1 // Emacs style mode select -*- C++ -*-
2 //-----------------------------------------------------------------------------
6 // Copyright (C) 1993-1996 by id Software, Inc.
8 // This source is available for distribution and/or modification
9 // only under the terms of the DOOM Source Code License as
10 // published by id Software. All rights reserved.
12 // The source is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
20 // DESCRIPTION: the automap code
22 //-----------------------------------------------------------------------------
24 static const char rcsid[] = "$Id: am_map.c,v 1.4 1997/02/03 21:24:33 b1 Exp $";
36 // Needs access to LFB.
49 // For use if I do walls with outsides/insides
50 #define REDS (256-5*16)
52 #define BLUES (256-4*16+8)
60 #define YELLOWS (256-32+7)
63 #define WHITE (256-47)
66 #define BACKGROUND BLACK
67 #define YOURCOLORS WHITE
69 #define WALLCOLORS REDS
70 #define WALLRANGE REDRANGE
71 #define TSWALLCOLORS GRAYS
72 #define TSWALLRANGE GRAYSRANGE
73 #define FDWALLCOLORS BROWNS
74 #define FDWALLRANGE BROWNRANGE
75 #define CDWALLCOLORS YELLOWS
76 #define CDWALLRANGE YELLOWRANGE
77 #define THINGCOLORS GREENS
78 //PORTME #define THINGRANGE GREENRANGE
79 #define SECRETWALLCOLORS WALLCOLORS
80 #define SECRETWALLRANGE WALLRANGE
81 #define GRIDCOLORS (GRAYS + GRAYSRANGE/2)
83 #define XHAIRCOLORS GRAYS
88 #define AM_PANDOWNKEY KEY_DOWNARROW
89 #define AM_PANUPKEY KEY_UPARROW
90 #define AM_PANRIGHTKEY KEY_RIGHTARROW
91 #define AM_PANLEFTKEY KEY_LEFTARROW
92 #define AM_ZOOMINKEY '='
93 #define AM_ZOOMOUTKEY '-'
94 #define AM_STARTKEY KEY_TAB
95 #define AM_ENDKEY KEY_TAB
96 #define AM_GOBIGKEY '0'
97 #define AM_FOLLOWKEY 'f'
98 #define AM_GRIDKEY 'g'
99 #define AM_MARKKEY 'm'
100 #define AM_CLEARMARKKEY 'c'
102 #define AM_NUMMARKPOINTS 10
105 #define INITSCALEMTOF (.2*FRACUNIT)
106 // how much the automap moves window per tic in frame-buffer coordinates
107 // moves 140 pixels in 1 second
109 // how much zoom-in per tic
110 // goes to 2x in 1 second
111 #define M_ZOOMIN ((int) (1.02*FRACUNIT))
112 // how much zoom-out per tic
113 // pulls out to 0.5x in 1 second
114 #define M_ZOOMOUT ((int) (FRACUNIT/1.02))
116 // translates between frame-buffer and map distances
117 #define FTOM(x) FixedMul(((x)<<16),scale_ftom)
118 #define MTOF(x) (FixedMul((x),scale_mtof)>>16)
119 // translates between frame-buffer and map coordinates
120 #define CXMTOF(x) (f_x + MTOF((x)-m_x))
121 #define CYMTOF(y) (f_y + (f_h - MTOF((y)-m_y)))
123 // the following is crap
124 #define LINE_NEVERSEE ML_DONTDRAW
154 // The vector graphics for the automap.
155 // A line drawing of the player pointing right,
156 // starting from the middle.
158 #define R ((8*PLAYERRADIUS)/7)
159 mline_t player_arrow[] = {
160 { { -R+R/8, 0 }, { R, 0 } }, // -----
161 { { R, 0 }, { R-R/2, R/4 } }, // ----->
162 { { R, 0 }, { R-R/2, -R/4 } },
163 { { -R+R/8, 0 }, { -R-R/8, R/4 } }, // >---->
164 { { -R+R/8, 0 }, { -R-R/8, -R/4 } },
165 { { -R+3*R/8, 0 }, { -R+R/8, R/4 } }, // >>--->
166 { { -R+3*R/8, 0 }, { -R+R/8, -R/4 } }
169 #define NUMPLYRLINES (sizeof(player_arrow)/sizeof(mline_t))
171 #define R ((8*PLAYERRADIUS)/7)
172 mline_t cheat_player_arrow[] = {
173 { { -R+R/8, 0 }, { R, 0 } }, // -----
174 { { R, 0 }, { R-R/2, R/6 } }, // ----->
175 { { R, 0 }, { R-R/2, -R/6 } },
176 { { -R+R/8, 0 }, { -R-R/8, R/6 } }, // >----->
177 { { -R+R/8, 0 }, { -R-R/8, -R/6 } },
178 { { -R+3*R/8, 0 }, { -R+R/8, R/6 } }, // >>----->
179 { { -R+3*R/8, 0 }, { -R+R/8, -R/6 } },
180 { { -R/2, 0 }, { -R/2, -R/6 } }, // >>-d--->
181 { { -R/2, -R/6 }, { -R/2+R/6, -R/6 } },
182 { { -R/2+R/6, -R/6 }, { -R/2+R/6, R/4 } },
183 { { -R/6, 0 }, { -R/6, -R/6 } }, // >>-dd-->
184 { { -R/6, -R/6 }, { 0, -R/6 } },
185 { { 0, -R/6 }, { 0, R/4 } },
186 { { R/6, R/4 }, { R/6, -R/7 } }, // >>-ddt->
187 { { R/6, -R/7 }, { R/6+R/32, -R/7-R/32 } },
188 { { R/6+R/32, -R/7-R/32 }, { R/6+R/10, -R/7 } }
191 #define NUMCHEATPLYRLINES (sizeof(cheat_player_arrow)/sizeof(mline_t))
194 mline_t triangle_guy[] = {
195 { { -.867*R, -.5*R }, { .867*R, -.5*R } },
196 { { .867*R, -.5*R } , { 0, R } },
197 { { 0, R }, { -.867*R, -.5*R } }
200 #define NUMTRIANGLEGUYLINES (sizeof(triangle_guy)/sizeof(mline_t))
203 mline_t thintriangle_guy[] = {
204 { { -.5*R, -.7*R }, { R, 0 } },
205 { { R, 0 }, { -.5*R, .7*R } },
206 { { -.5*R, .7*R }, { -.5*R, -.7*R } }
209 #define NUMTHINTRIANGLEGUYLINES (sizeof(thintriangle_guy)/sizeof(mline_t))
214 static int cheating = 0;
217 static int leveljuststarted = 1; // kluge until AM_LevelInit() is called
219 boolean automapactive = false;
220 static int finit_width = SCREENWIDTH;
221 static int finit_height = SCREENHEIGHT - 32;
223 // location of window on screen
227 // size of window on screen
231 static int lightlev; // used for funky strobing effect
232 static byte* fb; // pseudo-frame buffer
235 static mpoint_t m_paninc; // how far the window pans each tic (map coords)
236 static fixed_t mtof_zoommul; // how far the window zooms in each tic (map coords)
237 static fixed_t ftom_zoommul; // how far the window zooms in each tic (fb coords)
239 static fixed_t m_x, m_y; // LL x,y where the window is on the map (map coords)
240 static fixed_t m_x2, m_y2; // UR x,y where the window is on the map (map coords)
243 // width/height of window on map (map coords)
248 // based on level size
249 static fixed_t min_x;
250 static fixed_t min_y;
251 static fixed_t max_x;
252 static fixed_t max_y;
254 static fixed_t max_w; // max_x-min_x,
255 static fixed_t max_h; // max_y-min_y
257 // based on player size
258 static fixed_t min_w;
259 static fixed_t min_h;
262 static fixed_t min_scale_mtof; // used to tell when to stop zooming out
263 static fixed_t max_scale_mtof; // used to tell when to stop zooming in
265 // old stuff for recovery later
266 static fixed_t old_m_w, old_m_h;
267 static fixed_t old_m_x, old_m_y;
269 // old location used by the Follower routine
270 static mpoint_t f_oldloc;
272 // used by MTOF to scale from map-to-frame-buffer coords
273 static fixed_t scale_mtof = INITSCALEMTOF;
274 // used by FTOM to scale from frame-buffer-to-map coords (=1/scale_mtof)
275 static fixed_t scale_ftom;
277 static player_t *plr; // the player represented by an arrow
279 static patch_t *marknums[10]; // numbers used for marking by the automap
280 static mpoint_t markpoints[AM_NUMMARKPOINTS]; // where the points are
281 static int markpointnum = 0; // next point to be assigned
283 static int followplayer = 1; // specifies whether to follow the player around
285 static unsigned char cheat_amap_seq[] = { 0xb2, 0x26, 0x26, 0x2e, 0xff };
286 static cheatseq_t cheat_amap = { cheat_amap_seq, 0 };
288 static boolean stopped = true;
290 extern boolean viewactive;
291 //extern byte screens[][SCREENWIDTH*SCREENHEIGHT];
302 // Calculates the slope and slope according to the x-axis of a line
303 // segment in map coordinates (with the upright y-axis n' all) so
304 // that it can be used with the brain-dead drawing stuff.
313 dy = ml->a.y - ml->b.y;
314 dx = ml->b.x - ml->a.x;
315 if (!dy) is->islp = (dx<0?-MAXINT:MAXINT);
316 else is->islp = FixedDiv(dx, dy);
317 if (!dx) is->slp = (dy<0?-MAXINT:MAXINT);
318 else is->slp = FixedDiv(dy, dx);
325 void AM_activateNewScale(void)
340 void AM_saveScaleAndLoc(void)
351 void AM_restoreScaleAndLoc(void)
361 m_x = plr->mo->x - m_w/2;
362 m_y = plr->mo->y - m_h/2;
367 // Change the scaling multipliers
368 scale_mtof = FixedDiv(f_w<<FRACBITS, m_w);
369 scale_ftom = FixedDiv(FRACUNIT, scale_mtof);
373 // adds a marker at the current location
375 void AM_addMark(void)
377 markpoints[markpointnum].x = m_x + m_w/2;
378 markpoints[markpointnum].y = m_y + m_h/2;
379 markpointnum = (markpointnum + 1) % AM_NUMMARKPOINTS;
384 // Determines bounding box of all vertices,
385 // sets global variables controlling zoom range.
387 void AM_findMinMaxBoundaries(void)
393 min_x = min_y = MAXINT;
394 max_x = max_y = -MAXINT;
396 for (i=0;i<numvertexes;i++)
398 if (vertexes[i].x < min_x)
399 min_x = vertexes[i].x;
400 else if (vertexes[i].x > max_x)
401 max_x = vertexes[i].x;
403 if (vertexes[i].y < min_y)
404 min_y = vertexes[i].y;
405 else if (vertexes[i].y > max_y)
406 max_y = vertexes[i].y;
409 max_w = max_x - min_x;
410 max_h = max_y - min_y;
412 min_w = 2*PLAYERRADIUS; // const? never changed?
413 min_h = 2*PLAYERRADIUS;
415 a = FixedDiv(f_w<<FRACBITS, max_w);
416 b = FixedDiv(f_h<<FRACBITS, max_h);
418 min_scale_mtof = a < b ? a : b;
419 max_scale_mtof = FixedDiv(f_h<<FRACBITS, 2*PLAYERRADIUS);
427 void AM_changeWindowLoc(void)
429 if (m_paninc.x || m_paninc.y)
438 if (m_x + m_w/2 > max_x)
440 else if (m_x + m_w/2 < min_x)
443 if (m_y + m_h/2 > max_y)
445 else if (m_y + m_h/2 < min_y)
456 void AM_initVariables(void)
459 static event_t st_notify = { ev_keyup, AM_MSGENTERED };
461 automapactive = true;
468 m_paninc.x = m_paninc.y = 0;
469 ftom_zoommul = FRACUNIT;
470 mtof_zoommul = FRACUNIT;
475 // find player to center on initially
476 if (!playeringame[pnum = consoleplayer])
477 for (pnum=0;pnum<MAXPLAYERS;pnum++)
478 if (playeringame[pnum])
481 plr = &players[pnum];
482 m_x = plr->mo->x - m_w/2;
483 m_y = plr->mo->y - m_h/2;
484 AM_changeWindowLoc();
486 // for saving & restoring
492 // inform the status bar of the change
493 ST_Responder(&st_notify);
500 void AM_loadPics(void)
507 sprintf(namebuf, "AMMNUM%d", i);
508 marknums[i] = W_CacheLumpName(namebuf, PU_STATIC);
513 void AM_unloadPics(void)
518 Z_ChangeTag(marknums[i], PU_CACHE);
522 void AM_clearMarks(void)
526 for (i=0;i<AM_NUMMARKPOINTS;i++)
527 markpoints[i].x = -1; // means empty
532 // should be called at the start of every level
533 // right now, i figure it out myself
535 void AM_LevelInit(void)
537 leveljuststarted = 0;
545 AM_findMinMaxBoundaries();
546 scale_mtof = FixedDiv(min_scale_mtof, (int) (0.7*FRACUNIT));
547 if (scale_mtof > max_scale_mtof)
548 scale_mtof = min_scale_mtof;
549 scale_ftom = FixedDiv(FRACUNIT, scale_mtof);
560 static event_t st_notify = { 0, ev_keyup, AM_MSGEXITED };
563 automapactive = false;
564 ST_Responder(&st_notify);
573 static int lastlevel = -1, lastepisode = -1;
575 if (!stopped) AM_Stop();
577 if (lastlevel != gamemap || lastepisode != gameepisode)
581 lastepisode = gameepisode;
588 // set the window scale to the maximum size
590 void AM_minOutWindowScale(void)
592 scale_mtof = min_scale_mtof;
593 scale_ftom = FixedDiv(FRACUNIT, scale_mtof);
594 AM_activateNewScale();
598 // set the window scale to the minimum size
600 void AM_maxOutWindowScale(void)
602 scale_mtof = max_scale_mtof;
603 scale_ftom = FixedDiv(FRACUNIT, scale_mtof);
604 AM_activateNewScale();
609 // Handle events (user inputs) in automap mode
617 static int cheatstate=0;
618 static int bigstate=0;
619 static char buffer[20];
625 if (ev->type == ev_keydown && ev->data1 == AM_STARTKEY)
633 else if (ev->type == ev_keydown)
639 case AM_PANRIGHTKEY: // pan right
640 if (!followplayer) m_paninc.x = FTOM(F_PANINC);
643 case AM_PANLEFTKEY: // pan left
644 if (!followplayer) m_paninc.x = -FTOM(F_PANINC);
647 case AM_PANUPKEY: // pan up
648 if (!followplayer) m_paninc.y = FTOM(F_PANINC);
651 case AM_PANDOWNKEY: // pan down
652 if (!followplayer) m_paninc.y = -FTOM(F_PANINC);
655 case AM_ZOOMOUTKEY: // zoom out
656 mtof_zoommul = M_ZOOMOUT;
657 ftom_zoommul = M_ZOOMIN;
659 case AM_ZOOMINKEY: // zoom in
660 mtof_zoommul = M_ZOOMIN;
661 ftom_zoommul = M_ZOOMOUT;
669 bigstate = !bigstate;
672 AM_saveScaleAndLoc();
673 AM_minOutWindowScale();
675 else AM_restoreScaleAndLoc();
678 followplayer = !followplayer;
680 plr->message = followplayer ? AMSTR_FOLLOWON : AMSTR_FOLLOWOFF;
684 plr->message = grid ? AMSTR_GRIDON : AMSTR_GRIDOFF;
687 sprintf(buffer, "%s %d", AMSTR_MARKEDSPOT, markpointnum);
688 plr->message = buffer;
691 case AM_CLEARMARKKEY:
693 plr->message = AMSTR_MARKSCLEARED;
699 if (!deathmatch && cht_CheckCheat(&cheat_amap, ev->data1))
702 cheating = (cheating+1) % 3;
706 else if (ev->type == ev_keyup)
712 if (!followplayer) m_paninc.x = 0;
715 if (!followplayer) m_paninc.x = 0;
718 if (!followplayer) m_paninc.y = 0;
721 if (!followplayer) m_paninc.y = 0;
725 mtof_zoommul = FRACUNIT;
726 ftom_zoommul = FRACUNIT;
739 void AM_changeWindowScale(void)
742 // Change the scaling multipliers
743 scale_mtof = FixedMul(scale_mtof, mtof_zoommul);
744 scale_ftom = FixedDiv(FRACUNIT, scale_mtof);
746 if (scale_mtof < min_scale_mtof)
747 AM_minOutWindowScale();
748 else if (scale_mtof > max_scale_mtof)
749 AM_maxOutWindowScale();
751 AM_activateNewScale();
758 void AM_doFollowPlayer(void)
761 if (f_oldloc.x != plr->mo->x || f_oldloc.y != plr->mo->y)
763 m_x = FTOM(MTOF(plr->mo->x)) - m_w/2;
764 m_y = FTOM(MTOF(plr->mo->y)) - m_h/2;
767 f_oldloc.x = plr->mo->x;
768 f_oldloc.y = plr->mo->y;
770 // m_x = FTOM(MTOF(plr->mo->x - m_w/2));
771 // m_y = FTOM(MTOF(plr->mo->y - m_h/2));
772 // m_x = plr->mo->x - m_w/2;
773 // m_y = plr->mo->y - m_h/2;
782 void AM_updateLightLev(void)
785 //static int litelevels[] = { 0, 3, 5, 6, 6, 7, 7, 7 };
786 static int litelevels[] = { 0, 4, 7, 10, 12, 14, 15, 15 };
787 static int litelevelscnt = 0;
789 // Change light level
792 lightlev = litelevels[litelevelscnt++];
793 if (litelevelscnt == sizeof(litelevels)/sizeof(int)) litelevelscnt = 0;
794 nexttic = amclock + 6 - (amclock % 6);
801 // Updates on Game Tick
803 void AM_Ticker (void)
814 // Change the zoom if necessary
815 if (ftom_zoommul != FRACUNIT)
816 AM_changeWindowScale();
818 // Change x,y location
819 if (m_paninc.x || m_paninc.y)
820 AM_changeWindowLoc();
822 // Update light level
823 // AM_updateLightLev();
829 // Clear automap frame buffer.
831 void AM_clearFB(int color)
833 memset(fb, color, f_w*f_h);
838 // Automap clipping of lines.
840 // Based on Cohen-Sutherland clipping algorithm but with a slightly
841 // faster reject and precalculated slopes. If the speed is needed,
842 // use a hash algorithm to handle the common cases.
857 register outcode1 = 0;
858 register outcode2 = 0;
866 #define DOOUTCODE(oc, mx, my) \
868 if ((my) < 0) (oc) |= TOP; \
869 else if ((my) >= f_h) (oc) |= BOTTOM; \
870 if ((mx) < 0) (oc) |= LEFT; \
871 else if ((mx) >= f_w) (oc) |= RIGHT;
874 // do trivial rejects and outcodes
877 else if (ml->a.y < m_y)
882 else if (ml->b.y < m_y)
885 if (outcode1 & outcode2)
886 return false; // trivially outside
890 else if (ml->a.x > m_x2)
895 else if (ml->b.x > m_x2)
898 if (outcode1 & outcode2)
899 return false; // trivially outside
901 // transform to frame-buffer coordinates.
902 fl->a.x = CXMTOF(ml->a.x);
903 fl->a.y = CYMTOF(ml->a.y);
904 fl->b.x = CXMTOF(ml->b.x);
905 fl->b.y = CYMTOF(ml->b.y);
907 DOOUTCODE(outcode1, fl->a.x, fl->a.y);
908 DOOUTCODE(outcode2, fl->b.x, fl->b.y);
910 if (outcode1 & outcode2)
913 while (outcode1 | outcode2)
915 // may be partially inside box
916 // find an outside point
925 dy = fl->a.y - fl->b.y;
926 dx = fl->b.x - fl->a.x;
927 tmp.x = fl->a.x + (dx*(fl->a.y))/dy;
930 else if (outside & BOTTOM)
932 dy = fl->a.y - fl->b.y;
933 dx = fl->b.x - fl->a.x;
934 tmp.x = fl->a.x + (dx*(fl->a.y-f_h))/dy;
937 else if (outside & RIGHT)
939 dy = fl->b.y - fl->a.y;
940 dx = fl->b.x - fl->a.x;
941 tmp.y = fl->a.y + (dy*(f_w-1 - fl->a.x))/dx;
944 else if (outside & LEFT)
946 dy = fl->b.y - fl->a.y;
947 dx = fl->b.x - fl->a.x;
948 tmp.y = fl->a.y + (dy*(-fl->a.x))/dx;
952 if (outside == outcode1)
955 DOOUTCODE(outcode1, fl->a.x, fl->a.y);
960 DOOUTCODE(outcode2, fl->b.x, fl->b.y);
963 if (outcode1 & outcode2)
964 return false; // trivially outside
973 // Classic Bresenham w/ whatever optimizations needed for speed
992 // For debugging only
993 if ( fl->a.x < 0 || fl->a.x >= f_w
994 || fl->a.y < 0 || fl->a.y >= f_h
995 || fl->b.x < 0 || fl->b.x >= f_w
996 || fl->b.y < 0 || fl->b.y >= f_h)
998 fprintf(stderr, "fuck %d \r", fuck++);
1002 #define PUTDOT(xx,yy,cc) fb[(yy)*f_w+(xx)]=(cc)
1004 dx = fl->b.x - fl->a.x;
1005 ax = 2 * (dx<0 ? -dx : dx);
1008 dy = fl->b.y - fl->a.y;
1009 ay = 2 * (dy<0 ? -dy : dy);
1021 if (x == fl->b.x) return;
1036 PUTDOT(x, y, color);
1037 if (y == fl->b.y) return;
1051 // Clip lines, draw visible part sof lines.
1060 if (AM_clipMline(ml, &fl))
1061 AM_drawFline(&fl, color); // draws it on frame buffer using fb coords
1067 // Draws flat (floor/ceiling tile) aligned grid lines.
1069 void AM_drawGrid(int color)
1075 // Figure out start of vertical gridlines
1077 if ((start-bmaporgx)%(MAPBLOCKUNITS<<FRACBITS))
1078 start += (MAPBLOCKUNITS<<FRACBITS)
1079 - ((start-bmaporgx)%(MAPBLOCKUNITS<<FRACBITS));
1082 // draw vertical gridlines
1085 for (x=start; x<end; x+=(MAPBLOCKUNITS<<FRACBITS))
1089 AM_drawMline(&ml, color);
1092 // Figure out start of horizontal gridlines
1094 if ((start-bmaporgy)%(MAPBLOCKUNITS<<FRACBITS))
1095 start += (MAPBLOCKUNITS<<FRACBITS)
1096 - ((start-bmaporgy)%(MAPBLOCKUNITS<<FRACBITS));
1099 // draw horizontal gridlines
1102 for (y=start; y<end; y+=(MAPBLOCKUNITS<<FRACBITS))
1106 AM_drawMline(&ml, color);
1112 // Determines visible lines, draws them.
1113 // This is LineDef based, not LineSeg based.
1115 void AM_drawWalls(void)
1120 for (i=0;i<numlines;i++)
1122 l.a.x = lines[i].v1->x;
1123 l.a.y = lines[i].v1->y;
1124 l.b.x = lines[i].v2->x;
1125 l.b.y = lines[i].v2->y;
1126 if (cheating || (lines[i].flags & ML_MAPPED))
1128 if ((lines[i].flags & LINE_NEVERSEE) && !cheating)
1130 if (!lines[i].backsector)
1132 AM_drawMline(&l, WALLCOLORS+lightlev);
1136 if (lines[i].special == 39)
1138 AM_drawMline(&l, WALLCOLORS+WALLRANGE/2);
1140 else if (lines[i].flags & ML_SECRET) // secret door
1142 if (cheating) AM_drawMline(&l, SECRETWALLCOLORS + lightlev);
1143 else AM_drawMline(&l, WALLCOLORS+lightlev);
1145 else if (lines[i].backsector->floorheight
1146 != lines[i].frontsector->floorheight) {
1147 AM_drawMline(&l, FDWALLCOLORS + lightlev); // floor level change
1149 else if (lines[i].backsector->ceilingheight
1150 != lines[i].frontsector->ceilingheight) {
1151 AM_drawMline(&l, CDWALLCOLORS+lightlev); // ceiling level change
1153 else if (cheating) {
1154 AM_drawMline(&l, TSWALLCOLORS+lightlev);
1158 else if (plr->powers[pw_allmap])
1160 if (!(lines[i].flags & LINE_NEVERSEE)) AM_drawMline(&l, GRAYS+3);
1168 // Used to rotate player arrow line character.
1179 FixedMul(*x,finecosine[a>>ANGLETOFINESHIFT])
1180 - FixedMul(*y,finesine[a>>ANGLETOFINESHIFT]);
1183 FixedMul(*x,finesine[a>>ANGLETOFINESHIFT])
1184 + FixedMul(*y,finecosine[a>>ANGLETOFINESHIFT]);
1190 AM_drawLineCharacter
1202 for (i=0;i<lineguylines;i++)
1204 l.a.x = lineguy[i].a.x;
1205 l.a.y = lineguy[i].a.y;
1209 l.a.x = FixedMul(scale, l.a.x);
1210 l.a.y = FixedMul(scale, l.a.y);
1214 AM_rotate(&l.a.x, &l.a.y, angle);
1219 l.b.x = lineguy[i].b.x;
1220 l.b.y = lineguy[i].b.y;
1224 l.b.x = FixedMul(scale, l.b.x);
1225 l.b.y = FixedMul(scale, l.b.y);
1229 AM_rotate(&l.b.x, &l.b.y, angle);
1234 AM_drawMline(&l, color);
1238 void AM_drawPlayers(void)
1242 static int their_colors[] = { GREENS, GRAYS, BROWNS, REDS };
1243 int their_color = -1;
1249 AM_drawLineCharacter
1250 (cheat_player_arrow, NUMCHEATPLYRLINES, 0,
1251 plr->mo->angle, WHITE, plr->mo->x, plr->mo->y);
1253 AM_drawLineCharacter
1254 (player_arrow, NUMPLYRLINES, 0, plr->mo->angle,
1255 WHITE, plr->mo->x, plr->mo->y);
1259 for (i=0;i<MAXPLAYERS;i++)
1264 if ( (deathmatch && !singledemo) && p != plr)
1267 if (!playeringame[i])
1270 if (p->powers[pw_invisibility])
1271 color = 246; // *close* to black
1273 color = their_colors[their_color];
1275 AM_drawLineCharacter
1276 (player_arrow, NUMPLYRLINES, 0, p->mo->angle,
1277 color, p->mo->x, p->mo->y);
1283 AM_drawThings (int colors)
1288 for (i=0;i<numsectors;i++)
1290 t = sectors[i].thinglist;
1293 AM_drawLineCharacter
1294 (thintriangle_guy, NUMTHINTRIANGLEGUYLINES,
1295 16<<FRACBITS, t->angle, colors+lightlev, t->x, t->y);
1301 void AM_drawMarks(void)
1303 int i, fx, fy, w, h;
1305 for (i=0;i<AM_NUMMARKPOINTS;i++)
1307 if (markpoints[i].x != -1)
1309 // w = SHORT(marknums[i]->width);
1310 // h = SHORT(marknums[i]->height);
1311 w = 5; // because something's wrong with the wad, i guess
1312 h = 6; // because something's wrong with the wad, i guess
1313 fx = CXMTOF(markpoints[i].x);
1314 fy = CYMTOF(markpoints[i].y);
1315 if (fx >= f_x && fx <= f_w - w && fy >= f_y && fy <= f_h - h)
1316 V_DrawPatch(fx, fy, FB, marknums[i]);
1322 void AM_drawCrosshair(int color)
1324 fb[(f_w*(f_h+1))/2] = color; // single point for now
1328 void AM_Drawer (void)
1330 if (!automapactive) return;
1332 AM_clearFB(BACKGROUND);
1334 AM_drawGrid(GRIDCOLORS);
1338 AM_drawThings(THINGCOLORS);
1339 AM_drawCrosshair(XHAIRCOLORS);
1343 V_MarkRect(f_x, f_y, f_w, f_h);