1 
2 //**************************************************************************
3 //**
4 //** am_map.c : Heretic 2 : Raven Software, Corp.
5 //**
6 //** $RCSfile: am_map.c,v $
7 //** $Revision: 1.22 $
8 //** $Date: 96/01/06 18:37:23 $
9 //** $Author: bgokey $
10 //**
11 //**************************************************************************
12 
13 #include "h2def.h"
14 #include "p_local.h"
15 #include "am_map.h"
16 #include "am_data.h"
17 #include <stdio.h>
18 
19 /* for GL
20 #include "ogl_def.h"
21 #define MTOFX(x) FixedMul((x),scale_mtof)
22 #define CXMTOFX(x)  ((f_x<<16) + MTOFX((x)-m_x))
23 #define CYMTOFX(y)  ((f_y<<16) + ((f_h<<16) - MTOFX((y)-m_y)))
24 static int maplumpnum;
25 */
26 
27 #define NUMALIAS 3 // Number of antialiased lines.
28 
29 int cheating = 0;
30 static int grid = 0;
31 
32 //extern int use_gl;
33 
34 static int leveljuststarted = 1; // kluge until AM_LevelInit() is called
35 
36 boolean    automapactive = false;
37 static int finit_width = SCREENWIDTH;
38 static int finit_height = SCREENHEIGHT-SBARHEIGHT-3;
39 static int f_x, f_y; // location of window on screen
40 static int f_w, f_h; // size of window on screen
41 static int lightlev; // used for funky strobing effect
42 static byte *fb; // pseudo-frame buffer
43 static int amclock;
44 
45 static mpoint_t m_paninc; // how far the window pans each tic (map coords)
46 static fixed_t mtof_zoommul; // how far the window zooms in each tic (map coords)
47 static fixed_t ftom_zoommul; // how far the window zooms in each tic (fb coords)
48 
49 static fixed_t m_x, m_y;   // LL x,y where the window is on the map (map coords)
50 static fixed_t m_x2, m_y2; // UR x,y where the window is on the map (map coords)
51 
52 // width/height of window on map (map coords)
53 static fixed_t m_w, m_h;
54 static fixed_t min_x, min_y; // based on level size
55 static fixed_t max_x, max_y; // based on level size
56 static fixed_t max_w, max_h; // max_x-min_x, max_y-min_y
57 static fixed_t min_w, min_h; // based on player size
58 static fixed_t min_scale_mtof; // used to tell when to stop zooming out
59 static fixed_t max_scale_mtof; // used to tell when to stop zooming in
60 
61 // old stuff for recovery later
62 static fixed_t old_m_w, old_m_h;
63 static fixed_t old_m_x, old_m_y;
64 
65 // old location used by the Follower routine
66 static mpoint_t f_oldloc;
67 
68 // used by MTOF to scale from map-to-frame-buffer coords
69 static fixed_t scale_mtof = INITSCALEMTOF;
70 // used by FTOM to scale from frame-buffer-to-map coords (=1/scale_mtof)
71 static fixed_t scale_ftom;
72 
73 static player_t *plr; // the player represented by an arrow
74 static vertex_t oldplr;
75 
76 //static patch_t *marknums[10]; // numbers used for marking by the automap
77 //static mpoint_t markpoints[AM_NUMMARKPOINTS]; // where the points are
78 //static int markpointnum = 0; // next point to be assigned
79 
80 static int followplayer = 1; // specifies whether to follow the player around
81 
82 static char cheat_kills[] = { 'k', 'i', 'l', 'l', 's' };
83 static boolean ShowKills = 0;
84 static unsigned ShowKillsCount = 0;
85 
86 extern boolean viewactive;
87 
88 static byte antialias[NUMALIAS][8]=
89 {
90 	{ 83, 84, 85, 86, 87, 88, 89, 90 },
91 	{ 96, 96, 95, 94, 93, 92, 91, 90 },
92 	{ 107, 108, 109, 110, 111, 112, 89, 90 }
93 };
94 
95 /*
96 static byte *aliasmax[NUMALIAS] = {
97 	&antialias[0][7], &antialias[1][7], &antialias[2][7]
98 };*/
99 
100 /* for GL
101 static byte *maplump;
102 */
103 
104 static byte *maplump; // pointer to the raw data for the automap background.
105 static short mapystart=0; // y-value for the start of the map bitmap...used in
106 										//the parallax stuff.
107 static short mapxstart=0; //x-value for the bitmap.
108 
109 //void V_MarkRect (int x, int y, int width, int height);
110 
111 // Functions
112 
113 void DrawWuLine(int X0, int Y0, int X1, int Y1, byte *BaseColor,
114 	int NumLevels, unsigned short IntensityBits);
115 
116 void AM_DrawDeathmatchStats(void);
117 static void DrawWorldTimer(void);
118 
119 // Calculates the slope and slope according to the x-axis of a line
120 // segment in map coordinates (with the upright y-axis n' all) so
121 // that it can be used with the brain-dead drawing stuff.
122 
123 // Ripped out for Heretic
124 /*
125 void AM_getIslope(mline_t *ml, islope_t *is)
126 {
127   int dx, dy;
128 
129   dy = ml->a.y - ml->b.y;
130   dx = ml->b.x - ml->a.x;
131   if (!dy) is->islp = (dx<0?-MAXINT:MAXINT);
132   else is->islp = FixedDiv(dx, dy);
133   if (!dx) is->slp = (dy<0?-MAXINT:MAXINT);
134   else is->slp = FixedDiv(dy, dx);
135 }
136 */
137 
AM_activateNewScale(void)138 void AM_activateNewScale(void)
139 {
140   m_x += m_w/2;
141   m_y += m_h/2;
142   m_w = FTOM(f_w);
143   m_h = FTOM(f_h);
144   m_x -= m_w/2;
145   m_y -= m_h/2;
146   m_x2 = m_x + m_w;
147   m_y2 = m_y + m_h;
148 }
149 
AM_saveScaleAndLoc(void)150 void AM_saveScaleAndLoc(void)
151 {
152   old_m_x = m_x;
153   old_m_y = m_y;
154   old_m_w = m_w;
155   old_m_h = m_h;
156 }
157 
AM_restoreScaleAndLoc(void)158 void AM_restoreScaleAndLoc(void)
159 {
160 
161   m_w = old_m_w;
162   m_h = old_m_h;
163   if (!followplayer)
164   {
165     m_x = old_m_x;
166     m_y = old_m_y;
167   } else {
168     m_x = plr->mo->x - m_w/2;
169     m_y = plr->mo->y - m_h/2;
170   }
171   m_x2 = m_x + m_w;
172   m_y2 = m_y + m_h;
173 
174   // Change the scaling multipliers
175   scale_mtof = FixedDiv(f_w<<FRACBITS, m_w);
176   scale_ftom = FixedDiv(FRACUNIT, scale_mtof);
177 }
178 
179 // adds a marker at the current location
180 
181 /*
182 void AM_addMark(void)
183 {
184   markpoints[markpointnum].x = m_x + m_w/2;
185   markpoints[markpointnum].y = m_y + m_h/2;
186   markpointnum = (markpointnum + 1) % AM_NUMMARKPOINTS;
187 
188 }
189 */
AM_findMinMaxBoundaries(void)190 void AM_findMinMaxBoundaries(void)
191 {
192   int i;
193   fixed_t a, b;
194 
195   min_x = min_y = MAXINT;
196   max_x = max_y = -MAXINT;
197   for (i=0;i<numvertexes;i++)
198   {
199     if (vertexes[i].x < min_x) min_x = vertexes[i].x;
200     else if (vertexes[i].x > max_x) max_x = vertexes[i].x;
201     if (vertexes[i].y < min_y) min_y = vertexes[i].y;
202     else if (vertexes[i].y > max_y) max_y = vertexes[i].y;
203   }
204   max_w = max_x - min_x;
205   max_h = max_y - min_y;
206   min_w = 2*PLAYERRADIUS;
207   min_h = 2*PLAYERRADIUS;
208 
209   a = FixedDiv(f_w<<FRACBITS, max_w);
210   b = FixedDiv(f_h<<FRACBITS, max_h);
211   min_scale_mtof = a < b ? a : b;
212 
213   max_scale_mtof = FixedDiv(f_h<<FRACBITS, 2*PLAYERRADIUS);
214 
215 }
216 
AM_changeWindowLoc(void)217 void AM_changeWindowLoc(void)
218 {
219   if (m_paninc.x || m_paninc.y)
220   {
221     followplayer = 0;
222     f_oldloc.x = MAXINT;
223   }
224 
225   m_x += m_paninc.x;
226   m_y += m_paninc.y;
227 
228   if (m_x + m_w/2 > max_x)
229   {
230   		m_x = max_x - m_w/2;
231 		m_paninc.x=0;
232   }
233   else if (m_x + m_w/2 < min_x)
234   {
235   		m_x = min_x - m_w/2;
236 		m_paninc.x=0;
237   }
238   if (m_y + m_h/2 > max_y)
239   {
240   		m_y = max_y - m_h/2;
241 		m_paninc.y=0;
242   }
243   else if (m_y + m_h/2 < min_y)
244   {
245   		m_y = min_y - m_h/2;
246 		m_paninc.y=0;
247   }
248 /*
249   mapxstart += MTOF(m_paninc.x+FRACUNIT/2);
250   mapystart -= MTOF(m_paninc.y+FRACUNIT/2);
251   if(mapxstart >= finit_width)
252 		mapxstart -= finit_width;
253   if(mapxstart < 0)
254 		mapxstart += finit_width;
255   if(mapystart >= finit_height)
256 		mapystart -= finit_height;
257   if(mapystart < 0)
258 		mapystart += finit_height;
259 */
260   m_x2 = m_x + m_w;
261   m_y2 = m_y + m_h;
262 }
263 
AM_initVariables(void)264 void AM_initVariables(void)
265 {
266   int pnum;
267 	thinker_t *think;
268 	mobj_t *mo;
269 
270   //static event_t st_notify = { ev_keyup, AM_MSGENTERED };
271 
272   automapactive = true;
273   fb = screen;
274 
275   f_oldloc.x = MAXINT;
276   amclock = 0;
277   lightlev = 0;
278 
279   m_paninc.x = m_paninc.y = 0;
280   ftom_zoommul = FRACUNIT;
281   mtof_zoommul = FRACUNIT;
282 
283   m_w = FTOM(f_w);
284   m_h = FTOM(f_h);
285 
286   // find player to center on initially
287   if (!playeringame[pnum = consoleplayer])
288     for (pnum=0;pnum<MAXPLAYERS;pnum++) if (playeringame[pnum]) break;
289   plr = &players[pnum];
290   oldplr.x = plr->mo->x;
291   oldplr.y = plr->mo->y;
292   m_x = plr->mo->x - m_w/2;
293   m_y = plr->mo->y - m_h/2;
294   AM_changeWindowLoc();
295 
296   // for saving & restoring
297   old_m_x = m_x;
298   old_m_y = m_y;
299   old_m_w = m_w;
300   old_m_h = m_h;
301 
302 	// load in the location of keys, if in baby mode
303 
304 //	memset(KeyPoints, 0, sizeof(vertex_t)*3);
305 	if(gameskill == sk_baby)
306 	{
307 		for(think = thinkercap.next; think != &thinkercap; think = think->next)
308 		{
309 			if(think->function != P_MobjThinker)
310 			{ //not a mobj
311 				continue;
312 			}
313 			mo = (mobj_t *)think;
314 		}
315 	}
316 
317   // inform the status bar of the change
318 //c  ST_Responder(&st_notify);
319 }
320 
AM_loadPics(void)321 void AM_loadPics(void)
322 {
323  /*for GL
324    if (use_gl)
325    maplumpnum = W_GetNumForName("AUTOPAGE");
326   else*/
327    maplump = W_CacheLumpName("AUTOPAGE", PU_STATIC);
328 }
329 
330 
331 /*
332 void AM_clearMarks(void)
333 {
334   int i;
335   for (i=0;i<AM_NUMMARKPOINTS;i++) markpoints[i].x = -1; // means empty
336   markpointnum = 0;
337 }
338 */
339 
340 // should be called at the start of every level
341 // right now, i figure it out myself
342 
AM_LevelInit(void)343 void AM_LevelInit(void)
344 {
345   leveljuststarted = 0;
346 
347   f_x = f_y = 0;
348   f_w = finit_width;
349   f_h = finit_height;
350 	mapxstart = mapystart = 0;
351 
352 
353 //  AM_clearMarks();
354 
355   AM_findMinMaxBoundaries();
356   scale_mtof = FixedDiv(min_scale_mtof, (int) (0.7*FRACUNIT));
357   if (scale_mtof > max_scale_mtof) scale_mtof = min_scale_mtof;
358   scale_ftom = FixedDiv(FRACUNIT, scale_mtof);
359 }
360 
361 static boolean stopped = true;
362 
AM_Stop(void)363 void AM_Stop (void)
364 {
365   //static event_t st_notify = { 0, ev_keyup, AM_MSGEXITED };
366 
367 //  AM_unloadPics();
368   automapactive = false;
369 //  ST_Responder(&st_notify);
370   stopped = true;
371 	BorderNeedRefresh = true;
372 }
373 
AM_Start(void)374 void AM_Start (void)
375 {
376   static int lastlevel = -1, lastepisode = -1;
377 
378   if (!stopped) AM_Stop();
379   stopped = false;
380   if(gamestate != GS_LEVEL)
381   {
382 		return; // don't show automap if we aren't in a game!
383   }
384   if (lastlevel != gamemap || lastepisode != gameepisode)
385   {
386     AM_LevelInit();
387     lastlevel = gamemap;
388     lastepisode = gameepisode;
389   }
390   AM_initVariables();
391   AM_loadPics();
392 }
393 
394 // set the window scale to the maximum size
395 
AM_minOutWindowScale(void)396 void AM_minOutWindowScale(void)
397 {
398   scale_mtof = min_scale_mtof;
399   scale_ftom = FixedDiv(FRACUNIT, scale_mtof);
400   AM_activateNewScale();
401 }
402 
403 // set the window scale to the minimum size
404 
AM_maxOutWindowScale(void)405 void AM_maxOutWindowScale(void)
406 {
407   scale_mtof = max_scale_mtof;
408   scale_ftom = FixedDiv(FRACUNIT, scale_mtof);
409   AM_activateNewScale();
410 }
411 
AM_Responder(event_t * ev)412 boolean AM_Responder (event_t *ev)
413 {
414 	int rc;
415 	static int cheatstate=0;
416 	static int bigstate=0;
417 
418 	rc = false;
419 	if (!automapactive)
420 	{
421 		if (ev->type == ev_keydown && ev->data1 == AM_STARTKEY
422 			&& gamestate == GS_LEVEL)
423 		{
424 			AM_Start ();
425 			SB_state = -1;
426 			viewactive = false;
427 			rc = true;
428 		}
429 	}
430 	else if (ev->type == ev_keydown)
431 	{
432 		rc = true;
433 		switch(ev->data1)
434 		{
435 			case AM_PANRIGHTKEY: // pan right
436 				if (!followplayer) m_paninc.x = FTOM(F_PANINC);
437 				else rc = false;
438 				break;
439 			case AM_PANLEFTKEY: // pan left
440 				if (!followplayer) m_paninc.x = -FTOM(F_PANINC);
441 				else rc = false;
442 				break;
443 			case AM_PANUPKEY: // pan up
444 				if (!followplayer) m_paninc.y = FTOM(F_PANINC);
445 				else rc = false;
446 				break;
447 			case AM_PANDOWNKEY: // pan down
448 				if (!followplayer) m_paninc.y = -FTOM(F_PANINC);
449 				else rc = false;
450 				break;
451 			case AM_ZOOMOUTKEY: // zoom out
452 				mtof_zoommul = M_ZOOMOUT;
453 				ftom_zoommul = M_ZOOMIN;
454 				break;
455 			case AM_ZOOMINKEY: // zoom in
456 				mtof_zoommul = M_ZOOMIN;
457 				ftom_zoommul = M_ZOOMOUT;
458 				break;
459 			case AM_ENDKEY:
460 				bigstate = 0;
461 				viewactive = true;
462 				AM_Stop ();
463 				SB_state = -1;
464 				break;
465 			case AM_GOBIGKEY:
466 				bigstate = !bigstate;
467 				if (bigstate)
468 				{
469 					AM_saveScaleAndLoc();
470 					AM_minOutWindowScale();
471 				}
472 				else AM_restoreScaleAndLoc();
473 				break;
474 			case AM_FOLLOWKEY:
475 				followplayer = !followplayer;
476 				f_oldloc.x = MAXINT;
477 				P_SetMessage(plr,
478 					followplayer ? AMSTR_FOLLOWON : AMSTR_FOLLOWOFF, true);
479 				break;
480 			default:
481 				cheatstate=0;
482 				rc = false;
483 		}
484 
485 		if(cheat_kills[ShowKillsCount] == ev->data1 && netgame && deathmatch)
486 		{
487 			ShowKillsCount++;
488 			if(ShowKillsCount == 5)
489 			{
490 				ShowKillsCount = 0;
491 				rc = false;
492 				ShowKills ^= 1;
493 			}
494 		}
495 		else
496 		{
497 			ShowKillsCount = 0;
498 		}
499 	}
500 	else if (ev->type == ev_keyup)
501 	{
502 		rc = false;
503 		switch (ev->data1)
504 		{
505 			case AM_PANRIGHTKEY:
506 				if (!followplayer) m_paninc.x = 0;
507 				break;
508 			case AM_PANLEFTKEY:
509 				if (!followplayer) m_paninc.x = 0;
510 				break;
511 			case AM_PANUPKEY:
512 				if (!followplayer) m_paninc.y = 0;
513 				break;
514 			case AM_PANDOWNKEY:
515 				if (!followplayer) m_paninc.y = 0;
516 				break;
517 			case AM_ZOOMOUTKEY:
518 			case AM_ZOOMINKEY:
519 				mtof_zoommul = FRACUNIT;
520 				ftom_zoommul = FRACUNIT;
521 				break;
522 		}
523 	}
524 	return rc;
525 }
526 
AM_changeWindowScale(void)527 void AM_changeWindowScale(void)
528 {
529 
530   // Change the scaling multipliers
531   scale_mtof = FixedMul(scale_mtof, mtof_zoommul);
532   scale_ftom = FixedDiv(FRACUNIT, scale_mtof);
533 
534   if (scale_mtof < min_scale_mtof) AM_minOutWindowScale();
535   else if (scale_mtof > max_scale_mtof) AM_maxOutWindowScale();
536   else AM_activateNewScale();
537 }
538 
AM_doFollowPlayer(void)539 void AM_doFollowPlayer(void)
540 {
541   if (f_oldloc.x != plr->mo->x || f_oldloc.y != plr->mo->y)
542   {
543 //  m_x = FTOM(MTOF(plr->mo->x - m_w/2));
544 //  m_y = FTOM(MTOF(plr->mo->y - m_h/2));
545 //  m_x = plr->mo->x - m_w/2;
546 //  m_y = plr->mo->y - m_h/2;
547     m_x = FTOM(MTOF(plr->mo->x)) - m_w/2;
548     m_y = FTOM(MTOF(plr->mo->y)) - m_h/2;
549     m_x2 = m_x + m_w;
550     m_y2 = m_y + m_h;
551 
552   	 // do the parallax parchment scrolling.
553 /*
554 	 dmapx = (MTOF(plr->mo->x)-MTOF(f_oldloc.x)); //fixed point
555 	 dmapy = (MTOF(f_oldloc.y)-MTOF(plr->mo->y));
556 
557 	 if(f_oldloc.x == MAXINT) //to eliminate an error when the user first
558 		dmapx=0;  //goes into the automap.
559 	 mapxstart += dmapx;
560 	 mapystart += dmapy;
561 
562   	 while(mapxstart >= finit_width)
563 			mapxstart -= finit_width;
564     while(mapxstart < 0)
565 			mapxstart += finit_width;
566     while(mapystart >= finit_height)
567 			mapystart -= finit_height;
568     while(mapystart < 0)
569 			mapystart += finit_height;
570 */
571 	 f_oldloc.x = plr->mo->x;
572     f_oldloc.y = plr->mo->y;
573   }
574 }
575 
576 // Ripped out for Heretic
577 /*
578 void AM_updateLightLev(void)
579 {
580   static nexttic = 0;
581 //static int litelevels[] = { 0, 3, 5, 6, 6, 7, 7, 7 };
582   static int litelevels[] = { 0, 4, 7, 10, 12, 14, 15, 15 };
583   static int litelevelscnt = 0;
584 
585   // Change light level
586   if (amclock>nexttic)
587   {
588     lightlev = litelevels[litelevelscnt++];
589     if (litelevelscnt == sizeof(litelevels)/sizeof(int)) litelevelscnt = 0;
590     nexttic = amclock + 6 - (amclock % 6);
591   }
592 }
593 */
594 
AM_Ticker(void)595 void AM_Ticker (void)
596 {
597 
598   if (!automapactive) return;
599 
600   amclock++;
601 
602   if (followplayer) AM_doFollowPlayer();
603 
604   // Change the zoom if necessary
605   if (ftom_zoommul != FRACUNIT) AM_changeWindowScale();
606 
607   // Change x,y location
608   if (m_paninc.x || m_paninc.y) AM_changeWindowLoc();
609   // Update light level
610 // AM_updateLightLev();
611 
612 }
613 
AM_clearFB(int color)614 void AM_clearFB(int color)
615 {
616 	int i, j;
617 	int dmapx;
618 	int dmapy;
619 	float scaler;
620 	int lump;
621 
622 	if(followplayer)
623 	{
624 		dmapx = (MTOF(plr->mo->x)-MTOF(oldplr.x)); //fixed point
625 		dmapy = (MTOF(oldplr.y)-MTOF(plr->mo->y));
626 
627 		oldplr.x = plr->mo->x;
628 		oldplr.y = plr->mo->y;
629 //		if(f_oldloc.x == MAXINT) //to eliminate an error when the user first
630 //			dmapx=0;  //goes into the automap.
631 		mapxstart += dmapx>>1;
632 		mapystart += dmapy>>1;
633 
634 	  	while(mapxstart >= finit_width)
635 			mapxstart -= finit_width;
636 	   while(mapxstart < 0)
637 			mapxstart += finit_width;
638 	   while(mapystart >= finit_height)
639 			mapystart -= finit_height;
640 	   while(mapystart < 0)
641 			mapystart += finit_height;
642 	}
643 	else
644 	{
645 		mapxstart += (MTOF(m_paninc.x)>>1);
646 		mapystart -= (MTOF(m_paninc.y)>>1);
647 		if(mapxstart >= finit_width)
648 			mapxstart -= finit_width;
649 		if(mapxstart < 0)
650 			mapxstart += finit_width;
651 		if(mapystart >= finit_height)
652 		mapystart -= finit_height;
653 		if(mapystart < 0)
654 		mapystart += finit_height;
655 	}
656 #if 0
657 // for GL
658 	if (use_gl) {
659 	    OGL_SetColorAndAlpha(1, 1, 1, 1);
660 
661 	    OGL_SetFlat(W_GetNumForName("F_022")-firstflat);
662 	    scaler = sbarscale/20.0;
663 	    OGL_DrawCutRectTiled(0, finit_height+4, 320, 200-finit_height-4, 64, 64,
664     		160-160*scaler+1, finit_height, 320*scaler-2, 200-finit_height);
665 
666 	    OGL_SetPatch(lump=W_GetNumForName("bordb"));
667 	    OGL_DrawCutRectTiled(0, finit_height, 320, 4,
668     		lumptexsizes[lump].w, lumptexsizes[lump].h,
669     		160-160*scaler+1, finit_height, 320*scaler-2, 4);
670 
671 	    OGL_SetRawImage(maplumpnum, 0); // We only want the left portion.
672 	    OGL_DrawRectTiled( 0, 0, finit_width,
673                        /*(sbarscale<20)?200:*/ finit_height,
674 		128, 128);
675 
676 	}
677 	else
678 	{
679 #else
680 	//blit the automap background to the screen.
681 	j=mapystart*finit_width;
682 	for(i = 0; i < SCREENHEIGHT-SBARHEIGHT; i++)
683 	{
684 		memcpy(screen+i*finit_width, maplump+j+mapxstart,
685 			finit_width-mapxstart);
686 		memcpy(screen+i*finit_width+finit_width-mapxstart, maplump+j,
687 			mapxstart);
688 		j += finit_width;
689 		if(j >= finit_height*finit_width)
690 			j=0;
691 	}
692 /*    } for GL*/
693 //	 memcpy(screen, maplump, finit_width*finit_height);
694 //  memset(fb, color, f_w*f_h);
695 #endif
696 }
697 
698 // Based on Cohen-Sutherland clipping algorithm but with a slightly
699 // faster reject and precalculated slopes.  If I need the speed, will
700 // hash algorithm to the common cases.
701 
702 boolean AM_clipMline(mline_t *ml, fline_t *fl)
703 {
704   enum { LEFT=1, RIGHT=2, BOTTOM=4, TOP=8 };
705   register int outcode1 = 0, outcode2 = 0, outside;
706   fpoint_t tmp;
707   int dx, dy;
708 
709 #define DOOUTCODE(oc, mx, my) \
710   (oc) = 0; \
711   if ((my) < 0) (oc) |= TOP; \
712   else if ((my) >= f_h) (oc) |= BOTTOM; \
713   if ((mx) < 0) (oc) |= LEFT; \
714   else if ((mx) >= f_w) (oc) |= RIGHT
715 
716   // do trivial rejects and outcodes
717   if (ml->a.y > m_y2) outcode1 = TOP;
718   else if (ml->a.y < m_y) outcode1 = BOTTOM;
719   if (ml->b.y > m_y2) outcode2 = TOP;
720   else if (ml->b.y < m_y) outcode2 = BOTTOM;
721   if (outcode1 & outcode2) return false; // trivially outside
722 
723   if (ml->a.x < m_x) outcode1 |= LEFT;
724   else if (ml->a.x > m_x2) outcode1 |= RIGHT;
725   if (ml->b.x < m_x) outcode2 |= LEFT;
726   else if (ml->b.x > m_x2) outcode2 |= RIGHT;
727   if (outcode1 & outcode2) return false; // trivially outside
728 
729   // transform to frame-buffer coordinates.
730   fl->a.x = CXMTOF(ml->a.x);
731   fl->a.y = CYMTOF(ml->a.y);
732   fl->b.x = CXMTOF(ml->b.x);
733   fl->b.y = CYMTOF(ml->b.y);
734   DOOUTCODE(outcode1, fl->a.x, fl->a.y);
735   DOOUTCODE(outcode2, fl->b.x, fl->b.y);
736   if (outcode1 & outcode2) return false;
737 
738   while (outcode1 | outcode2)
739   {
740     // may be partially inside box
741     // find an outside point
742     if (outcode1) outside = outcode1;
743     else outside = outcode2;
744     // clip to each side
745     if (outside & TOP)
746     {
747       dy = fl->a.y - fl->b.y;
748       dx = fl->b.x - fl->a.x;
749       tmp.x = fl->a.x + (dx*(fl->a.y))/dy;
750       tmp.y = 0;
751     }
752     else if (outside & BOTTOM)
753     {
754       dy = fl->a.y - fl->b.y;
755       dx = fl->b.x - fl->a.x;
756       tmp.x = fl->a.x + (dx*(fl->a.y-f_h))/dy;
757       tmp.y = f_h-1;
758     }
759     else if (outside & RIGHT)
760     {
761       dy = fl->b.y - fl->a.y;
762       dx = fl->b.x - fl->a.x;
763       tmp.y = fl->a.y + (dy*(f_w-1 - fl->a.x))/dx;
764       tmp.x = f_w-1;
765     }
766     else if (outside & LEFT)
767     {
768       dy = fl->b.y - fl->a.y;
769       dx = fl->b.x - fl->a.x;
770       tmp.y = fl->a.y + (dy*(-fl->a.x))/dx;
771       tmp.x = 0;
772     }
773     if (outside == outcode1)
774     {
775       fl->a = tmp;
776       DOOUTCODE(outcode1, fl->a.x, fl->a.y);
777     } else {
778       fl->b = tmp;
779       DOOUTCODE(outcode2, fl->b.x, fl->b.y);
780     }
781     if (outcode1 & outcode2) return false; // trivially outside
782   }
783 
784   return true;
785 }
786 #undef DOOUTCODE
787 
788 // Classic Bresenham w/ whatever optimizations I need for speed
789 
790 void AM_drawFline(fline_t *fl, int color)
791 {
792 	register int x, y, dx, dy, sx, sy, ax, ay, d;
793 	//static fuck = 0;
794 
795 	switch(color)
796 	{
797 		case WALLCOLORS:
798 			DrawWuLine(fl->a.x, fl->a.y, fl->b.x, fl->b.y,
799 				&antialias[0][0], 8, 3);
800 			break;
801 		case FDWALLCOLORS:
802 			DrawWuLine(fl->a.x, fl->a.y, fl->b.x, fl->b.y,
803 				&antialias[1][0], 8, 3);
804 			break;
805 		case CDWALLCOLORS:
806 			DrawWuLine(fl->a.x, fl->a.y, fl->b.x, fl->b.y,
807 				&antialias[2][0], 8, 3);
808 			break;
809 		default:
810   		{
811 				// For debugging only
812   				if (   fl->a.x < 0 || fl->a.x >= f_w
813       				|| fl->a.y < 0 || fl->a.y >= f_h
814       				|| fl->b.x < 0 || fl->b.x >= f_w
815       				|| fl->b.y < 0 || fl->b.y >= f_h)
816   				{
817     				//fprintf(stderr, "fuck %d \r", fuck++);
818     				return;
819   				}
820 
821   				#define DOT(xx,yy,cc) fb[(yy)*f_w+(xx)]=(cc) //the MACRO!
822 
823   				dx = fl->b.x - fl->a.x;
824   				ax = 2 * (dx<0 ? -dx : dx);
825   				sx = dx<0 ? -1 : 1;
826 
827   				dy = fl->b.y - fl->a.y;
828   				ay = 2 * (dy<0 ? -dy : dy);
829   				sy = dy<0 ? -1 : 1;
830 
831   				x = fl->a.x;
832   				y = fl->a.y;
833 
834   				if (ax > ay)
835   				{
836     				d = ay - ax/2;
837     				while (1)
838     				{
839       				DOT(x,y,color);
840       				if (x == fl->b.x) return;
841       				if (d>=0)
842       				{
843 					y += sy;
844 					d -= ax;
845       				}
846       				x += sx;
847       				d += ay;
848     				}
849   				} else {
850     				d = ax - ay/2;
851     				while (1)
852     				{
853       				DOT(x, y, color);
854       				if (y == fl->b.y) return;
855       				if (d >= 0)
856       				{
857 					x += sx;
858 					d -= ay;
859       				}
860       				y += sy;
861       				d += ax;
862     				}
863   				}
864   		}
865   }
866 }
867 
868 /* Wu antialiased line drawer.
869  * (X0,Y0),(X1,Y1) = line to draw
870  * BaseColor = color # of first color in block used for antialiasing, the
871  *          100% intensity version of the drawing color
872  * NumLevels = size of color block, with BaseColor+NumLevels-1 being the
873  *          0% intensity version of the drawing color
874  * IntensityBits = log base 2 of NumLevels; the # of bits used to describe
875  *          the intensity of the drawing color. 2**IntensityBits==NumLevels
876  */
877 void PUTDOT(short xx,short yy,byte *cc, byte *cm)
878 {
879 	static int oldyy;
880 	static int oldyyshifted;
881 	byte *oldcc=cc;
882 
883 	if(xx < 32)
884 		cc += 7-(xx>>2);
885 	else if(xx > (finit_width - 32))
886 		cc += 7-((finit_width-xx) >> 2);
887 //	if(cc==oldcc) //make sure that we don't double fade the corners.
888 //	{
889 		if(yy < 32)
890 			cc += 7-(yy>>2);
891 		else if(yy > (finit_height - 32))
892 			cc += 7-((finit_height-yy) >> 2);
893 //	}
894 	if(cc > cm && cm != NULL)
895 	{
896 		cc = cm;
897 	}
898 	else if(cc > oldcc+6) // don't let the color escape from the fade table...
899 	{
900 		cc=oldcc+6;
901 	}
902 	if(yy == oldyy+1)
903 	{
904 		oldyy++;
905 		oldyyshifted += 320;
906 	}
907 	else if(yy == oldyy-1)
908 	{
909 		oldyy--;
910 		oldyyshifted -= 320;
911 	}
912 	else if(yy != oldyy)
913 	{
914 		oldyy = yy;
915 		oldyyshifted = yy*320;
916 	}
917 	fb[oldyyshifted+xx] = *(cc);
918 // 	fb[(yy)*f_w+(xx)]=*(cc);
919 }
920 
921 void DrawWuLine(int X0, int Y0, int X1, int Y1, byte *BaseColor,
922 	int NumLevels, unsigned short IntensityBits)
923 {
924    unsigned short IntensityShift, ErrorAdj, ErrorAcc;
925    unsigned short ErrorAccTemp, Weighting, WeightingComplementMask;
926    short DeltaX, DeltaY, Temp, XDir;
927 
928    /* Make sure the line runs top to bottom */
929    if (Y0 > Y1) {
930       Temp = Y0; Y0 = Y1; Y1 = Temp;
931       Temp = X0; X0 = X1; X1 = Temp;
932    }
933    /* Draw the initial pixel, which is always exactly intersected by
934       the line and so needs no weighting */
935    PUTDOT(X0, Y0, &BaseColor[0], NULL);
936 
937    if ((DeltaX = X1 - X0) >= 0) {
938       XDir = 1;
939    } else {
940       XDir = -1;
941       DeltaX = -DeltaX; /* make DeltaX positive */
942    }
943    /* Special-case horizontal, vertical, and diagonal lines, which
944       require no weighting because they go right through the center of
945       every pixel */
946    if ((DeltaY = Y1 - Y0) == 0) {
947       /* Horizontal line */
948       while (DeltaX-- != 0) {
949          X0 += XDir;
950          PUTDOT(X0, Y0, &BaseColor[0], NULL);
951       }
952       return;
953    }
954    if (DeltaX == 0) {
955       /* Vertical line */
956       do {
957          Y0++;
958          PUTDOT(X0, Y0, &BaseColor[0], NULL);
959       } while (--DeltaY != 0);
960       return;
961    }
962 	//diagonal line.
963 	if (DeltaX == DeltaY) {
964       do {
965          X0 += XDir;
966          Y0++;
967          PUTDOT(X0, Y0, &BaseColor[0], NULL);
968       } while (--DeltaY != 0);
969       return;
970    }
971    /* Line is not horizontal, diagonal, or vertical */
972    ErrorAcc = 0;  /* initialize the line error accumulator to 0 */
973    /* # of bits by which to shift ErrorAcc to get intensity level */
974    IntensityShift = 16 - IntensityBits;
975    /* Mask used to flip all bits in an intensity weighting, producing the
976       result (1 - intensity weighting) */
977    WeightingComplementMask = NumLevels - 1;
978    /* Is this an X-major or Y-major line? */
979    if (DeltaY > DeltaX) {
980       /* Y-major line; calculate 16-bit fixed-point fractional part of a
981          pixel that X advances each time Y advances 1 pixel, truncating the
982          result so that we won't overrun the endpoint along the X axis */
983       ErrorAdj = ((unsigned long) DeltaX << 16) / (unsigned long) DeltaY;
984       /* Draw all pixels other than the first and last */
985       while (--DeltaY) {
986          ErrorAccTemp = ErrorAcc;   /* remember currrent accumulated error */
987          ErrorAcc += ErrorAdj;      /* calculate error for next pixel */
988          if (ErrorAcc <= ErrorAccTemp) {
989             /* The error accumulator turned over, so advance the X coord */
990             X0 += XDir;
991          }
992          Y0++; /* Y-major, so always advance Y */
993          /* The IntensityBits most significant bits of ErrorAcc give us the
994             intensity weighting for this pixel, and the complement of the
995             weighting for the paired pixel */
996          Weighting = ErrorAcc >> IntensityShift;
997 			PUTDOT(X0, Y0, &BaseColor[Weighting], &BaseColor[7]);
998          PUTDOT(X0 + XDir, Y0,
999                &BaseColor[(Weighting ^ WeightingComplementMask)], &BaseColor[7]);
1000       }
1001       /* Draw the final pixel, which is always exactly intersected by the line
1002          and so needs no weighting */
1003       PUTDOT(X1, Y1, &BaseColor[0], NULL);
1004       return;
1005    }
1006    /* It's an X-major line; calculate 16-bit fixed-point fractional part of a
1007       pixel that Y advances each time X advances 1 pixel, truncating the
1008       result to avoid overrunning the endpoint along the X axis */
1009    ErrorAdj = ((unsigned long) DeltaY << 16) / (unsigned long) DeltaX;
1010    /* Draw all pixels other than the first and last */
1011    while (--DeltaX) {
1012       ErrorAccTemp = ErrorAcc;   /* remember currrent accumulated error */
1013       ErrorAcc += ErrorAdj;      /* calculate error for next pixel */
1014       if (ErrorAcc <= ErrorAccTemp) {
1015          /* The error accumulator turned over, so advance the Y coord */
1016          Y0++;
1017       }
1018       X0 += XDir; /* X-major, so always advance X */
1019       /* The IntensityBits most significant bits of ErrorAcc give us the
1020          intensity weighting for this pixel, and the complement of the
1021          weighting for the paired pixel */
1022       Weighting = ErrorAcc >> IntensityShift;
1023       PUTDOT(X0, Y0, &BaseColor[Weighting], &BaseColor[7]);
1024       PUTDOT(X0, Y0 + 1,
1025       		&BaseColor[(Weighting ^ WeightingComplementMask)], &BaseColor[7]);
1026 
1027    }
1028    /* Draw the final pixel, which is always exactly intersected by the line
1029       and so needs no weighting */
1030    PUTDOT(X1, Y1, &BaseColor[0], NULL);
1031 }
1032 
1033 void AM_drawMline(mline_t *ml, int color)
1034 {
1035 /* if (use_gl) { for GL
1036  byte *palette = W_CacheLumpName("playpal", PU_CACHE);
1037  byte r = palette[color*3], g = palette[color*3+1], b = palette[color*3+2];
1038 
1039  OGL_DrawLine( FIX2FLT(CXMTOFX(ml->a.x)), FIX2FLT(CYMTOFX(ml->a.y))/1.2,
1040                   FIX2FLT(CXMTOFX(ml->b.x)), FIX2FLT(CYMTOFX(ml->b.y))/1.2,
1041                   r/255.0, g/255.0, b/255.0, 1 );
1042  }
1043  else
1044  {*/
1045  static fline_t fl;
1046 
1047   if (AM_clipMline(ml, &fl))
1048     AM_drawFline(&fl, color); // draws it on frame buffer using fb coords
1049 // }
1050 }
1051 
1052 void AM_drawGrid(int color)
1053 {
1054   fixed_t x, y;
1055   fixed_t start, end;
1056   mline_t ml;
1057 
1058   // Figure out start of vertical gridlines
1059   start = m_x;
1060   if ((start-bmaporgx)%(MAPBLOCKUNITS<<FRACBITS))
1061     start += (MAPBLOCKUNITS<<FRACBITS)
1062       - ((start-bmaporgx)%(MAPBLOCKUNITS<<FRACBITS));
1063   end = m_x + m_w;
1064 
1065   // draw vertical gridlines
1066   ml.a.y = m_y;
1067   ml.b.y = m_y+m_h;
1068   for (x=start; x<end; x+=(MAPBLOCKUNITS<<FRACBITS))
1069   {
1070     ml.a.x = x;
1071     ml.b.x = x;
1072     AM_drawMline(&ml, color);
1073   }
1074 
1075   // Figure out start of horizontal gridlines
1076   start = m_y;
1077   if ((start-bmaporgy)%(MAPBLOCKUNITS<<FRACBITS))
1078     start += (MAPBLOCKUNITS<<FRACBITS)
1079       - ((start-bmaporgy)%(MAPBLOCKUNITS<<FRACBITS));
1080   end = m_y + m_h;
1081 
1082   // draw horizontal gridlines
1083   ml.a.x = m_x;
1084   ml.b.x = m_x + m_w;
1085   for (y=start; y<end; y+=(MAPBLOCKUNITS<<FRACBITS))
1086   {
1087     ml.a.y = y;
1088     ml.b.y = y;
1089     AM_drawMline(&ml, color);
1090   }
1091 }
1092 
1093 void AM_drawWalls(void)
1094 {
1095   int i;
1096   static mline_t l;
1097 
1098 /*  if (use_gl) { for GL
1099     //OGL_SetNoTexture();
1100     glDisable( GL_TEXTURE_2D );
1101 
1102     glLineWidth(2.5);
1103     glBegin(GL_LINES);  // We'll draw pretty much all of them.
1104     for(i=0;i<numlines;i++)
1105     {
1106         if (cheating || (lines[i].flags & ML_MAPPED))
1107         {
1108             if ((lines[i].flags & LINE_NEVERSEE) && !cheating)
1109                 continue;
1110             if (!lines[i].backsector)
1111             {
1112                 OGL_SetColor(WALLCOLORS);
1113             }
1114             else
1115             {
1116                 if (lines[i].flags & ML_SECRET) // secret door
1117                 {
1118                     if (cheating) //AM_drawMline(&l, 0);
1119                         OGL_SetColor(0);
1120                     else
1121                         OGL_SetColor(WALLCOLORS);
1122                 }
1123                 else if(lines[i].special == 13 || lines[i].special == 83)
1124                 { // Locked door line -- all locked doors are greed
1125                     OGL_SetColor(GREENKEY);
1126                 }
1127                 else if(lines[i].special == 70 || lines[i].special == 71)
1128                 { // intra-level teleports are blue
1129                     OGL_SetColor(BLUEKEY);
1130                 }
1131                 else if(lines[i].special == 74 || lines[i].special == 75)
1132                 { // inter-level teleport/game-winning exit -- both are red
1133                     OGL_SetColor(BLOODRED);
1134                 }
1135                 else if (lines[i].backsector->floorheight
1136                     != lines[i].frontsector->floorheight)
1137                 {
1138                     // floor level change
1139                     OGL_SetColor(FDWALLCOLORS);
1140                 }
1141                 else if (lines[i].backsector->ceilingheight
1142                     != lines[i].frontsector->ceilingheight)
1143                 {
1144                     // ceiling level change
1145                     OGL_SetColor(CDWALLCOLORS);
1146                 }
1147                 else if (cheating)
1148                 {
1149                     OGL_SetColor(TSWALLCOLORS);
1150                 }
1151                 else continue;
1152             }
1153         }
1154         else if (plr->powers[pw_allmap])
1155         {
1156             if (!(lines[i].flags & LINE_NEVERSEE))
1157                 OGL_SetColor(GRAYS+3);
1158             else
1159                 continue;
1160         }
1161         else continue;
1162 
1163         // Draw the line. 1.2 is the to-square aspect corrector.
1164         glVertex2f( FIX2FLT(CXMTOFX(lines[i].v1->x)),
1165                     FIX2FLT(CYMTOFX(lines[i].v1->y))/1.2);
1166         glVertex2f( FIX2FLT(CXMTOFX(lines[i].v2->x)),
1167                     FIX2FLT(CYMTOFX(lines[i].v2->y))/1.2);
1168     }
1169     glEnd();
1170     glLineWidth(1.0);
1171     glEnable( GL_TEXTURE_2D );
1172 
1173   }
1174   else
1175   {*/
1176 
1177   for (i=0;i<numlines;i++)
1178   {
1179     l.a.x = lines[i].v1->x;
1180     l.a.y = lines[i].v1->y;
1181     l.b.x = lines[i].v2->x;
1182     l.b.y = lines[i].v2->y;
1183     if (cheating || (lines[i].flags & ML_MAPPED))
1184     {
1185       if ((lines[i].flags & LINE_NEVERSEE) && !cheating)
1186 			continue;
1187       if (!lines[i].backsector)
1188       {
1189         AM_drawMline(&l, WALLCOLORS+lightlev);
1190       } else {
1191 	if (lines[i].flags & ML_SECRET) // secret door
1192 	{
1193 	  if (cheating) AM_drawMline(&l, 0);
1194 	  else AM_drawMline(&l, WALLCOLORS+lightlev);
1195 	}
1196 	else if(lines[i].special == 13 || lines[i].special == 83)
1197 	{ // Locked door line -- all locked doors are greed
1198 		AM_drawMline(&l, GREENKEY);
1199 	}
1200 	else if(lines[i].special == 70 || lines[i].special == 71)
1201 	{ // intra-level teleports are blue
1202 		AM_drawMline(&l, BLUEKEY);
1203 	}
1204 	else if(lines[i].special == 74 || lines[i].special == 75)
1205 	{ // inter-level teleport/game-winning exit -- both are red
1206 		AM_drawMline(&l, BLOODRED);
1207 	}
1208 	else if (lines[i].backsector->floorheight
1209 		   != lines[i].frontsector->floorheight) {
1210 	  AM_drawMline(&l, FDWALLCOLORS + lightlev); // floor level change
1211 	} else if (lines[i].backsector->ceilingheight
1212 		   != lines[i].frontsector->ceilingheight) {
1213 	  AM_drawMline(&l, CDWALLCOLORS+lightlev); // ceiling level change
1214 	} else if (cheating) {
1215 	  AM_drawMline(&l, TSWALLCOLORS+lightlev);
1216 	}
1217       }
1218     } else if (plr->powers[pw_allmap])
1219     {
1220       if (!(lines[i].flags & LINE_NEVERSEE)) AM_drawMline(&l, GRAYS+3);
1221     }
1222   }
1223 //  }
1224 }
1225 
1226 void AM_rotate(fixed_t *x, fixed_t *y, angle_t a)
1227 {
1228   fixed_t tmpx;
1229 
1230   tmpx = FixedMul(*x,finecosine[a>>ANGLETOFINESHIFT])
1231        - FixedMul(*y,finesine[a>>ANGLETOFINESHIFT]);
1232   *y   = FixedMul(*x,finesine[a>>ANGLETOFINESHIFT])
1233        + FixedMul(*y,finecosine[a>>ANGLETOFINESHIFT]);
1234   *x = tmpx;
1235 }
1236 
1237 void AM_drawLineCharacter(mline_t *lineguy, int lineguylines, fixed_t scale,
1238   angle_t angle, int color, fixed_t x, fixed_t y)
1239 {
1240   int i;
1241   mline_t l;
1242 
1243   for (i=0;i<lineguylines;i++)
1244   {
1245     l.a.x = lineguy[i].a.x;
1246     l.a.y = lineguy[i].a.y;
1247     if (scale)
1248     {
1249       l.a.x = FixedMul(scale, l.a.x);
1250       l.a.y = FixedMul(scale, l.a.y);
1251     }
1252     if (angle) AM_rotate(&l.a.x, &l.a.y, angle);
1253     l.a.x += x;
1254     l.a.y += y;
1255 
1256     l.b.x = lineguy[i].b.x;
1257     l.b.y = lineguy[i].b.y;
1258     if (scale)
1259     {
1260       l.b.x = FixedMul(scale, l.b.x);
1261       l.b.y = FixedMul(scale, l.b.y);
1262     }
1263     if (angle) AM_rotate(&l.b.x, &l.b.y, angle);
1264     l.b.x += x;
1265     l.b.y += y;
1266 
1267     AM_drawMline(&l, color);
1268   }
1269 }
1270 
1271 void AM_drawPlayers(void)
1272 {
1273 	int i;
1274 	player_t *p;
1275 	static int their_colors[] =
1276 	{
1277 		AM_PLR1_COLOR,
1278 		AM_PLR2_COLOR,
1279 		AM_PLR3_COLOR,
1280 		AM_PLR4_COLOR,
1281 		AM_PLR5_COLOR,
1282 		AM_PLR6_COLOR,
1283 		AM_PLR7_COLOR,
1284 		AM_PLR8_COLOR
1285 	};
1286 	int their_color = -1;
1287 	int color;
1288 
1289 	if(!netgame)
1290 	{
1291 		AM_drawLineCharacter(player_arrow, NUMPLYRLINES, 0, plr->mo->angle,
1292 			WHITE, plr->mo->x, plr->mo->y);
1293 		return;
1294 	}
1295 
1296 	for(i = 0; i < MAXPLAYERS; i++)
1297 	{
1298 		their_color++;
1299 		p = &players[i];
1300 		if(deathmatch && !singledemo && p != plr)
1301 		{
1302 			continue;
1303 		}
1304 		if (!playeringame[i]) continue;
1305 		color = their_colors[their_color];
1306 		AM_drawLineCharacter(player_arrow, NUMPLYRLINES, 0, p->mo->angle,
1307 								color, p->mo->x, p->mo->y);
1308 	}
1309 }
1310 
1311 void AM_drawThings(int colors, int colorrange)
1312 {
1313   int i;
1314   mobj_t *t;
1315 
1316   for (i=0;i<numsectors;i++)
1317   {
1318     t = sectors[i].thinglist;
1319     while (t)
1320     {
1321       AM_drawLineCharacter(thintriangle_guy, NUMTHINTRIANGLEGUYLINES,
1322 				16<<FRACBITS, t->angle, colors+lightlev, t->x, t->y);
1323       t = t->snext;
1324     }
1325   }
1326 }
1327 
1328 /*
1329 void AM_drawMarks(void)
1330 {
1331   int i, fx, fy, w, h;
1332 
1333   for (i=0;i<AM_NUMMARKPOINTS;i++)
1334   {
1335     if (markpoints[i].x != -1)
1336     {
1337       w = SHORT(marknums[i]->width);
1338       h = SHORT(marknums[i]->height);
1339       fx = CXMTOF(markpoints[i].x);
1340       fy = CYMTOF(markpoints[i].y);
1341       if (fx >= f_x && fx <= f_w - w && fy >= f_y && fy <= f_h - h)
1342   			V_DrawPatch(fx, fy, marknums[i]);
1343     }
1344   }
1345 }
1346 */
1347 /*
1348 void AM_drawkeys(void)
1349 {
1350 	if(KeyPoints[0].x != 0 || KeyPoints[0].y != 0)
1351 	{
1352 		AM_drawLineCharacter(keysquare, NUMKEYSQUARELINES, 0, 0, YELLOWKEY,
1353 			KeyPoints[0].x, KeyPoints[0].y);
1354 	}
1355 	if(KeyPoints[1].x != 0 || KeyPoints[1].y != 0)
1356 	{
1357 		AM_drawLineCharacter(keysquare, NUMKEYSQUARELINES, 0, 0, GREENKEY,
1358 			KeyPoints[1].x, KeyPoints[1].y);
1359 	}
1360 	if(KeyPoints[2].x != 0 || KeyPoints[2].y != 0)
1361 	{
1362 		AM_drawLineCharacter(keysquare, NUMKEYSQUARELINES, 0, 0, BLUEKEY,
1363 			KeyPoints[2].x, KeyPoints[2].y);
1364 	}
1365 }
1366 */
1367 
1368 /*
1369 void AM_drawCrosshair(int color)
1370 {
1371   fb[(f_w*(f_h+1))/2] = color; // single point for now
1372 }
1373 */
1374 
1375 #if 0
1376 // for GL
1377 void AM_OGL_SetupState()
1378 {
1379     float ys = screenHeight/200.0;
1380 
1381     // Let's set up a scissor box to clip the map lines and stuff.
1382     glPushAttrib(GL_SCISSOR_BIT);
1383     glScissor(0, screenHeight-finit_height*ys, screenWidth, finit_height*ys);
1384     glEnable(GL_SCISSOR_TEST);
1385 }
1386 
1387 void AM_OGL_RestoreState()
1388 {
1389     glPopAttrib();
1390 }
1391 #endif
1392 
1393 void AM_Drawer (void)
1394 {
1395   if (!automapactive) return;
1396 
1397   UpdateState |= I_FULLSCRN;
1398 
1399 #if 0
1400     // Update the height (in case sbarscale has been changed).
1401   if (use_gl)
1402     finit_height = SCREENHEIGHT-SBARHEIGHT*sbarscale/20; /*-3*/
1403 #endif
1404 
1405   AM_clearFB(BACKGROUND);
1406 
1407 #if 0
1408   if (use_gl)
1409     AM_OGL_SetupState();
1410 #endif
1411 
1412   if (grid) AM_drawGrid(GRIDCOLORS);
1413   AM_drawWalls();
1414   AM_drawPlayers();
1415 	DrawWorldTimer();
1416 
1417   if (cheating==2) AM_drawThings(THINGCOLORS, THINGRANGE);
1418 
1419 //  AM_drawCrosshair(XHAIRCOLORS);
1420 //  AM_drawMarks();
1421 //	if(gameskill == sk_baby) AM_drawkeys();
1422 
1423 #if 0
1424    if (use_gl)
1425     AM_OGL_RestoreState();
1426 #endif
1427 
1428 
1429 	MN_DrTextA(P_GetMapName(gamemap), 38, 144);
1430 	if(ShowKills && netgame && deathmatch)
1431 	{
1432 		AM_DrawDeathmatchStats();
1433 	}
1434 //  I_Update();
1435 //  V_MarkRect(f_x, f_y, f_w, f_h);
1436 
1437 }
1438 
1439 //===========================================================================
1440 //
1441 // AM_DrawDeathmatchStats
1442 //
1443 //===========================================================================
1444 
1445 // 8-player note:  Proper player color names here, too
1446 
1447 char *PlayerColorText[MAXPLAYERS] =
1448 {
1449 	"BLUE:",
1450 	"RED:",
1451 	"YELLOW:",
1452 	"GREEN:",
1453 //	"JADE:",
1454 //	"WHITE:",
1455 //	"HAZEL:",
1456 //	"PURPLE:"
1457 };
1458 
1459 void AM_DrawDeathmatchStats(void)
1460 {
1461 	int i, j, k, m;
1462 	int fragCount[MAXPLAYERS];
1463 	int order[MAXPLAYERS];
1464 	char textBuffer[80];
1465 	int yPosition;
1466 
1467 	for(i = 0; i < MAXPLAYERS; i++)
1468 	{
1469 		fragCount[i] = 0;
1470 		order[i] = -1;
1471 	}
1472 	for(i = 0; i < MAXPLAYERS; i++)
1473 	{
1474 		if(!playeringame[i])
1475 		{
1476 			continue;
1477 		}
1478 		else
1479 		{
1480 			for(j = 0; j < MAXPLAYERS; j++)
1481 			{
1482 				if(playeringame[j])
1483 				{
1484 					fragCount[i] += players[i].frags[j];
1485 				}
1486 			}
1487 			for(k = 0; k < MAXPLAYERS; k++)
1488 			{
1489 				if(order[k] == -1)
1490 				{
1491 					order[k] = i;
1492 					break;
1493 				}
1494 				else if(fragCount[i] > fragCount[order[k]])
1495 				{
1496 					for(m = MAXPLAYERS-1; m > k; m--)
1497 					{
1498 						 order[m] = order[m-1];
1499 					}
1500 					order[k] = i;
1501 					break;
1502 				}
1503 			}
1504 		}
1505 	}
1506 	yPosition = 15;
1507 	for(i = 0; i < MAXPLAYERS; i++)
1508 	{
1509 		if(!playeringame[order[i]])
1510 		{
1511 			continue;
1512 		}
1513 		else
1514 		{
1515 			MN_DrTextA(PlayerColorText[order[i]], 8, yPosition);
1516 			sprintf(textBuffer, "%d", fragCount[order[i]]);
1517 			MN_DrTextA(textBuffer, 80, yPosition);
1518 			yPosition += 10;
1519 		}
1520 	}
1521 }
1522 
1523 //===========================================================================
1524 //
1525 // DrawWorldTimer
1526 //
1527 //===========================================================================
1528 
1529 static void DrawWorldTimer(void)
1530 {
1531 	int days;
1532 	int hours;
1533 	int minutes;
1534 	int seconds;
1535 	int worldTimer;
1536 	char timeBuffer[15];
1537 	char dayBuffer[20];
1538 
1539 	worldTimer = players[consoleplayer].worldTimer;
1540 
1541 	worldTimer /= 35;
1542 	days = worldTimer/86400;
1543 	worldTimer -= days*86400;
1544 	hours = worldTimer/3600;
1545 	worldTimer -= hours*3600;
1546 	minutes = worldTimer/60;
1547 	worldTimer -= minutes*60;
1548 	seconds = worldTimer;
1549 
1550 	sprintf(timeBuffer, "%.2d : %.2d : %.2d", hours, minutes,seconds);
1551 	MN_DrTextA(timeBuffer, 240, 8);
1552 
1553 	if (days)
1554 	{
1555 		if (days==1)
1556 		{
1557 			sprintf(dayBuffer, "%.2d DAY", days);
1558 		}
1559 		else
1560 		{
1561 			sprintf(dayBuffer, "%.2d DAYS", days);
1562 		}
1563 		MN_DrTextA(dayBuffer, 240, 20);
1564 		if (days >= 5)
1565 		{
1566 			MN_DrTextA("YOU FREAK!!!", 230, 35);
1567 		}
1568 	}
1569 }
1570