1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225 |
- /*
- ===========================================================================
- Doom 3 BFG Edition GPL Source Code
- Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
- This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
- Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
- Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
- In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
- If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
- ===========================================================================
- */
- #include "Precompiled.h"
- #include "globaldata.h"
- #include <stdio.h>
- #include "z_zone.h"
- #include "doomdef.h"
- #include "st_stuff.h"
- #include "p_local.h"
- #include "w_wad.h"
- #include "m_cheat.h"
- #include "i_system.h"
- // Needs access to LFB.
- #include "v_video.h"
- // State.
- #include "doomstat.h"
- #include "r_state.h"
- // Data.
- #include "dstrings.h"
- #include "am_map.h"
- // For use if I do walls with outsides/insides
- // Automap colors
- // drawing stuff
- // scale on entry
- // how much the automap moves window per tic in frame-::g->buffer coordinates
- // moves 140 pixels in 1 second
- // how much zoom-in per tic
- // goes to 2x in 1 second
- // how much zoom-out per tic
- // pulls out to 0.5x in 1 second
- // translates between frame-::g->buffer and map distances
- // translates between frame-::g->buffer and map coordinates
- // the following is crap
- //
- // The vector graphics for the automap.
- // A line drawing of the player pointing right,
- // starting from the middle.
- //
- #define R ((8*PLAYERRADIUS)/7)
- mline_t player_arrow[] =
- {
- { { -R+R/8, 0 }, { R, 0 } }, // -----
- { { R, 0 }, { R-R/2, R/4 } }, // ----->
- { { R, 0 }, { R-R/2, -R/4 } },
- { { -R+R/8, 0 }, { -R-R/8, R/4 } }, // >---->
- { { -R+R/8, 0 }, { -R-R/8, -R/4 } },
- { { -R+3*R/8, 0 }, { -R+R/8, R/4 } }, // >>--->
- { { -R+3*R/8, 0 }, { -R+R/8, -R/4 } }
- };
- #undef R
- #define R ((8*PLAYERRADIUS)/7)
- mline_t cheat_player_arrow[] =
- {
- { { -R+R/8, 0 }, { R, 0 } }, // -----
- { { R, 0 }, { R-R/2, R/6 } }, // ----->
- { { R, 0 }, { R-R/2, -R/6 } },
- { { -R+R/8, 0 }, { -R-R/8, R/6 } }, // >----->
- { { -R+R/8, 0 }, { -R-R/8, -R/6 } },
- { { -R+3*R/8, 0 }, { -R+R/8, R/6 } }, // >>----->
- { { -R+3*R/8, 0 }, { -R+R/8, -R/6 } },
- { { -R/2, 0 }, { -R/2, -R/6 } }, // >>-d--->
- { { -R/2, -R/6 }, { -R/2+R/6, -R/6 } },
- { { -R/2+R/6, -R/6 }, { -R/2+R/6, R/4 } },
- { { -R/6, 0 }, { -R/6, -R/6 } }, // >>-dd-->
- { { -R/6, -R/6 }, { 0, -R/6 } },
- { { 0, -R/6 }, { 0, R/4 } },
- { { R/6, R/4 }, { R/6, -R/7 } }, // >>-ddt->
- { { R/6, -R/7 }, { R/6+R/32, -R/7-R/32 } },
- { { R/6+R/32, -R/7-R/32 }, { R/6+R/10, -R/7 } }
- };
- #undef R
- #define R (FRACUNIT)
- mline_t triangle_guy[] =
- {
- { { fixed_t(-.867*R), fixed_t(-.5*R) }, { fixed_t(.867*R), fixed_t(-.5*R) } },
- { { fixed_t(.867*R), fixed_t(-.5*R) } , { 0, R } },
- { { 0, R }, { fixed_t(-.867*R), fixed_t(-.5*R) } }
- };
- #undef R
- #define R (FRACUNIT)
- mline_t thintriangle_guy[] =
- {
- { { fixed_t(-.5*R), fixed_t(-.7*R) }, { R, 0 } },
- { { R, 0 }, { fixed_t(-.5*R), fixed_t(.7*R) } },
- { { fixed_t(-.5*R), fixed_t(.7*R) }, { fixed_t(-.5*R), fixed_t(-.7*R) } }
- };
- #undef R
- // location of window on screen
- // size of window on screen
- //
- // width/height of window on map (map coords)
- //
- // based on level size
- // based on player size
- // old stuff for recovery later
- // old location used by the Follower routine
- // used by MTOF to scale from map-to-frame-::g->buffer coords
- // used by FTOM to scale from frame-::g->buffer-to-map coords (=1/::g->scale_mtof)
- const unsigned char cheat_amap_seq[] =
- {
- 0xb2, 0x26, 0x26, 0x2e, 0xff
- };
- cheatseq_t cheat_amap = cheatseq_t( cheat_amap_seq, 0 );
- //extern byte ::g->screens[][SCREENWIDTH*SCREENHEIGHT];
- void
- V_MarkRect
- ( int x,
- int y,
- int width,
- int height );
- // Calculates the slope and slope according to the x-axis of a line
- // segment in map coordinates (with the upright y-axis n' all) so
- // that it can be used with the brain-dead drawing stuff.
- void
- AM_getIslope
- ( mline_t* ml,
- islope_t* is )
- {
- int dx, dy;
- dy = ml->a.y - ml->b.y;
- dx = ml->b.x - ml->a.x;
- if (!dy) is->islp = (dx<0?-MAXINT:MAXINT);
- else is->islp = FixedDiv(dx, dy);
- if (!dx) is->slp = (dy<0?-MAXINT:MAXINT);
- else is->slp = FixedDiv(dy, dx);
- }
- //
- //
- //
- void AM_activateNewScale(void)
- {
- ::g->m_x += ::g->m_w/2;
- ::g->m_y += ::g->m_h/2;
- ::g->m_w = FTOM(::g->f_w);
- ::g->m_h = FTOM(::g->f_h);
- ::g->m_x -= ::g->m_w/2;
- ::g->m_y -= ::g->m_h/2;
- ::g->m_x2 = ::g->m_x + ::g->m_w;
- ::g->m_y2 = ::g->m_y + ::g->m_h;
- }
- //
- //
- //
- void AM_saveScaleAndLoc(void)
- {
- ::g->old_m_x = ::g->m_x;
- ::g->old_m_y = ::g->m_y;
- ::g->old_m_w = ::g->m_w;
- ::g->old_m_h = ::g->m_h;
- }
- //
- //
- //
- void AM_restoreScaleAndLoc(void)
- {
- ::g->m_w = ::g->old_m_w;
- ::g->m_h = ::g->old_m_h;
- if (!::g->followplayer)
- {
- ::g->m_x = ::g->old_m_x;
- ::g->m_y = ::g->old_m_y;
- } else {
- ::g->m_x = ::g->amap_plr->mo->x - ::g->m_w/2;
- ::g->m_y = ::g->amap_plr->mo->y - ::g->m_h/2;
- }
- ::g->m_x2 = ::g->m_x + ::g->m_w;
- ::g->m_y2 = ::g->m_y + ::g->m_h;
- // Change the scaling multipliers
- ::g->scale_mtof = FixedDiv(::g->f_w<<FRACBITS, ::g->m_w);
- ::g->scale_ftom = FixedDiv(FRACUNIT, ::g->scale_mtof);
- }
- //
- // adds a marker at the current location
- //
- void AM_addMark(void)
- {
- ::g->markpoints[::g->markpointnum].x = ::g->m_x + ::g->m_w/2;
- ::g->markpoints[::g->markpointnum].y = ::g->m_y + ::g->m_h/2;
- ::g->markpointnum = (::g->markpointnum + 1) % AM_NUMMARKPOINTS;
- }
- //
- // Determines bounding box of all vertices,
- // sets global variables controlling zoom range.
- //
- void AM_findMinMaxBoundaries(void)
- {
- int i;
- fixed_t a;
- fixed_t b;
- ::g->min_x = ::g->min_y = MAXINT;
- ::g->max_x = ::g->max_y = -MAXINT;
- for (i=0; i < ::g->numvertexes; i++)
- {
- if (::g->vertexes[i].x < ::g->min_x)
- ::g->min_x = ::g->vertexes[i].x;
- else if (::g->vertexes[i].x > ::g->max_x)
- ::g->max_x = ::g->vertexes[i].x;
- if (::g->vertexes[i].y < ::g->min_y)
- ::g->min_y = ::g->vertexes[i].y;
- else if (::g->vertexes[i].y > ::g->max_y)
- ::g->max_y = ::g->vertexes[i].y;
- }
- ::g->max_w = ::g->max_x - ::g->min_x;
- ::g->max_h = ::g->max_y - ::g->min_y;
- ::g->min_w = 2*PLAYERRADIUS; // const? never changed?
- ::g->min_h = 2*PLAYERRADIUS;
- a = FixedDiv(::g->f_w<<FRACBITS, ::g->max_w);
- b = FixedDiv(::g->f_h<<FRACBITS, ::g->max_h);
- ::g->min_scale_mtof = a < b ? a : b;
- ::g->max_scale_mtof = FixedDiv(::g->f_h<<FRACBITS, 2*PLAYERRADIUS);
- }
- //
- //
- //
- void AM_changeWindowLoc(void)
- {
- if (::g->m_paninc.x || ::g->m_paninc.y)
- {
- ::g->followplayer = 0;
- ::g->f_oldloc.x = MAXINT;
- }
- ::g->m_x += ::g->m_paninc.x;
- ::g->m_y += ::g->m_paninc.y;
- if (::g->m_x + ::g->m_w/2 > ::g->max_x)
- ::g->m_x = ::g->max_x - ::g->m_w/2;
- else if (::g->m_x + ::g->m_w/2 < ::g->min_x)
- ::g->m_x = ::g->min_x - ::g->m_w/2;
- if (::g->m_y + ::g->m_h/2 > ::g->max_y)
- ::g->m_y = ::g->max_y - ::g->m_h/2;
- else if (::g->m_y + ::g->m_h/2 < ::g->min_y)
- ::g->m_y = ::g->min_y - ::g->m_h/2;
- ::g->m_x2 = ::g->m_x + ::g->m_w;
- ::g->m_y2 = ::g->m_y + ::g->m_h;
- }
- //
- //
- //
- void AM_initVariables(void)
- {
- static event_t st_notify = { ev_keyup, AM_MSGENTERED };
- int pnum;
- ::g->automapactive = true;
- ::g->fb = ::g->screens[0];
- ::g->f_oldloc.x = MAXINT;
- ::g->amclock = 0;
- ::g->lightlev = 0;
- ::g->m_paninc.x = ::g->m_paninc.y = 0;
- ::g->ftom_zoommul = FRACUNIT;
- ::g->mtof_zoommul = FRACUNIT;
- ::g->m_w = FTOM(::g->f_w);
- ::g->m_h = FTOM(::g->f_h);
- // find player to center on initially
- if (!::g->playeringame[pnum = ::g->consoleplayer])
- for (pnum=0;pnum<MAXPLAYERS;pnum++)
- if (::g->playeringame[pnum])
- break;
- ::g->amap_plr = &::g->players[pnum];
- ::g->m_x = ::g->amap_plr->mo->x - ::g->m_w/2;
- ::g->m_y = ::g->amap_plr->mo->y - ::g->m_h/2;
- AM_changeWindowLoc();
- // for saving & restoring
- ::g->old_m_x = ::g->m_x;
- ::g->old_m_y = ::g->m_y;
- ::g->old_m_w = ::g->m_w;
- ::g->old_m_h = ::g->m_h;
- // inform the status bar of the change
- ST_Responder(&st_notify);
- }
- //
- //
- //
- void AM_loadPics(void)
- {
- int i;
- char namebuf[9];
- for (i=0;i<10;i++)
- {
- sprintf(namebuf, "AMMNUM%d", i);
- ::g->marknums[i] = (patch_t*)W_CacheLumpName(namebuf, PU_STATIC_SHARED);
- }
- }
- void AM_unloadPics(void)
- {
- // int i;
- }
- void AM_clearMarks(void)
- {
- int i;
- for (i=0;i<AM_NUMMARKPOINTS;i++)
- ::g->markpoints[i].x = -1; // means empty
- ::g->markpointnum = 0;
- }
- //
- // should be called at the start of every level
- // right now, i figure it out myself
- //
- void AM_LevelInit(void)
- {
- ::g->leveljuststarted = 0;
- ::g->f_x = ::g->f_y = 0;
- ::g->f_w = ::g->finit_width;
- ::g->f_h = ::g->finit_height;
- AM_clearMarks();
- AM_findMinMaxBoundaries();
- ::g->scale_mtof = FixedDiv(::g->min_scale_mtof, (int) (0.7*FRACUNIT));
- if (::g->scale_mtof > ::g->max_scale_mtof)
- ::g->scale_mtof = ::g->min_scale_mtof;
- ::g->scale_ftom = FixedDiv(FRACUNIT, ::g->scale_mtof);
- }
- //
- //
- //
- void AM_Stop (void)
- {
- static event_t st_notify = { (evtype_t)0, ev_keyup, AM_MSGEXITED };
- AM_unloadPics();
- ::g->automapactive = false;
- ST_Responder(&st_notify);
- ::g->stopped = true;
- }
- //
- //
- //
- void AM_Start (void)
- {
- if (!::g->stopped) AM_Stop();
- ::g->stopped = false;
- if (::g->lastlevel != ::g->gamemap || ::g->lastepisode != ::g->gameepisode)
- {
- AM_LevelInit();
- ::g->lastlevel = ::g->gamemap;
- ::g->lastepisode = ::g->gameepisode;
- }
- AM_initVariables();
- AM_loadPics();
- }
- //
- // set the window scale to the maximum size
- //
- void AM_minOutWindowScale(void)
- {
- ::g->scale_mtof = ::g->min_scale_mtof;
- ::g->scale_ftom = FixedDiv(FRACUNIT, ::g->scale_mtof);
- AM_activateNewScale();
- }
- //
- // set the window scale to the minimum size
- //
- void AM_maxOutWindowScale(void)
- {
- ::g->scale_mtof = ::g->max_scale_mtof;
- ::g->scale_ftom = FixedDiv(FRACUNIT, ::g->scale_mtof);
- AM_activateNewScale();
- }
- //
- // Handle ::g->events (user inputs) in automap mode
- //
- qboolean
- AM_Responder
- ( event_t* ev )
- {
- int rc;
- rc = false;
- if (!::g->automapactive)
- {
- if (ev->type == ev_keydown && ev->data1 == AM_STARTKEY)
- {
- AM_Start ();
- ::g->viewactive = false;
- rc = true;
- }
- }
- else if (ev->type == ev_keydown)
- {
- rc = true;
- switch(ev->data1)
- {
- case AM_PANRIGHTKEY: // pan right
- if (!::g->followplayer) ::g->m_paninc.x = FTOM(F_PANINC);
- else rc = false;
- break;
- case AM_PANLEFTKEY: // pan left
- if (!::g->followplayer) ::g->m_paninc.x = -FTOM(F_PANINC);
- else rc = false;
- break;
- case AM_PANUPKEY: // pan up
- if (!::g->followplayer) ::g->m_paninc.y = FTOM(F_PANINC);
- else rc = false;
- break;
- case AM_PANDOWNKEY: // pan down
- if (!::g->followplayer) ::g->m_paninc.y = -FTOM(F_PANINC);
- else rc = false;
- break;
- case AM_ZOOMOUTKEY: // zoom out
- ::g->mtof_zoommul = M_ZOOMOUT;
- ::g->ftom_zoommul = M_ZOOMIN;
- break;
- case AM_ZOOMINKEY: // zoom in
- ::g->mtof_zoommul = M_ZOOMIN;
- ::g->ftom_zoommul = M_ZOOMOUT;
- break;
- case AM_ENDKEY:
- ::g->bigstate = 0;
- ::g->viewactive = true;
- AM_Stop ();
- break;
- case AM_GOBIGKEY:
- ::g->bigstate = !::g->bigstate;
- if (::g->bigstate)
- {
- AM_saveScaleAndLoc();
- AM_minOutWindowScale();
- }
- else AM_restoreScaleAndLoc();
- break;
- case AM_FOLLOWKEY:
- ::g->followplayer = !::g->followplayer;
- ::g->f_oldloc.x = MAXINT;
- ::g->amap_plr->message = ::g->followplayer ? AMSTR_FOLLOWON : AMSTR_FOLLOWOFF;
- break;
- case AM_GRIDKEY:
- ::g->grid = !::g->grid;
- ::g->amap_plr->message = ::g->grid ? AMSTR_GRIDON : AMSTR_GRIDOFF;
- break;
- case AM_MARKKEY:
- sprintf(::g->buffer, "%s %d", AMSTR_MARKEDSPOT, ::g->markpointnum);
- ::g->amap_plr->message = ::g->buffer;
- AM_addMark();
- break;
- case AM_CLEARMARKKEY:
- AM_clearMarks();
- ::g->amap_plr->message = AMSTR_MARKSCLEARED;
- break;
- default:
- ::g->cheatstate=0;
- rc = false;
- }
- if (!::g->deathmatch && cht_CheckCheat(&cheat_amap, ev->data1))
- {
- rc = false;
- ::g->cheating = (::g->cheating+1) % 3;
- }
- }
- else if (ev->type == ev_keyup)
- {
- rc = false;
- switch (ev->data1)
- {
- case AM_PANRIGHTKEY:
- if (!::g->followplayer) ::g->m_paninc.x = 0;
- break;
- case AM_PANLEFTKEY:
- if (!::g->followplayer) ::g->m_paninc.x = 0;
- break;
- case AM_PANUPKEY:
- if (!::g->followplayer) ::g->m_paninc.y = 0;
- break;
- case AM_PANDOWNKEY:
- if (!::g->followplayer) ::g->m_paninc.y = 0;
- break;
- case AM_ZOOMOUTKEY:
- case AM_ZOOMINKEY:
- ::g->mtof_zoommul = FRACUNIT;
- ::g->ftom_zoommul = FRACUNIT;
- break;
- }
- }
- return rc;
- }
- //
- // Zooming
- //
- void AM_changeWindowScale(void)
- {
- // Change the scaling multipliers
- ::g->scale_mtof = FixedMul(::g->scale_mtof, ::g->mtof_zoommul);
- ::g->scale_ftom = FixedDiv(FRACUNIT, ::g->scale_mtof);
- if (::g->scale_mtof < ::g->min_scale_mtof)
- AM_minOutWindowScale();
- else if (::g->scale_mtof > ::g->max_scale_mtof)
- AM_maxOutWindowScale();
- else
- AM_activateNewScale();
- }
- //
- //
- //
- void AM_doFollowPlayer(void)
- {
- if (::g->f_oldloc.x != ::g->amap_plr->mo->x || ::g->f_oldloc.y != ::g->amap_plr->mo->y)
- {
- ::g->m_x = FTOM(MTOF(::g->amap_plr->mo->x)) - ::g->m_w/2;
- ::g->m_y = FTOM(MTOF(::g->amap_plr->mo->y)) - ::g->m_h/2;
- ::g->m_x2 = ::g->m_x + ::g->m_w;
- ::g->m_y2 = ::g->m_y + ::g->m_h;
- ::g->f_oldloc.x = ::g->amap_plr->mo->x;
- ::g->f_oldloc.y = ::g->amap_plr->mo->y;
- // ::g->m_x = FTOM(MTOF(::g->amap_plr->mo->x - ::g->m_w/2));
- // ::g->m_y = FTOM(MTOF(::g->amap_plr->mo->y - ::g->m_h/2));
- // ::g->m_x = ::g->amap_plr->mo->x - ::g->m_w/2;
- // ::g->m_y = ::g->amap_plr->mo->y - ::g->m_h/2;
- }
- }
- //
- //
- //
- void AM_updateLightLev(void)
- {
- //static int litelevels[] = { 0, 3, 5, 6, 6, 7, 7, 7 };
- const static int litelevels[] = { 0, 4, 7, 10, 12, 14, 15, 15 };
- // Change light level
- if (::g->amclock>::g->nexttic)
- {
- ::g->lightlev = litelevels[::g->litelevelscnt++];
- if (::g->litelevelscnt == sizeof(litelevels)/sizeof(int)) ::g->litelevelscnt = 0;
- ::g->nexttic = ::g->amclock + 6 - (::g->amclock % 6);
- }
- }
- //
- // Updates on Game Tick
- //
- void AM_Ticker (void)
- {
- if (!::g->automapactive)
- return;
- ::g->amclock++;
- if (::g->followplayer)
- AM_doFollowPlayer();
- // Change the zoom if necessary
- if (::g->ftom_zoommul != FRACUNIT)
- AM_changeWindowScale();
- // Change x,y location
- if (::g->m_paninc.x || ::g->m_paninc.y)
- AM_changeWindowLoc();
- // Update light level
- // AM_updateLightLev();
- }
- //
- // Clear automap frame ::g->buffer.
- //
- void AM_clearFB(int color)
- {
- memset(::g->fb, color, ::g->f_w*::g->f_h);
- }
- //
- // Automap clipping of ::g->lines.
- //
- // Based on Cohen-Sutherland clipping algorithm but with a slightly
- // faster reject and precalculated slopes. If the speed is needed,
- // use a hash algorithm to handle the common cases.
- //
- qboolean
- AM_clipMline
- ( mline_t* ml,
- fline_t* fl )
- {
- enum
- {
- LEFT =1,
- RIGHT =2,
- BOTTOM =4,
- TOP =8
- };
- register int outcode1 = 0;
- register int outcode2 = 0;
- register int outside;
- fpoint_t tmp = { 0, 0 };
- int dx;
- int dy;
- // do trivial rejects and outcodes
- if (ml->a.y > ::g->m_y2)
- outcode1 = TOP;
- else if (ml->a.y < ::g->m_y)
- outcode1 = BOTTOM;
- if (ml->b.y > ::g->m_y2)
- outcode2 = TOP;
- else if (ml->b.y < ::g->m_y)
- outcode2 = BOTTOM;
- if (outcode1 & outcode2)
- return false; // trivially outside
- if (ml->a.x < ::g->m_x)
- outcode1 |= LEFT;
- else if (ml->a.x > ::g->m_x2)
- outcode1 |= RIGHT;
- if (ml->b.x < ::g->m_x)
- outcode2 |= LEFT;
- else if (ml->b.x > ::g->m_x2)
- outcode2 |= RIGHT;
- if (outcode1 & outcode2)
- return false; // trivially outside
- // transform to frame-::g->buffer coordinates.
- fl->a.x = CXMTOF(ml->a.x);
- fl->a.y = CYMTOF(ml->a.y);
- fl->b.x = CXMTOF(ml->b.x);
- fl->b.y = CYMTOF(ml->b.y);
- DOOUTCODE(outcode1, fl->a.x, fl->a.y);
- DOOUTCODE(outcode2, fl->b.x, fl->b.y);
- if (outcode1 & outcode2)
- return false;
- while (outcode1 | outcode2)
- {
- // may be partially inside box
- // find an outside point
- if (outcode1)
- outside = outcode1;
- else
- outside = outcode2;
- // clip to each side
- if (outside & TOP)
- {
- dy = fl->a.y - fl->b.y;
- dx = fl->b.x - fl->a.x;
- tmp.x = fl->a.x + (dx*(fl->a.y))/dy;
- tmp.y = 0;
- }
- else if (outside & BOTTOM)
- {
- dy = fl->a.y - fl->b.y;
- dx = fl->b.x - fl->a.x;
- tmp.x = fl->a.x + (dx*(fl->a.y-::g->f_h))/dy;
- tmp.y = ::g->f_h-1;
- }
- else if (outside & RIGHT)
- {
- dy = fl->b.y - fl->a.y;
- dx = fl->b.x - fl->a.x;
- tmp.y = fl->a.y + (dy*(::g->f_w-1 - fl->a.x))/dx;
- tmp.x = ::g->f_w-1;
- }
- else if (outside & LEFT)
- {
- dy = fl->b.y - fl->a.y;
- dx = fl->b.x - fl->a.x;
- tmp.y = fl->a.y + (dy*(-fl->a.x))/dx;
- tmp.x = 0;
- }
- if (outside == outcode1)
- {
- fl->a = tmp;
- DOOUTCODE(outcode1, fl->a.x, fl->a.y);
- }
- else
- {
- fl->b = tmp;
- DOOUTCODE(outcode2, fl->b.x, fl->b.y);
- }
- if (outcode1 & outcode2)
- return false; // trivially outside
- }
- return true;
- }
- #undef DOOUTCODE
- //
- // Classic Bresenham w/ whatever optimizations needed for speed
- //
- void
- AM_drawFline
- ( fline_t* fl,
- int color )
- {
- register int x;
- register int y;
- register int dx;
- register int dy;
- register int sx;
- register int sy;
- register int ax;
- register int ay;
- register int d;
- static int fuck = 0;
- // For debugging only
- if ( fl->a.x < 0 || fl->a.x >= ::g->f_w
- || fl->a.y < 0 || fl->a.y >= ::g->f_h
- || fl->b.x < 0 || fl->b.x >= ::g->f_w
- || fl->b.y < 0 || fl->b.y >= ::g->f_h)
- {
- I_PrintfE("fuck %d \r", fuck++);
- return;
- }
- dx = fl->b.x - fl->a.x;
- ax = 2 * (dx<0 ? -dx : dx);
- sx = dx<0 ? -1 : 1;
- dy = fl->b.y - fl->a.y;
- ay = 2 * (dy<0 ? -dy : dy);
- sy = dy<0 ? -1 : 1;
- x = fl->a.x;
- y = fl->a.y;
- if (ax > ay)
- {
- d = ay - ax/2;
- while (1)
- {
- PUTDOT(x,y,color);
- if (x == fl->b.x) return;
- if (d>=0)
- {
- y += sy;
- d -= ax;
- }
- x += sx;
- d += ay;
- }
- }
- else
- {
- d = ax - ay/2;
- while (1)
- {
- PUTDOT(x, y, color);
- if (y == fl->b.y) return;
- if (d >= 0)
- {
- x += sx;
- d -= ay;
- }
- y += sy;
- d += ax;
- }
- }
- }
- //
- // Clip ::g->lines, draw visible part sof ::g->lines.
- //
- void
- AM_drawMline
- ( mline_t* ml,
- int color )
- {
- static fline_t fl;
- if (AM_clipMline(ml, &fl))
- AM_drawFline(&fl, color); // draws it on frame ::g->buffer using ::g->fb coords
- }
- //
- // Draws flat (floor/ceiling tile) aligned ::g->grid ::g->lines.
- //
- void AM_drawGrid(int color)
- {
- fixed_t x, y;
- fixed_t start, end;
- mline_t ml;
- // Figure out start of vertical gridlines
- start = ::g->m_x;
- if ((start-::g->bmaporgx)%(MAPBLOCKUNITS<<FRACBITS))
- start += (MAPBLOCKUNITS<<FRACBITS)
- - ((start-::g->bmaporgx)%(MAPBLOCKUNITS<<FRACBITS));
- end = ::g->m_x + ::g->m_w;
- // draw vertical gridlines
- ml.a.y = ::g->m_y;
- ml.b.y = ::g->m_y+::g->m_h;
- for (x=start; x<end; x+=(MAPBLOCKUNITS<<FRACBITS))
- {
- ml.a.x = x;
- ml.b.x = x;
- AM_drawMline(&ml, color);
- }
- // Figure out start of horizontal gridlines
- start = ::g->m_y;
- if ((start-::g->bmaporgy)%(MAPBLOCKUNITS<<FRACBITS))
- start += (MAPBLOCKUNITS<<FRACBITS)
- - ((start-::g->bmaporgy)%(MAPBLOCKUNITS<<FRACBITS));
- end = ::g->m_y + ::g->m_h;
- // draw horizontal gridlines
- ml.a.x = ::g->m_x;
- ml.b.x = ::g->m_x + ::g->m_w;
- for (y=start; y<end; y+=(MAPBLOCKUNITS<<FRACBITS))
- {
- ml.a.y = y;
- ml.b.y = y;
- AM_drawMline(&ml, color);
- }
- }
- //
- // Determines visible ::g->lines, draws them.
- // This is LineDef based, not LineSeg based.
- //
- void AM_drawWalls(void)
- {
- int i;
- static mline_t l;
- for (i = 0; i < ::g->numlines; i++)
- {
- l.a.x = ::g->lines[i].v1->x;
- l.a.y = ::g->lines[i].v1->y;
- l.b.x = ::g->lines[i].v2->x;
- l.b.y = ::g->lines[i].v2->y;
- if (::g->cheating || (::g->lines[i].flags & ML_MAPPED))
- {
- if ((::g->lines[i].flags & LINE_NEVERSEE) && !::g->cheating)
- continue;
- if (!::g->lines[i].backsector)
- {
- AM_drawMline(&l, WALLCOLORS+::g->lightlev);
- }
- else
- {
- if (::g->lines[i].special == 39)
- { // teleporters
- AM_drawMline(&l, WALLCOLORS+WALLRANGE/2);
- }
- else if (::g->lines[i].flags & ML_SECRET) // secret door
- {
- if (::g->cheating) AM_drawMline(&l, SECRETWALLCOLORS + ::g->lightlev);
- else AM_drawMline(&l, WALLCOLORS+::g->lightlev);
- }
- else if (::g->lines[i].backsector->floorheight
- != ::g->lines[i].frontsector->floorheight) {
- AM_drawMline(&l, FDWALLCOLORS + ::g->lightlev); // floor level change
- }
- else if (::g->lines[i].backsector->ceilingheight
- != ::g->lines[i].frontsector->ceilingheight) {
- AM_drawMline(&l, CDWALLCOLORS+::g->lightlev); // ceiling level change
- }
- else if (::g->cheating) {
- AM_drawMline(&l, TSWALLCOLORS+::g->lightlev);
- }
- }
- }
- else if (::g->amap_plr->powers[pw_allmap])
- {
- if (!(::g->lines[i].flags & LINE_NEVERSEE)) AM_drawMline(&l, GRAYS+3);
- }
- }
- }
- //
- // Rotation in 2D.
- // Used to rotate player arrow line character.
- //
- void
- AM_rotate
- ( fixed_t* x,
- fixed_t* y,
- angle_t a )
- {
- fixed_t tmpx;
- tmpx =
- FixedMul(*x,finecosine[a>>ANGLETOFINESHIFT])
- - FixedMul(*y,finesine[a>>ANGLETOFINESHIFT]);
- *y =
- FixedMul(*x,finesine[a>>ANGLETOFINESHIFT])
- + FixedMul(*y,finecosine[a>>ANGLETOFINESHIFT]);
- *x = tmpx;
- }
- void
- AM_drawLineCharacter
- ( mline_t* lineguy,
- int lineguylines,
- fixed_t scale,
- angle_t angle,
- int color,
- fixed_t x,
- fixed_t y )
- {
- int i;
- mline_t l;
- for (i=0;i<lineguylines;i++)
- {
- l.a.x = lineguy[i].a.x;
- l.a.y = lineguy[i].a.y;
- if (scale)
- {
- l.a.x = FixedMul(scale, l.a.x);
- l.a.y = FixedMul(scale, l.a.y);
- }
- if (angle)
- AM_rotate(&l.a.x, &l.a.y, angle);
- l.a.x += x;
- l.a.y += y;
- l.b.x = lineguy[i].b.x;
- l.b.y = lineguy[i].b.y;
- if (scale)
- {
- l.b.x = FixedMul(scale, l.b.x);
- l.b.y = FixedMul(scale, l.b.y);
- }
- if (angle)
- AM_rotate(&l.b.x, &l.b.y, angle);
- l.b.x += x;
- l.b.y += y;
- AM_drawMline(&l, color);
- }
- }
- void AM_drawPlayers(void)
- {
- int i;
- player_t* p;
- static int their_colors[] = { GREENS, GRAYS, BROWNS, REDS };
- int their_color = -1;
- int color;
- if (!::g->netgame)
- {
- if (::g->cheating)
- AM_drawLineCharacter
- (cheat_player_arrow, NUMCHEATPLYRLINES, 0,
- ::g->amap_plr->mo->angle, WHITE, ::g->amap_plr->mo->x, ::g->amap_plr->mo->y);
- else
- AM_drawLineCharacter
- (player_arrow, NUMPLYRLINES, 0, ::g->amap_plr->mo->angle,
- WHITE, ::g->amap_plr->mo->x, ::g->amap_plr->mo->y);
- return;
- }
- for (i=0;i<MAXPLAYERS;i++)
- {
- their_color++;
- p = &::g->players[i];
- if ( (::g->deathmatch && !::g->singledemo) && p != ::g->amap_plr)
- continue;
- if (!::g->playeringame[i])
- continue;
- if (p->powers[pw_invisibility])
- color = 246; // *close* to black
- else
- color = their_colors[their_color];
- AM_drawLineCharacter
- (player_arrow, NUMPLYRLINES, 0, p->mo->angle,
- color, p->mo->x, p->mo->y);
- }
- }
- void
- AM_drawThings
- ( int colors,
- int colorrange)
- {
- int i;
- mobj_t* t;
- for (i = 0; i < ::g->numsectors; i++)
- {
- t = ::g->sectors[i].thinglist;
- while (t)
- {
- AM_drawLineCharacter
- (thintriangle_guy, NUMTHINTRIANGLEGUYLINES,
- 16<<FRACBITS, t->angle, colors+::g->lightlev, t->x, t->y);
- t = t->snext;
- }
- }
- }
- void AM_drawMarks(void)
- {
- int i, fx, fy, w, h;
- for (i=0;i<AM_NUMMARKPOINTS;i++)
- {
- if (::g->markpoints[i].x != -1)
- {
- // w = SHORT(::g->marknums[i]->width);
- // h = SHORT(::g->marknums[i]->height);
- w = 5; // because something's wrong with the wad, i guess
- h = 6; // because something's wrong with the wad, i guess
- fx = CXMTOF(::g->markpoints[i].x);
- fy = CYMTOF(::g->markpoints[i].y);
- if (fx >= ::g->f_x && fx <= ::g->f_w - w && fy >= ::g->f_y && fy <= ::g->f_h - h)
- V_DrawPatch(fx/GLOBAL_IMAGE_SCALER, fy/GLOBAL_IMAGE_SCALER, FB, ::g->marknums[i]);
- }
- }
- }
- void AM_drawCrosshair(int color)
- {
- ::g->fb[(::g->f_w*(::g->f_h+1))/2] = color; // single point for now
- }
- void AM_Drawer (void)
- {
- if (!::g->automapactive) return;
- AM_clearFB(BACKGROUND);
- if (::g->grid)
- AM_drawGrid(GRIDCOLORS);
- AM_drawWalls();
- AM_drawPlayers();
- if (::g->cheating==2)
- AM_drawThings(THINGCOLORS, THINGRANGE);
- AM_drawCrosshair(XHAIRCOLORS);
- AM_drawMarks();
- V_MarkRect(::g->f_x, ::g->f_y, ::g->f_w, ::g->f_h);
- }
|