1 /* $Id: guimap.c,v 5.7 2002/02/10 19:29:39 bertg Exp $
2 *
3 * XPilot, a multiplayer gravity war game. Copyright (C) 1991-2001 by
4 *
5 * Bj�rn Stabell <bjoern@xpilot.org>
6 * Ken Ronny Schouten <ken@xpilot.org>
7 * Bert Gijsbers <bert@xpilot.org>
8 * Dick Balaska <dick@xpilot.org>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 */
24
25 #include <stdlib.h>
26 #include <string.h>
27 #include <stdio.h>
28 #include <errno.h>
29 #include <sys/types.h>
30
31 #ifndef _WINDOWS
32 # include <unistd.h>
33 # include <X11/Xlib.h>
34 # include <X11/Xos.h>
35 #endif
36
37 #ifdef _WINDOWS
38 # include "NT/winX.h"
39 # include "NT/winBitmap.h"
40 #endif
41
42 #include "gfx2d.h"
43 #include "version.h"
44 #include "config.h"
45 #include "const.h"
46 #include "error.h"
47 #include "bit.h"
48 #include "types.h"
49 #include "keys.h"
50 #include "rules.h"
51 #include "setup.h"
52 #include "texture.h"
53 #include "paint.h"
54 #include "paintdata.h"
55 #include "paintmacros.h"
56 #include "record.h"
57 #include "xinit.h"
58 #include "protoclient.h"
59 #include "blockbitmaps.h"
60 #include "guimap.h"
61
62
63 char guimap_version[] = VERSION;
64
65
66 /* XXX better include a header. */
67 extern int wallColor; /* Color index for wall drawing */
68 extern int decorColor; /* Color index for decoration drawing */
69 extern char *wallTextureFile; /* Filename of wall texture */
70 extern char *decorTextureFile; /* Filename of decor texture */
71
72
73 extern setup_t *Setup;
74
75
Gui_paint_walls(int x,int y,int type,int xi,int yi)76 void Gui_paint_walls(int x, int y, int type, int xi, int yi)
77 {
78 if (!blockBitmaps) {
79 if (type & BLUE_LEFT) {
80 Segment_add(wallColor,
81 X(x),
82 Y(y),
83 X(x),
84 Y(y+BLOCK_SZ));
85 }
86 if (type & BLUE_DOWN) {
87 Segment_add(wallColor,
88 X(x),
89 Y(y),
90 X(x+BLOCK_SZ),
91 Y(y));
92 }
93 if (type & BLUE_RIGHT) {
94 Segment_add(wallColor,
95 X(x+BLOCK_SZ),
96 Y(y),
97 X(x+BLOCK_SZ),
98 Y(y+BLOCK_SZ));
99 }
100 if (type & BLUE_UP) {
101 Segment_add(wallColor,
102 X(x),
103 Y(y+BLOCK_SZ),
104 X(x+BLOCK_SZ),
105 Y(y+BLOCK_SZ));
106 }
107
108 if ((type & BLUE_FUEL) == BLUE_FUEL) {
109 }
110 else if (type & BLUE_OPEN) {
111 Segment_add(wallColor,
112 X(x),
113 Y(y),
114 X(x+BLOCK_SZ),
115 Y(y+BLOCK_SZ));
116 }
117 else if (type & BLUE_CLOSED) {
118 Segment_add(wallColor,
119 X(x),
120 Y(y+BLOCK_SZ),
121 X(x+BLOCK_SZ),
122 Y(y));
123 }
124 }
125 else {
126
127 if (type & BLUE_LEFT) {
128 PaintBitmap(p_draw, BM_WALL_LEFT, WINSCALE(X(x - 1)),
129 WINSCALE(Y(y + BLOCK_SZ)), WINSCALE(BLOCK_SZ),
130 WINSCALE(BLOCK_SZ), 0);
131 }
132 if (type & BLUE_DOWN) {
133 PaintBitmap(p_draw, BM_WALL_BOTTOM, WINSCALE(X(x)),
134 WINSCALE(Y(y + BLOCK_SZ - 1)), WINSCALE(BLOCK_SZ),
135 WINSCALE(BLOCK_SZ), 0);
136 }
137 if (type & BLUE_RIGHT) {
138 PaintBitmap(p_draw, BM_WALL_RIGHT, WINSCALE(X(x + 1)),
139 WINSCALE(Y(y + BLOCK_SZ)), WINSCALE(BLOCK_SZ),
140 WINSCALE(BLOCK_SZ), 0);
141 }
142 if (type & BLUE_UP) {
143 PaintBitmap(p_draw, BM_WALL_TOP, WINSCALE(X(x)),
144 WINSCALE(Y(y + BLOCK_SZ + 1)), WINSCALE(BLOCK_SZ),
145 WINSCALE(BLOCK_SZ), 0);
146 }
147 if ((type & BLUE_FUEL) == BLUE_FUEL) {
148 }
149
150 else if (type & BLUE_OPEN) {
151 PaintBitmap(p_draw, BM_WALL_UR, WINSCALE(X(x)),
152 WINSCALE(Y(y + BLOCK_SZ)), WINSCALE(BLOCK_SZ),
153 WINSCALE(BLOCK_SZ), 0);
154 }
155 else if (type & BLUE_CLOSED) {
156 PaintBitmap(p_draw, BM_WALL_UL, WINSCALE(X(x)),
157 WINSCALE(Y(y + BLOCK_SZ)), WINSCALE(BLOCK_SZ),
158 WINSCALE(BLOCK_SZ), 0);
159 }
160 }
161 }
162
163
Gui_paint_cannon(int x,int y,int type)164 void Gui_paint_cannon(int x, int y, int type)
165 {
166 if (!blockBitmaps) {
167 XPoint points[5];
168
169 SET_FG(colors[WHITE].pixel);
170 switch (type) {
171 case SETUP_CANNON_UP:
172 points[0].x = WINSCALE(X(x));
173 points[0].y = WINSCALE(Y(y));
174 points[1].x = WINSCALE(X(x+BLOCK_SZ));
175 points[1].y = WINSCALE(Y(y));
176 points[2].x = WINSCALE(X(x+BLOCK_SZ/2));
177 points[2].y = WINSCALE(Y(y+BLOCK_SZ/3));
178 break;
179 case SETUP_CANNON_DOWN:
180 points[0].x = WINSCALE(X(x));
181 points[0].y = WINSCALE(Y(y+BLOCK_SZ));
182 points[1].x = WINSCALE(X(x+BLOCK_SZ));
183 points[1].y = WINSCALE(Y(y+BLOCK_SZ));
184 points[2].x = WINSCALE(X(x+BLOCK_SZ/2));
185 points[2].y = WINSCALE(Y(y+2*BLOCK_SZ/3));
186 break;
187 case SETUP_CANNON_RIGHT:
188 points[0].x = WINSCALE(X(x));
189 points[0].y = WINSCALE(Y(y));
190 points[1].x = WINSCALE(X(x));
191 points[1].y = WINSCALE(Y(y+BLOCK_SZ));
192 points[2].x = WINSCALE(X(x+BLOCK_SZ/3));
193 points[2].y = WINSCALE(Y(y+BLOCK_SZ/2));
194 break;
195 case SETUP_CANNON_LEFT:
196 points[0].x = WINSCALE(X(x+BLOCK_SZ));
197 points[0].y = WINSCALE(Y(y));
198 points[1].x = WINSCALE(X(x+BLOCK_SZ));
199 points[1].y = WINSCALE(Y(y+BLOCK_SZ));
200 points[2].x = WINSCALE(X(x+2*BLOCK_SZ/3));
201 points[2].y = WINSCALE(Y(y+BLOCK_SZ/2));
202 break;
203 default:
204 errno = 0;
205 error("Unknown cannon type %d", type);
206 return;
207 }
208 points[3] = points[0];
209 rd.drawLines(dpy, p_draw, gc, points, 4, 0);
210 Erase_points(0, points, 4);
211 }
212 else {
213 switch (type) {
214 case SETUP_CANNON_UP:
215 PaintBitmap(p_draw, BM_CANNON_DOWN, WINSCALE(X(x)),
216 WINSCALE(Y(y + BLOCK_SZ)), WINSCALE(BLOCK_SZ),
217 WINSCALE(BLOCK_SZ), 0);
218 break;
219 case SETUP_CANNON_DOWN:
220 PaintBitmap(p_draw, BM_CANNON_UP, WINSCALE(X(x)),
221 WINSCALE(Y(y + BLOCK_SZ - 1)), WINSCALE(BLOCK_SZ),
222 WINSCALE(BLOCK_SZ), 0);
223 break;
224 case SETUP_CANNON_LEFT:
225 PaintBitmap(p_draw, BM_CANNON_RIGHT, WINSCALE(X(x)),
226 WINSCALE(Y(y + BLOCK_SZ)), WINSCALE(BLOCK_SZ),
227 WINSCALE(BLOCK_SZ), 0);
228 break;
229 case SETUP_CANNON_RIGHT:
230 PaintBitmap(p_draw, BM_CANNON_LEFT, WINSCALE(X(x - 1)),
231 WINSCALE(Y(y + BLOCK_SZ)), WINSCALE(BLOCK_SZ),
232 WINSCALE(BLOCK_SZ), 0);
233 break;
234 default:
235 errno = 0;
236 error("Bad base dir.");
237 return;
238 }
239 }
240 }
241
242
Gui_paint_fuel(int x,int y,int fuel)243 void Gui_paint_fuel(int x, int y, int fuel)
244 {
245 int fuel_images = Block_bitmap_images(BM_FUEL);
246
247 if (!blockBitmaps || !fuel_images) {
248 #define FUEL_BORDER 2
249 int size;
250
251 static char s[2] = "F";
252 static int text_width = 0;
253 static int text_is_bigger;
254
255 #ifndef WINDOWSCALING
256 if (!text_width)
257 #else
258 static DFLOAT lastScaleFactor;
259
260 if (!text_width || lastScaleFactor != scaleFactor)
261 #endif
262 {
263 #ifdef WINDOWSCALING
264
265 lastScaleFactor = scaleFactor;
266 #endif
267 text_width = XTextWidth(gameFont, s, 1);
268 text_is_bigger = text_width+4 > WINSCALE(BLOCK_SZ)+1 ||
269 (gameFont->ascent + gameFont->descent) > WINSCALE(BLOCK_SZ) + 2;
270 }
271 SET_FG(colors[RED].pixel);
272 size = (BLOCK_SZ - 2*FUEL_BORDER) * fuel / MAX_STATION_FUEL;
273 if (useErase) {
274 /* speedup for slow old cheap graphics cards like cg3.
275 or Xterminals with slow connection */
276 rd.drawLine(dpy, p_draw, gc,
277 WINSCALE(X(x + FUEL_BORDER)),
278 WINSCALE(Y(y + FUEL_BORDER + size)),
279 WINSCALE(X(x + FUEL_BORDER + (BLOCK_SZ - 2*FUEL_BORDER))),
280 WINSCALE(Y(y + FUEL_BORDER + size)));
281 } else {
282 rd.fillRectangle(dpy, p_draw, gc,
283 WINSCALE(X(x + FUEL_BORDER)),
284 WINSCALE(Y(y + FUEL_BORDER + size)),
285 WINSCALE(BLOCK_SZ - 2*FUEL_BORDER + 1),
286 WINSCALE(size + 1));
287 }
288 if (!text_is_bigger)
289 Erase_rectangle(WINSCALE(X(x)) - 1,
290 WINSCALE(Y(y + BLOCK_SZ)) - 1,
291 WINSCALE(BLOCK_SZ) + 2,
292 WINSCALE(BLOCK_SZ) + 2);
293
294 /* Draw F in fuel cells */
295 XSetFunction(dpy, gc, GXxor);
296 SET_FG(colors[BLACK].pixel ^ colors[RED].pixel);
297 x = WINSCALE(X(x + BLOCK_SZ/2)) - text_width/2,
298 y = WINSCALE(Y(y + BLOCK_SZ/2)) + gameFont->ascent/2,
299 rd.drawString(dpy, p_draw, gc, x, y, s, 1);
300 XSetFunction(dpy, gc, GXcopy);
301
302 if (text_is_bigger)
303 Erase_rectangle(x - 2, y - gameFont->ascent,
304 text_width + 4, gameFont->ascent + gameFont->descent);
305 }
306 else {
307 #define BITMAP_FUEL_BORDER 3
308
309 int size;
310 /* x + x * y will give a pseudo random number,
311 so different fuelcells will not be displayed with the same image-frame.*/
312 int image = ( (loops + x + x * y) % (fuel_images * 2) );
313
314 /* the animation is played from image 0-15 then back again from image 15-0 */
315
316 if (image >= fuel_images)
317 image = (2 * fuel_images - 1) - image;
318
319
320 size = (BLOCK_SZ - 2 * BITMAP_FUEL_BORDER) * fuel / MAX_STATION_FUEL;
321
322 PaintBitmap(p_draw, BM_FUELCELL, WINSCALE(X(x)), WINSCALE(Y(y + BLOCK_SZ)),
323 WINSCALE(BLOCK_SZ), WINSCALE(BLOCK_SZ), 0);
324
325 PaintFuelSlice(p_draw, BM_FUEL,
326 WINSCALE(X(x + BITMAP_FUEL_BORDER)),
327 WINSCALE(Y(y + size + BITMAP_FUEL_BORDER)),
328 WINSCALE(BLOCK_SZ - 2 * BITMAP_FUEL_BORDER),
329 WINSCALE(BLOCK_SZ - 2 * BITMAP_FUEL_BORDER),
330 image, WINSCALE(size));
331
332 Erase_rectangle(WINSCALE(X(x)) - 1,
333 WINSCALE(Y(y + BLOCK_SZ)) - 1,
334 WINSCALE(BLOCK_SZ) + 2, WINSCALE(BLOCK_SZ) + 2);
335
336 }
337 }
338
339
Gui_paint_base(int x,int y,int xi,int yi,int type)340 void Gui_paint_base(int x, int y, int xi, int yi, int type)
341 {
342 if (!blockBitmaps) {
343 const int BORDER = 4; /* in pixels */
344 int id, team, size;
345 other_t *other;
346 char s[3];
347
348 SET_FG(colors[WHITE].pixel);
349
350 switch (type) {
351 case SETUP_BASE_UP:
352 Segment_add(WHITE,
353 X(x), Y(y-1),
354 X(x+BLOCK_SZ), Y(y-1));
355 break;
356 case SETUP_BASE_DOWN:
357 Segment_add(WHITE,
358 X(x), Y(y+BLOCK_SZ+1),
359 X(x+BLOCK_SZ), Y(y+BLOCK_SZ+1));
360 break;
361 case SETUP_BASE_LEFT:
362 Segment_add(WHITE,
363 X(x+BLOCK_SZ+1), Y(y+BLOCK_SZ),
364 X(x+BLOCK_SZ+1), Y(y));
365 break;
366 case SETUP_BASE_RIGHT:
367 Segment_add(WHITE,
368 X(x-1), Y(y+BLOCK_SZ),
369 X(x-1), Y(y));
370 break;
371 default:
372 errno = 0;
373 error("Bad base dir.");
374 return;
375 }
376 /* only draw base teams if ship naming is on, SKS 25/05/94 */
377 if (!BIT(instruments, SHOW_SHIP_NAME) ||
378 Base_info_by_pos(xi, yi, &id, &team) == -1)
379 return;
380
381 /* operate in pixels from here out */
382 x = WINSCALE(X(x));
383 y = WINSCALE(Y(y));
384
385 if ((other = Other_by_id(id)) != NULL) {
386 if (other->name_width == 0) {
387 other->name_len = strlen(other->name);
388 other->name_width = 2 + XTextWidth(gameFont, other->name,
389 other->name_len);
390 }
391 }
392 if (BIT(Setup->mode, TEAM_PLAY)) {
393 s[0] = '0' + team;
394 if (other) {
395 s[1] = ' ';
396 s[2] = '\0';
397 } else
398 s[1] = '\0';
399 size = XTextWidth(gameFont, s, other ? 2 : 1);
400 } else
401 size = 0;
402
403 switch (type) {
404 case SETUP_BASE_UP:
405 y += BORDER + gameFont->ascent;
406 x += WINSCALE(BLOCK_SZ/2);
407 x -= size / 2 + (other ? other->name_width/2 : 0);
408 break;
409 case SETUP_BASE_DOWN:
410 y -= WINSCALE(BLOCK_SZ) + BORDER + gameFont->descent;
411 x += WINSCALE(BLOCK_SZ/2);
412 x -= size / 2 + (other ? other->name_width/2 : 0);
413 break;
414 case SETUP_BASE_LEFT:
415 x += WINSCALE(BLOCK_SZ) + BORDER;
416 y += -WINSCALE(BLOCK_SZ/2) + gameFont->ascent/2;
417 break;
418 case SETUP_BASE_RIGHT:
419 x -= BORDER + (other ? other->name_width : 0) + size;
420 y += -WINSCALE(BLOCK_SZ/2) + gameFont->ascent/2;
421 break;
422 }
423 if (size) {
424 rd.drawString(dpy, p_draw, gc, x, y, s, other ? 2 : 1);
425 Erase_rectangle(x - 1, y - gameFont->ascent - 1,
426 size + 2,
427 gameFont->ascent + gameFont->descent+2);
428 x += size;
429 }
430 if (other) {
431 rd.drawString(dpy, p_draw, gc, x, y,
432 other->name, other->name_len);
433 Erase_rectangle(x - 1,
434 y - gameFont->ascent - 1,
435 other->name_width + 2,
436 gameFont->ascent+gameFont->descent + 2);
437 }
438 }
439 else {
440 const int BORDER = 4; /* in pixels */
441 int id, team, size;
442 other_t *other;
443 char s[3];
444
445 SET_FG(colors[WHITE].pixel);
446
447 switch (type) {
448 case SETUP_BASE_UP:
449 PaintBitmap(p_draw, BM_BASE_DOWN, WINSCALE(X(x)),
450 WINSCALE(Y(y + BLOCK_SZ)), WINSCALE(BLOCK_SZ),
451 WINSCALE(BLOCK_SZ), 0);
452 break;
453 case SETUP_BASE_DOWN:
454 PaintBitmap(p_draw, BM_BASE_UP, WINSCALE(X(x)),
455 WINSCALE(Y(y + BLOCK_SZ - 1)), WINSCALE(BLOCK_SZ),
456 WINSCALE(BLOCK_SZ), 0);
457 break;
458 case SETUP_BASE_LEFT:
459 PaintBitmap(p_draw, BM_BASE_RIGHT, WINSCALE(X(x)),
460 WINSCALE(Y(y + BLOCK_SZ)), WINSCALE(BLOCK_SZ),
461 WINSCALE(BLOCK_SZ), 0);
462 break;
463 case SETUP_BASE_RIGHT:
464 PaintBitmap(p_draw, BM_BASE_LEFT, WINSCALE(X(x - 1)),
465 WINSCALE(Y(y + BLOCK_SZ)), WINSCALE(BLOCK_SZ),
466 WINSCALE(BLOCK_SZ), 0);
467 break;
468 default:
469 errno = 0;
470 error("Bad base dir.");
471 return;
472 }
473 /* only draw base teams if ship naming is on, SKS 25/05/94 */
474 if (!BIT(instruments, SHOW_SHIP_NAME) ||
475 Base_info_by_pos(xi, yi, &id, &team) == -1)
476 return;
477
478 /* operate in pixels from here out */
479 x = WINSCALE(X(x));
480 y = WINSCALE(Y(y));
481
482 if ((other = Other_by_id(id)) != NULL) {
483 if (other->name_width == 0) {
484 other->name_len = strlen(other->name);
485 other->name_width = 2 + XTextWidth(gameFont, other->name,
486 other->name_len);
487 }
488 }
489 if (BIT(Setup->mode, TEAM_PLAY)) {
490 s[0] = '0' + team;
491 if (other) {
492 s[1] = ' ';
493 s[2] = '\0';
494 }
495 else
496 s[1] = '\0';
497 size = XTextWidth(gameFont, s, other ? 2 : 1);
498 }
499 else
500 size = 0;
501
502 switch (type) {
503 case SETUP_BASE_UP:
504 y += BORDER + gameFont->ascent;
505 x += WINSCALE(BLOCK_SZ / 2);
506 x -= size / 2 + (other ? other->name_width / 2 : 0);
507 break;
508 case SETUP_BASE_DOWN:
509 y -= WINSCALE(BLOCK_SZ) + BORDER + gameFont->descent;
510 x += WINSCALE(BLOCK_SZ / 2);
511 x -= size / 2 + (other ? other->name_width / 2 : 0);
512 break;
513 case SETUP_BASE_LEFT:
514 x += WINSCALE(BLOCK_SZ) + BORDER;
515 y += -WINSCALE(BLOCK_SZ / 2) + gameFont->ascent / 2;
516 break;
517 case SETUP_BASE_RIGHT:
518 x -= BORDER + (other ? other->name_width : 0) + size;
519 y += -WINSCALE(BLOCK_SZ / 2) + gameFont->ascent / 2;
520 break;
521 }
522 if (size) {
523 rd.drawString(dpy, p_draw, gc, x, y, s, other ? 2 : 1);
524 Erase_rectangle(x - 1, y - gameFont->ascent - 1,
525 size + 2, gameFont->ascent + gameFont->descent + 2);
526 x += size;
527 }
528 if (other) {
529 rd.drawString(dpy, p_draw, gc, x, y, other->name, other->name_len);
530 Erase_rectangle(x - 1,
531 y - gameFont->ascent - 1,
532 other->name_width + 2,
533 gameFont->ascent + gameFont->descent + 2);
534 }
535 }
536 }
537
538
Gui_paint_decor(int x,int y,int xi,int yi,int type,bool last,bool more_y)539 void Gui_paint_decor(int x, int y, int xi, int yi, int type, bool last, bool more_y)
540 {
541 XPoint points[5];
542
543 int mask;
544 int fill_top_left = -1,
545 fill_top_right = -1,
546 fill_bottom_left = -1,
547 fill_bottom_right = -1;
548 static int decorTileReady = 0;
549 static Pixmap decorTile = None;
550 int decorTileDoit = false;
551 static unsigned char decor[256];
552 static int decorReady = 0;
553
554 SET_FG(colors[decorColor].pixel);
555
556 if (!decorReady) {
557 memset(decor, 0, sizeof decor);
558 decor[SETUP_DECOR_FILLED] = DECOR_UP | DECOR_LEFT | DECOR_DOWN | DECOR_RIGHT;
559 decor[SETUP_DECOR_RU] = DECOR_UP | DECOR_RIGHT | DECOR_CLOSED;
560 decor[SETUP_DECOR_RD] = DECOR_DOWN | DECOR_RIGHT | DECOR_OPEN | DECOR_BELOW;
561 decor[SETUP_DECOR_LU] = DECOR_UP | DECOR_LEFT | DECOR_OPEN;
562 decor[SETUP_DECOR_LD] = DECOR_LEFT | DECOR_DOWN | DECOR_CLOSED | DECOR_BELOW;
563 }
564
565 if (BIT(instruments, SHOW_TEXTURED_DECOR)) {
566 if (!decorTileReady) {
567 decorTile = Texture_decor();
568 decorTileReady = (decorTile == None) ? -1 : 1;
569 }
570 if (decorTileReady == 1) {
571 decorTileDoit = true;
572 XSetTile(dpy, gc, decorTile);
573 XSetTSOrigin(dpy, gc, -WINSCALE(realWorld.x), WINSCALE(realWorld.y));
574 XSetFillStyle(dpy, gc, FillTiled);
575 }
576 }
577
578 mask = decor[type];
579
580 if (!BIT(instruments, SHOW_FILLED_DECOR|SHOW_TEXTURED_DECOR)) {
581 if (mask & DECOR_LEFT) {
582 if ((xi == 0)
583 ? (!BIT(Setup->mode, WRAP_PLAY) ||
584 !(decor[Setup->map_data[(Setup->x - 1) * Setup->y + yi]]
585 & DECOR_RIGHT))
586 : !(decor[Setup->map_data[(xi - 1) * Setup->y + yi]]
587 & DECOR_RIGHT)) {
588 Segment_add(decorColor,
589 X(x),
590 Y(y),
591 X(x),
592 Y(y+BLOCK_SZ));
593 }
594 }
595 if (mask & DECOR_DOWN) {
596 if ((yi == 0)
597 ? (!BIT(Setup->mode, WRAP_PLAY) ||
598 !(decor[Setup->map_data[xi * Setup->y + Setup->y - 1]]
599 & DECOR_UP))
600 : !(decor[Setup->map_data[xi * Setup->y + (yi - 1)]]
601 & DECOR_UP)) {
602 Segment_add(decorColor,
603 X(x),
604 Y(y),
605 X(x+BLOCK_SZ),
606 Y(y));
607 }
608 }
609 if (mask & DECOR_RIGHT) {
610 if (!BIT(instruments, SHOW_OUTLINE_DECOR)
611 || ((xi == Setup->x - 1)
612 ? (!BIT(Setup->mode, WRAP_PLAY)
613 || !(decor[Setup->map_data[yi]]
614 & DECOR_LEFT))
615 : !(decor[Setup->map_data[(xi + 1) * Setup->y + yi]]
616 & DECOR_LEFT))) {
617 Segment_add(decorColor,
618 X(x+BLOCK_SZ),
619 Y(y),
620 X(x+BLOCK_SZ),
621 Y(y+BLOCK_SZ));
622 }
623 }
624 if (mask & DECOR_UP) {
625 if (!BIT(instruments, SHOW_OUTLINE_DECOR)
626 || ((yi == Setup->y - 1)
627 ? (!BIT(Setup->mode, WRAP_PLAY)
628 || !(decor[Setup->map_data[xi * Setup->y]]
629 & DECOR_DOWN))
630 : !(decor[Setup->map_data[xi * Setup->y + (yi + 1)]]
631 & DECOR_DOWN))) {
632 Segment_add(decorColor,
633 X(x),
634 Y(y+BLOCK_SZ),
635 X(x+BLOCK_SZ),
636 Y(y+BLOCK_SZ));
637 }
638 }
639 if (mask & DECOR_OPEN) {
640 Segment_add(decorColor,
641 X(x),
642 Y(y),
643 X(x+BLOCK_SZ),
644 Y(y+BLOCK_SZ));
645 }
646 else if (mask & DECOR_CLOSED) {
647 Segment_add(decorColor,
648 X(x),
649 Y(y+BLOCK_SZ),
650 X(x+BLOCK_SZ),
651 Y(y));
652 }
653 }
654 else {
655 if (mask & DECOR_OPEN) {
656 if (mask & DECOR_BELOW) {
657 fill_top_left = x + BLOCK_SZ;
658 fill_bottom_left = x;
659 fill_top_right = fill_bottom_right = -1;
660 } else {
661 fill_top_right = x + BLOCK_SZ;
662 fill_bottom_right = x;
663 }
664 }
665 else if (mask & DECOR_CLOSED) {
666 if (!(mask & DECOR_BELOW)) {
667 fill_top_left = x;
668 fill_bottom_left = x + BLOCK_SZ;
669 fill_top_right = fill_bottom_right = -1;
670 } else {
671 fill_top_right = x;
672 fill_bottom_right = x + BLOCK_SZ;
673 }
674 }
675 if (mask & DECOR_RIGHT) {
676 fill_top_right = fill_bottom_right = x + BLOCK_SZ;
677 }
678 if (fill_top_left == -1) {
679 fill_top_left = fill_bottom_left = x;
680 }
681 if (fill_top_right == -1
682 && (last || more_y)) {
683 fill_top_right = x + BLOCK_SZ;
684 fill_bottom_right = x + BLOCK_SZ;
685 }
686 if (fill_top_right != -1) {
687 points[0].x = WINSCALE(X(fill_bottom_left));
688 points[0].y = WINSCALE(Y(y));
689 points[1].x = WINSCALE(X(fill_top_left));
690 points[1].y = WINSCALE(Y(y + BLOCK_SZ));
691 points[2].x = WINSCALE(X(fill_top_right));
692 points[2].y = WINSCALE(Y(y + BLOCK_SZ));
693 points[3].x = WINSCALE(X(fill_bottom_right));
694 points[3].y = WINSCALE(Y(y));
695 points[4] = points[0];
696 rd.fillPolygon(dpy, p_draw, gc,
697 points, 5,
698 Convex, CoordModeOrigin);
699 if (useErase){
700 int left_x = MIN(fill_bottom_left, fill_top_left);
701 int right_x = MAX(fill_bottom_right, fill_top_right);
702 Erase_rectangle(WINSCALE(X(left_x)) - 1,
703 WINSCALE(Y(y + BLOCK_SZ)) - 1,
704 WINSCALE(right_x - left_x) + 4,
705 WINSCALE(BLOCK_SZ) + 3);
706 }
707 fill_top_left =
708 fill_top_right =
709 fill_bottom_left =
710 fill_bottom_right = -1;
711 }
712 }
713 if (decorTileDoit && last) {
714 XSetFillStyle(dpy, gc, FillSolid);
715 }
716 }
717
718
Gui_paint_setup_check(int x,int y,int xi,int yi)719 void Gui_paint_setup_check(int x, int y, int xi, int yi)
720 {
721 XPoint points[5];
722 if (!blockBitmaps) {
723 SET_FG(colors[BLUE].pixel);
724 points[0].x = WINSCALE(X(x+(BLOCK_SZ/2)));
725 points[0].y = WINSCALE(Y(y));
726 points[1].x = WINSCALE(X(x));
727 points[1].y = WINSCALE(Y(y+BLOCK_SZ/2));
728 points[2].x = WINSCALE(X(x+BLOCK_SZ/2));
729 points[2].y = WINSCALE(Y(y+BLOCK_SZ));
730 points[3].x = WINSCALE(X(x+BLOCK_SZ));
731 points[3].y = WINSCALE(Y(y+(BLOCK_SZ/2)));
732 points[4] = points[0];
733
734 if (Check_index_by_pos(xi, yi) == nextCheckPoint) {
735 rd.fillPolygon(dpy, p_draw, gc,
736 points, 5,
737 Convex, CoordModeOrigin);
738 Erase_rectangle(WINSCALE(X(x)),
739 WINSCALE(Y(y+BLOCK_SZ)),
740 WINSCALE(BLOCK_SZ),
741 WINSCALE(BLOCK_SZ));
742 } else {
743 rd.drawLines(dpy, p_draw, gc,
744 points, 5, 0);
745 Erase_points(0, points, 5);
746 }
747 } else {
748 if (Check_index_by_pos(xi, yi) == nextCheckPoint) {
749 PaintBitmap(p_draw, BM_CHECKPOINT, WINSCALE(X(x)), WINSCALE(Y(y + BLOCK_SZ)),
750 WINSCALE(BLOCK_SZ), WINSCALE(BLOCK_SZ), 1);
751
752 } else {
753 PaintBitmap(p_draw, BM_CHECKPOINT, WINSCALE(X(x)), WINSCALE(Y(y + BLOCK_SZ)),
754 WINSCALE(BLOCK_SZ), WINSCALE(BLOCK_SZ), 0);
755
756 }
757 Erase_rectangle(WINSCALE(X(x)),
758 WINSCALE(Y(y+BLOCK_SZ)),
759 WINSCALE(BLOCK_SZ),
760 WINSCALE(BLOCK_SZ));
761 }
762 }
763
764
Gui_paint_border(int x,int y,int xi,int yi)765 void Gui_paint_border(int x, int y, int xi, int yi)
766 {
767 Segment_add(wallColor,
768 X(x), Y(y),
769 X(xi), Y(yi));
770 }
771
772
Gui_paint_visible_border(int x,int y,int xi,int yi)773 void Gui_paint_visible_border(int x, int y, int xi, int yi)
774 {
775 Segment_add(hudColor,
776 X(x), Y(y),
777 X(x), Y(yi));
778
779 Segment_add(hudColor,
780 X(xi), Y(y),
781 X(xi), Y(yi));
782
783 Segment_add(hudColor,
784 X(x), Y(y),
785 X(xi), Y(y));
786
787 Segment_add(hudColor,
788 X(x), Y(yi),
789 X(xi), Y(yi));
790 }
791
792
Gui_paint_setup_acwise_grav(int x,int y)793 void Gui_paint_setup_acwise_grav(int x, int y)
794 {
795 Arc_add(RED, X(x+5), Y(y+BLOCK_SZ-5),
796 BLOCK_SZ-10, BLOCK_SZ-10, 64*150, 64*300);
797 Segment_add(RED,
798 X(x+BLOCK_SZ/2),
799 Y(y+BLOCK_SZ-5),
800 X(x+BLOCK_SZ/2+4),
801 Y(y+BLOCK_SZ-1));
802 Segment_add(RED,
803 X(x+BLOCK_SZ/2),
804 Y(y+BLOCK_SZ-5),
805 X(x+BLOCK_SZ/2+4),
806 Y(y+BLOCK_SZ-9));
807 }
808
809
Gui_paint_setup_cwise_grav(int x,int y)810 void Gui_paint_setup_cwise_grav(int x, int y)
811 {
812 Arc_add(RED,
813 X(x+5), Y(y+BLOCK_SZ-5),
814 BLOCK_SZ-10, BLOCK_SZ-10, 64*90, 64*300);
815 Segment_add(RED,
816 X(x+BLOCK_SZ/2),
817 Y(y+BLOCK_SZ-5),
818 X(x+BLOCK_SZ/2-4),
819 Y(y+BLOCK_SZ-1));
820 Segment_add(RED,
821 X(x+BLOCK_SZ/2),
822 Y(y+BLOCK_SZ-5),
823 X(x+BLOCK_SZ/2-4),
824 Y(y+BLOCK_SZ-9));
825 }
826
827
Gui_paint_setup_pos_grav(int x,int y)828 void Gui_paint_setup_pos_grav(int x, int y)
829 {
830 static const int INSIDE_BL = BLOCK_SZ - 2;
831 if (!blockBitmaps) {
832
833 Arc_add(RED,
834 X(x+1), Y(y+BLOCK_SZ-1),
835 INSIDE_BL, INSIDE_BL, 0, 64*360);
836 Segment_add(RED,
837 X(x+BLOCK_SZ/2),
838 Y(y+5),
839 X(x+BLOCK_SZ/2),
840 Y(y+BLOCK_SZ-5));
841 Segment_add(RED,
842 X(x+5),
843 Y(y+BLOCK_SZ/2),
844 X(x+BLOCK_SZ-5),
845 Y(y+BLOCK_SZ/2));
846 } else {
847 PaintBitmap(p_draw, BM_PLUSGRAVITY, WINSCALE(X(x)), WINSCALE(Y(y + BLOCK_SZ)),
848 WINSCALE(BLOCK_SZ), WINSCALE(BLOCK_SZ), 0);
849
850 }
851 }
852
853
Gui_paint_setup_neg_grav(int x,int y)854 void Gui_paint_setup_neg_grav(int x, int y)
855 {
856 static const int INSIDE_BL = BLOCK_SZ - 2;
857
858 if (!blockBitmaps) {
859
860 Arc_add(RED,
861 X(x+1), Y(y+BLOCK_SZ-1),
862 INSIDE_BL, INSIDE_BL, 0, 64*360);
863 Segment_add(RED,
864 X(x+5),
865 Y(y+BLOCK_SZ/2),
866 X(x+BLOCK_SZ-5),
867 Y(y+BLOCK_SZ/2));
868 } else {
869 PaintBitmap(p_draw, BM_MINUSGRAVITY, WINSCALE(X(x)), WINSCALE(Y(y + BLOCK_SZ)),
870 WINSCALE(BLOCK_SZ), WINSCALE(BLOCK_SZ), 0);
871
872 }
873 }
874
875
876
Gui_paint_setup_up_grav(int x,int y)877 void Gui_paint_setup_up_grav(int x, int y)
878 {
879 Segment_add(RED,
880 X(x+BLOCK_SZ/2),
881 Y(y),
882 X(x+BLOCK_SZ/2),
883 Y(y+BLOCK_SZ));
884 Segment_add(RED,
885 X(x+BLOCK_SZ/2),
886 Y(y+BLOCK_SZ),
887 X(x+BLOCK_SZ/2-10),
888 Y(y+BLOCK_SZ-10));
889 Segment_add(RED,
890 X(x+BLOCK_SZ/2),
891 Y(y+BLOCK_SZ),
892 X(x+BLOCK_SZ/2+10),
893 Y(y+BLOCK_SZ-10));
894 }
895
896
897
Gui_paint_setup_down_grav(int x,int y)898 void Gui_paint_setup_down_grav(int x, int y)
899 {
900 Segment_add(RED,
901 X(x+BLOCK_SZ/2),
902 Y(y),
903 X(x+BLOCK_SZ/2),
904 Y(y+BLOCK_SZ));
905 Segment_add(RED,
906 X(x+BLOCK_SZ/2),
907 Y(y),
908 X(x+BLOCK_SZ/2-10),
909 Y(y+10));
910 Segment_add(RED,
911 X(x+BLOCK_SZ/2),
912 Y(y),
913 X(x+BLOCK_SZ/2+10),
914 Y(y+10));
915 }
916
917
918
Gui_paint_setup_right_grav(int x,int y)919 void Gui_paint_setup_right_grav(int x, int y)
920 {
921 Segment_add(RED,
922 X(x),
923 Y(y+BLOCK_SZ/2),
924 X(x+BLOCK_SZ),
925 Y(y+BLOCK_SZ/2));
926 Segment_add(RED,
927 X(x+BLOCK_SZ),
928 Y(y+BLOCK_SZ/2),
929 X(x+BLOCK_SZ-10),
930 Y(y+BLOCK_SZ/2+10));
931 Segment_add(RED,
932 X(x+BLOCK_SZ),
933 Y(y+BLOCK_SZ/2),
934 X(x+BLOCK_SZ-10),
935 Y(y+BLOCK_SZ/2-10));
936 }
937
938
939
Gui_paint_setup_left_grav(int x,int y)940 void Gui_paint_setup_left_grav(int x, int y)
941 {
942 Segment_add(RED,
943 X(x),
944 Y(y+BLOCK_SZ/2),
945 X(x+BLOCK_SZ),
946 Y(y+BLOCK_SZ/2));
947 Segment_add(RED,
948 X(x),
949 Y(y+BLOCK_SZ/2),
950 X(x+10),
951 Y(y+BLOCK_SZ/2+10));
952 Segment_add(RED,
953 X(x),
954 Y(y+BLOCK_SZ/2),
955 X(x+10),
956 Y(y+BLOCK_SZ/2-10));
957 }
958
959
Gui_paint_setup_worm(int x,int y,int wormDrawCount)960 void Gui_paint_setup_worm(int x, int y, int wormDrawCount)
961 {
962 if (!blockBitmaps) {
963 static const int INSIDE_BL = BLOCK_SZ - 2;
964 static int wormOffset[8][3] = {
965 { 10, 10, 10 },
966 { 5, 10, 10 },
967 { 0, 10, 10 },
968 { 0, 5, 10 },
969 { 0, 0, 10 },
970 { 5, 0, 10 },
971 { 10, 0, 10 },
972 { 10, 5, 10 }
973 };
974 #define _O wormOffset[wormDrawCount]
975
976 SET_FG(colors[RED].pixel);
977 Arc_add(RED,
978 X(x) + 0, Y(y + BLOCK_SZ) + 0,
979 INSIDE_BL - 0, INSIDE_BL - 0, 0, 64 * 360);
980
981 Arc_add(RED,
982 X(x) + _O[0], Y(y + BLOCK_SZ) + _O[1],
983 INSIDE_BL - _O[2], INSIDE_BL - _O[2], 0, 64 * 360);
984
985 Arc_add(RED,
986 X(x) + _O[0] * 2, Y(y + BLOCK_SZ) + _O[1] * 2,
987 INSIDE_BL - _O[2] * 2, INSIDE_BL - _O[2] * 2, 0, 64 * 360);
988 }
989 else {
990 PaintBitmap(p_draw, BM_WORMHOLE, WINSCALE(X(x)), WINSCALE(Y(y + BLOCK_SZ)),
991 WINSCALE(BLOCK_SZ), WINSCALE(BLOCK_SZ), wormDrawCount);
992 }
993 }
994
995
Gui_paint_setup_item_concentrator(int x,int y)996 void Gui_paint_setup_item_concentrator(int x, int y)
997 {
998 static struct concentrator_triangle {
999 int radius;
1000 int displ;
1001 int dir_off;
1002 int rot_speed;
1003 int rot_dir;
1004 } tris[] = {
1005 #if 0
1006 { 14, 3, 0, 1, 0 },
1007 { 11, 5, 3, 2, 0 },
1008 { 7, 8, 5, 3, 0 },
1009 #else
1010 { 7, 3, 0, 3, 0 },
1011 { 11, 5, 3, 3, 0 },
1012 { 14, 8, 5, 3, 0 },
1013 #endif
1014 };
1015 static unsigned rot_dir;
1016 static long concentratorloop;
1017 unsigned rdir, tdir;
1018 int i, cx, cy;
1019 XPoint pts[4];
1020 if (!blockBitmaps) {
1021 SET_FG(colors[RED].pixel);
1022 if (concentratorloop != loops) {
1023 concentratorloop = loops;
1024 rot_dir += 5;
1025 for (i = 0; i < NELEM(tris); i++) {
1026 tris[i].rot_dir += tris[i].rot_speed;
1027 }
1028 }
1029 for (i = 0; i < NELEM(tris); i++) {
1030 /* I'll bet you didn't know that floating point math
1031 is faster than integer math on a pentium
1032 (and for some reason the UNIX way rounds off too much) */
1033 rdir = MOD2(rot_dir + tris[i].dir_off, RES);
1034 cx = (int)(X(x + BLOCK_SZ / 2)
1035 + tris[i].displ * tcos(rdir));
1036 cy = (int)(Y(y + BLOCK_SZ / 2)
1037 + tris[i].displ * tsin(rdir));
1038 tdir = MOD2(tris[i].rot_dir, RES);
1039 pts[0].x = WINSCALE(cx + (int)(tris[i].radius * tcos(tdir)));
1040 pts[0].y = WINSCALE(cy + (int)(tris[i].radius * tsin(tdir)));
1041 pts[1].x = WINSCALE(cx + (int)(tris[i].radius
1042 * tcos(MOD2(tdir + RES/3, RES))));
1043 pts[1].y = WINSCALE(cy + (int)(tris[i].radius
1044 * tsin(MOD2(tdir + RES/3, RES))));
1045 pts[2].x = WINSCALE(cx + (int)(tris[i].radius
1046 * tcos(MOD2(tdir + 2*RES/3, RES))));
1047 pts[2].y = WINSCALE(cy + (int)(tris[i].radius
1048 * tsin(MOD2(tdir + 2*RES/3, RES))));
1049 /* Trace("DC: %d cx=%d/%d %d/%d %d/%d %d/%d %d/%d\n",
1050 i, cx, cy, pts[0].x, pts[0].y,
1051 pts[1].x, pts[1].y, pts[2].x, pts[2].y, pts[3].x, pts[3].y); */
1052
1053 pts[3] = pts[0];
1054 rd.drawLines(dpy, p_draw, gc,
1055 pts, NELEM(pts), CoordModeOrigin);
1056 Erase_points(0, pts, NELEM(pts));
1057 }
1058 } else {
1059 PaintBitmap(p_draw, BM_CONCENTRATOR, WINSCALE(X(x)), WINSCALE(Y(y + BLOCK_SZ)),
1060 WINSCALE(BLOCK_SZ), WINSCALE(BLOCK_SZ), (loops + (x + x * y)) % 32);
1061
1062 }
1063 }
1064
1065
Gui_paint_setup_asteroid_concentrator(int x,int y)1066 void Gui_paint_setup_asteroid_concentrator(int x, int y)
1067 {
1068 static struct concentrator_square {
1069 int size;
1070 int displ;
1071 int dir_off;
1072 int rot_speed;
1073 int rot_dir;
1074 } sqrs[] = {
1075 #if 0
1076 { 16, 3, 0, 1, 0 },
1077 { 12, 5, 3, 2, 0 },
1078 { 8, 8, 5, 3, 0 },
1079 #else
1080 { 8, 3, 0, 3, 0 },
1081 { 12, 5, 3, 3, 0 },
1082 { 16, 8, 5, 3, 0 },
1083 #endif
1084 };
1085 static unsigned rot_dir;
1086 static long concentratorloop;
1087 unsigned rdir, tdir;
1088 int i, cx, cy;
1089 XPoint pts[5];
1090 if (!blockBitmaps) {
1091 SET_FG(colors[RED].pixel);
1092 if (concentratorloop != loops) {
1093 concentratorloop = loops;
1094 rot_dir += 5;
1095 for (i = 0; i < NELEM(sqrs); i++) {
1096 sqrs[i].rot_dir += sqrs[i].rot_speed;
1097 }
1098 }
1099 for (i = 0; i < NELEM(sqrs); i++) {
1100 /* I'll bet you didn't know that floating point math
1101 is faster than integer math on a pentium
1102 (and for some reason the UNIX way rounds off too much) */
1103 rdir = MOD2(rot_dir + sqrs[i].dir_off, RES);
1104 cx = (int)(X(x + BLOCK_SZ / 2)
1105 + sqrs[i].displ * tcos(rdir));
1106 cy = (int)(Y(y + BLOCK_SZ / 2)
1107 + sqrs[i].displ * tsin(rdir));
1108 tdir = MOD2(sqrs[i].rot_dir, RES);
1109 pts[0].x = WINSCALE(cx + (int)(sqrs[i].size * tcos(tdir)));
1110 pts[0].y = WINSCALE(cy + (int)(sqrs[i].size * tsin(tdir)));
1111 pts[1].x = WINSCALE(cx + (int)(sqrs[i].size * tcos(MOD2(tdir + RES/4, RES))));
1112 pts[1].y = WINSCALE(cy + (int)(sqrs[i].size * tsin(MOD2(tdir + RES/4, RES))));
1113 pts[2].x = WINSCALE(cx + (int)(sqrs[i].size * tcos(MOD2(tdir + 2*RES/4, RES))));
1114 pts[2].y = WINSCALE(cy + (int)(sqrs[i].size * tsin(MOD2(tdir + 2*RES/4, RES))));
1115 pts[3].x = WINSCALE(cx + (int)(sqrs[i].size * tcos(MOD2(tdir + 3*RES/4, RES))));
1116 pts[3].y = WINSCALE(cy + (int)(sqrs[i].size * tsin(MOD2(tdir + 3*RES/4, RES))));
1117 /* Trace("DC: %d cx=%d/%d %d/%d %d/%d %d/%d %d/%d\n",
1118 i, cx, cy, pts[0].x, pts[0].y,
1119 pts[1].x, pts[1].y, pts[2].x, pts[2].y, pts[3].x, pts[3].y); */
1120
1121 pts[4] = pts[0];
1122 rd.drawLines(dpy, p_draw, gc,
1123 pts, NELEM(pts), CoordModeOrigin);
1124 Erase_points(0, pts, NELEM(pts));
1125 }
1126 } else {
1127 PaintBitmap(p_draw, BM_ASTEROIDCONC, WINSCALE(X(x)), WINSCALE(Y(y + BLOCK_SZ)),
1128 WINSCALE(BLOCK_SZ), WINSCALE(BLOCK_SZ), (loops + (x + x * y)) % 32);
1129
1130 }
1131 }
1132
1133
Gui_paint_decor_dot(int x,int y,int size)1134 void Gui_paint_decor_dot(int x, int y, int size)
1135 {
1136 Rectangle_add(BLUE, X(x + BLOCK_SZ / 2) - (map_point_size >> 1),
1137 Y(y + BLOCK_SZ / 2) - (map_point_size >> 1),
1138 size, size);
1139 }
1140
1141
Gui_paint_setup_target(int x,int y,int target,int damage,bool own)1142 void Gui_paint_setup_target(int x, int y, int target, int damage, bool own)
1143 {
1144 int size, a1, a2, b1, b2, color;
1145 char s[2];
1146
1147 color = own ? BLUE : RED;
1148
1149 SET_FG(colors[color].pixel);
1150
1151 a1 = X(x);
1152 b1 = Y(y+BLOCK_SZ);
1153 a2 = a1 + BLOCK_SZ;
1154 b2 = b1 + BLOCK_SZ;
1155 Segment_add(color, a1, b1, a1, b2);
1156 Segment_add(color, a2, b1, a2, b2);
1157 Segment_add(color, a1, b1, a2, b1);
1158 Segment_add(color, a1, b2, a2, b2);
1159
1160 rd.drawRectangle(dpy, p_draw, gc,
1161 WINSCALE(X(x+(BLOCK_SZ+2)/4)),
1162 WINSCALE(Y(y+3*BLOCK_SZ/4)),
1163 WINSCALE(BLOCK_SZ/2),
1164 WINSCALE(BLOCK_SZ/2));
1165 Erase_4point(WINSCALE(X(x+(BLOCK_SZ+2)/4)),
1166 WINSCALE(Y(y+3*BLOCK_SZ/4)),
1167 WINSCALE(BLOCK_SZ/2), WINSCALE(BLOCK_SZ/2));
1168
1169 if (BIT(Setup->mode, TEAM_PLAY)) {
1170 s[0] = '0' + target; s[1] = '\0';
1171 size = XTextWidth(gameFont, s, 1);
1172 rd.drawString(dpy, p_draw, gc,
1173 WINSCALE(X(x + BLOCK_SZ/2)) - size/2,
1174 WINSCALE(Y(y + BLOCK_SZ/2))
1175 + gameFont->ascent/2,
1176 s, 1);
1177 Erase_rectangle(WINSCALE(X(x + BLOCK_SZ/2)) - size/2-1,
1178 WINSCALE(Y(y + BLOCK_SZ/2))
1179 + gameFont->ascent/2
1180 - gameFont->ascent - 1,
1181 size + 2,
1182 gameFont->ascent+ gameFont->descent+ 2);
1183 }
1184
1185 if (damage != TARGET_DAMAGE) {
1186 size = (damage * BLOCK_SZ) / (TARGET_DAMAGE * 2);
1187 a1 = x + size;
1188 a2 = y + size;
1189 b1 = x + (BLOCK_SZ - size);
1190 b2 = y + (BLOCK_SZ - size);
1191
1192 Segment_add(RED,
1193 X(a1), Y(a2),
1194 X(b1), Y(b2));
1195
1196 Segment_add(RED,
1197 X(a1), Y(b2),
1198 X(b1), Y(a2));
1199 }
1200 }
1201
1202
Gui_paint_setup_treasure(int x,int y,int treasure,bool own)1203 void Gui_paint_setup_treasure(int x, int y, int treasure, bool own)
1204 {
1205 if (!blockBitmaps) {
1206 char s[2];
1207 int color;
1208 int size;
1209 color = own ? BLUE : RED;
1210
1211 SET_FG(colors[color].pixel);
1212 Segment_add(color,
1213 X(x),Y(y),
1214 X(x),Y(y + BLOCK_SZ/2));
1215 Segment_add(color,
1216 X(x + BLOCK_SZ),Y(y),
1217 X(x + BLOCK_SZ),
1218 Y(y + BLOCK_SZ/2));
1219 Segment_add(color,
1220 X(x),Y(y),
1221 X(x + BLOCK_SZ),Y(y));
1222 Arc_add(color,
1223 X(x),
1224 Y(y + BLOCK_SZ),
1225 BLOCK_SZ, BLOCK_SZ, 0, 64*180);
1226 if (BIT(Setup->mode, TEAM_PLAY)) {
1227 s[1] = '\0'; s[0] = '0' + treasure;
1228 size = XTextWidth(gameFont, s, 1);
1229 rd.drawString(dpy, p_draw, gc,
1230 WINSCALE(X(x + BLOCK_SZ/2)) - size/2,
1231 WINSCALE(Y(y + 2*BALL_RADIUS)), s, 1);
1232 Erase_rectangle(WINSCALE(X(x + BLOCK_SZ/2)) - size/2 - 1,
1233 WINSCALE(Y(y + 2*BALL_RADIUS))
1234 - gameFont->ascent - 1,
1235 size + 2,
1236 gameFont->ascent+ gameFont->descent+ 2);
1237 }
1238 }
1239 else {
1240 char s[2];
1241 int size;
1242
1243 int type;
1244 int color;
1245
1246 type = own ? BM_HOLDER_FRIEND : BM_HOLDER_ENEMY;
1247
1248 PaintBitmap(p_draw, type, WINSCALE(X(x)), WINSCALE(Y(y + BLOCK_SZ)),
1249 WINSCALE(BLOCK_SZ), WINSCALE(BLOCK_SZ), 0);
1250
1251 if (BIT(Setup->mode, TEAM_PLAY)) {
1252 color = own ? BLUE : RED;
1253 SET_FG(colors[color].pixel);
1254
1255 s[1] = '\0'; s[0] = '0' + treasure;
1256 size = XTextWidth(gameFont, s, 1);
1257 rd.drawString(dpy, p_draw, gc,
1258 WINSCALE(X(x + BLOCK_SZ/2)) - size/2,
1259 WINSCALE(Y(y + BALL_RADIUS + 5)), s, 1);
1260 Erase_rectangle(WINSCALE(X(x + BLOCK_SZ/2 )) - size/2 - 1,
1261 WINSCALE(Y(y + BALL_RADIUS + 5))
1262 - gameFont->ascent - 1,
1263 size + 2,
1264 gameFont->ascent+ gameFont->descent+ 2);
1265 }
1266
1267 }
1268 }
1269
1270