1 // Emacs style mode select -*- C++ -*-
2 //-----------------------------------------------------------------------------
3 //
4 // $Id: am_map.cpp 4542 2014-02-09 17:39:42Z dr_sean $
5 //
6 // Copyright (C) 1993-1996 by id Software, Inc.
7 // Copyright (C) 2006-2014 by The Odamex Team.
8 //
9 // This program is free software; you can redistribute it and/or
10 // modify it under the terms of the GNU General Public License
11 // as published by the Free Software Foundation; either version 2
12 // of the License, or (at your option) any later version.
13 //
14 // This program is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 // GNU General Public License for more details.
18 //
19 // DESCRIPTION:
20 // AutoMap module.
21 //
22 //-----------------------------------------------------------------------------
23
24
25 #include <stdio.h>
26
27 #include "doomdef.h"
28 #include "g_level.h"
29 #include "z_zone.h"
30 #include "doomdef.h"
31 #include "st_stuff.h"
32 #include "p_local.h"
33 #include "p_lnspec.h"
34 #include "w_wad.h"
35 #include "v_palette.h"
36
37 #include "m_cheat.h"
38 #include "i_system.h"
39 #include "c_dispatch.h"
40 #include "p_ctf.h"
41 #include "cl_demo.h"
42
43 // Needs access to LFB.
44 #include "v_video.h"
45
46 #include "v_text.h"
47
48 extern patch_t *hu_font[];
49
50 // State.
51 #include "doomstat.h"
52 #include "r_state.h"
53
54 // Data.
55 #include "gstrings.h"
56
57 #include "am_map.h"
58
59 int CL_GetPlayerColor(player_t*);
60
61 // Group palette index and RGB value together:
62 typedef struct am_color_s {
63 palindex_t index;
64 argb_t rgb;
65 } am_color_t;
66
67 static am_color_t
68 Background, YourColor, WallColor, TSWallColor,
69 FDWallColor, CDWallColor, ThingColor,
70 SecretWallColor, GridColor, XHairColor,
71 NotSeenColor,
72 LockedColor,
73 AlmostBackground,
74 TeleportColor, ExitColor;
75
76 static int lockglow = 0;
77
78 EXTERN_CVAR (am_rotate)
EXTERN_CVAR(am_overlay)79 EXTERN_CVAR (am_overlay)
80 EXTERN_CVAR (am_showsecrets)
81 EXTERN_CVAR (am_showmonsters)
82 EXTERN_CVAR (am_showtime)
83 EXTERN_CVAR (am_classicmapstring)
84 EXTERN_CVAR (am_usecustomcolors)
85 EXTERN_CVAR (am_ovshare)
86
87 EXTERN_CVAR (am_backcolor)
88 EXTERN_CVAR (am_yourcolor)
89 EXTERN_CVAR (am_wallcolor)
90 EXTERN_CVAR (am_tswallcolor)
91 EXTERN_CVAR (am_fdwallcolor)
92 EXTERN_CVAR (am_cdwallcolor)
93 EXTERN_CVAR (am_thingcolor)
94 EXTERN_CVAR (am_gridcolor)
95 EXTERN_CVAR (am_xhaircolor)
96 EXTERN_CVAR (am_notseencolor)
97 EXTERN_CVAR (am_lockedcolor)
98 EXTERN_CVAR (am_exitcolor)
99 EXTERN_CVAR (am_teleportcolor)
100
101 EXTERN_CVAR (am_ovyourcolor)
102 EXTERN_CVAR (am_ovwallcolor)
103 EXTERN_CVAR (am_ovtswallcolor)
104 EXTERN_CVAR (am_ovfdwallcolor)
105 EXTERN_CVAR (am_ovcdwallcolor)
106 EXTERN_CVAR (am_ovthingcolor)
107 EXTERN_CVAR (am_ovgridcolor)
108 EXTERN_CVAR (am_ovxhaircolor)
109 EXTERN_CVAR (am_ovnotseencolor)
110 EXTERN_CVAR (am_ovlockedcolor)
111 EXTERN_CVAR (am_ovexitcolor)
112 EXTERN_CVAR (am_ovteleportcolor)
113
114 BEGIN_COMMAND (resetcustomcolors)
115 {
116 am_backcolor = "00 00 3a";
117 am_yourcolor = "fc e8 d8";
118 am_wallcolor = "00 8b ff";
119 am_tswallcolor = "10 32 7e";
120 am_fdwallcolor = "1a 1a 8a";
121 am_cdwallcolor = "00 00 5a";
122 am_thingcolor = "9f d3 ff";
123 am_gridcolor = "44 44 88";
124 am_xhaircolor = "80 80 80";
125 am_notseencolor = "00 22 6e";
126 am_lockedcolor = "bb bb bb";
127 am_exitcolor = "ff ff 00";
128 am_teleportcolor = "ff a3 00";
129
130 am_ovyourcolor = "fc e8 d8";
131 am_ovwallcolor = "00 8b ff";
132 am_ovtswallcolor = "10 32 7e";
133 am_ovfdwallcolor = "1a 1a 8a";
134 am_ovcdwallcolor = "00 00 5a";
135 am_ovthingcolor = "9f d3 ff";
136 am_ovgridcolor = "44 44 88";
137 am_ovxhaircolor = "80 80 80";
138 am_ovnotseencolor = "00 22 6e";
139 am_ovlockedcolor = "bb bb bb";
140 am_ovexitcolor = "ff ff 00";
141 am_ovteleportcolor = "ff a3 00";
142 Printf (PRINT_HIGH, "Custom automap colors reset to default.\n");
143 }
144 END_COMMAND (resetcustomcolors)
145
146 EXTERN_CVAR (screenblocks)
147
148 // drawing stuff
149 #define FB (screen)
150
151 #define AM_PANDOWNKEY KEY_DOWNARROW
152 #define AM_PANUPKEY KEY_UPARROW
153 #define AM_PANRIGHTKEY KEY_RIGHTARROW
154 #define AM_PANLEFTKEY KEY_LEFTARROW
155 #define AM_ZOOMINKEY KEY_EQUALS
156 #define AM_ZOOMINKEY2 0x4e // DIK_ADD
157 #define AM_ZOOMOUTKEY KEY_MINUS
158 #define AM_ZOOMOUTKEY2 0x4a // DIK_SUBTRACT
159 #define AM_GOBIGKEY 0x0b // DIK_0
160 #define AM_FOLLOWKEY 'f'
161 #define AM_GRIDKEY 'g'
162 #define AM_MARKKEY 'm'
163 #define AM_CLEARMARKKEY 'c'
164
165 #define AM_NUMMARKPOINTS 10
166
167 // scale on entry
168 #define INITSCALEMTOF (.2*FRACUNIT)
169 // how much the automap moves window per tic in frame-buffer coordinates
170 // moves 140 pixels in 1 second
171 #define F_PANINC (140/TICRATE)
172 // how much zoom-in per tic
173 // goes to 2x in 1 second
174 #define M_ZOOMIN ((int) (1.02*FRACUNIT))
175 // how much zoom-out per tic
176 // pulls out to 0.5x in 1 second
177 #define M_ZOOMOUT ((int) (FRACUNIT/1.02))
178
179 // translates between frame-buffer and map distances
180 #define FTOM(x) FixedMul(((x)<<16),scale_ftom)
181 #define MTOF(x) (FixedMul((x),scale_mtof)>>16)
182 // translates between frame-buffer and map coordinates
183 #define CXMTOF(x) (MTOF((x)-m_x)/* - f_x*/)
184 #define CYMTOF(y) (f_h - MTOF((y)-m_y)/* + f_y*/)
185
186 #define PUTDOTP(xx,yy,cc) fb[(yy)*f_p+(xx)]=(cc)
187 #define PUTDOTD(xx,yy,cc) *((argb_t *)(fb+(yy)*f_p+((xx)<<2)))=(cc)
188
189 typedef struct {
190 int x, y;
191 } fpoint_t;
192
193 typedef struct {
194 fpoint_t a, b;
195 } fline_t;
196
197 typedef struct {
198 fixed_t x,y;
199 } mpoint_t;
200
201 typedef struct {
202 mpoint_t a, b;
203 } mline_t;
204
205 typedef struct {
206 fixed_t slp, islp;
207 } islope_t;
208
209
210
211 //
212 // The vector graphics for the automap.
213 // A line drawing of the player pointing right,
214 // starting from the middle.
215 //
216 #define R ((8*PLAYERRADIUS)/7)
217 mline_t player_arrow[] = {
218 { { -R+R/8, 0 }, { R, 0 } }, // -----
219 { { R, 0 }, { R-R/2, R/4 } }, // ----->
220 { { R, 0 }, { R-R/2, -R/4 } },
221 { { -R+R/8, 0 }, { -R-R/8, R/4 } }, // >---->
222 { { -R+R/8, 0 }, { -R-R/8, -R/4 } },
223 { { -R+3*R/8, 0 }, { -R+R/8, R/4 } }, // >>--->
224 { { -R+3*R/8, 0 }, { -R+R/8, -R/4 } }
225 };
226 #undef R
227 #define NUMPLYRLINES (sizeof(player_arrow)/sizeof(mline_t))
228
229 #define R ((8*PLAYERRADIUS)/7)
230 mline_t cheat_player_arrow[] = {
231 { { -R+R/8, 0 }, { R, 0 } }, // -----
232 { { R, 0 }, { R-R/2, R/6 } }, // ----->
233 { { R, 0 }, { R-R/2, -R/6 } },
234 { { -R+R/8, 0 }, { -R-R/8, R/6 } }, // >----->
235 { { -R+R/8, 0 }, { -R-R/8, -R/6 } },
236 { { -R+3*R/8, 0 }, { -R+R/8, R/6 } }, // >>----->
237 { { -R+3*R/8, 0 }, { -R+R/8, -R/6 } },
238 { { -R/2, 0 }, { -R/2, -R/6 } }, // >>-d--->
239 { { -R/2, -R/6 }, { -R/2+R/6, -R/6 } },
240 { { -R/2+R/6, -R/6 }, { -R/2+R/6, R/4 } },
241 { { -R/6, 0 }, { -R/6, -R/6 } }, // >>-dd-->
242 { { -R/6, -R/6 }, { 0, -R/6 } },
243 { { 0, -R/6 }, { 0, R/4 } },
244 { { R/6, R/4 }, { R/6, -R/7 } }, // >>-ddt->
245 { { R/6, -R/7 }, { R/6+R/32, -R/7-R/32 } },
246 { { R/6+R/32, -R/7-R/32 }, { R/6+R/10, -R/7 } }
247 };
248 #undef R
249 #define NUMCHEATPLYRLINES (sizeof(cheat_player_arrow)/sizeof(mline_t))
250
251 #define R (FRACUNIT)
252 // [RH] Avoid lots of warnings without compiler-specific #pragmas
253 #define L(a,b,c,d) { {(fixed_t)((a)*R),(fixed_t)((b)*R)}, {(fixed_t)((c)*R),(fixed_t)((d)*R)} }
254 mline_t triangle_guy[] = {
255 L (-.867,-.5, .867,-.5),
256 L (.867,-.5, 0,1),
257 L (0,1, -.867,-.5)
258 };
259 #define NUMTRIANGLEGUYLINES (sizeof(triangle_guy)/sizeof(mline_t))
260
261 mline_t thintriangle_guy[] = {
262 L (-.5,-.7, 1,0),
263 L (1,0, -.5,.7),
264 L (-.5,.7, -.5,-.7)
265 };
266 #undef L
267 #undef R
268 #define NUMTHINTRIANGLEGUYLINES (sizeof(thintriangle_guy)/sizeof(mline_t))
269
270
271
272
273 static int cheating = 0;
274 static int grid = 0;
275
276 static int leveljuststarted = 1; // kluge until AM_LevelInit() is called
277
278 BOOL automapactive = false;
279
280 // location of window on screen
281 static int f_x;
282 static int f_y;
283
284 // size of window on screen
285 static int f_w;
286 static int f_h;
287 static int f_p; // [RH] # of bytes from start of a line to start of next
288
289 static byte *fb; // pseudo-frame buffer
290 static int amclock;
291
292 static mpoint_t m_paninc; // how far the window pans each tic (map coords)
293 static fixed_t mtof_zoommul; // how far the window zooms in each tic (map coords)
294 static fixed_t ftom_zoommul; // how far the window zooms in each tic (fb coords)
295
296 static fixed_t m_x, m_y; // LL x,y where the window is on the map (map coords)
297 static fixed_t m_x2, m_y2; // UR x,y where the window is on the map (map coords)
298
299 //
300 // width/height of window on map (map coords)
301 //
302 static fixed_t m_w;
303 static fixed_t m_h;
304
305 // based on level size
306 static fixed_t min_x;
307 static fixed_t min_y;
308 static fixed_t max_x;
309 static fixed_t max_y;
310
311 static fixed_t max_w; // max_x-min_x,
312 static fixed_t max_h; // max_y-min_y
313
314 // based on player size
315 static fixed_t min_w;
316 static fixed_t min_h;
317
318
319 static fixed_t min_scale_mtof; // used to tell when to stop zooming out
320 static fixed_t max_scale_mtof; // used to tell when to stop zooming in
321
322 // old stuff for recovery later
323 static fixed_t old_m_w, old_m_h;
324 static fixed_t old_m_x, old_m_y;
325
326 // old location used by the Follower routine
327 static mpoint_t f_oldloc;
328
329 // used by MTOF to scale from map-to-frame-buffer coords
330 static fixed_t scale_mtof = (fixed_t)INITSCALEMTOF;
331 // used by FTOM to scale from frame-buffer-to-map coords (=1/scale_mtof)
332 static fixed_t scale_ftom;
333
334 static patch_t *marknums[10]; // numbers used for marking by the automap
335 static mpoint_t markpoints[AM_NUMMARKPOINTS]; // where the points are
336 static int markpointnum = 0; // next point to be assigned
337
338 static bool followplayer = true; // specifies whether to follow the player around
339
340 // [RH] Not static so that the DeHackEd code can reach it.
341 extern byte cheat_amap_seq[5];
342 cheatseq_t cheat_amap = { cheat_amap_seq, 0 };
343
344 static BOOL stopped = true;
345
346 extern NetDemo netdemo;
347
348 #define NUMALIASES 3
349 #define WALLCOLORS -1
350 #define FDWALLCOLORS -2
351 #define CDWALLCOLORS -3
352
353 #define WEIGHTBITS 6
354 #define WEIGHTSHIFT (FRACBITS-WEIGHTBITS)
355 #define NUMWEIGHTS (1<<WEIGHTBITS)
356 #define WEIGHTMASK (NUMWEIGHTS-1)
357
358
359 void AM_rotatePoint (fixed_t *x, fixed_t *y);
360
361 //
362 //
363 //
AM_activateNewScale(void)364 void AM_activateNewScale(void)
365 {
366 m_x += m_w/2;
367 m_y += m_h/2;
368 m_w = FTOM(f_w);
369 m_h = FTOM(f_h);
370 m_x -= m_w/2;
371 m_y -= m_h/2;
372 m_x2 = m_x + m_w;
373 m_y2 = m_y + m_h;
374 }
375
376 //
377 //
378 //
AM_saveScaleAndLoc(void)379 void AM_saveScaleAndLoc(void)
380 {
381 old_m_x = m_x;
382 old_m_y = m_y;
383 old_m_w = m_w;
384 old_m_h = m_h;
385 }
386
387 //
388 //
389 //
AM_restoreScaleAndLoc(void)390 void AM_restoreScaleAndLoc(void)
391 {
392 m_w = old_m_w;
393 m_h = old_m_h;
394 if (!followplayer)
395 {
396 m_x = old_m_x;
397 m_y = old_m_y;
398 }
399 else
400 {
401 m_x = displayplayer().camera->x - m_w/2;
402 m_y = displayplayer().camera->y - m_h/2;
403 }
404 m_x2 = m_x + m_w;
405 m_y2 = m_y + m_h;
406
407 // Change the scaling multipliers
408 scale_mtof = FixedDiv(f_w<<FRACBITS, m_w);
409 scale_ftom = FixedDiv(FRACUNIT, scale_mtof);
410 }
411
412 //
413 // adds a marker at the current location
414 //
AM_addMark(void)415 void AM_addMark(void)
416 {
417 markpoints[markpointnum].x = m_x + m_w/2;
418 markpoints[markpointnum].y = m_y + m_h/2;
419 markpointnum = (markpointnum + 1) % AM_NUMMARKPOINTS;
420 }
421
422 //
423 // Determines bounding box of all vertices,
424 // sets global variables controlling zoom range.
425 //
AM_findMinMaxBoundaries(void)426 void AM_findMinMaxBoundaries(void)
427 {
428 int i;
429 fixed_t a;
430 fixed_t b;
431
432 min_x = min_y = MAXINT;
433 max_x = max_y = -MAXINT;
434
435 for (i=0;i<numvertexes;i++) {
436 if (vertexes[i].x < min_x)
437 min_x = vertexes[i].x;
438 else if (vertexes[i].x > max_x)
439 max_x = vertexes[i].x;
440
441 if (vertexes[i].y < min_y)
442 min_y = vertexes[i].y;
443 else if (vertexes[i].y > max_y)
444 max_y = vertexes[i].y;
445 }
446
447 max_w = max_x - min_x;
448 max_h = max_y - min_y;
449
450 min_w = 2*PLAYERRADIUS; // const? never changed?
451 min_h = 2*PLAYERRADIUS;
452
453 a = FixedDiv((screen->width)<<FRACBITS, max_w);
454 b = FixedDiv((screen->height)<<FRACBITS, max_h);
455
456 min_scale_mtof = a < b ? a : b;
457 max_scale_mtof = FixedDiv((screen->height)<<FRACBITS, 2*PLAYERRADIUS);
458 }
459
460
461 //
462 //
463 //
AM_changeWindowLoc(void)464 void AM_changeWindowLoc(void)
465 {
466 if (m_paninc.x || m_paninc.y) {
467 followplayer = 0;
468 f_oldloc.x = MAXINT;
469 }
470
471 m_x += m_paninc.x;
472 m_y += m_paninc.y;
473
474 if (m_x + m_w/2 > max_x)
475 m_x = max_x - m_w/2;
476 else if (m_x + m_w/2 < min_x)
477 m_x = min_x - m_w/2;
478
479 if (m_y + m_h/2 > max_y)
480 m_y = max_y - m_h/2;
481 else if (m_y + m_h/2 < min_y)
482 m_y = min_y - m_h/2;
483
484 m_x2 = m_x + m_w;
485 m_y2 = m_y + m_h;
486 }
487
488
489 //
490 //
491 //
AM_initVariables(void)492 void AM_initVariables(void)
493 {
494 static event_t st_notify = { ev_keyup, AM_MSGENTERED, 0, 0 };
495
496 automapactive = true;
497
498 f_oldloc.x = MAXINT;
499 amclock = 0;
500
501 m_paninc.x = m_paninc.y = 0;
502 ftom_zoommul = FRACUNIT;
503 mtof_zoommul = FRACUNIT;
504
505 m_w = FTOM(screen->width);
506 m_h = FTOM(screen->height);
507
508 // find player to center on initially
509 player_t *pl = &displayplayer();
510 if (!pl->ingame())
511 {
512 for (Players::iterator it = players.begin();it != players.end();++it)
513 {
514 if (it->ingame())
515 {
516 pl = &*it;
517 break;
518 }
519 }
520 }
521
522 if(!pl->camera)
523 return;
524
525 m_x = pl->camera->x - m_w/2;
526 m_y = pl->camera->y - m_h/2;
527 AM_changeWindowLoc();
528
529 // for saving & restoring
530 old_m_x = m_x;
531 old_m_y = m_y;
532 old_m_w = m_w;
533 old_m_h = m_h;
534
535 // inform the status bar of the change
536 ST_Responder (&st_notify);
537 }
538
539
AM_GetColorFromString(argb_t * palette,const char * colorstring)540 am_color_t AM_GetColorFromString(argb_t *palette, const char *colorstring)
541 {
542 am_color_t c;
543 c.rgb = (argb_t) V_GetColorFromString(NULL, colorstring);
544 c.index = BestColor2(palette, c.rgb, 256);
545 return c;
546 }
547
AM_BestColor(argb_t * palette,const int r,const int g,const int b,const int numcolors)548 am_color_t AM_BestColor(argb_t *palette, const int r, const int g, const int b, const int numcolors)
549 {
550 am_color_t c;
551 c.rgb = MAKERGB(r,g,b);
552 c.index = BestColor2(palette, c.rgb, 256);
553 return c;
554 }
555
AM_initColors(BOOL overlayed)556 void AM_initColors (BOOL overlayed)
557 {
558 // Look up the colors in the current palette:
559 argb_t *palette = GetDefaultPalette()->colors;
560
561 if (overlayed && !am_ovshare)
562 {
563 YourColor = AM_GetColorFromString (palette, am_ovyourcolor.cstring());
564 SecretWallColor =
565 WallColor= AM_GetColorFromString (palette, am_ovwallcolor.cstring());
566 TSWallColor = AM_GetColorFromString (palette, am_ovtswallcolor.cstring());
567 FDWallColor = AM_GetColorFromString (palette, am_ovfdwallcolor.cstring());
568 CDWallColor = AM_GetColorFromString (palette, am_ovcdwallcolor.cstring());
569 ThingColor = AM_GetColorFromString (palette, am_ovthingcolor.cstring());
570 GridColor = AM_GetColorFromString (palette, am_ovgridcolor.cstring());
571 XHairColor = AM_GetColorFromString (palette, am_ovxhaircolor.cstring());
572 NotSeenColor = AM_GetColorFromString (palette, am_ovnotseencolor.cstring());
573 LockedColor = AM_GetColorFromString (palette, am_ovlockedcolor.cstring());
574 ExitColor = AM_GetColorFromString (palette, am_ovexitcolor.cstring());
575 TeleportColor = AM_GetColorFromString (palette, am_ovteleportcolor.cstring());
576 }
577 else if (am_usecustomcolors || (overlayed && am_ovshare))
578 {
579 /* Use the custom colors in the am_* cvars */
580 Background = AM_GetColorFromString(palette, am_backcolor.cstring());
581 YourColor = AM_GetColorFromString(palette, am_yourcolor.cstring());
582 SecretWallColor =
583 WallColor = AM_GetColorFromString(palette, am_wallcolor.cstring());
584 TSWallColor = AM_GetColorFromString(palette, am_tswallcolor.cstring());
585 FDWallColor = AM_GetColorFromString(palette, am_fdwallcolor.cstring());
586 CDWallColor = AM_GetColorFromString(palette, am_cdwallcolor.cstring());
587 ThingColor = AM_GetColorFromString(palette, am_thingcolor.cstring());
588 GridColor = AM_GetColorFromString(palette, am_gridcolor.cstring());
589 XHairColor = AM_GetColorFromString(palette, am_xhaircolor.cstring());
590 NotSeenColor = AM_GetColorFromString(palette, am_notseencolor.cstring());
591 LockedColor = AM_GetColorFromString(palette, am_lockedcolor.cstring());
592 ExitColor = AM_GetColorFromString(palette, am_exitcolor.cstring());
593 TeleportColor = AM_GetColorFromString(palette, am_teleportcolor.cstring());
594 {
595 argb_t ba = AM_GetColorFromString(palette, am_backcolor.cstring()).rgb;
596 int r = RPART(ba) - 16;
597 int g = GPART(ba) - 16;
598 int b = BPART(ba) - 16;
599 if (r < 0) r += 32;
600 if (g < 0) g += 32;
601 if (b < 0) b += 32;
602 AlmostBackground.rgb = MAKERGB(r,g,b);
603 AlmostBackground.index = BestColor2(palette, AlmostBackground.rgb, 256);
604 }
605 }
606 else
607 {
608 /* Use colors corresponding to the original Doom's */
609 Background = AM_GetColorFromString(palette, "00 00 00");
610 YourColor = AM_GetColorFromString(palette, "FF FF FF");
611 AlmostBackground = AM_GetColorFromString(palette, "10 10 10");
612 SecretWallColor =
613 WallColor = AM_GetColorFromString(palette, "fc 00 00");
614 TSWallColor = AM_GetColorFromString(palette, "80 80 80");
615 FDWallColor = AM_GetColorFromString(palette, "bc 78 48");
616 LockedColor = AM_GetColorFromString(palette, "fc fc 00");
617 CDWallColor = AM_GetColorFromString(palette, "fc fc 00");
618 ThingColor = AM_GetColorFromString(palette, "74 fc 6c");
619 GridColor = AM_GetColorFromString(palette, "4c 4c 4c");
620 XHairColor = AM_GetColorFromString(palette, "80 80 80");
621 NotSeenColor = AM_GetColorFromString(palette, "6c 6c 6c");
622 }
623 }
624
625 //
626 //
627 //
AM_loadPics(void)628 void AM_loadPics(void)
629 {
630 int i;
631 char namebuf[9];
632
633 for (i = 0; i < 10; i++)
634 {
635 sprintf(namebuf, "AMMNUM%d", i);
636 marknums[i] = W_CachePatch (namebuf, PU_STATIC);
637 }
638 }
639
AM_unloadPics(void)640 void AM_unloadPics(void)
641 {
642 int i;
643
644 for (i = 0; i < 10; i++)
645 {
646 if (marknums[i])
647 {
648 Z_ChangeTag (marknums[i], PU_CACHE);
649 marknums[i] = NULL;
650 }
651 }
652 }
653
AM_clearMarks(void)654 void AM_clearMarks(void)
655 {
656 int i;
657
658 for (i = AM_NUMMARKPOINTS-1; i >= 0; i--)
659 markpoints[i].x = -1; // means empty
660 markpointnum = 0;
661 }
662
663 //
664 // should be called at the start of every level
665 // right now, i figure it out myself
666 //
AM_LevelInit(void)667 void AM_LevelInit(void)
668 {
669 leveljuststarted = 0;
670
671 AM_clearMarks();
672
673 AM_findMinMaxBoundaries();
674 scale_mtof = FixedDiv(min_scale_mtof, (int) (0.7*FRACUNIT));
675 if (scale_mtof > max_scale_mtof)
676 scale_mtof = min_scale_mtof;
677 scale_ftom = FixedDiv(FRACUNIT, scale_mtof);
678 }
679
680
681
682
683 //
684 //
685 //
AM_Stop(void)686 void AM_Stop (void)
687 {
688 static event_t st_notify = { ev_keyup, AM_MSGEXITED, 0, 0 };
689
690 if (!automapactive)
691 {
692 return;
693 }
694
695 AM_unloadPics ();
696 automapactive = false;
697 ST_Responder (&st_notify);
698 stopped = true;
699 viewactive = true;
700 }
701
702 //
703 //
704 //
AM_Start(void)705 void AM_Start (void)
706 {
707 static char lastmap[8] = "";
708
709 if (!stopped) AM_Stop();
710 stopped = false;
711 if (strncmp (lastmap, level.mapname, 8))
712 {
713 AM_LevelInit();
714 strncpy (lastmap, level.mapname, 8);
715 }
716 AM_initVariables();
717 AM_loadPics();
718 }
719
720 //
721 // set the window scale to the maximum size
722 //
AM_minOutWindowScale(void)723 void AM_minOutWindowScale(void)
724 {
725 scale_mtof = min_scale_mtof;
726 scale_ftom = FixedDiv(FRACUNIT, scale_mtof);
727 }
728
729 //
730 // set the window scale to the minimum size
731 //
AM_maxOutWindowScale(void)732 void AM_maxOutWindowScale(void)
733 {
734 scale_mtof = max_scale_mtof;
735 scale_ftom = FixedDiv(FRACUNIT, scale_mtof);
736 }
737
738
BEGIN_COMMAND(togglemap)739 BEGIN_COMMAND (togglemap)
740 {
741 if (gamestate != GS_LEVEL)
742 return;
743
744 if (!automapactive)
745 {
746 AM_Start ();
747 if (am_overlay)
748 viewactive = true;
749 else
750 viewactive = false;
751 }
752 else
753 {
754 if (am_overlay > 0 && am_overlay < 3 && viewactive)
755 {
756 viewactive = false;
757 }
758 else
759 {
760 AM_Stop ();
761 }
762 }
763
764 if (automapactive)
765 AM_initColors (viewactive);
766 }
END_COMMAND(togglemap)767 END_COMMAND (togglemap)
768
769 //
770 // Handle events (user inputs) in automap mode
771 //
772 BOOL AM_Responder (event_t *ev)
773 {
774 int rc;
775 static int bigstate = 0;
776
777 rc = false;
778
779 if (automapactive && ev->type == ev_keydown)
780 {
781 rc = true;
782 switch(ev->data1)
783 {
784 case AM_PANRIGHTKEY: // pan right
785 if (!followplayer)
786 m_paninc.x = FTOM(F_PANINC);
787 else
788 rc = false;
789 break;
790 case AM_PANLEFTKEY: // pan left
791 if (!followplayer)
792 m_paninc.x = -FTOM(F_PANINC);
793 else
794 rc = false;
795 break;
796 case AM_PANUPKEY: // pan up
797 if (!followplayer)
798 m_paninc.y = FTOM(F_PANINC);
799 else
800 rc = false;
801 break;
802 case AM_PANDOWNKEY: // pan down
803 if (!followplayer)
804 m_paninc.y = -FTOM(F_PANINC);
805 else
806 rc = false;
807 break;
808 case AM_ZOOMOUTKEY: // zoom out
809 case AM_ZOOMOUTKEY2:
810 mtof_zoommul = M_ZOOMOUT;
811 ftom_zoommul = M_ZOOMIN;
812 break;
813 case AM_ZOOMINKEY: // zoom in
814 case AM_ZOOMINKEY2:
815 mtof_zoommul = M_ZOOMIN;
816 ftom_zoommul = M_ZOOMOUT;
817 break;
818 case AM_GOBIGKEY:
819 bigstate = !bigstate;
820 if (bigstate)
821 {
822 AM_saveScaleAndLoc();
823 AM_minOutWindowScale();
824 }
825 else
826 AM_restoreScaleAndLoc();
827 break;
828 default:
829 switch (ev->data2)
830 {
831 case AM_FOLLOWKEY:
832 followplayer = !followplayer;
833 f_oldloc.x = MAXINT;
834 Printf (PRINT_HIGH, "%s\n", followplayer ? GStrings(AMSTR_FOLLOWON) : GStrings(AMSTR_FOLLOWOFF));
835 break;
836 case AM_GRIDKEY:
837 grid = !grid;
838 Printf (PRINT_HIGH, "%s\n", grid ? GStrings(AMSTR_GRIDON) : GStrings(AMSTR_GRIDOFF));
839 break;
840 case AM_MARKKEY:
841 Printf (PRINT_HIGH, "%s %d\n", GStrings(AMSTR_MARKEDSPOT), markpointnum);
842 AM_addMark();
843 break;
844 case AM_CLEARMARKKEY:
845 AM_clearMarks();
846 Printf (PRINT_HIGH, "%s\n", GStrings(AMSTR_MARKSCLEARED));
847 break;
848 default:
849 rc = false;
850 }
851 }
852 if (sv_gametype == GM_COOP && cht_CheckCheat(&cheat_amap, (char)ev->data2))
853 {
854 rc = true; // [RH] Eat last keypress of cheat sequence
855 cheating = (cheating+1) % 3;
856 }
857 }
858 else if (ev->type == ev_keyup)
859 {
860 rc = false;
861 switch (ev->data1)
862 {
863 case AM_PANRIGHTKEY:
864 if (!followplayer) m_paninc.x = 0;
865 break;
866 case AM_PANLEFTKEY:
867 if (!followplayer) m_paninc.x = 0;
868 break;
869 case AM_PANUPKEY:
870 if (!followplayer) m_paninc.y = 0;
871 break;
872 case AM_PANDOWNKEY:
873 if (!followplayer) m_paninc.y = 0;
874 break;
875 case AM_ZOOMOUTKEY:
876 case AM_ZOOMOUTKEY2:
877 case AM_ZOOMINKEY:
878 case AM_ZOOMINKEY2:
879 mtof_zoommul = FRACUNIT;
880 ftom_zoommul = FRACUNIT;
881 break;
882 }
883 }
884
885 return rc;
886 }
887
888
889 //
890 // Zooming
891 //
AM_changeWindowScale(void)892 void AM_changeWindowScale (void)
893 {
894 // Change the scaling multipliers
895 scale_mtof = FixedMul(scale_mtof, mtof_zoommul);
896 scale_ftom = FixedDiv(FRACUNIT, scale_mtof);
897
898 if (scale_mtof < min_scale_mtof)
899 AM_minOutWindowScale();
900 else if (scale_mtof > max_scale_mtof)
901 AM_maxOutWindowScale();
902 }
903
904
905 //
906 //
907 //
AM_doFollowPlayer(void)908 void AM_doFollowPlayer(void)
909 {
910 player_t &p = displayplayer();
911
912 if (f_oldloc.x != p.camera->x ||
913 f_oldloc.y != p.camera->y)
914 {
915 m_x = FTOM(MTOF(p.camera->x)) - m_w/2;
916 m_y = FTOM(MTOF(p.camera->y)) - m_h/2;
917 m_x2 = m_x + m_w;
918 m_y2 = m_y + m_h;
919 f_oldloc.x = p.camera->x;
920 f_oldloc.y = p.camera->y;
921 }
922 }
923
924 //
925 // Updates on Game Tick
926 //
AM_Ticker(void)927 void AM_Ticker (void)
928 {
929 if (!automapactive)
930 return;
931
932 amclock++;
933
934 if (followplayer)
935 AM_doFollowPlayer();
936
937 // Change the zoom if necessary
938 if (ftom_zoommul != FRACUNIT)
939 AM_changeWindowScale();
940
941 // Change x,y location
942 if (m_paninc.x || m_paninc.y)
943 AM_changeWindowLoc();
944
945 // NES - Glowing effect on locked doors.
946 if (lockglow < 90)
947 lockglow++;
948 else
949 lockglow = 0;
950
951 }
952
953
954 //
955 // Clear automap frame buffer.
956 //
AM_clearFB(am_color_t color)957 void AM_clearFB (am_color_t color)
958 {
959 int y;
960
961 if (screen->is8bit()) {
962 if (f_w == f_p)
963 memset (fb, color.index, f_w*f_h);
964 else
965 for (y = 0; y < f_h; y++)
966 memset (fb + y * f_p, color.index, f_w);
967 } else {
968 int x;
969 argb_t *line;
970
971 line = (argb_t *)(fb);
972 for (y = 0; y < f_h; y++) {
973 for (x = 0; x < f_w; x++) {
974 line[x] = color.rgb;
975 }
976 line += f_p >> 2;
977 }
978 }
979 }
980
981
982 //
983 // Automap clipping of lines.
984 //
985 // Based on Cohen-Sutherland clipping algorithm but with a slightly
986 // faster reject and precalculated slopes. If the speed is needed,
987 // use a hash algorithm to handle the common cases.
988 //
AM_clipMline(mline_t * ml,fline_t * fl)989 BOOL AM_clipMline (mline_t *ml, fline_t *fl)
990 {
991 enum {
992 LEFT =1,
993 RIGHT =2,
994 BOTTOM =4,
995 TOP =8
996 };
997
998 register int outcode1 = 0;
999 register int outcode2 = 0;
1000 register int outside;
1001
1002 fpoint_t tmp = {0, 0};
1003 int dx;
1004 int dy;
1005
1006
1007 #define DOOUTCODE(oc, mx, my) \
1008 (oc) = 0; \
1009 if ((my) < 0) (oc) |= TOP; \
1010 else if ((my) >= f_h) (oc) |= BOTTOM; \
1011 if ((mx) < 0) (oc) |= LEFT; \
1012 else if ((mx) >= f_w) (oc) |= RIGHT;
1013
1014 // do trivial rejects and outcodes
1015 if (ml->a.y > m_y2)
1016 outcode1 = TOP;
1017 else if (ml->a.y < m_y)
1018 outcode1 = BOTTOM;
1019
1020 if (ml->b.y > m_y2)
1021 outcode2 = TOP;
1022 else if (ml->b.y < m_y)
1023 outcode2 = BOTTOM;
1024
1025 if (outcode1 & outcode2)
1026 return false; // trivially outside
1027
1028 if (ml->a.x < m_x)
1029 outcode1 |= LEFT;
1030 else if (ml->a.x > m_x2)
1031 outcode1 |= RIGHT;
1032
1033 if (ml->b.x < m_x)
1034 outcode2 |= LEFT;
1035 else if (ml->b.x > m_x2)
1036 outcode2 |= RIGHT;
1037
1038 if (outcode1 & outcode2)
1039 return false; // trivially outside
1040
1041 // transform to frame-buffer coordinates.
1042 fl->a.x = CXMTOF(ml->a.x);
1043 fl->a.y = CYMTOF(ml->a.y);
1044 fl->b.x = CXMTOF(ml->b.x);
1045 fl->b.y = CYMTOF(ml->b.y);
1046
1047 DOOUTCODE(outcode1, fl->a.x, fl->a.y);
1048 DOOUTCODE(outcode2, fl->b.x, fl->b.y);
1049
1050 if (outcode1 & outcode2)
1051 return false;
1052
1053 while (outcode1 | outcode2) {
1054 // may be partially inside box
1055 // find an outside point
1056 if (outcode1)
1057 outside = outcode1;
1058 else
1059 outside = outcode2;
1060
1061 // clip to each side
1062 if (outside & TOP) {
1063 dy = fl->a.y - fl->b.y;
1064 dx = fl->b.x - fl->a.x;
1065 tmp.x = fl->a.x + (dx*(fl->a.y))/dy;
1066 tmp.y = 0;
1067 } else if (outside & BOTTOM) {
1068 dy = fl->a.y - fl->b.y;
1069 dx = fl->b.x - fl->a.x;
1070 tmp.x = fl->a.x + (dx*(fl->a.y-f_h))/dy;
1071 tmp.y = f_h-1;
1072 } else if (outside & RIGHT) {
1073 dy = fl->b.y - fl->a.y;
1074 dx = fl->b.x - fl->a.x;
1075 tmp.y = fl->a.y + (dy*(f_w-1 - fl->a.x))/dx;
1076 tmp.x = f_w-1;
1077 } else if (outside & LEFT) {
1078 dy = fl->b.y - fl->a.y;
1079 dx = fl->b.x - fl->a.x;
1080 tmp.y = fl->a.y + (dy*(-fl->a.x))/dx;
1081 tmp.x = 0;
1082 }
1083
1084 if (outside == outcode1) {
1085 fl->a = tmp;
1086 DOOUTCODE(outcode1, fl->a.x, fl->a.y);
1087 } else {
1088 fl->b = tmp;
1089 DOOUTCODE(outcode2, fl->b.x, fl->b.y);
1090 }
1091
1092 if (outcode1 & outcode2)
1093 return false; // trivially outside
1094 }
1095
1096 return true;
1097 }
1098 #undef DOOUTCODE
1099
1100
1101 //
1102 // Classic Bresenham w/ whatever optimizations needed for speed
1103 //
1104
1105 // Palettized (8bpp) version:
1106
AM_drawFlineP(fline_t * fl,byte color)1107 void AM_drawFlineP (fline_t* fl, byte color)
1108 {
1109 register int x;
1110 register int y;
1111 register int dx;
1112 register int dy;
1113 register int sx;
1114 register int sy;
1115 register int ax;
1116 register int ay;
1117 register int d;
1118
1119
1120 fl->a.x += f_x;
1121 fl->b.x += f_x;
1122 fl->a.y += f_y;
1123 fl->b.y += f_y;
1124
1125 dx = fl->b.x - fl->a.x;
1126 ax = 2 * (dx<0 ? -dx : dx);
1127 sx = dx<0 ? -1 : 1;
1128
1129 dy = fl->b.y - fl->a.y;
1130 ay = 2 * (dy<0 ? -dy : dy);
1131 sy = dy<0 ? -1 : 1;
1132
1133 x = fl->a.x;
1134 y = fl->a.y;
1135
1136 if (ax > ay) {
1137 d = ay - ax/2;
1138
1139 while (1) {
1140 PUTDOTP(x,y,(byte)color);
1141 if (x == fl->b.x)
1142 return;
1143 if (d >= 0)
1144 {
1145 y += sy;
1146 d -= ax;
1147 }
1148 x += sx;
1149 d += ay;
1150 }
1151 }
1152 else
1153 {
1154 d = ax - ay/2;
1155 while (1) {
1156 PUTDOTP(x, y, (byte)color);
1157 if (y == fl->b.y)
1158 return;
1159 if (d >= 0)
1160 {
1161 x += sx;
1162 d -= ay;
1163 }
1164 y += sy;
1165 d += ax;
1166 }
1167 }
1168 }
1169
1170 // Direct (32bpp) version:
1171
AM_drawFlineD(fline_t * fl,argb_t color)1172 void AM_drawFlineD(fline_t* fl, argb_t color)
1173 {
1174 register int x;
1175 register int y;
1176 register int dx;
1177 register int dy;
1178 register int sx;
1179 register int sy;
1180 register int ax;
1181 register int ay;
1182 register int d;
1183
1184 fl->a.x += f_x;
1185 fl->b.x += f_x;
1186 fl->a.y += f_y;
1187 fl->b.y += f_y;
1188
1189 dx = fl->b.x - fl->a.x;
1190 ax = 2 * (dx<0 ? -dx : dx);
1191 sx = dx<0 ? -1 : 1;
1192
1193 dy = fl->b.y - fl->a.y;
1194 ay = 2 * (dy<0 ? -dy : dy);
1195 sy = dy<0 ? -1 : 1;
1196
1197 x = fl->a.x;
1198 y = fl->a.y;
1199
1200 if (ax > ay) {
1201 d = ay - ax/2;
1202
1203 while (1) {
1204 PUTDOTD(x, y, color);
1205 if (x == fl->b.x)
1206 return;
1207 if (d >= 0)
1208 {
1209 y += sy;
1210 d -= ax;
1211 }
1212 x += sx;
1213 d += ay;
1214 }
1215 }
1216 else
1217 {
1218 d = ax - ay/2;
1219 while (1) {
1220 PUTDOTD(x, y, color);
1221 if (y == fl->b.y)
1222 return;
1223 if (d >= 0)
1224 {
1225 x += sx;
1226 d -= ay;
1227 }
1228 y += sy;
1229 d += ax;
1230 }
1231 }
1232 }
1233
1234
1235 //
1236 // Clip lines, draw visible part sof lines.
1237 //
AM_drawMline(mline_t * ml,am_color_t color)1238 void AM_drawMline (mline_t* ml, am_color_t color)
1239 {
1240 static fline_t fl;
1241
1242 if (AM_clipMline(ml, &fl))
1243 {
1244 // draws it on frame buffer using fb coords
1245 if (screen->is8bit())
1246 AM_drawFlineP(&fl, color.index);
1247 else
1248 AM_drawFlineD(&fl, color.rgb);
1249 }
1250 }
1251
1252
1253
1254 //
1255 // Draws flat (floor/ceiling tile) aligned grid lines.
1256 //
AM_drawGrid(am_color_t color)1257 void AM_drawGrid(am_color_t color)
1258 {
1259 fixed_t x, y;
1260 fixed_t start, end;
1261 mline_t ml;
1262
1263 // Figure out start of vertical gridlines
1264 start = m_x;
1265 if ((start-bmaporgx)%(MAPBLOCKUNITS<<FRACBITS))
1266 start += (MAPBLOCKUNITS<<FRACBITS)
1267 - ((start-bmaporgx)%(MAPBLOCKUNITS<<FRACBITS));
1268 end = m_x + m_w;
1269
1270 // draw vertical gridlines
1271 ml.a.y = m_y;
1272 ml.b.y = m_y+m_h;
1273 for (x=start; x<end; x+=(MAPBLOCKUNITS<<FRACBITS)) {
1274 ml.a.x = x;
1275 ml.b.x = x;
1276 if (am_rotate) {
1277 AM_rotatePoint (&ml.a.x, &ml.a.y);
1278 AM_rotatePoint (&ml.b.x, &ml.b.y);
1279 }
1280 AM_drawMline(&ml, color);
1281 }
1282
1283 // Figure out start of horizontal gridlines
1284 start = m_y;
1285 if ((start-bmaporgy)%(MAPBLOCKUNITS<<FRACBITS))
1286 start += (MAPBLOCKUNITS<<FRACBITS)
1287 - ((start-bmaporgy)%(MAPBLOCKUNITS<<FRACBITS));
1288 end = m_y + m_h;
1289
1290 // draw horizontal gridlines
1291 ml.a.x = m_x;
1292 ml.b.x = m_x + m_w;
1293 for (y=start; y<end; y+=(MAPBLOCKUNITS<<FRACBITS)) {
1294 ml.a.y = y;
1295 ml.b.y = y;
1296 if (am_rotate) {
1297 AM_rotatePoint (&ml.a.x, &ml.a.y);
1298 AM_rotatePoint (&ml.b.x, &ml.b.y);
1299 }
1300 AM_drawMline(&ml, color);
1301 }
1302 }
1303
1304 //
1305 // Determines visible lines, draws them.
1306 // This is LineDef based, not LineSeg based.
1307 //
AM_drawWalls(void)1308 void AM_drawWalls(void)
1309 {
1310 int i, r, g, b;
1311 static mline_t l;
1312 float rdif, gdif, bdif;
1313 palette_t *pal = GetDefaultPalette();
1314
1315
1316 for (i=0;i<numlines;i++) {
1317 l.a.x = lines[i].v1->x;
1318 l.a.y = lines[i].v1->y;
1319 l.b.x = lines[i].v2->x;
1320 l.b.y = lines[i].v2->y;
1321
1322 if (am_rotate) {
1323 AM_rotatePoint (&l.a.x, &l.a.y);
1324 AM_rotatePoint (&l.b.x, &l.b.y);
1325 }
1326
1327 if (cheating || (lines[i].flags & ML_MAPPED))
1328 {
1329 if ((lines[i].flags & ML_DONTDRAW) && !cheating)
1330 continue;
1331 if (!lines[i].backsector &&
1332 (((am_usecustomcolors || viewactive) &&
1333 lines[i].special != Exit_Normal &&
1334 lines[i].special != Exit_Secret) ||
1335 (!am_usecustomcolors && !viewactive)))
1336 {
1337 AM_drawMline(&l, WallColor);
1338 }
1339 else
1340 {
1341 if ((lines[i].special == Teleport ||
1342 lines[i].special == Teleport_NoFog ||
1343 lines[i].special == Teleport_Line) &&
1344 (am_usecustomcolors || viewactive))
1345 { // teleporters
1346 AM_drawMline(&l, TeleportColor);
1347 }
1348 else if ((lines[i].special == Teleport_NewMap ||
1349 lines[i].special == Teleport_EndGame ||
1350 lines[i].special == Exit_Normal ||
1351 lines[i].special == Exit_Secret) &&
1352 (am_usecustomcolors || viewactive))
1353 { // exit
1354 AM_drawMline(&l, ExitColor);
1355 }
1356 else if (lines[i].flags & ML_SECRET)
1357 { // secret door
1358 if (cheating)
1359 AM_drawMline(&l, SecretWallColor);
1360 else
1361 AM_drawMline(&l, WallColor);
1362 }
1363 else if (lines[i].special == Door_LockedRaise)
1364 {
1365 // NES - Locked doors glow from a predefined color to either blue, yellow, or red.
1366 r = RPART(LockedColor.rgb), g = GPART(LockedColor.rgb), b = BPART(LockedColor.rgb);
1367
1368 if (am_usecustomcolors) {
1369 if (lines[i].args[3] == (BCard | CardIsSkull)) {
1370 rdif = (0 - r)/30;
1371 gdif = (0 - g)/30;
1372 bdif = (255 - b)/30;
1373 } else if (lines[i].args[3] == (YCard | CardIsSkull)) {
1374 rdif = (255 - r)/30;
1375 gdif = (255 - g)/30;
1376 bdif = (0 - b)/30;
1377 } else {
1378 rdif = (255 - r)/30;
1379 gdif = (0 - g)/30;
1380 bdif = (0 - b)/30;
1381 }
1382
1383 if (lockglow < 30) {
1384 AM_drawMline (&l, AM_BestColor (pal->basecolors, r + ((int)rdif*lockglow),
1385 g + ((int)gdif*lockglow), b + ((int)bdif*lockglow),
1386 pal->numcolors));
1387 } else if (lockglow < 60) {
1388 AM_drawMline (&l, AM_BestColor (pal->basecolors, r + ((int)rdif*(60-lockglow)),
1389 g + ((int)gdif*(60-lockglow)), b + ((int)bdif*(60-lockglow)),
1390 pal->numcolors));
1391 } else {
1392 AM_drawMline (&l, AM_BestColor (pal->basecolors, r, g, b,
1393 pal->numcolors));
1394 }
1395 } else {
1396 AM_drawMline (&l, AM_BestColor (pal->basecolors, r, g, b,
1397 pal->numcolors));
1398 }
1399 }
1400 else if (lines[i].backsector->floorheight
1401 != lines[i].frontsector->floorheight)
1402 {
1403 AM_drawMline(&l, FDWallColor); // floor level change
1404 }
1405 else if (lines[i].backsector->ceilingheight
1406 != lines[i].frontsector->ceilingheight)
1407 {
1408 AM_drawMline(&l, CDWallColor); // ceiling level change
1409 }
1410 else if (cheating)
1411 {
1412 AM_drawMline(&l, TSWallColor);
1413 }
1414 }
1415 }
1416 else if (consoleplayer().powers[pw_allmap])
1417 {
1418 if (!(lines[i].flags & ML_DONTDRAW))
1419 AM_drawMline(&l, NotSeenColor);
1420 }
1421 }
1422 }
1423
1424
1425 //
1426 // Rotation in 2D.
1427 // Used to rotate player arrow line character.
1428 //
1429 void
AM_rotate(fixed_t * x,fixed_t * y,angle_t a)1430 AM_rotate
1431 ( fixed_t* x,
1432 fixed_t* y,
1433 angle_t a )
1434 {
1435 fixed_t tmpx;
1436
1437 tmpx =
1438 FixedMul(*x,finecosine[a>>ANGLETOFINESHIFT])
1439 - FixedMul(*y,finesine[a>>ANGLETOFINESHIFT]);
1440
1441 *y =
1442 FixedMul(*x,finesine[a>>ANGLETOFINESHIFT])
1443 + FixedMul(*y,finecosine[a>>ANGLETOFINESHIFT]);
1444
1445 *x = tmpx;
1446 }
1447
AM_rotatePoint(fixed_t * x,fixed_t * y)1448 void AM_rotatePoint (fixed_t *x, fixed_t *y)
1449 {
1450 player_t &p = displayplayer();
1451
1452 *x -= p.camera->x;
1453 *y -= p.camera->y;
1454 AM_rotate (x, y, ANG90 - p.camera->angle);
1455 *x += p.camera->x;
1456 *y += p.camera->y;
1457 }
1458
1459 void
AM_drawLineCharacter(mline_t * lineguy,int lineguylines,fixed_t scale,angle_t angle,am_color_t color,fixed_t x,fixed_t y)1460 AM_drawLineCharacter
1461 ( mline_t* lineguy,
1462 int lineguylines,
1463 fixed_t scale,
1464 angle_t angle,
1465 am_color_t color,
1466 fixed_t x,
1467 fixed_t y )
1468 {
1469 int i;
1470 mline_t l;
1471
1472 for (i=0;i<lineguylines;i++) {
1473 l.a.x = lineguy[i].a.x;
1474 l.a.y = lineguy[i].a.y;
1475
1476 if (scale) {
1477 l.a.x = FixedMul(scale, l.a.x);
1478 l.a.y = FixedMul(scale, l.a.y);
1479 }
1480
1481 if (angle)
1482 AM_rotate(&l.a.x, &l.a.y, angle);
1483
1484 l.a.x += x;
1485 l.a.y += y;
1486
1487 l.b.x = lineguy[i].b.x;
1488 l.b.y = lineguy[i].b.y;
1489
1490 if (scale) {
1491 l.b.x = FixedMul(scale, l.b.x);
1492 l.b.y = FixedMul(scale, l.b.y);
1493 }
1494
1495 if (angle)
1496 AM_rotate(&l.b.x, &l.b.y, angle);
1497
1498 l.b.x += x;
1499 l.b.y += y;
1500
1501 AM_drawMline(&l, color);
1502 }
1503 }
1504
AM_drawPlayers(void)1505 void AM_drawPlayers(void)
1506 {
1507 angle_t angle;
1508 player_t &conplayer = displayplayer();
1509 argb_t *palette;
1510 palette = GetDefaultPalette()->colors;
1511
1512 if (!multiplayer)
1513 {
1514 if (am_rotate)
1515 angle = ANG90;
1516 else
1517 angle = conplayer.camera->angle;
1518
1519 if (cheating)
1520 AM_drawLineCharacter
1521 (cheat_player_arrow, NUMCHEATPLYRLINES, 0,
1522 angle, YourColor, conplayer.camera->x, conplayer.camera->y);
1523 else
1524 AM_drawLineCharacter
1525 (player_arrow, NUMPLYRLINES, 0, angle,
1526 YourColor, conplayer.camera->x, conplayer.camera->y);
1527 return;
1528 }
1529
1530 for (Players::iterator it = players.begin();it != players.end();++it)
1531 {
1532 player_t *p = &*it;
1533 am_color_t color;
1534 mpoint_t pt;
1535
1536 if (!(it->ingame()) || !p->mo ||
1537 (((sv_gametype == GM_DM && p != &conplayer) ||
1538 ((sv_gametype == GM_TEAMDM || sv_gametype == GM_CTF) && p->userinfo.team != conplayer.userinfo.team))
1539 && !(netdemo.isPlaying() || netdemo.isPaused())
1540 && !demoplayback && !(conplayer.spectator)) || p->spectator)
1541 {
1542 continue;
1543 }
1544
1545 if (p->powers[pw_invisibility])
1546 color = AlmostBackground;
1547 else if (demoplayback && democlassic) {
1548 switch (it->id) {
1549 case 1: color = AM_GetColorFromString (palette, "00 FF 00"); break;
1550 case 2: color = AM_GetColorFromString (palette, "60 60 B0"); break;
1551 case 3: color = AM_GetColorFromString (palette, "B0 B0 30"); break;
1552 case 4: color = AM_GetColorFromString (palette, "C0 00 00"); break;
1553 default: break;
1554 }
1555 } else {
1556 int playercolor = CL_GetPlayerColor(p);
1557 color.rgb = (argb_t)playercolor;
1558 color.index = BestColor (GetDefaultPalette()->basecolors,
1559 RPART(playercolor),
1560 GPART(playercolor),
1561 BPART(playercolor),
1562 GetDefaultPalette()->numcolors);
1563 }
1564
1565 pt.x = p->mo->x;
1566 pt.y = p->mo->y;
1567 angle = p->mo->angle;
1568
1569 if (am_rotate)
1570 {
1571 AM_rotatePoint (&pt.x, &pt.y);
1572 angle -= conplayer.camera->angle - ANG90;
1573 }
1574
1575 AM_drawLineCharacter
1576 (player_arrow, NUMPLYRLINES, 0, angle,
1577 color, pt.x, pt.y);
1578 }
1579 }
1580
AM_drawThings(am_color_t color)1581 void AM_drawThings (am_color_t color)
1582 {
1583 int i;
1584 AActor* t;
1585 mpoint_t p;
1586 angle_t angle;
1587
1588 for (i=0;i<numsectors;i++)
1589 {
1590 t = sectors[i].thinglist;
1591 while (t)
1592 {
1593 p.x = t->x;
1594 p.y = t->y;
1595 angle = t->angle;
1596
1597 if (am_rotate)
1598 {
1599 AM_rotatePoint (&p.x, &p.y);
1600 angle += ANG90 - displayplayer().camera->angle;
1601 }
1602
1603 AM_drawLineCharacter(thintriangle_guy, NUMTHINTRIANGLEGUYLINES, 16<<FRACBITS, angle, color, p.x, p.y);
1604 t = t->snext;
1605 }
1606 }
1607 }
1608
AM_drawMarks(void)1609 void AM_drawMarks (void)
1610 {
1611 int i, fx, fy, w, h;
1612 mpoint_t pt;
1613
1614 for (i = 0; i < AM_NUMMARKPOINTS; i++)
1615 {
1616 if (markpoints[i].x != -1)
1617 {
1618 // w = LESHORT(marknums[i]->width);
1619 // h = LESHORT(marknums[i]->height);
1620 w = 5; // because something's wrong with the wad, i guess
1621 h = 6; // because something's wrong with the wad, i guess
1622
1623 pt.x = markpoints[i].x;
1624 pt.y = markpoints[i].y;
1625
1626 if (am_rotate)
1627 AM_rotatePoint (&pt.x, &pt.y);
1628
1629 fx = CXMTOF(pt.x);
1630 fy = CYMTOF(pt.y) - 3;
1631
1632 if (fx >= f_x && fx <= f_w - w && fy >= f_y && fy <= f_h - h)
1633 FB->DrawPatchCleanNoMove (marknums[i], fx, fy);
1634 }
1635 }
1636 }
1637
AM_drawCrosshair(am_color_t color)1638 void AM_drawCrosshair (am_color_t color)
1639 {
1640 // single point for now
1641 if (screen->is8bit())
1642 {
1643 PUTDOTP(f_w/2, (f_h+1)/2, (byte)color.index);
1644 }
1645 else
1646 {
1647 PUTDOTD(f_w/2, (f_h+1)/2, color.rgb);
1648 }
1649 }
1650
AM_Drawer(void)1651 void AM_Drawer (void)
1652 {
1653 if (!automapactive)
1654 return;
1655
1656 fb = screen->buffer;
1657 if (!viewactive)
1658 {
1659 // [RH] Set f_? here now to handle automap overlaying
1660 // and view size adjustments.
1661 f_x = f_y = 0;
1662 f_w = screen->width;
1663 f_h = ST_Y;
1664 f_p = screen->pitch;
1665
1666 AM_clearFB(Background);
1667 }
1668 else
1669 {
1670 f_x = viewwindowx;
1671 f_y = viewwindowy;
1672 f_w = realviewwidth;
1673 f_h = realviewheight;
1674 f_p = screen->pitch;
1675 }
1676 AM_activateNewScale();
1677
1678 if (grid)
1679 AM_drawGrid(GridColor);
1680
1681 AM_drawWalls();
1682 AM_drawPlayers();
1683 if (cheating==2)
1684 AM_drawThings(ThingColor);
1685
1686 if (!(viewactive && am_overlay < 2))
1687 AM_drawCrosshair(XHairColor);
1688
1689 AM_drawMarks();
1690
1691 if (!(viewactive && am_overlay < 2)) {
1692
1693 char line[64+10];
1694 int OV_Y, i, time = level.time / TICRATE, height;
1695
1696 height = (hu_font[0]->height() + 1) * CleanYfac;
1697 OV_Y = screen->height - ((32 * screen->height) / 200);
1698
1699 if (sv_gametype == GM_COOP)
1700 {
1701 if (am_showmonsters)
1702 {
1703 sprintf (line, TEXTCOLOR_RED "MONSTERS:"
1704 TEXTCOLOR_NORMAL " %d / %d",
1705 level.killed_monsters, level.total_monsters);
1706 if (viewactive && screenblocks == 11)
1707 FB->DrawTextClean (CR_GREY, screen->width - V_StringWidth (line) * CleanXfac, OV_Y - (height * 4) + 1, line);
1708 else if (viewactive && screenblocks == 12)
1709 FB->DrawTextClean (CR_GREY, 0, screen->height - (height * 2) + 1, line);
1710 else
1711 FB->DrawTextClean (CR_GREY, 0, ST_Y - (height * 2) + 1, line);
1712 }
1713
1714 if (am_showsecrets)
1715 {
1716 sprintf (line, TEXTCOLOR_RED "SECRETS:"
1717 TEXTCOLOR_NORMAL " %d / %d",
1718 level.found_secrets, level.total_secrets);
1719 if (viewactive && screenblocks == 11)
1720 FB->DrawTextClean (CR_GREY, screen->width - V_StringWidth (line) * CleanXfac, OV_Y - (height * 3) + 1, line);
1721 else if (viewactive && screenblocks == 12)
1722 FB->DrawTextClean (CR_GREY, screen->width - V_StringWidth (line) * CleanXfac, screen->height - (height * 2) + 1, line);
1723 else
1724 FB->DrawTextClean (CR_GREY, screen->width - V_StringWidth (line) * CleanXfac, ST_Y - (height * 2) + 1, line);
1725 }
1726 }
1727
1728 if (am_classicmapstring)
1729 {
1730 int firstmap;
1731 int mapoffset = 1;
1732 switch (gamemission)
1733 {
1734 case doom2:
1735 firstmap = HUSTR_1;
1736 break;
1737 case pack_plut:
1738 firstmap = PHUSTR_1;
1739 break;
1740 case pack_tnt:
1741 firstmap = THUSTR_1;
1742 break;
1743 default:
1744 firstmap = HUSTR_E1M1;
1745 mapoffset = level.cluster; // Episodes skip map numbers.
1746 break;
1747 }
1748 strcpy(line, GStrings(firstmap + level.levelnum - mapoffset));
1749
1750 if (viewactive && screenblocks == 11)
1751 FB->DrawTextClean(CR_RED, screen->width - V_StringWidth (line) * CleanXfac, OV_Y - (height * 1) + 1, line);
1752 else if (viewactive && screenblocks == 12)
1753 FB->DrawTextClean (CR_RED, 0, screen->height - (height * 1) + 1, line);
1754 else
1755 FB->DrawTextClean (CR_RED, 0, ST_Y - (height * 1) + 1, line);
1756 }
1757 else
1758 {
1759 line[0] = '\x8a';
1760 line[1] = CR_RED + 'A';
1761 i = 0;
1762 while (i < 8 && level.mapname[i]) {
1763 line[2 + i] = level.mapname[i];
1764 i++;
1765 }
1766 i += 2;
1767 line[i++] = ':';
1768 line[i++] = ' ';
1769 line[i++] = '\x8a';
1770 line[i++] = '-';
1771 strcpy (&line[i], level.level_name);
1772 if (viewactive && screenblocks == 11)
1773 FB->DrawTextClean (CR_GREY, screen->width - V_StringWidth (line) * CleanXfac, OV_Y - (height * 1) + 1, line);
1774 else if (viewactive && screenblocks == 12)
1775 FB->DrawTextClean (CR_GREY, 0, screen->height - (height * 1) + 1, line);
1776 else
1777 FB->DrawTextClean (CR_GREY, 0, ST_Y - (height * 1) + 1, line);
1778 }
1779
1780 if (am_showtime) {
1781 sprintf (line, " %02d:%02d:%02d", time/3600, (time%3600)/60, time%60); // Time
1782 if (viewactive && screenblocks == 11)
1783 FB->DrawTextClean (CR_RED, screen->width - V_StringWidth (line) * CleanXfac, OV_Y - (height * 2) + 1, line);
1784 else if (viewactive && screenblocks == 12)
1785 FB->DrawTextClean (CR_RED, screen->width - V_StringWidth (line) * CleanXfac, screen->height - (height * 1) + 1, line);
1786 else
1787 FB->DrawTextClean (CR_RED, screen->width - V_StringWidth (line) * CleanXfac, ST_Y - (height * 1) + 1, line);
1788 }
1789
1790 }
1791 }
1792
1793 VERSION_CONTROL (am_map_cpp, "$Id: am_map.cpp 4542 2014-02-09 17:39:42Z dr_sean $")
1794
1795
1796