am_map.c (19937B)
1 #include <stdio.h> 2 #include <limits.h> 3 4 #include "z_zone.h" 5 #include "doomdef.h" 6 #include "st_stuff.h" 7 #include "p_local.h" 8 #include "w_wad.h" 9 #include "m_cheat.h" 10 #include "i_system.h" 11 #include "v_video.h" 12 #include "doomstat.h" 13 #include "r_state.h" 14 #include "dstrings.h" 15 #include "am_map.h" 16 17 #define REDS (256-5*16) 18 #define REDRANGE 16 19 #define BLUES (256-4*16+8) 20 #define BLUERANGE 8 21 #define GREENS (7*16) 22 #define GREENRANGE 16 23 #define GRAYS (6*16) 24 #define GRAYSRANGE 16 25 #define BROWNS (4*16) 26 #define BROWNRANGE 16 27 #define YELLOWS (256-32+7) 28 #define YELLOWRANGE 1 29 #define BLACK 0 30 #define WHITE (256-47) 31 #define BACKGROUND BLACK 32 #define YOURCOLORS WHITE 33 #define YOURRANGE 0 34 #define WALLCOLORS REDS 35 #define WALLRANGE REDRANGE 36 #define TSWALLCOLORS GRAYS 37 #define TSWALLRANGE GRAYSRANGE 38 #define FDWALLCOLORS BROWNS 39 #define FDWALLRANGE BROWNRANGE 40 #define CDWALLCOLORS YELLOWS 41 #define CDWALLRANGE YELLOWRANGE 42 #define THINGCOLORS GREENS 43 #define THINGRANGE GREENRANGE 44 #define SECRETWALLCOLORS WALLCOLORS 45 #define SECRETWALLRANGE WALLRANGE 46 #define GRIDCOLORS (GRAYS + GRAYSRANGE/2) 47 #define GRIDRANGE 0 48 #define XHAIRCOLORS GRAYS 49 #define FB 0 50 #define AM_PANDOWNKEY KEY_DOWNARROW 51 #define AM_PANUPKEY KEY_UPARROW 52 #define AM_PANRIGHTKEY KEY_RIGHTARROW 53 #define AM_PANLEFTKEY KEY_LEFTARROW 54 #define AM_ZOOMINKEY '=' 55 #define AM_ZOOMOUTKEY '-' 56 #define AM_STARTKEY KEY_TAB 57 #define AM_ENDKEY KEY_TAB 58 #define AM_GOBIGKEY '0' 59 #define AM_FOLLOWKEY 'f' 60 #define AM_GRIDKEY 'g' 61 #define AM_MARKKEY 'm' 62 #define AM_CLEARMARKKEY 'c' 63 #define AM_NUMMARKPOINTS 10 64 #define INITSCALEMTOF (.2*FRACUNIT) 65 #define F_PANINC 4 66 #define M_ZOOMIN ((int) (1.02*FRACUNIT)) 67 #define M_ZOOMOUT ((int) (FRACUNIT/1.02)) 68 #define FTOM(x) FixedMul(((x)<<16),scale_ftom) 69 #define MTOF(x) (FixedMul((x),scale_mtof)>>16) 70 #define CXMTOF(x) (f_x + MTOF((x)-m_x)) 71 #define CYMTOF(y) (f_y + (f_h - MTOF((y)-m_y))) 72 #define LINE_NEVERSEE ML_DONTDRAW 73 #define NUMPLYRLINES (sizeof(player_arrow)/sizeof(mline_t)) 74 #define NUMCHEATPLYRLINES (sizeof(cheat_player_arrow)/sizeof(mline_t)) 75 #define NUMTRIANGLEGUYLINES (sizeof(triangle_guy)/sizeof(mline_t)) 76 #define NUMTHINTRIANGLEGUYLINES (sizeof(thintriangle_guy)/sizeof(mline_t)) 77 #define PUTDOT(xx,yy,cc) fb[(yy)*f_w+(xx)]=(cc) 78 #define DOOUTCODE(oc, mx, my) \ 79 (oc) = 0; \ 80 if ((my) < 0) (oc) |= TOP; \ 81 if ((my) >= f_h) (oc) |= BOTTOM; \ 82 if ((mx) < 0) (oc) |= LEFT; \ 83 if ((mx) >= f_w) (oc) |= RIGHT; 84 85 typedef struct { 86 int x, y; 87 }fpoint_t; 88 89 typedef struct { 90 fpoint_t a, b; 91 }fline_t; 92 93 typedef struct { 94 fixed_t x,y; 95 }mpoint_t; 96 97 typedef struct { 98 mpoint_t a, b; 99 }mline_t; 100 101 typedef struct { 102 fixed_t slp, islp; 103 }islope_t; 104 105 #define R ((8*PLAYERRADIUS)/7) 106 107 mline_t player_arrow[] = { 108 {{ -R+R/8, 0 }, { R, 0 }}, 109 {{ R, 0 }, { R-R/2, R/4 }}, 110 {{ R, 0 }, { R-R/2, -R/4 }}, 111 {{ -R+R/8, 0 }, { -R-R/8, R/4 }}, 112 {{ -R+R/8, 0 }, { -R-R/8, -R/4 }}, 113 {{ -R+3*R/8, 0 }, { -R+R/8, R/4 }}, 114 {{ -R+3*R/8, 0 }, { -R+R/8, -R/4 }} 115 }; 116 #undef R 117 118 #define R ((8*PLAYERRADIUS)/7) 119 mline_t cheat_player_arrow[] = { 120 { { -R+R/8, 0 }, { R, 0 } }, 121 { { R, 0 }, { R-R/2, R/6 } }, 122 { { R, 0 }, { R-R/2, -R/6 } }, 123 { { -R+R/8, 0 }, { -R-R/8, R/6 } }, 124 { { -R+R/8, 0 }, { -R-R/8, -R/6 } }, 125 { { -R+3*R/8, 0 }, { -R+R/8, R/6 } }, 126 { { -R+3*R/8, 0 }, { -R+R/8, -R/6 } }, 127 { { -R/2, 0 }, { -R/2, -R/6 } }, 128 { { -R/2, -R/6 }, { -R/2+R/6, -R/6 } }, 129 { { -R/2+R/6, -R/6 }, { -R/2+R/6, R/4 } }, 130 { { -R/6, 0 }, { -R/6, -R/6 } }, 131 { { -R/6, -R/6 }, { 0, -R/6 } }, 132 { { 0, -R/6 }, { 0, R/4 } }, 133 { { R/6, R/4 }, { R/6, -R/7 } }, 134 { { R/6, -R/7 }, { R/6+R/32, -R/7-R/32 } }, 135 { { R/6+R/32, -R/7-R/32 }, { R/6+R/10, -R/7 } } 136 }; 137 #undef R 138 139 #define R (FRACUNIT) 140 mline_t triangle_guy[] = { 141 { { -.867*R, -.5*R }, { .867*R, -.5*R } }, 142 { { .867*R, -.5*R } , { 0, R } }, 143 { { 0, R }, { -.867*R, -.5*R } } 144 }; 145 #undef R 146 147 #define R (FRACUNIT) 148 mline_t thintriangle_guy[] = { 149 { { -.5*R, -.7*R }, { R, 0 } }, 150 { { R, 0 }, { -.5*R, .7*R } }, 151 { { -.5*R, .7*R }, { -.5*R, -.7*R } } 152 }; 153 #undef R 154 155 static int cheating = 0; 156 static int grid = 0; 157 static int leveljuststarted = 1; 158 boolean automapactive = false; 159 static int finit_width = SCREENWIDTH; 160 static int finit_height = SCREENHEIGHT - 32; 161 static int f_x; 162 static int f_y; 163 static int f_w; 164 static int f_h; 165 static int lightlev; 166 static byte* fb; 167 static int amclock; 168 static mpoint_t m_paninc; 169 static fixed_t mtof_zoommul; 170 static fixed_t ftom_zoommul; 171 static fixed_t m_x, m_y; 172 static fixed_t m_x2, m_y2; 173 static fixed_t m_w; 174 static fixed_t m_h; 175 static fixed_t min_x; 176 static fixed_t min_y; 177 static fixed_t max_x; 178 static fixed_t max_y; 179 static fixed_t max_w; 180 static fixed_t max_h; 181 static fixed_t min_w; 182 static fixed_t min_h; 183 static fixed_t min_scale_mtof; 184 static fixed_t max_scale_mtof; 185 static fixed_t old_m_w, old_m_h; 186 static fixed_t old_m_x, old_m_y; 187 static mpoint_t f_oldloc; 188 static fixed_t scale_mtof = INITSCALEMTOF; 189 static fixed_t scale_ftom; 190 static player_t *plr; 191 static patch_t *marknums[10]; 192 static mpoint_t markpoints[AM_NUMMARKPOINTS]; 193 static int markpointnum = 0; 194 static int followplayer = 1; 195 static unsigned char cheat_amap_seq[] = { 0xb2, 0x26, 0x26, 0x2e, 0xff }; 196 static cheatseq_t cheat_amap = { cheat_amap_seq, 0 }; 197 static boolean stopped = true; 198 extern boolean viewactive; 199 200 void V_MarkRect(int x, int y, int width, int height); 201 202 void 203 AM_getIslope(mline_t* ml, islope_t* is) 204 { 205 int dx, dy; 206 207 dy = ml->a.y - ml->b.y; 208 dx = ml->b.x - ml->a.x; 209 if (!dy) is->islp = (dx<0?-INT_MAX:INT_MAX); 210 else is->islp = FixedDiv(dx, dy); 211 if (!dx) is->slp = (dy<0?-INT_MAX:INT_MAX); 212 else is->slp = FixedDiv(dy, dx); 213 } 214 215 void 216 AM_activateNewScale() 217 { 218 m_x += m_w/2; 219 m_y += m_h/2; 220 m_w = FTOM(f_w); 221 m_h = FTOM(f_h); 222 m_x -= m_w/2; 223 m_y -= m_h/2; 224 m_x2 = m_x + m_w; 225 m_y2 = m_y + m_h; 226 } 227 228 void 229 AM_saveScaleAndLoc() 230 { 231 old_m_x = m_x; 232 old_m_y = m_y; 233 old_m_w = m_w; 234 old_m_h = m_h; 235 } 236 237 void 238 AM_restoreScaleAndLoc() 239 { 240 m_w = old_m_w; 241 m_h = old_m_h; 242 if (!followplayer) { 243 m_x = old_m_x; 244 m_y = old_m_y; 245 } else { 246 m_x = plr->mo->x - m_w/2; 247 m_y = plr->mo->y - m_h/2; 248 } 249 m_x2 = m_x + m_w; 250 m_y2 = m_y + m_h; 251 scale_mtof = FixedDiv(f_w<<FRACBITS, m_w); 252 scale_ftom = FixedDiv(FRACUNIT, scale_mtof); 253 } 254 255 void 256 AM_addMark() 257 { 258 markpoints[markpointnum].x = m_x + m_w/2; 259 markpoints[markpointnum].y = m_y + m_h/2; 260 markpointnum = (markpointnum + 1) % AM_NUMMARKPOINTS; 261 } 262 263 void 264 AM_findMinMaxBoundaries() 265 { 266 int i; 267 fixed_t a; 268 fixed_t b; 269 270 min_x = min_y = INT_MAX; 271 max_x = max_y = -INT_MAX; 272 for (i = 0; i < numvertexes; ++i) { 273 if (vertexes[i].x < min_x) min_x = vertexes[i].x; 274 if (vertexes[i].x > max_x) max_x = vertexes[i].x; 275 if (vertexes[i].y < min_y) min_y = vertexes[i].y; 276 if (vertexes[i].y > max_y) max_y = vertexes[i].y; 277 } 278 max_w = max_x - min_x; 279 max_h = max_y - min_y; 280 min_w = 2 * PLAYERRADIUS; 281 min_h = 2 * PLAYERRADIUS; 282 a = FixedDiv(f_w << FRACBITS, max_w); 283 b = FixedDiv(f_h << FRACBITS, max_h); 284 min_scale_mtof = a < b ? a : b; 285 max_scale_mtof = FixedDiv(f_h<<FRACBITS, 2*PLAYERRADIUS); 286 } 287 288 void 289 AM_changeWindowLoc() 290 { 291 if (m_paninc.x || m_paninc.y) { 292 followplayer = 0; 293 f_oldloc.x = INT_MAX; 294 } 295 m_x += m_paninc.x; 296 m_y += m_paninc.y; 297 if (m_x + m_w/2 > max_x) m_x = max_x - m_w/2; 298 if (m_x + m_w/2 < min_x) m_x = min_x - m_w/2; 299 if (m_y + m_h/2 > max_y) m_y = max_y - m_h/2; 300 if (m_y + m_h/2 < min_y) m_y = min_y - m_h/2; 301 m_x2 = m_x + m_w; 302 m_y2 = m_y + m_h; 303 } 304 305 void 306 AM_initVariables() 307 { 308 static event_t st_notify = { ev_keyup, AM_MSGENTERED }; 309 int pnum; 310 311 automapactive = true; 312 fb = screens[0]; 313 f_oldloc.x = INT_MAX; 314 amclock = 0; 315 lightlev = 0; 316 m_paninc.x = m_paninc.y = 0; 317 ftom_zoommul = FRACUNIT; 318 mtof_zoommul = FRACUNIT; 319 m_w = FTOM(f_w); 320 m_h = FTOM(f_h); 321 if (!playeringame[pnum = consoleplayer]) 322 for (pnum=0;pnum<MAXPLAYERS;pnum++) 323 if (playeringame[pnum]) break; 324 plr = &players[pnum]; 325 m_x = plr->mo->x - m_w/2; 326 m_y = plr->mo->y - m_h/2; 327 AM_changeWindowLoc(); 328 old_m_x = m_x; 329 old_m_y = m_y; 330 old_m_w = m_w; 331 old_m_h = m_h; 332 ST_Responder(&st_notify); 333 } 334 335 void 336 AM_loadPics() 337 { 338 int i; 339 char namebuf[9]; 340 341 for (i = 0; i < 10; ++i) { 342 sprintf(namebuf, "AMMNUM%d", i); 343 marknums[i] = W_CacheLumpName(namebuf, PU_STATIC); 344 } 345 } 346 347 void 348 AM_unloadPics() 349 { 350 int i; 351 352 for (i=0;i<10;i++) 353 Z_ChangeTag(marknums[i], PU_CACHE); 354 355 } 356 357 void AM_clearMarks() 358 { 359 int i; 360 361 for (i=0;i<AM_NUMMARKPOINTS;i++) 362 markpoints[i].x = -1; 363 markpointnum = 0; 364 } 365 366 void 367 AM_LevelInit() 368 { 369 leveljuststarted = 0; 370 f_x = f_y = 0; 371 f_w = finit_width; 372 f_h = finit_height; 373 AM_clearMarks(); 374 AM_findMinMaxBoundaries(); 375 scale_mtof = FixedDiv(min_scale_mtof, (int) (0.7*FRACUNIT)); 376 if (scale_mtof > max_scale_mtof) scale_mtof = min_scale_mtof; 377 scale_ftom = FixedDiv(FRACUNIT, scale_mtof); 378 } 379 380 void 381 AM_Stop() 382 { 383 static event_t st_notify = { 0, ev_keyup, AM_MSGEXITED }; 384 385 AM_unloadPics(); 386 automapactive = false; 387 ST_Responder(&st_notify); 388 stopped = true; 389 } 390 391 void 392 AM_Start() 393 { 394 static int lastlevel = -1, lastepisode = -1; 395 396 if (!stopped) 397 AM_Stop(); 398 stopped = false; 399 if (lastlevel != gamemap || lastepisode != gameepisode) { 400 AM_LevelInit(); 401 lastlevel = gamemap; 402 lastepisode = gameepisode; 403 } 404 AM_initVariables(); 405 AM_loadPics(); 406 } 407 408 void 409 AM_minOutWindowScale() 410 { 411 scale_mtof = min_scale_mtof; 412 scale_ftom = FixedDiv(FRACUNIT, scale_mtof); 413 AM_activateNewScale(); 414 } 415 416 void 417 AM_maxOutWindowScale() 418 { 419 scale_mtof = max_scale_mtof; 420 scale_ftom = FixedDiv(FRACUNIT, scale_mtof); 421 AM_activateNewScale(); 422 } 423 424 boolean 425 AM_Responder(event_t* ev) 426 { 427 static int bigstate=0; 428 static char buffer[20]; 429 int rc; 430 431 rc = false; 432 if (!automapactive) { 433 if (ev->type == ev_keydown && ev->data1 == AM_STARTKEY) { 434 AM_Start(); 435 viewactive = false; 436 rc = true; 437 } 438 } 439 else if (ev->type == ev_keydown) { 440 rc = true; 441 switch (ev->data1) { 442 case AM_PANRIGHTKEY: 443 if (!followplayer) m_paninc.x = FTOM(F_PANINC); 444 else rc = false; 445 break; 446 case AM_PANLEFTKEY: 447 if (!followplayer) m_paninc.x = -FTOM(F_PANINC); 448 else rc = false; 449 break; 450 case AM_PANUPKEY: 451 if (!followplayer) m_paninc.y = FTOM(F_PANINC); 452 else rc = false; 453 break; 454 case AM_PANDOWNKEY: 455 if (!followplayer) m_paninc.y = -FTOM(F_PANINC); 456 else rc = false; 457 break; 458 case AM_ZOOMOUTKEY: 459 mtof_zoommul = M_ZOOMOUT; 460 ftom_zoommul = M_ZOOMIN; 461 break; 462 case AM_ZOOMINKEY: 463 mtof_zoommul = M_ZOOMIN; 464 ftom_zoommul = M_ZOOMOUT; 465 break; 466 case AM_ENDKEY: 467 bigstate = 0; 468 viewactive = true; 469 AM_Stop(); 470 break; 471 case AM_GOBIGKEY: 472 bigstate = !bigstate; 473 if (bigstate) { 474 AM_saveScaleAndLoc(); 475 AM_minOutWindowScale(); 476 } 477 else AM_restoreScaleAndLoc(); 478 break; 479 case AM_FOLLOWKEY: 480 followplayer = !followplayer; 481 f_oldloc.x = INT_MAX; 482 plr->message = followplayer ? lang[AMSTR_FOLLOWON] : lang[AMSTR_FOLLOWOFF]; 483 break; 484 case AM_GRIDKEY: 485 grid = !grid; 486 plr->message = grid ? lang[AMSTR_GRIDON] : lang[AMSTR_GRIDOFF]; 487 break; 488 case AM_MARKKEY: 489 sprintf(buffer, "%s %d", lang[AMSTR_MARKEDSPOT], markpointnum); 490 plr->message = buffer; 491 AM_addMark(); 492 break; 493 case AM_CLEARMARKKEY: 494 AM_clearMarks(); 495 plr->message = lang[AMSTR_MARKSCLEARED]; 496 break; 497 default: 498 rc = false; 499 } 500 if (!deathmatch && cht_CheckCheat(&cheat_amap, ev->data1)) { 501 rc = false; 502 cheating = (cheating+1) % 3; 503 } 504 } 505 else if (ev->type == ev_keyup) { 506 rc = false; 507 switch (ev->data1) { 508 case AM_PANRIGHTKEY: 509 if (!followplayer) m_paninc.x = 0; 510 break; 511 case AM_PANLEFTKEY: 512 if (!followplayer) m_paninc.x = 0; 513 break; 514 case AM_PANUPKEY: 515 if (!followplayer) m_paninc.y = 0; 516 break; 517 case AM_PANDOWNKEY: 518 if (!followplayer) m_paninc.y = 0; 519 break; 520 case AM_ZOOMOUTKEY: 521 case AM_ZOOMINKEY: 522 mtof_zoommul = FRACUNIT; 523 ftom_zoommul = FRACUNIT; 524 break; 525 } 526 } 527 return rc; 528 } 529 530 void 531 AM_changeWindowScale() 532 { 533 scale_mtof = FixedMul(scale_mtof, mtof_zoommul); 534 scale_ftom = FixedDiv(FRACUNIT, scale_mtof); 535 if (scale_mtof < min_scale_mtof) AM_minOutWindowScale(); 536 if (scale_mtof > max_scale_mtof) AM_maxOutWindowScale(); 537 else AM_activateNewScale(); 538 } 539 540 void 541 AM_doFollowPlayer() 542 { 543 if (f_oldloc.x != plr->mo->x || f_oldloc.y != plr->mo->y) { 544 m_x = FTOM(MTOF(plr->mo->x)) - m_w/2; 545 m_y = FTOM(MTOF(plr->mo->y)) - m_h/2; 546 m_x2 = m_x + m_w; 547 m_y2 = m_y + m_h; 548 f_oldloc.x = plr->mo->x; 549 f_oldloc.y = plr->mo->y; 550 } 551 } 552 553 void 554 AM_updateLightLev() 555 { 556 static int litelevels[] = { 0, 4, 7, 10, 12, 14, 15, 15 }; 557 static int nexttic = 0; 558 static int litelevelscnt = 0; 559 560 if (amclock>nexttic) { 561 lightlev = litelevels[litelevelscnt++]; 562 if (litelevelscnt == sizeof(litelevels)/sizeof(int)) litelevelscnt = 0; 563 nexttic = amclock + 6 - (amclock % 6); 564 } 565 } 566 567 void 568 AM_Ticker() 569 { 570 if (!automapactive) 571 return; 572 amclock++; 573 if (followplayer) AM_doFollowPlayer(); 574 if (ftom_zoommul != FRACUNIT) 575 AM_changeWindowScale(); 576 if (m_paninc.x || m_paninc.y) 577 AM_changeWindowLoc(); 578 } 579 580 void 581 AM_clearFB(int color) 582 { 583 memset(fb, color, f_w * f_h); 584 } 585 586 boolean 587 AM_clipMline(mline_t* ml, fline_t* fl) 588 { 589 enum { 590 LEFT =1, 591 RIGHT =2, 592 BOTTOM =4, 593 TOP =8 594 }; 595 596 int outcode1, outcode2, outside, dx, dy; 597 fpoint_t tmp; 598 599 outcode1 = outcode2 = 0; 600 if (ml->a.y > m_y2) outcode1 = TOP; 601 if (ml->a.y < m_y) outcode1 = BOTTOM; 602 if (ml->b.y > m_y2) outcode2 = TOP; 603 if (ml->b.y < m_y) outcode2 = BOTTOM; 604 if (outcode1 & outcode2) return false; 605 if (ml->a.x < m_x) outcode1 |= LEFT; 606 if (ml->a.x > m_x2) outcode1 |= RIGHT; 607 if (ml->b.x < m_x) outcode2 |= LEFT; 608 if (ml->b.x > m_x2) outcode2 |= RIGHT; 609 if (outcode1 & outcode2) return false; 610 fl->a.x = CXMTOF(ml->a.x); 611 fl->a.y = CYMTOF(ml->a.y); 612 fl->b.x = CXMTOF(ml->b.x); 613 fl->b.y = CYMTOF(ml->b.y); 614 DOOUTCODE(outcode1, fl->a.x, fl->a.y); 615 DOOUTCODE(outcode2, fl->b.x, fl->b.y); 616 if (outcode1 & outcode2) return false; 617 618 while (outcode1 | outcode2) { 619 if (outcode1) outside = outcode1; 620 else outside = outcode2; 621 if (outside & TOP) { 622 dy = fl->a.y - fl->b.y; 623 dx = fl->b.x - fl->a.x; 624 tmp.x = fl->a.x + (dx*(fl->a.y))/dy; 625 tmp.y = 0; 626 } 627 if (outside & BOTTOM) { 628 dy = fl->a.y - fl->b.y; 629 dx = fl->b.x - fl->a.x; 630 tmp.x = fl->a.x + (dx*(fl->a.y-f_h))/dy; 631 tmp.y = f_h-1; 632 } 633 if (outside & RIGHT) { 634 dy = fl->b.y - fl->a.y; 635 dx = fl->b.x - fl->a.x; 636 tmp.y = fl->a.y + (dy*(f_w-1 - fl->a.x))/dx; 637 tmp.x = f_w-1; 638 } 639 if (outside & LEFT) { 640 dy = fl->b.y - fl->a.y; 641 dx = fl->b.x - fl->a.x; 642 tmp.y = fl->a.y + (dy*(-fl->a.x))/dx; 643 tmp.x = 0; 644 } 645 if (outside == outcode1) { 646 fl->a = tmp; 647 DOOUTCODE(outcode1, fl->a.x, fl->a.y); 648 } else { 649 fl->b = tmp; 650 DOOUTCODE(outcode2, fl->b.x, fl->b.y); 651 } 652 if (outcode1 & outcode2) return false; 653 } 654 return true; 655 } 656 #undef DOOUTCODE 657 658 void 659 AM_drawFline(fline_t* fl, int color) 660 { 661 static int fuck = 0; 662 int x, y, dx, dy, sx, sy, ax, ay, d; 663 if (fl->a.x < 0 || fl->a.x >= f_w || fl->a.y < 0 || fl->a.y >= f_h || fl->b.x < 0 || fl->b.x >= f_w || fl->b.y < 0 || fl->b.y >= f_h) { 664 fprintf(stderr, "fuck %d \r", fuck++); 665 return; 666 } 667 dx = fl->b.x - fl->a.x; 668 ax = 2 * (dx<0 ? -dx : dx); 669 sx = dx<0 ? -1 : 1; 670 dy = fl->b.y - fl->a.y; 671 ay = 2 * (dy<0 ? -dy : dy); 672 sy = dy<0 ? -1 : 1; 673 x = fl->a.x; 674 y = fl->a.y; 675 if (ax > ay) { 676 d = ay - ax/2; 677 for (;;) { 678 PUTDOT(x,y,color); 679 if (x == fl->b.x) return; 680 if (d>=0) { 681 y += sy; 682 d -= ax; 683 } 684 x += sx; 685 d += ay; 686 } 687 } else { 688 d = ax - ay/2; 689 for (;;) { 690 PUTDOT(x, y, color); 691 if (y == fl->b.y) return; 692 if (d >= 0) { 693 x += sx; 694 d -= ay; 695 } 696 y += sy; 697 d += ax; 698 } 699 } 700 } 701 702 void 703 AM_drawMline(mline_t* ml, int color) 704 { 705 static fline_t fl; 706 707 if (AM_clipMline(ml, &fl)) AM_drawFline(&fl, color); 708 } 709 710 void 711 AM_drawGrid(int color) 712 { 713 fixed_t x, y, start, end; 714 mline_t ml; 715 716 start = m_x; 717 if ((start-bmaporgx)%(MAPBLOCKUNITS<<FRACBITS)) start += (MAPBLOCKUNITS<<FRACBITS) - ((start-bmaporgx)%(MAPBLOCKUNITS<<FRACBITS)); 718 end = m_x + m_w; 719 ml.a.y = m_y; 720 ml.b.y = m_y+m_h; 721 for (x=start; x<end; x+=(MAPBLOCKUNITS<<FRACBITS)) { 722 ml.a.x = x; 723 ml.b.x = x; 724 AM_drawMline(&ml, color); 725 } 726 start = m_y; 727 if ((start-bmaporgy)%(MAPBLOCKUNITS<<FRACBITS)) start += (MAPBLOCKUNITS<<FRACBITS) - ((start-bmaporgy)%(MAPBLOCKUNITS<<FRACBITS)); 728 end = m_y + m_h; 729 ml.a.x = m_x; 730 ml.b.x = m_x + m_w; 731 for (y=start; y<end; y+=(MAPBLOCKUNITS<<FRACBITS)) { 732 ml.a.y = y; 733 ml.b.y = y; 734 AM_drawMline(&ml, color); 735 } 736 } 737 738 void 739 AM_drawWalls() 740 { 741 static mline_t l; 742 int i; 743 744 for (i=0;i<numlines;i++) { 745 l.a.x = lines[i].v1->x; 746 l.a.y = lines[i].v1->y; 747 l.b.x = lines[i].v2->x; 748 l.b.y = lines[i].v2->y; 749 if (cheating || (lines[i].flags & ML_MAPPED)) { 750 if ((lines[i].flags & LINE_NEVERSEE) && !cheating) continue; 751 if (!lines[i].backsector) AM_drawMline(&l, WALLCOLORS+lightlev); 752 else { 753 if (lines[i].special == 39) AM_drawMline(&l, WALLCOLORS+WALLRANGE/2); 754 if (lines[i].flags & ML_SECRET) { 755 if (cheating) AM_drawMline(&l, SECRETWALLCOLORS + lightlev); 756 else AM_drawMline(&l, WALLCOLORS+lightlev); 757 } 758 if (lines[i].backsector->floorheight != lines[i].frontsector->floorheight) AM_drawMline(&l, FDWALLCOLORS + lightlev); 759 if (lines[i].backsector->ceilingheight != lines[i].frontsector->ceilingheight) AM_drawMline(&l, CDWALLCOLORS+lightlev); 760 if (cheating) AM_drawMline(&l, TSWALLCOLORS+lightlev); 761 } 762 } 763 if (plr->powers[pw_allmap]) 764 if (!(lines[i].flags & LINE_NEVERSEE)) AM_drawMline(&l, GRAYS+3); 765 } 766 } 767 768 void 769 AM_rotate(fixed_t* x, fixed_t* y, angle_t a) 770 { 771 fixed_t tmpx; 772 773 tmpx = FixedMul(*x,finecosine[a>>ANGLETOFINESHIFT]) - FixedMul(*y,finesine[a>>ANGLETOFINESHIFT]); 774 *y = FixedMul(*x,finesine[a>>ANGLETOFINESHIFT]) + FixedMul(*y,finecosine[a>>ANGLETOFINESHIFT]); 775 *x = tmpx; 776 } 777 778 void 779 AM_drawLineCharacter(mline_t* lineguy, int lineguylines, fixed_t scale, angle_t angle, int color, fixed_t x, fixed_t y) 780 { 781 mline_t l; 782 int i; 783 784 for (i = 0; i < lineguylines; ++i) { 785 l.a.x = lineguy[i].a.x; 786 l.a.y = lineguy[i].a.y; 787 if (scale) { 788 l.a.x = FixedMul(scale, l.a.x); 789 l.a.y = FixedMul(scale, l.a.y); 790 } 791 if (angle) AM_rotate(&l.a.x, &l.a.y, angle); 792 l.a.x += x; 793 l.a.y += y; 794 l.b.x = lineguy[i].b.x; 795 l.b.y = lineguy[i].b.y; 796 if (scale) { 797 l.b.x = FixedMul(scale, l.b.x); 798 l.b.y = FixedMul(scale, l.b.y); 799 } 800 if (angle) AM_rotate(&l.b.x, &l.b.y, angle); 801 l.b.x += x; 802 l.b.y += y; 803 AM_drawMline(&l, color); 804 } 805 } 806 807 void 808 AM_drawPlayers() 809 { 810 static int their_colors[] = { GREENS, GRAYS, BROWNS, REDS }; 811 player_t* p; 812 int i, color, their_color; 813 814 their_color = -1; 815 if (!netgame) { 816 if (cheating) AM_drawLineCharacter(cheat_player_arrow, NUMCHEATPLYRLINES, 0, plr->mo->angle, WHITE, plr->mo->x, plr->mo->y); 817 else AM_drawLineCharacter(player_arrow, NUMPLYRLINES, 0, plr->mo->angle, WHITE, plr->mo->x, plr->mo->y); 818 return; 819 } 820 for (i = 0; i < MAXPLAYERS; ++i) { 821 ++their_color; 822 p = &players[i]; 823 if ((deathmatch && !singledemo) && p != plr) continue; 824 if (!playeringame[i]) continue; 825 if (p->powers[pw_invisibility]) color = 246; 826 else color = their_colors[their_color]; 827 AM_drawLineCharacter(player_arrow, NUMPLYRLINES, 0, p->mo->angle, color, p->mo->x, p->mo->y); 828 } 829 } 830 831 void 832 AM_drawThings(int colors, int colorrange) 833 { 834 mobj_t* t; 835 int i; 836 837 for (i = 0; i < numsectors; ++i) 838 for (t = sectors[i].thinglist; t; t = t->snext) 839 AM_drawLineCharacter(thintriangle_guy, NUMTHINTRIANGLEGUYLINES, 16<<FRACBITS, t->angle, colors+lightlev, t->x, t->y); 840 } 841 842 void 843 AM_drawMarks() 844 { 845 int i, fx, fy, w, h; 846 847 for (i = 0; i < AM_NUMMARKPOINTS; ++i) { 848 if (markpoints[i].x != -1) { 849 w = 5; 850 h = 6; 851 fx = CXMTOF(markpoints[i].x); 852 fy = CYMTOF(markpoints[i].y); 853 if (fx >= f_x && fx <= f_w - w && fy >= f_y && fy <= f_h - h) V_DrawPatch(fx, fy, FB, marknums[i]); 854 } 855 } 856 } 857 858 void 859 AM_drawCrosshair(int color) 860 { 861 fb[(f_w*(f_h+1))/2] = color; 862 } 863 864 void 865 AM_Drawer() 866 { 867 if (!automapactive) 868 return; 869 AM_clearFB(BACKGROUND); 870 if (grid) AM_drawGrid(GRIDCOLORS); 871 AM_drawWalls(); 872 AM_drawPlayers(); 873 if (cheating==2) AM_drawThings(THINGCOLORS, THINGRANGE); 874 AM_drawCrosshair(XHAIRCOLORS); 875 AM_drawMarks(); 876 V_MarkRect(f_x, f_y, f_w, f_h); 877 }