1 /*
2 * XPilotNG/SDL, an SDL/OpenGL XPilot client.
3 *
4 * Copyright (C) 2003-2004 by
5 *
6 * Juha Lindstr�m <juhal@users.sourceforge.net>
7 * Erik Andersson <deity_at_home.se>
8 *
9 * Copyright (C) 1991-2002 by
10 *
11 * Bj�rn Stabell <bjoern@xpilot.org>
12 * Ken Ronny Schouten <ken@xpilot.org>
13 * Bert Gijsbers <bert@xpilot.org>
14 * Dick Balaska <dick@xpilot.org>
15 *
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2 of the License, or
19 * (at your option) any later version.
20 *
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 */
30
31 #include "xpclient_sdl.h"
32
33 #include "sdlpaint.h"
34 #include "images.h"
35 #include "glwidgets.h"
36 #include "text.h"
37 #include "asteroid_data.h"
38
39 Uint32 nullRGBA = 0x00000000;
40 Uint32 blackRGBA = 0x000000ff;
41 Uint32 whiteRGBA = 0xffffffff;
42 Uint32 blueRGBA = 0x0000ffff;
43 Uint32 redRGBA = 0xff0000ff;
44 Uint32 greenRGBA = 0x00ff00ff;
45 Uint32 yellowRGBA = 0xffff00ff;
46
47 Uint32 wallColorRGBA;
48 Uint32 decorColorRGBA;
49 Uint32 hudColorRGBA;
50 Uint32 connColorRGBA;
51 Uint32 scoreObjectColorRGBA;
52 Uint32 fuelColorRGBA;
53 Uint32 messagesColorRGBA;
54 Uint32 oldmessagesColorRGBA;
55 Uint32 msgScanBallColorRGBA;
56 Uint32 msgScanSafeColorRGBA;
57 Uint32 msgScanCoverColorRGBA;
58 Uint32 msgScanPopColorRGBA;
59 Uint32 ballColorRGBA;
60
61 Uint32 meterBorderColorRGBA;
62 Uint32 fuelMeterColorRGBA;
63 Uint32 powerMeterColorRGBA;
64 Uint32 turnSpeedMeterColorRGBA;
65 Uint32 packetSizeMeterColorRGBA;
66 Uint32 packetLossMeterColorRGBA;
67 Uint32 packetDropMeterColorRGBA;
68 Uint32 packetLagMeterColorRGBA;
69 Uint32 temporaryMeterColorRGBA;
70
71 Uint32 dirPtrColorRGBA;
72 Uint32 hudHLineColorRGBA;
73 Uint32 hudVLineColorRGBA;
74 Uint32 hudItemsColorRGBA;
75 Uint32 fuelGaugeColorRGBA;
76 Uint32 selfLWColorRGBA;
77 Uint32 teamLWColorRGBA;
78 Uint32 enemyLWColorRGBA;
79 Uint32 teamShipColorRGBA;
80 Uint32 team0ColorRGBA;
81 Uint32 team1ColorRGBA;
82 Uint32 team2ColorRGBA;
83 Uint32 team3ColorRGBA;
84 Uint32 team4ColorRGBA;
85 Uint32 team5ColorRGBA;
86 Uint32 team6ColorRGBA;
87 Uint32 team7ColorRGBA;
88 Uint32 team8ColorRGBA;
89 Uint32 team9ColorRGBA;
90 Uint32 shipNameColorRGBA;
91 Uint32 baseNameColorRGBA;
92 Uint32 manyLivesColorRGBA;
93 Uint32 twoLivesColorRGBA;
94 Uint32 oneLifeColorRGBA;
95 Uint32 zeroLivesColorRGBA;
96
97 Uint32 hudRadarEnemyColorRGBA;
98 Uint32 hudRadarOtherColorRGBA;
99 Uint32 hudRadarObjectColorRGBA;
100
101 Uint32 scoreInactiveSelfColorRGBA;
102 Uint32 scoreInactiveColorRGBA;
103 Uint32 scoreSelfColorRGBA;
104 Uint32 scoreColorRGBA;
105 Uint32 scoreOwnTeamColorRGBA;
106 Uint32 scoreEnemyTeamColorRGBA;
107
108 Uint32 selectionColorRGBA;
109
110 static int meterWidth = 60;
111 static int meterHeight = 10;
112
113 float hudRadarMapScale;
114 int hudRadarEnemyShape;
115 int hudRadarOtherShape;
116 int hudRadarObjectShape;
117 float hudRadarDotScale;
118
119 static double shipLineWidth;
120 static bool smoothLines;
121 static bool texturedBalls;
122 static bool texturedShips;
123 static GLuint polyListBase = 0;
124 static GLuint polyEdgeListBase = 0;
125 static GLuint asteroid = 0;
126
127 irec_t *select_bounds;
128
129 string_tex_t score_object_texs[MAX_SCORE_OBJECTS];
130 string_tex_t meter_texs[MAX_METERS];
131 string_tex_t message_texs[2*MAX_MSGS];
132 string_tex_t HUD_texs[MAX_HUD_TEXS+MAX_SCORE_OBJECTS];
133
134 int Gui_init(void);
135 void Gui_cleanup(void);
136
137 /* better to use alpha everywhere, less confusion */
set_alphacolor(Uint32 color)138 void set_alphacolor(Uint32 color)
139 {
140 glColor4ub((color >> 24) & 255,
141 (color >> 16) & 255,
142 (color >> 8) & 255,
143 color & 255);
144 }
145
get_alpha(Uint32 color)146 static GLubyte get_alpha(Uint32 color)
147 {
148 return (color & 255);
149 }
150
GL_X(int x)151 int GL_X(int x)
152 {
153 return (int)((x - world.x) * clData.scale);
154 }
155
GL_Y(int y)156 int GL_Y(int y)
157 {
158 return (int)((y - world.y) * clData.scale);
159 }
160
161
162 /* remove this later maybe? to tedious for me to edit them all away now */
Segment_add(Uint32 color,int x_1,int y_1,int x_2,int y_2)163 void Segment_add(Uint32 color, int x_1, int y_1, int x_2, int y_2)
164 {
165 if (smoothLines) glEnable(GL_LINE_SMOOTH);
166 set_alphacolor(color);
167 glBegin( GL_LINE_LOOP );
168 glVertex2i(x_1,y_1);
169 glVertex2i(x_2,y_2);
170 glEnd();
171 if (smoothLines) glDisable(GL_LINE_SMOOTH);
172 }
173
Circle(Uint32 color,int x,int y,int radius,int filled)174 void Circle(Uint32 color,
175 int x, int y,
176 int radius, int filled)
177 {
178 float i,resolution = 16;
179 set_alphacolor(color);
180 if (filled)
181 glBegin( GL_POLYGON );
182 else
183 glBegin( GL_LINE_LOOP );
184 /* Silly resolution */
185 for (i = 0.0f; i < TABLE_SIZE; i=i+((float)TABLE_SIZE)/resolution)
186 glVertex2f((x + tcos((int)i)*radius),(y + tsin((int)i)*radius));
187 glEnd();
188 }
189
wrap(int * xp,int * yp)190 static int wrap(int *xp, int *yp)
191 {
192 int x = *xp, y = *yp;
193 int returnval =1;
194
195 if (x < world.x || x > world.x + ext_view_width) {
196 if (x < realWorld.x || x > realWorld.x + ext_view_width)
197 returnval = 0;
198 *xp += world.x - realWorld.x;
199 }
200 if (y < world.y || y > world.y + ext_view_height) {
201 if (y < realWorld.y || y > realWorld.y + ext_view_height)
202 returnval = 0;
203 *yp += world.y - realWorld.y;
204 }
205 return returnval;
206 }
207
208 #ifndef CALLBACK
209 #define CALLBACK
210 #endif
211
vertex_callback(ipos_t * p,irec_t * trec)212 static void CALLBACK vertex_callback(ipos_t *p, irec_t *trec)
213 {
214 if (trec != NULL) {
215 glTexCoord2f((p->x + trec->x) / (GLfloat)trec->w,
216 (p->y + trec->y) / (GLfloat)trec->h);
217 }
218 glVertex2i(p->x, p->y);
219 }
220
tessellate_polygon(GLUtriangulatorObj * tess,int ind)221 static void tessellate_polygon(GLUtriangulatorObj *tess, int ind)
222 {
223 int i, x, y, minx, miny;
224 xp_polygon_t polygon;
225 polygon_style_t p_style;
226 image_t *texture = NULL;
227 irec_t trec;
228 GLdouble v[3] = { 0, 0, 0 };
229 ipos_t p[MAX_VERTICES];
230
231 polygon = polygons[ind];
232 p_style = polygon_styles[polygon.style];
233
234 p[0].x = p[0].y = 0;
235 if (BIT(p_style.flags, STYLE_TEXTURED)) {
236 texture = Image_get_texture(p_style.texture);
237 if (texture != NULL) {
238 x = y = minx = miny = 0;
239 for (i = 1; i < polygon.num_points; i++) {
240 x += polygon.points[i].x;
241 y += polygon.points[i].y;
242 if (x < minx) minx = x;
243 if (y < miny) miny = y;
244 }
245 trec.x = -minx;
246 trec.y = -miny - (polygon.bounds.h % texture->height);
247 trec.w = texture->frame_width;
248 trec.h = texture->height;
249 }
250 }
251 glNewList(polyListBase + ind, GL_COMPILE);
252 gluTessBeginPolygon(tess, texture ? &trec : NULL);
253 gluTessVertex(tess, v, &p[0]);
254 for (i = 1; i < polygon.num_points; i++) {
255 v[0] = p[i].x = p[i - 1].x + polygon.points[i].x;
256 v[1] = p[i].y = p[i - 1].y + polygon.points[i].y;
257 gluTessVertex(tess, v, &p[i]);
258 }
259 gluTessEndPolygon(tess);
260 glEndList();
261
262 glNewList(polyEdgeListBase + ind, GL_COMPILE);
263 if (polygon.edge_styles == NULL) { /* No special edges */
264 glBegin(GL_LINE_LOOP);
265 x = y = 0;
266 glVertex2i(x, y);
267 for (i = 1; i < polygon.num_points; i++) {
268 x += polygon.points[i].x;
269 y += polygon.points[i].y;
270 glVertex2i(x, y);
271 }
272 glEnd();
273 }
274 else { /* This polygon has special edges */
275 ipos_t pos1, pos2;
276 int sindex;
277
278 glBegin(GL_LINES);
279 pos1.x = 0;
280 pos1.y = 0;
281 for (i = 1; i < polygon.num_points; i++) {
282 pos2.x = pos1.x + polygon.points[i].x;
283 pos2.y = pos1.y + polygon.points[i].y;
284 sindex = polygon.edge_styles[i - 1];
285 /* Style 0 means internal edges which are never shown */
286 if (sindex != 0) {
287 glVertex2i(pos1.x, pos1.y);
288 glVertex2i(pos2.x, pos2.y);
289 }
290 pos1 = pos2;
291 }
292 glEnd();
293 }
294 glEndList();
295 }
296
asteroid_init(void)297 static int asteroid_init(void)
298 {
299 int i;
300 if ((asteroid = glGenLists(1)) == 0)
301 return -1;
302 glNewList(asteroid, GL_COMPILE);
303 glBegin(GL_TRIANGLES);
304 for (i = 0; i < VERTEX_COUNT; i++) {
305 glNormal3fv(normal_vectors[i]);
306 glTexCoord2fv(uv_vectors[i]);
307 glVertex3fv(vertex_vectors[i]);
308 }
309 glEnd();
310 glEndList();
311 return 0;
312 }
313
asteroid_cleanup(void)314 static void asteroid_cleanup(void)
315 {
316 if (asteroid)
317 glDeleteLists(asteroid, 1);
318 }
319
Gui_init(void)320 int Gui_init(void)
321 {
322 int i;
323 GLUtriangulatorObj *tess;
324
325 if (asteroid_init() == -1) {
326 error("failed to initialize asteroids");
327 return -1;
328 }
329
330 if (num_polygons == 0) return 0;
331
332 polyListBase = glGenLists(num_polygons);
333 polyEdgeListBase = glGenLists(num_polygons);
334 if ((!polyListBase)||(!polyEdgeListBase)) {
335 error("failed to generate display lists");
336 return -1;
337 }
338
339 tess = gluNewTess();
340 if (tess == NULL) {
341 error("failed to create tessellation object");
342 return -1;
343 }
344
345 /* TODO: figure out proper casting here do not use _GLUfuncptr */
346 /* it doesn't work on windows or MAC OS X */
347 #ifdef _MSC_VER
348 gluTessCallback(tess, GLU_TESS_BEGIN, glBegin);
349 gluTessCallback(tess, GLU_TESS_VERTEX_DATA, vertex_callback);
350 #else
351 gluTessCallback(tess, GLU_TESS_BEGIN, (GLvoid (*)(void))glBegin);
352 gluTessCallback(tess, GLU_TESS_VERTEX_DATA, (GLvoid (*)(void))vertex_callback);
353 #endif
354 gluTessCallback(tess, GLU_TESS_END, glEnd);
355
356 for (i = 0; i < num_polygons; i++) {
357 tessellate_polygon(tess, i);
358 }
359
360 gluDeleteTess(tess);
361
362 return 0;
363 }
364
Gui_cleanup(void)365 void Gui_cleanup(void)
366 {
367 if (polyListBase)
368 glDeleteLists(polyListBase, num_polygons);
369 asteroid_cleanup();
370 }
371
372 /* Map painting */
373
Gui_paint_cannon(int x,int y,int type)374 void Gui_paint_cannon(int x, int y, int type)
375 {
376 switch (type) {
377 case SETUP_CANNON_UP:
378 Image_paint(IMG_CANNON_DOWN, x, y, 0, whiteRGBA);
379 break;
380 case SETUP_CANNON_DOWN:
381 Image_paint(IMG_CANNON_UP, x, y + 1, 0, whiteRGBA);
382 break;
383 case SETUP_CANNON_LEFT:
384 Image_paint(IMG_CANNON_RIGHT, x, y, 0, whiteRGBA);
385 break;
386 case SETUP_CANNON_RIGHT:
387 Image_paint(IMG_CANNON_LEFT, x - 1, y, 0, whiteRGBA);
388 break;
389 default:
390 errno = 0;
391 error("Bad cannon dir.");
392 return;
393 }
394 }
395
Gui_paint_fuel(int x,int y,double fuel)396 void Gui_paint_fuel(int x, int y, double fuel)
397 {
398 #define FUEL_BORDER 3
399
400 int size, frame;
401 irec_t area;
402 image_t *img;
403
404 img = Image_get(IMG_FUEL);
405 if (img == NULL) return;
406
407 /* x + x * y will give a pseudo random number,
408 * so different fuelcells will not be displayed with the same
409 * image-frame. */
410 frame = ABS(loopsSlow + x + x * y) % (img->num_frames * 2);
411
412 /* the animation is played from image 0-15 then back again
413 * from image 15-0 */
414 if (frame >= img->num_frames)
415 frame = (2 * img->num_frames - 1) - frame;
416
417 size = (int)((BLOCK_SZ - 2 * FUEL_BORDER) * fuel / MAX_STATION_FUEL);
418
419 Image_paint(IMG_FUELCELL, x, y, 0, fuelColorRGBA);
420
421 area.x = 0;
422 area.y = (int)((BLOCK_SZ - 2 * FUEL_BORDER)
423 * (1 - fuel / MAX_STATION_FUEL));
424 area.w = BLOCK_SZ - 2 * FUEL_BORDER;
425 area.h = size;
426 Image_paint_area(IMG_FUEL,
427 x + FUEL_BORDER,
428 y + FUEL_BORDER,
429 frame,
430 &area,
431 fuelColorRGBA);
432 }
433
Gui_paint_base(int x,int y,int id,int team,int type)434 void Gui_paint_base(int x, int y, int id, int team, int type)
435 {
436 Uint32 color;
437 homebase_t *base = NULL;
438 other_t *other;
439 bool do_basewarning = false;
440
441 switch (type) {
442 case SETUP_BASE_UP:
443 Image_paint(IMG_BASE_DOWN, x, y, 0, whiteRGBA);
444 break;
445 case SETUP_BASE_DOWN:
446 Image_paint(IMG_BASE_UP, x, y + 1, 0, whiteRGBA);
447 break;
448 case SETUP_BASE_LEFT:
449 Image_paint(IMG_BASE_RIGHT, x, y, 0, whiteRGBA);
450 break;
451 case SETUP_BASE_RIGHT:
452 Image_paint(IMG_BASE_LEFT, x - 1, y, 0, whiteRGBA);
453 break;
454 default:
455 errno = 0;
456 error("Bad base dir.");
457 return;
458 }
459
460 if (!(other = Other_by_id(id))) return;
461
462 if (baseNameColorRGBA) {
463 if (!(color = Life_color(other)))
464 color = baseNameColorRGBA;
465 } else
466 color = whiteRGBA;
467
468 x = x + BLOCK_SZ / 2;
469 y = y + BLOCK_SZ / 2;
470
471 base = Homebase_by_id(id);
472 if (base != NULL) {
473 /*
474 * Hacks to support Mara's base warning on new servers and
475 * the red "meter" basewarning on old servers.
476 */
477 if (loops < base->appeartime)
478 do_basewarning = true;
479
480 if (version < 0x4F12 && do_basewarning) {
481 if (baseWarningType & 1) {
482 /* We assume the ship will appear after 3 seconds. */
483 int count = (int)(360 * (base->appeartime - loops)
484 / (3 * clientFPS));
485 LIMIT(count, 0, 360);
486 /* red box basewarning */
487 if (count > 0 && (baseWarningType & 1))
488 Gui_paint_appearing(x, y,
489 id, count);
490 }
491 }
492 }
493 /* Mara's flashy basewarning */
494 if (do_basewarning && (baseWarningType & 2)) {
495 if (loopsSlow & 1) {
496 if (color != whiteRGBA)
497 color = whiteRGBA;
498 else
499 color = redRGBA;
500 }
501 }
502
503 switch (type) {
504 case SETUP_BASE_UP:
505 mapnprint(&mapfont,color,CENTER,DOWN ,(x) ,(y - BLOCK_SZ / 2),maxCharsInNames,"%s",other->nick_name);
506 break;
507 case SETUP_BASE_DOWN:
508 mapnprint(&mapfont,color,CENTER,UP ,(x) ,(int)(y + BLOCK_SZ / 1.5),maxCharsInNames,"%s",other->nick_name);
509 break;
510 case SETUP_BASE_LEFT:
511 mapnprint(&mapfont,color,RIGHT,UP ,(x + BLOCK_SZ / 2) ,(y),maxCharsInNames,"%s",other->nick_name);
512 break;
513 case SETUP_BASE_RIGHT:
514 mapnprint(&mapfont,color,LEFT,UP ,(x - BLOCK_SZ / 2) ,(y),maxCharsInNames,"%s",other->nick_name);
515 break;
516 default:
517 errno = 0;
518 error("Bad base dir.");
519 }
520 }
521
Gui_paint_decor(int x,int y,int xi,int yi,int type,bool last,bool more_y)522 void Gui_paint_decor(int x, int y, int xi, int yi, int type,
523 bool last, bool more_y)
524 {
525 int mask;
526 static unsigned char decor[256];
527 static int decorReady = 0;
528
529 if (!decorReady) {
530 memset(decor, 0, sizeof decor);
531 decor[SETUP_DECOR_FILLED]
532 = DECOR_UP | DECOR_LEFT | DECOR_DOWN | DECOR_RIGHT;
533 decor[SETUP_DECOR_RU] = DECOR_UP | DECOR_RIGHT | DECOR_CLOSED;
534 decor[SETUP_DECOR_RD]
535 = DECOR_DOWN | DECOR_RIGHT | DECOR_OPEN | DECOR_BELOW;
536 decor[SETUP_DECOR_LU] = DECOR_UP | DECOR_LEFT | DECOR_OPEN;
537 decor[SETUP_DECOR_LD]
538 = DECOR_LEFT | DECOR_DOWN | DECOR_CLOSED | DECOR_BELOW;
539 }
540
541 mask = decor[type];
542
543 set_alphacolor(decorColorRGBA);
544 glBegin(GL_LINES);
545
546 if (mask & DECOR_LEFT) {
547 glVertex2i(x, y);
548 glVertex2i(x, y + BLOCK_SZ);
549 }
550 if (mask & DECOR_DOWN) {
551 glVertex2i(x, y);
552 glVertex2i(x + BLOCK_SZ, y);
553 }
554 if (mask & DECOR_RIGHT) {
555 glVertex2i(x + BLOCK_SZ, y);
556 glVertex2i(x + BLOCK_SZ, y + BLOCK_SZ);
557 }
558 if (mask & DECOR_UP) {
559 glVertex2i(x, y + BLOCK_SZ);
560 glVertex2i(x + BLOCK_SZ, y + BLOCK_SZ);
561 }
562 if (mask & DECOR_OPEN) {
563 glVertex2i(x, y);
564 glVertex2i(x + BLOCK_SZ, y + BLOCK_SZ);
565 } else if (mask & DECOR_CLOSED) {
566 glVertex2i(x, y + BLOCK_SZ);
567 glVertex2i(x + BLOCK_SZ, y);
568 }
569 glEnd();
570 }
571
Gui_paint_border(int x,int y,int xi,int yi)572 void Gui_paint_border(int x, int y, int xi, int yi)
573 {
574 set_alphacolor(wallColorRGBA);
575 glBegin(GL_LINE);
576 glVertex2i(x, y);
577 glVertex2i(xi, yi);
578 glEnd();
579 }
580
Gui_paint_visible_border(int x,int y,int xi,int yi)581 void Gui_paint_visible_border(int x, int y, int xi, int yi)
582 {
583 setupPaint_moving();
584 set_alphacolor(hudColorRGBA);
585 glBegin(GL_LINE_LOOP);
586 glVertex2i(x, y);
587 glVertex2i(x, yi);
588 glVertex2i(xi, yi);
589 glVertex2i(xi, y);
590 glEnd();
591 setupPaint_stationary();
592 }
593
Gui_paint_hudradar_limit(int x,int y,int xi,int yi)594 void Gui_paint_hudradar_limit(int x, int y, int xi, int yi)
595 {
596 set_alphacolor(blueRGBA);
597 glBegin(GL_LINE_LOOP);
598 glVertex2i(x, y);
599 glVertex2i(x, yi);
600 glVertex2i(xi, yi);
601 glVertex2i(xi, y);
602 glEnd();
603 }
604
Gui_paint_setup_check(int x,int y,bool isNext)605 void Gui_paint_setup_check(int x, int y, bool isNext)
606 {
607 if (isNext) {
608 Image_paint(IMG_CHECKPOINT, x, y, 0, whiteRGBA);
609 } else {
610 Image_paint(IMG_CHECKPOINT, x, y, 0, whiteRGBA - 128);
611 }
612 }
613
Gui_paint_setup_acwise_grav(int x,int y)614 void Gui_paint_setup_acwise_grav(int x, int y)
615 {
616 Image_paint(IMG_ACWISEGRAV, x, y, loopsSlow % 6, whiteRGBA);
617 }
618
Gui_paint_setup_cwise_grav(int x,int y)619 void Gui_paint_setup_cwise_grav(int x, int y)
620 {
621 Image_paint(IMG_CWISEGRAV, x, y, loopsSlow % 6, whiteRGBA);
622 }
623
Gui_paint_setup_pos_grav(int x,int y)624 void Gui_paint_setup_pos_grav(int x, int y)
625 {
626 Image_paint(IMG_PLUSGRAVITY, x, y, 0, whiteRGBA);
627 }
628
Gui_paint_setup_neg_grav(int x,int y)629 void Gui_paint_setup_neg_grav(int x, int y)
630 {
631 Image_paint(IMG_MINUSGRAVITY, x, y, 0, whiteRGBA);
632 }
633
paint_dir_grav(int x,int y,int dir)634 static void paint_dir_grav(int x, int y, int dir)
635 {
636 const int sz = BLOCK_SZ;
637 int cb, c0, c1, c2, p1, p2, swp;
638
639 cb = redRGBA - 255;
640 p1 = loops % sz;
641 p2 = (loops + sz / 2) % sz;
642
643 if (p1 < p2) {
644 c0 = cb + p1 * 128 / (sz / 2);
645 c1 = cb;
646 c2 = cb + 128;
647 } else {
648 c0 = cb + (sz - p1) * 128 / (sz / 2);
649 c1 = cb + 128;
650 c2 = cb;
651 swp = p1; p1 = p2; p2 = swp;
652 }
653
654 glEnable(GL_BLEND);
655
656 #define GRAV(x0,y0,x1,y1,x2,y2,x3,y3,x4,y4,x5,y5,x6,y6,x7,y7) \
657 glBegin(GL_QUAD_STRIP);\
658 set_alphacolor(c0); glVertex2i(x+x0,y+y0); glVertex2i(x+x1,y+y1);\
659 set_alphacolor(c1); glVertex2i(x+x2,y+y2); glVertex2i(x+x3,y+y3);\
660 set_alphacolor(c2); glVertex2i(x+x4,y+y4); glVertex2i(x+x5,y+y5);\
661 set_alphacolor(c0); glVertex2i(x+x6,y+y6); glVertex2i(x+x7,y+y7);\
662 glEnd();
663
664 switch(dir) {
665 case 0: /* up */
666 GRAV( 0, 0, sz, 0,
667 0, p1, sz, p1,
668 0, p2, sz, p2,
669 0, sz, sz, sz);
670 break;
671 case 1: /* right */
672 GRAV( 0, 0, 0, sz,
673 p1, 0, p1, sz,
674 p2, 0, p2, sz,
675 sz, 0, sz, sz);
676 break;
677 case 2: /* down */
678 GRAV( 0, sz, sz, sz,
679 0, sz-p1, sz, sz-p1,
680 0, sz-p2, sz, sz-p2,
681 0, 0, sz, 0);
682 break;
683 case 3: /* left */
684 GRAV( sz, 0, sz, sz,
685 sz-p1, 0, sz-p1, sz,
686 sz-p2, 0, sz-p2, sz,
687 0, 0, 0, sz);
688 break;
689 }
690 #undef GRAV
691
692 glDisable(GL_BLEND);
693 }
694
Gui_paint_setup_up_grav(int x,int y)695 void Gui_paint_setup_up_grav(int x, int y)
696 {
697 paint_dir_grav(x, y, 0);
698 }
699
Gui_paint_setup_down_grav(int x,int y)700 void Gui_paint_setup_down_grav(int x, int y)
701 {
702 paint_dir_grav(x, y, 2);
703 }
704
Gui_paint_setup_right_grav(int x,int y)705 void Gui_paint_setup_right_grav(int x, int y)
706 {
707 paint_dir_grav(x, y, 1);
708 }
709
Gui_paint_setup_left_grav(int x,int y)710 void Gui_paint_setup_left_grav(int x, int y)
711 {
712 paint_dir_grav(x, y, 3);
713 }
714
Gui_paint_setup_worm(int x,int y)715 void Gui_paint_setup_worm(int x, int y)
716 {
717 Image_paint_rotated(IMG_WORMHOLE, x, y, (loopsSlow << 3) % TABLE_SIZE, whiteRGBA);
718 }
719
Gui_paint_setup_item_concentrator(int x,int y)720 void Gui_paint_setup_item_concentrator(int x, int y)
721 {
722 Image_paint_rotated(IMG_CONCENTRATOR, x, y, (loopsSlow << 3) % TABLE_SIZE, whiteRGBA);
723 }
724
Gui_paint_setup_asteroid_concentrator(int x,int y)725 void Gui_paint_setup_asteroid_concentrator(int x, int y)
726 {
727 Image_paint_rotated(IMG_ASTEROIDCONC, x, y, (loopsSlow << 4) % TABLE_SIZE, whiteRGBA);
728 }
729
Gui_paint_decor_dot(int x,int y,int size)730 void Gui_paint_decor_dot(int x, int y, int size)
731 {
732 set_alphacolor(wallColorRGBA);
733 glBegin(GL_QUADS);
734 glVertex2i(x + ((BLOCK_SZ - size) >> 1),
735 y + ((BLOCK_SZ - size) >> 1));
736 glVertex2i(x + ((BLOCK_SZ - size) >> 1),
737 y + ((BLOCK_SZ + size) >> 1));
738 glVertex2i(x + ((BLOCK_SZ + size) >> 1),
739 y + ((BLOCK_SZ + size) >> 1));
740 glVertex2i(x + ((BLOCK_SZ + size) >> 1),
741 y + ((BLOCK_SZ - size) >> 1));
742 glEnd();
743 }
744
Gui_paint_setup_target(int x,int y,int team,double damage,bool own)745 void Gui_paint_setup_target(int x, int y, int team, double damage, bool own)
746 {
747 int damage_y;
748
749 Image_paint(IMG_TARGET, x, y, 0, whiteRGBA);
750 if (BIT(Setup->mode, TEAM_PLAY)) {
751 mapprint(&mapfont, whiteRGBA, RIGHT, UP, x + BLOCK_SZ, y, "%d", team);
752 }
753 if (damage != TARGET_DAMAGE) {
754 damage_y = y + (int)((BLOCK_SZ - 3) * (damage / TARGET_DAMAGE));
755 set_alphacolor(own ? blueRGBA : redRGBA);
756 glBegin(GL_LINE_LOOP);
757 glVertex2i(x, y + 3);
758 glVertex2i(x, y + BLOCK_SZ);
759 glVertex2i(x + 5, y + BLOCK_SZ);
760 glVertex2i(x + 5, y + 3);
761 glEnd();
762 glBegin(GL_QUADS);
763 glVertex2i(x, y + 3);
764 glVertex2i(x, damage_y);
765 glVertex2i(x + 5, damage_y);
766 glVertex2i(x + 5, y + 3);
767 glEnd();
768 }
769 }
770
Gui_paint_setup_treasure(int x,int y,int team,bool own)771 void Gui_paint_setup_treasure(int x, int y, int team, bool own)
772 {
773 Image_paint(own ? IMG_HOLDER_FRIEND : IMG_HOLDER_ENEMY, x, y, 0, whiteRGBA);
774 }
775
Gui_paint_walls(int x,int y,int type)776 void Gui_paint_walls(int x, int y, int type)
777 {
778 set_alphacolor(wallColorRGBA);
779 glBegin(GL_LINES);
780
781
782 if (type & BLUE_LEFT) {
783 glVertex2i(x, y);
784 glVertex2i(x, y + BLOCK_SZ);
785 }
786 if (type & BLUE_DOWN) {
787 glVertex2i(x, y);
788 glVertex2i(x + BLOCK_SZ, y);
789 }
790 if (type & BLUE_RIGHT) {
791 glVertex2i(x + BLOCK_SZ, y);
792 glVertex2i(x + BLOCK_SZ, y + BLOCK_SZ);
793 }
794 if (type & BLUE_UP) {
795 glVertex2i(x, y + BLOCK_SZ);
796 glVertex2i(x + BLOCK_SZ, y + BLOCK_SZ);
797 }
798 if ((type & BLUE_FUEL) == BLUE_FUEL) {
799 } else if (type & BLUE_OPEN) {
800 glVertex2i(x, y);
801 glVertex2i(x + BLOCK_SZ, y + BLOCK_SZ);
802 } else if (type & BLUE_CLOSED) {
803 glVertex2i(x, y + BLOCK_SZ);
804 glVertex2i(x + BLOCK_SZ, y);
805 }
806 glEnd();
807 }
808
Gui_paint_filled_slice(int bl,int tl,int tr,int br,int y)809 void Gui_paint_filled_slice(int bl, int tl, int tr, int br, int y)
810 {
811 set_alphacolor(wallColorRGBA);
812 glBegin(GL_QUADS);
813 glVertex2i(bl, y);
814 glVertex2i(tl, y + BLOCK_SZ);
815 glVertex2i(tr, y + BLOCK_SZ);
816 glVertex2i(br, y);
817 glEnd();
818 }
819
Gui_paint_polygon(int i,int xoff,int yoff)820 void Gui_paint_polygon(int i, int xoff, int yoff)
821 {
822 xp_polygon_t polygon;
823 polygon_style_t p_style;
824 edge_style_t e_style;
825 int width;
826 bool did_fill = false;
827
828 polygon = polygons[i];
829 p_style = polygon_styles[polygon.style];
830 e_style = edge_styles[p_style.def_edge_style];
831
832 if (BIT(p_style.flags, STYLE_INVISIBLE))
833 return;
834
835 glMatrixMode(GL_MODELVIEW);
836 glPushMatrix();
837 glLoadIdentity();
838
839 glTranslatef(polygon.points[0].x * clData.scale +
840 rint((xoff * Setup->width - world.x) * clData.scale),
841 polygon.points[0].y * clData.scale +
842 rint((yoff * Setup->height - world.y) * clData.scale), 0);
843 glScalef(clData.scale, clData.scale, 0);
844
845 /* possibly paint the polygon as filled or textured */
846 if ((instruments.texturedWalls || instruments.filledWorld) &&
847 BIT(p_style.flags, STYLE_TEXTURED | STYLE_FILLED)) {
848 if (BIT(p_style.flags, STYLE_TEXTURED)
849 && instruments.texturedWalls) {
850 Image_use_texture(p_style.texture);
851 glCallList(polyListBase + i);
852 Image_no_texture();
853 }
854 else {
855 set_alphacolor((p_style.rgb << 8) | 0xff);
856 glCallList(polyListBase + i);
857 }
858 did_fill = true;
859 }
860
861 width = e_style.width;
862 if (!did_fill && width == -1)
863 width = 1;
864
865 /* possibly paint the edges around the polygon */
866 if (width != -1) {
867 set_alphacolor((e_style.rgb << 8) | 0xff);
868 glLineWidth(width * clData.scale);
869 if (smoothLines) {
870 glEnable(GL_BLEND);
871 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
872 glEnable(GL_LINE_SMOOTH);
873 }
874 glCallList(polyEdgeListBase + i);
875 if (smoothLines) {
876 glDisable(GL_LINE_SMOOTH);
877 glDisable(GL_BLEND);
878 }
879 glLineWidth(1);
880 }
881 glPopMatrix();
882 }
883
884
885 /* Object painting */
886
887
Gui_paint_item_object(int type,int x,int y)888 void Gui_paint_item_object(int type, int x, int y)
889 {
890 int sz = 16;
891 Image_paint(IMG_ALL_ITEMS, x - 8, y - 4, type, whiteRGBA);
892 set_alphacolor(blueRGBA);
893 if (smoothLines) glEnable(GL_LINE_SMOOTH);
894 glBegin(GL_LINE_LOOP);
895 glVertex2i(x + sz, y + sz);
896 glVertex2i(x, y - sz);
897 glVertex2i(x - sz, y + sz);
898 glEnd();
899 if (smoothLines) glDisable(GL_LINE_SMOOTH);
900 }
901
Gui_paint_ball(int x,int y,int style)902 void Gui_paint_ball(int x, int y, int style)
903 {
904 int rgba = ballColorRGBA;
905
906 if (style >= 0 && style < num_polygon_styles)
907 rgba = (polygon_styles[style].rgb << 8) | 0xff;
908
909 if (texturedBalls)
910 Image_paint(IMG_BALL, x - BALL_RADIUS, y - BALL_RADIUS, 0, rgba);
911 else {
912 int i, numvert = 16, ang = RES / numvert;
913 /* kps hack, feel free to improve */
914 glEnable(GL_BLEND);
915 glBlendFunc(GL_SRC_ALPHA, GL_ONE);
916 set_alphacolor(ballColorRGBA);
917 if (smoothLines) glEnable(GL_LINE_SMOOTH);
918 glBegin(GL_LINE_LOOP);
919 for (i = 0; i < numvert; i++)
920 glVertex2d((double)x + tcos(i * ang) * BALL_RADIUS,
921 (double)y + tsin(i * ang) * BALL_RADIUS);
922 glEnd();
923 if (smoothLines) glDisable(GL_LINE_SMOOTH);
924 }
925 }
926
Gui_paint_ball_connector(int x_1,int y_1,int x_2,int y_2)927 void Gui_paint_ball_connector(int x_1, int y_1, int x_2, int y_2)
928 {
929 glEnable(GL_BLEND);
930 glBlendFunc(GL_SRC_ALPHA, GL_ONE);
931 set_alphacolor(connColorRGBA);
932 if (smoothLines) glEnable(GL_LINE_SMOOTH);
933 glBegin(GL_LINES);
934 glVertex2i(x_1, y_1);
935 glVertex2i(x_2, y_2);
936 glEnd();
937 if (smoothLines) glDisable(GL_LINE_SMOOTH);
938 }
939
Gui_paint_mine(int x,int y,int teammine,char * name)940 void Gui_paint_mine(int x, int y, int teammine, char *name)
941 {
942 Image_paint(teammine ? IMG_MINE_TEAM : IMG_MINE_OTHER,
943 x - 10, y - 7, 0, whiteRGBA);
944 if (name) {
945 mapnprint( &mapfont,
946 teammine ? blueRGBA : whiteRGBA,
947 CENTER, DOWN,
948 x, y - 15,
949 maxCharsInNames,"%s", name );
950 }
951 }
952
Gui_paint_spark(int color,int x,int y)953 void Gui_paint_spark(int color, int x, int y)
954 {
955 /*
956 Image_paint(IMG_SPARKS,
957 x + world.x,
958 world.y + ext_view_height - y,
959 color);
960 */
961 glColor3ub(255 * (color + 1) / 8,
962 255 * color * color / 64,
963 0);
964 glPointSize(sparkSize);
965 glBegin(GL_POINTS);
966 glVertex2i(x + world.x, world.y + ext_view_height - y);
967 glEnd();
968 }
969
Gui_paint_wreck(int x,int y,bool deadly,int wtype,int rot,int size)970 void Gui_paint_wreck(int x, int y, bool deadly, int wtype, int rot, int size)
971 {
972 int cnt, tx, ty;
973
974 set_alphacolor(deadly ? whiteRGBA : redRGBA);
975 glBegin(GL_LINE_LOOP);
976 for (cnt = 0; cnt < NUM_WRECKAGE_POINTS; cnt++) {
977 tx = (int)(wreckageShapes[wtype][cnt][rot].x * size) >> 8;
978 ty = (int)(wreckageShapes[wtype][cnt][rot].y * size) >> 8;
979 glVertex2i(x + tx, y + ty);
980 }
981 glEnd();
982 }
983
Gui_paint_asteroids_begin(void)984 void Gui_paint_asteroids_begin(void)
985 {
986 image_t *img;
987 GLfloat ambient[] = { 0.7F, 0.7F, 0.7F, 1.0F };
988
989 img = Image_get(IMG_ASTEROID);
990 if (img != NULL) {
991 glEnable(GL_TEXTURE_2D);
992 glBindTexture(GL_TEXTURE_2D, img->name);
993 }
994 glColor4ub(255, 255, 255, 255);
995 glEnable(GL_LIGHTING);
996 glEnable(GL_LIGHT0);
997 glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
998 glEnable(GL_CULL_FACE);
999 }
1000
Gui_paint_asteroids_end(void)1001 void Gui_paint_asteroids_end(void)
1002 {
1003 glDisable(GL_CULL_FACE);
1004 glDisable(GL_LIGHT0);
1005 glDisable(GL_LIGHTING);
1006 glDisable(GL_TEXTURE_2D);
1007
1008 /* this displays the asteroid hit area */
1009 #if 0
1010 int i, x, y, size;
1011 for (i = 0; i < num_asteroids; i++) {
1012 x = asteroid_ptr[i].x;
1013 y = asteroid_ptr[i].y;
1014 if (wrap(&x, &y)) {
1015 size = asteroid_ptr[i].size;
1016 Circle(whiteRGBA, x, y, (int)(0.8 * SHIP_SZ * size), 0);
1017 }
1018 }
1019 #endif
1020 }
1021
Gui_paint_asteroid(int x,int y,int type,int rot,int size)1022 void Gui_paint_asteroid(int x, int y, int type, int rot, int size)
1023 {
1024 GLfloat real_size;
1025
1026 real_size = 0.9 * SHIP_SZ * size;
1027 glPushMatrix();
1028 glTranslatef((GLfloat)x, (GLfloat)y, 0.0);
1029 glScalef(real_size, real_size, 1.0);
1030 glRotatef(360.0 * rot / TABLE_SIZE,
1031 (type & 1) - 0.5,
1032 (type & 2) - 1,
1033 (type & 4) - 2);
1034 glCallList(asteroid);
1035 glEnd();
1036 glPopMatrix();
1037 }
1038
1039
1040 /*
1041 * It seems that currently the screen coordinates are calculated already
1042 * in paintobjects.c. This should be changed.
1043 */
Gui_paint_fastshot(int color,int x,int y)1044 void Gui_paint_fastshot(int color, int x, int y)
1045 {
1046 int size = MIN(shotSize, 16);
1047
1048 Image_paint(IMG_BULLET,
1049 x + world.x - size/2,
1050 world.y - 16 + size/2 - 1 + ext_view_height - y,
1051 size - 1, whiteRGBA);
1052 }
1053
Gui_paint_teamshot(int x,int y)1054 void Gui_paint_teamshot(int x, int y)
1055 {
1056 int size = MIN(teamShotSize, 16);
1057
1058 Image_paint(IMG_BULLET_OWN,
1059 x + world.x - size/2,
1060 world.y - 16 + size/2 - 1 + ext_view_height - y,
1061 size - 1, whiteRGBA);
1062 }
1063
Gui_paint_missiles_begin(void)1064 void Gui_paint_missiles_begin(void)
1065 {
1066 }
1067
Gui_paint_missiles_end(void)1068 void Gui_paint_missiles_end(void)
1069 {
1070 }
1071
Gui_paint_missile(int x,int y,int len,int dir)1072 void Gui_paint_missile(int x, int y, int len, int dir)
1073 {
1074 Image_paint_rotated(IMG_MISSILE, x - 16, y - 16, dir, whiteRGBA);
1075 }
1076
Gui_paint_lasers_begin(void)1077 void Gui_paint_lasers_begin(void)
1078 {
1079 glEnable(GL_BLEND);
1080 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1081 if (smoothLines) glEnable(GL_LINE_SMOOTH);
1082 }
1083
Gui_paint_lasers_end(void)1084 void Gui_paint_lasers_end(void)
1085 {
1086 glDisable(GL_BLEND);
1087 if (smoothLines) glDisable(GL_LINE_SMOOTH);
1088 }
1089
Gui_paint_laser(int color,int x_1,int y_1,int len,int dir)1090 void Gui_paint_laser(int color, int x_1, int y_1, int len, int dir)
1091 {
1092 int x_2, y_2, rgba;
1093 x_2 = (int)(x_1 + len * tcos(dir));
1094 y_2 = (int)(y_1 + len * tsin(dir));
1095
1096 rgba =
1097 (color == RED) ? redRGBA :
1098 (color == BLUE) ? blueRGBA :
1099 whiteRGBA;
1100
1101 set_alphacolor(rgba - 128);
1102 glLineWidth(5);
1103 glBegin(GL_LINES);
1104 glVertex2i(x_1, y_1);
1105 glVertex2i(x_2, y_2);
1106 glEnd();
1107
1108 set_alphacolor(rgba);
1109 glLineWidth(1);
1110 glBegin(GL_LINES);
1111 glVertex2i(x_1, y_1);
1112 glVertex2i(x_2, y_2);
1113 glEnd();
1114 }
1115
Gui_paint_paused(int x,int y,int count)1116 void Gui_paint_paused(int x, int y, int count)
1117 {
1118 Image_paint(IMG_PAUSED,
1119 x - BLOCK_SZ / 2,
1120 y - BLOCK_SZ / 2,
1121 (count <= 0 || loopsSlow % 10 >= 5) ? 1 : 0, whiteRGBA);
1122 }
1123
Gui_paint_appearing(int x,int y,int id,int count)1124 void Gui_paint_appearing(int x, int y, int id, int count)
1125 {
1126 const unsigned hsize = 3 * BLOCK_SZ / 7;
1127 int minx,miny,maxx,maxy;
1128 Uint32 color;
1129 other_t *other = Other_by_id(id);
1130
1131 /* Make a note we are doing the base warning */
1132 if (version >= 0x4F12) {
1133 homebase_t *base = Homebase_by_id(id);
1134 if (base != NULL)
1135 base->appeartime = (long)(loops + (count * clientFPS) / 120);
1136 }
1137
1138 minx = x - (int)hsize;
1139 miny = y - (int)hsize;
1140 maxx = minx + 2 * hsize + 1;
1141 maxy = miny + (unsigned)(count / 180. * hsize + 1);
1142
1143 color = Life_color(other);
1144 set_alphacolor((color)?color:redRGBA);
1145
1146 glEnable(GL_BLEND);
1147 glBlendFunc(GL_SRC_ALPHA, GL_ONE);
1148 glBegin(GL_QUADS);
1149 glVertex2i(minx , miny);
1150 glVertex2i(maxx , miny);
1151 glVertex2i(maxx , maxy);
1152 glVertex2i(minx , maxy);
1153 glEnd();
1154 }
1155
Gui_paint_ecm(int x,int y,int size)1156 void Gui_paint_ecm(int x, int y, int size)
1157 {
1158 }
1159
Gui_paint_refuel(int x_0,int y_0,int x_1,int y_1)1160 void Gui_paint_refuel(int x_0, int y_0, int x_1, int y_1)
1161 {
1162 int stipple = 4;
1163
1164 set_alphacolor(fuelColorRGBA);
1165 glEnable(GL_BLEND);
1166 glBlendFunc(GL_SRC_ALPHA, GL_ONE);
1167 glLineStipple(stipple, 0xAAAA);
1168 glEnable(GL_LINE_STIPPLE);
1169 if (smoothLines) glEnable(GL_LINE_SMOOTH);
1170 glBegin(GL_LINES);
1171 glVertex2i(x_0, y_0);
1172 glVertex2i(x_1, y_1);
1173 glEnd();
1174 if (smoothLines) glDisable(GL_LINE_SMOOTH);
1175 glDisable(GL_LINE_STIPPLE);
1176 }
1177
Gui_paint_connector(int x_0,int y_0,int x_1,int y_1,int tractor)1178 void Gui_paint_connector(int x_0, int y_0, int x_1, int y_1, int tractor)
1179 {
1180 glEnable(GL_BLEND);
1181 glBlendFunc(GL_SRC_ALPHA, GL_ONE);
1182 set_alphacolor(connColorRGBA);
1183 glLineStipple(tractor ? 2 : 4, 0xAAAA);
1184 glEnable(GL_LINE_STIPPLE);
1185 if (smoothLines) glEnable(GL_LINE_SMOOTH);
1186 glBegin(GL_LINES);
1187 glVertex2i(x_0, y_0);
1188 glVertex2i(x_1, y_1);
1189 glEnd();
1190 if (smoothLines) glDisable(GL_LINE_SMOOTH);
1191 glDisable(GL_LINE_STIPPLE);
1192 /*glDisable(GL_BLEND);*/
1193 }
1194
Gui_paint_transporter(int x_0,int y_0,int x_1,int y_1)1195 void Gui_paint_transporter(int x_0, int y_0, int x_1, int y_1)
1196 {
1197 }
1198
Gui_paint_all_connectors_begin(void)1199 void Gui_paint_all_connectors_begin(void)
1200 {
1201 }
1202
Gui_paint_ships_begin(void)1203 void Gui_paint_ships_begin(void)
1204 {
1205 }
1206
Gui_paint_ships_end(void)1207 void Gui_paint_ships_end(void)
1208 {
1209 }
1210
1211 /*
1212 * Assume MAX_TEAMS is 10
1213 */
Team_color(int team)1214 int Team_color(int team)
1215 {
1216 switch (team) {
1217 case 0: return team0ColorRGBA;
1218 case 1: return team1ColorRGBA;
1219 case 2: return team2ColorRGBA;
1220 case 3: return team3ColorRGBA;
1221 case 4: return team4ColorRGBA;
1222 case 5: return team5ColorRGBA;
1223 case 6: return team6ColorRGBA;
1224 case 7: return team7ColorRGBA;
1225 case 8: return team8ColorRGBA;
1226 case 9: return team9ColorRGBA;
1227 default: break;
1228 }
1229 return 0;
1230 }
1231
Life_color_by_life(int life)1232 int Life_color_by_life(int life)
1233 {
1234 int color;
1235
1236 if (life > 2)
1237 color = manyLivesColorRGBA;
1238 else if (life == 2)
1239 color = twoLivesColorRGBA;
1240 else if (life == 1)
1241 color = oneLifeColorRGBA;
1242 else /* we catch all */
1243 color = zeroLivesColorRGBA;
1244 return color;
1245 }
1246
Life_color(other_t * other)1247 int Life_color(other_t *other)
1248 {
1249 int color = 0; /* default is 'no special color' */
1250
1251 if (other
1252 && (other->mychar == ' ' || other->mychar == 'R')
1253 && BIT(Setup->mode, LIMITED_LIVES))
1254 color = Life_color_by_life(other->life);
1255 return color;
1256 }
1257
Gui_is_my_tank(other_t * other)1258 static int Gui_is_my_tank(other_t *other)
1259 {
1260 char tank_name[MAX_NAME_LEN];
1261
1262 if (self == NULL
1263 || other == NULL
1264 || other->mychar != 'T'
1265 || (BIT(Setup->mode, TEAM_PLAY)
1266 && self->team != other->team)) {
1267 return 0;
1268 }
1269
1270 if (strlcpy(tank_name, self->nick_name, MAX_NAME_LEN) < MAX_NAME_LEN)
1271 strlcat(tank_name, "'s tank", MAX_NAME_LEN);
1272
1273 if (strcmp(tank_name, other->nick_name))
1274 return 0;
1275
1276 return 1;
1277 }
1278
Gui_calculate_ship_color(int id,other_t * other)1279 static int Gui_calculate_ship_color(int id, other_t *other)
1280 {
1281 Uint32 ship_color = whiteRGBA;
1282
1283 #ifndef NO_BLUE_TEAM
1284 if (BIT(Setup->mode, TEAM_PLAY)
1285 && eyesId != id
1286 && other != NULL
1287 && eyeTeam == other->team) {
1288 /* Paint teammates and allies ships with last life in teamLWColorRGBA */
1289 if (BIT(Setup->mode, LIMITED_LIVES)
1290 && (other->life == 0))
1291 ship_color = teamLWColorRGBA;
1292 else
1293 ship_color = teamShipColorRGBA;
1294 }
1295
1296 if (eyes != NULL
1297 && eyesId != id
1298 && other != NULL
1299 && eyes->alliance != ' '
1300 && eyes->alliance == other->alliance) {
1301 /* Paint teammates and allies ships with last life in teamLWColorRGBA */
1302 if (BIT(Setup->mode, LIMITED_LIVES)
1303 && (other->life == 0))
1304 ship_color = teamLWColorRGBA;
1305 else
1306 ship_color = teamShipColorRGBA;
1307 }
1308
1309 if (Gui_is_my_tank(other))
1310 ship_color = blueRGBA;
1311 #endif
1312 if (roundDelay > 0 && ship_color == whiteRGBA)
1313 ship_color = redRGBA;
1314
1315 /* Check for team color */
1316 if (other && BIT(Setup->mode, TEAM_PLAY)) {
1317 int team_color = Team_color(other->team);
1318 if (team_color)
1319 return team_color;
1320 }
1321
1322 /* Vato color hack start, edited by mara & kps */
1323 if (BIT(Setup->mode, LIMITED_LIVES)) {
1324 /* Paint your ship in selfLWColorRGBA when on last life */
1325 if (eyes != NULL
1326 && eyes->id == id
1327 && eyes->life == 0) {
1328 ship_color = selfLWColorRGBA;
1329 }
1330
1331 /* Paint enemy ships with last life in enemyLWColorRGBA */
1332 if (eyes != NULL
1333 && eyes->id != id
1334 && other != NULL
1335 && eyeTeam != other->team
1336 && other->life == 0) {
1337 ship_color = enemyLWColorRGBA;
1338 }
1339 }
1340 /* Vato color hack end */
1341
1342 return ship_color;
1343 }
1344
Gui_paint_ship_name(int x,int y,other_t * other)1345 static void Gui_paint_ship_name(int x, int y, other_t *other)
1346 {
1347 int color = Life_color(other);
1348
1349 /* TODO : do all name painting together, so we don't need
1350 * all theese setupPaint<foo> calls
1351 */
1352 if (shipNameColorRGBA) {
1353 if (!color)
1354 color = shipNameColorRGBA;
1355
1356 mapnprint(&mapfont, color, CENTER, DOWN,x,y - SHIP_SZ,maxCharsInNames,"%s",other->id_string);
1357 } else
1358 color = blueRGBA;
1359
1360 if (instruments.showLivesByShip
1361 && BIT(Setup->mode, LIMITED_LIVES)) {
1362 if (other->life < 1)
1363 color = whiteRGBA;
1364
1365 mapprint(&mapfont, color, LEFT, CENTER,x + SHIP_SZ,y,"%d", other->life);
1366 }
1367 }
1368
Gui_paint_ship(int x,int y,int dir,int id,int cloak,int phased,int shield,int deflector,int eshield)1369 void Gui_paint_ship(int x, int y, int dir, int id, int cloak, int phased,
1370 int shield, int deflector, int eshield)
1371 {
1372 int i, color, img;
1373 shipshape_t *ship;
1374 position_t point;
1375 other_t *other;
1376
1377 if (!(other = Other_by_id(id))) return;
1378
1379 if (!(color = Gui_calculate_ship_color(id,other))) return;
1380
1381 if ((!instruments.showShipShapes) && (self != NULL) && (self->id != id))
1382 ship = Default_ship();
1383 else if ((!instruments.showMyShipShape) && (self != NULL) && (self->id == id))
1384 ship = Default_ship();
1385 else
1386 ship = Ship_by_id(id);
1387
1388 if (shield) {
1389 Image_paint(IMG_SHIELD, x - 27, y - 27, 0, (color & 0xffffff00) + ((color & 0x000000ff)/2));
1390 }
1391 if (texturedShips) {
1392 if (BIT(Setup->mode, TEAM_PLAY)
1393 && other != NULL
1394 && self != NULL
1395 && self->team == other->team) {
1396 img = IMG_SHIP_FRIEND;
1397 } else if (self != NULL && self->id != id) {
1398 img = IMG_SHIP_ENEMY;
1399 } else {
1400 img = IMG_SHIP_SELF;
1401 }
1402 if (cloak || phased) Image_paint_rotated(img, x, y, dir, (color & 0xffffff00) + ((color & 0x000000ff)/2));
1403 else Image_paint_rotated(img, x, y, dir, color);
1404 } else {
1405 glEnable(GL_BLEND);
1406 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1407 glEnable(GL_LINE_SMOOTH);
1408 glLineWidth(shipLineWidth);
1409 set_alphacolor(color);
1410
1411 if (cloak || phased ) {
1412 glEnable(GL_LINE_STIPPLE);
1413 glLineStipple( 3, 0xAAAA );
1414 }
1415
1416 glBegin(GL_LINE_LOOP);
1417 for (i = 0; i < ship->num_points; i++) {
1418 point = Ship_get_point_position(ship, i, dir);
1419 glVertex2d(x + point.x, y + point.y);
1420 }
1421 glEnd();
1422
1423 if (cloak || phased ) glDisable(GL_LINE_STIPPLE);
1424
1425 glLineWidth(1);
1426 glDisable(GL_LINE_SMOOTH);
1427 glDisable(GL_BLEND);
1428 }
1429 if (self != NULL
1430 && self->id != id
1431 && other != NULL)
1432 Gui_paint_ship_name(x,y,other);
1433 }
1434
Paint_score_objects(void)1435 void Paint_score_objects(void)
1436 {
1437 int i, x, y;
1438
1439 if (!get_alpha(scoreObjectColorRGBA))
1440 return;
1441
1442 for (i = 0; i < MAX_SCORE_OBJECTS; i++) {
1443 score_object_t* sobj = &score_objects[i];
1444 if (sobj->life_time > 0) {
1445 if (loopsSlow % 3) {
1446 /* approximate font width to h =( */
1447 x = sobj->x * BLOCK_SZ + BLOCK_SZ/2;
1448 y = sobj->y * BLOCK_SZ + BLOCK_SZ/2;
1449 if (wrap(&x, &y)) {
1450 /*mapprint(&mapfont,scoreObjectColorRGBA,CENTER,CENTER,x,y,"%s",sobj->msg);*/
1451 if (!score_object_texs[i].tex_list || strcmp(sobj->msg,score_object_texs[i].text)) {
1452 free_string_texture(&score_object_texs[i]);
1453 draw_text(&mapfont, scoreObjectColorRGBA
1454 ,CENTER,CENTER, x, y, sobj->msg, true
1455 , &score_object_texs[i],false);
1456 } else disp_text(&score_object_texs[i],scoreObjectColorRGBA,CENTER,CENTER,x,y,false);
1457 }
1458 }
1459 sobj->life_time -= timePerFrame;
1460 if (sobj->life_time <= 0.0) {
1461 sobj->life_time = 0.0;
1462 sobj->hud_msg_len = 0;
1463 }
1464 } else {
1465 if (score_object_texs[i].tex_list) free_string_texture(&score_object_texs[i]);
1466 }
1467 }
1468 }
1469
Paint_select(void)1470 void Paint_select(void)
1471 {
1472 if(!select_bounds) return;
1473 set_alphacolor(selectionColorRGBA);
1474 glBegin(GL_LINE_LOOP);
1475 glVertex2i(select_bounds->x ,select_bounds->y );
1476 glVertex2i(select_bounds->x + select_bounds->w ,select_bounds->y );
1477 glVertex2i(select_bounds->x + select_bounds->w ,select_bounds->y + select_bounds->h);
1478 glVertex2i(select_bounds->x ,select_bounds->y + select_bounds->h);
1479 glEnd();
1480 }
1481
Paint_HUD_values(void)1482 void Paint_HUD_values(void)
1483 {
1484 int x, y;
1485
1486 if (!hudColorRGBA)
1487 return;
1488
1489 x = draw_width - 20;
1490 /* Better make sure it's below the meters */
1491 y = draw_height - 9*(MAX((GLuint)meterHeight,gamefont.h) + 6);
1492
1493 HUDprint(&gamefont,hudColorRGBA,RIGHT,DOWN,x,y,"FPS: %.3f",clientFPS);
1494 HUDprint(&gamefont,hudColorRGBA,RIGHT,DOWN,x,y-20,"CL.LAG : %.1f ms", clData.clientLag);
1495 }
1496
Paint_meter(int xoff,int y,string_tex_t * tex,int val,int max,int meter_color)1497 static void Paint_meter(int xoff, int y, string_tex_t *tex, int val, int max,
1498 int meter_color)
1499 {
1500 int mw1_4 = meterWidth/4,
1501 mw2_4 = meterWidth/2,
1502 mw3_4 = 3*meterWidth/4,
1503 mw4_4 = meterWidth,
1504 BORDER = 5;
1505 int x, xstr;
1506 int x_alignment;
1507 int color;
1508
1509 if (xoff >= 0) {
1510 x = xoff;
1511 xstr = x + meterWidth + BORDER;
1512 x_alignment = LEFT;
1513 } else {
1514 x = draw_width - (meterWidth - xoff);
1515 xstr = x - BORDER;
1516 x_alignment = RIGHT;
1517 }
1518
1519 set_alphacolor(meter_color);
1520 glBegin( GL_POLYGON );
1521 glVertex2i(x,y);
1522 glVertex2i(x,y+2+meterHeight-3);
1523 glVertex2i(x+(int)(((meterWidth)*val)/(max?max:1)),y+2+meterHeight-3);
1524 glVertex2i(x+(int)(((meterWidth)*val)/(max?max:1)),y);
1525 glEnd();
1526
1527
1528
1529 /* meterBorderColorRGBA = 0 obviously means no meter borders are drawn */
1530 if (meterBorderColorRGBA) {
1531 color = meterBorderColorRGBA;
1532
1533 set_alphacolor(color);
1534 glBegin( GL_LINE_LOOP );
1535 glVertex2i(x,y);
1536 glVertex2i(x,y + meterHeight);
1537 glVertex2i(x + meterWidth,y + meterHeight);
1538 glVertex2i(x + meterWidth,y);
1539 glEnd();
1540
1541 glBegin( GL_LINES );
1542 glVertex2i(x, y-4);glVertex2i(x, y+meterHeight+4);
1543 glVertex2i(x+mw4_4, y-4);glVertex2i(x+mw4_4, y+meterHeight+4);
1544 glVertex2i(x+mw2_4, y-3);glVertex2i(x+mw2_4, y+meterHeight+3);
1545 glVertex2i(x+mw1_4, y-1);glVertex2i(x+mw1_4, y+meterHeight+1);
1546 glVertex2i(x+mw3_4, y-1);glVertex2i(x+mw3_4, y+meterHeight+1);
1547 glEnd();
1548 }
1549
1550 if (!meterBorderColorRGBA)
1551 color = meter_color;
1552
1553 disp_text(tex,color,x_alignment,CENTER,xstr,draw_height - y - meterHeight/2,true);
1554 }
1555
Paint_meters(void)1556 void Paint_meters(void)
1557 {
1558 int spacing = MAX((GLuint)meterHeight,gamefont.h) + 6;
1559 int y = spacing, color;
1560 static bool setup_texs = true;
1561
1562 if (setup_texs) {
1563 render_text(&gamefont,"Fuel" , &meter_texs[0]);
1564 render_text(&gamefont,"Power" , &meter_texs[1]);
1565 render_text(&gamefont,"Turnspeed" , &meter_texs[2]);
1566 render_text(&gamefont,"Packet" , &meter_texs[3]);
1567 render_text(&gamefont,"Loss" , &meter_texs[4]);
1568 render_text(&gamefont,"Drop" , &meter_texs[5]);
1569 render_text(&gamefont,"Lag" , &meter_texs[6]);
1570 render_text(&gamefont,"Thrust Left" , &meter_texs[7]);
1571 render_text(&gamefont,"Shields Left" , &meter_texs[8]);
1572 render_text(&gamefont,"Phasing left" , &meter_texs[9]);
1573 render_text(&gamefont,"Self destructing", &meter_texs[10]);
1574 render_text(&gamefont,"SHUTDOWN" , &meter_texs[11]);
1575 setup_texs = false;
1576 }
1577
1578 glEnable(GL_BLEND);
1579 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1580 if (fuelMeterColorRGBA)
1581 Paint_meter(-10, y += spacing, &meter_texs[0],
1582 (int)fuelSum, (int)fuelMax, fuelMeterColorRGBA);
1583
1584 if (powerMeterColorRGBA)
1585 color = powerMeterColorRGBA;
1586 else if (controlTime > 0.0)
1587 color = temporaryMeterColorRGBA;
1588 else
1589 color = 0;
1590
1591 if (color)
1592 Paint_meter(-10, y += spacing, &meter_texs[1],
1593 (int)displayedPower, (int)MAX_PLAYER_POWER, color);
1594
1595 if (turnSpeedMeterColorRGBA)
1596 color = turnSpeedMeterColorRGBA;
1597 else if (controlTime > 0.0)
1598 color = temporaryMeterColorRGBA;
1599 else
1600 color = 0;
1601
1602 if (color)
1603 Paint_meter(-10, y += spacing, &meter_texs[2],
1604 (int)displayedTurnspeed, (int)MAX_PLAYER_TURNSPEED, color);
1605
1606 if (controlTime > 0.0) {
1607 controlTime -= timePerFrame;
1608 if (controlTime <= 0.0)
1609 controlTime = 0.0;
1610 }
1611
1612 if (packetSizeMeterColorRGBA)
1613 Paint_meter(-10, y += spacing, &meter_texs[3],
1614 (packet_size >= 4096) ? 4096 : packet_size, 4096,
1615 packetSizeMeterColorRGBA);
1616 if (packetLossMeterColorRGBA)
1617 Paint_meter(-10, y += spacing, &meter_texs[4], packet_loss, FPS,
1618 packetLossMeterColorRGBA);
1619 if (packetDropMeterColorRGBA)
1620 Paint_meter(-10, y += spacing, &meter_texs[5], packet_drop, FPS,
1621 packetDropMeterColorRGBA);
1622 if (packetLagMeterColorRGBA)
1623 Paint_meter(-10, y += spacing, &meter_texs[6], MIN(packet_lag, 1 * FPS), 1 * FPS,
1624 packetLagMeterColorRGBA);
1625
1626 if (temporaryMeterColorRGBA) {
1627 if (thrusttime >= 0 && thrusttimemax > 0)
1628 Paint_meter((ext_view_width-300)/2 -32, 2*ext_view_height/3,
1629 &meter_texs[7],
1630 (thrusttime >= thrusttimemax
1631 ? thrusttimemax : thrusttime),
1632 thrusttimemax, temporaryMeterColorRGBA);
1633
1634 if (shieldtime >= 0 && shieldtimemax > 0)
1635 Paint_meter((ext_view_width-300)/2 -32, 2*ext_view_height/3 + spacing,
1636 &meter_texs[8],
1637 (shieldtime >= shieldtimemax
1638 ? shieldtimemax : shieldtime),
1639 shieldtimemax, temporaryMeterColorRGBA);
1640
1641 if (phasingtime >= 0 && phasingtimemax > 0)
1642 Paint_meter((ext_view_width-300)/2 -32, 2*ext_view_height/3 + 2*spacing,
1643 &meter_texs[9],
1644 (phasingtime >= phasingtimemax
1645 ? phasingtimemax : phasingtime),
1646 phasingtimemax, temporaryMeterColorRGBA);
1647
1648 if (destruct > 0)
1649 Paint_meter((ext_view_width-300)/2 -32, 2*ext_view_height/3 + 3*spacing,
1650 &meter_texs[10], destruct, (int)SELF_DESTRUCT_DELAY,
1651 temporaryMeterColorRGBA);
1652
1653 if (shutdown_count >= 0)
1654 Paint_meter((ext_view_width-300)/2 -32, 2*ext_view_height/3 + 4*spacing,
1655 &meter_texs[11], shutdown_count, shutdown_delay,
1656 temporaryMeterColorRGBA);
1657 }
1658 glDisable(GL_BLEND);
1659 }
1660
Paint_lock(int hud_pos_x,int hud_pos_y)1661 static void Paint_lock(int hud_pos_x, int hud_pos_y)
1662 {
1663 other_t *target;
1664 const int BORDER = 2;
1665
1666 if ((target = Other_by_id(lock_id)) == NULL)
1667 return;
1668
1669 if (hudColorRGBA) {
1670 int color = Life_color(target);
1671
1672 if (!color)
1673 color = hudColorRGBA;
1674
1675 HUDnprint(&gamefont,
1676 color,CENTER,CENTER,
1677 hud_pos_x,
1678 hud_pos_y -(- hudSize + HUD_OFFSET - BORDER),
1679 strlen(target->id_string),"%s",target->id_string);
1680
1681 }
1682
1683
1684 }
1685
Paint_hudradar_dot(int x,int y,Uint32 col,int shape,int sz)1686 static void Paint_hudradar_dot(int x, int y, Uint32 col, int shape, int sz)
1687 {
1688 if (col == 0 || shape < 2 || sz == 0) return;
1689 set_alphacolor(col);
1690
1691 switch(shape) {
1692 case 2:
1693 case 3:
1694 Circle(col, x, y, sz, shape == 2 ? 1 : 0);
1695 break;
1696 case 4:
1697 case 5:
1698 glBegin(shape == 4 ? GL_QUADS : GL_LINE_LOOP);
1699 glVertex2i(x - sz, y - sz);
1700 glVertex2i(x - sz, y + sz);
1701 glVertex2i(x + sz, y + sz);
1702 glVertex2i(x + sz, y - sz);
1703 glEnd();
1704 break;
1705 case 6:
1706 case 7:
1707 glBegin(shape == 6 ? GL_TRIANGLES : GL_LINE_LOOP);
1708 glVertex2i(x - sz, y + sz);
1709 glVertex2i(x, y - sz);
1710 glVertex2i(x + sz, y + sz);
1711 glEnd();
1712 break;
1713 }
1714 }
1715
Paint_hudradar(double hrscale,double xlimit,double ylimit,int sz)1716 static void Paint_hudradar(double hrscale, double xlimit, double ylimit, int sz)
1717 {
1718 Uint32 c;
1719 int i, x, y, shape, size;
1720 int hrw = (int)(hrscale * 256);
1721 int hrh = (int)(hrscale * RadarHeight);
1722 double xf = (double) hrw / (double) Setup->width;
1723 double yf = (double) hrh / (double) Setup->height;
1724
1725 for (i = 0; i < num_radar; i++) {
1726 x = (int)(radar_ptr[i].x * hrscale
1727 - (world.x + ext_view_width / 2) * xf);
1728 y = (int)(radar_ptr[i].y * hrscale
1729 - (world.y + ext_view_height / 2) * yf);
1730
1731 if (x < -hrw / 2)
1732 x += hrw;
1733 else if (x > hrw / 2)
1734 x -= hrw;
1735
1736 if (y < -hrh / 2)
1737 y += hrh;
1738 else if (y > hrh / 2)
1739 y -= hrh;
1740
1741 if (!((x <= xlimit) && (x >= -xlimit)
1742 && (y <= ylimit) && (y >= -ylimit))) {
1743
1744 x = x + draw_width / 2;
1745 y = -y + draw_height / 2;
1746
1747 if (radar_ptr[i].type == RadarEnemy) {
1748 c = hudRadarEnemyColorRGBA;
1749 shape = hudRadarEnemyShape;
1750 } else {
1751 c = hudRadarOtherColorRGBA;
1752 shape = hudRadarOtherShape;
1753 }
1754 size = sz;
1755 if (radar_ptr[i].size == 0) {
1756 size >>= 1;
1757 if (hudRadarObjectColorRGBA)
1758 c = hudRadarObjectColorRGBA;
1759 if (hudRadarObjectShape)
1760 shape = hudRadarObjectShape;
1761 }
1762 Paint_hudradar_dot(x, y, c, shape, size);
1763 }
1764 }
1765 }
1766
Paint_HUD_items(int hud_pos_x,int hud_pos_y)1767 static void Paint_HUD_items(int hud_pos_x, int hud_pos_y)
1768 {
1769 const int BORDER = 3;
1770 char str[50];
1771 int vert_pos, horiz_pos, minx, miny, maxx, maxy;
1772 int i, maxWidth = -1,
1773 rect_x, rect_y, rect_width = 0, rect_height = 0;
1774 static int vertSpacing = -1;
1775 static fontbounds fb;
1776
1777
1778 /* Special itemtypes */
1779 if (vertSpacing < 0)
1780 vertSpacing = MAX(ITEM_SIZE, gamefont.h) + 1;
1781 /* find the scaled location, then work in pixels */
1782 vert_pos = hud_pos_y - hudSize+HUD_OFFSET + BORDER;
1783 horiz_pos = hud_pos_x - hudSize+HUD_OFFSET - BORDER;
1784 rect_width = 0;
1785 rect_height = 0;
1786 rect_x = horiz_pos;
1787 rect_y = vert_pos;
1788
1789 for (i = 0; i < NUM_ITEMS; i++) {
1790 int num = numItems[i];
1791
1792 if (i == ITEM_FUEL)
1793 continue;
1794
1795 if (instruments.showItems) {
1796 lastNumItems[i] = num;
1797 if (num <= 0)
1798 num = -1;
1799 } else {
1800 if (num != lastNumItems[i]) {
1801 numItemsTime[i] = (int)(showItemsTime * (double)FPS);
1802 lastNumItems[i] = num;
1803 }
1804 if (numItemsTime[i]-- <= 0) {
1805 numItemsTime[i] = 0;
1806 num = -1;
1807 }
1808 }
1809
1810 if (num >= 0) {
1811
1812 Image_paint(IMG_HUD_ITEMS,
1813 horiz_pos - ITEM_SIZE,
1814 vert_pos, (u_byte)i,
1815 hudItemsColorRGBA);
1816
1817 if (i == lose_item) {
1818 if (lose_item_active != 0) {
1819 if (lose_item_active < 0)
1820 lose_item_active++;
1821 minx = horiz_pos-ITEM_SIZE-2;
1822 maxx = horiz_pos;
1823 miny = vert_pos-2;
1824 maxy = vert_pos + ITEM_SIZE;
1825
1826 glBegin(GL_LINE_LOOP);
1827 glVertex2i(minx , miny);
1828 glVertex2i(maxx , miny);
1829 glVertex2i(maxx , maxy);
1830 glVertex2i(minx , maxy);
1831 glEnd();
1832 }
1833 }
1834
1835 /* Paint item count */
1836 sprintf(str, "%d", num);
1837 fb = printsize(&gamefont,"%s",str);
1838
1839 maxWidth = MAX(maxWidth, fb.width + BORDER + ITEM_SIZE);
1840
1841 HUDprint(&gamefont,hudItemsColorRGBA,RIGHT,UP,horiz_pos - ITEM_SIZE - BORDER
1842 ,draw_height - vert_pos - ITEM_SIZE,"%s",str);
1843
1844 vert_pos += vertSpacing;
1845
1846 if (vert_pos+vertSpacing
1847 > hud_pos_y+hudSize-HUD_OFFSET-BORDER) {
1848 rect_width += maxWidth + 2*BORDER;
1849 rect_height = MAX(rect_height, vert_pos - rect_y);
1850 horiz_pos -= maxWidth + 2*BORDER;
1851 vert_pos = hud_pos_y - hudSize+HUD_OFFSET + BORDER;
1852 maxWidth = -1;
1853 }
1854 }
1855 }
1856 if (maxWidth != -1)
1857 rect_width += maxWidth + BORDER;
1858
1859 if (rect_width > 0) {
1860 if (rect_height == 0)
1861 rect_height = vert_pos - rect_y;
1862 rect_x -= rect_width;
1863 }
1864
1865 }
1866
1867 typedef char hud_text_t[50];
1868
Paint_HUD(void)1869 void Paint_HUD(void)
1870 {
1871 const int BORDER = 3;
1872 char str[50];
1873 int hud_pos_x, hud_pos_y, size;
1874 int did_fuel = 0;
1875 int i, j, tex_index, modlen = 0;
1876 static char autopilot[] = "Autopilot";
1877 int tempx,tempy,tempw,temph;
1878 static hud_text_t hud_texts[MAX_HUD_TEXS+MAX_SCORE_OBJECTS];
1879
1880 fontbounds dummy;
1881 tex_index = 0;
1882 glEnable(GL_BLEND);
1883 /*
1884 * Show speed pointer
1885 */
1886 glBlendFunc(GL_SRC_ALPHA, GL_ONE);
1887 if (ptr_move_fact != 0.0
1888 && selfVisible
1889 && (selfVel.x != 0 || selfVel.y != 0))
1890 Segment_add(hudColorRGBA,
1891 draw_width / 2,
1892 draw_height / 2,
1893 (int)(draw_width / 2 - ptr_move_fact * selfVel.x),
1894 (int)(draw_height / 2 + ptr_move_fact * selfVel.y));
1895
1896 if (selfVisible && dirPtrColorRGBA) {
1897 Segment_add(dirPtrColorRGBA,
1898 (int) (draw_width / 2 +
1899 (100 - 15) * tcos(heading)),
1900 (int) (draw_height / 2 -
1901 (100 - 15) * tsin(heading)),
1902 (int) (draw_width / 2 + 100 * tcos(heading)),
1903 (int) (draw_height / 2 - 100 * tsin(heading)));
1904 }
1905
1906 /* TODO */
1907 /* This should be done in a nicer way now (using radar.c maybe) */
1908 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1909
1910 if (hudRadarEnemyColorRGBA
1911 || hudRadarOtherColorRGBA
1912 || hudRadarObjectColorRGBA) {
1913 hudRadarMapScale = (double) Setup->width / (double) 256;
1914 Paint_hudradar(
1915 hudRadarScale,
1916 (int)(hudRadarLimit * (ext_view_width / 2)
1917 * hudRadarScale / hudRadarMapScale),
1918 (int)(hudRadarLimit * (ext_view_height / 2)
1919 * hudRadarScale / hudRadarMapScale),
1920 hudRadarDotSize);
1921
1922 Paint_hudradar(hudRadarMapScale*clData.scale,
1923 (active_view_width / 2)*clData.scale,
1924 (active_view_height / 2)*clData.scale,
1925 SHIP_SZ);
1926 }
1927
1928
1929 glDisable(GL_BLEND);
1930 /* message scan hack by mara and jpv */
1931 if (Bms_test_state(BmsBall) && msgScanBallColorRGBA)
1932 Circle(msgScanBallColorRGBA, draw_width / 2,
1933 draw_height / 2, (int)(8*clData.scale),0);
1934 if (Bms_test_state(BmsCover) && msgScanCoverColorRGBA)
1935 Circle(msgScanCoverColorRGBA, draw_width / 2,
1936 draw_height / 2, (int)(6*clData.scale),0);
1937
1938 glEnable(GL_BLEND);
1939
1940 /*
1941 * Display the HUD
1942 */
1943 hud_pos_x = (int)(draw_width / 2 - hud_move_fact * selfVel.x);
1944 hud_pos_y = (int)(draw_height / 2 + hud_move_fact * selfVel.y);
1945
1946 glBlendFunc(GL_SRC_ALPHA, GL_ONE);
1947 /* HUD frame */
1948 glLineStipple(4, 0xAAAA);
1949 glEnable(GL_LINE_STIPPLE);
1950 if (hudHLineColorRGBA) {
1951 set_alphacolor(hudHLineColorRGBA);
1952 glBegin(GL_LINES);
1953 glVertex2i(hud_pos_x - hudSize,hud_pos_y - hudSize + HUD_OFFSET);
1954 glVertex2i(hud_pos_x + hudSize,hud_pos_y - hudSize + HUD_OFFSET);
1955
1956 glVertex2i(hud_pos_x - hudSize,hud_pos_y + hudSize - HUD_OFFSET);
1957 glVertex2i(hud_pos_x + hudSize,hud_pos_y + hudSize - HUD_OFFSET);
1958 glEnd();
1959 }
1960 if (hudVLineColorRGBA) {
1961 set_alphacolor(hudVLineColorRGBA);
1962 glBegin(GL_LINES);
1963 glVertex2i(hud_pos_x - hudSize + HUD_OFFSET,hud_pos_y - hudSize);
1964 glVertex2i(hud_pos_x - hudSize + HUD_OFFSET,hud_pos_y + hudSize);
1965
1966 glVertex2i(hud_pos_x + hudSize - HUD_OFFSET,hud_pos_y - hudSize);
1967 glVertex2i(hud_pos_x + hudSize - HUD_OFFSET,hud_pos_y + hudSize);
1968 glEnd();
1969 }
1970 glDisable(GL_LINE_STIPPLE);
1971
1972 if (hudItemsColorRGBA)
1973 Paint_HUD_items(hud_pos_x, hud_pos_y);
1974
1975 /* Fuel notify, HUD meter on */
1976 if (hudColorRGBA && (fuelTime > 0.0 || fuelSum < fuelNotify)) {
1977 did_fuel = 1;
1978 /* TODO fix this */
1979 sprintf(str, "%04d", (int)fuelSum);
1980 tex_index=0;
1981 if (strcmp(str,hud_texts[tex_index])!=0) {
1982 if (HUD_texs[tex_index].tex_list)
1983 free_string_texture(&HUD_texs[tex_index]);
1984 strlcpy(hud_texts[tex_index],str,50);
1985 }
1986 if (!HUD_texs[tex_index].tex_list)
1987 render_text(&gamefont, str, &HUD_texs[tex_index]);
1988 disp_text( &HUD_texs[tex_index],hudColorRGBA,LEFT,DOWN
1989 ,hud_pos_x + hudSize-HUD_OFFSET+BORDER
1990 ,hud_pos_y - (hudSize-HUD_OFFSET+BORDER)
1991 ,true );
1992
1993 if (numItems[ITEM_TANK]) {
1994 if (fuelCurrent == 0)
1995 strcpy(str,"M ");
1996 else
1997 sprintf(str, "T%d", fuelCurrent);
1998
1999 tex_index=1;
2000 if (strcmp(str,hud_texts[tex_index])!=0) {
2001 if (HUD_texs[tex_index].tex_list)
2002 free_string_texture(&HUD_texs[tex_index]);
2003 strlcpy(hud_texts[tex_index],str,50);
2004 }
2005 if (!HUD_texs[tex_index].tex_list)
2006 render_text(&gamefont, str, &HUD_texs[tex_index]);
2007 disp_text( &HUD_texs[tex_index],hudColorRGBA,LEFT,DOWN
2008 ,hud_pos_x + hudSize-HUD_OFFSET + BORDER
2009 ,hud_pos_y - hudSize-HUD_OFFSET + BORDER
2010 ,true );
2011
2012 }
2013 }
2014
2015 /* Update the lock display */
2016 Paint_lock(hud_pos_x, hud_pos_y);
2017
2018 /* Draw last score on hud if it is an message attached to it */
2019 if (hudColorRGBA) {
2020 for (i = 0, j = 0; i < MAX_SCORE_OBJECTS; i++) {
2021 score_object_t* sobj = &score_objects[(i+score_object)%MAX_SCORE_OBJECTS];
2022 if (sobj->hud_msg_len > 0) {
2023 dummy = printsize(&gamefont,"%s",sobj->hud_msg);
2024 if (sobj->hud_msg_width == -1)
2025 sobj->hud_msg_width = (int)dummy.width;
2026 if (j == 0 &&
2027 sobj->hud_msg_width > 2*hudSize-HUD_OFFSET*2 &&
2028 (did_fuel || hudVLineColorRGBA))
2029 ++j;
2030
2031 tex_index=MAX_HUD_TEXS+i;
2032 if (strcmp(sobj->hud_msg,hud_texts[tex_index])!=0) {
2033 if (HUD_texs[tex_index].tex_list)
2034 free_string_texture(&HUD_texs[tex_index]);
2035 strlcpy(hud_texts[tex_index],sobj->hud_msg,50);
2036 }
2037 if (!HUD_texs[tex_index].tex_list)
2038 render_text(&gamefont, sobj->hud_msg, &HUD_texs[tex_index]);
2039
2040 disp_text( &HUD_texs[tex_index],hudColorRGBA,CENTER,DOWN
2041 ,hud_pos_x
2042 ,hud_pos_y - (hudSize-HUD_OFFSET + BORDER + j * HUD_texs[tex_index].height)
2043 ,true );
2044 j++;
2045 }
2046 }
2047
2048 if (time_left > 0) {
2049 sprintf(str, "%3d:%02d", (int)(time_left / 60), (int)(time_left % 60));
2050 tex_index=3;
2051 if (strcmp(str,hud_texts[tex_index])!=0) {
2052 if (HUD_texs[tex_index].tex_list)
2053 free_string_texture(&HUD_texs[tex_index]);
2054 strlcpy(hud_texts[tex_index],str,50);
2055 }
2056 if (!HUD_texs[tex_index].tex_list)
2057 render_text(&gamefont, str, &HUD_texs[tex_index]);
2058 disp_text( &HUD_texs[tex_index],hudColorRGBA,RIGHT,DOWN
2059 ,hud_pos_x - hudSize+HUD_OFFSET - BORDER
2060 ,hud_pos_y + hudSize+HUD_OFFSET + BORDER
2061 ,true );
2062 }
2063
2064 /* Update the modifiers */
2065 modlen = strlen(mods);
2066 tex_index=4;
2067 if (strcmp(mods,hud_texts[tex_index])!=0) {
2068 if (HUD_texs[tex_index].tex_list)
2069 free_string_texture(&HUD_texs[tex_index]);
2070 strlcpy(hud_texts[tex_index],mods,50);
2071 }
2072 if(strlen(mods)) {
2073 if (!HUD_texs[tex_index].tex_list)
2074 render_text(&gamefont, mods, &HUD_texs[tex_index]);
2075 disp_text( &HUD_texs[tex_index],hudColorRGBA,RIGHT,UP
2076 ,hud_pos_x - hudSize+HUD_OFFSET-BORDER
2077 ,hud_pos_y - hudSize+HUD_OFFSET-BORDER
2078 ,true );
2079 }
2080
2081 if (autopilotLight) {
2082 tex_index=5;
2083 if (strcmp(autopilot,hud_texts[tex_index])!=0) {
2084 if (HUD_texs[tex_index].tex_list)
2085 free_string_texture(&HUD_texs[tex_index]);
2086 strlcpy(hud_texts[tex_index],autopilot,50);
2087 }
2088 if (!HUD_texs[tex_index].tex_list)
2089 render_text(&gamefont, autopilot, &HUD_texs[tex_index]);
2090 disp_text( &HUD_texs[tex_index],hudColorRGBA,RIGHT,DOWN
2091 ,hud_pos_x
2092 ,hud_pos_y + hudSize+HUD_OFFSET + BORDER + HUD_texs[tex_index].height*2
2093 ,true );
2094 }
2095 }
2096
2097 if (fuelTime > 0.0) {
2098 fuelTime -= timePerFrame;
2099 if (fuelTime <= 0.0)
2100 fuelTime = 0.0;
2101 }
2102
2103 /* draw fuel gauge */
2104 if (fuelGaugeColorRGBA &&
2105 ((fuelTime > 0.0)
2106 || (fuelSum < fuelNotify
2107 && ((fuelSum < fuelCritical && (loopsSlow % 4) < 2)
2108 || (fuelSum < fuelWarning
2109 && fuelSum > fuelCritical
2110 && (loopsSlow % 8) < 4)
2111 || (fuelSum > fuelWarning))))) {
2112
2113 set_alphacolor(fuelGaugeColorRGBA);
2114 tempx = hud_pos_x + hudSize - HUD_OFFSET + FUEL_GAUGE_OFFSET - 1;
2115 tempy = hud_pos_y - hudSize + HUD_OFFSET + FUEL_GAUGE_OFFSET - 1;
2116 tempw = HUD_OFFSET - (2*FUEL_GAUGE_OFFSET) + 3;
2117 temph = HUD_FUEL_GAUGE_SIZE + 3;
2118 glBegin(GL_LINE_LOOP);
2119 glVertex2i(tempx,tempy);
2120 glVertex2i(tempx,tempy+temph);
2121 glVertex2i(tempx+tempw,tempy+temph);
2122 glVertex2i(tempx+tempw,tempy);
2123 glEnd();
2124
2125 size = (int)((HUD_FUEL_GAUGE_SIZE * fuelSum) / fuelMax);
2126 tempx = hud_pos_x + hudSize - HUD_OFFSET + FUEL_GAUGE_OFFSET + 1;
2127 tempy = hud_pos_y - hudSize + HUD_OFFSET + FUEL_GAUGE_OFFSET + HUD_FUEL_GAUGE_SIZE - size + 1;
2128 tempw = HUD_OFFSET - (2*FUEL_GAUGE_OFFSET);
2129 temph = size;
2130 glBegin(GL_POLYGON);
2131 glVertex2i(tempx,tempy);
2132 glVertex2i(tempx,tempy+temph);
2133 glVertex2i(tempx+tempw,tempy+temph);
2134 glVertex2i(tempx+tempw,tempy);
2135 glEnd();
2136 }
2137 glDisable(GL_BLEND);
2138 }
2139
2140 typedef struct alert_timeout_struct alert_timeout;
2141 struct alert_timeout_struct {
2142 GLWidget *msg; /* use to build widget lists */
2143 double timeout;
2144 alert_timeout *next;
2145 };
2146 static alert_timeout *alert_timeout_list = NULL;
2147
Add_alert_message(const char * message,double timeout)2148 void Add_alert_message(const char *message, double timeout)
2149 {
2150 GLWidget *tmp = NULL;
2151 alert_timeout *tol;
2152
2153 tmp = Init_LabelWidget(message,&whiteRGBA,&nullRGBA,CENTER,CENTER);
2154 if (tmp) {
2155 ListWidget_Prepend(((WrapperWidget *)(MainWidget->wid_info))->alert_msgs,tmp);
2156 } else {
2157 error("Add_alert_message: Failed to create LabelWidget");
2158 return;
2159 }
2160
2161 tol = alert_timeout_list;
2162 alert_timeout_list = (alert_timeout *)malloc(sizeof(alert_timeout));
2163 alert_timeout_list->next = tol;
2164 alert_timeout_list->timeout = timeout;
2165 alert_timeout_list->msg = tmp;
2166 }
2167
Clear_alert_messages(void)2168 void Clear_alert_messages(void)
2169 {
2170 GLWidget *tmp,*list;
2171 bool dummy;
2172 alert_timeout *tol;
2173
2174 while ((tol = alert_timeout_list)) {
2175 alert_timeout_list = alert_timeout_list->next;
2176 free(tol);
2177 }
2178
2179 list = ((WrapperWidget *)(MainWidget->wid_info))->alert_msgs;
2180 dummy = true;
2181 while (dummy) {
2182 tmp = ListWidget_GetItemByIndex( list, 0 );
2183 if (tmp == NULL) break;
2184 dummy = ListWidget_Remove( list, tmp );
2185 }
2186 }
2187
Paint_messages(void)2188 void Paint_messages(void)
2189 {
2190 static int old_maxMessages = 0;
2191 static message_t **msgs[2];
2192 static GLWidget *msg_list[2] = {NULL,NULL};
2193 static bool showMessages = true;
2194
2195 int j, i = 0;
2196 Uint32 *msg_color;
2197 /*const int BORDER = 10;*/
2198 GLWidget *tmp = NULL,*tmp2 = NULL;
2199 LabelWidget *wi;
2200 message_t *msg;
2201
2202 alert_timeout *garbage, **tol = &alert_timeout_list;
2203 static int lastloops;
2204
2205 msgs[0] = TalkMsg;
2206 msgs[1] = GameMsg;
2207
2208 msg_list[0] = ((WrapperWidget *)(MainWidget->wid_info))->chat_msgs;
2209 msg_list[1] = ((WrapperWidget *)(MainWidget->wid_info))->game_msgs;
2210
2211 if ( showMessages != instruments.showMessages ) {
2212 if (!instruments.showMessages)
2213 DelGLWidgetListItem( &(MainWidget->children), ((WrapperWidget *)(MainWidget->wid_info))->game_msgs );
2214 else
2215 AppendGLWidgetList( &(MainWidget->children), ((WrapperWidget *)(MainWidget->wid_info))->game_msgs );
2216
2217 showMessages = instruments.showMessages;
2218 }
2219
2220 if ( maxMessages < old_maxMessages ) {
2221 for (i=0;i<2;++i)
2222 while ((tmp = ListWidget_GetItemByIndex(msg_list[i],maxMessages)) != NULL) {
2223 ListWidget_Remove(msg_list[i],tmp);
2224 Close_Widget(&tmp);
2225 }
2226 }
2227
2228 /* Check if any alert message has timed out, if so remove it */
2229 while ((*tol)) {
2230 if ((*tol)->timeout != 0.0) {
2231 (*tol)->timeout -= (loops - lastloops)/(double)FPS;
2232 if ((*tol)->timeout <= 0.0) {
2233 garbage = (*tol);
2234 *tol = (*tol)->next;
2235 ListWidget_Remove( ((WrapperWidget *)(MainWidget->wid_info))->alert_msgs, garbage->msg );
2236 free(garbage);
2237 continue;
2238 }
2239 }
2240 tol = &((*tol)->next);
2241 }
2242 lastloops = loops;
2243
2244 /* TODO: check whether there is a more efficient way to do this!
2245 * i.e. add labelwidgets as messages are added/removed
2246 * For now this will have to do...
2247 */
2248 for ( i=0 ; i < 2 ; ++i)
2249 for ( j=0 ; j <= maxMessages-1 ; ++j) {
2250 msg = (msgs[i])[j];
2251 tmp = tmp2 = NULL;
2252
2253 if ((msg->lifeTime -= timePerFrame) <= 0.0) {
2254 msg->txt[0] = '\0';
2255 msg->len = 0;
2256 msg->lifeTime = 0.0;
2257 }
2258
2259 if ((tmp = ListWidget_GetItemByIndex(msg_list[i],j) ) != NULL) {
2260 if ( !(wi = (LabelWidget *)tmp->wid_info) ) {
2261 error("Paint_messages: ListWidget lacks a wid_info ptr!");
2262 continue;
2263 }
2264 if (strlen(msg->txt)) {
2265 if ( strcmp(msg->txt, wi->tex.text) ) {
2266 tmp2 = Init_LabelWidget(msg->txt,&messagesColorRGBA,&nullRGBA,LEFT,CENTER);
2267 ListWidget_Insert(msg_list[i],tmp,tmp2);
2268 if (ListWidget_NELEM(msg_list[i])>maxMessages) {
2269 tmp = ListWidget_GetItemByIndex(msg_list[i],maxMessages);
2270 ListWidget_Remove(msg_list[i],tmp);
2271 Close_Widget(&tmp);
2272 }
2273 } else tmp2 = tmp;
2274 } else {
2275 ListWidget_Remove(msg_list[i],tmp);
2276 Close_Widget(&tmp);
2277 }
2278 } else {
2279 if (strlen(msg->txt)) {
2280 tmp2 = Init_LabelWidget(msg->txt,&messagesColorRGBA,&nullRGBA,LEFT,CENTER);
2281 ListWidget_Append(msg_list[i],tmp2);
2282 }
2283 }
2284
2285 if (msg->lifeTime <= MSG_FLASH_TIME)
2286 msg_color = &oldmessagesColorRGBA;
2287 else {
2288 /* If paused, don't bother to paint messages in mscScan* colors. */
2289 if (self && strchr("P", self->mychar))
2290 msg_color = &messagesColorRGBA;
2291 else {
2292 switch (msg->bmsinfo) {
2293 case BmsBall: msg_color = &msgScanBallColorRGBA; break;
2294 case BmsSafe: msg_color = &msgScanSafeColorRGBA; break;
2295 case BmsCover: msg_color = &msgScanCoverColorRGBA; break;
2296 case BmsPop: msg_color = &msgScanPopColorRGBA; break;
2297 default: msg_color = &messagesColorRGBA; break;
2298 }
2299 }
2300 }
2301
2302 /* kps ugly hack */
2303 if (newbie && msg->txt) {
2304 const char *help = "[*Newbie help*]";
2305 size_t sz = strlen(msg->txt);
2306 size_t hsz = strlen(help);
2307
2308 if (sz > hsz
2309 && !strcmp(help, &msg->txt[sz - hsz]))
2310 msg_color = &whiteRGBA;
2311 }
2312
2313
2314 if (tmp2) LabelWidget_SetColor(tmp2, msg_color, &nullRGBA);
2315 }
2316
2317 old_maxMessages = maxMessages;
2318 }
2319
set_rgba_color_option(xp_option_t * opt,const char * val)2320 static bool set_rgba_color_option(xp_option_t *opt, const char *val)
2321 {
2322 int c = 0;
2323 assert(val);
2324 if (*val != '#') return false;
2325 c = strtoul(val + 1, NULL, 16) & 0xffffffff;
2326 *((int*)Option_get_private_data(opt)) = c;
2327 return true;
2328 }
2329
get_rgba_color_option(xp_option_t * opt)2330 static const char *get_rgba_color_option(xp_option_t *opt)
2331 {
2332 static char buf[10];
2333 sprintf(buf, "#%08X", *((int*)Option_get_private_data(opt)));
2334 return buf;
2335 }
2336
2337 #define COLOR(variable, defval, description) \
2338 XP_STRING_OPTION(#variable, \
2339 defval, \
2340 NULL, \
2341 0, \
2342 set_rgba_color_option, \
2343 &variable, \
2344 get_rgba_color_option, \
2345 XP_OPTFLAG_CONFIG_COLORS, \
2346 "The color of " description ".\n")
2347
2348
2349 static xp_option_t sdlgui_options[] = {
2350
2351 COLOR(messagesColorRGBA, "#00aaaaff", "messages"),
2352 COLOR(oldmessagesColorRGBA, "#008888ff", "old messages"),
2353 COLOR(msgScanBallColorRGBA, "#ff0000ff", "ball warning"),
2354 COLOR(msgScanSafeColorRGBA, "#00ff00ff", "ball safe announcement"),
2355 COLOR(msgScanCoverColorRGBA, "#4e7cffff", "cover request"),
2356 COLOR(msgScanPopColorRGBA, "#ffbb11ff", "ball pop announcement"),
2357
2358 COLOR(meterBorderColorRGBA, "#0000ffaa", "meter borders"),
2359 COLOR(fuelMeterColorRGBA, "#ff0000aa", "fuel meter"),
2360 COLOR(fuelGaugeColorRGBA, "#0000ff44", "fuel gauge"),
2361 COLOR(powerMeterColorRGBA, "#ff0000aa", "power meter"),
2362 COLOR(turnSpeedMeterColorRGBA, "#ff0000aa", "turn speed meter"),
2363 COLOR(packetSizeMeterColorRGBA, "#ff0000aa", "packet size meter"),
2364 COLOR(packetLossMeterColorRGBA, "#ff0000aa", "packet loss meter"),
2365 COLOR(packetDropMeterColorRGBA, "#ff0000aa", "drop meter"),
2366 COLOR(packetLagMeterColorRGBA, "#ff0000aa", "lag meter"),
2367 COLOR(temporaryMeterColorRGBA, "#ff0000aa", "time meter"),
2368
2369 COLOR(ballColorRGBA, "#00ff00ff", "balls"),
2370 COLOR(connColorRGBA, "#00ff0088", "the ball connector"),
2371 COLOR(fuelColorRGBA, "#ffffff7f", "fuel cells"),
2372 COLOR(wallColorRGBA, "#0000ffff", "walls on blockmaps"),
2373 COLOR(decorColorRGBA, "#bb7700ff", "decorations on blockmaps"),
2374 COLOR(baseNameColorRGBA, "#77bbffff", "base name"),
2375 COLOR(shipNameColorRGBA, "#77bbffff", "ship name"),
2376 COLOR(scoreObjectColorRGBA, "#00ff0088", "score objects"),
2377
2378 COLOR(hudColorRGBA, "#ff000088", "the HUD"),
2379 COLOR(hudHLineColorRGBA, "#0000ff44", "horizontal HUD line"),
2380 COLOR(hudVLineColorRGBA, "#0000ff44", "vertical HUD line"),
2381 COLOR(hudItemsColorRGBA, "#0080ffaa", "hud items"),
2382 COLOR(hudRadarEnemyColorRGBA, "#ff000088", "enemy on HUD radar"),
2383 COLOR(hudRadarOtherColorRGBA, "#0000ff88", "friend on HUD radar"),
2384 COLOR(hudRadarObjectColorRGBA, "#00000000", "small object on HUD radar"),
2385
2386 COLOR(dirPtrColorRGBA, "#0000ff22", "direction pointer"),
2387 COLOR(selectionColorRGBA, "#ff0000ff", "selection"),
2388
2389 COLOR(scoreInactiveSelfColorRGBA, "#88008888", "my score when inactive"),
2390 COLOR(scoreInactiveColorRGBA, "#8800aa88", "score when inactive"),
2391 COLOR(scoreSelfColorRGBA, "#ffff00ff", "my score"),
2392 COLOR(scoreColorRGBA, "#888800ff", "score"),
2393 COLOR(scoreOwnTeamColorRGBA, "#0000ffff", "my team score"),
2394 COLOR(scoreEnemyTeamColorRGBA, "#ff0000ff", "enemy team score"),
2395
2396 COLOR(teamShipColorRGBA, "#0000ffff", "teammate color"),
2397 COLOR(team0ColorRGBA, "#00000000", "team 0"),
2398 COLOR(team1ColorRGBA, "#00000000", "team 1"),
2399 COLOR(team2ColorRGBA, "#00000000", "team 2"),
2400 COLOR(team3ColorRGBA, "#00000000", "team 3"),
2401 COLOR(team4ColorRGBA, "#00000000", "team 4"),
2402 COLOR(team5ColorRGBA, "#00000000", "team 5"),
2403 COLOR(team6ColorRGBA, "#00000000", "team 6"),
2404 COLOR(team7ColorRGBA, "#00000000", "team 7"),
2405 COLOR(team8ColorRGBA, "#00000000", "team 8"),
2406 COLOR(team9ColorRGBA, "#00000000", "team 9"),
2407
2408 COLOR(selfLWColorRGBA, "#ff0000ff", "my ship on last life"),
2409 COLOR(teamLWColorRGBA, "#ff00ffff", "team ship on last life"),
2410 COLOR(enemyLWColorRGBA, "#ffff00ff", "enemy ship on last life"),
2411 COLOR(manyLivesColorRGBA, "#666666aa", "name of ship with many lives"),
2412 COLOR(twoLivesColorRGBA, "#008800aa", "name of ship with two lives"),
2413 COLOR(oneLifeColorRGBA, "#aaaa00aa", "name of ship with one life"),
2414 COLOR(zeroLivesColorRGBA, "#ff0000aa", "name of ship with no lives"),
2415
2416 XP_INT_OPTION(
2417 "meterWidth",
2418 60, 0, 600,
2419 &meterWidth,
2420 NULL,
2421 XP_OPTFLAG_CONFIG_DEFAULT,
2422 "Set the width of the meters.\n"),
2423
2424 XP_INT_OPTION(
2425 "meterHeight",
2426 10, 0, 100,
2427 &meterHeight,
2428 NULL,
2429 XP_OPTFLAG_CONFIG_DEFAULT,
2430 "Set the height of a meter.\n"),
2431
2432 XP_DOUBLE_OPTION(
2433 "shipLineWidth",
2434 1.0, 1.0, 10.0,
2435 &shipLineWidth,
2436 NULL,
2437 XP_OPTFLAG_CONFIG_DEFAULT,
2438 "Set the line width of ships.\n"),
2439
2440 XP_BOOL_OPTION(
2441 "smoothLines",
2442 true,
2443 &smoothLines,
2444 NULL,
2445 XP_OPTFLAG_CONFIG_DEFAULT,
2446 "Use antialized smooth lines.\n"),
2447
2448 XP_BOOL_OPTION(
2449 "texturedBalls",
2450 true,
2451 &texturedBalls,
2452 NULL,
2453 XP_OPTFLAG_CONFIG_DEFAULT,
2454 "Draw balls with textures.\n"),
2455
2456 XP_BOOL_OPTION(
2457 "texturedShips",
2458 true,
2459 &texturedShips,
2460 NULL,
2461 XP_OPTFLAG_CONFIG_DEFAULT,
2462 "Draw ships with textures.\n"),
2463
2464 XP_INT_OPTION(
2465 "hudRadarEnemyShape",
2466 2, 1, 7,
2467 &hudRadarEnemyShape,
2468 NULL,
2469 XP_OPTFLAG_CONFIG_DEFAULT,
2470 "The shape of enemy ships on hud radar.\n"),
2471
2472 XP_INT_OPTION(
2473 "hudRadarOtherShape",
2474 2, 1, 7,
2475 &hudRadarOtherShape,
2476 NULL,
2477 XP_OPTFLAG_CONFIG_DEFAULT,
2478 "The shape of friendly ships on hud radar.\n"),
2479
2480 XP_INT_OPTION(
2481 "hudRadarObjectShape",
2482 0, 0, 7,
2483 &hudRadarObjectShape,
2484 NULL,
2485 XP_OPTFLAG_CONFIG_DEFAULT,
2486 "The shape of small objects on hud radar.\n")
2487 };
2488
Store_sdlgui_options(void)2489 void Store_sdlgui_options(void)
2490 {
2491 STORE_OPTIONS(sdlgui_options);
2492 }
2493