1 // renderhud.cpp: HUD rendering
2 
3 #include "cube.h"
4 
drawicon(Texture * tex,float x,float y,float s,int col,int row,float ts)5 void drawicon(Texture *tex, float x, float y, float s, int col, int row, float ts)
6 {
7     if(tex && tex->xs == tex->ys) quad(tex->id, x, y, s, ts*col, ts*row, ts);
8 }
9 
turn_on_transparency(int alpha=255)10 inline void turn_on_transparency(int alpha = 255)
11 {
12     glEnable(GL_BLEND);
13     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
14     glColor4ub(255, 255, 255, alpha);
15 }
16 
drawequipicon(float x,float y,int col,int row,float blend)17 void drawequipicon(float x, float y, int col, int row, float blend)
18 {
19     static Texture *tex = NULL;
20     if(!tex) tex = textureload("packages/misc/items.png", 4);
21     if(tex)
22     {
23         turn_on_transparency();
24         drawicon(tex, x, y, 120, col, row, 1/4.0f);
25         glDisable(GL_BLEND);
26     }
27 }
28 
29 VARP(radarentsize, 4, 12, 64);
30 
drawradaricon(float x,float y,float s,int col,int row)31 void drawradaricon(float x, float y, float s, int col, int row)
32 {
33     static Texture *tex = NULL;
34     if(!tex) tex = textureload("packages/misc/radaricons.png", 3);
35     if(tex)
36     {
37         glEnable(GL_BLEND);
38         drawicon(tex, x, y, s, col, row, 1/4.0f);
39         glDisable(GL_BLEND);
40     }
41 }
42 
drawctficon(float x,float y,float s,int col,int row,float ts,int alpha)43 void drawctficon(float x, float y, float s, int col, int row, float ts, int alpha)
44 {
45     static Texture *ctftex = NULL, *htftex = NULL, *ktftex = NULL;
46     if(!ctftex) ctftex = textureload("packages/misc/ctficons.png", 3);
47     if(!htftex) htftex = textureload("packages/misc/htficons.png", 3);
48     if(!ktftex) ktftex = textureload("packages/misc/ktficons.png", 3);
49     glColor4ub(255, 255, 255, alpha);
50     if(m_htf)
51     {
52         if(htftex) drawicon(htftex, x, y, s, col, row, ts);
53     }
54     else if(m_ktf)
55     {
56         if(ktftex) drawicon(ktftex, x, y, s, col, row, ts);
57     }
58     else
59     {
60         if(ctftex) drawicon(ctftex, x, y, s, col, row, ts);
61     }
62 }
63 
drawvoteicon(float x,float y,int col,int row,bool noblend)64 void drawvoteicon(float x, float y, int col, int row, bool noblend)
65 {
66     static Texture *tex = NULL;
67     if(!tex) tex = textureload("packages/misc/voteicons.png", 3);
68     if(tex)
69     {
70         if(noblend) glDisable(GL_BLEND);
71         else turn_on_transparency(); // if(transparency && !noblend)
72         drawicon(tex, x, y, 240, col, row, 1/2.0f);
73         if(noblend) glEnable(GL_BLEND);
74     }
75 }
76 
77 VARP(crosshairsize, 0, 15, 50);
78 VARP(showstats, 0, 1, 2);
79 VARP(crosshairfx, 0, 1, 1);
80 VARP(crosshairteamsign, 0, 1, 1);
81 VARP(hideradar, 0, 0, 1);
82 VARP(hidecompass, 0, 0, 1);
83 VARP(hideteam, 0, 0, 1);
84 VARP(hidectfhud, 0, 0, 1);
85 VARP(hidevote, 0, 0, 2);
86 VARP(hidehudmsgs, 0, 0, 1);
87 VARP(hidehudequipment, 0, 0, 1);
88 VARP(hideconsole, 0, 0, 1);
89 VARP(hidespecthud, 0, 0, 1);
90 VAR(showmap, 0, 0, 1);
91 
92 
93 //shotty::
94 /*
95 VAR(showsgpat, 0, 0, 1);
96 
97 void drawsgpat(int w, int h)
98 {
99     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
100     glDisable(GL_TEXTURE_2D);
101     glColor3ub(0, 0, 0);
102     float sz = min(VIRTW, VIRTH),
103     x1 = VIRTW/2 - sz/2,
104     x2 = VIRTW/2 + sz/2,
105     y1 = VIRTH/2 - sz/2,
106     y2 = VIRTH/2 + sz/2,
107     border = (512 - 64*2)/512.0f;
108     glBegin(GL_TRIANGLE_FAN);
109     glVertex2f(x1 + 0.5f*sz, y1 + 0.5f*sz);
110     int rgbcv = 0;
111     loopi(8+1)
112     {
113         // if((i%3)==0) { glColor3ub(rgbcv,rgbcv,rgbcv); rgbcv += 4; //rgbcv -= 255/(8+1); }
114         if(i%2) glColor3ub(64,64,64); else glColor3ub(32,32,32);
115         float c = 0.5f*(1 + border*cosf(i*2*M_PI/8.0f)), s = 0.5f*(1 + border*sinf(i*2*M_PI/8.0f));
116         glVertex2f(x1 + c*sz, y1 + s*sz);
117     }
118     glColor3ub(255,255,255);
119     glEnd();
120 
121     glDisable(GL_BLEND);
122 
123     rgbcv = 32;
124     glBegin(GL_TRIANGLE_STRIP);
125     loopi(8+1)
126     {
127         // if((i%3)==0) { glColor3ub(rgbcv,rgbcv,rgbcv); //,128); rgbcv += 8; //rgbcv -= 255/(8+1); }
128         if(i%2) glColor3ub(16,16,16); else glColor3ub(32,32,32);
129         float c = 0.5f*(1 + border*cosf(i*2*M_PI/8.0f)), s = 0.5f*(1 + border*sinf(i*2*M_PI/8.0f));
130         glVertex2f(x1 + c*sz, y1 + s*sz);
131         c = c < 0.4f ? 0 : (c > 0.6f ? 1 : 0.5f);
132         s = s < 0.4f ? 0 : (s > 0.6f ? 1 : 0.5f);
133         glVertex2f(x1 + c*sz, y1 + s*sz);
134     }
135     glColor3ub(255,255,255);
136     glEnd();
137 
138     glEnable(GL_TEXTURE_2D);
139     static Texture *pattex = NULL;
140     if(!pattex) pattex = textureload("packages/misc/sgpat.png", 4);
141     loopk(3)
142     {
143         switch(k)
144         {
145             case 0:  glColor3ub(  32, 250, 250); break; // center
146             case 1:  glColor3ub( 250,  64,  64); break; // middle
147             case 2:  glColor3ub( 250, 250,  64); break; // outer
148             default: glColor3ub( 255, 255, 255); break;
149         }
150         extern sgray pat[SGRAYS*3];
151         int j = k * SGRAYS;
152         loopi(SGRAYS)
153         {
154             if(pattex)
155             {
156                 vec p = pat[j+i].rv;
157                 int ppx = VIRTW/2 + p.x*(sz/2);
158                 int ppy = VIRTH/2 + p.y*(sz/2);
159                 drawicon(pattex, ppx, ppy, 16, 1, 1, 1);
160             }
161         }
162     }
163     glEnable(GL_BLEND);
164     /\*
165      // 2011may31: dmg/hits output comes upon each shot, let the pattern be shown "pure"
166      extern int lastsgs_hits;
167      extern int lastsgs_dmgt;
168      //draw_textf("H: %d DMG: %d", 8, 32, lastsgs_hits, lastsgs_dmgt);
169      defformatstring(t2show4hitdmg)("H: %d DMG: %d", lastsgs_hits, lastsgs_dmgt);
170      draw_text(t2show4hitdmg, VIRTW/2-text_width(t2show4hitdmg), VIRTH/2-3*FONTH/4);
171      *\/
172 }
173 */
174 //::shotty
175 
drawscope(bool preload)176 void drawscope(bool preload)
177 {
178     static Texture *scopetex = NULL;
179     if(!scopetex) scopetex = textureload("packages/misc/scope.png", 3);
180     if(preload) return;
181     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
182     glBindTexture(GL_TEXTURE_2D, scopetex->id);
183     glColor3ub(255, 255, 255);
184 
185     // figure out the bounds of the scope given the desired aspect ratio
186     float sz = min(VIRTW, VIRTH),
187           x1 = VIRTW/2 - sz/2,
188           x2 = VIRTW/2 + sz/2,
189           y1 = VIRTH/2 - sz/2,
190           y2 = VIRTH/2 + sz/2,
191           border = (512 - 64*2)/512.0f;
192 
193     // draw center viewport
194     glBegin(GL_TRIANGLE_FAN);
195     glTexCoord2f(0.5f, 0.5f);
196     glVertex2f(x1 + 0.5f*sz, y1 + 0.5f*sz);
197     loopi(8+1)
198     {
199         float c = 0.5f*(1 + border*cosf(i*2*M_PI/8.0f)), s = 0.5f*(1 + border*sinf(i*2*M_PI/8.0f));
200         glTexCoord2f(c, s);
201         glVertex2f(x1 + c*sz, y1 + s*sz);
202     }
203     glEnd();
204 
205     glDisable(GL_BLEND);
206 
207     // draw outer scope
208     glBegin(GL_TRIANGLE_STRIP);
209     loopi(8+1)
210     {
211         float c = 0.5f*(1 + border*cosf(i*2*M_PI/8.0f)), s = 0.5f*(1 + border*sinf(i*2*M_PI/8.0f));
212         glTexCoord2f(c, s);
213         glVertex2f(x1 + c*sz, y1 + s*sz);
214         c = c < 0.4f ? 0 : (c > 0.6f ? 1 : 0.5f);
215         s = s < 0.4f ? 0 : (s > 0.6f ? 1 : 0.5f);
216         glTexCoord2f(c, s);
217         glVertex2f(x1 + c*sz, y1 + s*sz);
218     }
219     glEnd();
220 
221     // fill unused space with border texels
222     if(x1 > 0 || x2 < VIRTW || y1 > 0 || y2 < VIRTH)
223     {
224         glBegin(GL_TRIANGLE_STRIP);
225         glTexCoord2f(0, 0); glVertex2f(0,  0);
226         glTexCoord2f(0, 0); glVertex2f(x1, y1);
227         glTexCoord2f(0, 1); glVertex2f(0,  VIRTH);
228         glTexCoord2f(0, 1); glVertex2f(x1, y2);
229 
230         glTexCoord2f(1, 1); glVertex2f(VIRTW, VIRTH);
231         glTexCoord2f(1, 1); glVertex2f(x2, y2);
232         glTexCoord2f(1, 0); glVertex2f(VIRTW, 0);
233         glTexCoord2f(1, 0); glVertex2f(x2, y1);
234 
235         glTexCoord2f(0, 0); glVertex2f(0,  0);
236         glTexCoord2f(0, 0); glVertex2f(x1, y1);
237         glEnd();
238     }
239 
240     glEnable(GL_BLEND);
241 }
242 
243 const char *crosshairnames[CROSSHAIR_NUM] = { "default", "teammate", "scope", "knife", "pistol", "carbine", "shotgun", "smg", "sniper", "ar", "cpistol", "grenades", "akimbo" };
244 Texture *crosshairs[CROSSHAIR_NUM] = { NULL }; // weapon specific crosshairs
245 
loadcrosshairtexture(const char * c)246 Texture *loadcrosshairtexture(const char *c)
247 {
248     defformatstring(p)("packages/crosshairs/%s", c);
249     Texture *crosshair = textureload(p, 3);
250     if(crosshair==notexture) crosshair = textureload("packages/crosshairs/default.png", 3);
251     return crosshair;
252 }
253 
loadcrosshair(char * c,char * name)254 void loadcrosshair(char *c, char *name)
255 {
256     if (strcmp(name, "") == 0 || strcmp(name, "all") == 0)
257     {
258         for (int i = 0; i < CROSSHAIR_NUM; i++)
259         {
260             if (i == CROSSHAIR_TEAMMATE || i == CROSSHAIR_SCOPE) continue;
261             crosshairs[i] = loadcrosshairtexture(c);
262         }
263         return;
264     }
265 
266     int n = -1;
267 
268     for (int i = 0; i < CROSSHAIR_NUM; i++)
269     {
270        if(strcmp(crosshairnames[i], name) == 0) { n = i; break; }
271     }
272 
273     if (n < 0 || n >= CROSSHAIR_NUM) return;
274 
275     crosshairs[n] = loadcrosshairtexture(c);
276 }
277 
278 COMMAND(loadcrosshair, "ss");
279 
drawcrosshair(playerent * p,int n,color * c,float size)280 void drawcrosshair(playerent *p, int n, color *c, float size)
281 {
282     Texture *crosshair = crosshairs[n];
283     if(!crosshair)
284     {
285         crosshair = crosshairs[CROSSHAIR_DEFAULT];
286         if(!crosshair) crosshair = crosshairs[CROSSHAIR_DEFAULT] = loadcrosshairtexture("default.png");
287     }
288 
289     if(crosshair->bpp==32) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
290     else glBlendFunc(GL_ONE, GL_ONE);
291     glBindTexture(GL_TEXTURE_2D, crosshair->id);
292     glColor3ub(255,255,255);
293     if(c) glColor3f(c->r, c->g, c->b);
294     else if(crosshairfx || n==CROSSHAIR_TEAMMATE)
295     {
296         if(n==CROSSHAIR_TEAMMATE) glColor3ub(255, 0, 0);
297         else if(!m_osok)
298         {
299             if(p->health<=25) glColor3ub(255,0,0);
300             else if(p->health<=50) glColor3ub(255,128,0);
301         }
302     }
303     float s = size>0 ? size : (float)crosshairsize;
304     float chsize = s * (p->weaponsel->type==GUN_ASSAULT && p->weaponsel->shots > 3 ? 1.4f : 1.0f) * (n==CROSSHAIR_TEAMMATE ? 2.0f : 1.0f);
305     glBegin(GL_TRIANGLE_STRIP);
306     glTexCoord2f(0, 0); glVertex2f(VIRTW/2 - chsize, VIRTH/2 - chsize);
307     glTexCoord2f(1, 0); glVertex2f(VIRTW/2 + chsize, VIRTH/2 - chsize);
308     glTexCoord2f(0, 1); glVertex2f(VIRTW/2 - chsize, VIRTH/2 + chsize);
309     glTexCoord2f(1, 1); glVertex2f(VIRTW/2 + chsize, VIRTH/2 + chsize);
310     glEnd();
311 }
312 
313 VARP(hidedamageindicator, 0, 0, 1);
314 VARP(damageindicatorsize, 0, 200, 10000);
315 VARP(damageindicatordist, 0, 500, 10000);
316 VARP(damageindicatortime, 1, 1000, 10000);
317 VARP(damageindicatoralpha, 1, 50, 100);
318 int damagedirections[4] = {0};
319 
updatedmgindicator(vec & attack)320 void updatedmgindicator(vec &attack)
321 {
322     if(hidedamageindicator || !damageindicatorsize) return;
323     float bestdist = 0.0f;
324     int bestdir = -1;
325     loopi(4)
326     {
327         vec d;
328         d.x = (float)(cosf(RAD*(player1->yaw-90+(i*90))));
329         d.y = (float)(sinf(RAD*(player1->yaw-90+(i*90))));
330         d.z = 0.0f;
331         d.add(player1->o);
332         float dist = d.dist(attack);
333         if(dist < bestdist || bestdir==-1)
334         {
335             bestdist = dist;
336             bestdir = i;
337         }
338     }
339     damagedirections[bestdir] = lastmillis+damageindicatortime;
340 }
341 
drawdmgindicator()342 void drawdmgindicator()
343 {
344     if(!damageindicatorsize) return;
345     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
346     glDisable(GL_TEXTURE_2D);
347     float size = (float)damageindicatorsize;
348     loopi(4)
349     {
350         if(!damagedirections[i] || damagedirections[i] < lastmillis) continue;
351         float t = damageindicatorsize/(float)(damagedirections[i]-lastmillis);
352         glPushMatrix();
353         glColor4f(0.5f, 0.0f, 0.0f, damageindicatoralpha/100.0f);
354         glTranslatef(VIRTW/2, VIRTH/2, 0);
355         glRotatef(i*90, 0, 0, 1);
356         glTranslatef(0, (float)-damageindicatordist, 0);
357         glScalef(max(0.0f, 1.0f-t), max(0.0f, 1.0f-t), 0);
358 
359         glBegin(GL_TRIANGLES);
360         glVertex3f(size/2.0f, size/2.0f, 0.0f);
361         glVertex3f(-size/2.0f, size/2.0f, 0.0f);
362         glVertex3f(0.0f, 0.0f, 0.0f);
363         glEnd();
364         glPopMatrix();
365     }
366     glEnable(GL_TEXTURE_2D);
367 }
368 
drawequipicons(playerent * p)369 void drawequipicons(playerent *p)
370 {
371     glDisable(GL_BLEND);
372     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
373     glColor4f(1.0f, 1.0f, 1.0f, 0.2f+(sinf(lastmillis/100.0f)+1.0f)/2.0f);
374 
375     // health & armor
376     if(p->armour) drawequipicon(560, 1650, (p->armour-1)/25, 2, false);
377     drawequipicon(20, 1650, 2, 3, (p->state!=CS_DEAD && p->health<=20 && !m_osok));
378     if(p->mag[GUN_GRENADE]) drawequipicon(1520, 1650, 3, 1, false);
379 
380     // weapons
381     int c = p->weaponsel->type != GUN_GRENADE ? p->weaponsel->type : p->prevweaponsel->type, r = 0;
382     if(c==GUN_AKIMBO || c==GUN_CPISTOL) c = GUN_PISTOL; // same icon for akimb & pistol
383     if(c>3) { c -= 4; r = 1; }
384 
385     if(p->weaponsel && p->weaponsel->type>=GUN_KNIFE && p->weaponsel->type<NUMGUNS)
386         drawequipicon(1020, 1650, c, r, (!p->weaponsel->mag && p->weaponsel->type != GUN_KNIFE && p->weaponsel->type != GUN_GRENADE));
387     glEnable(GL_BLEND);
388 }
389 
drawradarent(float x,float y,float yaw,int col,int row,float iconsize,bool pulse,const char * label=NULL,...)390 void drawradarent(float x, float y, float yaw, int col, int row, float iconsize, bool pulse, const char *label = NULL, ...)
391 {
392     glPushMatrix();
393     if(pulse) glColor4f(1.0f, 1.0f, 1.0f, 0.2f+(sinf(lastmillis/30.0f)+1.0f)/2.0f);
394     else glColor4f(1, 1, 1, 1);
395     glTranslatef(x, y, 0);
396     glRotatef(yaw, 0, 0, 1);
397     drawradaricon(-iconsize/2.0f, -iconsize/2.0f, iconsize, col, row);
398     glPopMatrix();
399     if(label && showmap)
400     {
401         glPushMatrix();
402         glEnable(GL_BLEND);
403         glTranslatef(iconsize/2, iconsize/2, 0);
404         glScalef(1/2.0f, 1/2.0f, 1/2.0f);
405         defvformatstring(lbl, label, label);
406         draw_text(lbl, (int)(x*2), (int)(y*2));
407         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
408         glDisable(GL_BLEND);
409         glPopMatrix();
410     }
411 }
412 
413 struct hudline : cline
414 {
415     int type;
416 
hudlinehudline417     hudline() : type(HUDMSG_INFO) {}
418 };
419 
420 struct hudmessages : consolebuffer<hudline>
421 {
hudmessageshudmessages422     hudmessages() : consolebuffer<hudline>(20) {}
423 
addlinehudmessages424     void addline(const char *sf)
425     {
426         if(conlines.length() && conlines[0].type&HUDMSG_OVERWRITE)
427         {
428             conlines[0].millis = totalmillis;
429             conlines[0].type = HUDMSG_INFO;
430             copystring(conlines[0].line, sf);
431         }
432         else consolebuffer<hudline>::addline(sf, totalmillis);
433     }
editlinehudmessages434     void editline(int type, const char *sf)
435     {
436         if(conlines.length() && ((conlines[0].type&HUDMSG_TYPE)==(type&HUDMSG_TYPE) || conlines[0].type&HUDMSG_OVERWRITE))
437         {
438             conlines[0].millis = totalmillis;
439             conlines[0].type = type;
440             copystring(conlines[0].line, sf);
441         }
442         else consolebuffer<hudline>::addline(sf, totalmillis).type = type;
443     }
renderhudmessages444     void render()
445     {
446         if(!conlines.length()) return;
447         glPushMatrix();
448         glLoadIdentity();
449         glOrtho(0, VIRTW*0.9f, VIRTH*0.9f, 0, -1, 1);
450         int dispmillis = arenaintermission ? 6000 : 3000;
451         loopi(min(conlines.length(), 3)) if(totalmillis-conlines[i].millis<dispmillis)
452         {
453             cline &c = conlines[i];
454             int tw = text_width(c.line);
455             draw_text(c.line, int(tw > VIRTW*0.9f ? 0 : (VIRTW*0.9f-tw)/2), int(((VIRTH*0.9f)/4*3)+FONTH*i+pow((totalmillis-c.millis)/(float)dispmillis, 4)*VIRTH*0.9f/4.0f));
456         }
457         glPopMatrix();
458     }
459 };
460 
461 hudmessages hudmsgs;
462 
hudoutf(const char * s,...)463 void hudoutf(const char *s, ...)
464 {
465     defvformatstring(sf, s, s);
466     hudmsgs.addline(sf);
467     conoutf("%s", sf);
468 }
469 
hudonlyf(const char * s,...)470 void hudonlyf(const char *s, ...)
471 {
472     defvformatstring(sf, s, s);
473     hudmsgs.addline(sf);
474 }
475 
hudeditf(int type,const char * s,...)476 void hudeditf(int type, const char *s, ...)
477 {
478     defvformatstring(sf, s, s);
479     hudmsgs.editline(type, sf);
480 }
481 
insideradar(const vec & centerpos,float radius,const vec & o)482 bool insideradar(const vec &centerpos, float radius, const vec &o)
483 {
484     if(showmap) return !o.reject(centerpos, radius);
485     return o.distxy(centerpos)<=radius;
486 }
487 
isattacking(playerent * p)488 bool isattacking(playerent *p) { return lastmillis-p->lastaction < 500; }
489 
getradarpos()490 vec getradarpos()
491 {
492     float radarviewsize = VIRTH/6;
493     float overlaysize = radarviewsize*4.0f/3.25f;
494     return vec(VIRTW-10-VIRTH/28-overlaysize, 10+VIRTH/52, 0);
495 }
496 
497 VARP(showmapbackdrop, 0, 0, 2);
498 VARP(showmapbackdroptransparency, 0, 75, 100);
499 VARP(radarheight, 5, 150, 500);
500 VAR(showradarvalues, 0, 0, 1); // DEBUG
501 
drawradar_showmap(playerent * p,int w,int h)502 void drawradar_showmap(playerent *p, int w, int h)
503 {
504     float minimapviewsize = 3*min(VIRTW,VIRTH)/4; //minimap default size
505     float halfviewsize = minimapviewsize/2.0f;
506     float iconsize = radarentsize/0.2f;
507     glColor3f(1.0f, 1.0f, 1.0f);
508     glPushMatrix();
509     extern GLuint minimaptex;
510     vec centerpos(VIRTW/2 , VIRTH/2, 0.0f);
511     if(showmapbackdrop)
512     {
513         glDisable(GL_TEXTURE_2D);
514         if(showmapbackdrop==2) glBlendFunc(GL_ONE_MINUS_DST_ALPHA, GL_ONE_MINUS_SRC_COLOR);
515         loopi(2)
516         {
517             int cg = i?(showmapbackdrop==2?((int)(255*(100-showmapbackdroptransparency)/100.0f)):0):(showmapbackdrop==2?((int)(255*(100-showmapbackdroptransparency)/100.0f)):64);
518             int co = i?0:4;
519             glColor3ub(cg, cg, cg);
520             glBegin(GL_QUADS);
521             glVertex2f( centerpos.x - halfviewsize - co, centerpos.y + halfviewsize + co);
522             glVertex2f( centerpos.x + halfviewsize + co, centerpos.y + halfviewsize + co);
523             glVertex2f( centerpos.x + halfviewsize + co, centerpos.y - halfviewsize - co);
524             glVertex2f( centerpos.x - halfviewsize - co, centerpos.y - halfviewsize - co);
525             glEnd();
526         }
527         glColor3ub(255,255,255);
528         glEnable(GL_TEXTURE_2D);
529     }
530     glTranslatef(centerpos.x - halfviewsize, centerpos.y - halfviewsize , 0);
531     glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_COLOR);
532     quad(minimaptex, 0, 0, minimapviewsize, 0.0f, 0.0f, 1.0f);
533     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
534     glDisable(GL_BLEND);
535 
536     float gdim = max(mapdims[4], mapdims[5]); //no border
537     float coordtrans = (minimapviewsize)/(gdim);
538 
539     float offd = fabs(float(mapdims[5])-float(mapdims[4])) /2.0f;
540     if(!gdim) { gdim = ssize/2.0f; offd = 0; }
541     float offx = gdim==mapdims[5] ? offd : 0;
542     float offy = gdim==mapdims[4] ? offd : 0;
543 
544     vec mdd = vec(mapdims[0]-offx, mapdims[1]-offy, 0);
545     vec cod(offx, offy, 0);
546     vec ppv = vec(p->o).sub(mdd).mul(coordtrans);
547 
548     if(team_isactive(p->team)) drawradarent(ppv.x, ppv.y, p->yaw, p->state==CS_ALIVE ? (isattacking(p) ? 2 : 0) : 1, 2, iconsize, isattacking(p), "%s", colorname(p)); // local player
549     loopv(players) // other players
550     {
551         playerent *pl = players[i];
552         if(!pl || pl==p || !isteam(p->team, pl->team) || !team_isactive(pl->team)) continue;
553         vec rtmp = vec(pl->o).sub(mdd).mul(coordtrans);
554         drawradarent(rtmp.x, rtmp.y, pl->yaw, pl->state==CS_ALIVE ? (isattacking(pl) ? 2 : 0) : 1, team_base(pl->team), iconsize, isattacking(pl), "%s", colorname(pl));
555     }
556     if(m_flags)
557     {
558         glColor4f(1.0f, 1.0f, 1.0f, (sinf(lastmillis / 100.0f) + 1.0f) / 2.0f);
559         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
560         loopi(2) // flag items
561         {
562             flaginfo &f = flaginfos[i];
563             entity *e = f.flagent;
564             if(!e) continue;
565             if(e->x == -1 && e-> y == -1) continue; // flagdummies
566             vec pos = vec(e->x, e->y, 0).sub(mdd).mul(coordtrans);
567             drawradarent(pos.x, pos.y, 0, m_ktf ? 2 : f.team, 3, iconsize, false); // draw bases
568             vec fltxoff = vec(8, -8, 0);
569             vec cpos = vec(f.pos.x, f.pos.y, f.pos.z).sub(mdd).mul(coordtrans).add(fltxoff);
570             if(f.state!=CTFF_STOLEN && !(m_ktf && f.state == CTFF_IDLE))
571             {
572                 float flgoff=fabs((radarentsize*2.1f)-8);
573                 drawradarent(cpos.x+flgoff, cpos.y-flgoff, 0, 3, m_ktf ? 2 : f.team, iconsize, false); // draw on entity pos
574             }
575             if(m_ktf && f.state == CTFF_IDLE) continue;
576             if(f.state==CTFF_STOLEN)
577             {
578                 float d2c = 1.6f * radarentsize/16.0f;
579                 vec apos(d2c, -d2c, 0);
580                 if(f.actor)
581                 {
582                     apos.add(f.actor->o);
583                     bool tm = i != team_base(p->team);
584                     if(m_htf) tm = !tm;
585                     else if(m_ktf) tm = true;
586                     if(tm)
587                     {
588                         apos.sub(mdd).mul(coordtrans);
589                         drawradarent(apos.x, apos.y, 0, 3, m_ktf ? 2 : f.team, iconsize, true); // draw near flag thief
590                     }
591                 }
592             }
593         }
594     }
595     glEnable(GL_BLEND);
596     glPopMatrix();
597 }
598 
drawradar_vicinity(playerent * p,int w,int h)599 void drawradar_vicinity(playerent *p, int w, int h)
600 {
601     extern GLuint minimaptex;
602     int gdim = max(mapdims[4], mapdims[5]);
603     float radarviewsize = min(VIRTW,VIRTH)/5;
604     float halfviewsize = radarviewsize/2.0f;
605     float iconsize = radarentsize/0.4f;
606     float scaleh = radarheight/(2.0f*gdim);
607     float scaled = radarviewsize/float(radarheight);
608     float offd = fabs((mapdims[5]-mapdims[4]) /2.0f);
609     if(!gdim) { gdim = ssize/2; offd = 0; }
610     float offx = gdim==mapdims[5]?offd:0;
611     float offy = gdim==mapdims[4]?offd:0;
612     vec rtr = vec(mapdims[0]-offx, mapdims[1]-offy, 0);
613     vec rsd = vec(mapdims[0]+mapdims[4]/2, mapdims[1]+mapdims[5]/2, 0);
614     float d2s = radarheight/2.0f;
615     glColor3f(1.0f, 1.0f, 1.0f);
616     glPushMatrix();
617     vec centerpos(VIRTW-halfviewsize-72, halfviewsize+64, 0);
618     glTranslatef(centerpos.x, centerpos.y, 0);
619     glRotatef(-camera1->yaw, 0, 0, 1);
620     glTranslatef(-halfviewsize, -halfviewsize, 0);
621     vec d4rc = vec(p->o).sub(rsd).normalize().mul(0);
622     vec usecenter = vec(p->o).sub(rtr).sub(d4rc);
623     if(showradarvalues)
624     {
625         conoutf("vicinity @ gdim = %d | scaleh = %.2f", gdim, scaleh);
626         conoutf("offd: %.2f [%.2f:%.2f]", offd, offx, offy);
627         conoutf("RTR: %.2f %.2f", rtr.x, rtr.y);
628         conoutf("RSD: %.2f %.2f", rsd.x, rsd.y);
629         conoutf("P.O: %.2f %.2f", p->o.x, p->o.y);
630         conoutf("U4C: %.2f %.2f | %.2f %.2f", usecenter.x, usecenter.y, usecenter.x/gdim, usecenter.y/gdim);
631         //showradarvalues = 0;
632     }
633     glDisable(GL_BLEND);
634     circle(minimaptex, halfviewsize, halfviewsize, halfviewsize, usecenter.x/(float)gdim, usecenter.y/(float)gdim, scaleh, 31); //Draw mimimaptext as radar background
635     glTranslatef(halfviewsize, halfviewsize, 0);
636     if(team_isactive(p->team)) drawradarent(0, 0, p->yaw, p->state==CS_ALIVE ? (isattacking(p) ? 2 : 0) : 1, 2, iconsize, isattacking(p), "%s", colorname(p)); // local player
637     loopv(players) // other players
638     {
639         playerent *pl = players[i];
640         if(!pl || pl==p || !isteam(p->team, pl->team) || !team_isactive(pl->team)) continue;
641         vec rtmp = vec(pl->o).sub(p->o);
642         bool isok = rtmp.magnitude() < d2s;
643         if(isok)
644         {
645             rtmp.mul(scaled);
646             drawradarent(rtmp.x, rtmp.y, pl->yaw, pl->state==CS_ALIVE ? (isattacking(pl) ? 2 : 0) : 1, team_base(pl->team), iconsize, isattacking(pl), "%s", colorname(pl));
647         }
648     }
649     if(m_flags)
650     {
651         glColor4f(1.0f, 1.0f, 1.0f, (sinf(lastmillis / 100.0f) + 1.0f) / 2.0f);
652         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
653         float d2c = 1.6f * radarentsize/16.0f;
654         loopi(2) // flag items
655         {
656             flaginfo &f = flaginfos[i];
657             entity *e = f.flagent;
658             if(!e) continue;
659             if(e->x == -1 && e-> y == -1) continue; // flagdummies
660             vec pos = vec(e->x, e->y, 0).sub(p->o);
661             vec cpos = vec(f.pos.x, f.pos.y, f.pos.z).sub(p->o);
662             //if(showradarvalues) { conoutf("dist2F[%d]: %.2f|%.2f || %.2f|%.2f", i, pos.x, pos.y, cpos.x, cpos.y); }
663             if(pos.magnitude() < d2s)
664             {
665                 pos.mul(scaled);
666                 drawradarent(pos.x, pos.y, 0, m_ktf ? 2 : f.team, 3, iconsize, false); // draw bases [circle doesn't need rotating]
667             }
668             if(f.state!=CTFF_STOLEN && !(m_ktf && f.state == CTFF_IDLE))
669             {
670                 if(cpos.magnitude() < d2s)
671                 {
672                     cpos.mul(scaled);
673                     float flgoff=radarentsize/0.68f;
674                     float ryaw=(camera1->yaw-45)*(2*PI/360);
675                     float offx=flgoff*cosf(-ryaw);
676                     float offy=flgoff*sinf(-ryaw);
677                     drawradarent(cpos.x+offx, cpos.y-offy, camera1->yaw, 3, m_ktf ? 2 : f.team, iconsize, false); // draw flag on entity pos
678                 }
679             }
680             if(m_ktf && f.state == CTFF_IDLE) continue;
681             if(f.state==CTFF_STOLEN)
682             {
683                 vec apos(d2c, -d2c, 0);
684                 if(f.actor)
685                 {
686                     apos.add(f.actor->o);
687                     bool tm = i != team_base(p->team);
688                     if(m_htf) tm = !tm;
689                     else if(m_ktf) tm = true;
690                     if(tm)
691                     {
692                         apos.sub(p->o);
693                         if(apos.magnitude() < d2s)
694                         {
695                             apos.mul(scaled);
696                             drawradarent(apos.x, apos.y, camera1->yaw, 3, m_ktf ? 2 : f.team, iconsize, true); // draw near flag thief
697                         }
698                     }
699                 }
700             }
701         }
702     }
703     showradarvalues = 0; // DEBUG - also see two bits commented-out above
704     glEnable(GL_BLEND);
705     glPopMatrix();
706     // eye candy:
707     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
708     glColor3f(1, 1, 1);
709     static Texture *bordertex = NULL;
710     if(!bordertex) bordertex = textureload("packages/misc/compass-base.png", 3);
711     quad(bordertex->id, centerpos.x-halfviewsize-16, centerpos.y-halfviewsize-16, radarviewsize+32, 0, 0, 1, 1);
712     if(!hidecompass)
713     {
714         static Texture *compasstex = NULL;
715         if(!compasstex) compasstex = textureload("packages/misc/compass-rose.png", 3);
716         glPushMatrix();
717         glTranslatef(centerpos.x, centerpos.y, 0);
718         glRotatef(-camera1->yaw, 0, 0, 1);
719         quad(compasstex->id, -halfviewsize-8, -halfviewsize-8, radarviewsize+16, 0, 0, 1, 1);
720         glPopMatrix();
721     }
722 
723 }
724 
drawradar(playerent * p,int w,int h)725 void drawradar(playerent *p, int w, int h)
726 {
727     if(showmap) drawradar_showmap(p,w,h);
728     else drawradar_vicinity(p,w,h);
729 }
730 
drawteamicons(int w,int h,bool spect)731 void drawteamicons(int w, int h, bool spect)
732 {
733     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
734     glColor3f(1, 1, 1);
735     static Texture *icons = NULL;
736     if(!icons) icons = textureload("packages/misc/teamicons.png", 3);
737     quad(icons->id, VIRTW-VIRTH/12-10, 10, VIRTH/12, team_base(spect ? players[player1->followplayercn]->team : player1->team) ? 0.5f : 0, 0, 0.49f, 1.0f);
738 }
739 
740 int damageblendmillis = 0;
741 
742 VARFP(damagescreen, 0, 1, 1, { if(!damagescreen) damageblendmillis = 0; });
743 VARP(damagescreenfactor, 1, 7, 100);
744 VARP(damagescreenalpha, 1, 45, 100);
745 VARP(damagescreenfade, 0, 125, 1000);
746 
damageblend(int n)747 void damageblend(int n)
748 {
749     if(!damagescreen) return;
750     if(lastmillis > damageblendmillis) damageblendmillis = lastmillis;
751     damageblendmillis += n*damagescreenfactor;
752 }
753 
drawmedals(float x,float y,int col,int row,Texture * tex)754 void drawmedals(float x, float y, int col, int row, Texture *tex)
755 {
756     if(tex)
757     {
758         glPushAttrib(GL_COLOR_BUFFER_BIT);
759         glDisable(GL_BLEND);
760         drawicon(tex, x, y, 120, col, row, 1/4.0f);
761         glPopAttrib();
762     }
763 }
764 const char *medal_str[] =
765 {
766     "Best Fragger", "Dude that dies a lot"
767 }; //just some medals string tests, nothing serious
768 extern bool medals_arrived;
769 extern medalsst a_medals[END_MDS];
drawscores()770 void drawscores()
771 {
772     static float time=0;
773     if(!medals_arrived) {time=0; return;} else if(time > 5){time=0; medals_arrived=0;}
774     static Texture *tex = NULL;
775     if(!tex) tex = textureload("packages/misc/nice_medals.png", 4);
776     time+=((float)(curtime))/1000;
777     float vw=VIRTW*7/4,vh=VIRTH*7/4;
778     glPushAttrib(GL_COLOR_BUFFER_BIT);
779     glLoadIdentity();
780     glOrtho(0, vw, vh, 0, -1, 1);
781     int left = vw/4, top = vh/4;
782     blendbox(left, top, left*3, top*3, true, -1);
783     top+=10;left+=10;const float txtdx=160,txtdy=30,medalsdy=130;
784     glColor4f(1,1,1,1);
785     float desttime=0;
786     loopi(END_MDS) {
787         if(a_medals[i].assigned) {
788             desttime+=0.3;
789             if(time < desttime) continue;
790             drawmedals(left, top, 0, 0, tex);
791             playerent *mpl = getclient(a_medals[i].cn);
792             draw_textf("%s %s: %d", left+txtdx, top+txtdy, medal_str[i], mpl->name, a_medals[i].item); top+=medalsdy;
793         }
794     }
795 
796     glPopAttrib();
797 }
798 
799 string enginestateinfo = "";
CSgetEngineState()800 void CSgetEngineState() { result(enginestateinfo); }
801 COMMANDN(getEngineState, CSgetEngineState, "");
802 
803 VARP(clockdisplay,0,0,2);
804 VARP(dbgpos,0,0,1);
805 VARP(showtargetname,0,1,1);
806 VARP(showspeed, 0, 0, 1);
807 
808 static char lastseen [20];
lasttarget()809 void lasttarget() { result(lastseen); }
810 COMMAND(lasttarget, "");
811 
gl_drawhud(int w,int h,int curfps,int nquads,int curvert,bool underwater)812 void gl_drawhud(int w, int h, int curfps, int nquads, int curvert, bool underwater)
813 {
814     playerent *p = camera1->type<ENT_CAMERA ? (playerent *)camera1 : player1;
815     bool spectating = player1->isspectating();
816 
817     glDisable(GL_DEPTH_TEST);
818 
819     glMatrixMode(GL_MODELVIEW);
820     glLoadIdentity();
821 
822     glMatrixMode(GL_PROJECTION);
823     glLoadIdentity();
824     glOrtho(0, VIRTW, VIRTH, 0, -1, 1);
825     glEnable(GL_BLEND);
826 
827     if(underwater)
828     {
829         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
830         glColor4ub(hdr.watercolor[0], hdr.watercolor[1], hdr.watercolor[2], 102);
831 
832         glBegin(GL_TRIANGLE_STRIP);
833         glVertex2f(0, 0);
834         glVertex2f(VIRTW, 0);
835         glVertex2f(0, VIRTH);
836         glVertex2f(VIRTW, VIRTH);
837         glEnd();
838     }
839 
840     if(lastmillis < damageblendmillis)
841     {
842         static Texture *damagetex = NULL;
843         if(!damagetex) damagetex = textureload("packages/misc/damage.png", 3);
844 
845         glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
846         glEnable(GL_TEXTURE_2D);
847         glBindTexture(GL_TEXTURE_2D, damagetex->id);
848         float fade = damagescreenalpha/100.0f;
849         if(damageblendmillis - lastmillis < damagescreenfade)
850             fade *= float(damageblendmillis - lastmillis)/damagescreenfade;
851         glColor4f(fade, fade, fade, fade);
852 
853         glBegin(GL_TRIANGLE_STRIP);
854         glTexCoord2f(0, 0); glVertex2f(0, 0);
855         glTexCoord2f(1, 0); glVertex2f(VIRTW, 0);
856         glTexCoord2f(0, 1); glVertex2f(0, VIRTH);
857         glTexCoord2f(1, 1); glVertex2f(VIRTW, VIRTH);
858         glEnd();
859     }
860 
861     glEnable(GL_TEXTURE_2D);
862 
863     playerent *targetplayer = playerincrosshair();
864     if (targetplayer) strcpy(lastseen, targetplayer->name);
865     bool menu = menuvisible();
866     bool command = getcurcommand() ? true : false;
867     bool reloading = lastmillis < p->weaponsel->reloading + p->weaponsel->info.reloadtime;
868     if((p->state==CS_ALIVE || p->state==CS_EDITING) && !reloading)
869     {
870         bool drawteamwarning = crosshairteamsign && targetplayer && isteam(targetplayer->team, p->team) && targetplayer->state==CS_ALIVE;
871         p->weaponsel->renderaimhelp(drawteamwarning);
872     }
873 
874     drawdmgindicator();
875 
876     if(p->state==CS_ALIVE && !hidehudequipment) drawequipicons(p);
877 
878     bool is_spect = (( player1->spectatemode==SM_FOLLOW1ST || player1->spectatemode==SM_FOLLOW3RD || player1->spectatemode==SM_FOLLOW3RD_TRANSPARENT ) &&
879             players.inrange(player1->followplayercn) && players[player1->followplayercn]);
880 
881     if(/*!menu &&*/ (!hideradar || showmap)) drawradar(p, w, h);
882     //if(showsgpat) drawsgpat(w,h); // shotty
883     if(!editmode)
884     {
885         glMatrixMode(GL_MODELVIEW);
886         if(!hideteam && m_teammode) drawteamicons(w, h, is_spect);
887         glMatrixMode(GL_PROJECTION);
888     }
889 
890     char *infostr = editinfo();
891     int commandh = 1570 + FONTH;
892     if(command) commandh -= rendercommand(20, 1570, VIRTW);
893     else if(infostr) draw_text(infostr, 20, 1570);
894     else if(targetplayer && showtargetname) draw_text(colorname(targetplayer), 20, 1570);
895     glLoadIdentity();
896     glOrtho(0, VIRTW*2, VIRTH*2, 0, -1, 1);
897     extern int tsens(int x);
898     tsens(-2000);
899     extern void r_accuracy(int h);
900     if (!is_spect) r_accuracy(commandh);
901     if(!hideconsole) renderconsole();
902     formatstring(enginestateinfo)("%d %d %d %d %d", curfps, lod_factor(), nquads, curvert, xtraverts);
903     if(showstats)
904     {
905         if(showstats==2)
906         {
907             const int left = (VIRTW-225-10)*2, top = (VIRTH*7/8)*2;
908             const int ttll = VIRTW*2 - 3*FONTH/2;
909             blendbox(left - 24, top - 24, VIRTW*2 - 72, VIRTH*2 - 48, true, -1);
910             int c_num;
911             int c_r = 255;      int c_g = 255;      int c_b = 255;
912             string c_val;
913     #define TXTCOLRGB \
914             switch(c_num) \
915             { \
916                 case 0: c_r = 120; c_g = 240; c_b = 120; break; \
917                 case 1: c_r = 120; c_g = 120; c_b = 240; break; \
918                 case 2: c_r = 230; c_g = 230; c_b = 110; break; \
919                 case 3: c_r = 250; c_g = 100; c_b = 100; break; \
920                 default: \
921                     c_r = 255; c_g = 255; c_b =  64; \
922                 break; \
923             }
924 
925             draw_text("fps", left - (text_width("fps") + FONTH/2), top    );
926             draw_text("lod", left - (text_width("lod") + FONTH/2), top+ 80);
927             draw_text("wqd", left - (text_width("wqd") + FONTH/2), top+160);
928             draw_text("wvt", left - (text_width("wvt") + FONTH/2), top+240);
929             draw_text("evt", left - (text_width("evt") + FONTH/2), top+320);
930 
931             //ttll -= 3*FONTH/2;
932 
933             formatstring(c_val)("%d", curfps);
934             c_num = curfps > 150 ? 0 : (curfps > 100 ? 1 : (curfps > 30 ? 2 : 3)); TXTCOLRGB
935             draw_text(c_val, ttll - text_width(c_val), top    , c_r, c_g, c_b);
936 
937             int lf = lod_factor();
938             formatstring(c_val)("%d", lf);
939             c_num = lf>199?(lf>299?(lf>399?3:2):1):0; TXTCOLRGB
940             draw_text(c_val, ttll - text_width(c_val), top+ 80, c_r, c_g, c_b);
941 
942             formatstring(c_val)("%d", nquads);
943             c_num = nquads>3999?(nquads>5999?(nquads>7999?3:2):1):0; TXTCOLRGB
944             draw_text(c_val, ttll - text_width(c_val), top+160, c_r, c_g, c_b);
945 
946             formatstring(c_val)("%d", curvert);
947             c_num = curvert>3999?(curvert>5999?(curvert>7999?3:2):1):0; TXTCOLRGB
948             draw_text(c_val, ttll - text_width(c_val), top+240, c_r, c_g, c_b);
949 
950             formatstring(c_val)("%d", xtraverts);
951             c_num = xtraverts>3999?(xtraverts>5999?(xtraverts>7999?3:2):1):0; TXTCOLRGB
952             draw_text(c_val, ttll - text_width(c_val), top+320, c_r, c_g, c_b);
953         }
954         else
955         {
956             if(dbgpos)
957             {
958                 pushfont("mono");
959                 defformatstring(o_yw)("%05.2f YAW", player1->yaw);
960                 draw_text(o_yw, VIRTW*2 - ( text_width(o_yw) + FONTH ), VIRTH*2 - 15*FONTH/2);
961                 defformatstring(o_p)("%05.2f PIT", player1->pitch);
962                 draw_text(o_p, VIRTW*2 - ( text_width(o_p) + FONTH ), VIRTH*2 - 13*FONTH/2);
963                 defformatstring(o_x)("%05.2f X  ", player1->o.x);
964                 draw_text(o_x, VIRTW*2 - ( text_width(o_x) + FONTH ), VIRTH*2 - 11*FONTH/2);
965                 defformatstring(o_y)("%05.2f Y  ", player1->o.y);
966                 draw_text(o_y, VIRTW*2 - ( text_width(o_y) + FONTH ), VIRTH*2 - 9*FONTH/2);
967                 defformatstring(o_z)("%05.2f Z  ", player1->o.z);
968                 draw_text(o_z, VIRTW*2 - ( text_width(o_z) + FONTH ), VIRTH*2 - 7*FONTH/2);
969                 popfont();
970             }
971             defformatstring(c_val)("fps %d", curfps);
972             draw_text(c_val, VIRTW*2 - ( text_width(c_val) + FONTH ), VIRTH*2 - 3*FONTH/2);
973         }
974     }
975     if(!intermission && clockdisplay!=0 && lastgametimeupdate!=0)
976     {
977         string gtime;
978         int cssec = (gametimecurrent+(lastmillis-lastgametimeupdate))/1000;
979         int gtsec = cssec%60;
980         int gtmin = cssec/60;
981         if(clockdisplay==1)
982         {
983             int gtmax = gametimemaximum/60000;
984             gtmin = gtmax - gtmin;
985             if(gtsec!=0)
986             {
987                 gtmin -= 1;
988                 gtsec = 60 - gtsec;
989             }
990         }
991         formatstring(gtime)("%02d:%02d", gtmin, gtsec);
992         draw_text(gtime, (2*VIRTW - text_width(gtime))/2, 2);
993     }
994 
995     if(hidevote < 2 && multiplayer(false))
996     {
997         extern votedisplayinfo *curvote;
998 
999         if(curvote && curvote->millis >= totalmillis && !(hidevote == 1 && curvote->localplayervoted && curvote->result == VOTE_NEUTRAL))
1000         {
1001             const int left = 20*2, top = VIRTH;
1002             draw_textf("%s called a vote:", left, top+240, curvote->owner ? colorname(curvote->owner) : "");
1003             draw_textf("%s", left, top+320, curvote->desc);
1004             draw_textf("----", left, top+400);
1005             draw_textf("%d yes vs. %d no", left, top+480, curvote->stats[VOTE_YES], curvote->stats[VOTE_NO]);
1006 
1007             glBlendFunc(GL_SRC_ALPHA, GL_ONE);
1008             glColor4f(1.0f, 1.0f, 1.0f, (sinf(lastmillis/100.0f)+1.0f) / 2.0f);
1009             switch(curvote->result)
1010             {
1011                 case VOTE_NEUTRAL:
1012                     drawvoteicon(left, top, 0, 0, true);
1013                     if(!curvote->localplayervoted)
1014                         draw_textf("\f3press F1/F2 to vote yes or no", left, top+560);
1015                     break;
1016                 default:
1017                     drawvoteicon(left, top, (curvote->result-1)&1, 1, false);
1018                     draw_textf("\f3vote %s", left, top+560, curvote->result == VOTE_YES ? "PASSED" : "FAILED");
1019                     break;
1020             }
1021         }
1022     }
1023     //else draw_textf("%c%d here F1/F2 will be praised during a vote", 20*2, VIRTH+560, '\f', 0); // see position (left/top) setting in block above
1024 
1025     if(menu) rendermenu();
1026     else if(command) renderdoc(40, VIRTH, max(commandh*2 - VIRTH, 0));
1027 
1028     if(!hidehudmsgs) hudmsgs.render();
1029 
1030 
1031     if(!hidespecthud && !menu && p->state==CS_DEAD && p->spectatemode<=SM_DEATHCAM)
1032     {
1033         glLoadIdentity();
1034         glOrtho(0, VIRTW*3/2, VIRTH*3/2, 0, -1, 1);
1035         const int left = (VIRTW*3/2)*6/8, top = (VIRTH*3/2)*3/4;
1036         draw_textf("SPACE to change view", left, top);
1037         draw_textf("SCROLL to change player", left, top+80);
1038     }
1039 
1040     /* * /
1041     glLoadIdentity();
1042     glOrtho(0, VIRTW*3/2, VIRTH*3/2, 0, -1, 1);
1043     const int tbMSGleft = (VIRTW*3/2)*5/6;
1044     const int tbMSGtop = (VIRTH*3/2)*7/8;
1045     draw_textf("!TEST BUILD!", tbMSGleft, tbMSGtop);
1046     / * */
1047 
1048     if(showspeed)
1049     {
1050         glLoadIdentity();
1051         glPushMatrix();
1052         glOrtho(0, VIRTW, VIRTH, 0, -1, 1);
1053         glScalef(0.8, 0.8, 1);
1054         draw_textf("Speed: %.2f", VIRTW/2, VIRTH, p->vel.magnitudexy());
1055         glPopMatrix();
1056     }
1057 
1058     drawscores();
1059     if(!hidespecthud && spectating && player1->spectatemode!=SM_DEATHCAM)
1060     {
1061         glLoadIdentity();
1062         glOrtho(0, VIRTW, VIRTH, 0, -1, 1);
1063         const char *specttext = "GHOST";
1064         if(player1->team == TEAM_SPECT) specttext = "GHOST";
1065         else if(player1->team == TEAM_CLA_SPECT) specttext = "[CLA]";
1066         else if(player1->team == TEAM_RVSF_SPECT) specttext = "[RVSF]";
1067         draw_text(specttext, VIRTW/40, VIRTH/10*7);
1068         if(is_spect)
1069         {
1070             defformatstring(name)("Player %s", players[player1->followplayercn]->name);
1071             draw_text(name, VIRTW/40, VIRTH/10*8);
1072         }
1073     }
1074 
1075     if(p->state==CS_ALIVE)
1076     {
1077         glLoadIdentity();
1078         glOrtho(0, VIRTW/2, VIRTH/2, 0, -1, 1);
1079 
1080         if(!hidehudequipment)
1081         {
1082             pushfont("huddigits");
1083             draw_textf("%d",  90, 823, p->health);
1084             if(p->armour) draw_textf("%d", 360, 823, p->armour);
1085             if(p->weaponsel && p->weaponsel->type>=GUN_KNIFE && p->weaponsel->type<NUMGUNS)
1086             {
1087                 glMatrixMode(GL_MODELVIEW);
1088                 if (p->weaponsel->type!=GUN_GRENADE) p->weaponsel->renderstats();
1089                 else p->prevweaponsel->renderstats();
1090                 if(p->mag[GUN_GRENADE]) p->weapons[GUN_GRENADE]->renderstats();
1091                 glMatrixMode(GL_PROJECTION);
1092             }
1093             popfont();
1094         }
1095 
1096         if(m_flags && !hidectfhud)
1097         {
1098             glLoadIdentity();
1099             glOrtho(0, VIRTW, VIRTH, 0, -1, 1);
1100             glColor4f(1.0f, 1.0f, 1.0f, 0.2f);
1101             turn_on_transparency(255);
1102             int flagscores[2];
1103             teamflagscores(flagscores[0], flagscores[1]);
1104 
1105             loopi(2) // flag state
1106             {
1107                 drawctficon(i*120+VIRTW/4.0f*3.0f, 1650, 120, i, 0, 1/4.0f, flaginfos[i].state == CTFF_INBASE ? 255 : 100);
1108                 if(m_teammode)
1109                 {
1110                     defformatstring(count)("%d", flagscores[i]);
1111                     int cw, ch;
1112                     text_bounds(count, cw, ch);
1113                     draw_textf(count, i*120+VIRTW/4.0f*3.0f+60-cw/2, 1590);
1114                 }
1115             }
1116 
1117             // big flag-stolen icon
1118             int ft = 0;
1119             if((flaginfos[0].state==CTFF_STOLEN && flaginfos[0].actor == p && flaginfos[0].ack) ||
1120                (flaginfos[1].state==CTFF_STOLEN && flaginfos[1].actor == p && flaginfos[1].ack && ++ft))
1121             {
1122                 drawctficon(VIRTW-225-10, VIRTH*5/8, 225, ft, 1, 1/2.0f, (sinf(lastmillis/100.0f)+1.0f) *128);
1123             }
1124         }
1125     }
1126 
1127     glDisable(GL_BLEND);
1128     glDisable(GL_TEXTURE_2D);
1129     glEnable(GL_DEPTH_TEST);
1130 
1131     glMatrixMode(GL_MODELVIEW);
1132 }
1133 
loadingscreen(const char * fmt,...)1134 void loadingscreen(const char *fmt, ...)
1135 {
1136     static Texture *logo = NULL;
1137     if(!logo) logo = textureload("packages/misc/startscreen.png", 3);
1138 
1139     glEnable(GL_TEXTURE_2D);
1140     glDisable(GL_DEPTH_TEST);
1141 
1142     glMatrixMode(GL_PROJECTION);
1143     glLoadIdentity();
1144     glOrtho(0, VIRTW, VIRTH, 0, -1, 1);
1145 
1146     glMatrixMode(GL_MODELVIEW);
1147     glLoadIdentity();
1148 
1149     glClearColor(0, 0, 0, 1);
1150     glColor3f(1, 1, 1);
1151 
1152     loopi(fmt ? 1 : 2)
1153     {
1154         glClear(GL_COLOR_BUFFER_BIT);
1155         quad(logo->id, (VIRTW-VIRTH)/2, 0, VIRTH, 0, 0, 1);
1156         if(fmt)
1157         {
1158             glEnable(GL_BLEND);
1159             defvformatstring(str, fmt, fmt);
1160             int w = text_width(str);
1161             draw_text(str, w>=VIRTW ? 0 : (VIRTW-w)/2, VIRTH*3/4);
1162             glDisable(GL_BLEND);
1163         }
1164         SDL_GL_SwapBuffers();
1165     }
1166 
1167     glDisable(GL_TEXTURE_2D);
1168     glEnable(GL_DEPTH_TEST);
1169 }
1170 
bar(float bar,int o,float r,float g,float b)1171 static void bar(float bar, int o, float r, float g, float b)
1172 {
1173     int side = 2*FONTH;
1174     float x1 = side, x2 = bar*(VIRTW*1.2f-2*side)+side;
1175     float y1 = o*FONTH;
1176     glColor3f(0.3f, 0.3f, 0.3f);
1177     glBegin(GL_TRIANGLE_STRIP);
1178     loopk(10)
1179     {
1180        float c = 1.2f*cosf(M_PI/2 + k/9.0f*M_PI), s = 1 + 1.2f*sinf(M_PI/2 + k/9.0f*M_PI);
1181        glVertex2f(x2 - c*FONTH, y1 + s*FONTH);
1182        glVertex2f(x1 + c*FONTH, y1 + s*FONTH);
1183     }
1184     glEnd();
1185 
1186     glColor3f(r, g, b);
1187     glBegin(GL_TRIANGLE_STRIP);
1188     loopk(10)
1189     {
1190        float c = cosf(M_PI/2 + k/9.0f*M_PI), s = 1 + sinf(M_PI/2 + k/9.0f*M_PI);
1191        glVertex2f(x2 - c*FONTH, y1 + s*FONTH);
1192        glVertex2f(x1 + c*FONTH, y1 + s*FONTH);
1193     }
1194     glEnd();
1195 }
1196 
show_out_of_renderloop_progress(float bar1,const char * text1,float bar2,const char * text2)1197 void show_out_of_renderloop_progress(float bar1, const char *text1, float bar2, const char *text2)   // also used during loading
1198 {
1199     c2skeepalive();
1200 
1201     glDisable(GL_DEPTH_TEST);
1202     glMatrixMode(GL_MODELVIEW);
1203     glPushMatrix();
1204     glLoadIdentity();
1205     glMatrixMode(GL_PROJECTION);
1206     glPushMatrix();
1207     glLoadIdentity();
1208     glOrtho(0, VIRTW*1.2f, VIRTH*1.2f, 0, -1, 1);
1209 
1210     glLineWidth(3);
1211 
1212     if(text1)
1213     {
1214         bar(1, 1, 0.1f, 0.1f, 0.1f);
1215         if(bar1>0) bar(bar1, 1, 0.2f, 0.2f, 0.2f);
1216     }
1217 
1218     if(bar2>0)
1219     {
1220         bar(1, 3, 0.1f, 0.1f, 0.1f);
1221         bar(bar2, 3, 0.2f, 0.2f, 0.2f);
1222     }
1223 
1224     glLineWidth(1);
1225 
1226     glEnable(GL_BLEND);
1227     glEnable(GL_TEXTURE_2D);
1228 
1229     if(text1) draw_text(text1, 2*FONTH, 1*FONTH + FONTH/2);
1230     if(bar2>0) draw_text(text2, 2*FONTH, 3*FONTH + FONTH/2);
1231 
1232     glDisable(GL_TEXTURE_2D);
1233     glDisable(GL_BLEND);
1234 
1235     glPopMatrix();
1236     glMatrixMode(GL_MODELVIEW);
1237     glPopMatrix();
1238 
1239     glEnable(GL_DEPTH_TEST);
1240     SDL_GL_SwapBuffers();
1241 }
1242 
1243