From 9f642ee002093704102ec73e9f96b4d5a1e76461 Mon Sep 17 00:00:00 2001 From: justin Date: Tue, 9 Apr 2024 19:46:44 -0700 Subject: [PATCH] Original Doom 2 Dos Source code as found on Mac/Dos archive.org leak. --- AM_DATA.H | 1 + AM_MAP.C | 1 + AM_MAP.H | 1 + AM_OIDS.C | 1 + AM_OIDS.H | 1 + DITHER.C | 1 + DITHER.H | 1 + DOOMDATA.H | 1 + DOOMDEF.H | 1 + DSTRINGS.H | 1 + DUTILS.C | 1 + DUTILS.H | 1 + D_FRENCH.H | 1 + D_MAIN.C | 1 + D_NET.C | 1 + F_FINALE.C | 1 + G_GAME.C | 1 + HU_LIB.C | 1 + HU_LIB.H | 1 + HU_STUFF.C | 1 + HU_STUFF.H | 1 + INFO.C | 1 + INFO.H | 1 + IRIX.C | 1 + IRIX.H | 1 + I_CYBER.C | 1 + I_DGA.C | 1 + I_HEADER.H | 1 + I_IBM.C | 1 + I_IBM_A.ASM | 1 + I_MAIN.C | 1 + I_PCNET.C | 1 + I_SOUND.C | 1 + I_SOUND.H | 1 + I_UNIX.C | 1 + I_X.C | 1 + M_MENU.C | 1 + M_MISC.C | 1 + PLANAR.ASM | 1 + P_CEILNG.C | 1 + P_DOORS.C | 1 + P_ENEMY.C | 1 + P_FLOOR.C | 1 + P_INTER.C | 1 + P_LIGHTS.C | 1 + P_LOCAL.H | 1 + P_MAP.C | 1 + P_MAPUTL.C | 1 + P_MOBJ.C | 1 + P_PLATS.C | 1 + P_PSPR.C | 1 + P_SETUP.C | 1 + P_SIGHT.C | 1 + P_SPEC.C | 1 + P_SPEC.H | 1 + P_SWITCH.C | 1 + P_TELEPT.C | 1 + P_TICK.C | 1 + P_USER.C | 1 + R_BSP.C | 1 + R_DATA.C | 1 + R_DRAW.C | 1 + R_LOCAL.H | 1 + R_MAIN.C | 1 + R_PLANE.C | 1 + R_SEGS.C | 1 + R_THINGS.C | 1 + SOUNDS.C | 1 + SOUNDS.H | 1 + SOUNDST.H | 1 + ST_LIB.C | 1 + ST_LIB.H | 1 + ST_STUFF.C | 1 + ST_STUFF.H | 1 + SUN.C | 1 + S_SOUND.C | 1 + T.C | 1 + TABLES.C | 1 + V_VIDEO.C | 1 + WADREAD.C | 1 + WADREAD.H | 1 + WI_DATA.H | 1 + WI_STUFF.C | 1 + WI_STUFF.H | 1 + W_WAD.C | 1 + Z_ZONE.C | 1 + 86 files changed, 86 insertions(+) create mode 100644 AM_DATA.H create mode 100644 AM_MAP.C create mode 100644 AM_MAP.H create mode 100644 AM_OIDS.C create mode 100644 AM_OIDS.H create mode 100644 DITHER.C create mode 100644 DITHER.H create mode 100644 DOOMDATA.H create mode 100644 DOOMDEF.H create mode 100644 DSTRINGS.H create mode 100644 DUTILS.C create mode 100644 DUTILS.H create mode 100644 D_FRENCH.H create mode 100644 D_MAIN.C create mode 100644 D_NET.C create mode 100644 F_FINALE.C create mode 100644 G_GAME.C create mode 100644 HU_LIB.C create mode 100644 HU_LIB.H create mode 100644 HU_STUFF.C create mode 100644 HU_STUFF.H create mode 100644 INFO.C create mode 100644 INFO.H create mode 100644 IRIX.C create mode 100644 IRIX.H create mode 100644 I_CYBER.C create mode 100644 I_DGA.C create mode 100644 I_HEADER.H create mode 100644 I_IBM.C create mode 100644 I_IBM_A.ASM create mode 100644 I_MAIN.C create mode 100644 I_PCNET.C create mode 100644 I_SOUND.C create mode 100644 I_SOUND.H create mode 100644 I_UNIX.C create mode 100644 I_X.C create mode 100644 M_MENU.C create mode 100644 M_MISC.C create mode 100644 PLANAR.ASM create mode 100644 P_CEILNG.C create mode 100644 P_DOORS.C create mode 100644 P_ENEMY.C create mode 100644 P_FLOOR.C create mode 100644 P_INTER.C create mode 100644 P_LIGHTS.C create mode 100644 P_LOCAL.H create mode 100644 P_MAP.C create mode 100644 P_MAPUTL.C create mode 100644 P_MOBJ.C create mode 100644 P_PLATS.C create mode 100644 P_PSPR.C create mode 100644 P_SETUP.C create mode 100644 P_SIGHT.C create mode 100644 P_SPEC.C create mode 100644 P_SPEC.H create mode 100644 P_SWITCH.C create mode 100644 P_TELEPT.C create mode 100644 P_TICK.C create mode 100644 P_USER.C create mode 100644 R_BSP.C create mode 100644 R_DATA.C create mode 100644 R_DRAW.C create mode 100644 R_LOCAL.H create mode 100644 R_MAIN.C create mode 100644 R_PLANE.C create mode 100644 R_SEGS.C create mode 100644 R_THINGS.C create mode 100644 SOUNDS.C create mode 100644 SOUNDS.H create mode 100644 SOUNDST.H create mode 100644 ST_LIB.C create mode 100644 ST_LIB.H create mode 100644 ST_STUFF.C create mode 100644 ST_STUFF.H create mode 100644 SUN.C create mode 100644 S_SOUND.C create mode 100644 T.C create mode 100644 TABLES.C create mode 100644 V_VIDEO.C create mode 100644 WADREAD.C create mode 100644 WADREAD.H create mode 100644 WI_DATA.H create mode 100644 WI_STUFF.C create mode 100644 WI_STUFF.H create mode 100644 W_WAD.C create mode 100644 Z_ZONE.C diff --git a/AM_DATA.H b/AM_DATA.H new file mode 100644 index 0000000..ad2d643 --- /dev/null +++ b/AM_DATA.H @@ -0,0 +1 @@ +// AM_data.h : The vector graphics for the automap #ifndef __AMDATA_H__ #define __AMDATA_H__ // 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 NUMPLYRLINES (sizeof(player_arrow)/sizeof(mline_t)) #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 NUMCHEATPLYRLINES (sizeof(cheat_player_arrow)/sizeof(mline_t)) #define R (FRACUNIT) mline_t triangle_guy[] = { { { -.867*R, -.5*R }, { .867*R, -.5*R } }, { { .867*R, -.5*R } , { 0, R } }, { { 0, R }, { -.867*R, -.5*R } } }; #undef R #define NUMTRIANGLEGUYLINES (sizeof(triangle_guy)/sizeof(mline_t)) #define R (FRACUNIT) mline_t thintriangle_guy[] = { { { -.5*R, -.7*R }, { R, 0 } }, { { R, 0 }, { -.5*R, .7*R } }, { { -.5*R, .7*R }, { -.5*R, -.7*R } } }; #undef R #define NUMTHINTRIANGLEGUYLINES (sizeof(thintriangle_guy)/sizeof(mline_t)) /* */ #endif \ No newline at end of file diff --git a/AM_MAP.C b/AM_MAP.C new file mode 100644 index 0000000..9191fa5 --- /dev/null +++ b/AM_MAP.C @@ -0,0 +1 @@ +// AM_map.c : the automap code #include "doomdef.h" #include "st_stuff.h" #include "p_local.h" #include "am_map.h" #include "dutils.h" #include #include "am_data.h" static int cheating = 0; static int grid = 0; static int leveljuststarted = 1; // kluge until AM_LevelInit() is called boolean automapactive = false; static int finit_width = SCREENWIDTH; static int finit_height = SCREENHEIGHT - 32; static int f_x, f_y; // location of window on screen static int f_w, f_h; // size of window on screen static int lightlev; // used for funky strobing effect static byte *fb; // pseudo-frame buffer static int amclock; static mpoint_t m_paninc; // how far the window pans each tic (map coords) static fixed_t mtof_zoommul; // how far the window zooms in each tic (map coords) static fixed_t ftom_zoommul; // how far the window zooms in each tic (fb coords) static fixed_t m_x, m_y; // LL x,y where the window is on the map (map coords) static fixed_t m_x2, m_y2; // UR x,y where the window is on the map (map coords) // width/height of window on map (map coords) static fixed_t m_w, m_h; static fixed_t min_x, min_y; // based on level size static fixed_t max_x, max_y; // based on level size static fixed_t max_w, max_h; // max_x-min_x, max_y-min_y static fixed_t min_w, min_h; // based on player size static fixed_t min_scale_mtof; // used to tell when to stop zooming out static fixed_t max_scale_mtof; // used to tell when to stop zooming in // old stuff for recovery later static fixed_t old_m_w, old_m_h; static fixed_t old_m_x, old_m_y; // old location used by the Follower routine static mpoint_t f_oldloc; // used by MTOF to scale from map-to-frame-buffer coords static fixed_t scale_mtof = INITSCALEMTOF; // used by FTOM to scale from frame-buffer-to-map coords (=1/scale_mtof) static fixed_t scale_ftom; static player_t *plr; // the player represented by an arrow static patch_t *marknums[10]; // numbers used for marking by the automap static mpoint_t markpoints[AM_NUMMARKPOINTS]; // where the points are static int markpointnum = 0; // next point to be assigned static int followplayer = 1; // specifies whether to follow the player around static unsigned char cheat_amap_seq[] = { 0xb2, 0x26, 0x26, 0x2e, 0xff }; static cheatseq_t cheat_amap = { cheat_amap_seq, 0 }; extern boolean viewactive; //extern byte 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) { m_x += m_w/2; m_y += m_h/2; m_w = FTOM(f_w); m_h = FTOM(f_h); m_x -= m_w/2; m_y -= m_h/2; m_x2 = m_x + m_w; m_y2 = m_y + m_h; } void AM_saveScaleAndLoc(void) { old_m_x = m_x; old_m_y = m_y; old_m_w = m_w; old_m_h = m_h; } void AM_restoreScaleAndLoc(void) { m_w = old_m_w; m_h = old_m_h; if (!followplayer) { m_x = old_m_x; m_y = old_m_y; } else { m_x = plr->mo->x - m_w/2; m_y = plr->mo->y - m_h/2; } m_x2 = m_x + m_w; m_y2 = m_y + m_h; // Change the scaling multipliers scale_mtof = FixedDiv(f_w< max_x) max_x = vertexes[i].x; if (vertexes[i].y < min_y) min_y = vertexes[i].y; else if (vertexes[i].y > max_y) max_y = vertexes[i].y; } max_w = max_x - min_x; max_h = max_y - min_y; min_w = 2*PLAYERRADIUS; min_h = 2*PLAYERRADIUS; a = FixedDiv(f_w< max_x) m_x = max_x - m_w/2; else if (m_x + m_w/2 < min_x) m_x = min_x - m_w/2; if (m_y + m_h/2 > max_y) m_y = max_y - m_h/2; else if (m_y + m_h/2 < min_y) m_y = min_y - m_h/2; m_x2 = m_x + m_w; m_y2 = m_y + m_h; } void AM_initVariables(void) { int pnum; static event_t st_notify = { ev_keyup, AM_MSGENTERED }; automapactive = true; fb = screens[0]; f_oldloc.x = MAXINT; amclock = 0; lightlev = 0; m_paninc.x = m_paninc.y = 0; ftom_zoommul = FRACUNIT; mtof_zoommul = FRACUNIT; m_w = FTOM(f_w); m_h = FTOM(f_h); // find player to center on initially if (!playeringame[pnum = consoleplayer]) for (pnum=0;pnummo->x - m_w/2; m_y = plr->mo->y - m_h/2; AM_changeWindowLoc(); // for saving & restoring old_m_x = m_x; old_m_y = m_y; old_m_w = m_w; old_m_h = 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); marknums[i] = W_CacheLumpName(namebuf, PU_STATIC); } } void AM_unloadPics(void) { int i; for (i=0;i<10;i++) Z_ChangeTag(marknums[i], PU_CACHE); } void AM_clearMarks(void) { int i; for (i=0;i max_scale_mtof) scale_mtof = min_scale_mtof; scale_ftom = FixedDiv(FRACUNIT, scale_mtof); } static boolean stopped = true; void AM_Stop (void) { static event_t st_notify = { 0, ev_keyup, AM_MSGEXITED }; AM_unloadPics(); automapactive = false; ST_Responder(&st_notify); stopped = true; } void AM_Start (void) { static int lastlevel = -1, lastepisode = -1; if (!stopped) AM_Stop(); stopped = false; if (lastlevel != gamemap || lastepisode != gameepisode) { AM_LevelInit(); lastlevel = gamemap; lastepisode = gameepisode; } AM_initVariables(); AM_loadPics(); } // set the window scale to the maximum size void AM_minOutWindowScale(void) { scale_mtof = min_scale_mtof; scale_ftom = FixedDiv(FRACUNIT, scale_mtof); AM_activateNewScale(); } // set the window scale to the minimum size void AM_maxOutWindowScale(void) { scale_mtof = max_scale_mtof; scale_ftom = FixedDiv(FRACUNIT, scale_mtof); AM_activateNewScale(); } boolean AM_Responder (event_t *ev) { int rc; static int cheatstate=0; static int bigstate=0; static char buffer[20]; rc = false; if (!automapactive) { if (ev->type == ev_keydown && ev->data1 == AM_STARTKEY) { AM_Start (); viewactive = false; rc = true; } } else if (ev->type == ev_keydown) { rc = true; switch(ev->data1) { case AM_PANRIGHTKEY: // pan right if (!followplayer) m_paninc.x = FTOM(F_PANINC); else rc = false; break; case AM_PANLEFTKEY: // pan left if (!followplayer) m_paninc.x = -FTOM(F_PANINC); else rc = false; break; case AM_PANUPKEY: // pan up if (!followplayer) m_paninc.y = FTOM(F_PANINC); else rc = false; break; case AM_PANDOWNKEY: // pan down if (!followplayer) m_paninc.y = -FTOM(F_PANINC); else rc = false; break; case AM_ZOOMOUTKEY: // zoom out mtof_zoommul = M_ZOOMOUT; ftom_zoommul = M_ZOOMIN; break; case AM_ZOOMINKEY: // zoom in mtof_zoommul = M_ZOOMIN; ftom_zoommul = M_ZOOMOUT; break; case AM_ENDKEY: bigstate = 0; viewactive = true; AM_Stop (); break; case AM_GOBIGKEY: bigstate = !bigstate; if (bigstate) { AM_saveScaleAndLoc(); AM_minOutWindowScale(); } else AM_restoreScaleAndLoc(); break; case AM_FOLLOWKEY: followplayer = !followplayer; f_oldloc.x = MAXINT; plr->message = followplayer ? AMSTR_FOLLOWON : AMSTR_FOLLOWOFF; break; case AM_GRIDKEY: grid = !grid; plr->message = grid ? AMSTR_GRIDON : AMSTR_GRIDOFF; break; case AM_MARKKEY: sprintf(buffer, "%s %d", AMSTR_MARKEDSPOT, markpointnum); plr->message = buffer; AM_addMark(); break; case AM_CLEARMARKKEY: AM_clearMarks(); plr->message = AMSTR_MARKSCLEARED; break; default: cheatstate=0; rc = false; } if (!deathmatch && cht_CheckCheat(&cheat_amap, ev->data1)) { rc = false; cheating = (cheating+1) % 3; } } else if (ev->type == ev_keyup) { rc = false; switch (ev->data1) { case AM_PANRIGHTKEY: if (!followplayer) m_paninc.x = 0; break; case AM_PANLEFTKEY: if (!followplayer) m_paninc.x = 0; break; case AM_PANUPKEY: if (!followplayer) m_paninc.y = 0; break; case AM_PANDOWNKEY: if (!followplayer) m_paninc.y = 0; break; case AM_ZOOMOUTKEY: case AM_ZOOMINKEY: mtof_zoommul = FRACUNIT; ftom_zoommul = FRACUNIT; break; } } return rc; } void AM_changeWindowScale(void) { // Change the scaling multipliers scale_mtof = FixedMul(scale_mtof, mtof_zoommul); scale_ftom = FixedDiv(FRACUNIT, scale_mtof); if (scale_mtof < min_scale_mtof) AM_minOutWindowScale(); else if (scale_mtof > max_scale_mtof) AM_maxOutWindowScale(); else AM_activateNewScale(); } void AM_doFollowPlayer(void) { if (f_oldloc.x != plr->mo->x || f_oldloc.y != plr->mo->y) { // m_x = FTOM(MTOF(plr->mo->x - m_w/2)); // m_y = FTOM(MTOF(plr->mo->y - m_h/2)); // m_x = plr->mo->x - m_w/2; // m_y = plr->mo->y - m_h/2; m_x = FTOM(MTOF(plr->mo->x)) - m_w/2; m_y = FTOM(MTOF(plr->mo->y)) - m_h/2; m_x2 = m_x + m_w; m_y2 = m_y + m_h; f_oldloc.x = plr->mo->x; f_oldloc.y = plr->mo->y; } } void AM_updateLightLev(void) { static nexttic = 0; //static int litelevels[] = { 0, 3, 5, 6, 6, 7, 7, 7 }; static int litelevels[] = { 0, 4, 7, 10, 12, 14, 15, 15 }; static int litelevelscnt = 0; // Change light level if (amclock>nexttic) { lightlev = litelevels[litelevelscnt++]; if (litelevelscnt == sizeof(litelevels)/sizeof(int)) litelevelscnt = 0; nexttic = amclock + 6 - (amclock % 6); } } void AM_Ticker (void) { if (!automapactive) return; amclock++; if (followplayer) AM_doFollowPlayer(); // Change the zoom if necessary if (ftom_zoommul != FRACUNIT) AM_changeWindowScale(); // Change x,y location if (m_paninc.x || m_paninc.y) AM_changeWindowLoc(); // Update light level // AM_updateLightLev(); } void AM_clearFB(int color) { memset(fb, color, f_w*f_h); } // Based on Cohen-Sutherland clipping algorithm but with a slightly // faster reject and precalculated slopes. If I need the speed, will // hash algorithm to the common cases. boolean AM_clipMline(mline_t *ml, fline_t *fl) { enum { LEFT=1, RIGHT=2, BOTTOM=4, TOP=8 }; register outcode1 = 0, outcode2 = 0, outside; fpoint_t tmp; int dx, dy; #define DOOUTCODE(oc, mx, my) \ (oc) = 0; \ if ((my) < 0) (oc) |= TOP; \ else if ((my) >= f_h) (oc) |= BOTTOM; \ if ((mx) < 0) (oc) |= LEFT; \ else if ((mx) >= f_w) (oc) |= RIGHT // do trivial rejects and outcodes if (ml->a.y > m_y2) outcode1 = TOP; else if (ml->a.y < m_y) outcode1 = BOTTOM; if (ml->b.y > m_y2) outcode2 = TOP; else if (ml->b.y < m_y) outcode2 = BOTTOM; if (outcode1 & outcode2) return false; // trivially outside if (ml->a.x < m_x) outcode1 |= LEFT; else if (ml->a.x > m_x2) outcode1 |= RIGHT; if (ml->b.x < m_x) outcode2 |= LEFT; else if (ml->b.x > m_x2) outcode2 |= RIGHT; if (outcode1 & outcode2) return false; // trivially outside // transform to frame-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-f_h))/dy; tmp.y = 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*(f_w-1 - fl->a.x))/dx; tmp.x = 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 I need for speed void AM_drawFline(fline_t *fl, int color) { register int x, y, dx, dy, sx, sy, ax, ay, d; static fuck = 0; // For debugging only 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) { fprintf(stderr, "fuck %d \r", fuck++); return; } #define PUTDOT(xx,yy,cc) fb[(yy)*f_w+(xx)]=(cc) 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; } } } 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 buffer using fb coords } void AM_drawGrid(int color) { fixed_t x, y; fixed_t start, end; mline_t ml; // Figure out start of vertical gridlines start = m_x; if ((start-bmaporgx)%(MAPBLOCKUNITS<x; l.a.y = lines[i].v1->y; l.b.x = lines[i].v2->x; l.b.y = lines[i].v2->y; if (cheating || (lines[i].flags & ML_MAPPED)) { if ((lines[i].flags & LINE_NEVERSEE) && !cheating) continue; if (!lines[i].backsector) { AM_drawMline(&l, WALLCOLORS+lightlev); } else { if (lines[i].special == 39) { // teleporters AM_drawMline(&l, WALLCOLORS+WALLRANGE/2); } else if (lines[i].flags & ML_SECRET) // secret door { if (cheating) AM_drawMline(&l, SECRETWALLCOLORS + lightlev); else AM_drawMline(&l, WALLCOLORS+lightlev); } else if (lines[i].backsector->floorheight != lines[i].frontsector->floorheight) { AM_drawMline(&l, FDWALLCOLORS + lightlev); // floor level change } else if (lines[i].backsector->ceilingheight != lines[i].frontsector->ceilingheight) { AM_drawMline(&l, CDWALLCOLORS+lightlev); // ceiling level change } else if (cheating) { AM_drawMline(&l, TSWALLCOLORS+lightlev); } } } else if (plr->powers[pw_allmap]) { if (!(lines[i].flags & LINE_NEVERSEE)) AM_drawMline(&l, GRAYS+3); } } } 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;imo->angle, WHITE, plr->mo->x, plr->mo->y); else AM_drawLineCharacter(player_arrow, NUMPLYRLINES, 0, plr->mo->angle, WHITE, plr->mo->x, plr->mo->y); return; } for (i=0;ipowers[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;iangle, colors+lightlev, t->x, t->y); t = t->snext; } } } void AM_drawMarks(void) { int i, fx, fy, w, h; for (i=0;iwidth); // h = SHORT(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(markpoints[i].x); fy = CYMTOF(markpoints[i].y); if (fx >= f_x && fx <= f_w - w && fy >= f_y && fy <= f_h - h) V_DrawPatch(fx, fy, FB, marknums[i]); } } } void AM_drawCrosshair(int color) { fb[(f_w*(f_h+1))/2] = color; // single point for now } void AM_Drawer (void) { if (!automapactive) return; AM_clearFB(BACKGROUND); if (grid) AM_drawGrid(GRIDCOLORS); AM_drawWalls(); AM_drawPlayers(); if (cheating==2) AM_drawThings(THINGCOLORS, THINGRANGE); AM_drawCrosshair(XHAIRCOLORS); AM_drawMarks(); V_MarkRect(f_x, f_y, f_w, f_h); } \ No newline at end of file diff --git a/AM_MAP.H b/AM_MAP.H new file mode 100644 index 0000000..7423318 --- /dev/null +++ b/AM_MAP.H @@ -0,0 +1 @@ +#ifndef __AMMAP_H__ #define __AMMAP_H__ // For use if I do walls with outsides/insides #define REDS (256-5*16) #define REDRANGE 16 #define BLUES (256-4*16+8) #define BLUERANGE 8 #define GREENS (7*16) #define GREENRANGE 16 #define GRAYS (6*16) #define GRAYSRANGE 16 #define BROWNS (4*16) #define BROWNRANGE 16 #define YELLOWS (256-32+7) #define YELLOWRANGE 1 #define BLACK 0 #define WHITE (256-47) // Automap colors #define BACKGROUND BLACK #define YOURCOLORS WHITE #define YOURRANGE 0 #define WALLCOLORS REDS #define WALLRANGE REDRANGE #define TSWALLCOLORS GRAYS #define TSWALLRANGE GRAYSRANGE #define FDWALLCOLORS BROWNS #define FDWALLRANGE BROWNRANGE #define CDWALLCOLORS YELLOWS #define CDWALLRANGE YELLOWRANGE #define THINGCOLORS GREENS #define THINGRANGE GREENRANGE #define SECRETWALLCOLORS WALLCOLORS #define SECRETWALLRANGE WALLRANGE #define GRIDCOLORS (GRAYS + GRAYSRANGE/2) #define GRIDRANGE 0 #define XHAIRCOLORS GRAYS // drawing stuff #define FB 0 #define AM_PANDOWNKEY KEY_DOWNARROW #define AM_PANUPKEY KEY_UPARROW #define AM_PANRIGHTKEY KEY_RIGHTARROW #define AM_PANLEFTKEY KEY_LEFTARROW #define AM_ZOOMINKEY '=' #define AM_ZOOMOUTKEY '-' #define AM_STARTKEY KEY_TAB #define AM_ENDKEY KEY_TAB #define AM_GOBIGKEY '0' #define AM_FOLLOWKEY 'f' #define AM_GRIDKEY 'g' #define AM_MARKKEY 'm' #define AM_CLEARMARKKEY 'c' #define AM_NUMMARKPOINTS 10 #define AM_MSGHEADER (('a'<<24)+('m'<<16)) #define AM_MSGENTERED (AM_MSGHEADER | ('e'<<8)) #define AM_MSGEXITED (AM_MSGHEADER | ('x'<<8)) // scale on entry #define INITSCALEMTOF (.2*FRACUNIT) // how much the automap moves window per tic in frame-buffer coordinates // moves 140 pixels in 1 second #define F_PANINC 4 // how much zoom-in per tic // goes to 2x in 1 second #define M_ZOOMIN ((int) (1.02*FRACUNIT)) // how much zoom-out per tic // pulls out to 0.5x in 1 second #define M_ZOOMOUT ((int) (FRACUNIT/1.02)) // translates between frame-buffer and map distances #define FTOM(x) FixedMul(((x)<<16),scale_ftom) #define MTOF(x) (FixedMul((x),scale_mtof)>>16) // translates between frame-buffer and map coordinates #define CXMTOF(x) (f_x + MTOF((x)-m_x)) #define CYMTOF(y) (f_y + (f_h - MTOF((y)-m_y))) // the following is crap #define LINE_NEVERSEE ML_DONTDRAW typedef struct { int x, y; } fpoint_t; typedef struct { fpoint_t a, b; } fline_t; typedef struct { fixed_t x,y; } mpoint_t; typedef struct { mpoint_t a, b; } mline_t; typedef struct { fixed_t slp, islp; } islope_t; #endif \ No newline at end of file diff --git a/AM_OIDS.C b/AM_OIDS.C new file mode 100644 index 0000000..004f224 --- /dev/null +++ b/AM_OIDS.C @@ -0,0 +1 @@ +// the asteroids-ish game inside of the automap #include "DoomDef.h" #include "AM_map.h" #include "AM_oids.h" fixed_t ff_x, ff_y, ff_w, ff_h; amo_bullet_t amo_bullets[AMO_MAXBULLETS]; boolean AM_oInRock(amo_rock_t *rock, fixed_t x, fixed_t y) { fixed_t dx2, dy2; boolean rc = false; dx2 = FixedMul(x-rock->x, x-rock->x); dy2 = FixedMul(y-rock->y, y-rock->y); if (dx2+dy2 <= rock->r2) rc = true; return rc; } void AM_oUpdateBullets(void) { int i; amo_bullet_t *a; for (a=amo_bullets;ax != -1) { // move bullet a->x += a->vx; a->y += a->vy; // destroy bullet if it left the screen if (a->x < ff_x || a->x >= ff_x + ff_w || a->y < ff_y || a->y >= ff_y + ff_h) { a->x = -1; continue; } // check for collision with any rock for (r=amo_rocks;rx != -1 && AM_oInRock(r, a->x, a->y)) { a->x = r->x = -1; // if collision, destroy bullet and rock break; } } } } } void AM_oTicker(void) { AM_oUpdateBullets(); AM_oUpdateShip(); AM_oUpdateRocks(); AM_oUpdateShrapnel(); } void AM_oDrawer(void) { } void AM_oInitData(void) { int i; for (i=0;i>1; // OPTIMIZE: this could be faster by making multiple copies of the dither // with the apropriate bits already masked off for (y=0 ; y>2; // OPTIMIZE: this could be faster by making multiple copies of the dither // with the apropriate bits already masked off for (y=0 ; y #include #ifdef __WATCOMC__ #define USEASM #include #define strcasecmp strcmpi #define strncasecmp strnicmp #endif #define VERSION 109 // if rangecheck is undefined, most parameter validation debugging code // will not be compiled #define RANGECHECK #define FRENCH // all external data is defined here #include "doomdata.h" // all important printed strings #ifdef FRENCH #include "d_french.h" #else #include "dstrings.h" #endif // header generated by multigen utility #include "info.h" // mode X mapmask register #define SC_INDEX 0x3c4 #define SC_MAPMASK 2 #define GC_INDEX 0x3ce #define GC_READMAP 4 #define GC_MODE 5 extern byte *destview, *destscreen; // PC direct to screen pointers // // most key data are simple ascii (uppercased) // #define KEY_RIGHTARROW 0xae #define KEY_LEFTARROW 0xac #define KEY_UPARROW 0xad #define KEY_DOWNARROW 0xaf #define KEY_ESCAPE 27 #define KEY_ENTER 13 #define KEY_TAB 9 #define KEY_F1 (0x80+0x3b) #define KEY_F2 (0x80+0x3c) #define KEY_F3 (0x80+0x3d) #define KEY_F4 (0x80+0x3e) #define KEY_F5 (0x80+0x3f) #define KEY_F6 (0x80+0x40) #define KEY_F7 (0x80+0x41) #define KEY_F8 (0x80+0x42) #define KEY_F9 (0x80+0x43) #define KEY_F10 (0x80+0x44) #define KEY_F11 (0x80+0x57) #define KEY_F12 (0x80+0x58) #define KEY_BACKSPACE 127 #define KEY_PAUSE 0xff #define KEY_EQUALS 0x3d #define KEY_MINUS 0x2d #define KEY_RSHIFT (0x80+0x36) #define KEY_RCTRL (0x80+0x1d) #define KEY_RALT (0x80+0x38) #define KEY_LALT KEY_RALT #define MAXCHAR ((char)0x7f) #define MAXSHORT ((short)0x7fff) #define MAXINT ((int)0x7fffffff) /* max pos 32-bit int */ #define MAXLONG ((long)0x7fffffff) #define MINCHAR ((char)0x80) #define MINSHORT ((short)0x8000) #define MININT ((int)0x80000000) /* max negative 32-bit integer */ #define MINLONG ((long)0x80000000) #define FINEANGLES 8192 #define FINEMASK (FINEANGLES-1) #define ANGLETOFINESHIFT 19 // 0x100000000 to 0x2000 #define SAVEGAMENAME "doomsav" /* =============================================================================== GLOBAL TYPES =============================================================================== */ #define MAXPLAYERS 4 #define TICRATE 35 // number of tics / second #define FRACBITS 16 #define FRACUNIT (1<type] int tics; // state tic counter state_t *state; int flags; int health; int movedir; // 0-7 int movecount; // when 0, select a new dir struct mobj_s *target; // thing being chased/attacked (or NULL) // also the originator for missiles int reactiontime; // if non 0, don't attack yet // used by player to freeze a bit after // teleporting int threshold; // if >0, the target will be chased // no matter what (even if shot) struct player_s *player; // only valid if type == MT_PLAYER int lastlook; // player number last looked for mapthing_t spawnpoint; // for nightmare respawn struct mobj_s *tracer; // thing being chased/attacked for tracers } mobj_t; // each sector has a degenmobj_t in it's center for sound origin purposes typedef struct { thinker_t thinker; // not used for anything fixed_t x,y,z; } degenmobj_t; // // frame flags // #define FF_FULLBRIGHT 0x8000 // flag in thing->frame #define FF_FRAMEMASK 0x7fff // // mobj flags // #define MF_SPECIAL 1 // call P_SpecialThing when touched #define MF_SOLID 2 #define MF_SHOOTABLE 4 #define MF_NOSECTOR 8 // don't use the sector links // (invisible but touchable) #define MF_NOBLOCKMAP 16 // don't use the blocklinks // (inert but displayable) #define MF_AMBUSH 32 #define MF_JUSTHIT 64 // try to attack right back #define MF_JUSTATTACKED 128 // take at least one step before attacking #define MF_SPAWNCEILING 256 // hang from ceiling instead of floor #define MF_NOGRAVITY 512 // don't apply gravity every tic // movement flags #define MF_DROPOFF 0x400 // allow jumps from high places #define MF_PICKUP 0x800 // for players to pick up items #define MF_NOCLIP 0x1000 // player cheat #define MF_SLIDE 0x2000 // keep info about sliding along walls #define MF_FLOAT 0x4000 // allow moves to any height, no gravity #define MF_TELEPORT 0x8000 // don't cross lines or look at heights #define MF_MISSILE 0x10000 // don't hit same species, explode on block #define MF_DROPPED 0x20000 // dropped by a demon, not level spawned #define MF_SHADOW 0x40000 // use fuzzy draw (shadow demons / invis) #define MF_NOBLOOD 0x80000 // don't bleed when shot (use puff) #define MF_CORPSE 0x100000 // don't stop moving halfway off a step #define MF_INFLOAT 0x200000 // floating to a height for a move, don't // auto float to target's height #define MF_COUNTKILL 0x400000 // count towards intermission kill total #define MF_COUNTITEM 0x800000 // count towards intermission item total #define MF_SKULLFLY 0x1000000 // skull in flight #define MF_NOTDMATCH 0x2000000 // don't spawn in death match (key cards) #define MF_TRANSLATION 0xc000000 // if 0x4 0x8 or 0xc, use a translation #define MF_TRANSSHIFT 26 // table for player colormaps //============================================================================= typedef enum { PST_LIVE, // playing PST_DEAD, // dead on the ground PST_REBORN // ready to restart } playerstate_t; // psprites are scaled shapes directly on the view screen // coordinates are given for a 320*200 view screen typedef enum { ps_weapon, ps_flash, NUMPSPRITES } psprnum_t; typedef struct { state_t *state; // a NULL state means not active int tics; fixed_t sx, sy; } pspdef_t; typedef enum { it_bluecard, it_yellowcard, it_redcard, it_blueskull, it_yellowskull, it_redskull, NUMCARDS } card_t; typedef enum { wp_fist, wp_pistol, wp_shotgun, wp_chaingun, wp_missile, wp_plasma, wp_bfg, wp_chainsaw, wp_supershotgun, NUMWEAPONS, wp_nochange } weapontype_t; typedef enum { am_clip, // pistol / chaingun am_shell, // shotgun am_cell, // BFG am_misl, // missile launcher NUMAMMO, am_noammo // chainsaw / fist } ammotype_t; typedef struct { ammotype_t ammo; int upstate; int downstate; int readystate; int atkstate; int flashstate; } weaponinfo_t; extern weaponinfo_t weaponinfo[NUMWEAPONS]; typedef enum { pw_invulnerability, pw_strength, pw_invisibility, pw_ironfeet, pw_allmap, pw_infrared, NUMPOWERS } powertype_t; #define INVULNTICS (30*35) #define INVISTICS (60*35) #define INFRATICS (120*35) #define IRONTICS (60*35) /* ================ = = player_t = ================ */ typedef struct player_s { mobj_t *mo; playerstate_t playerstate; ticcmd_t cmd; fixed_t viewz; // focal origin above r.z fixed_t viewheight; // base height above floor for viewz fixed_t deltaviewheight; // squat speed fixed_t bob; // bounded/scaled total momentum int health; // only used between levels, mo->health // is used during levels int armorpoints, armortype; // armor type is 0-2 int powers[NUMPOWERS]; // invinc and invis are tic counters boolean cards[NUMCARDS]; boolean backpack; int frags[MAXPLAYERS]; // kills of other players weapontype_t readyweapon; weapontype_t pendingweapon; // wp_nochange if not changing boolean weaponowned[NUMWEAPONS]; int ammo[NUMAMMO]; int maxammo[NUMAMMO]; int attackdown, usedown; // true if button down last tic int cheats; // bit flags int refire; // refired shots are less accurate int killcount, itemcount, secretcount; // for intermission char *message; // hint messages int damagecount, bonuscount;// for screen flashing mobj_t *attacker; // who did damage (NULL for floors) int extralight; // so gun flashes light up areas int fixedcolormap; // can be set to REDCOLORMAP, etc int colormap; // 0-3 for which color to draw player pspdef_t psprites[NUMPSPRITES]; // view sprites (gun, etc) boolean didsecret; // true if secret level has been done } player_t; #define CF_NOCLIP 1 #define CF_GODMODE 2 #define CF_NOMOMENTUM 4 // not really a cheat, just a debug aid #define BACKUPTICS 12 typedef struct { unsigned checksum; // high bit is retransmit request byte retransmitfrom; // only valid if NCMD_RETRANSMIT byte starttic; byte player, numtics; ticcmd_t cmds[BACKUPTICS]; } doomdata_t; typedef struct { long id; short intnum; // DOOM executes an int to execute commands // communication between DOOM and the driver short command; // CMD_SEND or CMD_GET short remotenode; // dest for send, set by get (-1 = no packet) short datalength; // bytes in doomdata to be sent // info common to all nodes short numnodes; // console is allways node 0 short ticdup; // 1 = no duplication, 2-5 = dup for slow nets short extratics; // 1 = send a backup tic in every packet short deathmatch; // 1 = deathmatch short savegame; // -1 = new game, 0-5 = load savegame short episode; // 1-3 short map; // 1-9 short skill; // 1-5 // info specific to this node short consoleplayer; short numplayers; short angleoffset; // 1 = left, 0 = center, -1 = right short drone; // 1 = drone // packet data to be sent doomdata_t data; } doomcom_t; #define DOOMCOM_ID 0x12345678l extern doomcom_t *doomcom; extern doomdata_t *netbuffer; // points inside doomcom #define MAXNETNODES 8 // max computers in a game #define CMD_SEND 1 #define CMD_GET 2 /* =============================================================================== GLOBAL VARIABLES =============================================================================== */ #define MAXEVENTS 64 extern event_t events[MAXEVENTS]; extern int eventhead, eventtail; extern fixed_t finesine[5*FINEANGLES/4]; extern fixed_t *finecosine; extern gameaction_t gameaction; #define SBARHEIGHT 32 // status bar height at bottom of screen extern boolean nomonsters; // checkparm of -nomonsters extern boolean respawnparm; // checkparm of -respawn extern boolean fastparm; // checkparm of -fast extern boolean statusbaractive; extern boolean automapactive; extern boolean menuactive; extern boolean paused; extern boolean usergame; // ok to save / end game extern boolean devparm; // launched with -devparm extern boolean shareware; // true if episode 1 only extern boolean registered; // true if complete version extern boolean commercial; // true if DOOM II: Hell On Earth extern boolean french; extern boolean deathmatch; // only if started as net death extern boolean netgame; // only true if >1 player extern boolean playeringame[MAXPLAYERS]; extern int consoleplayer; // player taking events and displaying extern int displayplayer; extern int viewangleoffset; // ANG90 = left side, ANG270 = right extern player_t players[MAXPLAYERS]; extern boolean singletics; // debug flag to cancel adaptiveness extern int maxammo[NUMAMMO]; extern boolean demoplayback; extern boolean demorecording; extern int skytexture; extern gamestate_t gamestate; extern skill_t gameskill; extern boolean respawnmonsters; extern int gameepisode; extern int gamemap; extern int totalkills, totalitems, totalsecret; // for intermission extern int levelstarttic; // gametic at level start extern int leveltime; // tics in game play for par extern ticcmd_t netcmds[MAXPLAYERS][BACKUPTICS]; extern int ticdup; extern char basedefault[1024]; #define MAXNETNODES 8 extern ticcmd_t localcmds[BACKUPTICS]; extern int rndindex; extern int gametic, maketic; extern int nettics[MAXNETNODES]; #define SAVEGAMESIZE 0x2c000 #define SAVESTRINGSIZE 24 extern byte *savebuffer, *save_p; extern mapthing_t deathmatchstarts[10], *deathmatch_p; extern mapthing_t playerstarts[MAXPLAYERS]; extern int viewwindowx, viewwindowy; extern int viewwidth, scaledviewwidth, viewheight; extern int mouseSensitivity; extern boolean precache; // if true, load all graphics at level load extern byte *screens[5]; extern boolean viewactive; extern boolean nodrawers; extern boolean noblit; extern boolean singledemo; // quit after playing a demo from cmdline extern FILE *debugfile; // wipegamestate can be set to -1 to force a wipe on the next draw extern gamestate_t wipegamestate; extern boolean modifiedgame; // set if homebrew stuff has been added extern int bodyqueslot; extern skill_t startskill; extern int startepisode, startmap; extern boolean autostart; /* =============================================================================== GLOBAL FUNCTIONS =============================================================================== */ fixed_t FixedMul (fixed_t a, fixed_t b); fixed_t FixedDiv (fixed_t a, fixed_t b); fixed_t FixedDiv2 (fixed_t a, fixed_t b); #ifdef __WATCOMC__ #pragma aux FixedMul = \ "imul ebx", \ "shrd eax,edx,16" \ parm [eax] [ebx] \ value [eax] \ modify exact [eax edx] #pragma aux FixedDiv2 = \ "cdq", \ "shld edx,eax,16", \ "sal eax,16", \ "idiv ebx" \ parm [eax] [ebx] \ value [eax] \ modify exact [eax edx] #endif #ifdef __BIG_ENDIAN__ short ShortSwap(short); long LongSwap(long); #define SHORT(x) ShortSwap(x) #define LONG(x) LongSwap(x) #else #define SHORT(x) (x) #define LONG(x) (x) #endif //----------- //MEMORY ZONE //----------- // tags < 100 are not overwritten until freed #define PU_STATIC 1 // static entire execution time #define PU_SOUND 2 // static while playing #define PU_MUSIC 3 // static while playing #define PU_DAVE 4 // anything else Dave wants static #define PU_LEVEL 50 // static until level exited #define PU_LEVSPEC 51 // a special thinker in a level // tags >= 100 are purgable whenever needed #define PU_PURGELEVEL 100 #define PU_CACHE 101 void Z_Init (void); void *Z_Malloc (int size, int tag, void *ptr); void Z_Free (void *ptr); void Z_FreeTags (int lowtag, int hightag); void Z_DumpHeap (int lowtag, int hightag); void Z_FileDumpHeap (FILE *f); void Z_CheckHeap (void); void Z_ChangeTag2 (void *ptr, int tag); int Z_FreeMemory (void); typedef struct memblock_s { int size; // including the header and possibly tiny fragments void **user; // NULL if a free block int tag; // purgelevel int id; // should be ZONEID struct memblock_s *next, *prev; } memblock_t; #define Z_ChangeTag(p,t) \ { \ if (( (memblock_t *)( (byte *)(p) - sizeof(memblock_t)))->id!=0x1d4a11) \ I_Error("Z_CT at "__FILE__":%i",__LINE__); \ Z_ChangeTag2(p,t); \ }; //------- //WADFILE //------- typedef struct { char name[8]; int handle,position,size; } lumpinfo_t; extern lumpinfo_t *lumpinfo; extern int numlumps; void W_InitMultipleFiles (char **filenames); void W_Reload (void); int W_CheckNumForName (char *name); int W_GetNumForName (char *name); int W_LumpLength (int lump); void W_ReadLump (int lump, void *dest); void *W_CacheLumpNum (int lump, int tag); void *W_CacheLumpName (char *name, int tag); //---------- //BASE LEVEL //---------- void D_DoomMain (void); // not a globally visible function, just included for source reference // calls all startup code // parses command line options // if not overrided, calls N_AdvanceDemo void D_DoomLoop (void); // not a globally visible function, just included for source reference // called by D_DoomMain, never exits // manages timing and IO // calls all ?_Responder, ?_Ticker, and ?_Drawer functions // calls I_GetTime, I_StartFrame, and I_StartTic void D_PostEvent (event_t *ev); // called by IO functions when input is detected void NetUpdate (void); // create any new ticcmds and broadcast to other players void D_QuitNetGame (void); // broadcasts special packets to other players to notify of game exit void TryRunTics (void); void D_PageTicker (void); void D_PageDrawer (void); void D_AdvanceDemo (void); void D_StartTitle (void); void mprintf(char *string); //--------- //SYSTEM IO //--------- #define SCREENWIDTH 320 #define SCREENHEIGHT 200 byte *I_ZoneBase (int *size); // called by startup code to get the ammount of memory to malloc // for the zone management int I_GetTime (void); // called by D_DoomLoop // returns current time in tics void I_StartFrame (void); // called by D_DoomLoop // called before processing any tics in a frame (just after displaying a frame) // time consuming syncronous operations are performed here (joystick reading) // can call D_PostEvent void I_StartTic (void); // called by D_DoomLoop // called before processing each tic in a frame // quick syncronous operations are performed here // can call D_PostEvent // asyncronous interrupt functions should maintain private ques that are // read by the syncronous functions to be converted into events ticcmd_t *I_BaseTiccmd (void); // either returns a null ticcmd, or calls a loadable driver to build it // this ticcmd will then be modified by the gameloop for normal input void I_Init (void); // called by D_DoomMain // determines the hardware configuration and sets up the video mode void I_InitGraphics (void); void I_InitNetwork (void); void I_NetCmd (void); void I_Error (char *error, ...); // called by anything that can generate a terminal error // bad exit with diagnostic message void I_Quit (void); // called by M_Responder when quit is selected // clean exit, displays sell blurb void I_SetPalette (byte *palette); // takes full 8 bit values void I_UpdateNoBlit (void); void I_FinishUpdate (void); void I_WaitVBL(int count); // wait for vertical retrace or pause a bit void I_ReadScreen (byte *scr); void I_BeginRead (void); void I_EndRead (void); byte *I_AllocLow (int length); // allocates from low memory under dos, just mallocs under unix void I_Tactile (int on, int off, int total); //---- //GAME //---- void G_DeathMatchSpawnPlayer (int playernum); void G_InitNew (skill_t skill, int episode, int map); void G_DeferedInitNew (skill_t skill, int episode, int map); // can be called by the startup code or M_Responder // a normal game starts at map 1, but a warp test can start elsewhere void G_DeferedPlayDemo (char *demo); void G_LoadGame (char *name); // can be called by the startup code or M_Responder // calls P_SetupLevel or W_EnterWorld void G_DoLoadGame (void); void G_SaveGame (int slot, char *description); // called by M_Responder void G_RecordDemo (char *name); // only called by startup code void G_BeginRecording (void); void G_PlayDemo (char *name); void G_TimeDemo (char *name); boolean G_CheckDemoStatus (void); void G_ExitLevel (void); void G_SecretExitLevel (void); void G_WorldDone (void); void G_Ticker (void); boolean G_Responder (event_t *ev); void G_ScreenShot (void); //----- //PLAY //----- void P_Ticker (void); // called by C_Ticker // can call G_PlayerExited // carries out all thinking of monsters and players void P_SetupLevel (int episode, int map, int playermask, skill_t skill); // called by W_Ticker void P_Init (void); // called by startup code void P_ArchivePlayers (void); void P_UnArchivePlayers (void); void P_ArchiveWorld (void); void P_UnArchiveWorld (void); void P_ArchiveThinkers (void); void P_UnArchiveThinkers (void); void P_ArchiveSpecials (void); void P_UnArchiveSpecials (void); // load / save game routines //----- //MENUS //----- boolean M_Responder (event_t *ev); // called by main loop // saves config file and calls I_Quit when user exits // even when the menu is not displayed, this can resize the view and // change game parameters // does all the real work of the menu interaction void M_Ticker (void); // called by main loop // only used for menu animation void M_Drawer (void); // called by main loop // draws the menus directly into the screen buffer void M_Init (void); // called by D_DoomMain // loads the config file void M_StartControlPanel (void); // called by intro code to force menu up upon a keypress // does nothing if menu is already up //------------ //INTERMISSION //------------ // Structure passed to WI_Start(wb) typedef struct { boolean in; // whether the player is in game int skills, sitems, ssecret, stime; // player stats int frags[4]; int score; // current score on entry, modified on return } wbplayerstruct_t; typedef struct { int epsd; // episode # (0-2) boolean didsecret; // if true, splash the secret level int last, next; // previous and next levels, origin 0 int maxkills, maxitems, maxsecret, maxfrags; int partime; // the par time int pnum; // index of this player in game wbplayerstruct_t plyr[MAXPLAYERS]; } wbstartstruct_t; extern wbstartstruct_t wminfo; // parms for world map / intermission void WI_Ticker (void); // called by main loop // animate the intermission void WI_Drawer (void); // called by main loop // draws the intermission directly into the screen buffer void WI_Start(wbstartstruct_t *wbstartstruct); // setup for an intermission //------ //FINALE //------ boolean F_Responder (event_t *ev); // called by main loop void F_Ticker (void); // called by main loop void F_Drawer (void); // called by main loop void F_StartFinale (void); //-------- //AUTO MAP //-------- boolean AM_Responder (event_t *ev); // called by main loop void AM_Ticker (void); // called by main loop void AM_Drawer (void); // called by main loop // called instead of view drawer if automapactive void AM_Stop (void); // called to force the automap to quit if the level is compelted // while it is up //---------- //STATUS BAR //---------- boolean ST_Responder (event_t *ev); // called by main loop void ST_Ticker (void); // called by main loop void ST_Drawer (boolean fullscreen, boolean refresh); // called by main loop void ST_Start (void); // called when the console player is spawned on each level void ST_Init (void); // called by startup code //---------- //HEADS UP TEXT //---------- void HU_Init(void); void HU_Start(void); boolean HU_Responder(event_t *ev); void HU_Ticker(void); void HU_Drawer(void); char HU_dequeueChatChar(void); void HU_Erase(void); //------- //REFRESH //------- void R_RenderPlayerView (player_t *player); // called by G_Drawer void R_Init (void); // called by startup code void R_FillBackScreen (void); void R_DrawViewBorder (void); // if the view size is not full screen, draws a border around it void R_SetViewSize (int blocks, int detail); // called by M_Responder int R_FlatNumForName (char *name); int R_TextureNumForName (char *name); int R_CheckTextureNumForName (char *name); // called by P_Ticker for switches and animations // returns the texture number for the texture name //---- //MISC //---- extern int myargc; extern char **myargv; int M_CheckParm (char *check); // returns the position of the given parameter in the arg list (0 if not found) int M_Random (void); // returns a number from 0 to 255 int P_Random (void); // as M_Random, but used only by the play simulation void M_ClearRandom (void); // fix randoms for demos void M_ClearBox (fixed_t *box); void M_AddToBox (fixed_t *box, fixed_t x, fixed_t y); // bounding box functions boolean M_WriteFile (char const *name, void *source, int length); int M_ReadFile (char const *name, byte **buffer); void M_ScreenShot (void); void M_LoadDefaults (void); void M_SaveDefaults (void); int M_DrawText (int x, int y, boolean direct, char *string); //------ // VIDEO //------ // screen 0 is the screen updated by I_Update screen // screen 1 is an extra buffer extern int dirtybox[4]; extern byte gammatable[5][256]; extern int usegamma; void V_Init (void); // allocates buffer screens, call before R_Init void V_CopyRect (int srcx, int srcy, int srcscrn, int width, int height, int destx, int desty, int destscrn); void V_DrawPatch (int x, int y, int scrn, patch_t *patch); void V_DrawPatchDirect (int x, int y, int scrn, patch_t *patch); void V_DrawBlock (int x, int y, int scrn, int width, int height, byte *src); // draw a linear block of pixels into the view buffer void V_GetBlock (int x, int y, int scrn, int width, int height, byte *dest); // reads a linear block of pixels into the view buffer void V_MarkRect (int x, int y, int width, int height); // header generated by Dave's sound utility #include "sounds.h" // file locations #ifdef __NeXT__ #define DEVMAPS "/flem/doom/" #define DEVDATA "/LocalId/" #endif #ifdef NORMALUNIX #define DEVMAPS "/flem/doom/" #define DEVDATA "/LocalId/" #endif #ifdef __WATCOMC__ #define DEVMAPS "e:/doom/" #define DEVDATA "c:/localid/" #endif #endif // __DOOMDEF__ \ No newline at end of file diff --git a/DSTRINGS.H b/DSTRINGS.H new file mode 100644 index 0000000..9836ccb --- /dev/null +++ b/DSTRINGS.H @@ -0,0 +1 @@ +// // Printed strings for translation // // // D_Main.C // #define D_DEVSTR "Development mode ON.\n" #define D_CDROM "CD-ROM Version: default.cfg from c:\\doomdata\n" // // M_Menu.C // #define PRESSKEY "press a key." #define PRESSYN "press y or n." #define QUITMSG "are you sure you want to\nquit this great game?" #define LOADNET "you can't do load while in a net game!\n\n"PRESSKEY #define QLOADNET "you can't quickload during a netgame!\n\n"PRESSKEY #define QSAVESPOT "you haven't picked a quicksave slot yet!\n\n"PRESSKEY #define SAVEDEAD "you can't save if you aren't playing!\n\n"PRESSKEY #define QSPROMPT "quicksave over your game named\n\n'%s'?\n\n"PRESSYN #define QLPROMPT "do you want to quickload the game named"\ "\n\n'%s'?\n\n"PRESSYN #define NEWGAME "you can't start a new game\n"\ "while in a network game.\n\n"PRESSKEY #define NIGHTMARE "are you sure? this skill level\n"\ "isn't even remotely fair.\n\n"PRESSYN #define SWSTRING "this is the shareware version of doom.\n\n"\ "you need to order the entire trilogy.\n\n"PRESSKEY #define MSGOFF "Messages OFF" #define MSGON "Messages ON" #define NETEND "you can't end a netgame!\n\n"PRESSKEY #define ENDGAME "are you sure you want to end the game?\n\n"PRESSYN #ifdef __WATCOMC__ #define DOSY "(press y to quit to dos.)" #else #define DOSY "(press y to quit)" #endif #define DETAILHI "High detail" #define DETAILLO "Low detail" #define GAMMALVL0 "Gamma correction OFF" #define GAMMALVL1 "Gamma correction level 1" #define GAMMALVL2 "Gamma correction level 2" #define GAMMALVL3 "Gamma correction level 3" #define GAMMALVL4 "Gamma correction level 4" #define EMPTYSTRING "empty slot" // // P_inter.C // #define GOTARMOR "Picked up the armor." #define GOTMEGA "Picked up the MegaArmor!" #define GOTHTHBONUS "Picked up a health bonus." #define GOTARMBONUS "Picked up an armor bonus." #define GOTSTIM "Picked up a stimpack." #define GOTMEDINEED "Picked up a medikit that you REALLY need!" #define GOTMEDIKIT "Picked up a medikit." #define GOTSUPER "Supercharge!" #define GOTBLUECARD "Picked up a blue keycard." #define GOTYELWCARD "Picked up a yellow keycard." #define GOTREDCARD "Picked up a red keycard." #define GOTBLUESKUL "Picked up a blue skull key." #define GOTYELWSKUL "Picked up a yellow skull key." #define GOTREDSKULL "Picked up a red skull key." #define GOTINVUL "Invulnerability!" #define GOTBERSERK "Berserk!" #define GOTINVIS "Partial Invisibility" #define GOTSUIT "Radiation Shielding Suit" #define GOTMAP "Computer Area Map" #define GOTVISOR "Light Amplification Visor" #define GOTMSPHERE "MegaSphere!" #define GOTCLIP "Picked up a clip." #define GOTCLIPBOX "Picked up a box of bullets." #define GOTROCKET "Picked up a rocket." #define GOTROCKBOX "Picked up a box of rockets." #define GOTCELL "Picked up an energy cell." #define GOTCELLBOX "Picked up an energy cell pack." #define GOTSHELLS "Picked up 4 shotgun shells." #define GOTSHELLBOX "Picked up a box of shotgun shells." #define GOTBACKPACK "Picked up a backpack full of ammo!" #define GOTBFG9000 "You got the BFG9000! Oh, yes." #define GOTCHAINGUN "You got the chaingun!" #define GOTCHAINSAW "A chainsaw! Find some meat!" #define GOTLAUNCHER "You got the rocket launcher!" #define GOTPLASMA "You got the plasma gun!" #define GOTSHOTGUN "You got the shotgun!" #define GOTSHOTGUN2 "You got the super shotgun!" // // P_Doors.C // #define PD_BLUEO "You need a blue key to activate this object" #define PD_REDO "You need a red key to activate this object" #define PD_YELLOWO "You need a yellow key to activate this object" #define PD_BLUEK "You need a blue key to open this door" #define PD_REDK "You need a red key to open this door" #define PD_YELLOWK "You need a yellow key to open this door" // // G_game.C // #define GGSAVED "game saved." // // HU_stuff.C // #define HUSTR_MSGU "[Message unsent]" #define HUSTR_E1M1 "E1M1: Hangar" #define HUSTR_E1M2 "E1M2: Nuclear Plant" #define HUSTR_E1M3 "E1M3: Toxin Refinery" #define HUSTR_E1M4 "E1M4: Command Control" #define HUSTR_E1M5 "E1M5: Phobos Lab" #define HUSTR_E1M6 "E1M6: Central Processing" #define HUSTR_E1M7 "E1M7: Computer Station" #define HUSTR_E1M8 "E1M8: Phobos Anomaly" #define HUSTR_E1M9 "E1M9: Military Base" #define HUSTR_E2M1 "E2M1: Deimos Anomaly" #define HUSTR_E2M2 "E2M2: Containment Area" #define HUSTR_E2M3 "E2M3: Refinery" #define HUSTR_E2M4 "E2M4: Deimos Lab" #define HUSTR_E2M5 "E2M5: Command Center" #define HUSTR_E2M6 "E2M6: Halls of the Damned" #define HUSTR_E2M7 "E2M7: Spawning Vats" #define HUSTR_E2M8 "E2M8: Tower of Babel" #define HUSTR_E2M9 "E2M9: Fortress of Mystery" #define HUSTR_E3M1 "E3M1: Hell Keep" #define HUSTR_E3M2 "E3M2: Slough of Despair" #define HUSTR_E3M3 "E3M3: Pandemonium" #define HUSTR_E3M4 "E3M4: House of Pain" #define HUSTR_E3M5 "E3M5: Unholy Cathedral" #define HUSTR_E3M6 "E3M6: Mt. Erebus" #define HUSTR_E3M7 "E3M7: Limbo" #define HUSTR_E3M8 "E3M8: Dis" #define HUSTR_E3M9 "E3M9: Warrens" #define HUSTR_1 "level 1: entryway" #define HUSTR_2 "level 2: underhalls" #define HUSTR_3 "level 3: the gantlet" #define HUSTR_4 "level 4: the focus" #define HUSTR_5 "level 5: the waste tunnels" #define HUSTR_6 "level 6: the crusher" #define HUSTR_7 "level 7: dead simple" #define HUSTR_8 "level 8: tricks and traps" #define HUSTR_9 "level 9: the pit" #define HUSTR_10 "level 10: refueling base" #define HUSTR_11 "level 11: 'o' of destruction!" #define HUSTR_12 "level 12: the factory" #define HUSTR_13 "level 13: downtown" #define HUSTR_14 "level 14: the inmost dens" #define HUSTR_15 "level 15: industrial zone" #define HUSTR_16 "level 16: suburbs" #define HUSTR_17 "level 17: tenements" #define HUSTR_18 "level 18: the courtyard" #define HUSTR_19 "level 19: the citadel" #define HUSTR_20 "level 20: gotcha!" #define HUSTR_21 "level 21: nirvana" #define HUSTR_22 "level 22: the catacombs" #define HUSTR_23 "level 23: barrels o' fun" #define HUSTR_24 "level 24: the chasm" #define HUSTR_25 "level 25: bloodfalls" #define HUSTR_26 "level 26: the abandoned mines" #define HUSTR_27 "level 27: monster condo" #define HUSTR_28 "level 28: the spirit world" #define HUSTR_29 "level 29: the living end" #define HUSTR_30 "level 30: icon of sin" #define HUSTR_31 "level 31: wolfenstein" #define HUSTR_32 "level 32: grosse" #define HUSTR_CHATMACRO1 "I'm ready to kick butt!" #define HUSTR_CHATMACRO2 "I'm OK." #define HUSTR_CHATMACRO3 "I'm not looking too good!" #define HUSTR_CHATMACRO4 "Help!" #define HUSTR_CHATMACRO5 "You suck!" #define HUSTR_CHATMACRO6 "Next time, scumbag..." #define HUSTR_CHATMACRO7 "Come here!" #define HUSTR_CHATMACRO8 "I'll take care of it." #define HUSTR_CHATMACRO9 "Yes" #define HUSTR_CHATMACRO0 "No" #define HUSTR_TALKTOSELF1 "You mumble to yourself" #define HUSTR_TALKTOSELF2 "Who's there?" #define HUSTR_TALKTOSELF3 "You scare yourself" #define HUSTR_TALKTOSELF4 "You start to rave" #define HUSTR_TALKTOSELF5 "You've lost it..." #define HUSTR_MESSAGESENT "[Message Sent]" // The following should NOT be changed unless it seems // just AWFULLY necessary #define HUSTR_PLRGREEN "Green: " #define HUSTR_PLRINDIGO "Indigo: " #define HUSTR_PLRBROWN "Brown: " #define HUSTR_PLRRED "Red: " #define HUSTR_KEYGREEN 'g' #define HUSTR_KEYINDIGO 'i' #define HUSTR_KEYBROWN 'b' #define HUSTR_KEYRED 'r' // // AM_map.C // #define AMSTR_FOLLOWON "Follow Mode ON" #define AMSTR_FOLLOWOFF "Follow Mode OFF" #define AMSTR_GRIDON "Grid ON" #define AMSTR_GRIDOFF "Grid OFF" #define AMSTR_MARKEDSPOT "Marked Spot" #define AMSTR_MARKSCLEARED "All Marks Cleared" // // ST_stuff.C // #define STSTR_MUS "Music Change" #define STSTR_NOMUS "IMPOSSIBLE SELECTION" #define STSTR_DQDON "Degreelessness Mode On" #define STSTR_DQDOFF "Degreelessness Mode Off" #define STSTR_KFAADDED "Very Happy Ammo Added" #define STSTR_FAADDED "Ammo (no keys) Added" #define STSTR_NCON "No Clipping Mode ON" #define STSTR_NCOFF "No Clipping Mode OFF" #define STSTR_BEHOLD "inVuln, Str, Inviso, Rad, Allmap, or Lite-amp" #define STSTR_BEHOLDX "Power-up Toggled" #define STSTR_CHOPPERS "... doesn't suck - GM" #define STSTR_CLEV "Changing Level..." // // F_Finale.C // #define E1TEXT "Once you beat the big badasses and\n"\ "clean out the moon base you're supposed\n"\ "to win, aren't you? Aren't you? Where's\n"\ "your fat reward and ticket home? What\n"\ "the hell is this? It's not supposed to\n"\ "end this way!\n"\ "\n" \ "It stinks like rotten meat, but looks\n"\ "like the lost Deimos base. Looks like\n"\ "you're stuck on The Shores of Hell.\n"\ "The only way out is through.\n"\ "\n"\ "To continue the DOOM experience, play\n"\ "The Shores of Hell and its amazing\n"\ "sequel, Inferno!\n" #define E2TEXT "You've done it! The hideous cyber-\n"\ "demon lord that ruled the lost Deimos\n"\ "moon base has been slain and you\n"\ "are triumphant! But ... where are\n"\ "you? You clamber to the edge of the\n"\ "moon and look down to see the awful\n"\ "truth.\n" \ "\n"\ "Deimos floats above Hell itself!\n"\ "You've never heard of anyone escaping\n"\ "from Hell, but you'll make the bastards\n"\ "sorry they ever heard of you! Quickly,\n"\ "you rappel down to the surface of\n"\ "Hell.\n"\ "\n" \ "Now, it's on to the final chapter of\n"\ "DOOM! -- Inferno." #define E3TEXT "The loathsome spiderdemon that\n"\ "masterminded the invasion of the moon\n"\ "bases and caused so much death has had\n"\ "its ass kicked for all time.\n"\ "\n"\ "A hidden doorway opens and you enter.\n"\ "You've proven too tough for Hell to\n"\ "contain, and now Hell at last plays\n"\ "fair -- for you emerge from the door\n"\ "to see the green fields of Earth!\n"\ "Home at last.\n" \ "\n"\ "You wonder what's been happening on\n"\ "Earth while you were battling evil\n"\ "unleashed. It's good that no Hell-\n"\ "spawn could have come through that\n"\ "door with you ..." // after level 6, put this: #define C1TEXT "YOU HAVE ENTERED DEEPLY INTO THE INFESTED\n" \ "STARPORT. BUT SOMETHING IS WRONG. THE\n" \ "MONSTERS HAVE BROUGHT THEIR OWN REALITY\n" \ "WITH THEM, AND THE STARPORT'S TECHNOLOGY\n" \ "IS BEING SUBVERTED BY THEIR PRESENCE.\n" \ "\n"\ "AHEAD, YOU SEE AN OUTPOST OF HELL, A\n" \ "FORTIFIED ZONE. IF YOU CAN GET PAST IT,\n" \ "YOU CAN PENETRATE INTO THE HAUNTED HEART\n" \ "OF THE STARBASE AND FIND THE CONTROLLING\n" \ "SWITCH WHICH HOLDS EARTH'S POPULATION\n" \ "HOSTAGE." // After level 11, put this: #define C2TEXT "YOU HAVE WON! YOUR VICTORY HAS ENABLED\n" \ "HUMANKIND TO EVACUATE EARTH AND ESCAPE\n"\ "THE NIGHTMARE. NOW YOU ARE THE ONLY\n"\ "HUMAN LEFT ON THE FACE OF THE PLANET.\n"\ "CANNIBAL MUTATIONS, CARNIVOROUS ALIENS,\n"\ "AND EVIL SPIRITS ARE YOUR ONLY NEIGHBORS.\n"\ "YOU SIT BACK AND WAIT FOR DEATH, CONTENT\n"\ "THAT YOU HAVE SAVED YOUR SPECIES.\n"\ "\n"\ "BUT THEN, EARTH CONTROL BEAMS DOWN A\n"\ "MESSAGE FROM SPACE: \"SENSORS HAVE LOCATED\n"\ "THE SOURCE OF THE ALIEN INVASION. IF YOU\n"\ "GO THERE, YOU MAY BE ABLE TO BLOCK THEIR\n"\ "ENTRY. THE ALIEN BASE IS IN THE HEART OF\n"\ "YOUR OWN HOME CITY, NOT FAR FROM THE\n"\ "STARPORT.\" SLOWLY AND PAINFULLY YOU GET\n"\ "UP AND RETURN TO THE FRAY." // After level 20, put this: #define C3TEXT "YOU ARE AT THE CORRUPT HEART OF THE CITY,\n"\ "SURROUNDED BY THE CORPSES OF YOUR ENEMIES.\n"\ "YOU SEE NO WAY TO DESTROY THE CREATURES'\n"\ "ENTRYWAY ON THIS SIDE, SO YOU CLENCH YOUR\n"\ "TEETH AND PLUNGE THROUGH IT.\n"\ "\n"\ "THERE MUST BE A WAY TO CLOSE IT ON THE\n"\ "OTHER SIDE. WHAT DO YOU CARE IF YOU'VE\n"\ "GOT TO GO THROUGH HELL TO GET TO IT?" // After level 29, put this: #define C4TEXT "THE HORRENDOUS VISAGE OF THE BIGGEST\n"\ "DEMON YOU'VE EVER SEEN CRUMBLES BEFORE\n"\ "YOU, AFTER YOU PUMP YOUR ROCKETS INTO\n"\ "HIS EXPOSED BRAIN. THE MONSTER SHRIVELS\n"\ "UP AND DIES, ITS THRASHING LIMBS\n"\ "DEVASTATING UNTOLD MILES OF HELL'S\n"\ "SURFACE.\n"\ "\n"\ "YOU'VE DONE IT. THE INVASION IS OVER.\n"\ "EARTH IS SAVED. HELL IS A WRECK. YOU\n"\ "WONDER WHERE BAD FOLKS WILL GO WHEN THEY\n"\ "DIE, NOW. WIPING THE SWEAT FROM YOUR\n"\ "FOREHEAD YOU BEGIN THE LONG TREK BACK\n"\ "HOME. REBUILDING EARTH OUGHT TO BE A\n"\ "LOT MORE FUN THAN RUINING IT WAS.\n" // Before level 31, put this: #define C5TEXT "CONGRATULATIONS, YOU'VE FOUND THE SECRET\n"\ "LEVEL! LOOKS LIKE IT'S BEEN BUILT BY\n"\ "HUMANS, RATHER THAN DEMONS. YOU WONDER\n"\ "WHO THE INMATES OF THIS CORNER OF HELL\n"\ "WILL BE." // Before level 32, put this: #define C6TEXT "CONGRATULATIONS, YOU'VE FOUND THE\n"\ "SUPER SECRET LEVEL! YOU'D BETTER\n"\ "BLAZE THROUGH THIS ONE!\n" // // Character cast strings F_FINALE.C // #define CC_ZOMBIE "ZOMBIEMAN" #define CC_SHOTGUN "SHOTGUN GUY" #define CC_HEAVY "HEAVY WEAPON DUDE" #define CC_IMP "IMP" #define CC_DEMON "DEMON" #define CC_LOST "LOST SOUL" #define CC_CACO "CACODEMON" #define CC_HELL "HELL KNIGHT" #define CC_BARON "BARON OF HELL" #define CC_ARACH "ARACHNOTRON" #define CC_PAIN "PAIN ELEMENTAL" #define CC_REVEN "REVENANT" #define CC_MANCU "MANCUBUS" #define CC_ARCH "ARCH-VILE" #define CC_SPIDER "THE SPIDER MASTERMIND" #define CC_CYBER "THE CYBERDEMON" #define CC_HERO "OUR HERO" \ No newline at end of file diff --git a/DUTILS.C b/DUTILS.C new file mode 100644 index 0000000..fb031d8 --- /dev/null +++ b/DUTILS.C @@ -0,0 +1 @@ +// // Dave's utilities including doubly-linked lists & simple state machines. // #include "dutils.h" #include "doomdef.h" // extern byte screens[][SCREENWIDTH*SCREENHEIGHT]; // // DOUBLY-LINKED LIST PACKAGE // dllist_t *dll_NewList(void) { dllist_t *rc; rc = (dllist_t *) Z_Malloc(sizeof(dllist_t), PU_STATIC, 0); rc->head = rc->tail = 0; return rc; } dlnode_t *dll_AddEndNode(dllist_t *list, void *data) { dlnode_t *rc; if (!list) I_Error("Bad list in dll_AddEndNode"); // DEBUG rc = (dlnode_t *) Z_Malloc(sizeof(dlnode_t), PU_STATIC, 0); rc->data = data; rc->next = 0; rc->prev = list->tail; if (list->tail) { list->tail->next = rc; list->tail = rc; } else list->tail = list->head = rc; return rc; } dlnode_t *dll_AddStartNode(dllist_t *list, void *data) { dlnode_t *rc; if (!list) I_Error("Bad list in dll_AddStartNode"); // DEBUG rc = (dlnode_t *) Z_Malloc(sizeof(dlnode_t), PU_STATIC, 0); rc->data = data; rc->next = list->head; rc->prev = 0; if (list->head) list->head->prev = rc; else list->tail = rc; list->head = rc; return rc; } void *dll_DelNode(dllist_t *list, dlnode_t *node) { void *rc; if (!list) // DEBUG I_Error("Bad list in dll_DelNode"); // DEBUG if (!list->head) // DEBUG I_Error("Empty list in dll_DelNode"); // DEBUG rc = node->data; if (node->prev) node->prev->next = node->next; if (node->next) node->next->prev = node->prev; if (node == list->head) list->head = node->next; if (node == list->tail) list->tail = node->prev; Z_Free(node); return rc; } void *dll_DelEndNode(dllist_t *list) { return dll_DelNode(list, list->tail); } void *dll_DelStartNode(dllist_t *list) { return dll_DelNode(list, list->head); } // // CHEAT SEQUENCE PACKAGE // static int firsttime = 1; static unsigned char cheat_xlate_table[256]; // // Returns a 1 if the cheat was successful, 0 if failed. // int cht_CheckCheat(cheatseq_t *cht, char key) { int i; int rc = 0; if (firsttime) { firsttime = 0; for (i=0;i<256;i++) cheat_xlate_table[i] = SCRAMBLE(i); } if (!cht->p) cht->p = cht->sequence; // initialize if first time if (*cht->p == 0) *(cht->p++) = key; else if (cheat_xlate_table[(unsigned char)key] == *cht->p) cht->p++; else cht->p = cht->sequence; if (*cht->p == 1) cht->p++; else if (*cht->p == 0xff) // end of sequence character { cht->p = cht->sequence; rc = 1; } return rc; } void cht_GetParam(cheatseq_t *cht, char *buffer) { unsigned char *p, c; p = cht->sequence; while (*(p++) != 1); do { c = *p; *(buffer++) = c; *(p++) = 0; } while (c && *p!=0xff ); if (*p==0xff) *buffer = 0; } // // SCREEN WIPE PACKAGE // static boolean go = 0; // when zero, stop the wipe static byte *wipe_scr_start, *wipe_scr_end, *wipe_scr; void wipe_shittyColMajorXform(short *array, int width, int height) { int x, y; short *dest; dest = (short *) Z_Malloc(width*height*2, PU_STATIC, 0); for(y=0;y *e) { newval = *w - ticks; if (newval < *e) *w = *e; else *w = newval; changed = true; } else if (*w < *e) { newval = *w + ticks; if (newval > *e) *w = *e; else *w = newval; changed = true; } } w++; e++; } return !changed; } int wipe_exitColorXForm(int width, int height, int ticks) { return 0; } static int *y; int wipe_initMelt(int width, int height, int ticks) { int i, r; // // copy start screen to main screen // memcpy(wipe_scr, wipe_scr_start, width*height); // // makes this wipe faster (in theory) to have stuff in column-major format // wipe_shittyColMajorXform((short*)wipe_scr_start, width/2, height); wipe_shittyColMajorXform((short*)wipe_scr_end, width/2, height); // // setup initial column positions (y<0 => not ready to scroll yet) // y = (int *) Z_Malloc(width*sizeof(int), PU_STATIC, 0); y[0] = -(M_Random()%16); for (i=1;i 0) y[i] = 0; else if (y[i] == -16) y[i] = -15; } return 0; } int wipe_doMelt(int width, int height, int ticks) { int i, j, dy, idx; short *s, *d; boolean done = true; width/=2; while (ticks--) { for (i=0;i= height) dy = height - y[i]; s = &((short *)wipe_scr_end)[i*height+y[i]]; d = &((short *)wipe_scr)[y[i]*width+i]; idx = 0; for (j=dy;j;j--) { d[idx] = *(s++); idx += width; } y[i] += dy; s = &((short *)wipe_scr_start)[i*height]; d = &((short *)wipe_scr)[y[i]*width+i]; idx = 0; for (j=height-y[i];j;j--) { d[idx] = *(s++); idx += width; } done = false; } } } return done; } int wipe_exitMelt(int width, int height, int ticks) { Z_Free(y); return 0; } int wipe_StartScreen(int x, int y, int width, int height) { wipe_scr_start = screens[2]; I_ReadScreen(wipe_scr_start); return 0; } int wipe_EndScreen(int x, int y, int width, int height) { wipe_scr_end = screens[3]; I_ReadScreen(wipe_scr_end); V_DrawBlock(x, y, 0, width, height, wipe_scr_start); // restore start scr. return 0; } int wipe_ScreenWipe(int wipeno, int x, int y, int width, int height, int ticks) { int rc; static int (*wipes[])(int, int, int) = { wipe_initColorXForm, wipe_doColorXForm, wipe_exitColorXForm, wipe_initMelt, wipe_doMelt, wipe_exitMelt }; void V_MarkRect(int, int, int, int); // initial stuff if (!go) { go = 1; // wipe_scr = (byte *) Z_Malloc(width*height, PU_STATIC, 0); // DEBUG wipe_scr = screens[0]; (*wipes[wipeno*3])(width, height, ticks); } // do a piece of wipe-in V_MarkRect(0, 0, width, height); rc = (*wipes[wipeno*3+1])(width, height, ticks); // V_DrawBlock(x, y, 0, width, height, wipe_scr); // DEBUG // final stuff if (rc) { go = 0; (*wipes[wipeno*3+2])(width, height, ticks); } return !go; } \ No newline at end of file diff --git a/DUTILS.H b/DUTILS.H new file mode 100644 index 0000000..41eb630 --- /dev/null +++ b/DUTILS.H @@ -0,0 +1 @@ +// // Dave's utilities including doubly-linked lists & simple state machines. // #ifndef __DLLIST_H__ #define __DLLIST_H__ #define RANGECHECKING // // RANGE-CHECKING PACAKGE // #ifdef RANGECHECKING // Does an inclusive range check of var. #define RNGCHECK(var, a, b) if ((var)<(a) || (var)>(b)) \ I_Error("%s=%d in %s:%d", #var, var, __FILE__, __LINE__) // Does a null-check and negative-check on pointer. #define PTRCHECK(ptr) if (!(ptr) || ((int)(ptr) < 0)) \ I_Error("%s=0x%lx in %s:%d", #ptr, (unsigned int)(ptr), __FILE__, __LINE__) #endif // // DOUBLY-LINKED LIST PACKAGE // typedef struct dlnode_struct dlnode_t; struct dlnode_struct { void *data; dlnode_t *prev, *next; }; typedef struct { dlnode_t *head; dlnode_t *tail; } dllist_t; dllist_t *dll_NewList(void); dlnode_t *dll_AddEndNode(dllist_t *list, void *data); dlnode_t *dll_AddStartNode(dllist_t *list, void *data); void *dll_DelNode(dllist_t *list, dlnode_t *node); void *dll_DelEndNode(dllist_t *list); void *dll_DelStartNode(dllist_t *list); // // CHEAT SEQUENCE PACKAGE // #define SCRAMBLE(a) \ ((((a)&1)<<7) + (((a)&2)<<5) + ((a)&4) + (((a)&8)<<1) \ + (((a)&16)>>1) + ((a)&32) + (((a)&64)>>5) + (((a)&128)>>7)) typedef struct { unsigned char *sequence; unsigned char *p; } cheatseq_t; int cht_CheckCheat(cheatseq_t *cht, char key); void cht_GetParam(cheatseq_t *cht, char *buffer); // // SCREEN WIPE PACKAGE // enum { wipe_ColorXForm, // simple gradual pixel change for 8-bit only wipe_Melt, // weird screen melt wipe_NUMWIPES }; int wipe_StartScreen(int x, int y, int width, int height); int wipe_EndScreen(int x, int y, int width, int height); int wipe_ScreenWipe(int wipeno, int x, int y, int width, int height, int ticks); #endif \ No newline at end of file diff --git a/D_FRENCH.H b/D_FRENCH.H new file mode 100644 index 0000000..f5024a8 --- /dev/null +++ b/D_FRENCH.H @@ -0,0 +1 @@ +// // Printed strings for translation // // // D_Main.C // #define D_DEVSTR "MODE DEVELOPPEMENT ON.\n" #define D_CDROM "VERSION CD-ROM: DEFAULT.CFG DANS C:\\DOOMDATA\n" // // M_Menu.C // #define PRESSKEY "APPUYEZ SUR UNE TOUCHE." #define PRESSYN "APPUYEZ SUR Y OU N" #define QUITMSG "VOUS VOULEZ VRAIMENT\nQUITTER CE SUPER JEU?" #define LOADNET "VOUS NE POUVEZ PAS CHARGER\nUN JEU EN RESEAU!\n\n"PRESSKEY #define QLOADNET "CHARGEMENT RAPIDE INTERDIT EN RESEAU!\n\n"PRESSKEY #define QSAVESPOT "VOUS N'AVEZ PAS CHOISI UN EMPLACEMENT!\n\n"PRESSKEY #define SAVEDEAD "VOUS NE POUVEZ PAS SAUVER SI VOUS NE JOUEZ "\ "PAS!\n\n"PRESSKEY #define QSPROMPT "SAUVEGARDE RAPIDE DANS LE FICHIER \n\n'%s'?\n\n"PRESSYN #define QLPROMPT "VOULEZ-VOUS CHARGER LA SAUVEGARDE"\ "\n\n'%s'?\n\n"PRESSYN #define NEWGAME "VOUS NE POUVEZ PAS LANCER\n"\ "UN NOUVEAU JEU SUR RESEAU.\n\n"PRESSKEY #define NIGHTMARE "VOUS CONFIRMEZ? CE NIVEAU EST\n"\ "VRAIMENT IMPITOYABLE!n"PRESSYN #define SWSTRING "CECI EST UNE VERSION SHAREWARE DE DOOM.\n\n"\ "VOUS DEVRIEZ COMMANDER LA TRILOGIE COMPLETE.\n\n"PRESSKEY #define MSGOFF "MESSAGES OFF" #define MSGON "MESSAGES ON" #define NETEND "VOUS NE POUVEZ PAS METTRE FIN A UN JEU SUR "\ "RESEAU!\n\n"PRESSKEY #define ENDGAME "VOUS VOULEZ VRAIMENT METTRE FIN AU JEU?\n\n"PRESSYN #ifdef __WATCOMC__ #define DOSY "(APPUYEZ SUR Y POUR REVENIR AU DOS.)" #else #define DOSY "(press y to quit)" #endif #define DETAILHI "GRAPHISMES MAXIMUM " #define DETAILLO "GRAPHISMES MINIMUM " #define GAMMALVL0 "CORRECTION GAMMA OFF" #define GAMMALVL1 "CORRECTION GAMMA NIVEAU 1" #define GAMMALVL2 "CORRECTION GAMMA NIVEAU 2" #define GAMMALVL3 "CORRECTION GAMMA NIVEAU 3" #define GAMMALVL4 "CORRECTION GAMMA NIVEAU 4" #define EMPTYSTRING "EMPLACEMENT VIDE" // // P_inter.C // #define GOTARMOR "ARMURE RECUPEREE." #define GOTMEGA "MEGA-ARMURE RECUPEREE!" #define GOTHTHBONUS "BONUS DE SANTE RECUPERE." #define GOTARMBONUS "BONUS D'ARMURE RECUPERE." #define GOTSTIM "STIMPACK RECUPERE." #define GOTMEDINEED "MEDIKIT RECUPERE. VOUS EN AVEZ VRAIMENT BESOIN!" #define GOTMEDIKIT "MEDIKIT RECUPERE." #define GOTSUPER "SUPERCHARGE!" #define GOTBLUECARD "CARTE MAGNETIQUE BLEUE RECUPEREE." #define GOTYELWCARD "CARTE MAGNETIQUE JAUNE RECUPEREE." #define GOTREDCARD "CARTE MAGNETIQUE ROUGE RECUPEREE." #define GOTBLUESKUL "CLEF CRANE BLEUE RECUPEREE." #define GOTYELWSKUL "CLEF CRANE JAUNE RECUPEREE." #define GOTREDSKULL "CLEF CRANE ROUGE RECUPEREE." #define GOTINVUL "INVULNERABILITE!" #define GOTBERSERK "BERSERK!" #define GOTINVIS "INVISIBILITE PARTIELLE " #define GOTSUIT "COMBINAISON ANTI-RADIATIONS " #define GOTMAP "CARTE INFORMATIQUE " #define GOTVISOR "VISEUR A AMPLIFICATION DE LUMIERE " #define GOTMSPHERE "MEGASPHERE!" #define GOTCLIP "CHARGEUR RECUPERE." #define GOTCLIPBOX "BOITE DE BALLES RECUPEREE." #define GOTROCKET "ROQUETTE RECUPEREE." #define GOTROCKBOX "CAISSE DE ROQUETTES RECUPEREE." #define GOTCELL "CELLULE D'ENERGIE RECUPEREE." #define GOTCELLBOX "PACK DE CELLULES D'ENERGIE RECUPERE." #define GOTSHELLS "4 CARTOUCHES RECUPEREES." #define GOTSHELLBOX "BOITE DE CARTOUCHES RECUPEREE." #define GOTBACKPACK "SAC PLEIN DE MUNITIONS RECUPERE!" #define GOTBFG9000 "VOUS AVEZ UN BFG9000! OH, OUI!" #define GOTCHAINGUN "VOUS AVEZ LA MITRAILLEUSE!" #define GOTCHAINSAW "UNE TRONCONNEUSE!" #define GOTLAUNCHER "VOUS AVEZ UN LANCE-ROQUETTES!" #define GOTPLASMA "VOUS AVEZ UN FUSIL A PLASMA!" #define GOTSHOTGUN "VOUS AVEZ UN FUSIL!" #define GOTSHOTGUN2 "VOUS AVEZ UN SUPER FUSIL!" // // P_Doors.C // #define PD_BLUEO "IL VOUS FAUT UNE CLEF BLEUE" #define PD_REDO "IL VOUS FAUT UNE CLEF ROUGE" #define PD_YELLOWO "IL VOUS FAUT UNE CLEF JAUNE" #define PD_BLUEK PD_BLUEO #define PD_REDK PD_REDO #define PD_YELLOWK PD_YELLOWO // // G_game.C // #define GGSAVED "JEU SAUVEGARDE." // // HU_stuff.C // #define HUSTR_MSGU "[MESSAGE NON ENVOYE]" #define HUSTR_E1M1 "E1M1: HANGAR" #define HUSTR_E1M2 "E1M2: USINE NUCLEAIRE " #define HUSTR_E1M3 "E1M3: RAFFINERIE DE TOXINES " #define HUSTR_E1M4 "E1M4: CENTRE DE CONTROLE " #define HUSTR_E1M5 "E1M5: LABORATOIRE PHOBOS " #define HUSTR_E1M6 "E1M6: TRAITEMENT CENTRAL " #define HUSTR_E1M7 "E1M7: CENTRE INFORMATIQUE " #define HUSTR_E1M8 "E1M8: ANOMALIE PHOBOS " #define HUSTR_E1M9 "E1M9: BASE MILITAIRE " #define HUSTR_E2M1 "E2M1: ANOMALIE DEIMOS " #define HUSTR_E2M2 "E2M2: ZONE DE CONFINEMENT " #define HUSTR_E2M3 "E2M3: RAFFINERIE" #define HUSTR_E2M4 "E2M4: LABORATOIRE DEIMOS " #define HUSTR_E2M5 "E2M5: CENTRE DE CONTROLE " #define HUSTR_E2M6 "E2M6: HALLS DES DAMNES " #define HUSTR_E2M7 "E2M7: CUVES DE REPRODUCTION " #define HUSTR_E2M8 "E2M8: TOUR DE BABEL " #define HUSTR_E2M9 "E2M9: FORTERESSE DU MYSTERE " #define HUSTR_E3M1 "E3M1: DONJON DE L'ENFER " #define HUSTR_E3M2 "E3M2: BOURBIER DU DESESPOIR " #define HUSTR_E3M3 "E3M3: PANDEMONIUM" #define HUSTR_E3M4 "E3M4: MAISON DE LA DOULEUR " #define HUSTR_E3M5 "E3M5: CATHEDRALE PROFANE " #define HUSTR_E3M6 "E3M6: MONT EREBUS" #define HUSTR_E3M7 "E3M7: LIMBES" #define HUSTR_E3M8 "E3M8: DIS" #define HUSTR_E3M9 "E3M9: CLAPIERS" #define HUSTR_1 "NIVEAU 1: ENTREE " #define HUSTR_2 "NIVEAU 2: HALLS SOUTERRAINS " #define HUSTR_3 "NIVEAU 3: LE FEU NOURRI " #define HUSTR_4 "NIVEAU 4: LE FOYER " #define HUSTR_5 "NIVEAU 5: LES EGOUTS " #define HUSTR_6 "NIVEAU 6: LE BROYEUR " #define HUSTR_7 "NIVEAU 7: L'HERBE DE LA MORT" #define HUSTR_8 "NIVEAU 8: RUSES ET PIEGES " #define HUSTR_9 "NIVEAU 9: LE PUITS " #define HUSTR_10 "NIVEAU 10: BASE DE RAVITAILLEMENT " #define HUSTR_11 "NIVEAU 11: LE CERCLE DE LA MORT!" #define HUSTR_12 "NIVEAU 12: L'USINE " #define HUSTR_13 "NIVEAU 13: LE CENTRE VILLE" #define HUSTR_14 "NIVEAU 14: LES ANTRES PROFONDES " #define HUSTR_15 "NIVEAU 15: LA ZONE INDUSTRIELLE " #define HUSTR_16 "NIVEAU 16: LA BANLIEUE" #define HUSTR_17 "NIVEAU 17: LES IMMEUBLES" #define HUSTR_18 "NIVEAU 18: LA COUR " #define HUSTR_19 "NIVEAU 19: LA CITADELLE " #define HUSTR_20 "NIVEAU 20: JE T'AI EU!" #define HUSTR_21 "NIVEAU 21: LE NIRVANA" #define HUSTR_22 "NIVEAU 22: LES CATACOMBES " #define HUSTR_23 "NIVEAU 23: LA GRANDE FETE " #define HUSTR_24 "NIVEAU 24: LE GOUFFRE " #define HUSTR_25 "NIVEAU 25: LES CHUTES DE SANG" #define HUSTR_26 "NIVEAU 26: LES MINES ABANDONNEES " #define HUSTR_27 "NIVEAU 27: CHEZ LES MONSTRES " #define HUSTR_28 "NIVEAU 28: LE MONDE DE L'ESPRIT " #define HUSTR_29 "NIVEAU 29: LA LIMITE " #define HUSTR_30 "NIVEAU 30: L'ICONE DU PECHE " #define HUSTR_31 "NIVEAU 31: WOLFENSTEIN" #define HUSTR_32 "NIVEAU 32: LE MASSACRE" #define HUSTR_CHATMACRO1 "JE SUIS PRET A LEUR EN FAIRE BAVER!" #define HUSTR_CHATMACRO2 "JE VAIS BIEN." #define HUSTR_CHATMACRO3 "JE N'AI PAS L'AIR EN FORME!" #define HUSTR_CHATMACRO4 "AU SECOURS!" #define HUSTR_CHATMACRO5 "TU CRAINS!" #define HUSTR_CHATMACRO6 "LA PROCHAINE FOIS, MINABLE..." #define HUSTR_CHATMACRO7 "VIENS ICI!" #define HUSTR_CHATMACRO8 "JE VAIS M'EN OCCUPER." #define HUSTR_CHATMACRO9 "OUI" #define HUSTR_CHATMACRO0 "NON" #define HUSTR_TALKTOSELF1 "VOUS PARLEZ TOUT SEUL " #define HUSTR_TALKTOSELF2 "QUI EST LA?" #define HUSTR_TALKTOSELF3 "VOUS VOUS FAITES PEUR " #define HUSTR_TALKTOSELF4 "VOUS COMMENCEZ A DELIRER " #define HUSTR_TALKTOSELF5 "VOUS ETES LARGUE..." #define HUSTR_MESSAGESENT "[MESSAGE ENVOYE]" // The following should NOT be changed unless it seems // just AWFULLY necessary #define HUSTR_PLRGREEN "VERT: " #define HUSTR_PLRINDIGO "INDIGO: " #define HUSTR_PLRBROWN "BRUN: " #define HUSTR_PLRRED "ROUGE: " #define HUSTR_KEYGREEN 'g' // french key should be "V" #define HUSTR_KEYINDIGO 'i' #define HUSTR_KEYBROWN 'b' #define HUSTR_KEYRED 'r' // // AM_map.C // #define AMSTR_FOLLOWON "MODE POURSUITE ON" #define AMSTR_FOLLOWOFF "MODE POURSUITE OFF" #define AMSTR_GRIDON "GRILLE ON" #define AMSTR_GRIDOFF "GRILLE OFF" #define AMSTR_MARKEDSPOT "REPERE MARQUE " #define AMSTR_MARKSCLEARED "REPERES EFFACES " // // ST_stuff.C // #define STSTR_MUS "CHANGEMENT DE MUSIQUE " #define STSTR_NOMUS "IMPOSSIBLE SELECTION" #define STSTR_DQDON "INVULNERABILITE ON " #define STSTR_DQDOFF "INVULNERABILITE OFF" #define STSTR_KFAADDED "ARMEMENT MAXIMUM! " #define STSTR_FAADDED "ARMES (SAUF CLEFS) AJOUTEES" #define STSTR_NCON "BARRIERES ON" #define STSTR_NCOFF "BARRIERES OFF" #define STSTR_BEHOLD " inVuln, Str, Inviso, Rad, Allmap, or Lite-amp" #define STSTR_BEHOLDX "AMELIORATION ACTIVEE" #define STSTR_CHOPPERS "... DOESN'T SUCK - GM" #define STSTR_CLEV "CHANGEMENT DE NIVEAU..." // // F_Finale.C // #define E1TEXT "APRES AVOIR VAINCU LES GROS MECHANTS\n"\ "ET NETTOYE LA BASE LUNAIRE, VOUS AVEZ\n"\ "GAGNE, NON? PAS VRAI? OU EST DONC VOTRE\n"\ " RECOMPENSE ET VOTRE BILLET DE\n"\ "RETOUR? QU'EST-QUE CA VEUT DIRE?CE"\ "N'EST PAS LA FIN ESPEREE!\n"\ "\n" \ "CA SENT LA VIANDE PUTREFIEE, MAIS\n"\ "ON DIRAIT LA BASE DEIMOS. VOUS ETES\n"\ "APPAREMMENT BLOQUE AUX PORTES DE L'ENFER.\n"\ "LA SEULE ISSUE EST DE L'AUTRE COTE.\n"\ "\n"\ "POUR VIVRE LA SUITE DE DOOM, JOUEZ\n"\ "A 'AUX PORTES DE L'ENFER' ET A\n"\ "L'EPISODE SUIVANT, 'L'ENFER'!\n" #define E2TEXT "VOUS AVEZ REUSSI. L'INFAME DEMON\n"\ "QUI CONTROLAIT LA BASE LUNAIRE DE\n"\ "DEIMOS EST MORT, ET VOUS AVEZ\n"\ "TRIOMPHE! MAIS... OU ETES-VOUS?\n"\ "VOUS GRIMPEZ JUSQU'AU BORD DE LA\n"\ "LUNE ET VOUS DECOUVREZ L'ATROCE\n"\ "VERITE.\n" \ "\n"\ "DEIMOS EST AU-DESSUS DE L'ENFER!\n"\ "VOUS SAVEZ QUE PERSONNE NE S'EN\n"\ "EST JAMAIS ECHAPPE, MAIS CES FUMIERS\n"\ "VONT REGRETTER DE VOUS AVOIR CONNU!\n"\ "VOUS REDESCENDEZ RAPIDEMENT VERS\n"\ "LA SURFACE DE L'ENFER.\n"\ "\n" \ "VOICI MAINTENANT LE CHAPITRE FINAL DE\n"\ "DOOM! -- L'ENFER." #define E3TEXT "LE DEMON ARACHNEEN ET REPUGNANT\n"\ "QUI A DIRIGE L'INVASION DES BASES\n"\ "LUNAIRES ET SEME LA MORT VIENT DE SE\n"\ "FAIRE PULVERISER UNE FOIS POUR TOUTES.\n"\ "\n"\ "UNE PORTE SECRETE S'OUVRE. VOUS ENTREZ.\n"\ "VOUS AVEZ PROUVE QUE VOUS POUVIEZ\n"\ "RESISTER AUX HORREURS DE L'ENFER.\n"\ "IL SAIT ETRE BEAU JOUEUR, ET LORSQUE\n"\ "VOUS SORTEZ, VOUS REVOYEZ LES VERTES\n"\ "PRAIRIES DE LA TERRE, VOTRE PLANETE.\n"\ "\n"\ "VOUS VOUS DEMANDEZ CE QUI S'EST PASSE\n"\ "SUR TERRE PENDANT QUE VOUS AVEZ\n"\ "COMBATTU LE DEMON. HEUREUSEMENT,\n"\ "AUCUN GERME DU MAL N'A FRANCHI\n"\ "CETTE PORTE AVEC VOUS..." // after level 6, put this: #define C1TEXT "VOUS ETES AU PLUS PROFOND DE L'ASTROPORT\n" \ "INFESTE DE MONSTRES, MAIS QUELQUE CHOSE\n" \ "NE VA PAS. ILS ONT APPORTE LEUR PROPRE\n" \ "REALITE, ET LA TECHNOLOGIE DE L'ASTROPORT\n" \ "EST AFFECTEE PAR LEUR PRESENCE.\n" \ "\n"\ "DEVANT VOUS, VOUS VOYEZ UN POSTE AVANCE\n" \ "DE L'ENFER, UNE ZONE FORTIFIEE. SI VOUS\n" \ "POUVEZ PASSER, VOUS POURREZ PENETRER AU\n" \ "COEUR DE LA BASE HANTEE ET TROUVER \n" \ "L'INTERRUPTEUR DE CONTROLE QUI GARDE LA \n" \ "POPULATION DE LA TERRE EN OTAGE." // After level 11, put this: #define C2TEXT "VOUS AVEZ GAGNE! VOTRE VICTOIRE A PERMIS\n" \ "A L'HUMANITE D'EVACUER LA TERRE ET \n"\ "D'ECHAPPER AU CAUCHEMAR. VOUS ETES \n"\ "MAINTENANT LE DERNIER HUMAIN A LA SURFACE \n"\ "DE LA PLANETE. VOUS ETES ENTOURE DE \n"\ "MUTANTS CANNIBALES, D'EXTRATERRESTRES \n"\ "CARNIVORES ET D'ESPRITS DU MAL. VOUS \n"\ "ATTENDEZ CALMEMENT LA MORT, HEUREUX \n"\ "D'AVOIR PU SAUVER VOTRE RACE.\n"\ "MAIS UN MESSAGE VOUS PARVIENT SOUDAIN\n"\ "DE L'ESPACE: \"NOS CAPTEURS ONT LOCALISE\n"\ "LA SOURCE DE L'INVASION EXTRATERRESTRE.\n"\ "SI VOUS Y ALLEZ, VOUS POURREZ PEUT-ETRE\n"\ "LES ARRETER. LEUR BASE EST SITUEE AU COEUR\n"\ "DE VOTRE VILLE NATALE, PRES DE L'ASTROPORT.\n"\ "VOUS VOUS RELEVEZ LENTEMENT ET PENIBLEMENT\n"\ "ET VOUS REPARTEZ POUR LE FRONT." // After level 20, put this: #define C3TEXT "VOUS ETES AU COEUR DE LA CITE CORROMPUE,\n"\ "ENTOURE PAR LES CADAVRES DE VOS ENNEMIS.\n"\ "VOUS NE VOYEZ PAS COMMENT DETRUIRE LA PORTE\n"\ "DES CREATURES DE CE COTE. VOUS SERREZ\n"\ "LES DENTS ET PLONGEZ DANS L'OUVERTURE.\n"\ "\n"\ "IL DOIT Y AVOIR UN MOYEN DE LA FERMER\n"\ "DE L'AUTRE COTE. VOUS ACCEPTEZ DE\n"\ "TRAVERSER L'ENFER POUR LE FAIRE?" // After level 29, put this: #define C4TEXT "LE VISAGE HORRIBLE D'UN DEMON D'UNE\n"\ "TAILLE INCROYABLE S'EFFONDRE DEVANT\n"\ "VOUS LORSQUE VOUS TIREZ UNE SALVE DE\n"\ "ROQUETTES DANS SON CERVEAU. LE MONSTRE\n"\ "SE RATATINE, SES MEMBRES DECHIQUETES\n"\ "SE REPANDANT SUR DES CENTAINES DE\n"\ "KILOMETRES A LA SURFACE DE L'ENFER.\n"\ "\n"\ "VOUS AVEZ REUSSI. L'INVASION N'AURA.\n"\ "PAS LIEU. LA TERRE EST SAUVEE. L'ENFER\n"\ "EST ANEANTI. EN VOUS DEMANDANT OU IRONT\n"\ "MAINTENANT LES DAMNES, VOUS ESSUYEZ\n"\ "VOTRE FRONT COUVERT DE SUEUR ET REPARTEZ\n"\ "VERS LA TERRE. SA RECONSTRUCTION SERA\n"\ "BEAUCOUP PLUS DROLE QUE SA DESTRUCTION.\n" // Before level 31, put this: #define C5TEXT "FELICITATIONS! VOUS AVEZ TROUVE LE\n"\ "NIVEAU SECRET! IL SEMBLE AVOIR ETE\n"\ "CONSTRUIT PAR LES HUMAINS. VOUS VOUS\n"\ "DEMANDEZ QUELS PEUVENT ETRE LES\n"\ "HABITANTS DE CE COIN PERDU DE L'ENFER." // Before level 32, put this: #define C6TEXT "FELICITATIONS! VOUS AVEZ DECOUVERT\n"\ "LE NIVEAU SUPER SECRET! VOUS FERIEZ\n"\ "MIEUX DE FONCER DANS CELUI-LA!\n" // // Character cast strings F_FINALE.C // #define CC_ZOMBIE "ZOMBIE" #define CC_SHOTGUN "TYPE AU FUSIL" #define CC_HEAVY "MEC SUPER-ARME" #define CC_IMP "DIABLOTIN" #define CC_DEMON "DEMON" #define CC_LOST "AME PERDUE" #define CC_CACO "CACODEMON" #define CC_HELL "CHEVALIER DE L'ENFER" #define CC_BARON "BARON DE L'ENFER" #define CC_ARACH "ARACHNOTRON" #define CC_PAIN "ELEMENTAIRE DE LA DOULEUR" #define CC_REVEN "REVENANT" #define CC_MANCU "MANCUBUS" #define CC_ARCH "ARCHI-INFAME" #define CC_SPIDER "L'ARAIGNEE CERVEAU" #define CC_CYBER "LE CYBERDEMON" #define CC_HERO "NOTRE HEROS" \ No newline at end of file diff --git a/D_MAIN.C b/D_MAIN.C new file mode 100644 index 0000000..ef3da2c --- /dev/null +++ b/D_MAIN.C @@ -0,0 +1 @@ +// D_main.c #ifdef __WATCOMC__ #include #include #include #endif #ifdef __NeXT__ #include #endif #ifdef NORMALUNIX #include #include #include #endif #include "doomdef.h" #include "dutils.h" void mprintf(char *string); boolean shareware; // true if only episode 1 present boolean registered; // true if complete version boolean commercial; // true if DOOM II: Hell On Earth boolean french; boolean devparm; // started game with -devparm boolean nomonsters; // checkparm of -nomonsters boolean respawnparm; // checkparm of -respawn boolean fastparm; // checkparm of -fast boolean drone; boolean singletics = false; // debug flag to cancel adaptiveness boolean modifiedgame; // set if homebrew stuff has been added //extern int soundVolume; extern int sfxVolume; extern int musicVolume; extern boolean inhelpscreens; skill_t startskill; int startepisode, startmap; boolean autostart; FILE *debugfile; boolean advancedemo; #define MAXWADFILES 20 char wadfile[1024]; // primary wad file char mapdir[1024]; // directory of development maps char basedefault[1024]; // default file char *wadfiles[MAXWADFILES]; void D_CheckNetGame (void); void D_ProcessEvents (void); void G_BuildTiccmd (ticcmd_t *cmd); void D_DoAdvanceDemo (void); /* =============================================================================== EVENT HANDLING Events are asyncronous inputs generally generated by the game user. Events can be discarded if no responder claims them =============================================================================== */ event_t events[MAXEVENTS]; int eventhead, eventtail; /* ==================== = = D_PostEvent = = Called by the I/O functions when input is detected ==================== */ void D_PostEvent (event_t *ev) { events[eventhead] = *ev; eventhead = (++eventhead)&(MAXEVENTS-1); } /* ==================== = = D_ProcessEvents = = Send all the events of the given timestamp down the responder chain ==================== */ void D_ProcessEvents (void) { event_t *ev; // IF STORE DEMO, DON'T ACCEPT INPUT if (commercial && (W_CheckNumForName("map01")<0)) return; for ( ; eventtail != eventhead ; eventtail = (++eventtail)&(MAXEVENTS-1) ) { ev = &events[eventtail]; if (M_Responder (ev)) continue; // menu ate the event G_Responder (ev); } } //============================================================================= fixed_t FixedDiv (fixed_t a, fixed_t b) { if ( (abs(a)>>14) >= abs(b)) return (a^b)<0 ? MININT : MAXINT; return FixedDiv2 (a,b); } //============================================================================= /* ============= = = D_Display = = draw current display, possibly wiping it from the previous ============= */ // wipegamestate can be set to -1 to force a wipe on the next draw gamestate_t wipegamestate = GS_DEMOSCREEN; extern boolean setsizeneeded; extern int showMessages; void R_ExecuteSetViewSize (void); void D_Display (void) { static boolean viewactivestate = false; static boolean menuactivestate = false; static boolean inhelpscreensstate = false; static boolean fullscreen = false; static gamestate_t oldgamestate = -1; static int borderdrawcount; int nowtime, tics; int wipestart, y; boolean done, wipe, redrawsbar; if (nodrawers) return; // for comparative timing / profiling redrawsbar = false; // // change the view size if needed // if (setsizeneeded) { R_ExecuteSetViewSize (); oldgamestate = -1; // force background redraw borderdrawcount = 3; } // // save the current screen if about to wipe // if (gamestate != wipegamestate) { wipe = true; wipe_StartScreen(0, 0, SCREENWIDTH, SCREENHEIGHT); } else wipe = false; if (gamestate == GS_LEVEL && gametic) HU_Erase(); // // do buffered drawing // switch (gamestate) { case GS_LEVEL: if (!gametic) break; if (automapactive) AM_Drawer (); if (wipe || (viewheight != 200 && fullscreen) ) redrawsbar = true; if (inhelpscreensstate && !inhelpscreens) redrawsbar = true; // just put away the help screen ST_Drawer (viewheight == 200, redrawsbar ); fullscreen = viewheight == 200; break; case GS_INTERMISSION: WI_Drawer (); break; case GS_FINALE: F_Drawer (); break; case GS_DEMOSCREEN: D_PageDrawer (); break; } // // draw buffered stuff to screen // I_UpdateNoBlit (); // // draw the view directly // if (gamestate == GS_LEVEL && !automapactive && gametic) R_RenderPlayerView (&players[displayplayer]); if (gamestate == GS_LEVEL && gametic) HU_Drawer (); // // clean up border stuff // if (gamestate != oldgamestate && gamestate != GS_LEVEL) I_SetPalette (W_CacheLumpName ("PLAYPAL",PU_CACHE)); // see if the border needs to be initially drawn if (gamestate == GS_LEVEL && oldgamestate != GS_LEVEL) { viewactivestate = false; // view wasn't active R_FillBackScreen (); // draw the pattern into the back screen } // see if the border needs to be updated to the screen if (gamestate == GS_LEVEL && !automapactive && scaledviewwidth != 320) { if (menuactive || menuactivestate || !viewactivestate) borderdrawcount = 3; if (borderdrawcount) { R_DrawViewBorder (); // erase old menu stuff borderdrawcount--; } } menuactivestate = menuactive; viewactivestate = viewactive; inhelpscreensstate = inhelpscreens; oldgamestate = wipegamestate = gamestate; // // draw pause pic // if (paused) { if (automapactive) y = 4; else y = viewwindowy+4; V_DrawPatchDirect (viewwindowx+ (scaledviewwidth-68)/2,y,0 ,W_CacheLumpName ("M_PAUSE", PU_CACHE)); } // // menus go directly to the screen // M_Drawer (); // menu is drawn even on top of everything NetUpdate (); // send out any new accumulation // normal update if (!wipe) { I_FinishUpdate (); // page flip or blit buffer return; } // // wipe update // wipe_EndScreen(0, 0, SCREENWIDTH, SCREENHEIGHT); wipestart = I_GetTime () - 1; do { do { nowtime = I_GetTime (); tics = nowtime - wipestart; } while (!tics); wipestart = nowtime; done = wipe_ScreenWipe(wipe_Melt , 0, 0, SCREENWIDTH, SCREENHEIGHT, tics); I_UpdateNoBlit (); M_Drawer (); // menu is drawn even on top of wipes I_FinishUpdate (); // page flip or blit buffer } while (!done); } /* =============================================================================== = = D_DoomLoop = =============================================================================== */ extern boolean demorecording; void D_DoomLoop (void) { if (demorecording) G_BeginRecording (); if (M_CheckParm ("-debugfile")) { char filename[20]; sprintf (filename,"debug%i.txt",consoleplayer); printf ("debug output to: %s\n",filename); debugfile = fopen (filename,"w"); } I_InitGraphics (); while (1) { I_StartFrame (); // frame syncronous IO operations // // process one or more tics // if (singletics) { I_StartTic (); D_ProcessEvents (); G_BuildTiccmd (&netcmds[consoleplayer][maketic%BACKUPTICS]); if (advancedemo) D_DoAdvanceDemo (); M_Ticker (); G_Ticker (); gametic++; maketic++; } else { TryRunTics (); // will run at least one tic } S_UpdateSounds (players[consoleplayer].mo);// move positional sounds D_Display (); } } /* =============================================================================== DEMO LOOP =============================================================================== */ int demosequence; int pagetic; char *pagename; /* ================ = = D_PageTicker = = Handles timing for warped projection = ================ */ void D_PageTicker (void) { if (--pagetic < 0) D_AdvanceDemo (); } /* ================ = = D_PageDrawer = ================ */ void D_PageDrawer (void) { V_DrawPatch (0,0, 0, W_CacheLumpName(pagename, PU_CACHE)); } /* ================= = = D_AdvanceDemo = = Called after each demo or intro demosequence finishes ================= */ void D_AdvanceDemo (void) { advancedemo = true; } void D_DoAdvanceDemo (void) { players[consoleplayer].playerstate = PST_LIVE; // don't reborn advancedemo = false; usergame = false; // can't save / end game here paused = false; gameaction = ga_nothing; demosequence = (demosequence+1)%6; switch (demosequence) { case 0: if (commercial) pagetic = 35 * 11; else pagetic = 170; gamestate = GS_DEMOSCREEN; pagename = "TITLEPIC"; commercial ? S_StartMusic(mus_dm2ttl):S_StartMusic (mus_intro); break; case 1: G_DeferedPlayDemo ("demo1"); break; case 2: pagetic = 200; gamestate = GS_DEMOSCREEN; pagename = "CREDIT"; break; case 3: G_DeferedPlayDemo ("demo2"); break; case 4: gamestate = GS_DEMOSCREEN; if (commercial) { pagetic = 35 * 11; pagename = "TITLEPIC"; S_StartMusic(mus_dm2ttl); } else { pagetic = 200; pagename = "HELP2"; } break; case 5: G_DeferedPlayDemo ("demo3"); break; } } /* ================= = = D_StartTitle = ================= */ void D_StartTitle (void) { gameaction = ga_nothing; demosequence = -1; D_AdvanceDemo (); } #ifdef __WATCOMC__ //==================================================== // // Print (in color) a string // //==================================================== int getx(void) { union REGS r; r.h.ah = 3; r.h.bh = 0; int386(0x10,&r,&r); return r.h.dl; } int gety(void) { union REGS r; r.h.ah = 3; r.h.bh = 0; int386(0x10,&r,&r); return r.h.dh; } void setxy(int x,int y) { union REGS r; r.h.ah = 2; r.h.bh = 0; r.h.dh = y; r.h.dl = x; int386(0x10,&r,&r); } void dprint(char *string,int fg,int bg) { union REGS r; int i,x,y; char color; color = (bg << 4) | fg; x = getx(); y = gety(); for (i = 0; i < strlen(string); i++) { r.h.ah = 9; r.h.al = string[i]; r.h.bh = 0; r.h.bl = color; r.w.cx = 1; int386(0x10,&r,&r); x++; if (x > 79) x = 0; setxy(x,y); } } #endif // // print title for every printed line // char title[128]; void mprintf(char *string) { #ifdef __WATCOMC__ int x; int y; #endif printf(string); #ifdef __WATCOMC__ x = getx(); y = gety(); setxy(0,0); dprint (title,4,7); setxy(x,y); #endif } /* ============== = = D_AddFile = ============== */ void D_AddFile (char *file) { int numwadfiles; char *newfile; for (numwadfiles = 0 ; wadfiles[numwadfiles] ; numwadfiles++) ; newfile = malloc (strlen(file)+1); strcpy (newfile, file); wadfiles[numwadfiles] = newfile; } /* ============= = = IdentifyVersion = ============= */ void IdentifyVersion (void) { char *doom1wad, *doomwad, *doom2wad, *doom2fwad; #ifdef NORMALUNIX char *home; char *doomwaddir; doomwaddir = getenv("DOOMWADDIR"); if (!doomwaddir) doomwaddir = "."; doom1wad = malloc(strlen(doomwaddir)+1+9+1); sprintf(doom1wad, "%s/doom1.wad", doomwaddir); doom2fwad = malloc(strlen(doomwaddir)+1+10+1); sprintf(doom2fwad, "%s/doom2f.wad", doomwaddir); doom2wad = malloc(strlen(doomwaddir)+1+9+1); sprintf(doom2wad, "%s/doom2.wad", doomwaddir); doomwad = malloc(strlen(doomwaddir)+1+8+1); sprintf(doomwad, "%s/doom.wad", doomwaddir); home = getenv("HOME"); if (!home) I_Error("Please set $HOME to your home directory"); sprintf(basedefault, "%s/.doomrc", home); #else strcpy (basedefault,"default.cfg"); doom1wad = "doom1.wad"; doom2fwad = "doom2f.wad"; doom2wad = "doom2.wad"; doomwad = "doom.wad"; #endif if (M_CheckParm ("-shdev")) { registered = false; shareware = true; devparm = true; D_AddFile (DEVDATA"doom1.wad"); D_AddFile (DEVMAPS"data/texture1.lmp"); D_AddFile (DEVMAPS"data/pnames.lmp"); strcpy (basedefault,DEVDATA"default.cfg"); return; } if (M_CheckParm ("-regdev")) { registered = true; devparm = true; D_AddFile (DEVDATA"doom.wad"); D_AddFile (DEVMAPS"data/texture1.lmp"); D_AddFile (DEVMAPS"data/texture2.lmp"); D_AddFile (DEVMAPS"data/pnames.lmp"); strcpy (basedefault,DEVDATA"default.cfg"); return; } if (M_CheckParm ("-comdev")) { commercial = true; devparm = true; D_AddFile (DEVDATA"doom2.wad"); D_AddFile (DEVMAPS"cdata/texture1.lmp"); D_AddFile (DEVMAPS"cdata/pnames.lmp"); strcpy (basedefault,DEVDATA"default.cfg"); return; } if ( !access (doom2fwad,R_OK) ) { commercial = true; french = true; printf("French version\n"); D_AddFile (doom2fwad); return; } if ( !access (doom2wad,R_OK) ) { commercial = true; D_AddFile (doom2wad); return; } if (! access (doomwad,R_OK) ) { registered = true; D_AddFile (doomwad); return; } if ( !access (doom1wad,R_OK) ) { shareware = true; D_AddFile (doom1wad); return; } printf("Game mode indeterminate.\n"); exit(1); // I_Error ("Game mode indeterminate\n"); } /* ============= = = CheckBetaTest = ============= */ void CheckBetaTest (void) { #ifdef BETATEST // // check password and date stamp for bad beta testers // struct dosdate_t d; char *p, *check; p = check = W_CacheLumpName ("bpas",PU_CACHE); while (*check > ' ') check++; *check = 0; if (!M_CheckParm (p)) I_Error ("Corrupt wadfile"); _dos_getdate(&d); if (d.year > 1993 || d.day > 20) I_Error ("Bad wadfile"); #endif } //======================================================== // // Find a Response File // //======================================================== void FindResponseFile (void) { int i; #define MAXARGVS 100 for (i = 1;i < myargc;i++) if (myargv[i][0] == '@') { FILE * handle; int size; int k; int index; int indexinfile; char *infile; char *file; char *moreargs[20]; char *firstargv; // READ THE RESPONSE FILE INTO MEMORY handle = fopen (&myargv[i][1],"rb"); if (!handle) { printf ("\nNo such response file!"); exit(1); } printf("Found response file %s!\n",&myargv[i][1]); fseek (handle,0,SEEK_END); size = ftell(handle); fseek (handle,0,SEEK_SET); file = malloc (size); fread (file,size,1,handle); fclose (handle); // KEEP ALL CMDLINE ARGS FOLLOWING @RESPONSEFILE ARG for (index = 0,k = i+1; k < myargc; k++) moreargs[index++] = myargv[k]; firstargv = myargv[0]; myargv = malloc(sizeof(char *)*MAXARGVS); memset(myargv,0,sizeof(char *)*MAXARGVS); myargv[0] = firstargv; infile = file; indexinfile = k = 0; indexinfile++; // SKIP PAST ARGV[0] (KEEP IT) do { myargv[indexinfile++] = infile+k; while(k < size && ((*(infile+k)>= ' '+1) && (*(infile+k)<='z'))) k++; *(infile+k) = 0; while(k < size && ((*(infile+k)<= ' ') || (*(infile+k)>'z'))) k++; } while(k < size); for (k = 0;k < index;k++) myargv[indexinfile++] = moreargs[k]; myargc = indexinfile; // DISPLAY ARGS printf("%d command-line args:\n",myargc); for (k=1;k 400) scale = 400; printf ("turbo scale: %i%%\n",scale); forwardmove[0] = forwardmove[0]*scale/100; forwardmove[1] = forwardmove[1]*scale/100; sidemove[0] = sidemove[0]*scale/100; sidemove[1] = sidemove[1]*scale/100; } // // add any files specified on the command line with -file wadfile to // the wad list // // convenience hack to allow -wart e m to add a wad file // prepend a tilde to the filename so wadfile will be reloadable p = M_CheckParm ("-wart"); if (p) { myargv[p][4] = 'p'; // big hack, change to -warp if (commercial) { p = atoi (myargv[p+1]); if (p<10) sprintf (file,"~"DEVMAPS"cdata/map0%i.wad", p); else sprintf (file,"~"DEVMAPS"cdata/map%i.wad", p); } else { sprintf (file,"~"DEVMAPS"E%cM%c.wad", myargv[p+1][0], myargv[p+2][0]); printf("Warping to Episode %s, Map %s.\n",myargv[p+1],myargv[p+2]); } D_AddFile (file); } p = M_CheckParm ("-file"); if (p) { // the parms after p are wadfile/lump names, until end of parms // or another - preceded parm modifiedgame = true; // homebrew levels while (++p != myargc && myargv[p][0] != '-') D_AddFile (myargv[p]); } p = M_CheckParm ("-playdemo"); if (!p) p = M_CheckParm ("-timedemo"); if (p && p < myargc-1) { sprintf (file,"%s.lmp", myargv[p+1]); D_AddFile (file); printf("Playing demo %s.lmp.\n",myargv[p+1]); } // // get skill / episode / map from parms // startskill = sk_medium; startepisode = 1; startmap = 1; autostart = false; p = M_CheckParm ("-skill"); if (p && p < myargc-1) { startskill = myargv[p+1][0]-'1'; autostart = true; } p = M_CheckParm ("-episode"); if (p && p < myargc-1) { startepisode = myargv[p+1][0]-'0'; startmap = 1; autostart = true; } p = M_CheckParm ("-timer"); if (p && p < myargc-1 && deathmatch) { int time; time = atoi(myargv[p+1]); printf("Levels will end after %d minute",time); if (time>1) printf("s"); printf(".\n"); } p = M_CheckParm ("-avg"); if (p && p < myargc-1 && deathmatch) printf("Austin Virtual Gaming: Levels will end after 20 minutes\n"); p = M_CheckParm ("-warp"); if (p && p < myargc-1) { if (commercial) startmap = atoi (myargv[p+1]); else { startepisode = myargv[p+1][0]-'0'; startmap = myargv[p+2][0]-'0'; } autostart = true; } // // init subsystems // printf ("V_Init: allocate screens.\n"); V_Init (); printf ("M_LoadDefaults: Load system defaults.\n"); M_LoadDefaults (); // load before initing other systems printf ("Z_Init: Init zone memory allocation daemon. \n"); Z_Init (); printf ("W_Init: Init WADfiles.\n"); W_InitMultipleFiles (wadfiles); // // Check for -file in shareware // if (modifiedgame) { char name[23][8]= { "e2m1","e2m2","e2m3","e2m4","e2m5","e2m6","e2m7","e2m8","e2m9", "e3m1","e3m3","e3m3","e3m4","e3m5","e3m6","e3m7","e3m8","e3m9", "dphoof","bfgga0","heada1","cybra1","spida1d1" }; int i; if (shareware) I_Error("\nYou cannot -file with the shareware " "version. Register!"); if (registered) for (i = 0;i < 23; i++) if (W_CheckNumForName(name[i])<0) I_Error("\nThis is not the registered version."); } // // print modified banner // if (modifiedgame) { printf ( "===========================================================================\n" "ATTENTION: This version of DOOM has been modified. If you would like to\n" "get a copy of the original game, call 1-800-IDGAMES or see the readme file.\n" " You will not receive technical support for modified games.\n" " press enter to continue\n" "===========================================================================\n" ); getchar (); } // // check which version // if (registered) { mprintf (" registered version.\n"); mprintf ( "===========================================================================\n" " This version is NOT SHAREWARE, do not distribute!\n" " Please report software piracy to the SPA: 1-800-388-PIR8\n" "===========================================================================\n" ); } if (shareware) mprintf (" shareware version.\n"); if (commercial) { mprintf (" commercial version.\n"); mprintf ( "===========================================================================\n" " Do not distribute!\n" " Please report software piracy to the SPA: 1-800-388-PIR8\n" "===========================================================================\n" ); // shareware = false; } mprintf ("M_Init: Init miscellaneous info.\n"); M_Init (); mprintf ("R_Init: Init DOOM refresh daemon - "); R_Init (); mprintf ("\nP_Init: Init Playloop state.\n"); P_Init (); mprintf ("I_Init: Setting up machine state.\n"); I_Init (); mprintf ("D_CheckNetGame: Checking network game status.\n"); D_CheckNetGame (); mprintf ("S_Init: Setting up sound.\n"); S_Init (sfxVolume*8,musicVolume*8); mprintf ("HU_Init: Setting up heads up display.\n"); HU_Init (); mprintf ("ST_Init: Init status bar.\n"); ST_Init (); CheckBetaTest (); // // check for a driver that wants intermission stats // p = M_CheckParm ("-statcopy"); if (p && p gametic for all players ============================================================================== */ #define RESENDCOUNT 10 #define PL_DRONE 0x80 // bit flag in doomdata->player ticcmd_t localcmds[BACKUPTICS]; ticcmd_t netcmds[MAXPLAYERS][BACKUPTICS]; int nettics[MAXNETNODES]; boolean nodeingame[MAXNETNODES]; // set false as nodes leave game boolean remoteresend[MAXNETNODES]; // set when local needs tics int resendto[MAXNETNODES]; // set when remote needs tics int resendcount[MAXNETNODES]; int nodeforplayer[MAXPLAYERS]; int maketic; int lastnettic, skiptics; int ticdup; int maxsend; // BACKUPTICS/(2*ticdup)-1 void D_ProcessEvents (void); void G_BuildTiccmd (ticcmd_t *cmd); void D_DoAdvanceDemo (void); boolean reboundpacket; doomdata_t reboundstore; int NetbufferSize (void) { return (int)&(((doomdata_t *)0)->cmds[netbuffer->numtics]); } unsigned NetbufferChecksum (void) { unsigned c; int i,l; c = 0x1234567; #if defined(NeXT) || defined(NORMALUNIX) return 0; // byte order problems #endif l = (NetbufferSize () - (int)&(((doomdata_t *)0)->retransmitfrom))/4; for (i=0 ; iretransmitfrom)[i] * (i+1); return c & NCMD_CHECKSUM; } int ExpandTics (int low) { int delta; delta = low - (maketic&0xff); if (delta >= -64 && delta <= 64) return (maketic&~0xff) + low; if (delta > 64) return (maketic&~0xff) - 256 + low; if (delta < -64) return (maketic&~0xff) + 256 + low; I_Error ("ExpandTics: strange value %i at maketic %i",low,maketic); return 0; } //============================================================================ /* ============== = = HSendPacket = ============== */ void HSendPacket (int node, int flags) { netbuffer->checksum = NetbufferChecksum () | flags; if (!node) { reboundstore = *netbuffer; reboundpacket = true; return; } if (demoplayback) return; if (!netgame) I_Error ("Tried to transmit to another node"); doomcom->command = CMD_SEND; doomcom->remotenode = node; doomcom->datalength = NetbufferSize (); if (debugfile) { int i; int realretrans; if (netbuffer->checksum & NCMD_RETRANSMIT) realretrans = ExpandTics (netbuffer->retransmitfrom); else realretrans = -1; fprintf (debugfile,"send (%i + %i, R %i) [%i] " ,ExpandTics(netbuffer->starttic),netbuffer->numtics, realretrans, doomcom->datalength); for (i=0 ; idatalength ; i++) fprintf (debugfile,"%i ",((byte *)netbuffer)[i]); fprintf (debugfile,"\n"); } I_NetCmd (); } /* ============== = = HGetPacket = = Returns false if no packet is waiting = ============== */ boolean HGetPacket (void) { if (reboundpacket) { *netbuffer = reboundstore; doomcom->remotenode = 0; reboundpacket = false; return true; } if (!netgame) return false; if (demoplayback) return false; doomcom->command = CMD_GET; I_NetCmd (); if (doomcom->remotenode == -1) return false; if (doomcom->datalength != NetbufferSize ()) { if (debugfile) fprintf (debugfile,"bad packet length %i\n",doomcom->datalength); return false; } if (NetbufferChecksum () != (netbuffer->checksum&NCMD_CHECKSUM) ) { if (debugfile) fprintf (debugfile,"bad packet checksum\n"); return false; } if (debugfile) { int realretrans; int i; if (netbuffer->checksum & NCMD_SETUP) fprintf (debugfile,"setup packet\n"); else { if (netbuffer->checksum & NCMD_RETRANSMIT) realretrans = ExpandTics (netbuffer->retransmitfrom); else realretrans = -1; fprintf (debugfile,"get %i = (%i + %i, R %i)[%i] ",doomcom->remotenode, ExpandTics(netbuffer->starttic),netbuffer->numtics, realretrans, doomcom->datalength); for (i=0 ; idatalength ; i++) fprintf (debugfile,"%i ",((byte *)netbuffer)[i]); fprintf (debugfile,"\n"); } } return true; } /* =================== = = GetPackets = =================== */ char exitmsg[80]; void GetPackets (void) { int netconsole; int netnode; ticcmd_t *src, *dest; int realend; int realstart; while (HGetPacket ()) { if (netbuffer->checksum & NCMD_SETUP) continue; // extra setup packet netconsole = netbuffer->player & ~PL_DRONE; netnode = doomcom->remotenode; // // to save bytes, only the low byte of tic numbers are sent // Figure out what the rest of the bytes are // realstart = ExpandTics (netbuffer->starttic); realend = (realstart+netbuffer->numtics); // // check for exiting the game // if (netbuffer->checksum & NCMD_EXIT) { if (!nodeingame[netnode]) continue; nodeingame[netnode] = false; playeringame[netconsole] = false; strcpy (exitmsg, "Player 1 left the game"); exitmsg[7] += netconsole; players[consoleplayer].message = exitmsg; if (demorecording) G_CheckDemoStatus (); continue; } // // check for a remote game kill // if (netbuffer->checksum & NCMD_KILL) I_Error ("Killed by network driver"); nodeforplayer[netconsole] = netnode; // // check for retransmit request // if ( resendcount[netnode] <= 0 && (netbuffer->checksum & NCMD_RETRANSMIT) ) { resendto[netnode] = ExpandTics(netbuffer->retransmitfrom); if (debugfile) fprintf (debugfile,"retransmit from %i\n", resendto[netnode]); resendcount[netnode] = RESENDCOUNT; } else resendcount[netnode]--; // // check for out of order / duplicated packet // if (realend == nettics[netnode]) continue; if (realend < nettics[netnode]) { if (debugfile) fprintf (debugfile,"out of order packet (%i + %i)\n" ,realstart,netbuffer->numtics); continue; } // // check for a missed packet // if (realstart > nettics[netnode]) { // stop processing until the other system resends the missed tics if (debugfile) fprintf (debugfile,"missed tics from %i (%i - %i)\n", netnode, realstart, nettics[netnode]); remoteresend[netnode] = true; continue; } // // update command store from the packet // { int start; remoteresend[netnode] = false; start = nettics[netnode] - realstart; src = &netbuffer->cmds[start]; while (nettics[netnode] < realend) { dest = &netcmds[netconsole][nettics[netnode]%BACKUPTICS]; nettics[netnode]++; *dest = *src; src++; } } } } /* ============= = = NetUpdate = = Builds ticcmds for console player = sends out a packet ============= */ int gametime; void NetUpdate (void) { int nowtime; int newtics; int i,j; int realstart; int gameticdiv; // // check time // nowtime = I_GetTime ()/ticdup; newtics = nowtime - gametime; gametime = nowtime; if (newtics <= 0) // nothing new to update goto listen; if (skiptics <= newtics) { newtics -= skiptics; skiptics = 0; } else { skiptics -= newtics; newtics = 0; } netbuffer->player = consoleplayer; // // build new ticcmds for console player // gameticdiv = gametic/ticdup; for (i=0 ; i= BACKUPTICS/2-1) break; // can't hold any more //printf ("mk:%i ",maketic); G_BuildTiccmd (&localcmds[maketic%BACKUPTICS]); maketic++; } if (singletics) return; // singletic update is syncronous // // send the packet to the other nodes // for (i=0 ; inumnodes ; i++) if (nodeingame[i]) { netbuffer->starttic = realstart = resendto[i]; netbuffer->numtics = maketic - realstart; if (netbuffer->numtics > BACKUPTICS) I_Error ("NetUpdate: netbuffer->numtics > BACKUPTICS"); resendto[i] = maketic - doomcom->extratics; for (j=0 ; j< netbuffer->numtics ; j++) netbuffer->cmds[j] = localcmds[(realstart+j)%BACKUPTICS]; if (remoteresend[i]) { netbuffer->retransmitfrom = nettics[i]; HSendPacket (i, NCMD_RETRANSMIT); } else { netbuffer->retransmitfrom = 0; HSendPacket (i, 0); } } // // listen for other packets // listen: GetPackets (); } /* ===================== = = CheckAbort = ===================== */ void CheckAbort (void) { event_t *ev; int stoptic; stoptic = I_GetTime () + 2; while (I_GetTime() < stoptic) I_StartTic (); I_StartTic (); for ( ; eventtail != eventhead ; eventtail = (++eventtail)&(MAXEVENTS-1) ) { ev = &events[eventtail]; if (ev->type == ev_keydown && ev->data1 == KEY_ESCAPE) I_Error ("Network game synchronization aborted."); } } /* ===================== = = D_ArbitrateNetStart = ===================== */ void D_ArbitrateNetStart (void) { int i; boolean gotinfo[MAXNETNODES]; autostart = true; memset (gotinfo,0,sizeof(gotinfo)); if (doomcom->consoleplayer) { // listen for setup info from key player mprintf ("listening for network start info...\n"); while (1) { CheckAbort (); if (!HGetPacket ()) continue; if (netbuffer->checksum & NCMD_SETUP) { if (netbuffer->player != VERSION) I_Error ("Different DOOM versions cannot play a net game!"); startskill = netbuffer->retransmitfrom & 15; deathmatch = (netbuffer->retransmitfrom & 0xc0) >> 6; nomonsters = (netbuffer->retransmitfrom & 0x20) > 0; respawnparm = (netbuffer->retransmitfrom & 0x10) > 0; startmap = netbuffer->starttic & 0x3f; startepisode = netbuffer->starttic >> 6; return; } } } else { // key player, send the setup info mprintf ("sending network start info...\n"); do { CheckAbort (); for (i=0 ; inumnodes ; i++) { netbuffer->retransmitfrom = startskill; if (deathmatch) netbuffer->retransmitfrom |= (deathmatch<<6); if (nomonsters) netbuffer->retransmitfrom |= 0x20; if (respawnparm) netbuffer->retransmitfrom |= 0x10; netbuffer->starttic = startepisode * 64 + startmap; netbuffer->player = VERSION; netbuffer->numtics = 0; HSendPacket (i, NCMD_SETUP); } #if 1 for(i = 10 ; i && HGetPacket(); --i) { if((netbuffer->player&0x7f) < MAXNETNODES) gotinfo[netbuffer->player&0x7f] = true; } #else while (HGetPacket ()) { gotinfo[netbuffer->player&0x7f] = true; } #endif for (i=1 ; inumnodes ; i++) if (!gotinfo[i]) break; } while (i < doomcom->numnodes); } } /* =================== = = D_CheckNetGame = = Works out player numbers among the net participants =================== */ extern int viewangleoffset; void D_CheckNetGame (void) { int i; for (i=0 ; iid != DOOMCOM_ID) I_Error ("Doomcom buffer invalid!"); netbuffer = &doomcom->data; consoleplayer = displayplayer = doomcom->consoleplayer; if (netgame) D_ArbitrateNetStart (); printf ("startskill %i deathmatch: %i startmap: %i startepisode: %i\n", startskill, deathmatch, startmap, startepisode); // read values out of doomcom ticdup = doomcom->ticdup; maxsend = BACKUPTICS/(2*ticdup)-1; if (maxsend<1) maxsend = 1; for (i=0 ; inumplayers ; i++) playeringame[i] = true; for (i=0 ; inumnodes ; i++) nodeingame[i] = true; printf ("player %i of %i (%i nodes)\n", consoleplayer+1, doomcom->numplayers, doomcom->numnodes); } /* ================== = = D_QuitNetGame = = Called before quitting to leave a net game without hanging the = other players = ================== */ void D_QuitNetGame (void) { int i, j; if (debugfile) fclose (debugfile); if (!netgame || !usergame || consoleplayer == -1 || demoplayback) return; // send a bunch of packets for security netbuffer->player = consoleplayer; netbuffer->numtics = 0; for (i=0 ; i<4 ; i++) { for (j=1 ; jnumnodes ; j++) if (nodeingame[j]) HSendPacket (j, NCMD_EXIT); I_WaitVBL (1); } } /* =============== = = TryRunTics = =============== */ int frametics[4], frameon; int frameskip[4]; int oldnettics; extern boolean advancedemo; void TryRunTics (void) { int i; int lowtic; int entertic; static int oldentertics; int realtics, availabletics; int counts; int numplaying; // // get real tics // entertic = I_GetTime ()/ticdup; realtics = entertic - oldentertics; oldentertics = entertic; // // get available tics // NetUpdate (); lowtic = MAXINT; numplaying = 0; for (i=0 ; inumnodes ; i++) if (nodeingame[i]) { numplaying++; if (nettics[i] < lowtic) lowtic = nettics[i]; } availabletics = lowtic - gametic/ticdup; // // decide how many tics to run // if (realtics < availabletics-1) counts = realtics+1; else if (realtics < availabletics) counts = realtics; else counts = availabletics; if (counts < 1) counts = 1; frameon++; if (debugfile) fprintf (debugfile,"=======real: %i avail: %i game: %i\n",realtics, availabletics,counts); if (!demoplayback) { //============================================================================= // // ideally nettics[0] should be 1 - 3 tics above lowtic // if we are consistantly slower, speed up time // for (i=0 ; i nettics[nodeforplayer[i]]); oldnettics = nettics[0]; if (frameskip[0] && frameskip[1] && frameskip[2] && frameskip[3]) { skiptics = 1; // printf ("+"); } } //============================================================================= } // demoplayback // // wait for new tics if needed // while (lowtic < gametic/ticdup + counts) { NetUpdate (); lowtic = MAXINT; for (i=0 ; inumnodes ; i++) if (nodeingame[i] && nettics[i] < lowtic) lowtic = nettics[i]; if (lowtic < gametic/ticdup) I_Error ("TryRunTics: lowtic < gametic"); // don't stay in here forever -- give the menu a chance to work if (I_GetTime ()/ticdup - entertic >= 20) { M_Ticker (); return; } } // // run the count * ticdup dics // while (counts--) { for (i=0 ; i lowtic) I_Error ("gametic>lowtic"); if (advancedemo) D_DoAdvanceDemo (); M_Ticker (); G_Ticker (); gametic++; // // modify command for duplicated tics // if (i != ticdup-1) { ticcmd_t *cmd; int buf; int j; buf = (gametic/ticdup)%BACKUPTICS; for (j=0 ; jchatchar = 0; if (cmd->buttons & BT_SPECIAL) cmd->buttons = 0; } } } NetUpdate (); // check for new console commands } } \ No newline at end of file diff --git a/F_FINALE.C b/F_FINALE.C new file mode 100644 index 0000000..d8dfadc --- /dev/null +++ b/F_FINALE.C @@ -0,0 +1 @@ +// F_finale.c #include "doomdef.h" #include "r_local.h" #include int finalestage; // 0 = text, 1 = art screen, 2 = character cast int finalecount; #define TEXTSPEED 3 #define TEXTWAIT 250 char *e1text = E1TEXT; char *e2text = E2TEXT; char *e3text = E3TEXT; char *c1text = C1TEXT; char *c2text = C2TEXT; char *c3text = C3TEXT; char *c4text = C4TEXT; char *c5text = C5TEXT; char *c6text = C6TEXT; char *finaletext; char *finaleflat; void F_StartCast (void); void F_CastTicker (void); boolean F_CastResponder (event_t *ev); void F_CastDrawer (void); /* ======================= = = F_StartFinale = ======================= */ void F_StartFinale (void) { gameaction = ga_nothing; gamestate = GS_FINALE; viewactive = false; automapactive = false; if (commercial) { switch (gamemap) { case 6: finaleflat = "SLIME16"; finaletext = c1text; break; case 11: finaleflat = "RROCK14"; finaletext = c2text; break; case 20: finaleflat = "RROCK07"; finaletext = c3text; break; case 30: finaleflat = "RROCK17"; finaletext = c4text; break; case 15: finaleflat = "RROCK13"; finaletext = c5text; break; case 31: finaleflat = "RROCK19"; finaletext = c6text; break; } S_ChangeMusic(mus_read_m, true); } else { switch (gameepisode) { case 1: finaleflat = "FLOOR4_8"; finaletext = e1text; break; case 2: finaleflat = "SFLR6_1"; finaletext = e2text; break; case 3: finaleflat = "MFLR8_4"; finaletext = e3text; break; } S_ChangeMusic(mus_victor, true); } finalestage = 0; finalecount = 0; } boolean F_Responder (event_t *event) { if (finalestage == 2) return F_CastResponder (event); return false; } /* ======================= = = F_Ticker = ======================= */ void F_Ticker (void) { int i; // // check for skipping // if (commercial && finalecount > 50) { // go on to the next level for (i=0 ; istrlen (finaletext)*TEXTSPEED + TEXTWAIT) { finalecount = 0; finalestage = 1; wipegamestate = -1; // force a wipe if (gameepisode == 3) S_StartMusic (mus_bunny); } } /* ======================= = = F_TextWrite = ======================= */ #include "hu_stuff.h" extern patch_t *hu_font[HU_FONTSIZE]; void F_TextWrite (void) { byte *src, *dest; int x,y,w; int count; char *ch; int c; int cx, cy; // // erase the entire screen to a tiled background // src = W_CacheLumpName ( finaleflat , PU_CACHE); dest = screens[0]; for (y=0 ; y HU_FONTSIZE) { cx += 4; continue; } w = SHORT (hu_font[c]->width); if (cx+w > SCREENWIDTH) break; V_DrawPatch(cx, cy, 0, hu_font[c]); cx+=w; } } //============================================================================ typedef struct { char *name; mobjtype_t type; } castinfo_t; castinfo_t castorder[] = { {CC_ZOMBIE, MT_POSSESSED}, {CC_SHOTGUN, MT_SHOTGUY}, {CC_HEAVY, MT_CHAINGUY}, {CC_IMP, MT_TROOP}, {CC_DEMON, MT_SERGEANT}, {CC_LOST, MT_SKULL}, {CC_CACO, MT_HEAD}, {CC_HELL, MT_KNIGHT}, {CC_BARON, MT_BRUISER}, {CC_ARACH, MT_BABY}, {CC_PAIN, MT_PAIN}, {CC_REVEN, MT_UNDEAD}, {CC_MANCU, MT_FATSO}, {CC_ARCH, MT_VILE}, {CC_SPIDER, MT_SPIDER}, {CC_CYBER, MT_CYBORG}, {CC_HERO, MT_PLAYER}, {NULL,0} }; int castnum; int casttics; state_t *caststate; boolean castdeath; int castframes; int castonmelee; boolean castattacking; /* ======================= = = F_StartCast = ======================= */ extern gamestate_t wipegamestate; void F_StartCast (void) { wipegamestate = -1; // force a screen wipe castnum = 0; caststate = &states[mobjinfo[castorder[castnum].type].seestate]; casttics = caststate->tics; castdeath = false; finalestage = 2; castframes = 0; castonmelee = 0; castattacking = false; S_ChangeMusic(mus_evil, true); } /* ======================= = = F_CastTicker = ======================= */ void F_CastTicker (void) { int st; int sfx; if (--casttics > 0) return; // not time to change state yet if (caststate->tics == -1 || caststate->nextstate == S_NULL) { // switch from deathstate to next monster castnum++; castdeath = false; if (castorder[castnum].name == NULL) castnum = 0; if (mobjinfo[castorder[castnum].type].seesound) S_StartSound (NULL, mobjinfo[castorder[castnum].type].seesound); caststate = &states[mobjinfo[castorder[castnum].type].seestate]; castframes = 0; } else { // just advance to next state in animation if (caststate == &states[S_PLAY_ATK1]) goto stopattack; // Oh, gross hack! st = caststate->nextstate; caststate = &states[st]; castframes++; //============================================== // sound hacks.... switch (st) { case S_PLAY_ATK1: sfx = sfx_dshtgn; break; case S_POSS_ATK2: sfx = sfx_pistol; break; case S_SPOS_ATK2: sfx = sfx_shotgn; break; case S_VILE_ATK2: sfx = sfx_vilatk; break; case S_SKEL_FIST2: sfx = sfx_skeswg; break; case S_SKEL_FIST4: sfx = sfx_skepch; break; case S_SKEL_MISS2: sfx = sfx_skeatk; break; case S_FATT_ATK8: case S_FATT_ATK5: case S_FATT_ATK2: sfx = sfx_firsht; break; case S_CPOS_ATK2: case S_CPOS_ATK3: case S_CPOS_ATK4: sfx = sfx_shotgn; break; case S_TROO_ATK3: sfx = sfx_claw; break; case S_SARG_ATK2: sfx = sfx_sgtatk; break; case S_BOSS_ATK2: case S_BOS2_ATK2: case S_HEAD_ATK2: sfx = sfx_firsht; break; case S_SKULL_ATK2: sfx = sfx_sklatk; break; case S_SPID_ATK2: case S_SPID_ATK3: sfx = sfx_shotgn; break; case S_BSPI_ATK2: sfx = sfx_plasma; break; case S_CYBER_ATK2: case S_CYBER_ATK4: case S_CYBER_ATK6: sfx = sfx_rlaunc; break; case S_PAIN_ATK3: sfx = sfx_sklatk; break; default: sfx = 0; break; } if (sfx) S_StartSound (NULL, sfx); //============================================== } if (castframes == 12) { // go into attack frame castattacking = true; if (castonmelee) caststate=&states[mobjinfo[castorder[castnum].type].meleestate]; else caststate=&states[mobjinfo[castorder[castnum].type].missilestate]; castonmelee ^= 1; if (caststate == &states[S_NULL]) { if (castonmelee) caststate= &states[mobjinfo[castorder[castnum].type].meleestate]; else caststate= &states[mobjinfo[castorder[castnum].type].missilestate]; } } if (castattacking) { if (castframes == 24 || caststate == &states[mobjinfo[castorder[castnum].type].seestate] ) { stopattack: castattacking = false; castframes = 0; caststate = &states[mobjinfo[castorder[castnum].type].seestate]; } } casttics = caststate->tics; if (casttics == -1) casttics = 15; } /* ======================= = = F_CastResponder = ======================= */ boolean F_CastResponder (event_t *ev) { if (ev->type != ev_keydown) return false; if (castdeath) return true; // already in dying frames // go into death frame castdeath = true; caststate = &states[mobjinfo[castorder[castnum].type].deathstate]; casttics = caststate->tics; castframes = 0; castattacking = false; if (mobjinfo[castorder[castnum].type].deathsound) S_StartSound (NULL, mobjinfo[castorder[castnum].type].deathsound); return true; } void F_CastPrint (char *text) { char *ch; int c; int cx; int w,width; // // find width // ch = text; width = 0; while (ch) { c = *ch++; if (!c) break; c = toupper(c) - HU_FONTSTART; if (c < 0 || c> HU_FONTSIZE) { width += 4; continue; } w = SHORT (hu_font[c]->width); width += w; } // // draw it // cx = 160-width/2; ch = text; while (ch) { c = *ch++; if (!c) break; c = toupper(c) - HU_FONTSTART; if (c < 0 || c> HU_FONTSIZE) { cx += 4; continue; } w = SHORT (hu_font[c]->width); V_DrawPatch(cx, 180, 0, hu_font[c]); cx+=w; } } /* ======================= = = F_CastDrawer = ======================= */ void V_DrawPatchFlipped (int x, int y, int scrn, patch_t *patch); void F_CastDrawer (void) { spritedef_t *sprdef; spriteframe_t *sprframe; int lump; boolean flip; patch_t *patch; // // erase the entire screen to a background // V_DrawPatch (0,0,0, W_CacheLumpName ("BOSSBACK", PU_CACHE)); F_CastPrint (castorder[castnum].name); // // draw the current frame in the middle of the screen // sprdef = &sprites[caststate->sprite]; sprframe = &sprdef->spriteframes[ caststate->frame & FF_FRAMEMASK]; lump = sprframe->lump[0]; flip = (boolean)sprframe->flip[0]; patch = W_CacheLumpNum (lump+firstspritelump, PU_CACHE); if (flip) V_DrawPatchFlipped (160,170,0,patch); else V_DrawPatch (160,170,0,patch); } //============================================================================ /* ======================= = = F_DrawPatchCol = ======================= */ void F_DrawPatchCol (int x, patch_t *patch, int col) { column_t *column; byte *source, *dest, *desttop; int count; column = (column_t *)((byte *)patch + LONG(patch->columnofs[col])); desttop = screens[0]+x; // step through the posts in a column while (column->topdelta != 0xff ) { source = (byte *)column + 3; dest = desttop + column->topdelta*SCREENWIDTH; count = column->length; while (count--) { *dest = *source++; dest += SCREENWIDTH; } column = (column_t *)( (byte *)column + column->length + 4 ); } } /* ================== = = F_BunnyScroll = ================== */ void F_BunnyScroll (void) { int scrolled, x; patch_t *p1, *p2; char name[10]; int stage; static int laststage; p1 = W_CacheLumpName ("PFUB2", PU_LEVEL); p2 = W_CacheLumpName ("PFUB1", PU_LEVEL); V_MarkRect (0, 0, SCREENWIDTH, SCREENHEIGHT); scrolled = 320 - (finalecount-230)/2; if (scrolled > 320) scrolled = 320; if (scrolled < 0) scrolled = 0; for ( x=0 ; x 6) stage = 6; if (stage > laststage) { S_StartSound (NULL, sfx_pistol); laststage = stage; } sprintf (name,"END%i",stage); V_DrawPatch ((SCREENWIDTH-13*8)/2, (SCREENHEIGHT-8*8)/2,0, W_CacheLumpName (name,PU_CACHE)); } //============================================================================ /* ======================= = = F_Drawer = ======================= */ void F_Drawer (void) { if (finalestage == 2) { F_CastDrawer (); return; } if (!finalestage) F_TextWrite (); else { switch (gameepisode) { case 1: V_DrawPatch (0,0, 0, W_CacheLumpName("HELP2", PU_CACHE)); break; case 2: V_DrawPatch (0,0, 0, W_CacheLumpName("VICTORY2", PU_CACHE)); break; case 3: F_BunnyScroll (); break; } } } \ No newline at end of file diff --git a/G_GAME.C b/G_GAME.C new file mode 100644 index 0000000..f6ff102 --- /dev/null +++ b/G_GAME.C @@ -0,0 +1 @@ +// G_game.c #include #include "doomdef.h" #include "p_local.h" boolean G_CheckDemoStatus (void); void G_ReadDemoTiccmd (ticcmd_t *cmd); void G_WriteDemoTiccmd (ticcmd_t *cmd); void G_PlayerReborn (int player); void G_InitNew (skill_t skill, int episode, int map); void G_DoReborn (int playernum); void G_DoLoadLevel (void); void G_DoNewGame (void); void G_DoLoadGame (void); void G_DoPlayDemo (void); void G_DoCompleted (void); void G_DoVictory (void); void G_DoWorldDone (void); void G_DoSaveGame (void); gameaction_t gameaction; gamestate_t gamestate; skill_t gameskill; boolean respawnmonsters; int gameepisode; int gamemap; boolean paused; boolean sendpause; // send a pause event next tic boolean sendsave; // send a save event next tic boolean usergame; // ok to save / end game boolean timingdemo; // if true, exit with report on completion boolean nodrawers; // for comparative timing purposes boolean noblit; // for comparative timing purposes int starttime; // for comparative timing purposes boolean viewactive; boolean deathmatch; // only if started as net death boolean netgame; // only true if packets are broadcast boolean playeringame[MAXPLAYERS]; player_t players[MAXPLAYERS]; int consoleplayer; // player taking events and displaying int displayplayer; // view being displayed int gametic; int levelstarttic; // gametic at level start int totalkills, totalitems, totalsecret; // for intermission char demoname[32]; boolean demorecording; boolean demoplayback; boolean netdemo; byte *demobuffer, *demo_p, *demoend; boolean singledemo; // quit after playing a demo from cmdline boolean precache = true; // if true, load all graphics at start wbstartstruct_t wminfo; // parms for world map / intermission short consistancy[MAXPLAYERS][BACKUPTICS]; byte *savebuffer, *save_p; // // controls (have defaults) // int key_right, key_left, key_up, key_down; int key_strafeleft, key_straferight; int key_fire, key_use, key_strafe, key_speed; int mousebfire; int mousebstrafe; int mousebforward; int joybfire; int joybstrafe; int joybuse; int joybspeed; #define MAXPLMOVE (forwardmove[1]) #define TURBOTHRESHOLD 0x32 fixed_t forwardmove[2] = {0x19, 0x32}; fixed_t sidemove[2] = {0x18, 0x28}; fixed_t angleturn[3] = {640, 1280, 320}; // + slow turn #define SLOWTURNTICS 6 #define NUMKEYS 256 boolean gamekeydown[NUMKEYS]; int turnheld; // for accelerative turning boolean mousearray[4]; boolean *mousebuttons = &mousearray[1]; // allow [-1] int mousex, mousey; // mouse values are used once int dclicktime, dclickstate, dclicks; int dclicktime2, dclickstate2, dclicks2; int joyxmove, joyymove; // joystick values are repeated boolean joyarray[5]; boolean *joybuttons = &joyarray[1]; // allow [-1] int savegameslot; char savedescription[32]; #define BODYQUESIZE 32 mobj_t *bodyque[BODYQUESIZE]; int bodyqueslot; void *statcopy; // for statistics driver //============================================================================= int G_CmdChecksum (ticcmd_t *cmd) { int i,sum; sum = 0; for (i=0 ; i< sizeof(*cmd)/4 - 1 ; i++) sum += ((int *)cmd)[i]; return sum; } /* ==================== = = G_BuildTiccmd = = Builds a ticcmd from all of the available inputs or reads it from the = demo buffer. = If recording a demo, write it out ==================== */ extern int isCyberPresent; // is CyberMan present? void I_ReadCyberCmd (ticcmd_t *cmd); void G_BuildTiccmd (ticcmd_t *cmd) { int i; boolean strafe, bstrafe; int speed, tspeed; int forward, side; ticcmd_t *base; base = I_BaseTiccmd (); // empty, or external driver memcpy (cmd,base,sizeof(*cmd)); cmd->consistancy = consistancy[consoleplayer][maketic%BACKUPTICS]; if (isCyberPresent) I_ReadCyberCmd (cmd); strafe = gamekeydown[key_strafe] || mousebuttons[mousebstrafe] || joybuttons[joybstrafe]; speed = gamekeydown[key_speed] || joybuttons[joybspeed]; forward = side = 0; // // use two stage accelerative turning on the keyboard and joystick // if (joyxmove < 0 || joyxmove > 0 || gamekeydown[key_right] || gamekeydown[key_left]) turnheld += ticdup; else turnheld = 0; if (turnheld < SLOWTURNTICS) tspeed = 2; // slow turn else tspeed = speed; // // let movement keys cancel each other out // if (strafe) { if (gamekeydown[key_right]) { // fprintf(stderr, "strafe right\n"); side += sidemove[speed]; } if (gamekeydown[key_left]) { // fprintf(stderr, "strafe left\n"); side -= sidemove[speed]; } if (joyxmove > 0) side += sidemove[speed]; if (joyxmove < 0) side -= sidemove[speed]; } else { if (gamekeydown[key_right]) cmd->angleturn -= angleturn[tspeed]; if (gamekeydown[key_left]) cmd->angleturn += angleturn[tspeed]; if (joyxmove > 0) cmd->angleturn -= angleturn[tspeed]; if (joyxmove < 0) cmd->angleturn += angleturn[tspeed]; } if (gamekeydown[key_up]) { // fprintf(stderr, "up\n"); forward += forwardmove[speed]; } if (gamekeydown[key_down]) { // fprintf(stderr, "down\n"); forward -= forwardmove[speed]; } if (joyymove < 0) forward += forwardmove[speed]; if (joyymove > 0) forward -= forwardmove[speed]; if (gamekeydown[key_straferight]) side += sidemove[speed]; if (gamekeydown[key_strafeleft]) side -= sidemove[speed]; // // buttons // cmd->chatchar = HU_dequeueChatChar(); if (gamekeydown[key_fire] || mousebuttons[mousebfire] || joybuttons[joybfire]) cmd->buttons |= BT_ATTACK; if (gamekeydown[key_use] || joybuttons[joybuse] ) { cmd->buttons |= BT_USE; dclicks = 0; // clear double clicks if hit use button } for (i=0 ; ibuttons |= BT_CHANGE; cmd->buttons |= i< 1 ) { dclickstate = mousebuttons[mousebforward]; if (dclickstate) dclicks++; if (dclicks == 2) { cmd->buttons |= BT_USE; dclicks = 0; } else dclicktime = 0; } else { dclicktime += ticdup; if (dclicktime > 20) { dclicks = 0; dclickstate = 0; } } // // strafe double click // bstrafe = mousebuttons[mousebstrafe] || joybuttons[joybstrafe]; if (bstrafe != dclickstate2 && dclicktime2 > 1 ) { dclickstate2 = bstrafe; if (dclickstate2) dclicks2++; if (dclicks2 == 2) { cmd->buttons |= BT_USE; dclicks2 = 0; } else dclicktime2 = 0; } else { dclicktime2 += ticdup; if (dclicktime2 > 20) { dclicks2 = 0; dclickstate2 = 0; } } forward += mousey; if (strafe) side += mousex*2; else cmd->angleturn -= mousex*0x8; mousex = mousey = 0; if (forward > MAXPLMOVE) forward = MAXPLMOVE; else if (forward < -MAXPLMOVE) forward = -MAXPLMOVE; if (side > MAXPLMOVE) side = MAXPLMOVE; else if (side < -MAXPLMOVE) side = -MAXPLMOVE; cmd->forwardmove += forward; cmd->sidemove += side; // // special buttons // if (sendpause) { sendpause = false; cmd->buttons = BT_SPECIAL | BTS_PAUSE; } if (sendsave) { sendsave = false; cmd->buttons = BT_SPECIAL | BTS_SAVEGAME | (savegameslot<type == ev_keydown && ev->data1 == KEY_F12 && (singledemo || !deathmatch) ) { // spy mode do { displayplayer++; if (displayplayer == MAXPLAYERS) displayplayer = 0; } while (!playeringame[displayplayer] && displayplayer != consoleplayer); return true; } // // any other key pops up menu if in demos // if (gameaction == ga_nothing && !singledemo && (demoplayback || gamestate == GS_DEMOSCREEN) ) { if (ev->type == ev_keydown || (ev->type == ev_mouse && ev->data1) || (ev->type == ev_joystick && ev->data1) ) { M_StartControlPanel (); return true; } return false; } if (gamestate == GS_LEVEL) { #if 0 if (devparm && ev->type == ev_keydown && ev->data1 == ';') { G_DeathMatchSpawnPlayer (0); return true; } #endif if (HU_Responder (ev)) return true; // chat ate the event if (ST_Responder (ev)) return true; // status window ate it if (AM_Responder (ev)) return true; // automap ate it } if (gamestate == GS_FINALE) { if (F_Responder (ev)) return true; // finale ate the event } switch (ev->type) { case ev_keydown: if (ev->data1 == KEY_PAUSE) { sendpause = true; return true; } if (ev->data1 data1] = true; return true; // eat key down events case ev_keyup: if (ev->data1 data1] = false; return false; // always let key up events filter down case ev_mouse: mousebuttons[0] = ev->data1 & 1; mousebuttons[1] = ev->data1 & 2; mousebuttons[2] = ev->data1 & 4; mousex = ev->data2*(mouseSensitivity+5)/10; mousey = ev->data3*(mouseSensitivity+5)/10; return true; // eat events case ev_joystick: joybuttons[0] = ev->data1 & 1; joybuttons[1] = ev->data1 & 2; joybuttons[2] = ev->data1 & 4; joybuttons[3] = ev->data1 & 8; joyxmove = ev->data2; joyymove = ev->data3; return true; // eat events default: break; } return false; } /* =============================================================================== = = G_Ticker = = Make ticcmd_ts for the players = =============================================================================== */ void G_Ticker (void) { int i, buf; ticcmd_t *cmd; // // do player reborns if needed // for (i=0 ; iforwardmove > TURBOTHRESHOLD && !(gametic&31) && ((gametic>>5)&3) == i ) { static char turbomessage[80]; extern char *player_names[4]; sprintf (turbomessage, "%s is turbo!",player_names[i]); players[consoleplayer].message = turbomessage; } if (netgame && !netdemo && !(gametic%ticdup) ) { if (gametic > BACKUPTICS && consistancy[i][buf] != cmd->consistancy) { I_Error ("consistency failure (%i should be %i)",cmd->consistancy, consistancy[i][buf]); } if (players[i].mo) consistancy[i][buf] = players[i].mo->x; else consistancy[i][buf] = rndindex; } } // // check for special buttons // for (i=0 ; i>BTS_SAVESHIFT; gameaction = ga_savegame; break; } } } // // do main actions // switch (gamestate) { case GS_LEVEL: P_Ticker (); ST_Ticker (); AM_Ticker (); HU_Ticker (); break; case GS_INTERMISSION: WI_Ticker (); break; case GS_FINALE: F_Ticker (); break; case GS_DEMOSCREEN: D_PageTicker (); break; } } /* ============================================================================== PLAYER STRUCTURE FUNCTIONS also see P_SpawnPlayer in P_Things ============================================================================== */ /* ==================== = = G_InitPlayer = = Called at the start = Called by the game initialization functions ==================== */ void G_InitPlayer (int player) { player_t *p; // set up the saved info p = &players[player]; // clear everything else to defaults G_PlayerReborn (player); } /* ==================== = = G_PlayerFinishLevel = = Can when a player completes a level ==================== */ void G_PlayerFinishLevel (int player) { player_t *p; p = &players[player]; memset (p->powers, 0, sizeof (p->powers)); memset (p->cards, 0, sizeof (p->cards)); p->mo->flags &= ~MF_SHADOW; // cancel invisibility p->extralight = 0; // cancel gun flashes p->fixedcolormap = 0; // cancel ir gogles p->damagecount = 0; // no palette changes p->bonuscount = 0; } /* ==================== = = G_PlayerReborn = = Called after a player dies = almost everything is cleared and initialized ==================== */ void G_PlayerReborn (int player) { player_t *p; int i; int frags[MAXPLAYERS]; int killcount, itemcount, secretcount; memcpy (frags,players[player].frags,sizeof(frags)); killcount = players[player].killcount; itemcount = players[player].itemcount; secretcount = players[player].secretcount; p = &players[player]; memset (p, 0, sizeof(*p)); memcpy (players[player].frags, frags, sizeof(players[player].frags)); players[player].killcount = killcount; players[player].itemcount = itemcount; players[player].secretcount = secretcount; p->usedown = p->attackdown = true; // don't do anything immediately p->playerstate = PST_LIVE; p->health = MAXHEALTH; p->readyweapon = p->pendingweapon = wp_pistol; p->weaponowned[wp_fist] = true; p->weaponowned[wp_pistol] = true; p->ammo[am_clip] = 50; for (i=0 ; imaxammo[i] = maxammo[i]; } /* ==================== = = G_CheckSpot = = Returns false if the player cannot be respawned at the given mapthing_t spot = because something is occupying it ==================== */ void P_SpawnPlayer (mapthing_t *mthing); boolean G_CheckSpot (int playernum, mapthing_t *mthing) { fixed_t x,y; subsector_t *ss; unsigned an; mobj_t *mo; int i; if (!players[playernum].mo) { // first spawn of level, before corpses for (i=0 ; ix == mthing->x << FRACBITS && players[i].mo->y == mthing->y << FRACBITS) return false; return true; } x = mthing->x << FRACBITS; y = mthing->y << FRACBITS; if (!P_CheckPosition (players[playernum].mo, x, y) ) return false; // flush an old corpse if needed if (bodyqueslot >= BODYQUESIZE) P_RemoveMobj (bodyque[bodyqueslot%BODYQUESIZE]); bodyque[bodyqueslot%BODYQUESIZE] = players[playernum].mo; bodyqueslot++; // spawn a teleport fog ss = R_PointInSubsector (x,y); an = ( ANG45 * (mthing->angle/45) ) >> ANGLETOFINESHIFT; mo = P_SpawnMobj (x+20*finecosine[an], y+20*finesine[an] , ss->sector->floorheight , MT_TFOG); if (players[consoleplayer].viewz != 1) S_StartSound (mo, sfx_telept); // don't start sound on first frame return true; } /* ==================== = = G_DeathMatchSpawnPlayer = = Spawns a player at one of the random death match spots = called at level load and each death ==================== */ void G_DeathMatchSpawnPlayer (int playernum) { int i,j; int selections; selections = deathmatch_p - deathmatchstarts; if (selections < 4) I_Error ("Only %i deathmatch spots, 4 required", selections); for (j=0 ; j<20 ; j++) { i = P_Random() % selections; if (G_CheckSpot (playernum, &deathmatchstarts[i]) ) { deathmatchstarts[i].type = playernum+1; P_SpawnPlayer (&deathmatchstarts[i]); return; } } // no good spot, so the player will probably get stuck P_SpawnPlayer (&playerstarts[playernum]); } /* ==================== = = G_DoReborn = ==================== */ void G_DoReborn (int playernum) { int i; if (!netgame) gameaction = ga_loadlevel; // reload the level from scratch else { // respawn at the start players[playernum].mo->player = NULL; // dissasociate the corpse // spawn at random spot if in death match if (deathmatch) { G_DeathMatchSpawnPlayer (playernum); return; } if (G_CheckSpot (playernum, &playerstarts[playernum]) ) { P_SpawnPlayer (&playerstarts[playernum]); return; } // try to spawn at one of the other players spots for (i=0 ; i>16; *save_p++ = leveltime>>8; *save_p++ = leveltime; P_ArchivePlayers (); P_ArchiveWorld (); P_ArchiveThinkers (); P_ArchiveSpecials (); *save_p++ = 0x1d; // consistancy marker length = save_p - savebuffer; if (length > SAVEGAMESIZE) I_Error ("Savegame buffer overrun"); M_WriteFile (name, savebuffer, length); gameaction = ga_nothing; savedescription[0] = 0; players[consoleplayer].message = GGSAVED; R_FillBackScreen (); // draw the pattern into the back screen } /* ==================== = = G_InitNew = = Can be called by the startup code or the menu task = consoleplayer, displayplayer, playeringame[] should be set ==================== */ skill_t d_skill; int d_episode; int d_map; void G_DeferedInitNew (skill_t skill, int episode, int map) { d_skill = skill; d_episode = episode; d_map = map; gameaction = ga_newgame; } void G_DoNewGame (void) { demoplayback = false; netdemo = false; netgame = false; deathmatch = false; playeringame[1] = playeringame[2] = playeringame[3] = 0; respawnparm = false; fastparm = false; nomonsters = false; consoleplayer = 0; G_InitNew (d_skill, d_episode, d_map); gameaction = ga_nothing; } extern int skytexture; void G_InitNew (skill_t skill, int episode, int map) { int i; if (paused) { paused = false; S_ResumeSound (); } if (skill > sk_nightmare) skill = sk_nightmare; if (episode < 1) episode = 1; if (episode > 3) episode = 3; if (episode > 1 && shareware) episode = 1; // only start episode 1 on shareware if (map < 1) map = 1; if (map > 9 && !commercial) map = 9; M_ClearRandom (); if (skill == sk_nightmare || respawnparm ) respawnmonsters = true; else respawnmonsters = false; if (fastparm || (skill == sk_nightmare && gameskill != sk_nightmare) ) { for (i=S_SARG_RUN1 ; i<=S_SARG_PAIN2 ; i++) states[i].tics >>= 1; mobjinfo[MT_BRUISERSHOT].speed = 20*FRACUNIT; mobjinfo[MT_HEADSHOT].speed = 20*FRACUNIT; mobjinfo[MT_TROOPSHOT].speed = 20*FRACUNIT; } else if (skill != sk_nightmare && gameskill == sk_nightmare) { for (i=S_SARG_RUN1 ; i<=S_SARG_PAIN2 ; i++) states[i].tics <<= 1; mobjinfo[MT_BRUISERSHOT].speed = 15*FRACUNIT; mobjinfo[MT_HEADSHOT].speed = 10*FRACUNIT; mobjinfo[MT_TROOPSHOT].speed = 10*FRACUNIT; } // force players to be initialized upon first level load for (i=0 ; iforwardmove = ((signed char)*demo_p++); cmd->sidemove = ((signed char)*demo_p++); cmd->angleturn = ((unsigned char)*demo_p++)<<8; cmd->buttons = (unsigned char)*demo_p++; } void G_WriteDemoTiccmd (ticcmd_t *cmd) { if (gamekeydown['q']) // press q to end demo recording G_CheckDemoStatus (); *demo_p++ = cmd->forwardmove; *demo_p++ = cmd->sidemove; *demo_p++ = (cmd->angleturn+128)>>8; *demo_p++ = cmd->buttons; demo_p -= 4; if (demo_p > demoend - 16) { // no more space G_CheckDemoStatus (); return; } G_ReadDemoTiccmd (cmd); // make SURE it is exactly the same } /* =================== = = G_RecordDemo = =================== */ void G_RecordDemo (char *name) { int i; int maxsize; usergame = false; strcpy (demoname, name); strcat (demoname, ".lmp"); maxsize = 0x20000; i = M_CheckParm ("-maxdemo"); if (i && i #include "doomdef.h" #include "hu_lib.h" #include "r_local.h" // boolean : whether the screen is always erased #define noterased viewwindowx extern boolean automapactive; // in AM_map.c void R_VideoErase(int y, int offset); void HUlib_init(void) { } void HUlib_clearTextLine(hu_textline_t *t) { t->len = 0; t->l[0] = 0; t->needsupdate = true; } void HUlib_initTextLine(hu_textline_t *t, int x, int y, patch_t **f, int sc) { t->x = x; t->y = y; t->f = f; t->sc = sc; HUlib_clearTextLine(t); } boolean HUlib_addCharToTextLine(hu_textline_t *t, char ch) { if (t->len == HU_MAXLINELENGTH) return false; else { t->l[t->len++] = ch; t->l[t->len] = 0; t->needsupdate = 4; return true; } } boolean HUlib_delCharFromTextLine(hu_textline_t *t) { if (!t->len) return false; else { t->l[--t->len] = 0; t->needsupdate = 4; return true; } } void HUlib_drawTextLine(hu_textline_t *l, boolean drawcursor) { int i, w, x; unsigned char c; // draw the new stuff x = l->x; for (i=0;ilen;i++) { c = toupper(l->l[i]); if (c != ' ' && c >= l->sc && c <= '_') { w = SHORT(l->f[c - l->sc]->width); if (x+w > SCREENWIDTH) break; V_DrawPatchDirect(x, l->y, FG, l->f[c - l->sc]); x += w; } else { x += 4; if (x >= SCREENWIDTH) break; } } // draw the cursor if requested if (drawcursor && x + SHORT(l->f['_' - l->sc]->width) <= SCREENWIDTH) V_DrawPatchDirect(x, l->y, FG, l->f['_' - l->sc]); } // sorta called by HU_Erase and just better darn get things straight void HUlib_eraseTextLine(hu_textline_t *l) { int lh, y, yoffset; static boolean lastautomapactive = true; // only erases when NOT in automap and the screen is reduced. // and the text must either need updating or refreshing (because of // a recent change back from the automap) if (!automapactive && viewwindowx && l->needsupdate) { lh = SHORT(l->f[0]->height) + 1; for (y=l->y,yoffset=y*SCREENWIDTH ; yy+lh ; y++,yoffset+=SCREENWIDTH) { if (y < viewwindowy || y >= viewwindowy + viewheight) R_VideoErase(yoffset, SCREENWIDTH); // erase entire line else { R_VideoErase(yoffset, viewwindowx); // erase left border R_VideoErase(yoffset + viewwindowx + viewwidth, viewwindowx); // erase right border } } } lastautomapactive = automapactive; if (l->needsupdate) l->needsupdate--; } void HUlib_initSText(hu_stext_t *s, int x, int y, int h, patch_t **font, int startchar, boolean *on) { int i; s->h = h; s->on = on; s->laston = true; s->cl = 0; for (i=0;il[i], x, y - i*(SHORT(font[0]->height)+1), font, startchar); } void HUlib_addLineToSText(hu_stext_t *s) { int i; // add a clear line if (++s->cl == s->h) s->cl = 0; HUlib_clearTextLine(&s->l[s->cl]); // everything needs updating for (i=0 ; ih ; i++) s->l[i].needsupdate = 4; } void HUlib_addMessageToSText(hu_stext_t *s, char *prefix, char *msg) { HUlib_addLineToSText(s); if (prefix) while (*prefix) HUlib_addCharToTextLine(&s->l[s->cl], *(prefix++)); while (*msg) HUlib_addCharToTextLine(&s->l[s->cl], *(msg++)); } void HUlib_drawSText(hu_stext_t *s) { int i, idx; hu_textline_t *l; if (!*s->on) return; // if not on, don't draw // draw everything for (i=0 ; ih ; i++) { idx = s->cl - i; if (idx < 0) idx += s->h; // handle queue of lines l = &s->l[idx]; // need a decision made here on whether to skip the draw HUlib_drawTextLine(l, false); // no cursor, please } } void HUlib_eraseSText(hu_stext_t *s) { int i; for (i=0 ; ih ; i++) { if (s->laston && !*s->on) s->l[i].needsupdate = 4; HUlib_eraseTextLine(&s->l[i]); } s->laston = *s->on; } void HUlib_initIText(hu_itext_t *it, int x, int y, patch_t **font, int startchar, boolean *on) { it->lm = 0; // default left margin is start of text it->on = on; it->laston = true; HUlib_initTextLine(&it->l, x, y, font, startchar); } // The following deletion routines adhere to the left margin restriction void HUlib_delCharFromIText(hu_itext_t *it) { if (it->l.len != it->lm) HUlib_delCharFromTextLine(&it->l); } void HUlib_eraseLineFromIText(hu_itext_t *it) { while (it->lm != it->l.len) HUlib_delCharFromTextLine(&it->l); } // Resets left margin as well void HUlib_resetIText(hu_itext_t *it) { it->lm = 0; HUlib_clearTextLine(&it->l); } void HUlib_addPrefixToIText(hu_itext_t *it, char *str) { while (*str) HUlib_addCharToTextLine(&it->l, *(str++)); it->lm = it->l.len; } // wrapper function for handling general keyed input. // returns true if it ate the key boolean HUlib_keyInIText(hu_itext_t *it, unsigned char ch) { if (ch >= ' ' && ch <= '_') HUlib_addCharToTextLine(&it->l, (char) ch); else if (ch == KEY_BACKSPACE) HUlib_delCharFromIText(it); else if (ch != KEY_ENTER) return false; // did not eat key return true; // ate the key } void HUlib_drawIText(hu_itext_t *it) { hu_textline_t *l = &it->l; if (!*it->on) return; HUlib_drawTextLine(l, true); // draw the line w/ cursor } void HUlib_eraseIText(hu_itext_t *it) { if (it->laston && !*it->on) it->l.needsupdate = 4; HUlib_eraseTextLine(&it->l); it->laston = *it->on; } \ No newline at end of file diff --git a/HU_LIB.H b/HU_LIB.H new file mode 100644 index 0000000..2ff4389 --- /dev/null +++ b/HU_LIB.H @@ -0,0 +1 @@ +#ifndef __HULIB__ #define __HULIB__ // background and foreground screen numbers #define BG 1 #define FG 0 // font stuff #define HU_CHARERASE KEY_BACKSPACE #define HU_MAXLINES 4 #define HU_MAXLINELENGTH 80 /* * Typedefs of widgets */ // Text Line widget (parent of Scrolling Text and Input Text widgets) typedef struct { int x, y; // left-justified position of scrolling text window patch_t **f;// font int sc; // start character char l[HU_MAXLINELENGTH+1]; // line of text int len; // current line length int needsupdate; // whether this line needs to be udpated } hu_textline_t; // Scrolling Text window widget (child of Text Line widget) typedef struct { hu_textline_t l[HU_MAXLINES]; // text lines to draw int h; // height in lines int cl; // current line number boolean *on;// pointer to boolean stating whether to update window boolean laston; // last value of *->on. } hu_stext_t; // Input Text Line widget (child of Text Line widget) typedef struct { hu_textline_t l; // text line to input on int lm; // left margin past which I am not to delete characters boolean *on;// pointer to boolean stating whether to update window boolean laston; // last value of *->on; } hu_itext_t; /* * Widget creation, access, and update routines */ // initializes heads-up widget library void HUlib_init(void); // textline code void HUlib_clearTextLine(hu_textline_t *t); // clear a line of text void HUlib_initTextLine(hu_textline_t *t, int x, int y, patch_t **f, int sc); boolean HUlib_addCharToTextLine(hu_textline_t *t, char ch); // returns success boolean HUlib_delCharFromTextLine(hu_textline_t *t); // returns success void HUlib_drawTextLine(hu_textline_t *l, boolean drawcursor); // draws tline void HUlib_eraseTextLine(hu_textline_t *l); // erases text line // Scrolling Text window widget routines void HUlib_initSText(hu_stext_t *s, int x, int y, int h, patch_t **font, int startchar, boolean *on); void HUlib_addLineToSText(hu_stext_t *s); // add a new line void HUlib_addMessageToSText(hu_stext_t *s, char *prefix, char *msg); void HUlib_drawSText(hu_stext_t *s); // draws stext void HUlib_eraseSText(hu_stext_t *s); // erases all stext lines // Input Text Line widget routines void HUlib_initIText(hu_itext_t *it, int x, int y, patch_t **font, int startchar, boolean *on); void HUlib_delCharFromIText(hu_itext_t *it); // enforces left margin void HUlib_eraseLineFromIText(hu_itext_t *it); // enforces left margin void HUlib_resetIText(hu_itext_t *it); // resets line and left margin void HUlib_addPrefixToIText(hu_itext_t *it, char *str); // left of left-margin boolean HUlib_keyInIText(hu_itext_t *it, unsigned char ch); // whether eaten void HUlib_drawIText(hu_itext_t *it); void HUlib_eraseIText(hu_itext_t *it); // erases all itext lines #endif \ No newline at end of file diff --git a/HU_STUFF.C b/HU_STUFF.C new file mode 100644 index 0000000..0de3ced --- /dev/null +++ b/HU_STUFF.C @@ -0,0 +1 @@ +// // Heads-up displays // #include #include "doomdef.h" #include "hu_stuff.h" #include "hu_lib.h" char *chat_macros[] = { HUSTR_CHATMACRO0, HUSTR_CHATMACRO1, HUSTR_CHATMACRO2, HUSTR_CHATMACRO3, HUSTR_CHATMACRO4, HUSTR_CHATMACRO5, HUSTR_CHATMACRO6, HUSTR_CHATMACRO7, HUSTR_CHATMACRO8, HUSTR_CHATMACRO9 }; char *player_names[] = { HUSTR_PLRGREEN, HUSTR_PLRINDIGO, HUSTR_PLRBROWN, HUSTR_PLRRED }; char chat_char; // remove later. static player_t *plr; patch_t *hu_font[HU_FONTSIZE]; static hu_textline_t w_title; boolean chat_on; static hu_itext_t w_chat; static boolean always_off = false; static char chat_dest[MAXPLAYERS]; static hu_itext_t w_inputbuffer[MAXPLAYERS]; static boolean message_on; boolean message_dontfuckwithme; static boolean message_nottobefuckedwith; static hu_stext_t w_message; static int message_counter; extern int showMessages; extern boolean automapactive; static boolean headsupactive = false; // the actual names can be found in DStrings.h char *mapnames[] = { HUSTR_E1M1, HUSTR_E1M2, HUSTR_E1M3, HUSTR_E1M4, HUSTR_E1M5, HUSTR_E1M6, HUSTR_E1M7, HUSTR_E1M8, HUSTR_E1M9, HUSTR_E2M1, HUSTR_E2M2, HUSTR_E2M3, HUSTR_E2M4, HUSTR_E2M5, HUSTR_E2M6, HUSTR_E2M7, HUSTR_E2M8, HUSTR_E2M9, HUSTR_E3M1, HUSTR_E3M2, HUSTR_E3M3, HUSTR_E3M4, HUSTR_E3M5, HUSTR_E3M6, HUSTR_E3M7, HUSTR_E3M8, HUSTR_E3M9, "NEWLEVEL", "NEWLEVEL", "NEWLEVEL", "NEWLEVEL", "NEWLEVEL", "NEWLEVEL", "NEWLEVEL", "NEWLEVEL", "NEWLEVEL", "NEWLEVEL", "NEWLEVEL", "NEWLEVEL", "NEWLEVEL", "NEWLEVEL", "NEWLEVEL", "NEWLEVEL", "NEWLEVEL", "NEWLEVEL", "NEWLEVEL" }; char *mapnames2[] = { HUSTR_1, HUSTR_2, HUSTR_3, HUSTR_4, HUSTR_5, HUSTR_6, HUSTR_7, HUSTR_8, HUSTR_9, HUSTR_10, HUSTR_11, HUSTR_12, HUSTR_13, HUSTR_14, HUSTR_15, HUSTR_16, HUSTR_17, HUSTR_18, HUSTR_19, HUSTR_20, HUSTR_21, HUSTR_22, HUSTR_23, HUSTR_24, HUSTR_25, HUSTR_26, HUSTR_27, HUSTR_28, HUSTR_29, HUSTR_30, HUSTR_31, HUSTR_32 }; char *shiftxform; const char french_shiftxform[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, ' ', '!', '"', '#', '$', '%', '&', '"', // shift-' '(', ')', '*', '+', '?', // shift-, '_', // shift-- '>', // shift-. '?', // shift-/ '0', // shift-0 '1', // shift-1 '2', // shift-2 '3', // shift-3 '4', // shift-4 '5', // shift-5 '6', // shift-6 '7', // shift-7 '8', // shift-8 '9', // shift-9 '/', '.', // shift-; '<', '+', // shift-= '>', '?', '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', // shift-[ '!', // shift-backslash - OH MY GOD DOES WATCOM SUCK ']', // shift-] '"', '_', '\'', // shift-` 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '{', '|', '}', '~', 127 }; const char english_shiftxform[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, ' ', '!', '"', '#', '$', '%', '&', '"', // shift-' '(', ')', '*', '+', '<', // shift-, '_', // shift-- '>', // shift-. '?', // shift-/ ')', // shift-0 '!', // shift-1 '@', // shift-2 '#', // shift-3 '$', // shift-4 '%', // shift-5 '^', // shift-6 '&', // shift-7 '*', // shift-8 '(', // shift-9 ':', ':', // shift-; '<', '+', // shift-= '>', '?', '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', // shift-[ '!', // shift-backslash - OH MY GOD DOES WATCOM SUCK ']', // shift-] '"', '_', '\'', // shift-` 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '{', '|', '}', '~', 127 }; char frenchKeyMap[128]= { 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24, 25,26,27,28,29,30,31, ' ','!','"','#','$','%','&','%','(',')','*','+',';','-',':','!', '0','1','2','3','4','5','6','7','8','9',':','M','<','=','>','?', '@','Q','B','C','D','E','F','G','H','I','J','K','L',',','N','O', 'P','A','R','S','T','U','V','Z','X','Y','W','^','\\','$','^','_', '@','Q','B','C','D','E','F','G','H','I','J','K','L',',','N','O', 'P','A','R','S','T','U','V','Z','X','Y','W','^','\\','$','^',127 }; char ForeignTranslation(unsigned char ch) { return ch < 128 ? frenchKeyMap[ch] : ch; } void HU_Init(void) { int i, j; char buffer[9]; if (french) shiftxform = french_shiftxform; else shiftxform = english_shiftxform; // load the heads-up font j = HU_FONTSTART; for (i=0;imessage && !message_nottobefuckedwith) || (plr->message && message_dontfuckwithme)) { HUlib_addMessageToSText(&w_message, 0, plr->message); plr->message = 0; message_on = true; message_counter = HU_MSGTIMEOUT; message_nottobefuckedwith = message_dontfuckwithme; message_dontfuckwithme = 0; } } // else message_on = false; // check for incoming chat characters if (netgame) { for (i=0 ; i= 'a' && c <= 'z') c = (char) shiftxform[(unsigned char) c]; rc = HUlib_keyInIText(&w_inputbuffer[i], c); if (rc && c == KEY_ENTER) { if (w_inputbuffer[i].l.len && (chat_dest[i] == consoleplayer+1 || chat_dest[i] == HU_BROADCAST)) { HUlib_addMessageToSText(&w_message, player_names[i], w_inputbuffer[i].l.l); message_nottobefuckedwith = true; message_on = true; message_counter = HU_MSGTIMEOUT; commercial ? S_StartSound(0, sfx_radio): S_StartSound(0, sfx_tink); } HUlib_resetIText(&w_inputbuffer[i]); } } players[i].cmd.chatchar = 0; } } } } #define QUEUESIZE 128 static char chatchars[QUEUESIZE]; static int head = 0, tail = 0; void HU_queueChatChar(char c) { if (((head + 1) & (QUEUESIZE-1)) == tail) { plr->message = HUSTR_MSGU; } else { chatchars[head] = c; head = (head + 1) & (QUEUESIZE-1); } } char HU_dequeueChatChar(void) { char c; if (head != tail) { c = chatchars[tail]; tail = (tail + 1) & (QUEUESIZE-1); } else { c = 0; } return c; } boolean HU_Responder(event_t *ev) { static char lastmessage[HU_MAXLINELENGTH+1]; char *macromessage; boolean eatkey = false; static boolean shiftdown = false; static boolean altdown = false; unsigned char c; int i, numplayers; static char destination_keys[MAXPLAYERS] = { HUSTR_KEYGREEN, HUSTR_KEYINDIGO, HUSTR_KEYBROWN, HUSTR_KEYRED }; static int num_nobrainers = 0; numplayers = 0; for (i=0 ; idata1 == KEY_RSHIFT) { shiftdown = ev->type == ev_keydown; return false; } else if (ev->data1 == KEY_RALT || ev->data1 == KEY_LALT) { altdown = ev->type == ev_keydown; return false; } if (ev->type != ev_keydown) return false; if (!chat_on) { if (ev->data1 == HU_MSGREFRESH) { message_on = true; message_counter = HU_MSGTIMEOUT; eatkey = true; } else if (netgame && ev->data1 == HU_INPUTTOGGLE) { eatkey = chat_on = true; HUlib_resetIText(&w_chat); HU_queueChatChar(HU_BROADCAST); } else if (netgame && numplayers > 2) { for (i=0; idata1 == destination_keys[i]) { if (playeringame[i] && i!=consoleplayer) { eatkey = chat_on = true; HUlib_resetIText(&w_chat); HU_queueChatChar(i+1); break; } else if (i == consoleplayer) { num_nobrainers++; if (num_nobrainers < 3) plr->message = HUSTR_TALKTOSELF1; else if (num_nobrainers < 6) plr->message = HUSTR_TALKTOSELF2; else if (num_nobrainers < 9) plr->message = HUSTR_TALKTOSELF3; else if (num_nobrainers < 32) plr->message = HUSTR_TALKTOSELF4; else plr->message = HUSTR_TALKTOSELF5; } } } } } else { c = ev->data1; // send a macro if (altdown) { c = c - '0'; if (c > 9) return false; // fprintf(stderr, "got here\n"); macromessage = chat_macros[c]; // kill last message with a '\n' HU_queueChatChar(KEY_ENTER); // DEBUG!!! // send the macro message while (*macromessage) HU_queueChatChar(*macromessage++); HU_queueChatChar(KEY_ENTER); // leave chat mode and notify that it was sent chat_on = false; strcpy(lastmessage, chat_macros[c]); plr->message = lastmessage; eatkey = true; } else { if (french) c = ForeignTranslation(c); if (shiftdown || (c >= 'a' && c <= 'z')) c = shiftxform[c]; eatkey = HUlib_keyInIText(&w_chat, c); if (eatkey) { // static unsigned char buf[20]; // DEBUG HU_queueChatChar(c); // sprintf(buf, "KEY: %d => %d", ev->data1, c); // plr->message = buf; } if (c == KEY_ENTER) { chat_on = false; if (w_chat.l.len) { strcpy(lastmessage, w_chat.l.l); plr->message = lastmessage; } } else if (c == KEY_ESCAPE) chat_on = false; } } return eatkey; } \ No newline at end of file diff --git a/HU_STUFF.H b/HU_STUFF.H new file mode 100644 index 0000000..bd0a59a --- /dev/null +++ b/HU_STUFF.H @@ -0,0 +1 @@ +#ifndef __HU_STUFF_H__ #define __HU_STUFF_H__ #define HU_FONTSTART '!' // the first font characters #define HU_FONTEND '_' // the last font characters #define HU_FONTSIZE (HU_FONTEND - HU_FONTSTART + 1) // # of glyphs in font #define HU_BROADCAST 5 #define HU_MSGREFRESH KEY_ENTER #define HU_MSGX 0 #define HU_MSGY 0 #define HU_MSGWIDTH 64 // in characters #define HU_MSGHEIGHT 1 // in lines #define HU_MSGTIMEOUT (4*TICRATE) #define HU_TITLE (mapnames[(gameepisode-1)*9+gamemap-1]) #define HU_TITLE2 (mapnames2[gamemap-1]) #define HU_TITLEHEIGHT 1 #define HU_TITLEX 0 #define HU_TITLEY (167 - SHORT(hu_font[0]->height)) #define HU_INPUTTOGGLE 't' #define HU_INPUTX HU_MSGX #define HU_INPUTY (HU_MSGY + HU_MSGHEIGHT*(SHORT(hu_font[0]->height) + 1)) #define HU_INPUTWIDTH 64 #define HU_INPUTHEIGHT 1 #endif \ No newline at end of file diff --git a/INFO.C b/INFO.C new file mode 100644 index 0000000..2f24bfb --- /dev/null +++ b/INFO.C @@ -0,0 +1 @@ +#include "doomdef.h" // generated by multigen char *sprnames[NUMSPRITES] = { "TROO","SHTG","PUNG","PISG","PISF","SHTF","SHT2","CHGG","CHGF","MISG", "MISF","SAWG","PLSG","PLSF","BFGG","BFGF","BLUD","PUFF","BAL1","BAL2", "PLSS","PLSE","MISL","BFS1","BFE1","BFE2","TFOG","IFOG","PLAY","POSS", "SPOS","VILE","FIRE","FATB","FBXP","SKEL","MANF","FATT","CPOS","SARG", "HEAD","BAL7","BOSS","BOS2","SKUL","SPID","BSPI","APLS","APBX","CYBR", "PAIN","SSWV","KEEN","BBRN","BOSF","ARM1","ARM2","BAR1","BEXP","FCAN", "BON1","BON2","BKEY","RKEY","YKEY","BSKU","RSKU","YSKU","STIM","MEDI", "SOUL","PINV","PSTR","PINS","MEGA","SUIT","PMAP","PVIS","CLIP","AMMO", "ROCK","BROK","CELL","CELP","SHEL","SBOX","BPAK","BFUG","MGUN","CSAW", "LAUN","PLAS","SHOT","SGN2","COLU","SMT2","GOR1","POL2","POL5","POL4", "POL3","POL1","POL6","GOR2","GOR3","GOR4","GOR5","SMIT","COL1","COL2", "COL3","COL4","CAND","CBRA","COL6","TRE1","TRE2","ELEC","CEYE","FSKU", "COL5","TBLU","TGRN","TRED","SMBT","SMGT","SMRT","HDB1","HDB2","HDB3", "HDB4","HDB5","HDB6","POB1","POB2","BRS1","TLMP","TLP2" }; void A_Light0 (); void A_WeaponReady (); void A_Lower (); void A_Raise (); void A_Punch (); void A_ReFire (); void A_FirePistol (); void A_Light1 (); void A_FireShotgun (); void A_Light2 (); void A_FireShotgun2 (); void A_CheckReload (); void A_OpenShotgun2 (); void A_LoadShotgun2 (); void A_CloseShotgun2 (); void A_FireCGun (); void A_GunFlash (); void A_FireMissile (); void A_Saw (); void A_FirePlasma (); void A_BFGsound (); void A_FireBFG (); void A_BFGSpray (); void A_Explode (); void A_Pain (); void A_PlayerScream (); void A_Fall (); void A_XScream (); void A_Look (); void A_Chase (); void A_FaceTarget (); void A_PosAttack (); void A_Scream (); void A_SPosAttack (); void A_VileChase (); void A_VileStart (); void A_VileTarget (); void A_VileAttack (); void A_StartFire (); void A_Fire (); void A_FireCrackle (); void A_Tracer (); void A_SkelWhoosh (); void A_SkelFist (); void A_SkelMissile (); void A_FatRaise (); void A_FatAttack1 (); void A_FatAttack2 (); void A_FatAttack3 (); void A_BossDeath (); void A_CPosAttack (); void A_CPosRefire (); void A_TroopAttack (); void A_SargAttack (); void A_HeadAttack (); void A_BruisAttack (); void A_SkullAttack (); void A_Metal (); void A_SpidRefire (); void A_BabyMetal (); void A_BspiAttack (); void A_Hoof (); void A_CyberAttack (); void A_PainAttack (); void A_PainDie (); void A_KeenDie (); void A_BrainPain (); void A_BrainScream (); void A_BrainDie (); void A_BrainAwake (); void A_BrainSpit (); void A_SpawnSound (); void A_SpawnFly (); void A_BrainExplode (); state_t states[NUMSTATES] = { {SPR_TROO,0,-1,NULL,S_NULL,0,0}, // S_NULL {SPR_SHTG,4,0,A_Light0,S_NULL,0,0}, // S_LIGHTDONE {SPR_PUNG,0,1,A_WeaponReady,S_PUNCH,0,0}, // S_PUNCH {SPR_PUNG,0,1,A_Lower,S_PUNCHDOWN,0,0}, // S_PUNCHDOWN {SPR_PUNG,0,1,A_Raise,S_PUNCHUP,0,0}, // S_PUNCHUP {SPR_PUNG,1,4,NULL,S_PUNCH2,0,0}, // S_PUNCH1 {SPR_PUNG,2,4,A_Punch,S_PUNCH3,0,0}, // S_PUNCH2 {SPR_PUNG,3,5,NULL,S_PUNCH4,0,0}, // S_PUNCH3 {SPR_PUNG,2,4,NULL,S_PUNCH5,0,0}, // S_PUNCH4 {SPR_PUNG,1,5,A_ReFire,S_PUNCH,0,0}, // S_PUNCH5 {SPR_PISG,0,1,A_WeaponReady,S_PISTOL,0,0}, // S_PISTOL {SPR_PISG,0,1,A_Lower,S_PISTOLDOWN,0,0}, // S_PISTOLDOWN {SPR_PISG,0,1,A_Raise,S_PISTOLUP,0,0}, // S_PISTOLUP {SPR_PISG,0,4,NULL,S_PISTOL2,0,0}, // S_PISTOL1 {SPR_PISG,1,6,A_FirePistol,S_PISTOL3,0,0}, // S_PISTOL2 {SPR_PISG,2,4,NULL,S_PISTOL4,0,0}, // S_PISTOL3 {SPR_PISG,1,5,A_ReFire,S_PISTOL,0,0}, // S_PISTOL4 {SPR_PISF,32768,7,A_Light1,S_LIGHTDONE,0,0}, // S_PISTOLFLASH {SPR_SHTG,0,1,A_WeaponReady,S_SGUN,0,0}, // S_SGUN {SPR_SHTG,0,1,A_Lower,S_SGUNDOWN,0,0}, // S_SGUNDOWN {SPR_SHTG,0,1,A_Raise,S_SGUNUP,0,0}, // S_SGUNUP {SPR_SHTG,0,3,NULL,S_SGUN2,0,0}, // S_SGUN1 {SPR_SHTG,0,7,A_FireShotgun,S_SGUN3,0,0}, // S_SGUN2 {SPR_SHTG,1,5,NULL,S_SGUN4,0,0}, // S_SGUN3 {SPR_SHTG,2,5,NULL,S_SGUN5,0,0}, // S_SGUN4 {SPR_SHTG,3,4,NULL,S_SGUN6,0,0}, // S_SGUN5 {SPR_SHTG,2,5,NULL,S_SGUN7,0,0}, // S_SGUN6 {SPR_SHTG,1,5,NULL,S_SGUN8,0,0}, // S_SGUN7 {SPR_SHTG,0,3,NULL,S_SGUN9,0,0}, // S_SGUN8 {SPR_SHTG,0,7,A_ReFire,S_SGUN,0,0}, // S_SGUN9 {SPR_SHTF,32768,4,A_Light1,S_SGUNFLASH2,0,0}, // S_SGUNFLASH1 {SPR_SHTF,32769,3,A_Light2,S_LIGHTDONE,0,0}, // S_SGUNFLASH2 {SPR_SHT2,0,1,A_WeaponReady,S_DSGUN,0,0}, // S_DSGUN {SPR_SHT2,0,1,A_Lower,S_DSGUNDOWN,0,0}, // S_DSGUNDOWN {SPR_SHT2,0,1,A_Raise,S_DSGUNUP,0,0}, // S_DSGUNUP {SPR_SHT2,0,3,NULL,S_DSGUN2,0,0}, // S_DSGUN1 {SPR_SHT2,0,7,A_FireShotgun2,S_DSGUN3,0,0}, // S_DSGUN2 {SPR_SHT2,1,7,NULL,S_DSGUN4,0,0}, // S_DSGUN3 {SPR_SHT2,2,7,A_CheckReload,S_DSGUN5,0,0}, // S_DSGUN4 {SPR_SHT2,3,7,A_OpenShotgun2,S_DSGUN6,0,0}, // S_DSGUN5 {SPR_SHT2,4,7,NULL,S_DSGUN7,0,0}, // S_DSGUN6 {SPR_SHT2,5,7,A_LoadShotgun2,S_DSGUN8,0,0}, // S_DSGUN7 {SPR_SHT2,6,6,NULL,S_DSGUN9,0,0}, // S_DSGUN8 {SPR_SHT2,7,6,A_CloseShotgun2,S_DSGUN10,0,0}, // S_DSGUN9 {SPR_SHT2,0,5,A_ReFire,S_DSGUN,0,0}, // S_DSGUN10 {SPR_SHT2,1,7,NULL,S_DSNR2,0,0}, // S_DSNR1 {SPR_SHT2,0,3,NULL,S_DSGUNDOWN,0,0}, // S_DSNR2 {SPR_SHT2,32776,5,A_Light1,S_DSGUNFLASH2,0,0}, // S_DSGUNFLASH1 {SPR_SHT2,32777,4,A_Light2,S_LIGHTDONE,0,0}, // S_DSGUNFLASH2 {SPR_CHGG,0,1,A_WeaponReady,S_CHAIN,0,0}, // S_CHAIN {SPR_CHGG,0,1,A_Lower,S_CHAINDOWN,0,0}, // S_CHAINDOWN {SPR_CHGG,0,1,A_Raise,S_CHAINUP,0,0}, // S_CHAINUP {SPR_CHGG,0,4,A_FireCGun,S_CHAIN2,0,0}, // S_CHAIN1 {SPR_CHGG,1,4,A_FireCGun,S_CHAIN3,0,0}, // S_CHAIN2 {SPR_CHGG,1,0,A_ReFire,S_CHAIN,0,0}, // S_CHAIN3 {SPR_CHGF,32768,5,A_Light1,S_LIGHTDONE,0,0}, // S_CHAINFLASH1 {SPR_CHGF,32769,5,A_Light2,S_LIGHTDONE,0,0}, // S_CHAINFLASH2 {SPR_MISG,0,1,A_WeaponReady,S_MISSILE,0,0}, // S_MISSILE {SPR_MISG,0,1,A_Lower,S_MISSILEDOWN,0,0}, // S_MISSILEDOWN {SPR_MISG,0,1,A_Raise,S_MISSILEUP,0,0}, // S_MISSILEUP {SPR_MISG,1,8,A_GunFlash,S_MISSILE2,0,0}, // S_MISSILE1 {SPR_MISG,1,12,A_FireMissile,S_MISSILE3,0,0}, // S_MISSILE2 {SPR_MISG,1,0,A_ReFire,S_MISSILE,0,0}, // S_MISSILE3 {SPR_MISF,32768,3,A_Light1,S_MISSILEFLASH2,0,0}, // S_MISSILEFLASH1 {SPR_MISF,32769,4,NULL,S_MISSILEFLASH3,0,0}, // S_MISSILEFLASH2 {SPR_MISF,32770,4,A_Light2,S_MISSILEFLASH4,0,0}, // S_MISSILEFLASH3 {SPR_MISF,32771,4,A_Light2,S_LIGHTDONE,0,0}, // S_MISSILEFLASH4 {SPR_SAWG,2,4,A_WeaponReady,S_SAWB,0,0}, // S_SAW {SPR_SAWG,3,4,A_WeaponReady,S_SAW,0,0}, // S_SAWB {SPR_SAWG,2,1,A_Lower,S_SAWDOWN,0,0}, // S_SAWDOWN {SPR_SAWG,2,1,A_Raise,S_SAWUP,0,0}, // S_SAWUP {SPR_SAWG,0,4,A_Saw,S_SAW2,0,0}, // S_SAW1 {SPR_SAWG,1,4,A_Saw,S_SAW3,0,0}, // S_SAW2 {SPR_SAWG,1,0,A_ReFire,S_SAW,0,0}, // S_SAW3 {SPR_PLSG,0,1,A_WeaponReady,S_PLASMA,0,0}, // S_PLASMA {SPR_PLSG,0,1,A_Lower,S_PLASMADOWN,0,0}, // S_PLASMADOWN {SPR_PLSG,0,1,A_Raise,S_PLASMAUP,0,0}, // S_PLASMAUP {SPR_PLSG,0,3,A_FirePlasma,S_PLASMA2,0,0}, // S_PLASMA1 {SPR_PLSG,1,20,A_ReFire,S_PLASMA,0,0}, // S_PLASMA2 {SPR_PLSF,32768,4,A_Light1,S_LIGHTDONE,0,0}, // S_PLASMAFLASH1 {SPR_PLSF,32769,4,A_Light1,S_LIGHTDONE,0,0}, // S_PLASMAFLASH2 {SPR_BFGG,0,1,A_WeaponReady,S_BFG,0,0}, // S_BFG {SPR_BFGG,0,1,A_Lower,S_BFGDOWN,0,0}, // S_BFGDOWN {SPR_BFGG,0,1,A_Raise,S_BFGUP,0,0}, // S_BFGUP {SPR_BFGG,0,20,A_BFGsound,S_BFG2,0,0}, // S_BFG1 {SPR_BFGG,1,10,A_GunFlash,S_BFG3,0,0}, // S_BFG2 {SPR_BFGG,1,10,A_FireBFG,S_BFG4,0,0}, // S_BFG3 {SPR_BFGG,1,20,A_ReFire,S_BFG,0,0}, // S_BFG4 {SPR_BFGF,32768,11,A_Light1,S_BFGFLASH2,0,0}, // S_BFGFLASH1 {SPR_BFGF,32769,6,A_Light2,S_LIGHTDONE,0,0}, // S_BFGFLASH2 {SPR_BLUD,2,8,NULL,S_BLOOD2,0,0}, // S_BLOOD1 {SPR_BLUD,1,8,NULL,S_BLOOD3,0,0}, // S_BLOOD2 {SPR_BLUD,0,8,NULL,S_NULL,0,0}, // S_BLOOD3 {SPR_PUFF,32768,4,NULL,S_PUFF2,0,0}, // S_PUFF1 {SPR_PUFF,1,4,NULL,S_PUFF3,0,0}, // S_PUFF2 {SPR_PUFF,2,4,NULL,S_PUFF4,0,0}, // S_PUFF3 {SPR_PUFF,3,4,NULL,S_NULL,0,0}, // S_PUFF4 {SPR_BAL1,32768,4,NULL,S_TBALL2,0,0}, // S_TBALL1 {SPR_BAL1,32769,4,NULL,S_TBALL1,0,0}, // S_TBALL2 {SPR_BAL1,32770,6,NULL,S_TBALLX2,0,0}, // S_TBALLX1 {SPR_BAL1,32771,6,NULL,S_TBALLX3,0,0}, // S_TBALLX2 {SPR_BAL1,32772,6,NULL,S_NULL,0,0}, // S_TBALLX3 {SPR_BAL2,32768,4,NULL,S_RBALL2,0,0}, // S_RBALL1 {SPR_BAL2,32769,4,NULL,S_RBALL1,0,0}, // S_RBALL2 {SPR_BAL2,32770,6,NULL,S_RBALLX2,0,0}, // S_RBALLX1 {SPR_BAL2,32771,6,NULL,S_RBALLX3,0,0}, // S_RBALLX2 {SPR_BAL2,32772,6,NULL,S_NULL,0,0}, // S_RBALLX3 {SPR_PLSS,32768,6,NULL,S_PLASBALL2,0,0}, // S_PLASBALL {SPR_PLSS,32769,6,NULL,S_PLASBALL,0,0}, // S_PLASBALL2 {SPR_PLSE,32768,4,NULL,S_PLASEXP2,0,0}, // S_PLASEXP {SPR_PLSE,32769,4,NULL,S_PLASEXP3,0,0}, // S_PLASEXP2 {SPR_PLSE,32770,4,NULL,S_PLASEXP4,0,0}, // S_PLASEXP3 {SPR_PLSE,32771,4,NULL,S_PLASEXP5,0,0}, // S_PLASEXP4 {SPR_PLSE,32772,4,NULL,S_NULL,0,0}, // S_PLASEXP5 {SPR_MISL,32768,1,NULL,S_ROCKET,0,0}, // S_ROCKET {SPR_BFS1,32768,4,NULL,S_BFGSHOT2,0,0}, // S_BFGSHOT {SPR_BFS1,32769,4,NULL,S_BFGSHOT,0,0}, // S_BFGSHOT2 {SPR_BFE1,32768,8,NULL,S_BFGLAND2,0,0}, // S_BFGLAND {SPR_BFE1,32769,8,NULL,S_BFGLAND3,0,0}, // S_BFGLAND2 {SPR_BFE1,32770,8,A_BFGSpray,S_BFGLAND4,0,0}, // S_BFGLAND3 {SPR_BFE1,32771,8,NULL,S_BFGLAND5,0,0}, // S_BFGLAND4 {SPR_BFE1,32772,8,NULL,S_BFGLAND6,0,0}, // S_BFGLAND5 {SPR_BFE1,32773,8,NULL,S_NULL,0,0}, // S_BFGLAND6 {SPR_BFE2,32768,8,NULL,S_BFGEXP2,0,0}, // S_BFGEXP {SPR_BFE2,32769,8,NULL,S_BFGEXP3,0,0}, // S_BFGEXP2 {SPR_BFE2,32770,8,NULL,S_BFGEXP4,0,0}, // S_BFGEXP3 {SPR_BFE2,32771,8,NULL,S_NULL,0,0}, // S_BFGEXP4 {SPR_MISL,32769,8,A_Explode,S_EXPLODE2,0,0}, // S_EXPLODE1 {SPR_MISL,32770,6,NULL,S_EXPLODE3,0,0}, // S_EXPLODE2 {SPR_MISL,32771,4,NULL,S_NULL,0,0}, // S_EXPLODE3 {SPR_TFOG,32768,6,NULL,S_TFOG01,0,0}, // S_TFOG {SPR_TFOG,32769,6,NULL,S_TFOG02,0,0}, // S_TFOG01 {SPR_TFOG,32768,6,NULL,S_TFOG2,0,0}, // S_TFOG02 {SPR_TFOG,32769,6,NULL,S_TFOG3,0,0}, // S_TFOG2 {SPR_TFOG,32770,6,NULL,S_TFOG4,0,0}, // S_TFOG3 {SPR_TFOG,32771,6,NULL,S_TFOG5,0,0}, // S_TFOG4 {SPR_TFOG,32772,6,NULL,S_TFOG6,0,0}, // S_TFOG5 {SPR_TFOG,32773,6,NULL,S_TFOG7,0,0}, // S_TFOG6 {SPR_TFOG,32774,6,NULL,S_TFOG8,0,0}, // S_TFOG7 {SPR_TFOG,32775,6,NULL,S_TFOG9,0,0}, // S_TFOG8 {SPR_TFOG,32776,6,NULL,S_TFOG10,0,0}, // S_TFOG9 {SPR_TFOG,32777,6,NULL,S_NULL,0,0}, // S_TFOG10 {SPR_IFOG,32768,6,NULL,S_IFOG01,0,0}, // S_IFOG {SPR_IFOG,32769,6,NULL,S_IFOG02,0,0}, // S_IFOG01 {SPR_IFOG,32768,6,NULL,S_IFOG2,0,0}, // S_IFOG02 {SPR_IFOG,32769,6,NULL,S_IFOG3,0,0}, // S_IFOG2 {SPR_IFOG,32770,6,NULL,S_IFOG4,0,0}, // S_IFOG3 {SPR_IFOG,32771,6,NULL,S_IFOG5,0,0}, // S_IFOG4 {SPR_IFOG,32772,6,NULL,S_NULL,0,0}, // S_IFOG5 {SPR_PLAY,0,-1,NULL,S_NULL,0,0}, // S_PLAY {SPR_PLAY,0,4,NULL,S_PLAY_RUN2,0,0}, // S_PLAY_RUN1 {SPR_PLAY,1,4,NULL,S_PLAY_RUN3,0,0}, // S_PLAY_RUN2 {SPR_PLAY,2,4,NULL,S_PLAY_RUN4,0,0}, // S_PLAY_RUN3 {SPR_PLAY,3,4,NULL,S_PLAY_RUN1,0,0}, // S_PLAY_RUN4 {SPR_PLAY,4,12,NULL,S_PLAY,0,0}, // S_PLAY_ATK1 {SPR_PLAY,32773,6,NULL,S_PLAY_ATK1,0,0}, // S_PLAY_ATK2 {SPR_PLAY,6,4,NULL,S_PLAY_PAIN2,0,0}, // S_PLAY_PAIN {SPR_PLAY,6,4,A_Pain,S_PLAY,0,0}, // S_PLAY_PAIN2 {SPR_PLAY,7,10,NULL,S_PLAY_DIE2,0,0}, // S_PLAY_DIE1 {SPR_PLAY,8,10,A_PlayerScream,S_PLAY_DIE3,0,0}, // S_PLAY_DIE2 {SPR_PLAY,9,10,A_Fall,S_PLAY_DIE4,0,0}, // S_PLAY_DIE3 {SPR_PLAY,10,10,NULL,S_PLAY_DIE5,0,0}, // S_PLAY_DIE4 {SPR_PLAY,11,10,NULL,S_PLAY_DIE6,0,0}, // S_PLAY_DIE5 {SPR_PLAY,12,10,NULL,S_PLAY_DIE7,0,0}, // S_PLAY_DIE6 {SPR_PLAY,13,-1,NULL,S_NULL,0,0}, // S_PLAY_DIE7 {SPR_PLAY,14,5,NULL,S_PLAY_XDIE2,0,0}, // S_PLAY_XDIE1 {SPR_PLAY,15,5,A_XScream,S_PLAY_XDIE3,0,0}, // S_PLAY_XDIE2 {SPR_PLAY,16,5,A_Fall,S_PLAY_XDIE4,0,0}, // S_PLAY_XDIE3 {SPR_PLAY,17,5,NULL,S_PLAY_XDIE5,0,0}, // S_PLAY_XDIE4 {SPR_PLAY,18,5,NULL,S_PLAY_XDIE6,0,0}, // S_PLAY_XDIE5 {SPR_PLAY,19,5,NULL,S_PLAY_XDIE7,0,0}, // S_PLAY_XDIE6 {SPR_PLAY,20,5,NULL,S_PLAY_XDIE8,0,0}, // S_PLAY_XDIE7 {SPR_PLAY,21,5,NULL,S_PLAY_XDIE9,0,0}, // S_PLAY_XDIE8 {SPR_PLAY,22,-1,NULL,S_NULL,0,0}, // S_PLAY_XDIE9 {SPR_POSS,0,10,A_Look,S_POSS_STND2,0,0}, // S_POSS_STND {SPR_POSS,1,10,A_Look,S_POSS_STND,0,0}, // S_POSS_STND2 {SPR_POSS,0,4,A_Chase,S_POSS_RUN2,0,0}, // S_POSS_RUN1 {SPR_POSS,0,4,A_Chase,S_POSS_RUN3,0,0}, // S_POSS_RUN2 {SPR_POSS,1,4,A_Chase,S_POSS_RUN4,0,0}, // S_POSS_RUN3 {SPR_POSS,1,4,A_Chase,S_POSS_RUN5,0,0}, // S_POSS_RUN4 {SPR_POSS,2,4,A_Chase,S_POSS_RUN6,0,0}, // S_POSS_RUN5 {SPR_POSS,2,4,A_Chase,S_POSS_RUN7,0,0}, // S_POSS_RUN6 {SPR_POSS,3,4,A_Chase,S_POSS_RUN8,0,0}, // S_POSS_RUN7 {SPR_POSS,3,4,A_Chase,S_POSS_RUN1,0,0}, // S_POSS_RUN8 {SPR_POSS,4,10,A_FaceTarget,S_POSS_ATK2,0,0}, // S_POSS_ATK1 {SPR_POSS,5,8,A_PosAttack,S_POSS_ATK3,0,0}, // S_POSS_ATK2 {SPR_POSS,4,8,NULL,S_POSS_RUN1,0,0}, // S_POSS_ATK3 {SPR_POSS,6,3,NULL,S_POSS_PAIN2,0,0}, // S_POSS_PAIN {SPR_POSS,6,3,A_Pain,S_POSS_RUN1,0,0}, // S_POSS_PAIN2 {SPR_POSS,7,5,NULL,S_POSS_DIE2,0,0}, // S_POSS_DIE1 {SPR_POSS,8,5,A_Scream,S_POSS_DIE3,0,0}, // S_POSS_DIE2 {SPR_POSS,9,5,A_Fall,S_POSS_DIE4,0,0}, // S_POSS_DIE3 {SPR_POSS,10,5,NULL,S_POSS_DIE5,0,0}, // S_POSS_DIE4 {SPR_POSS,11,-1,NULL,S_NULL,0,0}, // S_POSS_DIE5 {SPR_POSS,12,5,NULL,S_POSS_XDIE2,0,0}, // S_POSS_XDIE1 {SPR_POSS,13,5,A_XScream,S_POSS_XDIE3,0,0}, // S_POSS_XDIE2 {SPR_POSS,14,5,A_Fall,S_POSS_XDIE4,0,0}, // S_POSS_XDIE3 {SPR_POSS,15,5,NULL,S_POSS_XDIE5,0,0}, // S_POSS_XDIE4 {SPR_POSS,16,5,NULL,S_POSS_XDIE6,0,0}, // S_POSS_XDIE5 {SPR_POSS,17,5,NULL,S_POSS_XDIE7,0,0}, // S_POSS_XDIE6 {SPR_POSS,18,5,NULL,S_POSS_XDIE8,0,0}, // S_POSS_XDIE7 {SPR_POSS,19,5,NULL,S_POSS_XDIE9,0,0}, // S_POSS_XDIE8 {SPR_POSS,20,-1,NULL,S_NULL,0,0}, // S_POSS_XDIE9 {SPR_POSS,10,5,NULL,S_POSS_RAISE2,0,0}, // S_POSS_RAISE1 {SPR_POSS,9,5,NULL,S_POSS_RAISE3,0,0}, // S_POSS_RAISE2 {SPR_POSS,8,5,NULL,S_POSS_RAISE4,0,0}, // S_POSS_RAISE3 {SPR_POSS,7,5,NULL,S_POSS_RUN1,0,0}, // S_POSS_RAISE4 {SPR_SPOS,0,10,A_Look,S_SPOS_STND2,0,0}, // S_SPOS_STND {SPR_SPOS,1,10,A_Look,S_SPOS_STND,0,0}, // S_SPOS_STND2 {SPR_SPOS,0,3,A_Chase,S_SPOS_RUN2,0,0}, // S_SPOS_RUN1 {SPR_SPOS,0,3,A_Chase,S_SPOS_RUN3,0,0}, // S_SPOS_RUN2 {SPR_SPOS,1,3,A_Chase,S_SPOS_RUN4,0,0}, // S_SPOS_RUN3 {SPR_SPOS,1,3,A_Chase,S_SPOS_RUN5,0,0}, // S_SPOS_RUN4 {SPR_SPOS,2,3,A_Chase,S_SPOS_RUN6,0,0}, // S_SPOS_RUN5 {SPR_SPOS,2,3,A_Chase,S_SPOS_RUN7,0,0}, // S_SPOS_RUN6 {SPR_SPOS,3,3,A_Chase,S_SPOS_RUN8,0,0}, // S_SPOS_RUN7 {SPR_SPOS,3,3,A_Chase,S_SPOS_RUN1,0,0}, // S_SPOS_RUN8 {SPR_SPOS,4,10,A_FaceTarget,S_SPOS_ATK2,0,0}, // S_SPOS_ATK1 {SPR_SPOS,32773,10,A_SPosAttack,S_SPOS_ATK3,0,0}, // S_SPOS_ATK2 {SPR_SPOS,4,10,NULL,S_SPOS_RUN1,0,0}, // S_SPOS_ATK3 {SPR_SPOS,6,3,NULL,S_SPOS_PAIN2,0,0}, // S_SPOS_PAIN {SPR_SPOS,6,3,A_Pain,S_SPOS_RUN1,0,0}, // S_SPOS_PAIN2 {SPR_SPOS,7,5,NULL,S_SPOS_DIE2,0,0}, // S_SPOS_DIE1 {SPR_SPOS,8,5,A_Scream,S_SPOS_DIE3,0,0}, // S_SPOS_DIE2 {SPR_SPOS,9,5,A_Fall,S_SPOS_DIE4,0,0}, // S_SPOS_DIE3 {SPR_SPOS,10,5,NULL,S_SPOS_DIE5,0,0}, // S_SPOS_DIE4 {SPR_SPOS,11,-1,NULL,S_NULL,0,0}, // S_SPOS_DIE5 {SPR_SPOS,12,5,NULL,S_SPOS_XDIE2,0,0}, // S_SPOS_XDIE1 {SPR_SPOS,13,5,A_XScream,S_SPOS_XDIE3,0,0}, // S_SPOS_XDIE2 {SPR_SPOS,14,5,A_Fall,S_SPOS_XDIE4,0,0}, // S_SPOS_XDIE3 {SPR_SPOS,15,5,NULL,S_SPOS_XDIE5,0,0}, // S_SPOS_XDIE4 {SPR_SPOS,16,5,NULL,S_SPOS_XDIE6,0,0}, // S_SPOS_XDIE5 {SPR_SPOS,17,5,NULL,S_SPOS_XDIE7,0,0}, // S_SPOS_XDIE6 {SPR_SPOS,18,5,NULL,S_SPOS_XDIE8,0,0}, // S_SPOS_XDIE7 {SPR_SPOS,19,5,NULL,S_SPOS_XDIE9,0,0}, // S_SPOS_XDIE8 {SPR_SPOS,20,-1,NULL,S_NULL,0,0}, // S_SPOS_XDIE9 {SPR_SPOS,11,5,NULL,S_SPOS_RAISE2,0,0}, // S_SPOS_RAISE1 {SPR_SPOS,10,5,NULL,S_SPOS_RAISE3,0,0}, // S_SPOS_RAISE2 {SPR_SPOS,9,5,NULL,S_SPOS_RAISE4,0,0}, // S_SPOS_RAISE3 {SPR_SPOS,8,5,NULL,S_SPOS_RAISE5,0,0}, // S_SPOS_RAISE4 {SPR_SPOS,7,5,NULL,S_SPOS_RUN1,0,0}, // S_SPOS_RAISE5 {SPR_VILE,0,10,A_Look,S_VILE_STND2,0,0}, // S_VILE_STND {SPR_VILE,1,10,A_Look,S_VILE_STND,0,0}, // S_VILE_STND2 {SPR_VILE,0,2,A_VileChase,S_VILE_RUN2,0,0}, // S_VILE_RUN1 {SPR_VILE,0,2,A_VileChase,S_VILE_RUN3,0,0}, // S_VILE_RUN2 {SPR_VILE,1,2,A_VileChase,S_VILE_RUN4,0,0}, // S_VILE_RUN3 {SPR_VILE,1,2,A_VileChase,S_VILE_RUN5,0,0}, // S_VILE_RUN4 {SPR_VILE,2,2,A_VileChase,S_VILE_RUN6,0,0}, // S_VILE_RUN5 {SPR_VILE,2,2,A_VileChase,S_VILE_RUN7,0,0}, // S_VILE_RUN6 {SPR_VILE,3,2,A_VileChase,S_VILE_RUN8,0,0}, // S_VILE_RUN7 {SPR_VILE,3,2,A_VileChase,S_VILE_RUN9,0,0}, // S_VILE_RUN8 {SPR_VILE,4,2,A_VileChase,S_VILE_RUN10,0,0}, // S_VILE_RUN9 {SPR_VILE,4,2,A_VileChase,S_VILE_RUN11,0,0}, // S_VILE_RUN10 {SPR_VILE,5,2,A_VileChase,S_VILE_RUN12,0,0}, // S_VILE_RUN11 {SPR_VILE,5,2,A_VileChase,S_VILE_RUN1,0,0}, // S_VILE_RUN12 {SPR_VILE,32774,0,A_VileStart,S_VILE_ATK2,0,0}, // S_VILE_ATK1 {SPR_VILE,32774,10,A_FaceTarget,S_VILE_ATK3,0,0}, // S_VILE_ATK2 {SPR_VILE,32775,8,A_VileTarget,S_VILE_ATK4,0,0}, // S_VILE_ATK3 {SPR_VILE,32776,8,A_FaceTarget,S_VILE_ATK5,0,0}, // S_VILE_ATK4 {SPR_VILE,32777,8,A_FaceTarget,S_VILE_ATK6,0,0}, // S_VILE_ATK5 {SPR_VILE,32778,8,A_FaceTarget,S_VILE_ATK7,0,0}, // S_VILE_ATK6 {SPR_VILE,32779,8,A_FaceTarget,S_VILE_ATK8,0,0}, // S_VILE_ATK7 {SPR_VILE,32780,8,A_FaceTarget,S_VILE_ATK9,0,0}, // S_VILE_ATK8 {SPR_VILE,32781,8,A_FaceTarget,S_VILE_ATK10,0,0}, // S_VILE_ATK9 {SPR_VILE,32782,8,A_VileAttack,S_VILE_ATK11,0,0}, // S_VILE_ATK10 {SPR_VILE,32783,20,NULL,S_VILE_RUN1,0,0}, // S_VILE_ATK11 {SPR_VILE,32794,10,NULL,S_VILE_HEAL2,0,0}, // S_VILE_HEAL1 {SPR_VILE,32795,10,NULL,S_VILE_HEAL3,0,0}, // S_VILE_HEAL2 {SPR_VILE,32796,10,NULL,S_VILE_RUN1,0,0}, // S_VILE_HEAL3 {SPR_VILE,16,5,NULL,S_VILE_PAIN2,0,0}, // S_VILE_PAIN {SPR_VILE,16,5,A_Pain,S_VILE_RUN1,0,0}, // S_VILE_PAIN2 {SPR_VILE,16,7,NULL,S_VILE_DIE2,0,0}, // S_VILE_DIE1 {SPR_VILE,17,7,A_Scream,S_VILE_DIE3,0,0}, // S_VILE_DIE2 {SPR_VILE,18,7,A_Fall,S_VILE_DIE4,0,0}, // S_VILE_DIE3 {SPR_VILE,19,7,NULL,S_VILE_DIE5,0,0}, // S_VILE_DIE4 {SPR_VILE,20,7,NULL,S_VILE_DIE6,0,0}, // S_VILE_DIE5 {SPR_VILE,21,7,NULL,S_VILE_DIE7,0,0}, // S_VILE_DIE6 {SPR_VILE,22,7,NULL,S_VILE_DIE8,0,0}, // S_VILE_DIE7 {SPR_VILE,23,5,NULL,S_VILE_DIE9,0,0}, // S_VILE_DIE8 {SPR_VILE,24,5,NULL,S_VILE_DIE10,0,0}, // S_VILE_DIE9 {SPR_VILE,25,-1,NULL,S_NULL,0,0}, // S_VILE_DIE10 {SPR_FIRE,32768,2,A_StartFire,S_FIRE2,0,0}, // S_FIRE1 {SPR_FIRE,32769,2,A_Fire,S_FIRE3,0,0}, // S_FIRE2 {SPR_FIRE,32768,2,A_Fire,S_FIRE4,0,0}, // S_FIRE3 {SPR_FIRE,32769,2,A_Fire,S_FIRE5,0,0}, // S_FIRE4 {SPR_FIRE,32770,2,A_FireCrackle,S_FIRE6,0,0}, // S_FIRE5 {SPR_FIRE,32769,2,A_Fire,S_FIRE7,0,0}, // S_FIRE6 {SPR_FIRE,32770,2,A_Fire,S_FIRE8,0,0}, // S_FIRE7 {SPR_FIRE,32769,2,A_Fire,S_FIRE9,0,0}, // S_FIRE8 {SPR_FIRE,32770,2,A_Fire,S_FIRE10,0,0}, // S_FIRE9 {SPR_FIRE,32771,2,A_Fire,S_FIRE11,0,0}, // S_FIRE10 {SPR_FIRE,32770,2,A_Fire,S_FIRE12,0,0}, // S_FIRE11 {SPR_FIRE,32771,2,A_Fire,S_FIRE13,0,0}, // S_FIRE12 {SPR_FIRE,32770,2,A_Fire,S_FIRE14,0,0}, // S_FIRE13 {SPR_FIRE,32771,2,A_Fire,S_FIRE15,0,0}, // S_FIRE14 {SPR_FIRE,32772,2,A_Fire,S_FIRE16,0,0}, // S_FIRE15 {SPR_FIRE,32771,2,A_Fire,S_FIRE17,0,0}, // S_FIRE16 {SPR_FIRE,32772,2,A_Fire,S_FIRE18,0,0}, // S_FIRE17 {SPR_FIRE,32771,2,A_Fire,S_FIRE19,0,0}, // S_FIRE18 {SPR_FIRE,32772,2,A_FireCrackle,S_FIRE20,0,0}, // S_FIRE19 {SPR_FIRE,32773,2,A_Fire,S_FIRE21,0,0}, // S_FIRE20 {SPR_FIRE,32772,2,A_Fire,S_FIRE22,0,0}, // S_FIRE21 {SPR_FIRE,32773,2,A_Fire,S_FIRE23,0,0}, // S_FIRE22 {SPR_FIRE,32772,2,A_Fire,S_FIRE24,0,0}, // S_FIRE23 {SPR_FIRE,32773,2,A_Fire,S_FIRE25,0,0}, // S_FIRE24 {SPR_FIRE,32774,2,A_Fire,S_FIRE26,0,0}, // S_FIRE25 {SPR_FIRE,32775,2,A_Fire,S_FIRE27,0,0}, // S_FIRE26 {SPR_FIRE,32774,2,A_Fire,S_FIRE28,0,0}, // S_FIRE27 {SPR_FIRE,32775,2,A_Fire,S_FIRE29,0,0}, // S_FIRE28 {SPR_FIRE,32774,2,A_Fire,S_FIRE30,0,0}, // S_FIRE29 {SPR_FIRE,32775,2,A_Fire,S_NULL,0,0}, // S_FIRE30 {SPR_PUFF,1,4,NULL,S_SMOKE2,0,0}, // S_SMOKE1 {SPR_PUFF,2,4,NULL,S_SMOKE3,0,0}, // S_SMOKE2 {SPR_PUFF,1,4,NULL,S_SMOKE4,0,0}, // S_SMOKE3 {SPR_PUFF,2,4,NULL,S_SMOKE5,0,0}, // S_SMOKE4 {SPR_PUFF,3,4,NULL,S_NULL,0,0}, // S_SMOKE5 {SPR_FATB,32768,2,A_Tracer,S_TRACER2,0,0}, // S_TRACER {SPR_FATB,32769,2,A_Tracer,S_TRACER,0,0}, // S_TRACER2 {SPR_FBXP,32768,8,NULL,S_TRACEEXP2,0,0}, // S_TRACEEXP1 {SPR_FBXP,32769,6,NULL,S_TRACEEXP3,0,0}, // S_TRACEEXP2 {SPR_FBXP,32770,4,NULL,S_NULL,0,0}, // S_TRACEEXP3 {SPR_SKEL,0,10,A_Look,S_SKEL_STND2,0,0}, // S_SKEL_STND {SPR_SKEL,1,10,A_Look,S_SKEL_STND,0,0}, // S_SKEL_STND2 {SPR_SKEL,0,2,A_Chase,S_SKEL_RUN2,0,0}, // S_SKEL_RUN1 {SPR_SKEL,0,2,A_Chase,S_SKEL_RUN3,0,0}, // S_SKEL_RUN2 {SPR_SKEL,1,2,A_Chase,S_SKEL_RUN4,0,0}, // S_SKEL_RUN3 {SPR_SKEL,1,2,A_Chase,S_SKEL_RUN5,0,0}, // S_SKEL_RUN4 {SPR_SKEL,2,2,A_Chase,S_SKEL_RUN6,0,0}, // S_SKEL_RUN5 {SPR_SKEL,2,2,A_Chase,S_SKEL_RUN7,0,0}, // S_SKEL_RUN6 {SPR_SKEL,3,2,A_Chase,S_SKEL_RUN8,0,0}, // S_SKEL_RUN7 {SPR_SKEL,3,2,A_Chase,S_SKEL_RUN9,0,0}, // S_SKEL_RUN8 {SPR_SKEL,4,2,A_Chase,S_SKEL_RUN10,0,0}, // S_SKEL_RUN9 {SPR_SKEL,4,2,A_Chase,S_SKEL_RUN11,0,0}, // S_SKEL_RUN10 {SPR_SKEL,5,2,A_Chase,S_SKEL_RUN12,0,0}, // S_SKEL_RUN11 {SPR_SKEL,5,2,A_Chase,S_SKEL_RUN1,0,0}, // S_SKEL_RUN12 {SPR_SKEL,6,0,A_FaceTarget,S_SKEL_FIST2,0,0}, // S_SKEL_FIST1 {SPR_SKEL,6,6,A_SkelWhoosh,S_SKEL_FIST3,0,0}, // S_SKEL_FIST2 {SPR_SKEL,7,6,A_FaceTarget,S_SKEL_FIST4,0,0}, // S_SKEL_FIST3 {SPR_SKEL,8,6,A_SkelFist,S_SKEL_RUN1,0,0}, // S_SKEL_FIST4 {SPR_SKEL,32777,0,A_FaceTarget,S_SKEL_MISS2,0,0}, // S_SKEL_MISS1 {SPR_SKEL,32777,10,A_FaceTarget,S_SKEL_MISS3,0,0}, // S_SKEL_MISS2 {SPR_SKEL,10,10,A_SkelMissile,S_SKEL_MISS4,0,0}, // S_SKEL_MISS3 {SPR_SKEL,10,10,A_FaceTarget,S_SKEL_RUN1,0,0}, // S_SKEL_MISS4 {SPR_SKEL,11,5,NULL,S_SKEL_PAIN2,0,0}, // S_SKEL_PAIN {SPR_SKEL,11,5,A_Pain,S_SKEL_RUN1,0,0}, // S_SKEL_PAIN2 {SPR_SKEL,11,7,NULL,S_SKEL_DIE2,0,0}, // S_SKEL_DIE1 {SPR_SKEL,12,7,NULL,S_SKEL_DIE3,0,0}, // S_SKEL_DIE2 {SPR_SKEL,13,7,A_Scream,S_SKEL_DIE4,0,0}, // S_SKEL_DIE3 {SPR_SKEL,14,7,A_Fall,S_SKEL_DIE5,0,0}, // S_SKEL_DIE4 {SPR_SKEL,15,7,NULL,S_SKEL_DIE6,0,0}, // S_SKEL_DIE5 {SPR_SKEL,16,-1,NULL,S_NULL,0,0}, // S_SKEL_DIE6 {SPR_SKEL,16,5,NULL,S_SKEL_RAISE2,0,0}, // S_SKEL_RAISE1 {SPR_SKEL,15,5,NULL,S_SKEL_RAISE3,0,0}, // S_SKEL_RAISE2 {SPR_SKEL,14,5,NULL,S_SKEL_RAISE4,0,0}, // S_SKEL_RAISE3 {SPR_SKEL,13,5,NULL,S_SKEL_RAISE5,0,0}, // S_SKEL_RAISE4 {SPR_SKEL,12,5,NULL,S_SKEL_RAISE6,0,0}, // S_SKEL_RAISE5 {SPR_SKEL,11,5,NULL,S_SKEL_RUN1,0,0}, // S_SKEL_RAISE6 {SPR_MANF,32768,4,NULL,S_FATSHOT2,0,0}, // S_FATSHOT1 {SPR_MANF,32769,4,NULL,S_FATSHOT1,0,0}, // S_FATSHOT2 {SPR_MISL,32769,8,NULL,S_FATSHOTX2,0,0}, // S_FATSHOTX1 {SPR_MISL,32770,6,NULL,S_FATSHOTX3,0,0}, // S_FATSHOTX2 {SPR_MISL,32771,4,NULL,S_NULL,0,0}, // S_FATSHOTX3 {SPR_FATT,0,15,A_Look,S_FATT_STND2,0,0}, // S_FATT_STND {SPR_FATT,1,15,A_Look,S_FATT_STND,0,0}, // S_FATT_STND2 {SPR_FATT,0,4,A_Chase,S_FATT_RUN2,0,0}, // S_FATT_RUN1 {SPR_FATT,0,4,A_Chase,S_FATT_RUN3,0,0}, // S_FATT_RUN2 {SPR_FATT,1,4,A_Chase,S_FATT_RUN4,0,0}, // S_FATT_RUN3 {SPR_FATT,1,4,A_Chase,S_FATT_RUN5,0,0}, // S_FATT_RUN4 {SPR_FATT,2,4,A_Chase,S_FATT_RUN6,0,0}, // S_FATT_RUN5 {SPR_FATT,2,4,A_Chase,S_FATT_RUN7,0,0}, // S_FATT_RUN6 {SPR_FATT,3,4,A_Chase,S_FATT_RUN8,0,0}, // S_FATT_RUN7 {SPR_FATT,3,4,A_Chase,S_FATT_RUN9,0,0}, // S_FATT_RUN8 {SPR_FATT,4,4,A_Chase,S_FATT_RUN10,0,0}, // S_FATT_RUN9 {SPR_FATT,4,4,A_Chase,S_FATT_RUN11,0,0}, // S_FATT_RUN10 {SPR_FATT,5,4,A_Chase,S_FATT_RUN12,0,0}, // S_FATT_RUN11 {SPR_FATT,5,4,A_Chase,S_FATT_RUN1,0,0}, // S_FATT_RUN12 {SPR_FATT,6,20,A_FatRaise,S_FATT_ATK2,0,0}, // S_FATT_ATK1 {SPR_FATT,32775,10,A_FatAttack1,S_FATT_ATK3,0,0}, // S_FATT_ATK2 {SPR_FATT,8,5,A_FaceTarget,S_FATT_ATK4,0,0}, // S_FATT_ATK3 {SPR_FATT,6,5,A_FaceTarget,S_FATT_ATK5,0,0}, // S_FATT_ATK4 {SPR_FATT,32775,10,A_FatAttack2,S_FATT_ATK6,0,0}, // S_FATT_ATK5 {SPR_FATT,8,5,A_FaceTarget,S_FATT_ATK7,0,0}, // S_FATT_ATK6 {SPR_FATT,6,5,A_FaceTarget,S_FATT_ATK8,0,0}, // S_FATT_ATK7 {SPR_FATT,32775,10,A_FatAttack3,S_FATT_ATK9,0,0}, // S_FATT_ATK8 {SPR_FATT,8,5,A_FaceTarget,S_FATT_ATK10,0,0}, // S_FATT_ATK9 {SPR_FATT,6,5,A_FaceTarget,S_FATT_RUN1,0,0}, // S_FATT_ATK10 {SPR_FATT,9,3,NULL,S_FATT_PAIN2,0,0}, // S_FATT_PAIN {SPR_FATT,9,3,A_Pain,S_FATT_RUN1,0,0}, // S_FATT_PAIN2 {SPR_FATT,10,6,NULL,S_FATT_DIE2,0,0}, // S_FATT_DIE1 {SPR_FATT,11,6,A_Scream,S_FATT_DIE3,0,0}, // S_FATT_DIE2 {SPR_FATT,12,6,A_Fall,S_FATT_DIE4,0,0}, // S_FATT_DIE3 {SPR_FATT,13,6,NULL,S_FATT_DIE5,0,0}, // S_FATT_DIE4 {SPR_FATT,14,6,NULL,S_FATT_DIE6,0,0}, // S_FATT_DIE5 {SPR_FATT,15,6,NULL,S_FATT_DIE7,0,0}, // S_FATT_DIE6 {SPR_FATT,16,6,NULL,S_FATT_DIE8,0,0}, // S_FATT_DIE7 {SPR_FATT,17,6,NULL,S_FATT_DIE9,0,0}, // S_FATT_DIE8 {SPR_FATT,18,6,NULL,S_FATT_DIE10,0,0}, // S_FATT_DIE9 {SPR_FATT,19,-1,A_BossDeath,S_NULL,0,0}, // S_FATT_DIE10 {SPR_FATT,17,5,NULL,S_FATT_RAISE2,0,0}, // S_FATT_RAISE1 {SPR_FATT,16,5,NULL,S_FATT_RAISE3,0,0}, // S_FATT_RAISE2 {SPR_FATT,15,5,NULL,S_FATT_RAISE4,0,0}, // S_FATT_RAISE3 {SPR_FATT,14,5,NULL,S_FATT_RAISE5,0,0}, // S_FATT_RAISE4 {SPR_FATT,13,5,NULL,S_FATT_RAISE6,0,0}, // S_FATT_RAISE5 {SPR_FATT,12,5,NULL,S_FATT_RAISE7,0,0}, // S_FATT_RAISE6 {SPR_FATT,11,5,NULL,S_FATT_RAISE8,0,0}, // S_FATT_RAISE7 {SPR_FATT,10,5,NULL,S_FATT_RUN1,0,0}, // S_FATT_RAISE8 {SPR_CPOS,0,10,A_Look,S_CPOS_STND2,0,0}, // S_CPOS_STND {SPR_CPOS,1,10,A_Look,S_CPOS_STND,0,0}, // S_CPOS_STND2 {SPR_CPOS,0,3,A_Chase,S_CPOS_RUN2,0,0}, // S_CPOS_RUN1 {SPR_CPOS,0,3,A_Chase,S_CPOS_RUN3,0,0}, // S_CPOS_RUN2 {SPR_CPOS,1,3,A_Chase,S_CPOS_RUN4,0,0}, // S_CPOS_RUN3 {SPR_CPOS,1,3,A_Chase,S_CPOS_RUN5,0,0}, // S_CPOS_RUN4 {SPR_CPOS,2,3,A_Chase,S_CPOS_RUN6,0,0}, // S_CPOS_RUN5 {SPR_CPOS,2,3,A_Chase,S_CPOS_RUN7,0,0}, // S_CPOS_RUN6 {SPR_CPOS,3,3,A_Chase,S_CPOS_RUN8,0,0}, // S_CPOS_RUN7 {SPR_CPOS,3,3,A_Chase,S_CPOS_RUN1,0,0}, // S_CPOS_RUN8 {SPR_CPOS,4,10,A_FaceTarget,S_CPOS_ATK2,0,0}, // S_CPOS_ATK1 {SPR_CPOS,32773,4,A_CPosAttack,S_CPOS_ATK3,0,0}, // S_CPOS_ATK2 {SPR_CPOS,32772,4,A_CPosAttack,S_CPOS_ATK4,0,0}, // S_CPOS_ATK3 {SPR_CPOS,5,1,A_CPosRefire,S_CPOS_ATK2,0,0}, // S_CPOS_ATK4 {SPR_CPOS,6,3,NULL,S_CPOS_PAIN2,0,0}, // S_CPOS_PAIN {SPR_CPOS,6,3,A_Pain,S_CPOS_RUN1,0,0}, // S_CPOS_PAIN2 {SPR_CPOS,7,5,NULL,S_CPOS_DIE2,0,0}, // S_CPOS_DIE1 {SPR_CPOS,8,5,A_Scream,S_CPOS_DIE3,0,0}, // S_CPOS_DIE2 {SPR_CPOS,9,5,A_Fall,S_CPOS_DIE4,0,0}, // S_CPOS_DIE3 {SPR_CPOS,10,5,NULL,S_CPOS_DIE5,0,0}, // S_CPOS_DIE4 {SPR_CPOS,11,5,NULL,S_CPOS_DIE6,0,0}, // S_CPOS_DIE5 {SPR_CPOS,12,5,NULL,S_CPOS_DIE7,0,0}, // S_CPOS_DIE6 {SPR_CPOS,13,-1,NULL,S_NULL,0,0}, // S_CPOS_DIE7 {SPR_CPOS,14,5,NULL,S_CPOS_XDIE2,0,0}, // S_CPOS_XDIE1 {SPR_CPOS,15,5,A_XScream,S_CPOS_XDIE3,0,0}, // S_CPOS_XDIE2 {SPR_CPOS,16,5,A_Fall,S_CPOS_XDIE4,0,0}, // S_CPOS_XDIE3 {SPR_CPOS,17,5,NULL,S_CPOS_XDIE5,0,0}, // S_CPOS_XDIE4 {SPR_CPOS,18,5,NULL,S_CPOS_XDIE6,0,0}, // S_CPOS_XDIE5 {SPR_CPOS,19,-1,NULL,S_NULL,0,0}, // S_CPOS_XDIE6 {SPR_CPOS,13,5,NULL,S_CPOS_RAISE2,0,0}, // S_CPOS_RAISE1 {SPR_CPOS,12,5,NULL,S_CPOS_RAISE3,0,0}, // S_CPOS_RAISE2 {SPR_CPOS,11,5,NULL,S_CPOS_RAISE4,0,0}, // S_CPOS_RAISE3 {SPR_CPOS,10,5,NULL,S_CPOS_RAISE5,0,0}, // S_CPOS_RAISE4 {SPR_CPOS,9,5,NULL,S_CPOS_RAISE6,0,0}, // S_CPOS_RAISE5 {SPR_CPOS,8,5,NULL,S_CPOS_RAISE7,0,0}, // S_CPOS_RAISE6 {SPR_CPOS,7,5,NULL,S_CPOS_RUN1,0,0}, // S_CPOS_RAISE7 {SPR_TROO,0,10,A_Look,S_TROO_STND2,0,0}, // S_TROO_STND {SPR_TROO,1,10,A_Look,S_TROO_STND,0,0}, // S_TROO_STND2 {SPR_TROO,0,3,A_Chase,S_TROO_RUN2,0,0}, // S_TROO_RUN1 {SPR_TROO,0,3,A_Chase,S_TROO_RUN3,0,0}, // S_TROO_RUN2 {SPR_TROO,1,3,A_Chase,S_TROO_RUN4,0,0}, // S_TROO_RUN3 {SPR_TROO,1,3,A_Chase,S_TROO_RUN5,0,0}, // S_TROO_RUN4 {SPR_TROO,2,3,A_Chase,S_TROO_RUN6,0,0}, // S_TROO_RUN5 {SPR_TROO,2,3,A_Chase,S_TROO_RUN7,0,0}, // S_TROO_RUN6 {SPR_TROO,3,3,A_Chase,S_TROO_RUN8,0,0}, // S_TROO_RUN7 {SPR_TROO,3,3,A_Chase,S_TROO_RUN1,0,0}, // S_TROO_RUN8 {SPR_TROO,4,8,A_FaceTarget,S_TROO_ATK2,0,0}, // S_TROO_ATK1 {SPR_TROO,5,8,A_FaceTarget,S_TROO_ATK3,0,0}, // S_TROO_ATK2 {SPR_TROO,6,6,A_TroopAttack,S_TROO_RUN1,0,0}, // S_TROO_ATK3 {SPR_TROO,7,2,NULL,S_TROO_PAIN2,0,0}, // S_TROO_PAIN {SPR_TROO,7,2,A_Pain,S_TROO_RUN1,0,0}, // S_TROO_PAIN2 {SPR_TROO,8,8,NULL,S_TROO_DIE2,0,0}, // S_TROO_DIE1 {SPR_TROO,9,8,A_Scream,S_TROO_DIE3,0,0}, // S_TROO_DIE2 {SPR_TROO,10,6,NULL,S_TROO_DIE4,0,0}, // S_TROO_DIE3 {SPR_TROO,11,6,A_Fall,S_TROO_DIE5,0,0}, // S_TROO_DIE4 {SPR_TROO,12,-1,NULL,S_NULL,0,0}, // S_TROO_DIE5 {SPR_TROO,13,5,NULL,S_TROO_XDIE2,0,0}, // S_TROO_XDIE1 {SPR_TROO,14,5,A_XScream,S_TROO_XDIE3,0,0}, // S_TROO_XDIE2 {SPR_TROO,15,5,NULL,S_TROO_XDIE4,0,0}, // S_TROO_XDIE3 {SPR_TROO,16,5,A_Fall,S_TROO_XDIE5,0,0}, // S_TROO_XDIE4 {SPR_TROO,17,5,NULL,S_TROO_XDIE6,0,0}, // S_TROO_XDIE5 {SPR_TROO,18,5,NULL,S_TROO_XDIE7,0,0}, // S_TROO_XDIE6 {SPR_TROO,19,5,NULL,S_TROO_XDIE8,0,0}, // S_TROO_XDIE7 {SPR_TROO,20,-1,NULL,S_NULL,0,0}, // S_TROO_XDIE8 {SPR_TROO,12,8,NULL,S_TROO_RAISE2,0,0}, // S_TROO_RAISE1 {SPR_TROO,11,8,NULL,S_TROO_RAISE3,0,0}, // S_TROO_RAISE2 {SPR_TROO,10,6,NULL,S_TROO_RAISE4,0,0}, // S_TROO_RAISE3 {SPR_TROO,9,6,NULL,S_TROO_RAISE5,0,0}, // S_TROO_RAISE4 {SPR_TROO,8,6,NULL,S_TROO_RUN1,0,0}, // S_TROO_RAISE5 {SPR_SARG,0,10,A_Look,S_SARG_STND2,0,0}, // S_SARG_STND {SPR_SARG,1,10,A_Look,S_SARG_STND,0,0}, // S_SARG_STND2 {SPR_SARG,0,2,A_Chase,S_SARG_RUN2,0,0}, // S_SARG_RUN1 {SPR_SARG,0,2,A_Chase,S_SARG_RUN3,0,0}, // S_SARG_RUN2 {SPR_SARG,1,2,A_Chase,S_SARG_RUN4,0,0}, // S_SARG_RUN3 {SPR_SARG,1,2,A_Chase,S_SARG_RUN5,0,0}, // S_SARG_RUN4 {SPR_SARG,2,2,A_Chase,S_SARG_RUN6,0,0}, // S_SARG_RUN5 {SPR_SARG,2,2,A_Chase,S_SARG_RUN7,0,0}, // S_SARG_RUN6 {SPR_SARG,3,2,A_Chase,S_SARG_RUN8,0,0}, // S_SARG_RUN7 {SPR_SARG,3,2,A_Chase,S_SARG_RUN1,0,0}, // S_SARG_RUN8 {SPR_SARG,4,8,A_FaceTarget,S_SARG_ATK2,0,0}, // S_SARG_ATK1 {SPR_SARG,5,8,A_FaceTarget,S_SARG_ATK3,0,0}, // S_SARG_ATK2 {SPR_SARG,6,8,A_SargAttack,S_SARG_RUN1,0,0}, // S_SARG_ATK3 {SPR_SARG,7,2,NULL,S_SARG_PAIN2,0,0}, // S_SARG_PAIN {SPR_SARG,7,2,A_Pain,S_SARG_RUN1,0,0}, // S_SARG_PAIN2 {SPR_SARG,8,8,NULL,S_SARG_DIE2,0,0}, // S_SARG_DIE1 {SPR_SARG,9,8,A_Scream,S_SARG_DIE3,0,0}, // S_SARG_DIE2 {SPR_SARG,10,4,NULL,S_SARG_DIE4,0,0}, // S_SARG_DIE3 {SPR_SARG,11,4,A_Fall,S_SARG_DIE5,0,0}, // S_SARG_DIE4 {SPR_SARG,12,4,NULL,S_SARG_DIE6,0,0}, // S_SARG_DIE5 {SPR_SARG,13,-1,NULL,S_NULL,0,0}, // S_SARG_DIE6 {SPR_SARG,13,5,NULL,S_SARG_RAISE2,0,0}, // S_SARG_RAISE1 {SPR_SARG,12,5,NULL,S_SARG_RAISE3,0,0}, // S_SARG_RAISE2 {SPR_SARG,11,5,NULL,S_SARG_RAISE4,0,0}, // S_SARG_RAISE3 {SPR_SARG,10,5,NULL,S_SARG_RAISE5,0,0}, // S_SARG_RAISE4 {SPR_SARG,9,5,NULL,S_SARG_RAISE6,0,0}, // S_SARG_RAISE5 {SPR_SARG,8,5,NULL,S_SARG_RUN1,0,0}, // S_SARG_RAISE6 {SPR_HEAD,0,10,A_Look,S_HEAD_STND,0,0}, // S_HEAD_STND {SPR_HEAD,0,3,A_Chase,S_HEAD_RUN1,0,0}, // S_HEAD_RUN1 {SPR_HEAD,1,5,A_FaceTarget,S_HEAD_ATK2,0,0}, // S_HEAD_ATK1 {SPR_HEAD,2,5,A_FaceTarget,S_HEAD_ATK3,0,0}, // S_HEAD_ATK2 {SPR_HEAD,32771,5,A_HeadAttack,S_HEAD_RUN1,0,0}, // S_HEAD_ATK3 {SPR_HEAD,4,3,NULL,S_HEAD_PAIN2,0,0}, // S_HEAD_PAIN {SPR_HEAD,4,3,A_Pain,S_HEAD_PAIN3,0,0}, // S_HEAD_PAIN2 {SPR_HEAD,5,6,NULL,S_HEAD_RUN1,0,0}, // S_HEAD_PAIN3 {SPR_HEAD,6,8,NULL,S_HEAD_DIE2,0,0}, // S_HEAD_DIE1 {SPR_HEAD,7,8,A_Scream,S_HEAD_DIE3,0,0}, // S_HEAD_DIE2 {SPR_HEAD,8,8,NULL,S_HEAD_DIE4,0,0}, // S_HEAD_DIE3 {SPR_HEAD,9,8,NULL,S_HEAD_DIE5,0,0}, // S_HEAD_DIE4 {SPR_HEAD,10,8,A_Fall,S_HEAD_DIE6,0,0}, // S_HEAD_DIE5 {SPR_HEAD,11,-1,NULL,S_NULL,0,0}, // S_HEAD_DIE6 {SPR_HEAD,11,8,NULL,S_HEAD_RAISE2,0,0}, // S_HEAD_RAISE1 {SPR_HEAD,10,8,NULL,S_HEAD_RAISE3,0,0}, // S_HEAD_RAISE2 {SPR_HEAD,9,8,NULL,S_HEAD_RAISE4,0,0}, // S_HEAD_RAISE3 {SPR_HEAD,8,8,NULL,S_HEAD_RAISE5,0,0}, // S_HEAD_RAISE4 {SPR_HEAD,7,8,NULL,S_HEAD_RAISE6,0,0}, // S_HEAD_RAISE5 {SPR_HEAD,6,8,NULL,S_HEAD_RUN1,0,0}, // S_HEAD_RAISE6 {SPR_BAL7,32768,4,NULL,S_BRBALL2,0,0}, // S_BRBALL1 {SPR_BAL7,32769,4,NULL,S_BRBALL1,0,0}, // S_BRBALL2 {SPR_BAL7,32770,6,NULL,S_BRBALLX2,0,0}, // S_BRBALLX1 {SPR_BAL7,32771,6,NULL,S_BRBALLX3,0,0}, // S_BRBALLX2 {SPR_BAL7,32772,6,NULL,S_NULL,0,0}, // S_BRBALLX3 {SPR_BOSS,0,10,A_Look,S_BOSS_STND2,0,0}, // S_BOSS_STND {SPR_BOSS,1,10,A_Look,S_BOSS_STND,0,0}, // S_BOSS_STND2 {SPR_BOSS,0,3,A_Chase,S_BOSS_RUN2,0,0}, // S_BOSS_RUN1 {SPR_BOSS,0,3,A_Chase,S_BOSS_RUN3,0,0}, // S_BOSS_RUN2 {SPR_BOSS,1,3,A_Chase,S_BOSS_RUN4,0,0}, // S_BOSS_RUN3 {SPR_BOSS,1,3,A_Chase,S_BOSS_RUN5,0,0}, // S_BOSS_RUN4 {SPR_BOSS,2,3,A_Chase,S_BOSS_RUN6,0,0}, // S_BOSS_RUN5 {SPR_BOSS,2,3,A_Chase,S_BOSS_RUN7,0,0}, // S_BOSS_RUN6 {SPR_BOSS,3,3,A_Chase,S_BOSS_RUN8,0,0}, // S_BOSS_RUN7 {SPR_BOSS,3,3,A_Chase,S_BOSS_RUN1,0,0}, // S_BOSS_RUN8 {SPR_BOSS,4,8,A_FaceTarget,S_BOSS_ATK2,0,0}, // S_BOSS_ATK1 {SPR_BOSS,5,8,A_FaceTarget,S_BOSS_ATK3,0,0}, // S_BOSS_ATK2 {SPR_BOSS,6,8,A_BruisAttack,S_BOSS_RUN1,0,0}, // S_BOSS_ATK3 {SPR_BOSS,7,2,NULL,S_BOSS_PAIN2,0,0}, // S_BOSS_PAIN {SPR_BOSS,7,2,A_Pain,S_BOSS_RUN1,0,0}, // S_BOSS_PAIN2 {SPR_BOSS,8,8,NULL,S_BOSS_DIE2,0,0}, // S_BOSS_DIE1 {SPR_BOSS,9,8,A_Scream,S_BOSS_DIE3,0,0}, // S_BOSS_DIE2 {SPR_BOSS,10,8,NULL,S_BOSS_DIE4,0,0}, // S_BOSS_DIE3 {SPR_BOSS,11,8,A_Fall,S_BOSS_DIE5,0,0}, // S_BOSS_DIE4 {SPR_BOSS,12,8,NULL,S_BOSS_DIE6,0,0}, // S_BOSS_DIE5 {SPR_BOSS,13,8,NULL,S_BOSS_DIE7,0,0}, // S_BOSS_DIE6 {SPR_BOSS,14,-1,A_BossDeath,S_NULL,0,0}, // S_BOSS_DIE7 {SPR_BOSS,14,8,NULL,S_BOSS_RAISE2,0,0}, // S_BOSS_RAISE1 {SPR_BOSS,13,8,NULL,S_BOSS_RAISE3,0,0}, // S_BOSS_RAISE2 {SPR_BOSS,12,8,NULL,S_BOSS_RAISE4,0,0}, // S_BOSS_RAISE3 {SPR_BOSS,11,8,NULL,S_BOSS_RAISE5,0,0}, // S_BOSS_RAISE4 {SPR_BOSS,10,8,NULL,S_BOSS_RAISE6,0,0}, // S_BOSS_RAISE5 {SPR_BOSS,9,8,NULL,S_BOSS_RAISE7,0,0}, // S_BOSS_RAISE6 {SPR_BOSS,8,8,NULL,S_BOSS_RUN1,0,0}, // S_BOSS_RAISE7 {SPR_BOS2,0,10,A_Look,S_BOS2_STND2,0,0}, // S_BOS2_STND {SPR_BOS2,1,10,A_Look,S_BOS2_STND,0,0}, // S_BOS2_STND2 {SPR_BOS2,0,3,A_Chase,S_BOS2_RUN2,0,0}, // S_BOS2_RUN1 {SPR_BOS2,0,3,A_Chase,S_BOS2_RUN3,0,0}, // S_BOS2_RUN2 {SPR_BOS2,1,3,A_Chase,S_BOS2_RUN4,0,0}, // S_BOS2_RUN3 {SPR_BOS2,1,3,A_Chase,S_BOS2_RUN5,0,0}, // S_BOS2_RUN4 {SPR_BOS2,2,3,A_Chase,S_BOS2_RUN6,0,0}, // S_BOS2_RUN5 {SPR_BOS2,2,3,A_Chase,S_BOS2_RUN7,0,0}, // S_BOS2_RUN6 {SPR_BOS2,3,3,A_Chase,S_BOS2_RUN8,0,0}, // S_BOS2_RUN7 {SPR_BOS2,3,3,A_Chase,S_BOS2_RUN1,0,0}, // S_BOS2_RUN8 {SPR_BOS2,4,8,A_FaceTarget,S_BOS2_ATK2,0,0}, // S_BOS2_ATK1 {SPR_BOS2,5,8,A_FaceTarget,S_BOS2_ATK3,0,0}, // S_BOS2_ATK2 {SPR_BOS2,6,8,A_BruisAttack,S_BOS2_RUN1,0,0}, // S_BOS2_ATK3 {SPR_BOS2,7,2,NULL,S_BOS2_PAIN2,0,0}, // S_BOS2_PAIN {SPR_BOS2,7,2,A_Pain,S_BOS2_RUN1,0,0}, // S_BOS2_PAIN2 {SPR_BOS2,8,8,NULL,S_BOS2_DIE2,0,0}, // S_BOS2_DIE1 {SPR_BOS2,9,8,A_Scream,S_BOS2_DIE3,0,0}, // S_BOS2_DIE2 {SPR_BOS2,10,8,NULL,S_BOS2_DIE4,0,0}, // S_BOS2_DIE3 {SPR_BOS2,11,8,A_Fall,S_BOS2_DIE5,0,0}, // S_BOS2_DIE4 {SPR_BOS2,12,8,NULL,S_BOS2_DIE6,0,0}, // S_BOS2_DIE5 {SPR_BOS2,13,8,NULL,S_BOS2_DIE7,0,0}, // S_BOS2_DIE6 {SPR_BOS2,14,-1,NULL,S_NULL,0,0}, // S_BOS2_DIE7 {SPR_BOS2,14,8,NULL,S_BOS2_RAISE2,0,0}, // S_BOS2_RAISE1 {SPR_BOS2,13,8,NULL,S_BOS2_RAISE3,0,0}, // S_BOS2_RAISE2 {SPR_BOS2,12,8,NULL,S_BOS2_RAISE4,0,0}, // S_BOS2_RAISE3 {SPR_BOS2,11,8,NULL,S_BOS2_RAISE5,0,0}, // S_BOS2_RAISE4 {SPR_BOS2,10,8,NULL,S_BOS2_RAISE6,0,0}, // S_BOS2_RAISE5 {SPR_BOS2,9,8,NULL,S_BOS2_RAISE7,0,0}, // S_BOS2_RAISE6 {SPR_BOS2,8,8,NULL,S_BOS2_RUN1,0,0}, // S_BOS2_RAISE7 {SPR_SKUL,32768,10,A_Look,S_SKULL_STND2,0,0}, // S_SKULL_STND {SPR_SKUL,32769,10,A_Look,S_SKULL_STND,0,0}, // S_SKULL_STND2 {SPR_SKUL,32768,6,A_Chase,S_SKULL_RUN2,0,0}, // S_SKULL_RUN1 {SPR_SKUL,32769,6,A_Chase,S_SKULL_RUN1,0,0}, // S_SKULL_RUN2 {SPR_SKUL,32770,10,A_FaceTarget,S_SKULL_ATK2,0,0}, // S_SKULL_ATK1 {SPR_SKUL,32771,4,A_SkullAttack,S_SKULL_ATK3,0,0}, // S_SKULL_ATK2 {SPR_SKUL,32770,4,NULL,S_SKULL_ATK4,0,0}, // S_SKULL_ATK3 {SPR_SKUL,32771,4,NULL,S_SKULL_ATK3,0,0}, // S_SKULL_ATK4 {SPR_SKUL,32772,3,NULL,S_SKULL_PAIN2,0,0}, // S_SKULL_PAIN {SPR_SKUL,32772,3,A_Pain,S_SKULL_RUN1,0,0}, // S_SKULL_PAIN2 {SPR_SKUL,32773,6,NULL,S_SKULL_DIE2,0,0}, // S_SKULL_DIE1 {SPR_SKUL,32774,6,A_Scream,S_SKULL_DIE3,0,0}, // S_SKULL_DIE2 {SPR_SKUL,32775,6,NULL,S_SKULL_DIE4,0,0}, // S_SKULL_DIE3 {SPR_SKUL,32776,6,A_Fall,S_SKULL_DIE5,0,0}, // S_SKULL_DIE4 {SPR_SKUL,9,6,NULL,S_SKULL_DIE6,0,0}, // S_SKULL_DIE5 {SPR_SKUL,10,6,NULL,S_NULL,0,0}, // S_SKULL_DIE6 {SPR_SPID,0,10,A_Look,S_SPID_STND2,0,0}, // S_SPID_STND {SPR_SPID,1,10,A_Look,S_SPID_STND,0,0}, // S_SPID_STND2 {SPR_SPID,0,3,A_Metal,S_SPID_RUN2,0,0}, // S_SPID_RUN1 {SPR_SPID,0,3,A_Chase,S_SPID_RUN3,0,0}, // S_SPID_RUN2 {SPR_SPID,1,3,A_Chase,S_SPID_RUN4,0,0}, // S_SPID_RUN3 {SPR_SPID,1,3,A_Chase,S_SPID_RUN5,0,0}, // S_SPID_RUN4 {SPR_SPID,2,3,A_Metal,S_SPID_RUN6,0,0}, // S_SPID_RUN5 {SPR_SPID,2,3,A_Chase,S_SPID_RUN7,0,0}, // S_SPID_RUN6 {SPR_SPID,3,3,A_Chase,S_SPID_RUN8,0,0}, // S_SPID_RUN7 {SPR_SPID,3,3,A_Chase,S_SPID_RUN9,0,0}, // S_SPID_RUN8 {SPR_SPID,4,3,A_Metal,S_SPID_RUN10,0,0}, // S_SPID_RUN9 {SPR_SPID,4,3,A_Chase,S_SPID_RUN11,0,0}, // S_SPID_RUN10 {SPR_SPID,5,3,A_Chase,S_SPID_RUN12,0,0}, // S_SPID_RUN11 {SPR_SPID,5,3,A_Chase,S_SPID_RUN1,0,0}, // S_SPID_RUN12 {SPR_SPID,32768,20,A_FaceTarget,S_SPID_ATK2,0,0}, // S_SPID_ATK1 {SPR_SPID,32774,4,A_SPosAttack,S_SPID_ATK3,0,0}, // S_SPID_ATK2 {SPR_SPID,32775,4,A_SPosAttack,S_SPID_ATK4,0,0}, // S_SPID_ATK3 {SPR_SPID,32775,1,A_SpidRefire,S_SPID_ATK2,0,0}, // S_SPID_ATK4 {SPR_SPID,8,3,NULL,S_SPID_PAIN2,0,0}, // S_SPID_PAIN {SPR_SPID,8,3,A_Pain,S_SPID_RUN1,0,0}, // S_SPID_PAIN2 {SPR_SPID,9,20,A_Scream,S_SPID_DIE2,0,0}, // S_SPID_DIE1 {SPR_SPID,10,10,A_Fall,S_SPID_DIE3,0,0}, // S_SPID_DIE2 {SPR_SPID,11,10,NULL,S_SPID_DIE4,0,0}, // S_SPID_DIE3 {SPR_SPID,12,10,NULL,S_SPID_DIE5,0,0}, // S_SPID_DIE4 {SPR_SPID,13,10,NULL,S_SPID_DIE6,0,0}, // S_SPID_DIE5 {SPR_SPID,14,10,NULL,S_SPID_DIE7,0,0}, // S_SPID_DIE6 {SPR_SPID,15,10,NULL,S_SPID_DIE8,0,0}, // S_SPID_DIE7 {SPR_SPID,16,10,NULL,S_SPID_DIE9,0,0}, // S_SPID_DIE8 {SPR_SPID,17,10,NULL,S_SPID_DIE10,0,0}, // S_SPID_DIE9 {SPR_SPID,18,30,NULL,S_SPID_DIE11,0,0}, // S_SPID_DIE10 {SPR_SPID,18,-1,A_BossDeath,S_NULL,0,0}, // S_SPID_DIE11 {SPR_BSPI,0,10,A_Look,S_BSPI_STND2,0,0}, // S_BSPI_STND {SPR_BSPI,1,10,A_Look,S_BSPI_STND,0,0}, // S_BSPI_STND2 {SPR_BSPI,0,20,NULL,S_BSPI_RUN1,0,0}, // S_BSPI_SIGHT {SPR_BSPI,0,3,A_BabyMetal,S_BSPI_RUN2,0,0}, // S_BSPI_RUN1 {SPR_BSPI,0,3,A_Chase,S_BSPI_RUN3,0,0}, // S_BSPI_RUN2 {SPR_BSPI,1,3,A_Chase,S_BSPI_RUN4,0,0}, // S_BSPI_RUN3 {SPR_BSPI,1,3,A_Chase,S_BSPI_RUN5,0,0}, // S_BSPI_RUN4 {SPR_BSPI,2,3,A_Chase,S_BSPI_RUN6,0,0}, // S_BSPI_RUN5 {SPR_BSPI,2,3,A_Chase,S_BSPI_RUN7,0,0}, // S_BSPI_RUN6 {SPR_BSPI,3,3,A_BabyMetal,S_BSPI_RUN8,0,0}, // S_BSPI_RUN7 {SPR_BSPI,3,3,A_Chase,S_BSPI_RUN9,0,0}, // S_BSPI_RUN8 {SPR_BSPI,4,3,A_Chase,S_BSPI_RUN10,0,0}, // S_BSPI_RUN9 {SPR_BSPI,4,3,A_Chase,S_BSPI_RUN11,0,0}, // S_BSPI_RUN10 {SPR_BSPI,5,3,A_Chase,S_BSPI_RUN12,0,0}, // S_BSPI_RUN11 {SPR_BSPI,5,3,A_Chase,S_BSPI_RUN1,0,0}, // S_BSPI_RUN12 {SPR_BSPI,32768,20,A_FaceTarget,S_BSPI_ATK2,0,0}, // S_BSPI_ATK1 {SPR_BSPI,32774,4,A_BspiAttack,S_BSPI_ATK3,0,0}, // S_BSPI_ATK2 {SPR_BSPI,32775,4,NULL,S_BSPI_ATK4,0,0}, // S_BSPI_ATK3 {SPR_BSPI,32775,1,A_SpidRefire,S_BSPI_ATK2,0,0}, // S_BSPI_ATK4 {SPR_BSPI,8,3,NULL,S_BSPI_PAIN2,0,0}, // S_BSPI_PAIN {SPR_BSPI,8,3,A_Pain,S_BSPI_RUN1,0,0}, // S_BSPI_PAIN2 {SPR_BSPI,9,20,A_Scream,S_BSPI_DIE2,0,0}, // S_BSPI_DIE1 {SPR_BSPI,10,7,A_Fall,S_BSPI_DIE3,0,0}, // S_BSPI_DIE2 {SPR_BSPI,11,7,NULL,S_BSPI_DIE4,0,0}, // S_BSPI_DIE3 {SPR_BSPI,12,7,NULL,S_BSPI_DIE5,0,0}, // S_BSPI_DIE4 {SPR_BSPI,13,7,NULL,S_BSPI_DIE6,0,0}, // S_BSPI_DIE5 {SPR_BSPI,14,7,NULL,S_BSPI_DIE7,0,0}, // S_BSPI_DIE6 {SPR_BSPI,15,-1,A_BossDeath,S_NULL,0,0}, // S_BSPI_DIE7 {SPR_BSPI,15,5,NULL,S_BSPI_RAISE2,0,0}, // S_BSPI_RAISE1 {SPR_BSPI,14,5,NULL,S_BSPI_RAISE3,0,0}, // S_BSPI_RAISE2 {SPR_BSPI,13,5,NULL,S_BSPI_RAISE4,0,0}, // S_BSPI_RAISE3 {SPR_BSPI,12,5,NULL,S_BSPI_RAISE5,0,0}, // S_BSPI_RAISE4 {SPR_BSPI,11,5,NULL,S_BSPI_RAISE6,0,0}, // S_BSPI_RAISE5 {SPR_BSPI,10,5,NULL,S_BSPI_RAISE7,0,0}, // S_BSPI_RAISE6 {SPR_BSPI,9,5,NULL,S_BSPI_RUN1,0,0}, // S_BSPI_RAISE7 {SPR_APLS,32768,5,NULL,S_ARACH_PLAZ2,0,0}, // S_ARACH_PLAZ {SPR_APLS,32769,5,NULL,S_ARACH_PLAZ,0,0}, // S_ARACH_PLAZ2 {SPR_APBX,32768,5,NULL,S_ARACH_PLEX2,0,0}, // S_ARACH_PLEX {SPR_APBX,32769,5,NULL,S_ARACH_PLEX3,0,0}, // S_ARACH_PLEX2 {SPR_APBX,32770,5,NULL,S_ARACH_PLEX4,0,0}, // S_ARACH_PLEX3 {SPR_APBX,32771,5,NULL,S_ARACH_PLEX5,0,0}, // S_ARACH_PLEX4 {SPR_APBX,32772,5,NULL,S_NULL,0,0}, // S_ARACH_PLEX5 {SPR_CYBR,0,10,A_Look,S_CYBER_STND2,0,0}, // S_CYBER_STND {SPR_CYBR,1,10,A_Look,S_CYBER_STND,0,0}, // S_CYBER_STND2 {SPR_CYBR,0,3,A_Hoof,S_CYBER_RUN2,0,0}, // S_CYBER_RUN1 {SPR_CYBR,0,3,A_Chase,S_CYBER_RUN3,0,0}, // S_CYBER_RUN2 {SPR_CYBR,1,3,A_Chase,S_CYBER_RUN4,0,0}, // S_CYBER_RUN3 {SPR_CYBR,1,3,A_Chase,S_CYBER_RUN5,0,0}, // S_CYBER_RUN4 {SPR_CYBR,2,3,A_Chase,S_CYBER_RUN6,0,0}, // S_CYBER_RUN5 {SPR_CYBR,2,3,A_Chase,S_CYBER_RUN7,0,0}, // S_CYBER_RUN6 {SPR_CYBR,3,3,A_Metal,S_CYBER_RUN8,0,0}, // S_CYBER_RUN7 {SPR_CYBR,3,3,A_Chase,S_CYBER_RUN1,0,0}, // S_CYBER_RUN8 {SPR_CYBR,4,6,A_FaceTarget,S_CYBER_ATK2,0,0}, // S_CYBER_ATK1 {SPR_CYBR,5,12,A_CyberAttack,S_CYBER_ATK3,0,0}, // S_CYBER_ATK2 {SPR_CYBR,4,12,A_FaceTarget,S_CYBER_ATK4,0,0}, // S_CYBER_ATK3 {SPR_CYBR,5,12,A_CyberAttack,S_CYBER_ATK5,0,0}, // S_CYBER_ATK4 {SPR_CYBR,4,12,A_FaceTarget,S_CYBER_ATK6,0,0}, // S_CYBER_ATK5 {SPR_CYBR,5,12,A_CyberAttack,S_CYBER_RUN1,0,0}, // S_CYBER_ATK6 {SPR_CYBR,6,10,A_Pain,S_CYBER_RUN1,0,0}, // S_CYBER_PAIN {SPR_CYBR,7,10,NULL,S_CYBER_DIE2,0,0}, // S_CYBER_DIE1 {SPR_CYBR,8,10,A_Scream,S_CYBER_DIE3,0,0}, // S_CYBER_DIE2 {SPR_CYBR,9,10,NULL,S_CYBER_DIE4,0,0}, // S_CYBER_DIE3 {SPR_CYBR,10,10,NULL,S_CYBER_DIE5,0,0}, // S_CYBER_DIE4 {SPR_CYBR,11,10,NULL,S_CYBER_DIE6,0,0}, // S_CYBER_DIE5 {SPR_CYBR,12,10,A_Fall,S_CYBER_DIE7,0,0}, // S_CYBER_DIE6 {SPR_CYBR,13,10,NULL,S_CYBER_DIE8,0,0}, // S_CYBER_DIE7 {SPR_CYBR,14,10,NULL,S_CYBER_DIE9,0,0}, // S_CYBER_DIE8 {SPR_CYBR,15,30,NULL,S_CYBER_DIE10,0,0}, // S_CYBER_DIE9 {SPR_CYBR,15,-1,A_BossDeath,S_NULL,0,0}, // S_CYBER_DIE10 {SPR_PAIN,0,10,A_Look,S_PAIN_STND,0,0}, // S_PAIN_STND {SPR_PAIN,0,3,A_Chase,S_PAIN_RUN2,0,0}, // S_PAIN_RUN1 {SPR_PAIN,0,3,A_Chase,S_PAIN_RUN3,0,0}, // S_PAIN_RUN2 {SPR_PAIN,1,3,A_Chase,S_PAIN_RUN4,0,0}, // S_PAIN_RUN3 {SPR_PAIN,1,3,A_Chase,S_PAIN_RUN5,0,0}, // S_PAIN_RUN4 {SPR_PAIN,2,3,A_Chase,S_PAIN_RUN6,0,0}, // S_PAIN_RUN5 {SPR_PAIN,2,3,A_Chase,S_PAIN_RUN1,0,0}, // S_PAIN_RUN6 {SPR_PAIN,3,5,A_FaceTarget,S_PAIN_ATK2,0,0}, // S_PAIN_ATK1 {SPR_PAIN,4,5,A_FaceTarget,S_PAIN_ATK3,0,0}, // S_PAIN_ATK2 {SPR_PAIN,32773,5,A_FaceTarget,S_PAIN_ATK4,0,0}, // S_PAIN_ATK3 {SPR_PAIN,32773,0,A_PainAttack,S_PAIN_RUN1,0,0}, // S_PAIN_ATK4 {SPR_PAIN,6,6,NULL,S_PAIN_PAIN2,0,0}, // S_PAIN_PAIN {SPR_PAIN,6,6,A_Pain,S_PAIN_RUN1,0,0}, // S_PAIN_PAIN2 {SPR_PAIN,32775,8,NULL,S_PAIN_DIE2,0,0}, // S_PAIN_DIE1 {SPR_PAIN,32776,8,A_Scream,S_PAIN_DIE3,0,0}, // S_PAIN_DIE2 {SPR_PAIN,32777,8,NULL,S_PAIN_DIE4,0,0}, // S_PAIN_DIE3 {SPR_PAIN,32778,8,NULL,S_PAIN_DIE5,0,0}, // S_PAIN_DIE4 {SPR_PAIN,32779,8,A_PainDie,S_PAIN_DIE6,0,0}, // S_PAIN_DIE5 {SPR_PAIN,32780,8,NULL,S_NULL,0,0}, // S_PAIN_DIE6 {SPR_PAIN,12,8,NULL,S_PAIN_RAISE2,0,0}, // S_PAIN_RAISE1 {SPR_PAIN,11,8,NULL,S_PAIN_RAISE3,0,0}, // S_PAIN_RAISE2 {SPR_PAIN,10,8,NULL,S_PAIN_RAISE4,0,0}, // S_PAIN_RAISE3 {SPR_PAIN,9,8,NULL,S_PAIN_RAISE5,0,0}, // S_PAIN_RAISE4 {SPR_PAIN,8,8,NULL,S_PAIN_RAISE6,0,0}, // S_PAIN_RAISE5 {SPR_PAIN,7,8,NULL,S_PAIN_RUN1,0,0}, // S_PAIN_RAISE6 {SPR_SSWV,0,10,A_Look,S_SSWV_STND2,0,0}, // S_SSWV_STND {SPR_SSWV,1,10,A_Look,S_SSWV_STND,0,0}, // S_SSWV_STND2 {SPR_SSWV,0,3,A_Chase,S_SSWV_RUN2,0,0}, // S_SSWV_RUN1 {SPR_SSWV,0,3,A_Chase,S_SSWV_RUN3,0,0}, // S_SSWV_RUN2 {SPR_SSWV,1,3,A_Chase,S_SSWV_RUN4,0,0}, // S_SSWV_RUN3 {SPR_SSWV,1,3,A_Chase,S_SSWV_RUN5,0,0}, // S_SSWV_RUN4 {SPR_SSWV,2,3,A_Chase,S_SSWV_RUN6,0,0}, // S_SSWV_RUN5 {SPR_SSWV,2,3,A_Chase,S_SSWV_RUN7,0,0}, // S_SSWV_RUN6 {SPR_SSWV,3,3,A_Chase,S_SSWV_RUN8,0,0}, // S_SSWV_RUN7 {SPR_SSWV,3,3,A_Chase,S_SSWV_RUN1,0,0}, // S_SSWV_RUN8 {SPR_SSWV,4,10,A_FaceTarget,S_SSWV_ATK2,0,0}, // S_SSWV_ATK1 {SPR_SSWV,5,10,A_FaceTarget,S_SSWV_ATK3,0,0}, // S_SSWV_ATK2 {SPR_SSWV,32774,4,A_CPosAttack,S_SSWV_ATK4,0,0}, // S_SSWV_ATK3 {SPR_SSWV,5,6,A_FaceTarget,S_SSWV_ATK5,0,0}, // S_SSWV_ATK4 {SPR_SSWV,32774,4,A_CPosAttack,S_SSWV_ATK6,0,0}, // S_SSWV_ATK5 {SPR_SSWV,5,1,A_CPosRefire,S_SSWV_ATK2,0,0}, // S_SSWV_ATK6 {SPR_SSWV,7,3,NULL,S_SSWV_PAIN2,0,0}, // S_SSWV_PAIN {SPR_SSWV,7,3,A_Pain,S_SSWV_RUN1,0,0}, // S_SSWV_PAIN2 {SPR_SSWV,8,5,NULL,S_SSWV_DIE2,0,0}, // S_SSWV_DIE1 {SPR_SSWV,9,5,A_Scream,S_SSWV_DIE3,0,0}, // S_SSWV_DIE2 {SPR_SSWV,10,5,A_Fall,S_SSWV_DIE4,0,0}, // S_SSWV_DIE3 {SPR_SSWV,11,5,NULL,S_SSWV_DIE5,0,0}, // S_SSWV_DIE4 {SPR_SSWV,12,-1,NULL,S_NULL,0,0}, // S_SSWV_DIE5 {SPR_SSWV,13,5,NULL,S_SSWV_XDIE2,0,0}, // S_SSWV_XDIE1 {SPR_SSWV,14,5,A_XScream,S_SSWV_XDIE3,0,0}, // S_SSWV_XDIE2 {SPR_SSWV,15,5,A_Fall,S_SSWV_XDIE4,0,0}, // S_SSWV_XDIE3 {SPR_SSWV,16,5,NULL,S_SSWV_XDIE5,0,0}, // S_SSWV_XDIE4 {SPR_SSWV,17,5,NULL,S_SSWV_XDIE6,0,0}, // S_SSWV_XDIE5 {SPR_SSWV,18,5,NULL,S_SSWV_XDIE7,0,0}, // S_SSWV_XDIE6 {SPR_SSWV,19,5,NULL,S_SSWV_XDIE8,0,0}, // S_SSWV_XDIE7 {SPR_SSWV,20,5,NULL,S_SSWV_XDIE9,0,0}, // S_SSWV_XDIE8 {SPR_SSWV,21,-1,NULL,S_NULL,0,0}, // S_SSWV_XDIE9 {SPR_SSWV,12,5,NULL,S_SSWV_RAISE2,0,0}, // S_SSWV_RAISE1 {SPR_SSWV,11,5,NULL,S_SSWV_RAISE3,0,0}, // S_SSWV_RAISE2 {SPR_SSWV,10,5,NULL,S_SSWV_RAISE4,0,0}, // S_SSWV_RAISE3 {SPR_SSWV,9,5,NULL,S_SSWV_RAISE5,0,0}, // S_SSWV_RAISE4 {SPR_SSWV,8,5,NULL,S_SSWV_RUN1,0,0}, // S_SSWV_RAISE5 {SPR_KEEN,0,-1,NULL,S_KEENSTND,0,0}, // S_KEENSTND {SPR_KEEN,0,6,NULL,S_COMMKEEN2,0,0}, // S_COMMKEEN {SPR_KEEN,1,6,NULL,S_COMMKEEN3,0,0}, // S_COMMKEEN2 {SPR_KEEN,2,6,A_Scream,S_COMMKEEN4,0,0}, // S_COMMKEEN3 {SPR_KEEN,3,6,NULL,S_COMMKEEN5,0,0}, // S_COMMKEEN4 {SPR_KEEN,4,6,NULL,S_COMMKEEN6,0,0}, // S_COMMKEEN5 {SPR_KEEN,5,6,NULL,S_COMMKEEN7,0,0}, // S_COMMKEEN6 {SPR_KEEN,6,6,NULL,S_COMMKEEN8,0,0}, // S_COMMKEEN7 {SPR_KEEN,7,6,NULL,S_COMMKEEN9,0,0}, // S_COMMKEEN8 {SPR_KEEN,8,6,NULL,S_COMMKEEN10,0,0}, // S_COMMKEEN9 {SPR_KEEN,9,6,NULL,S_COMMKEEN11,0,0}, // S_COMMKEEN10 {SPR_KEEN,10,6,A_KeenDie,S_COMMKEEN12,0,0}, // S_COMMKEEN11 {SPR_KEEN,11,-1,NULL,S_NULL,0,0}, // S_COMMKEEN12 {SPR_KEEN,12,4,NULL,S_KEENPAIN2,0,0}, // S_KEENPAIN {SPR_KEEN,12,8,A_Pain,S_KEENSTND,0,0}, // S_KEENPAIN2 {SPR_BBRN,0,-1,NULL,S_NULL,0,0}, // S_BRAIN {SPR_BBRN,1,36,A_BrainPain,S_BRAIN,0,0}, // S_BRAIN_PAIN {SPR_BBRN,0,100,A_BrainScream,S_BRAIN_DIE2,0,0}, // S_BRAIN_DIE1 {SPR_BBRN,0,10,NULL,S_BRAIN_DIE3,0,0}, // S_BRAIN_DIE2 {SPR_BBRN,0,10,NULL,S_BRAIN_DIE4,0,0}, // S_BRAIN_DIE3 {SPR_BBRN,0,-1,A_BrainDie,S_NULL,0,0}, // S_BRAIN_DIE4 {SPR_SSWV,0,10,A_Look,S_BRAINEYE,0,0}, // S_BRAINEYE {SPR_SSWV,0,181,A_BrainAwake,S_BRAINEYE1,0,0}, // S_BRAINEYESEE {SPR_SSWV,0,150,A_BrainSpit,S_BRAINEYE1,0,0}, // S_BRAINEYE1 {SPR_BOSF,32768,3,A_SpawnSound,S_SPAWN2,0,0}, // S_SPAWN1 {SPR_BOSF,32769,3,A_SpawnFly,S_SPAWN3,0,0}, // S_SPAWN2 {SPR_BOSF,32770,3,A_SpawnFly,S_SPAWN4,0,0}, // S_SPAWN3 {SPR_BOSF,32771,3,A_SpawnFly,S_SPAWN1,0,0}, // S_SPAWN4 {SPR_FIRE,32768,4,A_Fire,S_SPAWNFIRE2,0,0}, // S_SPAWNFIRE1 {SPR_FIRE,32769,4,A_Fire,S_SPAWNFIRE3,0,0}, // S_SPAWNFIRE2 {SPR_FIRE,32770,4,A_Fire,S_SPAWNFIRE4,0,0}, // S_SPAWNFIRE3 {SPR_FIRE,32771,4,A_Fire,S_SPAWNFIRE5,0,0}, // S_SPAWNFIRE4 {SPR_FIRE,32772,4,A_Fire,S_SPAWNFIRE6,0,0}, // S_SPAWNFIRE5 {SPR_FIRE,32773,4,A_Fire,S_SPAWNFIRE7,0,0}, // S_SPAWNFIRE6 {SPR_FIRE,32774,4,A_Fire,S_SPAWNFIRE8,0,0}, // S_SPAWNFIRE7 {SPR_FIRE,32775,4,A_Fire,S_NULL,0,0}, // S_SPAWNFIRE8 {SPR_MISL,32769,10,NULL,S_BRAINEXPLODE2,0,0}, // S_BRAINEXPLODE1 {SPR_MISL,32770,10,NULL,S_BRAINEXPLODE3,0,0}, // S_BRAINEXPLODE2 {SPR_MISL,32771,10,A_BrainExplode,S_NULL,0,0}, // S_BRAINEXPLODE3 {SPR_ARM1,0,6,NULL,S_ARM1A,0,0}, // S_ARM1 {SPR_ARM1,32769,7,NULL,S_ARM1,0,0}, // S_ARM1A {SPR_ARM2,0,6,NULL,S_ARM2A,0,0}, // S_ARM2 {SPR_ARM2,32769,6,NULL,S_ARM2,0,0}, // S_ARM2A {SPR_BAR1,0,6,NULL,S_BAR2,0,0}, // S_BAR1 {SPR_BAR1,1,6,NULL,S_BAR1,0,0}, // S_BAR2 {SPR_BEXP,32768,5,NULL,S_BEXP2,0,0}, // S_BEXP {SPR_BEXP,32769,5,A_Scream,S_BEXP3,0,0}, // S_BEXP2 {SPR_BEXP,32770,5,NULL,S_BEXP4,0,0}, // S_BEXP3 {SPR_BEXP,32771,10,A_Explode,S_BEXP5,0,0}, // S_BEXP4 {SPR_BEXP,32772,10,NULL,S_NULL,0,0}, // S_BEXP5 {SPR_FCAN,32768,4,NULL,S_BBAR2,0,0}, // S_BBAR1 {SPR_FCAN,32769,4,NULL,S_BBAR3,0,0}, // S_BBAR2 {SPR_FCAN,32770,4,NULL,S_BBAR1,0,0}, // S_BBAR3 {SPR_BON1,0,6,NULL,S_BON1A,0,0}, // S_BON1 {SPR_BON1,1,6,NULL,S_BON1B,0,0}, // S_BON1A {SPR_BON1,2,6,NULL,S_BON1C,0,0}, // S_BON1B {SPR_BON1,3,6,NULL,S_BON1D,0,0}, // S_BON1C {SPR_BON1,2,6,NULL,S_BON1E,0,0}, // S_BON1D {SPR_BON1,1,6,NULL,S_BON1,0,0}, // S_BON1E {SPR_BON2,0,6,NULL,S_BON2A,0,0}, // S_BON2 {SPR_BON2,1,6,NULL,S_BON2B,0,0}, // S_BON2A {SPR_BON2,2,6,NULL,S_BON2C,0,0}, // S_BON2B {SPR_BON2,3,6,NULL,S_BON2D,0,0}, // S_BON2C {SPR_BON2,2,6,NULL,S_BON2E,0,0}, // S_BON2D {SPR_BON2,1,6,NULL,S_BON2,0,0}, // S_BON2E {SPR_BKEY,0,10,NULL,S_BKEY2,0,0}, // S_BKEY {SPR_BKEY,32769,10,NULL,S_BKEY,0,0}, // S_BKEY2 {SPR_RKEY,0,10,NULL,S_RKEY2,0,0}, // S_RKEY {SPR_RKEY,32769,10,NULL,S_RKEY,0,0}, // S_RKEY2 {SPR_YKEY,0,10,NULL,S_YKEY2,0,0}, // S_YKEY {SPR_YKEY,32769,10,NULL,S_YKEY,0,0}, // S_YKEY2 {SPR_BSKU,0,10,NULL,S_BSKULL2,0,0}, // S_BSKULL {SPR_BSKU,32769,10,NULL,S_BSKULL,0,0}, // S_BSKULL2 {SPR_RSKU,0,10,NULL,S_RSKULL2,0,0}, // S_RSKULL {SPR_RSKU,32769,10,NULL,S_RSKULL,0,0}, // S_RSKULL2 {SPR_YSKU,0,10,NULL,S_YSKULL2,0,0}, // S_YSKULL {SPR_YSKU,32769,10,NULL,S_YSKULL,0,0}, // S_YSKULL2 {SPR_STIM,0,-1,NULL,S_NULL,0,0}, // S_STIM {SPR_MEDI,0,-1,NULL,S_NULL,0,0}, // S_MEDI {SPR_SOUL,32768,6,NULL,S_SOUL2,0,0}, // S_SOUL {SPR_SOUL,32769,6,NULL,S_SOUL3,0,0}, // S_SOUL2 {SPR_SOUL,32770,6,NULL,S_SOUL4,0,0}, // S_SOUL3 {SPR_SOUL,32771,6,NULL,S_SOUL5,0,0}, // S_SOUL4 {SPR_SOUL,32770,6,NULL,S_SOUL6,0,0}, // S_SOUL5 {SPR_SOUL,32769,6,NULL,S_SOUL,0,0}, // S_SOUL6 {SPR_PINV,32768,6,NULL,S_PINV2,0,0}, // S_PINV {SPR_PINV,32769,6,NULL,S_PINV3,0,0}, // S_PINV2 {SPR_PINV,32770,6,NULL,S_PINV4,0,0}, // S_PINV3 {SPR_PINV,32771,6,NULL,S_PINV,0,0}, // S_PINV4 {SPR_PSTR,32768,-1,NULL,S_NULL,0,0}, // S_PSTR {SPR_PINS,32768,6,NULL,S_PINS2,0,0}, // S_PINS {SPR_PINS,32769,6,NULL,S_PINS3,0,0}, // S_PINS2 {SPR_PINS,32770,6,NULL,S_PINS4,0,0}, // S_PINS3 {SPR_PINS,32771,6,NULL,S_PINS,0,0}, // S_PINS4 {SPR_MEGA,32768,6,NULL,S_MEGA2,0,0}, // S_MEGA {SPR_MEGA,32769,6,NULL,S_MEGA3,0,0}, // S_MEGA2 {SPR_MEGA,32770,6,NULL,S_MEGA4,0,0}, // S_MEGA3 {SPR_MEGA,32771,6,NULL,S_MEGA,0,0}, // S_MEGA4 {SPR_SUIT,32768,-1,NULL,S_NULL,0,0}, // S_SUIT {SPR_PMAP,32768,6,NULL,S_PMAP2,0,0}, // S_PMAP {SPR_PMAP,32769,6,NULL,S_PMAP3,0,0}, // S_PMAP2 {SPR_PMAP,32770,6,NULL,S_PMAP4,0,0}, // S_PMAP3 {SPR_PMAP,32771,6,NULL,S_PMAP5,0,0}, // S_PMAP4 {SPR_PMAP,32770,6,NULL,S_PMAP6,0,0}, // S_PMAP5 {SPR_PMAP,32769,6,NULL,S_PMAP,0,0}, // S_PMAP6 {SPR_PVIS,32768,6,NULL,S_PVIS2,0,0}, // S_PVIS {SPR_PVIS,1,6,NULL,S_PVIS,0,0}, // S_PVIS2 {SPR_CLIP,0,-1,NULL,S_NULL,0,0}, // S_CLIP {SPR_AMMO,0,-1,NULL,S_NULL,0,0}, // S_AMMO {SPR_ROCK,0,-1,NULL,S_NULL,0,0}, // S_ROCK {SPR_BROK,0,-1,NULL,S_NULL,0,0}, // S_BROK {SPR_CELL,0,-1,NULL,S_NULL,0,0}, // S_CELL {SPR_CELP,0,-1,NULL,S_NULL,0,0}, // S_CELP {SPR_SHEL,0,-1,NULL,S_NULL,0,0}, // S_SHEL {SPR_SBOX,0,-1,NULL,S_NULL,0,0}, // S_SBOX {SPR_BPAK,0,-1,NULL,S_NULL,0,0}, // S_BPAK {SPR_BFUG,0,-1,NULL,S_NULL,0,0}, // S_BFUG {SPR_MGUN,0,-1,NULL,S_NULL,0,0}, // S_MGUN {SPR_CSAW,0,-1,NULL,S_NULL,0,0}, // S_CSAW {SPR_LAUN,0,-1,NULL,S_NULL,0,0}, // S_LAUN {SPR_PLAS,0,-1,NULL,S_NULL,0,0}, // S_PLAS {SPR_SHOT,0,-1,NULL,S_NULL,0,0}, // S_SHOT {SPR_SGN2,0,-1,NULL,S_NULL,0,0}, // S_SHOT2 {SPR_COLU,32768,-1,NULL,S_NULL,0,0}, // S_COLU {SPR_SMT2,0,-1,NULL,S_NULL,0,0}, // S_STALAG {SPR_GOR1,0,10,NULL,S_BLOODYTWITCH2,0,0}, // S_BLOODYTWITCH {SPR_GOR1,1,15,NULL,S_BLOODYTWITCH3,0,0}, // S_BLOODYTWITCH2 {SPR_GOR1,2,8,NULL,S_BLOODYTWITCH4,0,0}, // S_BLOODYTWITCH3 {SPR_GOR1,1,6,NULL,S_BLOODYTWITCH,0,0}, // S_BLOODYTWITCH4 {SPR_PLAY,13,-1,NULL,S_NULL,0,0}, // S_DEADTORSO {SPR_PLAY,18,-1,NULL,S_NULL,0,0}, // S_DEADBOTTOM {SPR_POL2,0,-1,NULL,S_NULL,0,0}, // S_HEADSONSTICK {SPR_POL5,0,-1,NULL,S_NULL,0,0}, // S_GIBS {SPR_POL4,0,-1,NULL,S_NULL,0,0}, // S_HEADONASTICK {SPR_POL3,32768,6,NULL,S_HEADCANDLES2,0,0}, // S_HEADCANDLES {SPR_POL3,32769,6,NULL,S_HEADCANDLES,0,0}, // S_HEADCANDLES2 {SPR_POL1,0,-1,NULL,S_NULL,0,0}, // S_DEADSTICK {SPR_POL6,0,6,NULL,S_LIVESTICK2,0,0}, // S_LIVESTICK {SPR_POL6,1,8,NULL,S_LIVESTICK,0,0}, // S_LIVESTICK2 {SPR_GOR2,0,-1,NULL,S_NULL,0,0}, // S_MEAT2 {SPR_GOR3,0,-1,NULL,S_NULL,0,0}, // S_MEAT3 {SPR_GOR4,0,-1,NULL,S_NULL,0,0}, // S_MEAT4 {SPR_GOR5,0,-1,NULL,S_NULL,0,0}, // S_MEAT5 {SPR_SMIT,0,-1,NULL,S_NULL,0,0}, // S_STALAGTITE {SPR_COL1,0,-1,NULL,S_NULL,0,0}, // S_TALLGRNCOL {SPR_COL2,0,-1,NULL,S_NULL,0,0}, // S_SHRTGRNCOL {SPR_COL3,0,-1,NULL,S_NULL,0,0}, // S_TALLREDCOL {SPR_COL4,0,-1,NULL,S_NULL,0,0}, // S_SHRTREDCOL {SPR_CAND,32768,-1,NULL,S_NULL,0,0}, // S_CANDLESTIK {SPR_CBRA,32768,-1,NULL,S_NULL,0,0}, // S_CANDELABRA {SPR_COL6,0,-1,NULL,S_NULL,0,0}, // S_SKULLCOL {SPR_TRE1,0,-1,NULL,S_NULL,0,0}, // S_TORCHTREE {SPR_TRE2,0,-1,NULL,S_NULL,0,0}, // S_BIGTREE {SPR_ELEC,0,-1,NULL,S_NULL,0,0}, // S_TECHPILLAR {SPR_CEYE,32768,6,NULL,S_EVILEYE2,0,0}, // S_EVILEYE {SPR_CEYE,32769,6,NULL,S_EVILEYE3,0,0}, // S_EVILEYE2 {SPR_CEYE,32770,6,NULL,S_EVILEYE4,0,0}, // S_EVILEYE3 {SPR_CEYE,32769,6,NULL,S_EVILEYE,0,0}, // S_EVILEYE4 {SPR_FSKU,32768,6,NULL,S_FLOATSKULL2,0,0}, // S_FLOATSKULL {SPR_FSKU,32769,6,NULL,S_FLOATSKULL3,0,0}, // S_FLOATSKULL2 {SPR_FSKU,32770,6,NULL,S_FLOATSKULL,0,0}, // S_FLOATSKULL3 {SPR_COL5,0,14,NULL,S_HEARTCOL2,0,0}, // S_HEARTCOL {SPR_COL5,1,14,NULL,S_HEARTCOL,0,0}, // S_HEARTCOL2 {SPR_TBLU,32768,4,NULL,S_BLUETORCH2,0,0}, // S_BLUETORCH {SPR_TBLU,32769,4,NULL,S_BLUETORCH3,0,0}, // S_BLUETORCH2 {SPR_TBLU,32770,4,NULL,S_BLUETORCH4,0,0}, // S_BLUETORCH3 {SPR_TBLU,32771,4,NULL,S_BLUETORCH,0,0}, // S_BLUETORCH4 {SPR_TGRN,32768,4,NULL,S_GREENTORCH2,0,0}, // S_GREENTORCH {SPR_TGRN,32769,4,NULL,S_GREENTORCH3,0,0}, // S_GREENTORCH2 {SPR_TGRN,32770,4,NULL,S_GREENTORCH4,0,0}, // S_GREENTORCH3 {SPR_TGRN,32771,4,NULL,S_GREENTORCH,0,0}, // S_GREENTORCH4 {SPR_TRED,32768,4,NULL,S_REDTORCH2,0,0}, // S_REDTORCH {SPR_TRED,32769,4,NULL,S_REDTORCH3,0,0}, // S_REDTORCH2 {SPR_TRED,32770,4,NULL,S_REDTORCH4,0,0}, // S_REDTORCH3 {SPR_TRED,32771,4,NULL,S_REDTORCH,0,0}, // S_REDTORCH4 {SPR_SMBT,32768,4,NULL,S_BTORCHSHRT2,0,0}, // S_BTORCHSHRT {SPR_SMBT,32769,4,NULL,S_BTORCHSHRT3,0,0}, // S_BTORCHSHRT2 {SPR_SMBT,32770,4,NULL,S_BTORCHSHRT4,0,0}, // S_BTORCHSHRT3 {SPR_SMBT,32771,4,NULL,S_BTORCHSHRT,0,0}, // S_BTORCHSHRT4 {SPR_SMGT,32768,4,NULL,S_GTORCHSHRT2,0,0}, // S_GTORCHSHRT {SPR_SMGT,32769,4,NULL,S_GTORCHSHRT3,0,0}, // S_GTORCHSHRT2 {SPR_SMGT,32770,4,NULL,S_GTORCHSHRT4,0,0}, // S_GTORCHSHRT3 {SPR_SMGT,32771,4,NULL,S_GTORCHSHRT,0,0}, // S_GTORCHSHRT4 {SPR_SMRT,32768,4,NULL,S_RTORCHSHRT2,0,0}, // S_RTORCHSHRT {SPR_SMRT,32769,4,NULL,S_RTORCHSHRT3,0,0}, // S_RTORCHSHRT2 {SPR_SMRT,32770,4,NULL,S_RTORCHSHRT4,0,0}, // S_RTORCHSHRT3 {SPR_SMRT,32771,4,NULL,S_RTORCHSHRT,0,0}, // S_RTORCHSHRT4 {SPR_HDB1,0,-1,NULL,S_NULL,0,0}, // S_HANGNOGUTS {SPR_HDB2,0,-1,NULL,S_NULL,0,0}, // S_HANGBNOBRAIN {SPR_HDB3,0,-1,NULL,S_NULL,0,0}, // S_HANGTLOOKDN {SPR_HDB4,0,-1,NULL,S_NULL,0,0}, // S_HANGTSKULL {SPR_HDB5,0,-1,NULL,S_NULL,0,0}, // S_HANGTLOOKUP {SPR_HDB6,0,-1,NULL,S_NULL,0,0}, // S_HANGTNOBRAIN {SPR_POB1,0,-1,NULL,S_NULL,0,0}, // S_COLONGIBS {SPR_POB2,0,-1,NULL,S_NULL,0,0}, // S_SMALLPOOL {SPR_BRS1,0,-1,NULL,S_NULL,0,0}, // S_BRAINSTEM {SPR_TLMP,32768,4,NULL,S_TECHLAMP2,0,0}, // S_TECHLAMP {SPR_TLMP,32769,4,NULL,S_TECHLAMP3,0,0}, // S_TECHLAMP2 {SPR_TLMP,32770,4,NULL,S_TECHLAMP4,0,0}, // S_TECHLAMP3 {SPR_TLMP,32771,4,NULL,S_TECHLAMP,0,0}, // S_TECHLAMP4 {SPR_TLP2,32768,4,NULL,S_TECH2LAMP2,0,0}, // S_TECH2LAMP {SPR_TLP2,32769,4,NULL,S_TECH2LAMP3,0,0}, // S_TECH2LAMP2 {SPR_TLP2,32770,4,NULL,S_TECH2LAMP4,0,0}, // S_TECH2LAMP3 {SPR_TLP2,32771,4,NULL,S_TECH2LAMP,0,0} // S_TECH2LAMP4 }; mobjinfo_t mobjinfo[NUMMOBJTYPES] = { { // MT_PLAYER -1, // doomednum S_PLAY, // spawnstate 100, // spawnhealth S_PLAY_RUN1, // seestate sfx_None, // seesound 0, // reactiontime sfx_None, // attacksound S_PLAY_PAIN, // painstate 255, // painchance sfx_plpain, // painsound S_NULL, // meleestate S_PLAY_ATK1, // missilestate S_PLAY_DIE1, // deathstate S_PLAY_XDIE1, // xdeathstate sfx_pldeth, // deathsound 0, // speed 16*FRACUNIT, // radius 56*FRACUNIT, // height 100, // mass 0, // damage sfx_None, // activesound MF_SOLID|MF_SHOOTABLE|MF_DROPOFF|MF_PICKUP|MF_NOTDMATCH, // flags S_NULL // raisestate }, { // MT_POSSESSED 3004, // doomednum S_POSS_STND, // spawnstate 20, // spawnhealth S_POSS_RUN1, // seestate sfx_posit1, // seesound 8, // reactiontime sfx_pistol, // attacksound S_POSS_PAIN, // painstate 200, // painchance sfx_popain, // painsound 0, // meleestate S_POSS_ATK1, // missilestate S_POSS_DIE1, // deathstate S_POSS_XDIE1, // xdeathstate sfx_podth1, // deathsound 8, // speed 20*FRACUNIT, // radius 56*FRACUNIT, // height 100, // mass 0, // damage sfx_posact, // activesound MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL, // flags S_POSS_RAISE1 // raisestate }, { // MT_SHOTGUY 9, // doomednum S_SPOS_STND, // spawnstate 30, // spawnhealth S_SPOS_RUN1, // seestate sfx_posit2, // seesound 8, // reactiontime 0, // attacksound S_SPOS_PAIN, // painstate 170, // painchance sfx_popain, // painsound 0, // meleestate S_SPOS_ATK1, // missilestate S_SPOS_DIE1, // deathstate S_SPOS_XDIE1, // xdeathstate sfx_podth2, // deathsound 8, // speed 20*FRACUNIT, // radius 56*FRACUNIT, // height 100, // mass 0, // damage sfx_posact, // activesound MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL, // flags S_SPOS_RAISE1 // raisestate }, { // MT_VILE 64, // doomednum S_VILE_STND, // spawnstate 700, // spawnhealth S_VILE_RUN1, // seestate sfx_vilsit, // seesound 8, // reactiontime 0, // attacksound S_VILE_PAIN, // painstate 10, // painchance sfx_vipain, // painsound 0, // meleestate S_VILE_ATK1, // missilestate S_VILE_DIE1, // deathstate S_NULL, // xdeathstate sfx_vildth, // deathsound 15, // speed 20*FRACUNIT, // radius 56*FRACUNIT, // height 500, // mass 0, // damage sfx_vilact, // activesound MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL, // flags S_NULL // raisestate }, { // MT_FIRE -1, // doomednum S_FIRE1, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed 20*FRACUNIT, // radius 16*FRACUNIT, // height 100, // mass 0, // damage sfx_None, // activesound MF_NOBLOCKMAP|MF_NOGRAVITY, // flags S_NULL // raisestate }, { // MT_UNDEAD 66, // doomednum S_SKEL_STND, // spawnstate 300, // spawnhealth S_SKEL_RUN1, // seestate sfx_skesit, // seesound 8, // reactiontime 0, // attacksound S_SKEL_PAIN, // painstate 100, // painchance sfx_popain, // painsound S_SKEL_FIST1, // meleestate S_SKEL_MISS1, // missilestate S_SKEL_DIE1, // deathstate S_NULL, // xdeathstate sfx_skedth, // deathsound 10, // speed 20*FRACUNIT, // radius 56*FRACUNIT, // height 500, // mass 0, // damage sfx_skeact, // activesound MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL, // flags S_SKEL_RAISE1 // raisestate }, { // MT_TRACER -1, // doomednum S_TRACER, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_skeatk, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_TRACEEXP1, // deathstate S_NULL, // xdeathstate sfx_barexp, // deathsound 10*FRACUNIT, // speed 11*FRACUNIT, // radius 8*FRACUNIT, // height 100, // mass 10, // damage sfx_None, // activesound MF_NOBLOCKMAP|MF_MISSILE|MF_DROPOFF|MF_NOGRAVITY, // flags S_NULL // raisestate }, { // MT_SMOKE -1, // doomednum S_SMOKE1, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed 20*FRACUNIT, // radius 16*FRACUNIT, // height 100, // mass 0, // damage sfx_None, // activesound MF_NOBLOCKMAP|MF_NOGRAVITY, // flags S_NULL // raisestate }, { // MT_FATSO 67, // doomednum S_FATT_STND, // spawnstate 600, // spawnhealth S_FATT_RUN1, // seestate sfx_mansit, // seesound 8, // reactiontime 0, // attacksound S_FATT_PAIN, // painstate 80, // painchance sfx_mnpain, // painsound 0, // meleestate S_FATT_ATK1, // missilestate S_FATT_DIE1, // deathstate S_NULL, // xdeathstate sfx_mandth, // deathsound 8, // speed 48*FRACUNIT, // radius 64*FRACUNIT, // height 1000, // mass 0, // damage sfx_posact, // activesound MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL, // flags S_FATT_RAISE1 // raisestate }, { // MT_FATSHOT -1, // doomednum S_FATSHOT1, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_firsht, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_FATSHOTX1, // deathstate S_NULL, // xdeathstate sfx_firxpl, // deathsound 20*FRACUNIT, // speed 6*FRACUNIT, // radius 8*FRACUNIT, // height 100, // mass 8, // damage sfx_None, // activesound MF_NOBLOCKMAP|MF_MISSILE|MF_DROPOFF|MF_NOGRAVITY, // flags S_NULL // raisestate }, { // MT_CHAINGUY 65, // doomednum S_CPOS_STND, // spawnstate 70, // spawnhealth S_CPOS_RUN1, // seestate sfx_posit2, // seesound 8, // reactiontime 0, // attacksound S_CPOS_PAIN, // painstate 170, // painchance sfx_popain, // painsound 0, // meleestate S_CPOS_ATK1, // missilestate S_CPOS_DIE1, // deathstate S_CPOS_XDIE1, // xdeathstate sfx_podth2, // deathsound 8, // speed 20*FRACUNIT, // radius 56*FRACUNIT, // height 100, // mass 0, // damage sfx_posact, // activesound MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL, // flags S_CPOS_RAISE1 // raisestate }, { // MT_TROOP 3001, // doomednum S_TROO_STND, // spawnstate 60, // spawnhealth S_TROO_RUN1, // seestate sfx_bgsit1, // seesound 8, // reactiontime 0, // attacksound S_TROO_PAIN, // painstate 200, // painchance sfx_popain, // painsound S_TROO_ATK1, // meleestate S_TROO_ATK1, // missilestate S_TROO_DIE1, // deathstate S_TROO_XDIE1, // xdeathstate sfx_bgdth1, // deathsound 8, // speed 20*FRACUNIT, // radius 56*FRACUNIT, // height 100, // mass 0, // damage sfx_bgact, // activesound MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL, // flags S_TROO_RAISE1 // raisestate }, { // MT_SERGEANT 3002, // doomednum S_SARG_STND, // spawnstate 150, // spawnhealth S_SARG_RUN1, // seestate sfx_sgtsit, // seesound 8, // reactiontime sfx_sgtatk, // attacksound S_SARG_PAIN, // painstate 180, // painchance sfx_dmpain, // painsound S_SARG_ATK1, // meleestate 0, // missilestate S_SARG_DIE1, // deathstate S_NULL, // xdeathstate sfx_sgtdth, // deathsound 10, // speed 30*FRACUNIT, // radius 56*FRACUNIT, // height 400, // mass 0, // damage sfx_dmact, // activesound MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL, // flags S_SARG_RAISE1 // raisestate }, { // MT_SHADOWS 58, // doomednum S_SARG_STND, // spawnstate 150, // spawnhealth S_SARG_RUN1, // seestate sfx_sgtsit, // seesound 8, // reactiontime sfx_sgtatk, // attacksound S_SARG_PAIN, // painstate 180, // painchance sfx_dmpain, // painsound S_SARG_ATK1, // meleestate 0, // missilestate S_SARG_DIE1, // deathstate S_NULL, // xdeathstate sfx_sgtdth, // deathsound 10, // speed 30*FRACUNIT, // radius 56*FRACUNIT, // height 400, // mass 0, // damage sfx_dmact, // activesound MF_SOLID|MF_SHOOTABLE|MF_SHADOW|MF_COUNTKILL, // flags S_SARG_RAISE1 // raisestate }, { // MT_HEAD 3005, // doomednum S_HEAD_STND, // spawnstate 400, // spawnhealth S_HEAD_RUN1, // seestate sfx_cacsit, // seesound 8, // reactiontime 0, // attacksound S_HEAD_PAIN, // painstate 128, // painchance sfx_dmpain, // painsound 0, // meleestate S_HEAD_ATK1, // missilestate S_HEAD_DIE1, // deathstate S_NULL, // xdeathstate sfx_cacdth, // deathsound 8, // speed 31*FRACUNIT, // radius 56*FRACUNIT, // height 400, // mass 0, // damage sfx_dmact, // activesound MF_SOLID|MF_SHOOTABLE|MF_FLOAT|MF_NOGRAVITY|MF_COUNTKILL, // flags S_HEAD_RAISE1 // raisestate }, { // MT_BRUISER 3003, // doomednum S_BOSS_STND, // spawnstate 1000, // spawnhealth S_BOSS_RUN1, // seestate sfx_brssit, // seesound 8, // reactiontime 0, // attacksound S_BOSS_PAIN, // painstate 50, // painchance sfx_dmpain, // painsound S_BOSS_ATK1, // meleestate S_BOSS_ATK1, // missilestate S_BOSS_DIE1, // deathstate S_NULL, // xdeathstate sfx_brsdth, // deathsound 8, // speed 24*FRACUNIT, // radius 64*FRACUNIT, // height 1000, // mass 0, // damage sfx_dmact, // activesound MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL, // flags S_BOSS_RAISE1 // raisestate }, { // MT_BRUISERSHOT -1, // doomednum S_BRBALL1, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_firsht, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_BRBALLX1, // deathstate S_NULL, // xdeathstate sfx_firxpl, // deathsound 15*FRACUNIT, // speed 6*FRACUNIT, // radius 8*FRACUNIT, // height 100, // mass 8, // damage sfx_None, // activesound MF_NOBLOCKMAP|MF_MISSILE|MF_DROPOFF|MF_NOGRAVITY, // flags S_NULL // raisestate }, { // MT_KNIGHT 69, // doomednum S_BOS2_STND, // spawnstate 500, // spawnhealth S_BOS2_RUN1, // seestate sfx_kntsit, // seesound 8, // reactiontime 0, // attacksound S_BOS2_PAIN, // painstate 50, // painchance sfx_dmpain, // painsound S_BOS2_ATK1, // meleestate S_BOS2_ATK1, // missilestate S_BOS2_DIE1, // deathstate S_NULL, // xdeathstate sfx_kntdth, // deathsound 8, // speed 24*FRACUNIT, // radius 64*FRACUNIT, // height 1000, // mass 0, // damage sfx_dmact, // activesound MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL, // flags S_BOS2_RAISE1 // raisestate }, { // MT_SKULL 3006, // doomednum S_SKULL_STND, // spawnstate 100, // spawnhealth S_SKULL_RUN1, // seestate 0, // seesound 8, // reactiontime sfx_sklatk, // attacksound S_SKULL_PAIN, // painstate 256, // painchance sfx_dmpain, // painsound 0, // meleestate S_SKULL_ATK1, // missilestate S_SKULL_DIE1, // deathstate S_NULL, // xdeathstate sfx_firxpl, // deathsound 8, // speed 16*FRACUNIT, // radius 56*FRACUNIT, // height 50, // mass 3, // damage sfx_dmact, // activesound MF_SOLID|MF_SHOOTABLE|MF_FLOAT|MF_NOGRAVITY, // flags S_NULL // raisestate }, { // MT_SPIDER 7, // doomednum S_SPID_STND, // spawnstate 3000, // spawnhealth S_SPID_RUN1, // seestate sfx_spisit, // seesound 8, // reactiontime sfx_shotgn, // attacksound S_SPID_PAIN, // painstate 40, // painchance sfx_dmpain, // painsound 0, // meleestate S_SPID_ATK1, // missilestate S_SPID_DIE1, // deathstate S_NULL, // xdeathstate sfx_spidth, // deathsound 12, // speed 128*FRACUNIT, // radius 100*FRACUNIT, // height 1000, // mass 0, // damage sfx_dmact, // activesound MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL, // flags S_NULL // raisestate }, { // MT_BABY 68, // doomednum S_BSPI_STND, // spawnstate 500, // spawnhealth S_BSPI_SIGHT, // seestate sfx_bspsit, // seesound 8, // reactiontime 0, // attacksound S_BSPI_PAIN, // painstate 128, // painchance sfx_dmpain, // painsound 0, // meleestate S_BSPI_ATK1, // missilestate S_BSPI_DIE1, // deathstate S_NULL, // xdeathstate sfx_bspdth, // deathsound 12, // speed 64*FRACUNIT, // radius 64*FRACUNIT, // height 600, // mass 0, // damage sfx_bspact, // activesound MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL, // flags S_BSPI_RAISE1 // raisestate }, { // MT_CYBORG 16, // doomednum S_CYBER_STND, // spawnstate 4000, // spawnhealth S_CYBER_RUN1, // seestate sfx_cybsit, // seesound 8, // reactiontime 0, // attacksound S_CYBER_PAIN, // painstate 20, // painchance sfx_dmpain, // painsound 0, // meleestate S_CYBER_ATK1, // missilestate S_CYBER_DIE1, // deathstate S_NULL, // xdeathstate sfx_cybdth, // deathsound 16, // speed 40*FRACUNIT, // radius 110*FRACUNIT, // height 1000, // mass 0, // damage sfx_dmact, // activesound MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL, // flags S_NULL // raisestate }, { // MT_PAIN 71, // doomednum S_PAIN_STND, // spawnstate 400, // spawnhealth S_PAIN_RUN1, // seestate sfx_pesit, // seesound 8, // reactiontime 0, // attacksound S_PAIN_PAIN, // painstate 128, // painchance sfx_pepain, // painsound 0, // meleestate S_PAIN_ATK1, // missilestate S_PAIN_DIE1, // deathstate S_NULL, // xdeathstate sfx_pedth, // deathsound 8, // speed 31*FRACUNIT, // radius 56*FRACUNIT, // height 400, // mass 0, // damage sfx_dmact, // activesound MF_SOLID|MF_SHOOTABLE|MF_FLOAT|MF_NOGRAVITY|MF_COUNTKILL, // flags S_PAIN_RAISE1 // raisestate }, { // MT_WOLFSS 84, // doomednum S_SSWV_STND, // spawnstate 50, // spawnhealth S_SSWV_RUN1, // seestate sfx_sssit, // seesound 8, // reactiontime 0, // attacksound S_SSWV_PAIN, // painstate 170, // painchance sfx_popain, // painsound 0, // meleestate S_SSWV_ATK1, // missilestate S_SSWV_DIE1, // deathstate S_SSWV_XDIE1, // xdeathstate sfx_ssdth, // deathsound 8, // speed 20*FRACUNIT, // radius 56*FRACUNIT, // height 100, // mass 0, // damage sfx_posact, // activesound MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL, // flags S_SSWV_RAISE1 // raisestate }, { // MT_KEEN 72, // doomednum S_KEENSTND, // spawnstate 100, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_KEENPAIN, // painstate 256, // painchance sfx_keenpn, // painsound S_NULL, // meleestate S_NULL, // missilestate S_COMMKEEN, // deathstate S_NULL, // xdeathstate sfx_keendt, // deathsound 0, // speed 16*FRACUNIT, // radius 72*FRACUNIT, // height 10000000, // mass 0, // damage sfx_None, // activesound MF_SOLID|MF_SPAWNCEILING|MF_NOGRAVITY|MF_SHOOTABLE|MF_COUNTKILL, // flags S_NULL // raisestate }, { // MT_BOSSBRAIN 88, // doomednum S_BRAIN, // spawnstate 250, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_BRAIN_PAIN, // painstate 255, // painchance sfx_bospn, // painsound S_NULL, // meleestate S_NULL, // missilestate S_BRAIN_DIE1, // deathstate S_NULL, // xdeathstate sfx_bosdth, // deathsound 0, // speed 16*FRACUNIT, // radius 16*FRACUNIT, // height 10000000, // mass 0, // damage sfx_None, // activesound MF_SOLID|MF_SHOOTABLE, // flags S_NULL // raisestate }, { // MT_BOSSSPIT 89, // doomednum S_BRAINEYE, // spawnstate 1000, // spawnhealth S_BRAINEYESEE, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed 20*FRACUNIT, // radius 32*FRACUNIT, // height 100, // mass 0, // damage sfx_None, // activesound MF_NOBLOCKMAP|MF_NOSECTOR, // flags S_NULL // raisestate }, { // MT_BOSSTARGET 87, // doomednum S_NULL, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed 20*FRACUNIT, // radius 32*FRACUNIT, // height 100, // mass 0, // damage sfx_None, // activesound MF_NOBLOCKMAP|MF_NOSECTOR, // flags S_NULL // raisestate }, { // MT_SPAWNSHOT -1, // doomednum S_SPAWN1, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_bospit, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_firxpl, // deathsound 10*FRACUNIT, // speed 6*FRACUNIT, // radius 32*FRACUNIT, // height 100, // mass 3, // damage sfx_None, // activesound MF_NOBLOCKMAP|MF_MISSILE|MF_DROPOFF|MF_NOGRAVITY|MF_NOCLIP, // flags S_NULL // raisestate }, { // MT_SPAWNFIRE -1, // doomednum S_SPAWNFIRE1, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed 20*FRACUNIT, // radius 16*FRACUNIT, // height 100, // mass 0, // damage sfx_None, // activesound MF_NOBLOCKMAP|MF_NOGRAVITY, // flags S_NULL // raisestate }, { // MT_BARREL 2035, // doomednum S_BAR1, // spawnstate 20, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_BEXP, // deathstate S_NULL, // xdeathstate sfx_barexp, // deathsound 0, // speed 10*FRACUNIT, // radius 42*FRACUNIT, // height 100, // mass 0, // damage sfx_None, // activesound MF_SOLID|MF_SHOOTABLE|MF_NOBLOOD, // flags S_NULL // raisestate }, { // MT_TROOPSHOT -1, // doomednum S_TBALL1, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_firsht, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_TBALLX1, // deathstate S_NULL, // xdeathstate sfx_firxpl, // deathsound 10*FRACUNIT, // speed 6*FRACUNIT, // radius 8*FRACUNIT, // height 100, // mass 3, // damage sfx_None, // activesound MF_NOBLOCKMAP|MF_MISSILE|MF_DROPOFF|MF_NOGRAVITY, // flags S_NULL // raisestate }, { // MT_HEADSHOT -1, // doomednum S_RBALL1, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_firsht, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_RBALLX1, // deathstate S_NULL, // xdeathstate sfx_firxpl, // deathsound 10*FRACUNIT, // speed 6*FRACUNIT, // radius 8*FRACUNIT, // height 100, // mass 5, // damage sfx_None, // activesound MF_NOBLOCKMAP|MF_MISSILE|MF_DROPOFF|MF_NOGRAVITY, // flags S_NULL // raisestate }, { // MT_ROCKET -1, // doomednum S_ROCKET, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_rlaunc, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_EXPLODE1, // deathstate S_NULL, // xdeathstate sfx_barexp, // deathsound 20*FRACUNIT, // speed 11*FRACUNIT, // radius 8*FRACUNIT, // height 100, // mass 20, // damage sfx_None, // activesound MF_NOBLOCKMAP|MF_MISSILE|MF_DROPOFF|MF_NOGRAVITY, // flags S_NULL // raisestate }, { // MT_PLASMA -1, // doomednum S_PLASBALL, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_plasma, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_PLASEXP, // deathstate S_NULL, // xdeathstate sfx_firxpl, // deathsound 25*FRACUNIT, // speed 13*FRACUNIT, // radius 8*FRACUNIT, // height 100, // mass 5, // damage sfx_None, // activesound MF_NOBLOCKMAP|MF_MISSILE|MF_DROPOFF|MF_NOGRAVITY, // flags S_NULL // raisestate }, { // MT_BFG -1, // doomednum S_BFGSHOT, // spawnstate 1000, // spawnhealth S_NULL, // seestate 0, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_BFGLAND, // deathstate S_NULL, // xdeathstate sfx_rxplod, // deathsound 25*FRACUNIT, // speed 13*FRACUNIT, // radius 8*FRACUNIT, // height 100, // mass 100, // damage sfx_None, // activesound MF_NOBLOCKMAP|MF_MISSILE|MF_DROPOFF|MF_NOGRAVITY, // flags S_NULL // raisestate }, { // MT_ARACHPLAZ -1, // doomednum S_ARACH_PLAZ, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_plasma, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_ARACH_PLEX, // deathstate S_NULL, // xdeathstate sfx_firxpl, // deathsound 25*FRACUNIT, // speed 13*FRACUNIT, // radius 8*FRACUNIT, // height 100, // mass 5, // damage sfx_None, // activesound MF_NOBLOCKMAP|MF_MISSILE|MF_DROPOFF|MF_NOGRAVITY, // flags S_NULL // raisestate }, { // MT_PUFF -1, // doomednum S_PUFF1, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed 20*FRACUNIT, // radius 16*FRACUNIT, // height 100, // mass 0, // damage sfx_None, // activesound MF_NOBLOCKMAP|MF_NOGRAVITY, // flags S_NULL // raisestate }, { // MT_BLOOD -1, // doomednum S_BLOOD1, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed 20*FRACUNIT, // radius 16*FRACUNIT, // height 100, // mass 0, // damage sfx_None, // activesound MF_NOBLOCKMAP, // flags S_NULL // raisestate }, { // MT_TFOG -1, // doomednum S_TFOG, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed 20*FRACUNIT, // radius 16*FRACUNIT, // height 100, // mass 0, // damage sfx_None, // activesound MF_NOBLOCKMAP|MF_NOGRAVITY, // flags S_NULL // raisestate }, { // MT_IFOG -1, // doomednum S_IFOG, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed 20*FRACUNIT, // radius 16*FRACUNIT, // height 100, // mass 0, // damage sfx_None, // activesound MF_NOBLOCKMAP|MF_NOGRAVITY, // flags S_NULL // raisestate }, { // MT_TELEPORTMAN 14, // doomednum S_NULL, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed 20*FRACUNIT, // radius 16*FRACUNIT, // height 100, // mass 0, // damage sfx_None, // activesound MF_NOBLOCKMAP|MF_NOSECTOR, // flags S_NULL // raisestate }, { // MT_EXTRABFG -1, // doomednum S_BFGEXP, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed 20*FRACUNIT, // radius 16*FRACUNIT, // height 100, // mass 0, // damage sfx_None, // activesound MF_NOBLOCKMAP|MF_NOGRAVITY, // flags S_NULL // raisestate }, { // MT_MISC0 2018, // doomednum S_ARM1, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed 20*FRACUNIT, // radius 16*FRACUNIT, // height 100, // mass 0, // damage sfx_None, // activesound MF_SPECIAL, // flags S_NULL // raisestate }, { // MT_MISC1 2019, // doomednum S_ARM2, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed 20*FRACUNIT, // radius 16*FRACUNIT, // height 100, // mass 0, // damage sfx_None, // activesound MF_SPECIAL, // flags S_NULL // raisestate }, { // MT_MISC2 2014, // doomednum S_BON1, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed 20*FRACUNIT, // radius 16*FRACUNIT, // height 100, // mass 0, // damage sfx_None, // activesound MF_SPECIAL|MF_COUNTITEM, // flags S_NULL // raisestate }, { // MT_MISC3 2015, // doomednum S_BON2, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed 20*FRACUNIT, // radius 16*FRACUNIT, // height 100, // mass 0, // damage sfx_None, // activesound MF_SPECIAL|MF_COUNTITEM, // flags S_NULL // raisestate }, { // MT_MISC4 5, // doomednum S_BKEY, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed 20*FRACUNIT, // radius 16*FRACUNIT, // height 100, // mass 0, // damage sfx_None, // activesound MF_SPECIAL|MF_NOTDMATCH, // flags S_NULL // raisestate }, { // MT_MISC5 13, // doomednum S_RKEY, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed 20*FRACUNIT, // radius 16*FRACUNIT, // height 100, // mass 0, // damage sfx_None, // activesound MF_SPECIAL|MF_NOTDMATCH, // flags S_NULL // raisestate }, { // MT_MISC6 6, // doomednum S_YKEY, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed 20*FRACUNIT, // radius 16*FRACUNIT, // height 100, // mass 0, // damage sfx_None, // activesound MF_SPECIAL|MF_NOTDMATCH, // flags S_NULL // raisestate }, { // MT_MISC7 39, // doomednum S_YSKULL, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed 20*FRACUNIT, // radius 16*FRACUNIT, // height 100, // mass 0, // damage sfx_None, // activesound MF_SPECIAL|MF_NOTDMATCH, // flags S_NULL // raisestate }, { // MT_MISC8 38, // doomednum S_RSKULL, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed 20*FRACUNIT, // radius 16*FRACUNIT, // height 100, // mass 0, // damage sfx_None, // activesound MF_SPECIAL|MF_NOTDMATCH, // flags S_NULL // raisestate }, { // MT_MISC9 40, // doomednum S_BSKULL, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed 20*FRACUNIT, // radius 16*FRACUNIT, // height 100, // mass 0, // damage sfx_None, // activesound MF_SPECIAL|MF_NOTDMATCH, // flags S_NULL // raisestate }, { // MT_MISC10 2011, // doomednum S_STIM, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed 20*FRACUNIT, // radius 16*FRACUNIT, // height 100, // mass 0, // damage sfx_None, // activesound MF_SPECIAL, // flags S_NULL // raisestate }, { // MT_MISC11 2012, // doomednum S_MEDI, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed 20*FRACUNIT, // radius 16*FRACUNIT, // height 100, // mass 0, // damage sfx_None, // activesound MF_SPECIAL, // flags S_NULL // raisestate }, { // MT_MISC12 2013, // doomednum S_SOUL, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed 20*FRACUNIT, // radius 16*FRACUNIT, // height 100, // mass 0, // damage sfx_None, // activesound MF_SPECIAL|MF_COUNTITEM, // flags S_NULL // raisestate }, { // MT_INV 2022, // doomednum S_PINV, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed 20*FRACUNIT, // radius 16*FRACUNIT, // height 100, // mass 0, // damage sfx_None, // activesound MF_SPECIAL|MF_COUNTITEM, // flags S_NULL // raisestate }, { // MT_MISC13 2023, // doomednum S_PSTR, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed 20*FRACUNIT, // radius 16*FRACUNIT, // height 100, // mass 0, // damage sfx_None, // activesound MF_SPECIAL|MF_COUNTITEM, // flags S_NULL // raisestate }, { // MT_INS 2024, // doomednum S_PINS, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed 20*FRACUNIT, // radius 16*FRACUNIT, // height 100, // mass 0, // damage sfx_None, // activesound MF_SPECIAL|MF_COUNTITEM, // flags S_NULL // raisestate }, { // MT_MISC14 2025, // doomednum S_SUIT, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed 20*FRACUNIT, // radius 16*FRACUNIT, // height 100, // mass 0, // damage sfx_None, // activesound MF_SPECIAL, // flags S_NULL // raisestate }, { // MT_MISC15 2026, // doomednum S_PMAP, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed 20*FRACUNIT, // radius 16*FRACUNIT, // height 100, // mass 0, // damage sfx_None, // activesound MF_SPECIAL|MF_COUNTITEM, // flags S_NULL // raisestate }, { // MT_MISC16 2045, // doomednum S_PVIS, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed 20*FRACUNIT, // radius 16*FRACUNIT, // height 100, // mass 0, // damage sfx_None, // activesound MF_SPECIAL|MF_COUNTITEM, // flags S_NULL // raisestate }, { // MT_MEGA 83, // doomednum S_MEGA, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed 20*FRACUNIT, // radius 16*FRACUNIT, // height 100, // mass 0, // damage sfx_None, // activesound MF_SPECIAL|MF_COUNTITEM, // flags S_NULL // raisestate }, { // MT_CLIP 2007, // doomednum S_CLIP, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed 20*FRACUNIT, // radius 16*FRACUNIT, // height 100, // mass 0, // damage sfx_None, // activesound MF_SPECIAL, // flags S_NULL // raisestate }, { // MT_MISC17 2048, // doomednum S_AMMO, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed 20*FRACUNIT, // radius 16*FRACUNIT, // height 100, // mass 0, // damage sfx_None, // activesound MF_SPECIAL, // flags S_NULL // raisestate }, { // MT_MISC18 2010, // doomednum S_ROCK, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed 20*FRACUNIT, // radius 16*FRACUNIT, // height 100, // mass 0, // damage sfx_None, // activesound MF_SPECIAL, // flags S_NULL // raisestate }, { // MT_MISC19 2046, // doomednum S_BROK, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed 20*FRACUNIT, // radius 16*FRACUNIT, // height 100, // mass 0, // damage sfx_None, // activesound MF_SPECIAL, // flags S_NULL // raisestate }, { // MT_MISC20 2047, // doomednum S_CELL, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed 20*FRACUNIT, // radius 16*FRACUNIT, // height 100, // mass 0, // damage sfx_None, // activesound MF_SPECIAL, // flags S_NULL // raisestate }, { // MT_MISC21 17, // doomednum S_CELP, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed 20*FRACUNIT, // radius 16*FRACUNIT, // height 100, // mass 0, // damage sfx_None, // activesound MF_SPECIAL, // flags S_NULL // raisestate }, { // MT_MISC22 2008, // doomednum S_SHEL, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed 20*FRACUNIT, // radius 16*FRACUNIT, // height 100, // mass 0, // damage sfx_None, // activesound MF_SPECIAL, // flags S_NULL // raisestate }, { // MT_MISC23 2049, // doomednum S_SBOX, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed 20*FRACUNIT, // radius 16*FRACUNIT, // height 100, // mass 0, // damage sfx_None, // activesound MF_SPECIAL, // flags S_NULL // raisestate }, { // MT_MISC24 8, // doomednum S_BPAK, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed 20*FRACUNIT, // radius 16*FRACUNIT, // height 100, // mass 0, // damage sfx_None, // activesound MF_SPECIAL, // flags S_NULL // raisestate }, { // MT_MISC25 2006, // doomednum S_BFUG, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed 20*FRACUNIT, // radius 16*FRACUNIT, // height 100, // mass 0, // damage sfx_None, // activesound MF_SPECIAL, // flags S_NULL // raisestate }, { // MT_CHAINGUN 2002, // doomednum S_MGUN, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed 20*FRACUNIT, // radius 16*FRACUNIT, // height 100, // mass 0, // damage sfx_None, // activesound MF_SPECIAL, // flags S_NULL // raisestate }, { // MT_MISC26 2005, // doomednum S_CSAW, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed 20*FRACUNIT, // radius 16*FRACUNIT, // height 100, // mass 0, // damage sfx_None, // activesound MF_SPECIAL, // flags S_NULL // raisestate }, { // MT_MISC27 2003, // doomednum S_LAUN, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed 20*FRACUNIT, // radius 16*FRACUNIT, // height 100, // mass 0, // damage sfx_None, // activesound MF_SPECIAL, // flags S_NULL // raisestate }, { // MT_MISC28 2004, // doomednum S_PLAS, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed 20*FRACUNIT, // radius 16*FRACUNIT, // height 100, // mass 0, // damage sfx_None, // activesound MF_SPECIAL, // flags S_NULL // raisestate }, { // MT_SHOTGUN 2001, // doomednum S_SHOT, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed 20*FRACUNIT, // radius 16*FRACUNIT, // height 100, // mass 0, // damage sfx_None, // activesound MF_SPECIAL, // flags S_NULL // raisestate }, { // MT_SUPERSHOTGUN 82, // doomednum S_SHOT2, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed 20*FRACUNIT, // radius 16*FRACUNIT, // height 100, // mass 0, // damage sfx_None, // activesound MF_SPECIAL, // flags S_NULL // raisestate }, { // MT_MISC29 85, // doomednum S_TECHLAMP, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed 16*FRACUNIT, // radius 16*FRACUNIT, // height 100, // mass 0, // damage sfx_None, // activesound MF_SOLID, // flags S_NULL // raisestate }, { // MT_MISC30 86, // doomednum S_TECH2LAMP, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed 16*FRACUNIT, // radius 16*FRACUNIT, // height 100, // mass 0, // damage sfx_None, // activesound MF_SOLID, // flags S_NULL // raisestate }, { // MT_MISC31 2028, // doomednum S_COLU, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed 16*FRACUNIT, // radius 16*FRACUNIT, // height 100, // mass 0, // damage sfx_None, // activesound MF_SOLID, // flags S_NULL // raisestate }, { // MT_MISC32 30, // doomednum S_TALLGRNCOL, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed 16*FRACUNIT, // radius 16*FRACUNIT, // height 100, // mass 0, // damage sfx_None, // activesound MF_SOLID, // flags S_NULL // raisestate }, { // MT_MISC33 31, // doomednum S_SHRTGRNCOL, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed 16*FRACUNIT, // radius 16*FRACUNIT, // height 100, // mass 0, // damage sfx_None, // activesound MF_SOLID, // flags S_NULL // raisestate }, { // MT_MISC34 32, // doomednum S_TALLREDCOL, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed 16*FRACUNIT, // radius 16*FRACUNIT, // height 100, // mass 0, // damage sfx_None, // activesound MF_SOLID, // flags S_NULL // raisestate }, { // MT_MISC35 33, // doomednum S_SHRTREDCOL, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed 16*FRACUNIT, // radius 16*FRACUNIT, // height 100, // mass 0, // damage sfx_None, // activesound MF_SOLID, // flags S_NULL // raisestate }, { // MT_MISC36 37, // doomednum S_SKULLCOL, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed 16*FRACUNIT, // radius 16*FRACUNIT, // height 100, // mass 0, // damage sfx_None, // activesound MF_SOLID, // flags S_NULL // raisestate }, { // MT_MISC37 36, // doomednum S_HEARTCOL, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed 16*FRACUNIT, // radius 16*FRACUNIT, // height 100, // mass 0, // damage sfx_None, // activesound MF_SOLID, // flags S_NULL // raisestate }, { // MT_MISC38 41, // doomednum S_EVILEYE, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed 16*FRACUNIT, // radius 16*FRACUNIT, // height 100, // mass 0, // damage sfx_None, // activesound MF_SOLID, // flags S_NULL // raisestate }, { // MT_MISC39 42, // doomednum S_FLOATSKULL, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed 16*FRACUNIT, // radius 16*FRACUNIT, // height 100, // mass 0, // damage sfx_None, // activesound MF_SOLID, // flags S_NULL // raisestate }, { // MT_MISC40 43, // doomednum S_TORCHTREE, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed 16*FRACUNIT, // radius 16*FRACUNIT, // height 100, // mass 0, // damage sfx_None, // activesound MF_SOLID, // flags S_NULL // raisestate }, { // MT_MISC41 44, // doomednum S_BLUETORCH, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed 16*FRACUNIT, // radius 16*FRACUNIT, // height 100, // mass 0, // damage sfx_None, // activesound MF_SOLID, // flags S_NULL // raisestate }, { // MT_MISC42 45, // doomednum S_GREENTORCH, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed 16*FRACUNIT, // radius 16*FRACUNIT, // height 100, // mass 0, // damage sfx_None, // activesound MF_SOLID, // flags S_NULL // raisestate }, { // MT_MISC43 46, // doomednum S_REDTORCH, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed 16*FRACUNIT, // radius 16*FRACUNIT, // height 100, // mass 0, // damage sfx_None, // activesound MF_SOLID, // flags S_NULL // raisestate }, { // MT_MISC44 55, // doomednum S_BTORCHSHRT, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed 16*FRACUNIT, // radius 16*FRACUNIT, // height 100, // mass 0, // damage sfx_None, // activesound MF_SOLID, // flags S_NULL // raisestate }, { // MT_MISC45 56, // doomednum S_GTORCHSHRT, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed 16*FRACUNIT, // radius 16*FRACUNIT, // height 100, // mass 0, // damage sfx_None, // activesound MF_SOLID, // flags S_NULL // raisestate }, { // MT_MISC46 57, // doomednum S_RTORCHSHRT, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed 16*FRACUNIT, // radius 16*FRACUNIT, // height 100, // mass 0, // damage sfx_None, // activesound MF_SOLID, // flags S_NULL // raisestate }, { // MT_MISC47 47, // doomednum S_STALAGTITE, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed 16*FRACUNIT, // radius 16*FRACUNIT, // height 100, // mass 0, // damage sfx_None, // activesound MF_SOLID, // flags S_NULL // raisestate }, { // MT_MISC48 48, // doomednum S_TECHPILLAR, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed 16*FRACUNIT, // radius 16*FRACUNIT, // height 100, // mass 0, // damage sfx_None, // activesound MF_SOLID, // flags S_NULL // raisestate }, { // MT_MISC49 34, // doomednum S_CANDLESTIK, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed 20*FRACUNIT, // radius 16*FRACUNIT, // height 100, // mass 0, // damage sfx_None, // activesound 0, // flags S_NULL // raisestate }, { // MT_MISC50 35, // doomednum S_CANDELABRA, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed 16*FRACUNIT, // radius 16*FRACUNIT, // height 100, // mass 0, // damage sfx_None, // activesound MF_SOLID, // flags S_NULL // raisestate }, { // MT_MISC51 49, // doomednum S_BLOODYTWITCH, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed 16*FRACUNIT, // radius 68*FRACUNIT, // height 100, // mass 0, // damage sfx_None, // activesound MF_SOLID|MF_SPAWNCEILING|MF_NOGRAVITY, // flags S_NULL // raisestate }, { // MT_MISC52 50, // doomednum S_MEAT2, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed 16*FRACUNIT, // radius 84*FRACUNIT, // height 100, // mass 0, // damage sfx_None, // activesound MF_SOLID|MF_SPAWNCEILING|MF_NOGRAVITY, // flags S_NULL // raisestate }, { // MT_MISC53 51, // doomednum S_MEAT3, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed 16*FRACUNIT, // radius 84*FRACUNIT, // height 100, // mass 0, // damage sfx_None, // activesound MF_SOLID|MF_SPAWNCEILING|MF_NOGRAVITY, // flags S_NULL // raisestate }, { // MT_MISC54 52, // doomednum S_MEAT4, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed 16*FRACUNIT, // radius 68*FRACUNIT, // height 100, // mass 0, // damage sfx_None, // activesound MF_SOLID|MF_SPAWNCEILING|MF_NOGRAVITY, // flags S_NULL // raisestate }, { // MT_MISC55 53, // doomednum S_MEAT5, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed 16*FRACUNIT, // radius 52*FRACUNIT, // height 100, // mass 0, // damage sfx_None, // activesound MF_SOLID|MF_SPAWNCEILING|MF_NOGRAVITY, // flags S_NULL // raisestate }, { // MT_MISC56 59, // doomednum S_MEAT2, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed 20*FRACUNIT, // radius 84*FRACUNIT, // height 100, // mass 0, // damage sfx_None, // activesound MF_SPAWNCEILING|MF_NOGRAVITY, // flags S_NULL // raisestate }, { // MT_MISC57 60, // doomednum S_MEAT4, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed 20*FRACUNIT, // radius 68*FRACUNIT, // height 100, // mass 0, // damage sfx_None, // activesound MF_SPAWNCEILING|MF_NOGRAVITY, // flags S_NULL // raisestate }, { // MT_MISC58 61, // doomednum S_MEAT3, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed 20*FRACUNIT, // radius 52*FRACUNIT, // height 100, // mass 0, // damage sfx_None, // activesound MF_SPAWNCEILING|MF_NOGRAVITY, // flags S_NULL // raisestate }, { // MT_MISC59 62, // doomednum S_MEAT5, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed 20*FRACUNIT, // radius 52*FRACUNIT, // height 100, // mass 0, // damage sfx_None, // activesound MF_SPAWNCEILING|MF_NOGRAVITY, // flags S_NULL // raisestate }, { // MT_MISC60 63, // doomednum S_BLOODYTWITCH, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed 20*FRACUNIT, // radius 68*FRACUNIT, // height 100, // mass 0, // damage sfx_None, // activesound MF_SPAWNCEILING|MF_NOGRAVITY, // flags S_NULL // raisestate }, { // MT_MISC61 22, // doomednum S_HEAD_DIE6, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed 20*FRACUNIT, // radius 16*FRACUNIT, // height 100, // mass 0, // damage sfx_None, // activesound 0, // flags S_NULL // raisestate }, { // MT_MISC62 15, // doomednum S_PLAY_DIE7, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed 20*FRACUNIT, // radius 16*FRACUNIT, // height 100, // mass 0, // damage sfx_None, // activesound 0, // flags S_NULL // raisestate }, { // MT_MISC63 18, // doomednum S_POSS_DIE5, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed 20*FRACUNIT, // radius 16*FRACUNIT, // height 100, // mass 0, // damage sfx_None, // activesound 0, // flags S_NULL // raisestate }, { // MT_MISC64 21, // doomednum S_SARG_DIE6, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed 20*FRACUNIT, // radius 16*FRACUNIT, // height 100, // mass 0, // damage sfx_None, // activesound 0, // flags S_NULL // raisestate }, { // MT_MISC65 23, // doomednum S_SKULL_DIE6, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed 20*FRACUNIT, // radius 16*FRACUNIT, // height 100, // mass 0, // damage sfx_None, // activesound 0, // flags S_NULL // raisestate }, { // MT_MISC66 20, // doomednum S_TROO_DIE5, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed 20*FRACUNIT, // radius 16*FRACUNIT, // height 100, // mass 0, // damage sfx_None, // activesound 0, // flags S_NULL // raisestate }, { // MT_MISC67 19, // doomednum S_SPOS_DIE5, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed 20*FRACUNIT, // radius 16*FRACUNIT, // height 100, // mass 0, // damage sfx_None, // activesound 0, // flags S_NULL // raisestate }, { // MT_MISC68 10, // doomednum S_PLAY_XDIE9, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed 20*FRACUNIT, // radius 16*FRACUNIT, // height 100, // mass 0, // damage sfx_None, // activesound 0, // flags S_NULL // raisestate }, { // MT_MISC69 12, // doomednum S_PLAY_XDIE9, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed 20*FRACUNIT, // radius 16*FRACUNIT, // height 100, // mass 0, // damage sfx_None, // activesound 0, // flags S_NULL // raisestate }, { // MT_MISC70 28, // doomednum S_HEADSONSTICK, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed 16*FRACUNIT, // radius 16*FRACUNIT, // height 100, // mass 0, // damage sfx_None, // activesound MF_SOLID, // flags S_NULL // raisestate }, { // MT_MISC71 24, // doomednum S_GIBS, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed 20*FRACUNIT, // radius 16*FRACUNIT, // height 100, // mass 0, // damage sfx_None, // activesound 0, // flags S_NULL // raisestate }, { // MT_MISC72 27, // doomednum S_HEADONASTICK, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed 16*FRACUNIT, // radius 16*FRACUNIT, // height 100, // mass 0, // damage sfx_None, // activesound MF_SOLID, // flags S_NULL // raisestate }, { // MT_MISC73 29, // doomednum S_HEADCANDLES, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed 16*FRACUNIT, // radius 16*FRACUNIT, // height 100, // mass 0, // damage sfx_None, // activesound MF_SOLID, // flags S_NULL // raisestate }, { // MT_MISC74 25, // doomednum S_DEADSTICK, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed 16*FRACUNIT, // radius 16*FRACUNIT, // height 100, // mass 0, // damage sfx_None, // activesound MF_SOLID, // flags S_NULL // raisestate }, { // MT_MISC75 26, // doomednum S_LIVESTICK, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed 16*FRACUNIT, // radius 16*FRACUNIT, // height 100, // mass 0, // damage sfx_None, // activesound MF_SOLID, // flags S_NULL // raisestate }, { // MT_MISC76 54, // doomednum S_BIGTREE, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed 32*FRACUNIT, // radius 16*FRACUNIT, // height 100, // mass 0, // damage sfx_None, // activesound MF_SOLID, // flags S_NULL // raisestate }, { // MT_MISC77 70, // doomednum S_BBAR1, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed 16*FRACUNIT, // radius 16*FRACUNIT, // height 100, // mass 0, // damage sfx_None, // activesound MF_SOLID, // flags S_NULL // raisestate }, { // MT_MISC78 73, // doomednum S_HANGNOGUTS, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed 16*FRACUNIT, // radius 88*FRACUNIT, // height 100, // mass 0, // damage sfx_None, // activesound MF_SOLID|MF_SPAWNCEILING|MF_NOGRAVITY, // flags S_NULL // raisestate }, { // MT_MISC79 74, // doomednum S_HANGBNOBRAIN, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed 16*FRACUNIT, // radius 88*FRACUNIT, // height 100, // mass 0, // damage sfx_None, // activesound MF_SOLID|MF_SPAWNCEILING|MF_NOGRAVITY, // flags S_NULL // raisestate }, { // MT_MISC80 75, // doomednum S_HANGTLOOKDN, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed 16*FRACUNIT, // radius 64*FRACUNIT, // height 100, // mass 0, // damage sfx_None, // activesound MF_SOLID|MF_SPAWNCEILING|MF_NOGRAVITY, // flags S_NULL // raisestate }, { // MT_MISC81 76, // doomednum S_HANGTSKULL, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed 16*FRACUNIT, // radius 64*FRACUNIT, // height 100, // mass 0, // damage sfx_None, // activesound MF_SOLID|MF_SPAWNCEILING|MF_NOGRAVITY, // flags S_NULL // raisestate }, { // MT_MISC82 77, // doomednum S_HANGTLOOKUP, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed 16*FRACUNIT, // radius 64*FRACUNIT, // height 100, // mass 0, // damage sfx_None, // activesound MF_SOLID|MF_SPAWNCEILING|MF_NOGRAVITY, // flags S_NULL // raisestate }, { // MT_MISC83 78, // doomednum S_HANGTNOBRAIN, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed 16*FRACUNIT, // radius 64*FRACUNIT, // height 100, // mass 0, // damage sfx_None, // activesound MF_SOLID|MF_SPAWNCEILING|MF_NOGRAVITY, // flags S_NULL // raisestate }, { // MT_MISC84 79, // doomednum S_COLONGIBS, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed 20*FRACUNIT, // radius 16*FRACUNIT, // height 100, // mass 0, // damage sfx_None, // activesound MF_NOBLOCKMAP, // flags S_NULL // raisestate }, { // MT_MISC85 80, // doomednum S_SMALLPOOL, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed 20*FRACUNIT, // radius 16*FRACUNIT, // height 100, // mass 0, // damage sfx_None, // activesound MF_NOBLOCKMAP, // flags S_NULL // raisestate }, { // MT_MISC86 81, // doomednum S_BRAINSTEM, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed 20*FRACUNIT, // radius 16*FRACUNIT, // height 100, // mass 0, // damage sfx_None, // activesound MF_NOBLOCKMAP, // flags S_NULL // raisestate } }; \ No newline at end of file diff --git a/INFO.H b/INFO.H new file mode 100644 index 0000000..db90caa --- /dev/null +++ b/INFO.H @@ -0,0 +1 @@ +// generated by multigen typedef enum { SPR_TROO, SPR_SHTG, SPR_PUNG, SPR_PISG, SPR_PISF, SPR_SHTF, SPR_SHT2, SPR_CHGG, SPR_CHGF, SPR_MISG, SPR_MISF, SPR_SAWG, SPR_PLSG, SPR_PLSF, SPR_BFGG, SPR_BFGF, SPR_BLUD, SPR_PUFF, SPR_BAL1, SPR_BAL2, SPR_PLSS, SPR_PLSE, SPR_MISL, SPR_BFS1, SPR_BFE1, SPR_BFE2, SPR_TFOG, SPR_IFOG, SPR_PLAY, SPR_POSS, SPR_SPOS, SPR_VILE, SPR_FIRE, SPR_FATB, SPR_FBXP, SPR_SKEL, SPR_MANF, SPR_FATT, SPR_CPOS, SPR_SARG, SPR_HEAD, SPR_BAL7, SPR_BOSS, SPR_BOS2, SPR_SKUL, SPR_SPID, SPR_BSPI, SPR_APLS, SPR_APBX, SPR_CYBR, SPR_PAIN, SPR_SSWV, SPR_KEEN, SPR_BBRN, SPR_BOSF, SPR_ARM1, SPR_ARM2, SPR_BAR1, SPR_BEXP, SPR_FCAN, SPR_BON1, SPR_BON2, SPR_BKEY, SPR_RKEY, SPR_YKEY, SPR_BSKU, SPR_RSKU, SPR_YSKU, SPR_STIM, SPR_MEDI, SPR_SOUL, SPR_PINV, SPR_PSTR, SPR_PINS, SPR_MEGA, SPR_SUIT, SPR_PMAP, SPR_PVIS, SPR_CLIP, SPR_AMMO, SPR_ROCK, SPR_BROK, SPR_CELL, SPR_CELP, SPR_SHEL, SPR_SBOX, SPR_BPAK, SPR_BFUG, SPR_MGUN, SPR_CSAW, SPR_LAUN, SPR_PLAS, SPR_SHOT, SPR_SGN2, SPR_COLU, SPR_SMT2, SPR_GOR1, SPR_POL2, SPR_POL5, SPR_POL4, SPR_POL3, SPR_POL1, SPR_POL6, SPR_GOR2, SPR_GOR3, SPR_GOR4, SPR_GOR5, SPR_SMIT, SPR_COL1, SPR_COL2, SPR_COL3, SPR_COL4, SPR_CAND, SPR_CBRA, SPR_COL6, SPR_TRE1, SPR_TRE2, SPR_ELEC, SPR_CEYE, SPR_FSKU, SPR_COL5, SPR_TBLU, SPR_TGRN, SPR_TRED, SPR_SMBT, SPR_SMGT, SPR_SMRT, SPR_HDB1, SPR_HDB2, SPR_HDB3, SPR_HDB4, SPR_HDB5, SPR_HDB6, SPR_POB1, SPR_POB2, SPR_BRS1, SPR_TLMP, SPR_TLP2, NUMSPRITES } spritenum_t; typedef enum { S_NULL, S_LIGHTDONE, S_PUNCH, S_PUNCHDOWN, S_PUNCHUP, S_PUNCH1, S_PUNCH2, S_PUNCH3, S_PUNCH4, S_PUNCH5, S_PISTOL, S_PISTOLDOWN, S_PISTOLUP, S_PISTOL1, S_PISTOL2, S_PISTOL3, S_PISTOL4, S_PISTOLFLASH, S_SGUN, S_SGUNDOWN, S_SGUNUP, S_SGUN1, S_SGUN2, S_SGUN3, S_SGUN4, S_SGUN5, S_SGUN6, S_SGUN7, S_SGUN8, S_SGUN9, S_SGUNFLASH1, S_SGUNFLASH2, S_DSGUN, S_DSGUNDOWN, S_DSGUNUP, S_DSGUN1, S_DSGUN2, S_DSGUN3, S_DSGUN4, S_DSGUN5, S_DSGUN6, S_DSGUN7, S_DSGUN8, S_DSGUN9, S_DSGUN10, S_DSNR1, S_DSNR2, S_DSGUNFLASH1, S_DSGUNFLASH2, S_CHAIN, S_CHAINDOWN, S_CHAINUP, S_CHAIN1, S_CHAIN2, S_CHAIN3, S_CHAINFLASH1, S_CHAINFLASH2, S_MISSILE, S_MISSILEDOWN, S_MISSILEUP, S_MISSILE1, S_MISSILE2, S_MISSILE3, S_MISSILEFLASH1, S_MISSILEFLASH2, S_MISSILEFLASH3, S_MISSILEFLASH4, S_SAW, S_SAWB, S_SAWDOWN, S_SAWUP, S_SAW1, S_SAW2, S_SAW3, S_PLASMA, S_PLASMADOWN, S_PLASMAUP, S_PLASMA1, S_PLASMA2, S_PLASMAFLASH1, S_PLASMAFLASH2, S_BFG, S_BFGDOWN, S_BFGUP, S_BFG1, S_BFG2, S_BFG3, S_BFG4, S_BFGFLASH1, S_BFGFLASH2, S_BLOOD1, S_BLOOD2, S_BLOOD3, S_PUFF1, S_PUFF2, S_PUFF3, S_PUFF4, S_TBALL1, S_TBALL2, S_TBALLX1, S_TBALLX2, S_TBALLX3, S_RBALL1, S_RBALL2, S_RBALLX1, S_RBALLX2, S_RBALLX3, S_PLASBALL, S_PLASBALL2, S_PLASEXP, S_PLASEXP2, S_PLASEXP3, S_PLASEXP4, S_PLASEXP5, S_ROCKET, S_BFGSHOT, S_BFGSHOT2, S_BFGLAND, S_BFGLAND2, S_BFGLAND3, S_BFGLAND4, S_BFGLAND5, S_BFGLAND6, S_BFGEXP, S_BFGEXP2, S_BFGEXP3, S_BFGEXP4, S_EXPLODE1, S_EXPLODE2, S_EXPLODE3, S_TFOG, S_TFOG01, S_TFOG02, S_TFOG2, S_TFOG3, S_TFOG4, S_TFOG5, S_TFOG6, S_TFOG7, S_TFOG8, S_TFOG9, S_TFOG10, S_IFOG, S_IFOG01, S_IFOG02, S_IFOG2, S_IFOG3, S_IFOG4, S_IFOG5, S_PLAY, S_PLAY_RUN1, S_PLAY_RUN2, S_PLAY_RUN3, S_PLAY_RUN4, S_PLAY_ATK1, S_PLAY_ATK2, S_PLAY_PAIN, S_PLAY_PAIN2, S_PLAY_DIE1, S_PLAY_DIE2, S_PLAY_DIE3, S_PLAY_DIE4, S_PLAY_DIE5, S_PLAY_DIE6, S_PLAY_DIE7, S_PLAY_XDIE1, S_PLAY_XDIE2, S_PLAY_XDIE3, S_PLAY_XDIE4, S_PLAY_XDIE5, S_PLAY_XDIE6, S_PLAY_XDIE7, S_PLAY_XDIE8, S_PLAY_XDIE9, S_POSS_STND, S_POSS_STND2, S_POSS_RUN1, S_POSS_RUN2, S_POSS_RUN3, S_POSS_RUN4, S_POSS_RUN5, S_POSS_RUN6, S_POSS_RUN7, S_POSS_RUN8, S_POSS_ATK1, S_POSS_ATK2, S_POSS_ATK3, S_POSS_PAIN, S_POSS_PAIN2, S_POSS_DIE1, S_POSS_DIE2, S_POSS_DIE3, S_POSS_DIE4, S_POSS_DIE5, S_POSS_XDIE1, S_POSS_XDIE2, S_POSS_XDIE3, S_POSS_XDIE4, S_POSS_XDIE5, S_POSS_XDIE6, S_POSS_XDIE7, S_POSS_XDIE8, S_POSS_XDIE9, S_POSS_RAISE1, S_POSS_RAISE2, S_POSS_RAISE3, S_POSS_RAISE4, S_SPOS_STND, S_SPOS_STND2, S_SPOS_RUN1, S_SPOS_RUN2, S_SPOS_RUN3, S_SPOS_RUN4, S_SPOS_RUN5, S_SPOS_RUN6, S_SPOS_RUN7, S_SPOS_RUN8, S_SPOS_ATK1, S_SPOS_ATK2, S_SPOS_ATK3, S_SPOS_PAIN, S_SPOS_PAIN2, S_SPOS_DIE1, S_SPOS_DIE2, S_SPOS_DIE3, S_SPOS_DIE4, S_SPOS_DIE5, S_SPOS_XDIE1, S_SPOS_XDIE2, S_SPOS_XDIE3, S_SPOS_XDIE4, S_SPOS_XDIE5, S_SPOS_XDIE6, S_SPOS_XDIE7, S_SPOS_XDIE8, S_SPOS_XDIE9, S_SPOS_RAISE1, S_SPOS_RAISE2, S_SPOS_RAISE3, S_SPOS_RAISE4, S_SPOS_RAISE5, S_VILE_STND, S_VILE_STND2, S_VILE_RUN1, S_VILE_RUN2, S_VILE_RUN3, S_VILE_RUN4, S_VILE_RUN5, S_VILE_RUN6, S_VILE_RUN7, S_VILE_RUN8, S_VILE_RUN9, S_VILE_RUN10, S_VILE_RUN11, S_VILE_RUN12, S_VILE_ATK1, S_VILE_ATK2, S_VILE_ATK3, S_VILE_ATK4, S_VILE_ATK5, S_VILE_ATK6, S_VILE_ATK7, S_VILE_ATK8, S_VILE_ATK9, S_VILE_ATK10, S_VILE_ATK11, S_VILE_HEAL1, S_VILE_HEAL2, S_VILE_HEAL3, S_VILE_PAIN, S_VILE_PAIN2, S_VILE_DIE1, S_VILE_DIE2, S_VILE_DIE3, S_VILE_DIE4, S_VILE_DIE5, S_VILE_DIE6, S_VILE_DIE7, S_VILE_DIE8, S_VILE_DIE9, S_VILE_DIE10, S_FIRE1, S_FIRE2, S_FIRE3, S_FIRE4, S_FIRE5, S_FIRE6, S_FIRE7, S_FIRE8, S_FIRE9, S_FIRE10, S_FIRE11, S_FIRE12, S_FIRE13, S_FIRE14, S_FIRE15, S_FIRE16, S_FIRE17, S_FIRE18, S_FIRE19, S_FIRE20, S_FIRE21, S_FIRE22, S_FIRE23, S_FIRE24, S_FIRE25, S_FIRE26, S_FIRE27, S_FIRE28, S_FIRE29, S_FIRE30, S_SMOKE1, S_SMOKE2, S_SMOKE3, S_SMOKE4, S_SMOKE5, S_TRACER, S_TRACER2, S_TRACEEXP1, S_TRACEEXP2, S_TRACEEXP3, S_SKEL_STND, S_SKEL_STND2, S_SKEL_RUN1, S_SKEL_RUN2, S_SKEL_RUN3, S_SKEL_RUN4, S_SKEL_RUN5, S_SKEL_RUN6, S_SKEL_RUN7, S_SKEL_RUN8, S_SKEL_RUN9, S_SKEL_RUN10, S_SKEL_RUN11, S_SKEL_RUN12, S_SKEL_FIST1, S_SKEL_FIST2, S_SKEL_FIST3, S_SKEL_FIST4, S_SKEL_MISS1, S_SKEL_MISS2, S_SKEL_MISS3, S_SKEL_MISS4, S_SKEL_PAIN, S_SKEL_PAIN2, S_SKEL_DIE1, S_SKEL_DIE2, S_SKEL_DIE3, S_SKEL_DIE4, S_SKEL_DIE5, S_SKEL_DIE6, S_SKEL_RAISE1, S_SKEL_RAISE2, S_SKEL_RAISE3, S_SKEL_RAISE4, S_SKEL_RAISE5, S_SKEL_RAISE6, S_FATSHOT1, S_FATSHOT2, S_FATSHOTX1, S_FATSHOTX2, S_FATSHOTX3, S_FATT_STND, S_FATT_STND2, S_FATT_RUN1, S_FATT_RUN2, S_FATT_RUN3, S_FATT_RUN4, S_FATT_RUN5, S_FATT_RUN6, S_FATT_RUN7, S_FATT_RUN8, S_FATT_RUN9, S_FATT_RUN10, S_FATT_RUN11, S_FATT_RUN12, S_FATT_ATK1, S_FATT_ATK2, S_FATT_ATK3, S_FATT_ATK4, S_FATT_ATK5, S_FATT_ATK6, S_FATT_ATK7, S_FATT_ATK8, S_FATT_ATK9, S_FATT_ATK10, S_FATT_PAIN, S_FATT_PAIN2, S_FATT_DIE1, S_FATT_DIE2, S_FATT_DIE3, S_FATT_DIE4, S_FATT_DIE5, S_FATT_DIE6, S_FATT_DIE7, S_FATT_DIE8, S_FATT_DIE9, S_FATT_DIE10, S_FATT_RAISE1, S_FATT_RAISE2, S_FATT_RAISE3, S_FATT_RAISE4, S_FATT_RAISE5, S_FATT_RAISE6, S_FATT_RAISE7, S_FATT_RAISE8, S_CPOS_STND, S_CPOS_STND2, S_CPOS_RUN1, S_CPOS_RUN2, S_CPOS_RUN3, S_CPOS_RUN4, S_CPOS_RUN5, S_CPOS_RUN6, S_CPOS_RUN7, S_CPOS_RUN8, S_CPOS_ATK1, S_CPOS_ATK2, S_CPOS_ATK3, S_CPOS_ATK4, S_CPOS_PAIN, S_CPOS_PAIN2, S_CPOS_DIE1, S_CPOS_DIE2, S_CPOS_DIE3, S_CPOS_DIE4, S_CPOS_DIE5, S_CPOS_DIE6, S_CPOS_DIE7, S_CPOS_XDIE1, S_CPOS_XDIE2, S_CPOS_XDIE3, S_CPOS_XDIE4, S_CPOS_XDIE5, S_CPOS_XDIE6, S_CPOS_RAISE1, S_CPOS_RAISE2, S_CPOS_RAISE3, S_CPOS_RAISE4, S_CPOS_RAISE5, S_CPOS_RAISE6, S_CPOS_RAISE7, S_TROO_STND, S_TROO_STND2, S_TROO_RUN1, S_TROO_RUN2, S_TROO_RUN3, S_TROO_RUN4, S_TROO_RUN5, S_TROO_RUN6, S_TROO_RUN7, S_TROO_RUN8, S_TROO_ATK1, S_TROO_ATK2, S_TROO_ATK3, S_TROO_PAIN, S_TROO_PAIN2, S_TROO_DIE1, S_TROO_DIE2, S_TROO_DIE3, S_TROO_DIE4, S_TROO_DIE5, S_TROO_XDIE1, S_TROO_XDIE2, S_TROO_XDIE3, S_TROO_XDIE4, S_TROO_XDIE5, S_TROO_XDIE6, S_TROO_XDIE7, S_TROO_XDIE8, S_TROO_RAISE1, S_TROO_RAISE2, S_TROO_RAISE3, S_TROO_RAISE4, S_TROO_RAISE5, S_SARG_STND, S_SARG_STND2, S_SARG_RUN1, S_SARG_RUN2, S_SARG_RUN3, S_SARG_RUN4, S_SARG_RUN5, S_SARG_RUN6, S_SARG_RUN7, S_SARG_RUN8, S_SARG_ATK1, S_SARG_ATK2, S_SARG_ATK3, S_SARG_PAIN, S_SARG_PAIN2, S_SARG_DIE1, S_SARG_DIE2, S_SARG_DIE3, S_SARG_DIE4, S_SARG_DIE5, S_SARG_DIE6, S_SARG_RAISE1, S_SARG_RAISE2, S_SARG_RAISE3, S_SARG_RAISE4, S_SARG_RAISE5, S_SARG_RAISE6, S_HEAD_STND, S_HEAD_RUN1, S_HEAD_ATK1, S_HEAD_ATK2, S_HEAD_ATK3, S_HEAD_PAIN, S_HEAD_PAIN2, S_HEAD_PAIN3, S_HEAD_DIE1, S_HEAD_DIE2, S_HEAD_DIE3, S_HEAD_DIE4, S_HEAD_DIE5, S_HEAD_DIE6, S_HEAD_RAISE1, S_HEAD_RAISE2, S_HEAD_RAISE3, S_HEAD_RAISE4, S_HEAD_RAISE5, S_HEAD_RAISE6, S_BRBALL1, S_BRBALL2, S_BRBALLX1, S_BRBALLX2, S_BRBALLX3, S_BOSS_STND, S_BOSS_STND2, S_BOSS_RUN1, S_BOSS_RUN2, S_BOSS_RUN3, S_BOSS_RUN4, S_BOSS_RUN5, S_BOSS_RUN6, S_BOSS_RUN7, S_BOSS_RUN8, S_BOSS_ATK1, S_BOSS_ATK2, S_BOSS_ATK3, S_BOSS_PAIN, S_BOSS_PAIN2, S_BOSS_DIE1, S_BOSS_DIE2, S_BOSS_DIE3, S_BOSS_DIE4, S_BOSS_DIE5, S_BOSS_DIE6, S_BOSS_DIE7, S_BOSS_RAISE1, S_BOSS_RAISE2, S_BOSS_RAISE3, S_BOSS_RAISE4, S_BOSS_RAISE5, S_BOSS_RAISE6, S_BOSS_RAISE7, S_BOS2_STND, S_BOS2_STND2, S_BOS2_RUN1, S_BOS2_RUN2, S_BOS2_RUN3, S_BOS2_RUN4, S_BOS2_RUN5, S_BOS2_RUN6, S_BOS2_RUN7, S_BOS2_RUN8, S_BOS2_ATK1, S_BOS2_ATK2, S_BOS2_ATK3, S_BOS2_PAIN, S_BOS2_PAIN2, S_BOS2_DIE1, S_BOS2_DIE2, S_BOS2_DIE3, S_BOS2_DIE4, S_BOS2_DIE5, S_BOS2_DIE6, S_BOS2_DIE7, S_BOS2_RAISE1, S_BOS2_RAISE2, S_BOS2_RAISE3, S_BOS2_RAISE4, S_BOS2_RAISE5, S_BOS2_RAISE6, S_BOS2_RAISE7, S_SKULL_STND, S_SKULL_STND2, S_SKULL_RUN1, S_SKULL_RUN2, S_SKULL_ATK1, S_SKULL_ATK2, S_SKULL_ATK3, S_SKULL_ATK4, S_SKULL_PAIN, S_SKULL_PAIN2, S_SKULL_DIE1, S_SKULL_DIE2, S_SKULL_DIE3, S_SKULL_DIE4, S_SKULL_DIE5, S_SKULL_DIE6, S_SPID_STND, S_SPID_STND2, S_SPID_RUN1, S_SPID_RUN2, S_SPID_RUN3, S_SPID_RUN4, S_SPID_RUN5, S_SPID_RUN6, S_SPID_RUN7, S_SPID_RUN8, S_SPID_RUN9, S_SPID_RUN10, S_SPID_RUN11, S_SPID_RUN12, S_SPID_ATK1, S_SPID_ATK2, S_SPID_ATK3, S_SPID_ATK4, S_SPID_PAIN, S_SPID_PAIN2, S_SPID_DIE1, S_SPID_DIE2, S_SPID_DIE3, S_SPID_DIE4, S_SPID_DIE5, S_SPID_DIE6, S_SPID_DIE7, S_SPID_DIE8, S_SPID_DIE9, S_SPID_DIE10, S_SPID_DIE11, S_BSPI_STND, S_BSPI_STND2, S_BSPI_SIGHT, S_BSPI_RUN1, S_BSPI_RUN2, S_BSPI_RUN3, S_BSPI_RUN4, S_BSPI_RUN5, S_BSPI_RUN6, S_BSPI_RUN7, S_BSPI_RUN8, S_BSPI_RUN9, S_BSPI_RUN10, S_BSPI_RUN11, S_BSPI_RUN12, S_BSPI_ATK1, S_BSPI_ATK2, S_BSPI_ATK3, S_BSPI_ATK4, S_BSPI_PAIN, S_BSPI_PAIN2, S_BSPI_DIE1, S_BSPI_DIE2, S_BSPI_DIE3, S_BSPI_DIE4, S_BSPI_DIE5, S_BSPI_DIE6, S_BSPI_DIE7, S_BSPI_RAISE1, S_BSPI_RAISE2, S_BSPI_RAISE3, S_BSPI_RAISE4, S_BSPI_RAISE5, S_BSPI_RAISE6, S_BSPI_RAISE7, S_ARACH_PLAZ, S_ARACH_PLAZ2, S_ARACH_PLEX, S_ARACH_PLEX2, S_ARACH_PLEX3, S_ARACH_PLEX4, S_ARACH_PLEX5, S_CYBER_STND, S_CYBER_STND2, S_CYBER_RUN1, S_CYBER_RUN2, S_CYBER_RUN3, S_CYBER_RUN4, S_CYBER_RUN5, S_CYBER_RUN6, S_CYBER_RUN7, S_CYBER_RUN8, S_CYBER_ATK1, S_CYBER_ATK2, S_CYBER_ATK3, S_CYBER_ATK4, S_CYBER_ATK5, S_CYBER_ATK6, S_CYBER_PAIN, S_CYBER_DIE1, S_CYBER_DIE2, S_CYBER_DIE3, S_CYBER_DIE4, S_CYBER_DIE5, S_CYBER_DIE6, S_CYBER_DIE7, S_CYBER_DIE8, S_CYBER_DIE9, S_CYBER_DIE10, S_PAIN_STND, S_PAIN_RUN1, S_PAIN_RUN2, S_PAIN_RUN3, S_PAIN_RUN4, S_PAIN_RUN5, S_PAIN_RUN6, S_PAIN_ATK1, S_PAIN_ATK2, S_PAIN_ATK3, S_PAIN_ATK4, S_PAIN_PAIN, S_PAIN_PAIN2, S_PAIN_DIE1, S_PAIN_DIE2, S_PAIN_DIE3, S_PAIN_DIE4, S_PAIN_DIE5, S_PAIN_DIE6, S_PAIN_RAISE1, S_PAIN_RAISE2, S_PAIN_RAISE3, S_PAIN_RAISE4, S_PAIN_RAISE5, S_PAIN_RAISE6, S_SSWV_STND, S_SSWV_STND2, S_SSWV_RUN1, S_SSWV_RUN2, S_SSWV_RUN3, S_SSWV_RUN4, S_SSWV_RUN5, S_SSWV_RUN6, S_SSWV_RUN7, S_SSWV_RUN8, S_SSWV_ATK1, S_SSWV_ATK2, S_SSWV_ATK3, S_SSWV_ATK4, S_SSWV_ATK5, S_SSWV_ATK6, S_SSWV_PAIN, S_SSWV_PAIN2, S_SSWV_DIE1, S_SSWV_DIE2, S_SSWV_DIE3, S_SSWV_DIE4, S_SSWV_DIE5, S_SSWV_XDIE1, S_SSWV_XDIE2, S_SSWV_XDIE3, S_SSWV_XDIE4, S_SSWV_XDIE5, S_SSWV_XDIE6, S_SSWV_XDIE7, S_SSWV_XDIE8, S_SSWV_XDIE9, S_SSWV_RAISE1, S_SSWV_RAISE2, S_SSWV_RAISE3, S_SSWV_RAISE4, S_SSWV_RAISE5, S_KEENSTND, S_COMMKEEN, S_COMMKEEN2, S_COMMKEEN3, S_COMMKEEN4, S_COMMKEEN5, S_COMMKEEN6, S_COMMKEEN7, S_COMMKEEN8, S_COMMKEEN9, S_COMMKEEN10, S_COMMKEEN11, S_COMMKEEN12, S_KEENPAIN, S_KEENPAIN2, S_BRAIN, S_BRAIN_PAIN, S_BRAIN_DIE1, S_BRAIN_DIE2, S_BRAIN_DIE3, S_BRAIN_DIE4, S_BRAINEYE, S_BRAINEYESEE, S_BRAINEYE1, S_SPAWN1, S_SPAWN2, S_SPAWN3, S_SPAWN4, S_SPAWNFIRE1, S_SPAWNFIRE2, S_SPAWNFIRE3, S_SPAWNFIRE4, S_SPAWNFIRE5, S_SPAWNFIRE6, S_SPAWNFIRE7, S_SPAWNFIRE8, S_BRAINEXPLODE1, S_BRAINEXPLODE2, S_BRAINEXPLODE3, S_ARM1, S_ARM1A, S_ARM2, S_ARM2A, S_BAR1, S_BAR2, S_BEXP, S_BEXP2, S_BEXP3, S_BEXP4, S_BEXP5, S_BBAR1, S_BBAR2, S_BBAR3, S_BON1, S_BON1A, S_BON1B, S_BON1C, S_BON1D, S_BON1E, S_BON2, S_BON2A, S_BON2B, S_BON2C, S_BON2D, S_BON2E, S_BKEY, S_BKEY2, S_RKEY, S_RKEY2, S_YKEY, S_YKEY2, S_BSKULL, S_BSKULL2, S_RSKULL, S_RSKULL2, S_YSKULL, S_YSKULL2, S_STIM, S_MEDI, S_SOUL, S_SOUL2, S_SOUL3, S_SOUL4, S_SOUL5, S_SOUL6, S_PINV, S_PINV2, S_PINV3, S_PINV4, S_PSTR, S_PINS, S_PINS2, S_PINS3, S_PINS4, S_MEGA, S_MEGA2, S_MEGA3, S_MEGA4, S_SUIT, S_PMAP, S_PMAP2, S_PMAP3, S_PMAP4, S_PMAP5, S_PMAP6, S_PVIS, S_PVIS2, S_CLIP, S_AMMO, S_ROCK, S_BROK, S_CELL, S_CELP, S_SHEL, S_SBOX, S_BPAK, S_BFUG, S_MGUN, S_CSAW, S_LAUN, S_PLAS, S_SHOT, S_SHOT2, S_COLU, S_STALAG, S_BLOODYTWITCH, S_BLOODYTWITCH2, S_BLOODYTWITCH3, S_BLOODYTWITCH4, S_DEADTORSO, S_DEADBOTTOM, S_HEADSONSTICK, S_GIBS, S_HEADONASTICK, S_HEADCANDLES, S_HEADCANDLES2, S_DEADSTICK, S_LIVESTICK, S_LIVESTICK2, S_MEAT2, S_MEAT3, S_MEAT4, S_MEAT5, S_STALAGTITE, S_TALLGRNCOL, S_SHRTGRNCOL, S_TALLREDCOL, S_SHRTREDCOL, S_CANDLESTIK, S_CANDELABRA, S_SKULLCOL, S_TORCHTREE, S_BIGTREE, S_TECHPILLAR, S_EVILEYE, S_EVILEYE2, S_EVILEYE3, S_EVILEYE4, S_FLOATSKULL, S_FLOATSKULL2, S_FLOATSKULL3, S_HEARTCOL, S_HEARTCOL2, S_BLUETORCH, S_BLUETORCH2, S_BLUETORCH3, S_BLUETORCH4, S_GREENTORCH, S_GREENTORCH2, S_GREENTORCH3, S_GREENTORCH4, S_REDTORCH, S_REDTORCH2, S_REDTORCH3, S_REDTORCH4, S_BTORCHSHRT, S_BTORCHSHRT2, S_BTORCHSHRT3, S_BTORCHSHRT4, S_GTORCHSHRT, S_GTORCHSHRT2, S_GTORCHSHRT3, S_GTORCHSHRT4, S_RTORCHSHRT, S_RTORCHSHRT2, S_RTORCHSHRT3, S_RTORCHSHRT4, S_HANGNOGUTS, S_HANGBNOBRAIN, S_HANGTLOOKDN, S_HANGTSKULL, S_HANGTLOOKUP, S_HANGTNOBRAIN, S_COLONGIBS, S_SMALLPOOL, S_BRAINSTEM, S_TECHLAMP, S_TECHLAMP2, S_TECHLAMP3, S_TECHLAMP4, S_TECH2LAMP, S_TECH2LAMP2, S_TECH2LAMP3, S_TECH2LAMP4, NUMSTATES } statenum_t; typedef struct { spritenum_t sprite; long frame; long tics; void (*action) (); statenum_t nextstate; long misc1, misc2; } state_t; extern state_t states[NUMSTATES]; extern char *sprnames[NUMSPRITES]; typedef enum { MT_PLAYER, MT_POSSESSED, MT_SHOTGUY, MT_VILE, MT_FIRE, MT_UNDEAD, MT_TRACER, MT_SMOKE, MT_FATSO, MT_FATSHOT, MT_CHAINGUY, MT_TROOP, MT_SERGEANT, MT_SHADOWS, MT_HEAD, MT_BRUISER, MT_BRUISERSHOT, MT_KNIGHT, MT_SKULL, MT_SPIDER, MT_BABY, MT_CYBORG, MT_PAIN, MT_WOLFSS, MT_KEEN, MT_BOSSBRAIN, MT_BOSSSPIT, MT_BOSSTARGET, MT_SPAWNSHOT, MT_SPAWNFIRE, MT_BARREL, MT_TROOPSHOT, MT_HEADSHOT, MT_ROCKET, MT_PLASMA, MT_BFG, MT_ARACHPLAZ, MT_PUFF, MT_BLOOD, MT_TFOG, MT_IFOG, MT_TELEPORTMAN, MT_EXTRABFG, MT_MISC0, MT_MISC1, MT_MISC2, MT_MISC3, MT_MISC4, MT_MISC5, MT_MISC6, MT_MISC7, MT_MISC8, MT_MISC9, MT_MISC10, MT_MISC11, MT_MISC12, MT_INV, MT_MISC13, MT_INS, MT_MISC14, MT_MISC15, MT_MISC16, MT_MEGA, MT_CLIP, MT_MISC17, MT_MISC18, MT_MISC19, MT_MISC20, MT_MISC21, MT_MISC22, MT_MISC23, MT_MISC24, MT_MISC25, MT_CHAINGUN, MT_MISC26, MT_MISC27, MT_MISC28, MT_SHOTGUN, MT_SUPERSHOTGUN, MT_MISC29, MT_MISC30, MT_MISC31, MT_MISC32, MT_MISC33, MT_MISC34, MT_MISC35, MT_MISC36, MT_MISC37, MT_MISC38, MT_MISC39, MT_MISC40, MT_MISC41, MT_MISC42, MT_MISC43, MT_MISC44, MT_MISC45, MT_MISC46, MT_MISC47, MT_MISC48, MT_MISC49, MT_MISC50, MT_MISC51, MT_MISC52, MT_MISC53, MT_MISC54, MT_MISC55, MT_MISC56, MT_MISC57, MT_MISC58, MT_MISC59, MT_MISC60, MT_MISC61, MT_MISC62, MT_MISC63, MT_MISC64, MT_MISC65, MT_MISC66, MT_MISC67, MT_MISC68, MT_MISC69, MT_MISC70, MT_MISC71, MT_MISC72, MT_MISC73, MT_MISC74, MT_MISC75, MT_MISC76, MT_MISC77, MT_MISC78, MT_MISC79, MT_MISC80, MT_MISC81, MT_MISC82, MT_MISC83, MT_MISC84, MT_MISC85, MT_MISC86, NUMMOBJTYPES} mobjtype_t; typedef struct { int doomednum; int spawnstate; int spawnhealth; int seestate; int seesound; int reactiontime; int attacksound; int painstate; int painchance; int painsound; int meleestate; int missilestate; int deathstate; int xdeathstate; int deathsound; int speed; int radius; int height; int mass; int damage; int activesound; int flags; int raisestate; } mobjinfo_t; extern mobjinfo_t mobjinfo[NUMMOBJTYPES]; \ No newline at end of file diff --git a/IRIX.C b/IRIX.C new file mode 100644 index 0000000..6ee5e7f --- /dev/null +++ b/IRIX.C @@ -0,0 +1 @@ +#include "sndserver.h" #include #include #include #include "irix.h" #define al_QUEUESIZE SAMPLECOUNT*2 //#define al_QUEUESIZE SAMPLECOUNT extern int snd_verbose; extern int myargc; extern char **myargv; static ALconfig al_config; static ALport al_outport; void I_InitMusic(void) { } void I_InitSound(int samplerate, int samplesize) { long paramset[16*2]; if (samplesize == 24) samplesize = 32; // takes care of padding for 24-bit sound ALseterrorhandler(0); // turn off audio library error handler al_config = ALnewconfig(); // create new config for specific rate & format // ALsetchannels(al_config, AL_MONO); // mono ALsetchannels(al_config, AL_STEREO); // stereo ALsetqueuesize(al_config, al_QUEUESIZE); // submission queue size ALsetsampfmt(al_config, AL_SAMPFMT_TWOSCOMP); // 2's complement fmt ALsetwidth(al_config, samplesize/8); // word size al_outport = ALopenport("iddigout1", "w", al_config); if (!al_outport) { fprintf(stderr, "Could not open audio port\n"); exit(-1); } paramset[0] = AL_OUTPUT_RATE; paramset[1] = samplerate; ALsetparams(AL_DEFAULT_DEVICE, paramset, 2); paramset[0*2] = AL_INPUT_SOURCE; paramset[1*2] = AL_LEFT_INPUT_ATTEN; paramset[2*2] = AL_RIGHT_INPUT_ATTEN; paramset[3*2] = AL_INPUT_RATE; paramset[4*2] = AL_OUTPUT_RATE; paramset[5*2] = AL_LEFT_SPEAKER_GAIN; paramset[6*2] = AL_RIGHT_SPEAKER_GAIN; paramset[7*2] = AL_INPUT_COUNT; paramset[8*2] = AL_OUTPUT_COUNT; paramset[9*2] = AL_UNUSED_COUNT; paramset[10*2] = AL_SYNC_INPUT_TO_AES; paramset[11*2] = AL_SYNC_OUTPUT_TO_AES; paramset[12*2] = AL_MONITOR_CTL; paramset[13*2] = AL_LEFT_MONITOR_ATTEN; paramset[14*2] = AL_RIGHT_MONITOR_ATTEN; ALgetparams(AL_DEFAULT_DEVICE, paramset, 15*2); if (snd_verbose) { fprintf(stderr, "AL_INPUT_SOURCE=%d\n", paramset[0*2+1]); fprintf(stderr, "AL_LEFT_INPUT_ATTEN=%d\n", paramset[1*2+1]); fprintf(stderr, "AL_RIGHT_INPUT_ATTEN=%d\n", paramset[2*2+1]); fprintf(stderr, "AL_INPUT_RATE=%d\n", paramset[3*2+1]); fprintf(stderr, "AL_OUTPUT_RATE=%d\n", paramset[4*2+1]); fprintf(stderr, "AL_LEFT_SPEAKER_GAIN=%d\n", paramset[5*2+1]); fprintf(stderr, "AL_RIGHT_SPEAKER_GAIN=%d\n", paramset[6*2+1]); fprintf(stderr, "AL_INPUT_COUNT=%d\n", paramset[7*2+1]); fprintf(stderr, "AL_OUTPUT_COUNT=%d\n", paramset[8*2+1]); fprintf(stderr, "AL_UNUSED_COUNT=%d\n", paramset[9*2+1]); fprintf(stderr, "AL_SYNC_INPUT_TO_AES=%d\n", paramset[10*2+1]); fprintf(stderr, "AL_SYNC_OUTPUT_TO_AES=%d\n", paramset[11*2+1]); fprintf(stderr, "AL_MONITOR_CTL=%d\n", paramset[12*2+1]); fprintf(stderr, "AL_LEFT_MONITOR_ATTEN=%d\n", paramset[13*2+1]); fprintf(stderr, "AL_RIGHT_MONITOR_ATTEN=%d\n", paramset[14*2+1]); fprintf(stderr, "ALgetchannels()=%d\n", ALgetchannels(al_config)); fprintf(stderr, "ALgetqueuesize()=%d\n", ALgetqueuesize(al_config)); fprintf(stderr, "ALgetsampfmt()=%d\n", ALgetsampfmt(al_config)); fprintf(stderr, "ALgetwidth()=%d\n", ALgetwidth(al_config)); } } signed char debugbuffer[1024][8]; void I_SubmitOutputBuffer(void *samples, int samplecount) { int i; /* for (i=0 ; i<1024 ; i++) { debugbuffer[i][0] = ((signed char *) samples)[i]; debugbuffer[i][1] = ((signed char *) samples)[i+1]; } ALwritesamps(al_outport, debugbuffer, 1024); */ ALwritesamps(al_outport, samples, samplecount*2); } void I_ShutdownSound(void) { ALfreeconfig(al_config); ALcloseport(al_outport); } void I_ShutdownMusic(void) { } \ No newline at end of file diff --git a/IRIX.H b/IRIX.H new file mode 100644 index 0000000..0ffe102 --- /dev/null +++ b/IRIX.H @@ -0,0 +1 @@ +#ifndef __IRIX_H__ #define __IRIX_H__ void I_InitMusic(void); void I_InitSound(int samplerate, int samplesound); void I_SubmitOutputBuffer(void *samples, int samplecount); void I_ShutdownSound(void); void I_ShutdownMusic(void); #endif \ No newline at end of file diff --git a/I_CYBER.C b/I_CYBER.C new file mode 100644 index 0000000..b2fb4f3 --- /dev/null +++ b/I_CYBER.C @@ -0,0 +1 @@ +// I_cyber.c #include #include /* ==================================================== Doom control structure The keybaord and joystick will add to the values set by the cyberman, to a maximum of 0x19000 for forwardmove and sidemove. Angleturn is not bounded at all. parm normal fast ----- ------ ---- forwardmove 0xc800 0x19000 sidemove 0xc000 0x14000 angleturn 0x2800000 0x5000000 The keyboard and joystick have a 1/3 second slow turn of 0x1400000 under normal speed to help aiming. ==================================================== */ typedef struct { char forwardmove; // *2048 for move char sidemove; // *2048 for move short angleturn; // <<16 for angle delta short consistancy; // checks for net game unsigned char chatchar; unsigned char buttons; } ticcmd_t; #define BT_ATTACK 1 #define BT_USE 2 #define BT_CHANGE 4 // if true, the next 3 bits hold weapon num #define BT_WEAPONMASK (8+16+32) #define BT_WEAPONSHIFT 3 //================================================== // // CyberMan detection and usage info // //================================================== #define DPMI_INT 0x31 #define MOUSE_INT 0x33 #define DOSMEMSIZE 64 // enough for any SWIFT structure typedef struct { short x; short y; short z; short pitch; short roll; short yaw; short buttons; } SWIFT_3DStatus; // DPMI real mode interrupt structure static struct rminfo { long EDI; long ESI; long EBP; long reserved_by_system; long EBX; long EDX; long ECX; long EAX; short flags; short ES,DS,FS,GS,IP,CS,SP,SS; } RMI; typedef struct { unsigned char deviceType; unsigned char majorVersion; unsigned char minorVersion; unsigned char absRelFlags; unsigned char centeringFlags; unsigned char reserved[5]; } StaticDeviceData; // values for deviceType: #define DEVTYPE_CYBERMAN 1 short selector; unsigned short segment; // segment of DOS memory block SWIFT_3DStatus *cyberstat; int isCyberPresent; // is CyberMan present? static union REGS regs; static struct SREGS sregs; extern int mousepresent; //=========================================================== // // I_StartupCyberMan // // If a cyberman is present, init it and set isCyberPresent to 1 //=========================================================== void I_StartupCyberMan(void) { StaticDeviceData *pbuf; int success = 0; isCyberPresent = 0; cyberstat = (SWIFT_3DStatus *)I_AllocLow (DOSMEMSIZE); segment = (int)cyberstat>>4; pbuf = (StaticDeviceData *)cyberstat; memset(pbuf, 0, sizeof (StaticDeviceData)); // Use DPMI call 300h to issue mouse interrupt memset(&RMI, 0, sizeof(RMI)); RMI.EAX = 0x53C1; // SWIFT: Get Static Device Data RMI.ES = segment; RMI.EDX = 0; memset(&sregs, 0, sizeof (sregs)); regs.w.ax = 0x0300; // DPMI: simulate interrupt regs.w.bx = MOUSE_INT; regs.w.cx = 0; regs.x.edi = FP_OFF(&RMI); sregs.es = FP_SEG(&RMI); int386x( DPMI_INT, ®s, ®s, &sregs ); if ((short)RMI.EAX != 1) { // SWIFT functions not present printf("CyberMan: Wrong mouse driver - no SWIFT support (AX=%04x).\n", (unsigned)(short)RMI.EAX); } else if (pbuf->deviceType != DEVTYPE_CYBERMAN) { // no SWIFT device, or not CyberMan if (pbuf->deviceType == 0) { printf("CyberMan: no SWIFT device connected.\n"); } else { printf("CyberMan: SWIFT device is not a CyberMan! (type=%d)\n", pbuf->deviceType); } } else { printf("CyberMan: CyberMan %d.%02d connected.\n", pbuf->majorVersion, pbuf->minorVersion); isCyberPresent = 1; mousepresent = 0; } } /* =============== = = I_ReadCyberCmds = =============== */ int oldpos; void I_ReadCyberCmd (ticcmd_t *cmd) { int delta; // Use DPMI call 300h to issue mouse interrupt memset(&RMI, 0, sizeof(RMI)); RMI.EAX = 0x5301; // SWIFT: Get Position and Buttons RMI.ES = segment; RMI.EDX = 0; memset(&sregs, 0, sizeof (sregs)); regs.w.ax = 0x0300; // DPMI: simulate interrupt regs.w.bx = MOUSE_INT; regs.w.cx = 0; regs.x.edi = FP_OFF(&RMI); sregs.es = FP_SEG(&RMI); int386x( DPMI_INT, ®s, ®s, &sregs ); if (cyberstat->y < -7900) cmd->forwardmove = 0xc800/2048; else if (cyberstat->y > 7900) cmd->forwardmove = -0xc800/2048; if (cyberstat->buttons & 4) cmd->buttons |= BT_ATTACK; if (cyberstat->buttons & 2) cmd->buttons |= BT_USE; delta = cyberstat->x - oldpos; oldpos = cyberstat->x; if (cyberstat->buttons & 1) { // strafe if (cyberstat->x < -7900) cmd->sidemove = -0xc800/2048; else if (cyberstat->x > 7900) cmd->sidemove = 0xc800/2048; else cmd->sidemove = delta*40/2048; } else { if (cyberstat->x < -7900) cmd->angleturn = 0x280; else if (cyberstat->x > 7900) cmd->angleturn = -0x280; else cmd->angleturn = -delta*0xa/16; } } void I_Tactile (int on, int off, int total) { if (!isCyberPresent) return; on /= 5; off /= 5; total /= 40; if (on > 255) on = 255; if (off > 255) off = 255; if (total > 255) total = 255; memset(&RMI, 0, sizeof(RMI)); RMI.EAX = 0x5330; // SWIFT: Get Position and Buttons RMI.EBX = on*256+off; RMI.ECX = total; memset(&sregs, 0, sizeof (sregs)); regs.w.ax = 0x0300; // DPMI: simulate interrupt regs.w.bx = MOUSE_INT; regs.w.cx = 0; regs.x.edi = FP_OFF(&RMI); sregs.es = FP_SEG(&RMI); int386x( DPMI_INT, ®s, ®s, &sregs ); } \ No newline at end of file diff --git a/I_DGA.C b/I_DGA.C new file mode 100644 index 0000000..31f20c0 --- /dev/null +++ b/I_DGA.C @@ -0,0 +1 @@ + #include #include #include /*#include */ /*#include */ #include #define DEPTH 8 #include #include #include #include #include #include #include #include #include #define CG3_MMAP_OFFSET 0x04000000 #include #include #include #include #include #include "dga/dga.h" #include "doomdef.h" static Display *display=0; static int screen; static int root; static Visual *vis ; static Window win; static Colormap cmap ; static sigset_t signalset; static int input_pending; static u_char * f_fb; static Dga_window clientp ; static int win_x, win_y, win_w, win_h; static int f_dpy_pitch; static int f_dpy_width; static int f_dpy_height; unsigned char *win_ptr; int framecount = 0; long long frametime; #define POINTER_WARP_COUNTDOWN 1 XEvent report; boolean grabMouse; int doPointerWarp = POINTER_WARP_COUNTDOWN; static int multiply=1; unsigned exptable2[256]; unsigned exptable3[256]; // long long exptable8[256]; int showkeysym=0; static void blocksigio(void) { if(sigprocmask(SIG_BLOCK, & signalset, NULL) < 0) perror("sigprocmask"); } static void unblocksigio(void) { if(sigprocmask(SIG_UNBLOCK, & signalset, NULL) < 0) perror("sigprocmask"); } static void gotio(void) { // fprintf(stderr, "got SIGPOLL\n"); input_pending = 1; } int xlatekey(void) { int rc; rc = XKeycodeToKeysym(display, report.xkey.keycode, 0); if (showkeysym) printf("k=[%d] \r", rc); switch(rc) { case XK_Left: rc = KEY_LEFTARROW; break; case XK_Right: rc = KEY_RIGHTARROW; break; case XK_Down: rc = KEY_DOWNARROW; break; case XK_Up: rc = KEY_UPARROW; break; case XK_Escape: rc = KEY_ESCAPE; break; case XK_Return: rc = KEY_ENTER; break; case XK_Tab: rc = KEY_TAB; break; case XK_F1: rc = KEY_F1; break; case XK_F2: rc = KEY_F2; break; case XK_F3: rc = KEY_F3; break; case XK_F4: rc = KEY_F4; break; case XK_F5: rc = KEY_F5; break; case XK_F6: rc = KEY_F6; break; case XK_F7: rc = KEY_F7; break; case XK_F8: rc = KEY_F8; break; case XK_F9: rc = KEY_F9; break; case XK_F10: rc = KEY_F10; break; case XK_F11: rc = KEY_F11; break; case XK_F12: rc = KEY_F12; break; case XK_BackSpace: case XK_Delete: rc = KEY_BACKSPACE; break; case XK_Pause: rc = KEY_PAUSE; break; case XK_KP_Equal: case XK_equal: rc = KEY_EQUALS; break; case XK_KP_Subtract: case XK_minus: rc = KEY_MINUS; break; case XK_Shift_L: case XK_Shift_R: rc = KEY_RSHIFT; break; case XK_Control_L: case 65512: case 65312: case 65406: case XK_Control_R: rc = KEY_RCTRL; break; case XK_Alt_L: case XK_Meta_L: // case XK_Alt_R: // case XK_Meta_R: rc = KEY_RALT; break; case 268828432: rc = KEY_F11; break; case 268828433: rc = KEY_F12; break; default: if (rc >= XK_space && rc <= XK_asciitilde) rc = rc - XK_space + ' '; if (rc >= 'A' && rc <= 'Z') rc = rc - 'A' + 'a'; break; } return rc; } void I_ShutdownGraphics(void) { dga_win_ungrab(clientp, 1) ; XDgaUnGrabWindow(display, win) ; XCloseDisplay(display); } /* ================ = = I_Error = ================ */ extern boolean demorecording; void I_Error (char *error, ...) { va_list argptr; char string[1024]; if (demorecording) G_CheckDemoStatus(); D_QuitNetGame (); I_ShutdownGraphics(); va_start (argptr,error); fprintf (stderr, "Error: "); vfprintf (stderr,error,argptr); fprintf (stderr, "\n"); va_end (argptr); exit(-1); } /* ==================== = = I_StartFrame = ==================== */ void I_StartFrame (void) { } static int lastmousex = 0; static int lastmousey = 0; boolean mousemoved = false; boolean shmFinished; void I_GetEvent(void) { event_t event; XNextEvent(display, &report); switch (report.type) { case KeyPress: event.type = ev_keydown; event.data1 = xlatekey(); D_PostEvent(&event); break; case KeyRelease: event.type = ev_keyup; event.data1 = xlatekey(); D_PostEvent(&event); break; case ButtonPress: event.type = ev_mouse; event.data1 = (report.xbutton.state & Button1Mask) | (report.xbutton.state & Button2Mask ? 2 : 0) | (report.xbutton.state & Button3Mask ? 4 : 0) | (report.xbutton.button == Button1) | (report.xbutton.button == Button2 ? 2 : 0) | (report.xbutton.button == Button3 ? 4 : 0); event.data2 = event.data3 = 0; D_PostEvent(&event); break; case ButtonRelease: event.type = ev_mouse; event.data1 = (report.xbutton.state & Button1Mask) | (report.xbutton.state & Button2Mask ? 2 : 0) | (report.xbutton.state & Button3Mask ? 4 : 0) ^ (report.xbutton.button == Button1 ? 1 : 0) ^ (report.xbutton.button == Button2 ? 2 : 0) ^ (report.xbutton.button == Button3 ? 4 : 0); event.data2 = event.data3 = 0; D_PostEvent(&event); break; case MotionNotify: event.type = ev_mouse; event.data1 = (report.xmotion.state & Button1Mask) | (report.xmotion.state & Button2Mask ? 2 : 0) | (report.xmotion.state & Button3Mask ? 4 : 0); event.data2 = (report.xmotion.x - lastmousex) << 2; event.data3 = (lastmousey - report.xmotion.y) << 2; if (event.data2 || event.data3) { lastmousex = report.xmotion.x; lastmousey = report.xmotion.y; if (report.xmotion.x != win_w/2 && report.xmotion.y != win_h/2) { D_PostEvent(&event); mousemoved = false; } else { mousemoved = true; } } break; case Expose: case ConfigureNotify: break; default: break; } } /* ==================== = = I_StartTic = ==================== */ void I_StartTic (void) { if (!display) return; if(input_pending) { blocksigio(); while( XEventsQueued(display, QueuedAfterFlush)) I_GetEvent(); input_pending = 0; unblocksigio(); } if (grabMouse) { if (!--doPointerWarp) { XWarpPointer( display, None, win, 0, 0, 0, 0, win_w/2, win_h/2); doPointerWarp = POINTER_WARP_COUNTDOWN; } } mousemoved = false; } /* ==================== = = I_UpdateNoBlit = ==================== */ void I_UpdateNoBlit (void) { } void dgarender(void) { static int lasttic; int tics, i; static unsigned char *bigscreen=0; int incamt; long long *olineptrs[4]; unsigned int *ilineptr; int x, y; incamt = (multiply*f_dpy_pitch - win_w) / 8; ilineptr = (unsigned int *) (screens[0]); for (i=0 ; i 20) tics = 20; for (i=0 ; i milliseconds. void I_StopSong(int handle); // called by anything that wishes to stop music. // stops a song abruptly. // SFX I/O // void *I_GetSoundEffect (char *soundname); // called by routines which wish to play a sound effect at some later // time. Pass it the lump name of a sound effect WITHOUT the sfx // prefix. This means the maximum name length is 7 letters/digits. // The prefixes for different sound cards are 'S','M','A', and 'P'. // They refer to the card type. The routine will cache in the // appropriate sound effect when it is played. void I_UngetSoundEffect (void *soundset); // called by routines which wish to no longer use the sounds at all // frees up the associated structure. It stops any currently playing // sound effects. void I_StartSound (channel_t *c, int vol, int sep, int pitch, int priority); // Starts a sound in a particular sound channel void I_UpdateSoundParams(channel_t *c, int vol, int sep, int pitch); // Updates the volume, separation, and pitch of a sound channel void I_StopSound(channel_t *c); // Stops a sound channel int I_SoundIsPlaying(channel_t *c); // called by S_*()'s to see if a channel is still playing. Returns 0 // if no longer playing, 1 if playing. #endif \ No newline at end of file diff --git a/I_IBM.C b/I_IBM.C new file mode 100644 index 0000000..540697b --- /dev/null +++ b/I_IBM.C @@ -0,0 +1 @@ +#include #include #include #include #include #include "DoomDef.h" #include "R_local.h" #include "dmx.h" #include "sounds.h" #include "i_sound.h" #define DPMI_INT 0x31 //#define NOKBD //#define NOTIMER void I_StartupNet (void); void I_ShutdownNet (void); typedef struct { unsigned edi, esi, ebp, reserved, ebx, edx, ecx, eax; unsigned short flags, es, ds, fs, gs, ip, cs, sp, ss; } dpmiregs_t; extern dpmiregs_t dpmiregs; void I_ReadMouse (void); void I_InitDiskFlash (void); extern int usemouse, usejoystick; /* ============================================================================= CONSTANTS ============================================================================= */ //#define SC_INDEX 0x3C4 #define SC_RESET 0 #define SC_CLOCK 1 //#define SC_MAPMASK 2 #define SC_CHARMAP 3 #define SC_MEMMODE 4 #define CRTC_INDEX 0x3D4 #define CRTC_H_TOTAL 0 #define CRTC_H_DISPEND 1 #define CRTC_H_BLANK 2 #define CRTC_H_ENDBLANK 3 #define CRTC_H_RETRACE 4 #define CRTC_H_ENDRETRACE 5 #define CRTC_V_TOTAL 6 #define CRTC_OVERFLOW 7 #define CRTC_ROWSCAN 8 #define CRTC_MAXSCANLINE 9 #define CRTC_CURSORSTART 10 #define CRTC_CURSOREND 11 #define CRTC_STARTHIGH 12 #define CRTC_STARTLOW 13 #define CRTC_CURSORHIGH 14 #define CRTC_CURSORLOW 15 #define CRTC_V_RETRACE 16 #define CRTC_V_ENDRETRACE 17 #define CRTC_V_DISPEND 18 #define CRTC_OFFSET 19 #define CRTC_UNDERLINE 20 #define CRTC_V_BLANK 21 #define CRTC_V_ENDBLANK 22 #define CRTC_MODE 23 #define CRTC_LINECOMPARE 24 //#define GC_INDEX 0x3CE #define GC_SETRESET 0 #define GC_ENABLESETRESET 1 #define GC_COLORCOMPARE 2 #define GC_DATAROTATE 3 //#define GC_READMAP 4 //#define GC_MODE 5 #define GC_MISCELLANEOUS 6 #define GC_COLORDONTCARE 7 #define GC_BITMASK 8 #define ATR_INDEX 0x3c0 #define ATR_MODE 16 #define ATR_OVERSCAN 17 #define ATR_COLORPLANEENABLE 18 #define ATR_PELPAN 19 #define ATR_COLORSELECT 20 #define STATUS_REGISTER_1 0x3da #define PEL_WRITE_ADR 0x3c8 #define PEL_READ_ADR 0x3c7 #define PEL_DATA 0x3c9 #define PEL_MASK 0x3c6 boolean grmode; //================================================== // // joystick vars // //================================================== boolean joystickpresent; extern unsigned joystickx, joysticky; boolean I_ReadJoystick (void); // returns false if not connected //================================================== #define VBLCOUNTER 34000 // hardware tics to a frame #define TIMERINT 8 #define KEYBOARDINT 9 #define CRTCOFF (_inbyte(STATUS_REGISTER_1)&1) #define CLI _disable() #define STI _enable() #define _outbyte(x,y) (outp(x,y)) #define _outhword(x,y) (outpw(x,y)) #define _inbyte(x) (inp(x)) #define _inhword(x) (inpw(x)) #define MOUSEB1 1 #define MOUSEB2 2 #define MOUSEB3 4 boolean mousepresent; static int tsm_ID = -1; // tsm init flag //=============================== int ticcount; union REGS regs; // scratch for int calls struct SREGS segregs; boolean novideo; // if true, stay in text mode for debugging #define KBDQUESIZE 32 byte keyboardque[KBDQUESIZE]; int kbdtail, kbdhead; #define KEY_LSHIFT 0xfe #define KEY_INS (0x80+0x52) #define KEY_DEL (0x80+0x53) #define KEY_PGUP (0x80+0x49) #define KEY_PGDN (0x80+0x51) #define KEY_HOME (0x80+0x47) #define KEY_END (0x80+0x4f) #define SC_RSHIFT 0x36 #define SC_LSHIFT 0x2a byte scantokey[128] = { // 0 1 2 3 4 5 6 7 // 8 9 A B C D E F 0 , 27, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', KEY_BACKSPACE, 9, // 0 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', 13 , KEY_RCTRL,'a', 's', // 1 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', 39 , '`', KEY_LSHIFT,92, 'z', 'x', 'c', 'v', // 2 'b', 'n', 'm', ',', '.', '/', KEY_RSHIFT,'*', KEY_RALT,' ', 0 , KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_F5, // 3 KEY_F6, KEY_F7, KEY_F8, KEY_F9, KEY_F10,0 , 0 , KEY_HOME, KEY_UPARROW,KEY_PGUP,'-',KEY_LEFTARROW,'5',KEY_RIGHTARROW,'+',KEY_END, //4 KEY_DOWNARROW,KEY_PGDN,KEY_INS,KEY_DEL,0,0, 0, KEY_F11, KEY_F12,0 , 0 , 0 , 0 , 0 , 0 , 0, // 5 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, // 6 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 // 7 }; //=========================================================================== // // control api // typedef struct { int intnum; // doom will call this interrupt ticcmd_t ticcmd; // then the driver will fill in this structure } doomcontrol_t; ticcmd_t emptycmd; doomcontrol_t *doomcon; ticcmd_t *I_BaseTiccmd (void) { if (!doomcon) return &emptycmd; DPMIInt (doomcon->intnum); return &doomcon->ticcmd; } //=========================================================================== /* ================= = = I_GetTime = = returns time in 1/35th second tics ================= */ int I_GetTime (void) { #ifdef NOTIMER ticcount++; #endif return ticcount; } //=========================================================================== /* ================= = = I_ColorBorder = ================= */ void I_ColorBorder (void) { int i; I_WaitVBL(1); _outbyte (PEL_WRITE_ADR,0); for (i=0 ; i<3 ; i++) _outbyte(PEL_DATA,63 ); } void I_UnColorBorder (void) { int i; I_WaitVBL(1); _outbyte (PEL_WRITE_ADR,0); for (i=0 ; i<3 ; i++) _outbyte(PEL_DATA,0); } /* =============================================================================== USER INPUT =============================================================================== */ /* ================= = = I_WaitVBL = ================= */ void I_WaitVBL (int vbls) { int old; int i,stat; if (novideo) return; while (vbls--) { do { stat = inp(STATUS_REGISTER_1); if (stat & 8) break; } while (1); do { stat = inp(STATUS_REGISTER_1); if ( (stat & 8) == 0 ) break; } while ( 1 ); #if 0 // wait for display enabled, so we know it isn't just after vsync waitdisplay: // CLI; while (CRTCOFF) ; waitnodisplay: // CLI; while (!CRTCOFF) ; // wait for display just turned off waitbottom: STI; i--; // time for an interrupt CLI; for (i=0;i<10;i++) { stat = _inbyte(STATUS_REGISTER_1); if (stat & 8) goto waitdisplay; // vsync... if (!(stat&1)) goto waitbottom; } STI; #endif } } /* ================= = = I_SetPalette = = takes full 8 bit values ================= */ void I_SetPalette (byte *palette) { int i; if (novideo) return; I_WaitVBL (1); _outbyte (PEL_WRITE_ADR,0); for (i=0;i<768;i++) _outbyte(PEL_DATA,(gammatable[usegamma][*palette++])>>2 ); } /* ============================================================================= GRAPHICS MODE ============================================================================= */ byte *screen; byte *currentscreen, *destscreen, *destview; #define PLANEWIDTH 80 /* ============== = = I_UpdateBox = ============== */ void I_UpdateBox (int x, int y, int width, int height) { int ofs; byte *source; short *dest; int p,x1, x2; int srcdelta, destdelta; int wwide; if (x<0 || y<0 || width <= 0 || height <= 0 || x+width > SCREENWIDTH || y+height > SCREENHEIGHT) I_Error ("Bad I_UpdateBox (%i, %i, %i, %i)",x,y,width,height); x1 = x>>3; x2 = (x+width)>>3; wwide = x2-x1+1; ofs = y*SCREENWIDTH+(x1<<3); srcdelta = SCREENWIDTH - (wwide<<3); destdelta = PLANEWIDTH/2 - wwide; outp (SC_INDEX, SC_MAPMASK); for (p = 0 ; p < 4 ; p++) { outp (SC_INDEX+1, 1<>2)); for (y=0 ; y volddirtybox[BOXTOP] ? dirtybox[BOXTOP] : volddirtybox[BOXTOP]; updatebox[BOXRIGHT] = dirtybox[BOXRIGHT] > volddirtybox[BOXRIGHT] ? dirtybox[BOXRIGHT] : volddirtybox[BOXRIGHT]; updatebox[BOXBOTTOM] = dirtybox[BOXBOTTOM] < volddirtybox[BOXBOTTOM] ? dirtybox[BOXBOTTOM] : volddirtybox[BOXBOTTOM]; updatebox[BOXLEFT] = dirtybox[BOXLEFT] < volddirtybox[BOXLEFT] ? dirtybox[BOXLEFT] : volddirtybox[BOXLEFT]; updatebox[BOXTOP] = updatebox[BOXTOP] > olddirtybox[BOXTOP] ? updatebox[BOXTOP] : olddirtybox[BOXTOP]; updatebox[BOXRIGHT] = updatebox[BOXRIGHT] > olddirtybox[BOXRIGHT] ? updatebox[BOXRIGHT] : olddirtybox[BOXRIGHT]; updatebox[BOXBOTTOM] = updatebox[BOXBOTTOM] < olddirtybox[BOXBOTTOM] ? updatebox[BOXBOTTOM] : olddirtybox[BOXBOTTOM]; updatebox[BOXLEFT] = updatebox[BOXLEFT] < olddirtybox[BOXLEFT] ? updatebox[BOXLEFT] : olddirtybox[BOXLEFT]; // save this drawing into olddirtybox memcpy (volddirtybox, olddirtybox, sizeof(volddirtybox)); memcpy (olddirtybox, dirtybox, sizeof(olddirtybox)); // update other drawing if (updatebox[BOXTOP] >= updatebox[BOXBOTTOM]) I_UpdateBox (updatebox[BOXLEFT],updatebox[BOXBOTTOM], updatebox[BOXRIGHT] - updatebox[BOXLEFT]+1, updatebox[BOXTOP] - updatebox[BOXBOTTOM]+1); M_ClearBox (dirtybox); } /* ============== = = I_FinishUpdate = ============== */ void I_FinishUpdate (void) { static int lasttic; int tics, i; // // draw tics // if (devparm) { tics = ticcount - lasttic; lasttic = ticcount; if (tics > 20) tics = 20; outpw (SC_INDEX, SC_MAPMASK + 256); for (i=0 ; i64k scans // _outbyte (CRTC_INDEX,CRTC_UNDERLINE); _outbyte (CRTC_INDEX+1,_inbyte(CRTC_INDEX+1)&~0x40); _outbyte (CRTC_INDEX,CRTC_MODE); _outbyte (CRTC_INDEX+1,_inbyte(CRTC_INDEX+1)|0x40); _outbyte (GC_INDEX,GC_READMAP); I_SetPalette (W_CacheLumpName ("PLAYPAL",PU_CACHE)); I_InitDiskFlash (); } /* ============== = = I_ShutdownGraphics = ============== */ void I_ShutdownGraphics (void) { if ( *(byte *)0x449 == 0x13) // don't reset mode if it didn't get set { regs.w.ax = 3; int386 (0x10,®s,®s); // back to text mode } } /* ============== = = I_ReadScreen = = Reads the screen currently displayed into a linear buffer = ============== */ void I_ReadScreen (byte *scr) { int i,p; outp (GC_INDEX, GC_READMAP); for (p=0 ; p<4 ; p++) { outp (GC_INDEX+1,p); for (i=0 ; i> 4)&1)^1; if (buttons != oldbuttons) { oldbuttons = buttons; continue; } if ( (lastpress& 0x7f) == 1 ) { joystickpresent = false; return false; } } while ( !buttons); do { I_WaitVBL (1); buttons = ((inp(0x201) >> 4)&1)^1; if (buttons != oldbuttons) { oldbuttons = buttons; continue; } if ( (lastpress& 0x7f) == 1 ) { joystickpresent = false; return false; } } while ( buttons); return true; } /* =============== = = I_StartupJoystick = =============== */ int basejoyx, basejoyy; void I_StartupJoystick (void) { int buttons; int count; int centerx, centery; joystickpresent = 0; if ( M_CheckParm ("-nojoy") || !usejoystick ) return; if (!I_ReadJoystick ()) { joystickpresent = false; printf ("joystick not found\n"); return; } printf ("joystick found\n"); joystickpresent = true; printf ("CENTER the joystick and press button 1:"); if (!WaitJoyButton ()) return; I_ReadJoystick (); centerx = joystickx; centery = joysticky; printf ("\nPush the joystick to the UPPER LEFT corner and press button 1:"); if (!WaitJoyButton ()) return; I_ReadJoystick (); joyxl = (centerx + joystickx)/2; joyyl = (centerx + joysticky)/2; printf ("\nPush the joystick to the LOWER RIGHT corner and press button 1:"); if (!WaitJoyButton ()) return; I_ReadJoystick (); joyxh = (centerx + joystickx)/2; joyyh = (centery + joysticky)/2; printf ("\n"); } /* =============== = = I_JoystickEvents = =============== */ void I_JoystickEvents (void) { event_t ev; // // joystick events // if (!joystickpresent) return; I_ReadJoystick (); ev.type = ev_joystick; ev.data1 = ((inp(0x201) >> 4)&15)^15; if (joystickx < joyxl) ev.data2 = -1; else if (joystickx > joyxh) ev.data2 = 1; else ev.data2 = 0; if (joysticky < joyyl) ev.data3 = -1; else if (joysticky > joyyh) ev.data3 = 1; else ev.data3 = 0; D_PostEvent (&ev); } /* ============================================================================ DPMI STUFF ============================================================================ */ #define REALSTACKSIZE 1024 dpmiregs_t dpmiregs; unsigned realstackseg; void I_DivException (void); int I_SetDivException (void); void DPMIFarCall (void) { segread (&segregs); regs.w.ax = 0x301; regs.w.bx = 0; regs.w.cx = 0; regs.x.edi = (unsigned)&dpmiregs; segregs.es = segregs.ds; int386x( DPMI_INT, ®s, ®s, &segregs ); } void DPMIInt (int i) { dpmiregs.ss = realstackseg; dpmiregs.sp = REALSTACKSIZE-4; segread (&segregs); regs.w.ax = 0x300; regs.w.bx = i; regs.w.cx = 0; regs.x.edi = (unsigned)&dpmiregs; segregs.es = segregs.ds; int386x( DPMI_INT, ®s, ®s, &segregs ); } /* ============== = = I_StartupDPMI = ============== */ void I_StartupDPMI (void) { extern char __begtext; extern char ___argc; int n,d; // // allocate a decent stack for real mode ISRs // realstackseg = (int)I_AllocLow (1024) >> 4; // // lock the entire program down // _dpmi_lockregion (&__begtext, &___argc - &__begtext); // // catch divide by 0 exception // #if 0 segread(&segregs); regs.w.ax = 0x0203; // DPMI set processor exception handler vector regs.w.bx = 0; // int 0 regs.w.cx = segregs.cs; regs.x.edx = (int)&I_DivException; printf ("%x : %x\n",regs.w.cx, regs.x.edx); int386( DPMI_INT, ®s, ®s); #endif #if 0 n = I_SetDivException (); printf ("return: %i\n",n); n = 100; d = 0; printf ("100 / 0 = %i\n",n/d); exit (1); #endif } /* ============================================================================ TIMER INTERRUPT ============================================================================ */ void (__interrupt __far *oldtimerisr) (); void IO_ColorBlack (int r, int g, int b) { _outbyte (PEL_WRITE_ADR,0); _outbyte(PEL_DATA,r); _outbyte(PEL_DATA,g); _outbyte(PEL_DATA,b); } /* ================ = = IO_TimerISR = ================ */ //void __interrupt IO_TimerISR (void) void __interrupt __far IO_TimerISR (void) { ticcount++; _outbyte(0x20,0x20); // Ack the interrupt } /* ===================== = = IO_SetTimer0 = = Sets system timer 0 to the specified speed = ===================== */ void IO_SetTimer0(int speed) { if (speed > 0 && speed < 150) I_Error ("INT_SetTimer0: %i is a bad value",speed); _outbyte(0x43,0x36); // Change timer 0 _outbyte(0x40,speed); _outbyte(0x40,speed >> 8); } /* =============== = = IO_StartupTimer = =============== */ void IO_StartupTimer (void) { oldtimerisr = _dos_getvect(TIMERINT); _dos_setvect (0x8000 | TIMERINT, IO_TimerISR); IO_SetTimer0 (VBLCOUNTER); } void IO_ShutdownTimer (void) { if (oldtimerisr) { IO_SetTimer0 (0); // back to 18.4 ips _dos_setvect (TIMERINT, oldtimerisr); } } //=========================================================================== /* =============== = = I_Init = = hook interrupts and set graphics mode = =============== */ void I_Init (void) { int i; extern void I_StartupTimer(void); novideo = M_CheckParm ("novideo"); // check for an external controler i = M_CheckParm ("-control"); // -control if (i) { doomcon = (doomcontrol_t *)atoi(myargv[i+1]); printf ("Using external control API\n"); } printf ("I_StartupDPMI\n"); I_StartupDPMI (); printf ("I_StartupMouse\n"); I_StartupMouse (); printf ("I_StartupJoystick\n"); I_StartupJoystick (); printf ("I_StartupKeyboard\n"); I_StartupKeyboard (); //printf ("I_StartupTimer\n"); // I_StartupTimer (); //IO_StartupTimer (); printf ("I_StartupSound\n"); I_StartupSound (); } /* =============== = = I_Shutdown = = return to default system state = =============== */ void I_Shutdown (void) { I_ShutdownGraphics (); I_ShutdownSound (); I_ShutdownTimer (); //IO_ShutdownTimer (); I_ShutdownMouse (); I_ShutdownKeyboard (); } /* ================ = = I_Error = ================ */ boolean G_CheckDemoStatus (void); void I_Error (char *error, ...) { va_list argptr; D_QuitNetGame (); I_Shutdown (); va_start (argptr,error); vprintf (error,argptr); va_end (argptr); printf ("\n"); exit (1); } /* ================ = = I_Quit = ================ */ void I_Quit (void) { byte *scr; if (demorecording) G_CheckDemoStatus (); else D_QuitNetGame (); M_SaveDefaults (); scr = (byte *)W_CacheLumpName ("ENDOOM", PU_CACHE); I_Shutdown (); #if 1 memcpy ((void *)0xb8000,scr,80*25*2); regs.w.ax = 0x0200; regs.h.bh = 0; regs.h.dl = 0; regs.h.dh = 23; int386 (0x10,(const union REGS *)®s,®s); // set text pos printf("\n"); #endif exit(0); } /* =============== = = I_ZoneBase = =============== */ byte *I_ZoneBase (int *size) { int meminfo[32]; int heap; int i; int block; byte *ptr; memset (meminfo,0,sizeof(meminfo)); segread(&segregs); segregs.es = segregs.ds; regs.w.ax = 0x500; // get memory info regs.x.edi = (int)&meminfo; int386x( 0x31, ®s, ®s, &segregs ); heap = meminfo[0]; printf ("DPMI memory: 0x%x",heap); do { heap -= 0x20000; // leave 128k alone if (heap > 0x800000) heap = 0x800000; ptr = malloc (heap); } while (!ptr); printf (", 0x%x allocated for zone\n", heap); if (heap < 0x180000) { printf("\n"); printf("Insufficient memory! You need to have at least 3.7 megabytes of total\n"); printf("free memory available for DOOM to execute. Reconfigure your CONFIG.SYS\n"); printf("or AUTOEXEC.BAT to load fewer device drivers or TSR's. We recommend\n"); printf("creating a custom boot menu item in your CONFIG.SYS for optimum DOOMing.\n"); printf("Please consult your DOS manual (\"Making more memory available\") for\n"); printf("information on how to free up more memory for DOOM.\n\n"); printf("DOOM aborted.\n"); exit(1); // I_Error ("DOOM aborted."); } #if 0 regs.w.ax = 0x501; // allocate linear block regs.w.bx = heap>>16; regs.w.cx = heap&0xffff; int386( 0x31, ®s, ®s); if (regs.w.cflag) I_Error ("Couldn't allocate DPMI memory!"); block = (regs.w.si << 16) + regs.w.di; #endif *size = heap; return ptr; } /* ============================================================================= DISK ICON FLASHING ============================================================================= */ void I_InitDiskFlash (void) { void *pic; byte *temp; if (M_CheckParm("-cdrom")) pic = W_CacheLumpName ("STCDROM",PU_CACHE); else pic = W_CacheLumpName ("STDISK",PU_CACHE); temp = destscreen; destscreen = (byte *)0xac000; V_DrawPatchDirect (SCREENWIDTH-16,SCREENHEIGHT-16,0,pic); destscreen = temp; } // draw disk icon void I_BeginRead (void) { byte *src,*dest; int y; if (!grmode) return; // write through all planes outp (SC_INDEX,SC_MAPMASK); outp (SC_INDEX+1,15); // set write mode 1 outp (GC_INDEX,GC_MODE); outp (GC_INDEX+1,inp(GC_INDEX+1)|1); // copy to backup src = currentscreen + 184*80 + 304/4; dest = (byte *)0xac000 + 184*80 + 288/4; for (y=0 ; y<16 ; y++) { dest[0] = src[0]; dest[1] = src[1]; dest[2] = src[2]; dest[3] = src[3]; src += 80; dest += 80; } // copy disk over dest = currentscreen + 184*80 + 304/4; src = (byte *)0xac000 + 184*80 + 304/4; for (y=0 ; y<16 ; y++) { dest[0] = src[0]; dest[1] = src[1]; dest[2] = src[2]; dest[3] = src[3]; src += 80; dest += 80; } // set write mode 0 outp (GC_INDEX,GC_MODE); outp (GC_INDEX+1,inp(GC_INDEX+1)&~1); } // erase disk icon void I_EndRead (void) { byte *src,*dest; int y; if (!grmode) return; // write through all planes outp (SC_INDEX,SC_MAPMASK); outp (SC_INDEX+1,15); // set write mode 1 outp (GC_INDEX,GC_MODE); outp (GC_INDEX+1,inp(GC_INDEX+1)|1); // copy disk over dest = currentscreen + 184*80 + 304/4; src = (byte *)0xac000 + 184*80 + 288/4; for (y=0 ; y<16 ; y++) { dest[0] = src[0]; dest[1] = src[1]; dest[2] = src[2]; dest[3] = src[3]; src += 80; dest += 80; } // set write mode 0 outp (GC_INDEX,GC_MODE); outp (GC_INDEX+1,inp(GC_INDEX+1)&~1); } /* ============= = = I_AllocLow = ============= */ byte *I_AllocLow (int length) { byte *mem; // DPMI call 100h allocates DOS memory segread(&segregs); regs.w.ax = 0x0100; // DPMI allocate DOS memory regs.w.bx = (length+15) / 16; int386( DPMI_INT, ®s, ®s); // segment = regs.w.ax; // selector = regs.w.dx; if (regs.w.cflag != 0) I_Error ("I_AllocLow: DOS alloc of %i failed, %i free", length, regs.w.bx*16); mem = (void *) ((regs.x.eax & 0xFFFF) << 4); memset (mem,0,length); return mem; } /* ============================================================================ NETWORKING ============================================================================ */ /* // FUCKED LINES typedef struct { char priv[508]; } doomdata_t; */ // FUCKED LINES #define DOOMCOM_ID 0x12345678l /* // FUCKED LINES typedef struct { long id; short intnum; // DOOM executes an int to execute commands // communication between DOOM and the driver short command; // CMD_SEND or CMD_GET short remotenode; // dest for send, set by get (-1 = no packet) short datalength; // bytes in doomdata to be sent // info common to all nodes short numnodes; // console is allways node 0 short ticdup; // 1 = no duplication, 2-5 = dup for slow nets short extratics; // 1 = send a backup tic in every packet short deathmatch; // 1 = deathmatch short savegame; // -1 = new game, 0-5 = load savegame short episode; // 1-3 short map; // 1-9 short skill; // 1-5 // info specific to this node short consoleplayer; short numplayers; short angleoffset; // 1 = left, 0 = center, -1 = right short drone; // 1 = drone // packet data to be sent doomdata_t data; } doomcom_t; */ // FUCKED LINES extern doomcom_t *doomcom; /* ==================== = = I_InitNetwork = ==================== */ void I_InitNetwork (void) { int i; i = M_CheckParm ("-net"); if (!i) { // // single player game // doomcom = malloc (sizeof (*doomcom) ); if (!doomcom) I_Error("malloc() in I_InitNetwork() failed"); memset (doomcom, 0, sizeof(*doomcom) ); netgame = false; doomcom->id = DOOMCOM_ID; doomcom->numplayers = doomcom->numnodes = 1; doomcom->deathmatch = false; doomcom->consoleplayer = 0; doomcom->ticdup = 1; doomcom->extratics = 0; return; } netgame = true; doomcom = (doomcom_t *)atoi(myargv[i+1]); //DEBUG doomcom->skill = startskill; doomcom->episode = startepisode; doomcom->map = startmap; doomcom->deathmatch = deathmatch; } void I_NetCmd (void) { if (!netgame) I_Error ("I_NetCmd when not in netgame"); DPMIInt (doomcom->intnum); } \ No newline at end of file diff --git a/I_IBM_A.ASM b/I_IBM_A.ASM new file mode 100644 index 0000000..df662e0 --- /dev/null +++ b/I_IBM_A.ASM @@ -0,0 +1 @@ + .386 .MODEL small .DATA .CODE IF 0 #define PEL_WRITE_ADR 0x3c8 #define PEL_READ_ADR 0x3c7 #define PEL_DATA 0x3c9 ENDIF ;================ ; ; I_DivException ; ;================ PROC I_DivException_ PUBLIC I_DivException_ mov edx,03c9h mov al,63 out dx,al mov ebx,0ffffffh mov eax,[ebx] retf ENDP ;================ ; ; I_SetDivException ; ;================ PROC I_SetDivException_ PUBLIC I_SetDivException_ pusha mov eax,0212h mov ebx,0 mov ecx,cs mov edx,OFFSET I_DivException_ int 31h jnc good popa mov eax,0 ret good: popa mov eax,1 ret ENDP ;================ ; ; I_ReadJoystick ; ; Read the absolute joystick values ; returns false if not connected ;================ .data _joystickx dd 0 _joysticky dd 0 PUBLIC _joystickx, _joysticky .code PROC I_ReadJoystick_ PUBLIC I_ReadJoystick_ pusha pushf ; state of interrupt flag cli mov dx,0201h in al,dx out dx,al ; Clear the resistors mov ah,1 ; Get masks into registers mov ch,2 xor esi,esi ; Clear count registers xor edi,edi xor ebx,ebx ; Clear high byte of bx for later mov ebp,10000 ; joystick is disconnected if value is this big jloop: in al,dx ; Get bits indicating whether all are finished dec ebp ; Check bounding register jz bad ; We have a silly value - abort mov bl,al ; Duplicate the bits and bl,ah ; Mask off useless bits (in [xb]) add esi,ebx ; Possibly increment count register mov cl,bl ; Save for testing later mov bl,al and bl,ch ; [yb] add edi,ebx add cl,bl jnz jloop ; If both bits were 0, drop out done: mov [_joystickx],esi shr edi,1 ; because 2s were added mov [_joysticky],edi popf ; restore interrupt flag popa mov eax,1 ; read was ok ret bad: popf ; restore interrupt flag popa xor eax,eax ; read was bad ret ENDP END \ No newline at end of file diff --git a/I_MAIN.C b/I_MAIN.C new file mode 100644 index 0000000..b684f75 --- /dev/null +++ b/I_MAIN.C @@ -0,0 +1 @@ + #include "doomdef.h" void main (int argc, char **argv) { myargc = argc; myargv = argv; D_DoomMain (); } \ No newline at end of file diff --git a/I_PCNET.C b/I_PCNET.C new file mode 100644 index 0000000..d0b261c --- /dev/null +++ b/I_PCNET.C @@ -0,0 +1 @@ +// I_pcnet.m #include #include "DoomDef.h" /* ============================================================================= IPX PACKET DRIVER ============================================================================= */ #define DPMI_INT 0x31 typedef unsigned char BYTE; typedef unsigned short WORD; typedef unsigned long LONG; typedef struct IPXPacketStructure { WORD PacketCheckSum; /* high-low */ WORD PacketLength; /* high-low */ BYTE PacketTransportControl; BYTE PacketType; BYTE dNetwork[4]; /* high-low */ BYTE dNode[6]; /* high-low */ BYTE dSocket[2]; /* high-low */ BYTE sNetwork[4]; /* high-low */ BYTE sNode[6]; /* high-low */ BYTE sSocket[2]; /* high-low */ } IPXPacket; typedef struct { BYTE network[4]; /* high-low */ BYTE node[6]; /* high-low */ } localadr_t; typedef struct ECBStructure { WORD Link[2]; /* offset-segment */ WORD ESRAddress[2]; /* offset-segment */ BYTE InUseFlag; BYTE CompletionCode; WORD ECBSocket; /* high-low */ BYTE IPXWorkspace[4]; /* N/A */ BYTE DriverWorkspace[12]; /* N/A */ BYTE ImmediateAddress[6]; /* high-low */ WORD FragmentCount; /* low-high */ // struct ECBFragment FragmentDescriptor[1]; WORD fAddress[2]; /* offset-segment */ WORD fSize; /* low-high */ } ECB; typedef struct { unsigned edi, esi, ebp, reserved, ebx, edx, ecx, eax; unsigned short flags, es, ds, fs, gs, ip, cs, sp, ss; } dpmiregs_t; extern dpmiregs_t dpmiregs; int socketid = 0x869c; // broadcast socket number typedef struct { ECB ecb; IPXPacket ipx; netstruc_t data; int checksum; } packet_t; #define NUMPACKETS 10 packet_t *packets; // [NUMPACKETS] extern union REGS regs; // scratch for int calls extern struct SREGS segregs; unsigned enteripx[2]; #define REAL_OFF(x) ((unsigned)(x)&15) #define REAL_SEG(x) ((unsigned)(x)>>4) int localnetid, remotenetid; localadr_t *localipxadr; void DPMIInt (int i); //=========================================================================== int OpenSocket(short socketNumber) { regs.w.bx = 0; regs.h.al = 0; // longevity regs.w.dx = socketNumber; int386(0x7A,®s,®s); if (regs.h.al) I_Error ("OpenSocket: 0x%x",regs.h.al); return regs.w.dx; } void ListenForPacket(ECB *ecb) { memset (&dpmiregs,0,sizeof(dpmiregs)); dpmiregs.esi = REAL_OFF(ecb); dpmiregs.es = REAL_SEG(ecb); dpmiregs.ebx = 4; dpmiregs.ip = enteripx[0]; dpmiregs.cs = enteripx[1]; //printf ("listen\n"); DPMIInt (0x7a); //printf ("done\n"); if (dpmiregs.eax & 0xff) I_Error ("ListenForPacket: 0x%x",dpmiregs.eax&0xff); } void GetLocalAddress (void) { // // allocate dos memory for info // localipxadr = (localadr_t *)I_AllocLow (sizeof(localadr_t)); // // get the address from ipx // memset (&dpmiregs,0,sizeof(dpmiregs)); dpmiregs.esi = REAL_OFF(localipxadr); dpmiregs.es = REAL_SEG(localipxadr); dpmiregs.ebx = 9; dpmiregs.ip = enteripx[0]; dpmiregs.cs = enteripx[1]; DPMIInt (0x7a); if (dpmiregs.eax & 0xff) I_Error ("Get inet addr: 0x%x",dpmiregs.eax&0xff); localnetid = *(int *)localipxadr->node; localnetid ^= *(int *)&localipxadr->node[2]; printf ("localnetid: 0x%x\n",localnetid); } /* ==================== = = I_ShutdownNet = ==================== */ void I_ShutdownNet (void) { } /* ==================== = = I_InitNetwork = ==================== */ void I_InitNetwork (void) { int i,j; int socketnum; // // get IPX function address // memset(&dpmiregs,0,sizeof(dpmiregs)); dpmiregs.eax = 0x7a00; DPMIInt (0x2f); if ( (dpmiregs.eax&0xff) != 0xff) I_Error ("IPX not detected\n"); enteripx[0] = (dpmiregs.edi)&0xffff; enteripx[1] = dpmiregs.es; // printf ("ipxcall: 0x%x:0x%x\n",enteripx[1],enteripx[0]); // // allocate dos memory for packets // packets = (packet_t *)I_AllocLow (NUMPACKETS*sizeof(packet_t)); // // allocate a socket for sending and receiving // i = M_CheckParm ("-port"); if (i>0 && i>8) + ((socketid&255)<<8) ); // printf ("socketnum: 0x%x\n",socketnum); GetLocalAddress (); // // set up a receiving ECB // memset (packets,0,NUMPACKETS*sizeof(packet_t)); for (i=1 ; i>8; // // sync // //SendPacket (); // NetSync (); //getchar(); } /* ============== = = SendPacket = ============== */ void SendPacket (void) { int j, checksum; //printf ("send\n"); while (packets[0].ecb.InUseFlag) { //printf ("Send: inuse: 0x%x\n",packets[0].ecb.InUseFlag); } //printf ("not in use\n"); // put the data into an ipx packet memcpy (&packets[0].data, &netbuffer, sizeof(netbuffer)); checksum = 0; for (j=0 ; j #include "doomdef.h" #include "dmx.h" #include "sounds.h" #include "i_sound.h" /* =============== = = I_StartupTimer = =============== */ static int tsm_ID; void I_StartupTimer (void) { #ifndef NOTIMER extern int I_TimerISR(void); printf("I_StartupTimer()\n"); // installs master timer. Must be done before StartupTimer()! TSM_Install(SND_TICRATE); tsm_ID = TSM_NewService (I_TimerISR, 35, 0, 0); // max priority if (tsm_ID == -1) { I_Error("Can't register 35 Hz timer w/ DMX library"); } #endif } void I_ShutdownTimer (void) { TSM_DelService(tsm_ID); TSM_Remove(); } /* * * SOUND HEADER & DATA * * */ // sound information #if 0 const char *dnames[] = {"None", "PC_Speaker", "Adlib", "Sound_Blaster", "ProAudio_Spectrum16", "Gravis_Ultrasound", "MPU", "AWE32" }; #endif const char snd_prefixen[] = { 'P', 'P', 'A', 'S', 'S', 'S', 'M', 'M', 'M', 'S', 'S', 'S' }; int snd_DesiredMusicDevice, snd_DesiredSfxDevice; int snd_MusicDevice, // current music card # (index to dmxCodes) snd_SfxDevice, // current sfx card # (index to dmxCodes) snd_MaxVolume, // maximum volume for sound snd_MusicVolume; // maximum volume for music int dmxCodes[NUM_SCARDS]; // the dmx code for a given card int snd_SBport, snd_SBirq, snd_SBdma; // sound blaster variables int snd_Mport; // midi variables extern boolean snd_MusicAvail, // whether music is available snd_SfxAvail; // whether sfx are available void I_PauseSong(int handle) { MUS_PauseSong(handle); } void I_ResumeSong(int handle) { MUS_ResumeSong(handle); } void I_SetMusicVolume(int volume) { MUS_SetMasterVolume(volume); snd_MusicVolume = volume; } void I_SetSfxVolume(int volume) { snd_MaxVolume = volume; // THROW AWAY? } /* * * SONG API * */ int I_RegisterSong(void *data) { int rc = MUS_RegisterSong(data); #ifdef SNDDEBUG if (rc<0) printf("MUS_Reg() returned %d\n", rc); #endif return rc; } void I_UnRegisterSong(int handle) { int rc = MUS_UnregisterSong(handle); #ifdef SNDDEBUG if (rc < 0) printf("MUS_Unreg() returned %d\n", rc); #endif } int I_QrySongPlaying(int handle) { int rc = MUS_QrySongPlaying(handle); #ifdef SNDDEBUG if (rc < 0) printf("MUS_QrySP() returned %d\n", rc); #endif return rc; } // Stops a song. MUST be called before I_UnregisterSong(). void I_StopSong(int handle) { int rc; rc = MUS_StopSong(handle); #ifdef SNDDEBUG if (rc < 0) printf("MUS_StopSong() returned %d\n", rc); #endif // Fucking kluge pause { int s; extern volatile int ticcount; for (s=ticcount ; ticcount - s < 10 ; ); } } void I_PlaySong(int handle, boolean looping) { int rc; rc = MUS_ChainSong(handle, looping ? handle : -1); #ifdef SNDDEBUG if (rc < 0) printf("MUS_ChainSong() returned %d\n", rc); #endif rc = MUS_PlaySong(handle, snd_MusicVolume); #ifdef SNDDEBUG if (rc < 0) printf("MUS_PlaySong() returned %d\n", rc); #endif } /* * * SOUND FX API * */ // Gets lump nums of the named sound. Returns pointer which will be // passed to I_StartSound() when you want to start an SFX. Must be // sure to pass this to UngetSoundEffect() so that they can be // freed! int I_GetSfxLumpNum(sfxinfo_t *sound) { char namebuf[9]; if (sound->link) sound = sound->link; sprintf(namebuf, "d%c%s", snd_prefixen[snd_SfxDevice], sound->name); return W_GetNumForName(namebuf); } int I_StartSound (int id, void *data, int vol, int sep, int pitch, int priority) { // hacks out certain PC sounds if (snd_SfxDevice == PC && (data == S_sfx[sfx_posact].data || data == S_sfx[sfx_bgact].data || data == S_sfx[sfx_dmact].data || data == S_sfx[sfx_dmpain].data || data == S_sfx[sfx_popain].data || data == S_sfx[sfx_sawidl].data)) return -1; else return SFX_PlayPatch(data, sep, pitch, vol, 0, 100); } void I_StopSound(int handle) { // extern volatile long gDmaCount; // long waittocount; SFX_StopPatch(handle); // waittocount = gDmaCount + 2; // while (gDmaCount < waittocount) ; } int I_SoundIsPlaying(int handle) { return SFX_Playing(handle); } void I_UpdateSoundParams(int handle, int vol, int sep, int pitch) { SFX_SetOrigin(handle, pitch, sep, vol); } /* * * SOUND STARTUP STUFF * * */ // // Why PC's Suck, Reason #8712 // void I_sndArbitrateCards(void) { boolean codec, ens, gus, adlib, pc, sb, midi; int i, rc, mputype, p, opltype, wait, dmxlump; snd_MaxVolume = 127; snd_MusicDevice = snd_DesiredMusicDevice; snd_SfxDevice = snd_DesiredSfxDevice; // check command-line parameters- overrides config file // if (M_CheckParm("-nosound")) snd_MusicDevice = snd_SfxDevice = snd_none; if (M_CheckParm("-nosfx")) snd_SfxDevice = snd_none; if (M_CheckParm("-nomusic")) snd_MusicDevice = snd_none; if (snd_MusicDevice > snd_MPU && snd_MusicDevice <= snd_MPU3) snd_MusicDevice = snd_MPU; if (snd_MusicDevice == snd_SB) snd_MusicDevice = snd_Adlib; if (snd_MusicDevice == snd_PAS) snd_MusicDevice = snd_Adlib; // figure out what i've got to initialize // gus = snd_MusicDevice == snd_GUS || snd_SfxDevice == snd_GUS; sb = snd_SfxDevice == snd_SB || snd_MusicDevice == snd_SB; ens = snd_SfxDevice == snd_ENS; codec = snd_SfxDevice == snd_CODEC; adlib = snd_MusicDevice == snd_Adlib ; pc = snd_SfxDevice == snd_PC; midi = snd_MusicDevice == snd_MPU; // initialize whatever i've got // if ( ens ) { if (devparm) printf("ENSONIQ\n"); if (ENS_Detect()) printf("Dude. The ENSONIQ ain't responding.\n" ); } if (codec) { if (devparm) printf("CODEC p=0x%x, d=%d\n", snd_SBport, snd_SBdma ); if (CODEC_Detect(&snd_SBport,&snd_SBdma)) printf("CODEC. The CODEC ain't responding.\n"); } if (gus) { if (devparm) printf("GUS\n"); fprintf(stderr, "GUS1\n"); if (GF1_Detect()) printf("Dude. The GUS ain't responding.\n"); else { fprintf(stderr, "GUS2\n"); if (commercial) dmxlump = W_GetNumForName("dmxgusc"); else dmxlump = W_GetNumForName("dmxgus"); GF1_SetMap(W_CacheLumpNum(dmxlump, PU_CACHE), lumpinfo[dmxlump].size); } } if (sb) { if (devparm) printf("cfg p=0x%x, i=%d, d=%d\n", snd_SBport, snd_SBirq, snd_SBdma); if (SB_Detect(&snd_SBport, &snd_SBirq, &snd_SBdma, 0)) printf("SB isn't responding at p=0x%x, i=%d, d=%d\n", snd_SBport, snd_SBirq, snd_SBdma); else SB_SetCard(snd_SBport, snd_SBirq, snd_SBdma); if (devparm) printf("SB_Detect returned p=0x%x,i=%d,d=%d\n", snd_SBport, snd_SBirq, snd_SBdma); } if (adlib) { if (devparm) printf("Adlib\n"); if (AL_Detect(&wait,0)) printf("Dude. The Adlib isn't responding.\n"); else AL_SetCard(wait, W_CacheLumpName("genmidi", PU_STATIC)); } if (midi) { if (devparm) printf("Midi\n"); if (devparm) printf("cfg p=0x%x\n", snd_Mport); if (MPU_Detect(&snd_Mport, &i)) printf("The MPU-401 isn't reponding @ p=0x%x.\n", snd_Mport); else MPU_SetCard(snd_Mport); } } // inits all sound stuff void I_StartupSound (void) { int rc, i; if (devparm) printf("I_StartupSound: Hope you hear a pop.\n"); // initialize dmxCodes[] dmxCodes[0] = 0; dmxCodes[snd_PC] = AHW_PC_SPEAKER; dmxCodes[snd_Adlib] = AHW_ADLIB; dmxCodes[snd_SB] = AHW_SOUND_BLASTER; dmxCodes[snd_PAS] = AHW_MEDIA_VISION; dmxCodes[snd_GUS] = AHW_ULTRA_SOUND; dmxCodes[snd_MPU] = AHW_MPU_401; dmxCodes[snd_AWE] = AHW_AWE32; dmxCodes[snd_ENS] = AHW_ENSONIQ; dmxCodes[snd_CODEC] =AHW_CODEC; // inits sound library timer stuff I_StartupTimer(); // pick the sound cards i'm going to use // I_sndArbitrateCards(); if (devparm) { printf(" Music device #%d & dmxCode=%d\n", snd_MusicDevice, dmxCodes[snd_MusicDevice]); printf(" Sfx device #%d & dmxCode=%d\n", snd_SfxDevice, dmxCodes[snd_SfxDevice]); } // inits DMX sound library printf(" calling DMX_Init\n"); rc = DMX_Init(SND_TICRATE, SND_MAXSONGS, dmxCodes[snd_MusicDevice], dmxCodes[snd_SfxDevice]); if (devparm) printf(" DMX_Init() returned %d\n", rc); } // shuts down all sound stuff void I_ShutdownSound (void) { extern volatile int ticcount; int w; S_PauseSound(); // hack to kill last note w = ticcount + 30; while (ticcount != w) ; DMX_DeInit(); } void I_SetChannels(int channels) { WAV_PlayMode(channels, SND_SAMPLERATE); } \ No newline at end of file diff --git a/I_SOUND.H b/I_SOUND.H new file mode 100644 index 0000000..93ec325 --- /dev/null +++ b/I_SOUND.H @@ -0,0 +1 @@ +#ifndef __SOUND__ #define __SOUND__ #define SND_TICRATE 140 // tic rate for updating sound #define SND_MAXSONGS 40 // max number of songs in game #define SND_SAMPLERATE 11025 // sample rate of sound effects typedef enum { snd_none, snd_PC, snd_Adlib, snd_SB, snd_PAS, snd_GUS, snd_MPU, snd_MPU2, snd_MPU3, snd_AWE, snd_ENS, snd_CODEC, NUM_SCARDS } cardenum_t; #endif \ No newline at end of file diff --git a/I_UNIX.C b/I_UNIX.C new file mode 100644 index 0000000..8ba4bdf --- /dev/null +++ b/I_UNIX.C @@ -0,0 +1 @@ +// I_unix.c, Doom for UNIX #include #include #include #include #include #include #ifndef LINUX #include #endif #include #include #include #include "doomdef.h" int isCyberPresent; void NetSend (void); boolean NetListen (void); typedef union { short a; unsigned char b[sizeof(short)]; } s_endian; typedef union { long a; unsigned char b[sizeof(long)]; } l_endian; static s_endian endianness = { 1 }; FILE *sndserver=0; char *sndserver_filename; int mb_used = 6; void I_ReadCyberCmd(ticcmd_t *cmd) { } void I_Tactile(int on, int off, int total) { } ticcmd_t emptycmd; ticcmd_t *I_BaseTiccmd(void) { return &emptycmd; } short ShortSwap (short dat) { // if (endianness.b[0]) // return dat; // do not flip little-endian // else return ((dat&0xff)<<8) | ((dat>>8)&0xff); } long LongSwap (long dat) { // if (endianness.b[0]) // return dat; // do not flip little-endian // else // otherwise flip it // return ((l_endian) dat).b[0] // + (((l_endian) dat).b[1] << 8) // + (((l_endian) dat).b[2] << 16) // + (((l_endian) dat).b[3] << 24); return (((unsigned)dat)>>24) | ((dat>>8)&0xff00) | ((dat<<8)&0xff0000) | (dat<<24); } #if !defined(USEASM) && (!defined(__WATCOMC__) || !defined(__i386) || defined(NORMALUNIX)) fixed_t FixedMul (fixed_t a, fixed_t b) { return ((long long) a * (long long) b) >> FRACBITS; } fixed_t FixedDiv2 (fixed_t a, fixed_t b) { #if 0 long long c; c = ((long long)a<<16) / ((long long)b); return (fixed_t) c; #endif double c; c = ((double)a) / ((double)b) * FRACUNIT; if (c >= 2147483648.0 || c < -2147483648.0) I_Error("FixedDiv: divide by zero"); return (fixed_t) c; } #endif int I_GetHeapSize (void) { return mb_used*1024*1024; } byte *I_ZoneBase (int *size) { *size = mb_used*1024*1024; return (byte *) malloc (*size); } /* ================= = = I_GetTime = = returns time in 1/70th second tics ================= */ int I_GetTime (void) { struct timeval tp; struct timezone tzp; int newtics; static int basetime=0; gettimeofday(&tp, &tzp); if (!basetime) basetime = tp.tv_sec; newtics = (tp.tv_sec-basetime)*TICRATE + tp.tv_usec*TICRATE/1000000; return newtics; } /* * MUSIC & SFX API */ void I_SetMusicVolume(int volume) { } void I_SetSfxVolume(int volume) { } // GENERAL SFX API void I_SetChannels(int channels) { } int I_GetSfxLumpNum(sfxinfo_t *sfx) { char namebuf[9]; sprintf(namebuf, "ds%s", sfx->name); return W_GetNumForName(namebuf); } int I_StartSound (int id, void *data, int vol, int sep, int pitch, int priority) { if (sndserver) { fprintf(sndserver, "p%2.2x%2.2x%2.2x%2.2x\n", id, pitch, vol, sep); fflush(sndserver); } } void I_StopSound (int handle) { } int I_SoundIsPlaying(int handle) { return gametic < handle; } void I_UpdateSoundParams(int handle, int vol, int sep, int pitch) { } // MUSIC API static int looping=0, musicdies=-1; void I_StopSong(int handle) { looping = 0; musicdies = 0; } void I_PauseSong (int handle) { } void I_ResumeSong (int handle) { } void I_PlaySong(int handle, int looping) { musicdies = gametic + TICRATE*30; } void I_UnRegisterSong(int handle) {} int I_RegisterSong(void *data) { return 1; } int I_QrySongPlaying(int handle) { return looping || musicdies > gametic; } void I_ShutdownSound(void) { if (sndserver) { fprintf(sndserver, "q\n"); fflush(sndserver); } } /* ==================== = = I_Init = ==================== */ void I_Init (void) { char buffer[256]; if (getenv("DOOMWADDIR")) sprintf(buffer, "%s/%s", getenv("DOOMWADDIR"), sndserver_filename); else sprintf(buffer, "%s", sndserver_filename); // start sound process if ( ! access(buffer, X_OK) ) { strcat(buffer, " -quiet"); sndserver = popen(buffer, "w"); } else fprintf(stderr, "Could not start sound server [%s]\n", buffer); // I_InitGraphics(); } /* ================ = = I_Quit = ================ */ void I_ShutdownGraphics(void); void I_Quit (void) { D_QuitNetGame (); I_ShutdownSound(); M_SaveDefaults (); I_ShutdownGraphics(); exit(0); } void I_WaitVBL(int count) { #ifdef SGI sginap(1); #else #ifdef SUN sleep(0); #else usleep (count * (1000000/70) ); #endif #endif } void I_BeginRead(void) { } void I_EndRead(void) { } byte *I_AllocLow(int length) { byte *mem; mem = (byte *)malloc (length); memset (mem,0,length); return mem; } /* ============================================================================== NETWORKING ============================================================================== */ #include #include int DOOMPORT = (IPPORT_USERRESERVED +0x1d ); int sendsocket, insocket; struct sockaddr_in sendaddress[MAXNETNODES]; void (*netget) (void); void (*netsend) (void); /* =============== = = UDPsocket = =============== */ int UDPsocket (void) { int s; // allocate a socket s = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP); if (s<0) I_Error ("can't create socket: %s",strerror(errno)); return s; } /* =============== = = BindToLocalPort = =============== */ void BindToLocalPort (int s, int port) { int v; struct sockaddr_in address; memset (&address, 0, sizeof(address)); address.sin_family = AF_INET; address.sin_addr.s_addr = INADDR_ANY; address.sin_port = port; v = bind (s, (void *)&address, sizeof(address)); if (v == -1) I_Error ("BindToPort: bind: %s", strerror(errno)); } /* ============== = = PacketSend = ============== */ void PacketSend (void) { int c; doomdata_t sw; // byte swap sw.checksum = htonl(netbuffer->checksum); sw.player = netbuffer->player; sw.retransmitfrom = netbuffer->retransmitfrom; sw.starttic = netbuffer->starttic; sw.numtics = netbuffer->numtics; for (c=0 ; c< netbuffer->numtics ; c++) { sw.cmds[c].forwardmove = netbuffer->cmds[c].forwardmove; sw.cmds[c].sidemove = netbuffer->cmds[c].sidemove; sw.cmds[c].angleturn = htons(netbuffer->cmds[c].angleturn); sw.cmds[c].consistancy = htons(netbuffer->cmds[c].consistancy); sw.cmds[c].chatchar = netbuffer->cmds[c].chatchar; sw.cmds[c].buttons = netbuffer->cmds[c].buttons; } //printf ("sending %i\n",gametic); c = sendto (sendsocket , &sw, doomcom->datalength ,0,(void *)&sendaddress[doomcom->remotenode] ,sizeof(sendaddress[doomcom->remotenode])); // if (c == -1) // I_Error ("SendPacket error: %s",strerror(errno)); } /* ============== = = PacketGet = ============== */ void PacketGet (void) { int i,c; struct sockaddr_in fromaddress; int fromlen; doomdata_t sw; fromlen = sizeof(fromaddress); c = recvfrom (insocket, &sw, sizeof(sw), 0 , (struct sockaddr *)&fromaddress, &fromlen ); if (c == -1 ) { if (errno != EWOULDBLOCK) I_Error ("GetPacket: %s",strerror(errno)); doomcom->remotenode = -1; // no packet return; } { static int first=1; if (first) printf("len=%d:p=[0x%x 0x%x] \n", c, *(int*)&sw, *((int*)&sw+1)); first = 0; } // find remote node number for (i=0 ; inumnodes ; i++) if ( fromaddress.sin_addr.s_addr == sendaddress[i].sin_addr.s_addr ) break; if (i == doomcom->numnodes) { // packet isn't from one of the players (new game broadcast) doomcom->remotenode = -1; // no packet return; } doomcom->remotenode = i; // good packet from a game player doomcom->datalength = c; // byte swap netbuffer->checksum = ntohl(sw.checksum); netbuffer->player = sw.player; netbuffer->retransmitfrom = sw.retransmitfrom; netbuffer->starttic = sw.starttic; netbuffer->numtics = sw.numtics; for (c=0 ; c< netbuffer->numtics ; c++) { netbuffer->cmds[c].forwardmove = sw.cmds[c].forwardmove; netbuffer->cmds[c].sidemove = sw.cmds[c].sidemove; netbuffer->cmds[c].angleturn = ntohs(sw.cmds[c].angleturn); netbuffer->cmds[c].consistancy = ntohs(sw.cmds[c].consistancy); netbuffer->cmds[c].chatchar = sw.cmds[c].chatchar; netbuffer->cmds[c].buttons = sw.cmds[c].buttons; } } int GetLocalAddress (void) { char hostname[1024]; struct hostent *hostentry; // host information entry int v; // get local address v = gethostname (hostname, sizeof(hostname)); if (v == -1) I_Error ("GetLocalAddress : gethostname: errno %d",errno); hostentry = gethostbyname (hostname); if (!hostentry) I_Error ("GetLocalAddress : gethostbyname: couldn't get local host"); return *(int *)hostentry->h_addr_list[0]; } /* ==================== = = I_InitNetwork = ==================== */ void I_InitNetwork (void) { boolean trueval = true; int i,p; struct hostent *hostentry; // host information entry doomcom = malloc (sizeof (*doomcom) ); memset (doomcom, 0, sizeof(*doomcom) ); // // set up for network // i = M_CheckParm ("-dup"); if (i && i< myargc-1) { doomcom->ticdup = myargv[i+1][0]-'0'; if (doomcom->ticdup < 1) doomcom->ticdup = 1; if (doomcom->ticdup > 9) doomcom->ticdup = 9; } else doomcom-> ticdup = 1; if (M_CheckParm ("-extratic")) doomcom-> extratics = 1; else doomcom-> extratics = 0; p = M_CheckParm ("-port"); if (p && p ... // i = M_CheckParm ("-net"); if (!i) { // // single player game // netgame = false; doomcom->id = DOOMCOM_ID; doomcom->numplayers = doomcom->numnodes = 1; doomcom->deathmatch = false; doomcom->consoleplayer = 0; return; } netsend = PacketSend; netget = PacketGet; netgame = true; // // parse player number and host list // doomcom->consoleplayer = myargv[i+1][0]-'1'; doomcom->numnodes = 1; // this node for sure i++; while (++i < myargc && myargv[i][0] != '-') { sendaddress[doomcom->numnodes].sin_family = AF_INET; sendaddress[doomcom->numnodes].sin_port = htons(DOOMPORT); if (myargv[i][0] == '.') { sendaddress[doomcom->numnodes].sin_addr.s_addr = inet_addr (myargv[i]+1); } else { hostentry = gethostbyname (myargv[i]); if (!hostentry) I_Error ("gethostbyname: couldn't find %s", myargv[i]); sendaddress[doomcom->numnodes].sin_addr.s_addr = *(int *)hostentry->h_addr_list[0]; } doomcom->numnodes++; } doomcom->id = DOOMCOM_ID; doomcom->numplayers = doomcom->numnodes; // // build message to receive // insocket = UDPsocket (); BindToLocalPort (insocket,htons(DOOMPORT)); ioctl (insocket, FIONBIO, &trueval); sendsocket = UDPsocket (); } void I_NetCmd (void) { if (doomcom->command == CMD_SEND) { netsend (); } else if (doomcom->command == CMD_GET) { netget (); } else I_Error ("Bad net cmd: %i\n",doomcom->command); } \ No newline at end of file diff --git a/I_X.C b/I_X.C new file mode 100644 index 0000000..dfcf249 --- /dev/null +++ b/I_X.C @@ -0,0 +1 @@ +// I_X.c, Doom for X #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "doomdef.h" #define POINTER_WARP_COUNTDOWN 1 Display *X_display=0; Window X_mainWindow; Colormap X_cmap; Visual *X_visual; GC X_gc; XEvent X_event; int X_screen; XVisualInfo X_visualinfo; XImage *image; int X_width, X_height; boolean doShm; XShmSegmentInfo X_shminfo; int X_shmeventtype; boolean grabMouse; int doPointerWarp = POINTER_WARP_COUNTDOWN; static int multiply=1; // // Translates the key currently in X_event // int xlatekey(void) { int rc; switch(rc = XKeycodeToKeysym(X_display, X_event.xkey.keycode, 0)) { case XK_Left: rc = KEY_LEFTARROW; break; case XK_Right: rc = KEY_RIGHTARROW; break; case XK_Down: rc = KEY_DOWNARROW; break; case XK_Up: rc = KEY_UPARROW; break; case XK_Escape: rc = KEY_ESCAPE; break; case XK_Return: rc = KEY_ENTER; break; case XK_Tab: rc = KEY_TAB; break; case XK_F1: rc = KEY_F1; break; case XK_F2: rc = KEY_F2; break; case XK_F3: rc = KEY_F3; break; case XK_F4: rc = KEY_F4; break; case XK_F5: rc = KEY_F5; break; case XK_F6: rc = KEY_F6; break; case XK_F7: rc = KEY_F7; break; case XK_F8: rc = KEY_F8; break; case XK_F9: rc = KEY_F9; break; case XK_F10: rc = KEY_F10; break; case XK_F11: rc = KEY_F11; break; case XK_F12: rc = KEY_F12; break; case XK_BackSpace: case XK_Delete: rc = KEY_BACKSPACE; break; case XK_Pause: rc = KEY_PAUSE; break; case XK_KP_Equal: case XK_equal: rc = KEY_EQUALS; break; case XK_KP_Subtract: case XK_minus: rc = KEY_MINUS; break; case XK_Shift_L: case XK_Shift_R: rc = KEY_RSHIFT; break; case XK_Control_L: case XK_Control_R: rc = KEY_RCTRL; break; case XK_Alt_L: case XK_Meta_L: case XK_Alt_R: case XK_Meta_R: rc = KEY_RALT; break; default: if (rc >= XK_space && rc <= XK_asciitilde) rc = rc - XK_space + ' '; if (rc >= 'A' && rc <= 'Z') rc = rc - 'A' + 'a'; break; } return rc; } void I_ShutdownGraphics(void) { // get rid of shared memory shmdt(X_shminfo.shmaddr); shmctl(X_shminfo.shmid, IPC_RMID, 0); } /* ================ = = I_Error = ================ */ extern boolean demorecording; void I_Error (char *error, ...) { va_list argptr; char string[1024]; if (demorecording) G_CheckDemoStatus(); D_QuitNetGame (); I_ShutdownGraphics(); va_start (argptr,error); fprintf (stderr, "Error: "); vfprintf (stderr,error,argptr); fprintf (stderr, "\n"); va_end (argptr); exit(-1); } /* ==================== = = I_StartFrame = ==================== */ void I_StartFrame (void) { // er? } static int lastmousex = 0; static int lastmousey = 0; boolean mousemoved = false; boolean shmFinished; void I_GetEvent(void) { event_t event; // put event-grabbing stuff in here XNextEvent(X_display, &X_event); switch (X_event.type) { case KeyPress: event.type = ev_keydown; event.data1 = xlatekey(); D_PostEvent(&event); // fprintf(stderr, "k"); break; case KeyRelease: event.type = ev_keyup; event.data1 = xlatekey(); D_PostEvent(&event); // fprintf(stderr, "ku"); break; case ButtonPress: event.type = ev_mouse; event.data1 = (X_event.xbutton.state & Button1Mask) | (X_event.xbutton.state & Button2Mask ? 2 : 0) | (X_event.xbutton.state & Button3Mask ? 4 : 0) | (X_event.xbutton.button == Button1) | (X_event.xbutton.button == Button2 ? 2 : 0) | (X_event.xbutton.button == Button3 ? 4 : 0); event.data2 = event.data3 = 0; D_PostEvent(&event); // fprintf(stderr, "b"); break; case ButtonRelease: event.type = ev_mouse; event.data1 = (X_event.xbutton.state & Button1Mask) | (X_event.xbutton.state & Button2Mask ? 2 : 0) | (X_event.xbutton.state & Button3Mask ? 4 : 0) ^ (X_event.xbutton.button == Button1 ? 1 : 0) ^ (X_event.xbutton.button == Button2 ? 2 : 0) ^ (X_event.xbutton.button == Button3 ? 4 : 0); event.data2 = event.data3 = 0; D_PostEvent(&event); // fprintf(stderr, "bu"); break; case MotionNotify: event.type = ev_mouse; event.data1 = (X_event.xmotion.state & Button1Mask) | (X_event.xmotion.state & Button2Mask ? 2 : 0) | (X_event.xmotion.state & Button3Mask ? 4 : 0); event.data2 = (X_event.xmotion.x - lastmousex) << 2; event.data3 = (lastmousey - X_event.xmotion.y) << 2; if (event.data2 || event.data3) { lastmousex = X_event.xmotion.x; lastmousey = X_event.xmotion.y; if (X_event.xmotion.x != X_width/2 && X_event.xmotion.y != X_height/2) { D_PostEvent(&event); // fprintf(stderr, "m"); mousemoved = false; } else { mousemoved = true; } } break; case Expose: case ConfigureNotify: break; default: if (doShm && X_event.type == X_shmeventtype) shmFinished = true; break; } } Cursor createnullcursor( Display *display, Window root) { Pixmap cursormask; XGCValues xgc; GC gc; XColor dummycolour; Cursor cursor; cursormask = XCreatePixmap(display, root, 1, 1, 1/*depth*/); xgc.function = GXclear; gc = XCreateGC(display, cursormask, GCFunction, &xgc); XFillRectangle(display, cursormask, gc, 0, 0, 1, 1); dummycolour.pixel = 0; dummycolour.red = 0; dummycolour.flags = 04; cursor = XCreatePixmapCursor(display, cursormask, cursormask, &dummycolour,&dummycolour, 0,0); XFreePixmap(display,cursormask); XFreeGC(display,gc); return cursor; } /* ==================== = = I_StartTic = ==================== */ void I_StartTic (void) { if (!X_display) return; while (XPending(X_display)) I_GetEvent(); // warp the pointer back to the middle of the window or it'll wander off if (grabMouse) { if (!--doPointerWarp) { XWarpPointer( X_display, None, X_mainWindow, 0, 0, 0, 0, X_width/2, X_height/2); doPointerWarp = POINTER_WARP_COUNTDOWN; } } mousemoved = false; } /* ==================== = = I_UpdateNoBlit = ==================== */ void I_UpdateNoBlit (void) { // what is this? } /* ==================== = = I_FinishUpdate = ==================== */ void I_FinishUpdate (void) { static int lasttic; int tics, i; static unsigned char *bigscreen=0; // draws little dots on the bottom of the screen if (devparm) { i = I_GetTime(); tics = i - lasttic; lasttic = i; if (tics > 20) tics = 20; for (i=0 ; idata[i*X_width]; y = SCREENHEIGHT; while (y--) { x = SCREENWIDTH; do { fouripixels = *ilineptr++; twoopixels = (fouripixels & 0xff000000) | ((fouripixels>>8) & 0xffff00) | ((fouripixels>>16) & 0xff); twomoreopixels = ((fouripixels<<16) & 0xff000000) | ((fouripixels<<8) & 0xffff00) | (fouripixels & 0xff); #ifdef __BIG_ENDIAN__ *olineptrs[0]++ = twoopixels; *olineptrs[1]++ = twoopixels; *olineptrs[0]++ = twomoreopixels; *olineptrs[1]++ = twomoreopixels; #else *olineptrs[0]++ = twomoreopixels; *olineptrs[1]++ = twomoreopixels; *olineptrs[0]++ = twoopixels; *olineptrs[1]++ = twoopixels; #endif } while (x-=4); olineptrs[0] += X_width/4; olineptrs[1] += X_width/4; } } else if (multiply == 3) { unsigned int *olineptrs[3]; unsigned int *ilineptr; int x, y, i; unsigned int fouropixels[3]; unsigned int fouripixels; ilineptr = (unsigned int *) (screens[0]); for (i=0 ; i<3 ; i++) olineptrs[i] = (unsigned int *) &image->data[i*X_width]; y = SCREENHEIGHT; while (y--) { x = SCREENWIDTH; do { fouripixels = *ilineptr++; fouropixels[0] = (fouripixels & 0xff000000) | ((fouripixels>>8) & 0xff0000) | ((fouripixels>>16) & 0xffff); fouropixels[1] = ((fouripixels<<8) & 0xff000000) | (fouripixels & 0xffff00) | ((fouripixels>>8) & 0xff); fouropixels[2] = ((fouripixels<<16) & 0xffff0000) | ((fouripixels<<8) & 0xff00) | (fouripixels & 0xff); #ifdef __BIG_ENDIAN__ *olineptrs[0]++ = fouropixels[0]; *olineptrs[1]++ = fouropixels[0]; *olineptrs[2]++ = fouropixels[0]; *olineptrs[0]++ = fouropixels[1]; *olineptrs[1]++ = fouropixels[1]; *olineptrs[2]++ = fouropixels[1]; *olineptrs[0]++ = fouropixels[2]; *olineptrs[1]++ = fouropixels[2]; *olineptrs[2]++ = fouropixels[2]; #else *olineptrs[0]++ = fouropixels[2]; *olineptrs[1]++ = fouropixels[2]; *olineptrs[2]++ = fouropixels[2]; *olineptrs[0]++ = fouropixels[1]; *olineptrs[1]++ = fouropixels[1]; *olineptrs[2]++ = fouropixels[1]; *olineptrs[0]++ = fouropixels[0]; *olineptrs[1]++ = fouropixels[0]; *olineptrs[2]++ = fouropixels[0]; #endif } while (x-=4); olineptrs[0] += 2*X_width/4; olineptrs[1] += 2*X_width/4; olineptrs[2] += 2*X_width/4; } } else if (multiply == 4) { void Expand4(unsigned *, double *); Expand4 ((unsigned *)(screens[0]), (double *) (image->data)); } if (doShm) { if (!XShmPutImage( X_display, X_mainWindow, X_gc, image, 0, 0, 0, 0, X_width, X_height, True )) I_Error("XShmPutImage() failed\n"); // wait for it to finish and processes all input events shmFinished = false; do { I_GetEvent(); } while (!shmFinished); } else { // draw the image XPutImage( X_display, X_mainWindow, X_gc, image, 0, 0, 0, 0, X_width, X_height ); // sync up with server XSync(X_display, False); } } /* ==================== = = I_ReadScreen = ==================== */ void I_ReadScreen (byte *scr) { memcpy (scr, screens[0], SCREENWIDTH*SCREENHEIGHT); } static XColor colors[256]; void UploadNewPalette(Colormap cmap, byte *palette) { register int i, c; static boolean firstcall = true; #ifdef __cplusplus if (X_visualinfo.c_class == PseudoColor && X_visualinfo.depth == 8) #else if (X_visualinfo.class == PseudoColor && X_visualinfo.depth == 8) #endif { // initialize the colormap if (firstcall) { firstcall = false; for (i=0 ; i<256 ; i++) { colors[i].pixel = i; colors[i].flags = DoRed|DoGreen|DoBlue; } } // set the X colormap entries for (i=0 ; i<256 ; i++) { c = gammatable[usegamma][*palette++]; colors[i].red = (c<<8) + c; c = gammatable[usegamma][*palette++]; colors[i].green = (c<<8) + c; c = gammatable[usegamma][*palette++]; colors[i].blue = (c<<8) + c; } // store the colors to the current colormap XStoreColors(X_display, cmap, colors, 256); } } /* ==================== = = I_SetPalette = ==================== */ void I_SetPalette (byte *palette) { UploadNewPalette(X_cmap, palette); } void grabsharedmemory(int size) { int key = ('d'<<24) | ('o'<<16) | ('o'<<8) | 'm'; struct shmid_ds shminfo; int minsize = 320*200; int id, rc, done=0, pollution=5; // try to use what was here before do { id = shmget((key_t) key, minsize, 0777); // just get the id if (id != -1) { rc=shmctl(id, IPC_STAT, &shminfo); // get stats on it if (!rc) { if (shminfo.shm_nattch) { fprintf(stderr, "User %d appears to be running " "DOOM. Is that wise?\n", shminfo.shm_cpid); key++; } else { if (getuid() == shminfo.shm_perm.cuid) { rc = shmctl(id, IPC_RMID, 0); if (!rc) fprintf(stderr, "Was able to kill my old shared memory\n"); else I_Error( "Was NOT able to kill my old shared memory"); id = shmget((key_t)key, size, IPC_CREAT|0777); if (id==-1) I_Error("Could not get shared memory"); rc=shmctl(id, IPC_STAT, &shminfo); break; } if (size >= shminfo.shm_segsz) { fprintf(stderr, "will use %d's stale shared " "memory\n", shminfo.shm_cpid); break; } else { fprintf(stderr, "warning: can't use stale " "shared memory belonging to id %d, " "key=0x%x\n", shminfo.shm_cpid, key); key++; } } } else { I_Error("could not get stats on key=%d", key); } } else { id = shmget((key_t)key, size, IPC_CREAT|0777); if (id==-1) { extern int errno; fprintf(stderr, "errno=%d\n", errno); I_Error("Could not get any shared memory"); } break; } } while (--pollution); if (!pollution) { I_Error("Sorry, system too polluted with stale " "shared memory segments.\n"); } X_shminfo.shmid = id; // attach to the shared memory segment image->data = X_shminfo.shmaddr = shmat(id, 0, 0); fprintf(stderr, "shared memory id=%d, addr=0x%x\n", id, (int) (image->data)); } void I_InitGraphics(void) { char *displayname, *d; int n, pnum, x=0, y=0; int xsign=1, ysign=1; int oktodraw; unsigned long attribmask; XSetWindowAttributes attribs; XGCValues xgcvalues; int valuemask; static int firsttime=1; if (!firsttime) return; firsttime = 0; signal(SIGINT, (void (*)(int)) I_Quit); if (M_CheckParm("-2")) multiply = 2; if (M_CheckParm("-3")) multiply = 3; if (M_CheckParm("-4")) multiply = 4; X_width = SCREENWIDTH * multiply; X_height = SCREENHEIGHT * multiply; // check for command-line display name if (pnum=M_CheckParm("-disp")) displayname = myargv[pnum+1]; else displayname = 0; // check if the user wants to grab the mouse (quite unnice) grabMouse = !!M_CheckParm("-grabmouse"); // check for command-line geometry if (pnum=M_CheckParm("-geom")) { n = sscanf(myargv[pnum+1], "%c%d%c%d", &xsign, &x, &ysign, &y); if (n==2) x = y = 0; else if (n==6) { if (xsign == '-') x = -x; if (ysign == '-') y = -y; } else I_Error("bad -geom parameter"); } // open the display X_display = XOpenDisplay(displayname); if (!X_display) { if (displayname) I_Error("Could not open display [%s]", displayname); else I_Error("Could not open display (DISPLAY=[%s])", getenv("DISPLAY")); } // use the default visual X_screen = DefaultScreen(X_display); if (!XMatchVisualInfo(X_display, X_screen, 8, PseudoColor, &X_visualinfo)) I_Error("xdoom currently only supports 256-color PseudoColor screens"); X_visual = X_visualinfo.visual; // check for the MITSHM extension doShm = XShmQueryExtension(X_display); // even if it's available, make sure it's a local connection if (doShm) { if (!displayname) displayname = (char *) getenv("DISPLAY"); if (displayname) { d = displayname; while (*d && (*d != ':')) d++; if (*d) *d = 0; if (!(!strcasecmp(displayname, "unix") || !*displayname)) doShm = false; } } fprintf(stderr, "Using MITSHM extension\n"); // create the colormap X_cmap = XCreateColormap(X_display, RootWindow(X_display, X_screen), X_visual, AllocAll); // setup attributes for main window attribmask = CWEventMask | CWColormap | CWBorderPixel; // attribs.event_mask = KeyPressMask | KeyReleaseMask | ExposureMask // | PointerMotionMask | ButtonPressMask | ButtonReleaseMask; attribs.event_mask = KeyPressMask | KeyReleaseMask | ExposureMask; attribs.colormap = X_cmap; attribs.border_pixel = 0; // create the main window X_mainWindow = XCreateWindow( X_display, RootWindow(X_display, X_screen), x, y, X_width, X_height, 0, // borderwidth 8, // depth InputOutput, X_visual, attribmask, &attribs ); XDefineCursor(X_display, X_mainWindow, createnullcursor( X_display, X_mainWindow ) ); // create the GC valuemask = GCGraphicsExposures; xgcvalues.graphics_exposures = False; X_gc = XCreateGC( X_display, X_mainWindow, valuemask, &xgcvalues ); // map the window XMapWindow(X_display, X_mainWindow); // wait until it's OK to draw oktodraw = 0; while (!oktodraw) { XNextEvent(X_display, &X_event); if (X_event.type == Expose && !X_event.xexpose.count) oktodraw = 1; } // grabs the pointer so it's restricted to this window if (grabMouse) XGrabPointer(X_display, X_mainWindow, True, ButtonPressMask |ButtonReleaseMask|PointerMotionMask, GrabModeAsync, GrabModeAsync, X_mainWindow, None, CurrentTime); if (doShm) { X_shmeventtype = XShmGetEventBase(X_display) + ShmCompletion; // create the image image = XShmCreateImage( X_display, X_visual, 8, ZPixmap, 0, &X_shminfo, X_width, X_height ); grabsharedmemory(image->bytes_per_line * image->height); /* // create the shared memory segment X_shminfo.shmid = shmget (IPC_PRIVATE, image->bytes_per_line * image->height, IPC_CREAT | 0777); if (X_shminfo.shmid < 0) { perror(""); I_Error("shmget() failed in InitGraphics()"); } fprintf(stderr, "shared memory id=%d\n", X_shminfo.shmid); // attach to the shared memory segment image->data = X_shminfo.shmaddr = shmat(X_shminfo.shmid, 0, 0); */ if (!image->data) { perror(""); I_Error("shmat() failed in InitGraphics()"); } // get the X server to attach to it if (!XShmAttach(X_display, &X_shminfo)) I_Error("XShmAttach() failed in InitGraphics()"); } else { image = XCreateImage( X_display, X_visual, 8, ZPixmap, 0, malloc(X_width * X_height), X_width, X_height, 8, X_width ); } if (multiply == 1) screens[0] = (unsigned char *) (image->data); else screens[0] = (unsigned char *) malloc (SCREENWIDTH * SCREENHEIGHT); } unsigned exptable[256]; void InitExpand (void) { int i; for (i=0 ; i<256 ; i++) exptable[i] = i | (i<<8) | (i<<16) | (i<<24); } double exptable2[256*256]; void InitExpand2 (void) { int i,j; unsigned iexp, jexp; double *exp; union { double d; unsigned u[2]; } pixel; printf ("building exptable2...\n"); exp = exptable2; for (i=0 ; i<256 ; i++) { pixel.u[0] = i | (i<<8) | (i<<16) | (i<<24); for (j=0 ; j<256 ; j++) { pixel.u[1] = j | (j<<8) | (j<<16) | (j<<24); *exp++ = pixel.d; } } printf ("done.\n"); } int inited; void Expand4 (unsigned *lineptr, double *xline) { double dpixel; unsigned x, y; unsigned fourpixels; unsigned step; double *exp; exp = exptable2; if (!inited) { inited = 1; InitExpand2 (); } step = 3*SCREENWIDTH/2; y = SCREENHEIGHT-1; do { x = SCREENWIDTH; do { fourpixels = lineptr[0]; dpixel = *(double *)( (int)exp + ( (fourpixels&0xffff0000)>>13) ); xline[0] = dpixel; xline[160] = dpixel; xline[320] = dpixel; xline[480] = dpixel; dpixel = *(double *)( (int)exp + ( (fourpixels&0xffff)<<3 ) ); xline[1] = dpixel; xline[161] = dpixel; xline[321] = dpixel; xline[481] = dpixel; fourpixels = lineptr[1]; dpixel = *(double *)( (int)exp + ( (fourpixels&0xffff0000)>>13) ); xline[2] = dpixel; xline[162] = dpixel; xline[322] = dpixel; xline[482] = dpixel; dpixel = *(double *)( (int)exp + ( (fourpixels&0xffff)<<3 ) ); xline[3] = dpixel; xline[163] = dpixel; xline[323] = dpixel; xline[483] = dpixel; fourpixels = lineptr[2]; dpixel = *(double *)( (int)exp + ( (fourpixels&0xffff0000)>>13) ); xline[4] = dpixel; xline[164] = dpixel; xline[324] = dpixel; xline[484] = dpixel; dpixel = *(double *)( (int)exp + ( (fourpixels&0xffff)<<3 ) ); xline[5] = dpixel; xline[165] = dpixel; xline[325] = dpixel; xline[485] = dpixel; fourpixels = lineptr[3]; dpixel = *(double *)( (int)exp + ( (fourpixels&0xffff0000)>>13) ); xline[6] = dpixel; xline[166] = dpixel; xline[326] = dpixel; xline[486] = dpixel; dpixel = *(double *)( (int)exp + ( (fourpixels&0xffff)<<3 ) ); xline[7] = dpixel; xline[167] = dpixel; xline[327] = dpixel; xline[487] = dpixel; lineptr+=4; xline+=8; } while (x-=16); xline += step; } while (y--); } \ No newline at end of file diff --git a/M_MENU.C b/M_MENU.C new file mode 100644 index 0000000..5e25228 --- /dev/null +++ b/M_MENU.C @@ -0,0 +1 @@ +// M_menu.c #include "doomdef.h" #include "hu_stuff.h" extern patch_t *hu_font[HU_FONTSIZE]; extern boolean message_dontfuckwithme; #ifdef __NeXT__ #include #endif #include #include #include #include extern boolean chat_on; // in heads-up code // // defaulted values // int mouseSensitivity; // has default int showMessages; // has default 0 = off, 1 = on int sfxVolume; // has default 0 - 15 int musicVolume; // has default 0 - 15 int detailLevel; // has default, 0 = high, 1 = normal int screenblocks; // has default int screenSize; // temp for screenblocks (0-9) int quickSaveSlot; // -1 = no slot picked! int messageToPrint; // 1 = message to be printed char *messageString; // ...and here's the message string! int messx; // message x & y int messy; int messageLastMenuActive; boolean messageNeedsInput; // timed message = no input from user void (*messageRoutine)(int response); #define SAVESTRINGSIZE 24 char gammamsg[5][26] = { GAMMALVL0, GAMMALVL1, GAMMALVL2, GAMMALVL3, GAMMALVL4 }; int saveStringEnter; // we're going to be entering a savegame string int saveSlot; // which slot to save in int saveCharIndex; // which char we're editing char saveOldString[SAVESTRINGSIZE]; // old save description before edit boolean inhelpscreens; boolean menuactive; #define SKULLXOFF -32 #define LINEHEIGHT 16 extern boolean sendpause; char savegamestrings[10][SAVESTRINGSIZE]; // // QuitDOOM messages // char endmsg[8][80]= { QUITMSG, "please don't leave, there's more\ndemons to toast!", "let's beat it -- this is turning\ninto a bloodbath!", "i wouldn't leave if i were you.\ndos is much worse.", "you're trying to say you like dos\nbetter than me, right?", "don't leave yet -- there's a\ndemon around that corner!", "ya know, next time you come in here\ni'm gonna toast ya.", "go ahead and leave. see if i care." }; // // QuitDOOM II messages // #if 1 char endmsg2[8][80]= { QUITMSG, "you want to quit?\nthen, thou hast lost an eighth!", "don't go now, there's a \ndimensional shambler waiting\nat the dos prompt!", "get outta here and go back\nto your boring programs.", "if i were your boss, i'd \n deathmatch ya in a minute!", "look, bud. you leave now\nand you forfeit your body count!", "just leave. when you come\nback, i'll be waiting with a bat.", "you're lucky i don't smack\nyou for thinking about leaving." }; #else char endmsg2[8][80]= { QUITMSG, "fuck you, pussy!\nget the fuck out!", "you quit and i'll jizz\nin your cystholes!", "if you leave, i'll make\nthe lord drink my jizz.", "hey, ron! can we say\n'fuck' in the game?", "i'd leave: this is just\nmore monsters and levels.\nwhat a load.", "suck it down, asshole!\nyou're a fucking wimp!", "don't quit now! we're \nstill spending your money!" }; #endif char endstring[160]; // // MENU TYPEDEFS // typedef struct { short status; // 0 = no cursor here, 1 = ok,2 = arrows ok char name[10]; void (*routine)(int choice); // choice = menu item #. if status = 2, // ...choice=0:leftarrow,1:rightarrow char alphaKey; // hotkey in menu } menuitem_t; typedef struct menu_s { short numitems; // # of menu items struct menu_s *prevMenu; // previous menu menuitem_t *menuitems; // menu items void (*routine)(); // draw routine short x,y; // x,y of menu short lastOn; // last item user was on in menu } menu_t; short itemOn; // menu item skull is on short skullAnimCounter; // skull animation counter short whichSkull; // which skull to draw char skullName[2][8] = // graphic name of skulls {"M_SKULL1","M_SKULL2"}; menu_t *currentMenu; // current menudef // // PROTOTYPES // void M_NewGame(int choice); void M_Episode(int choice); void M_ChooseSkill(int choice); void M_LoadGame(int choice); void M_SaveGame(int choice); void M_Options(int choice); void M_EndGame(int choice); void M_ReadThis(int choice); void M_QuitDOOM(int choice); void M_ChangeMessages(int choice); void M_ChangeSensitivity(int choice); void M_SfxVol(int choice); void M_MusicVol(int choice); void M_ChangeDetail(int choice); void M_SizeDisplay(int choice); void M_StartGame(int choice); void M_Sound(int choice); void M_ReadThis(int choice); void M_ReadThis2(int choice); void M_FinishReadThis(int choice); void M_LoadSelect(int choice); void M_SaveSelect(int choice); void M_ReadSaveStrings(void); void M_QuickSave(void); void M_QuickLoad(void); void M_DrawMainMenu(void); void M_DrawReadThis1(void); void M_DrawReadThis2(void); void M_DrawNewGame(void); void M_DrawEpisode(void); void M_DrawOptions(void); void M_DrawSound(void); void M_DrawLoad(void); void M_DrawSave(void); void M_DrawSaveLoadBorder(int x,int y); void M_SetupNextMenu(menu_t *menudef); void M_DrawThermo(int x,int y,int thermWidth,int thermDot); void M_DrawEmptyCell(menu_t *menu,int item); void M_DrawSelCell(menu_t *menu,int item); void M_WriteText(int x, int y, char *string); int M_StringWidth(char *string); int M_StringHeight(char *string); void M_StartControlPanel(void); void M_StartMessage(char *string,void *routine,boolean input); void M_StopMessage(void); void M_ClearMenus (void); //============================================= // // DOOM MENU // //============================================= enum { newgame = 0, options, loadgame, savegame, readthis, quitdoom, main_end } main_e; menuitem_t MainMenu[]= { {1,"M_NGAME",M_NewGame,'n'}, {1,"M_OPTION",M_Options,'o'}, {1,"M_LOADG",M_LoadGame,'l'}, {1,"M_SAVEG",M_SaveGame,'s'}, {1,"M_RDTHIS",M_ReadThis,'r'}, {1,"M_QUITG",M_QuitDOOM,'q'} }; menu_t MainDef = { main_end, NULL, MainMenu, M_DrawMainMenu, 97,64, 0 }; //============================================= // // EPISODE SELECT // //============================================= enum { ep1, ep2, ep3, ep_end } episodes_e; menuitem_t EpisodeMenu[]= { {1,"M_EPI1",M_Episode,'k'}, {1,"M_EPI2", M_Episode,'t'}, {1,"M_EPI3", M_Episode,'i'} }; menu_t EpiDef = { ep_end, // # of menu items &MainDef, // previous menu EpisodeMenu, // menuitem_t -> M_DrawEpisode, // drawing routine -> 48,63, // x,y ep1 // lastOn }; //============================================= // // NEW GAME // //============================================= enum { killthings, toorough, hurtme, violence, nightmare, newg_end } newgame_e; menuitem_t NewGameMenu[]= { {1,"M_JKILL",M_ChooseSkill,'i'}, {1,"M_ROUGH", M_ChooseSkill,'h'}, {1,"M_HURT", M_ChooseSkill,'h'}, {1,"M_ULTRA", M_ChooseSkill,'u'}, {1,"M_NMARE", M_ChooseSkill,'n'} }; menu_t NewDef = { newg_end, // # of menu items &EpiDef, // previous menu NewGameMenu, // menuitem_t -> M_DrawNewGame, // drawing routine -> 48,63, // x,y hurtme // lastOn }; //============================================= // // OPTIONS MENU // //============================================= enum { endgame, messages, detail, scrnsize, option_empty1, mousesens, option_empty2, soundvol, opt_end } options_e; menuitem_t OptionsMenu[]= { {1,"M_ENDGAM",M_EndGame,'e'}, {1,"M_MESSG",M_ChangeMessages,'m'}, {1,"M_DETAIL",M_ChangeDetail,'g'}, {2,"M_SCRNSZ",M_SizeDisplay,'s'}, {-1,"",0}, {2,"M_MSENS",M_ChangeSensitivity,'m'}, {-1,"",0}, {1,"M_SVOL",M_Sound,'s'} }; menu_t OptionsDef = { opt_end, &MainDef, OptionsMenu, M_DrawOptions, 60,37, 0 }; //============================================= // // Read This! MENU 1 & 2 // //============================================= enum { rdthsempty1, read1_end } read_e; menuitem_t ReadMenu1[]= { {1,"",M_ReadThis2,0} }; menu_t ReadDef1 = { read1_end, &MainDef, ReadMenu1, M_DrawReadThis1, 280,185, 0 }; enum { rdthsempty2, read2_end } read_e2; menuitem_t ReadMenu2[]= { {1,"",M_FinishReadThis,0} }; menu_t ReadDef2 = { read2_end, &ReadDef1, ReadMenu2, M_DrawReadThis2, 330,175, 0 }; //============================================= // // SOUND VOLUME MENU // //============================================= enum { sfx_vol, sfx_empty1, music_vol, sfx_empty2, sound_end } sound_e; menuitem_t SoundMenu[]= { {2,"M_SFXVOL",M_SfxVol,'s'}, {-1,"",0}, {2,"M_MUSVOL",M_MusicVol,'m'}, {-1,"",0} }; menu_t SoundDef = { sound_end, &OptionsDef, SoundMenu, M_DrawSound, 80,64, 0 }; //============================================= // // LOAD GAME MENU // //============================================= enum { load1, load2, load3, load4, load5, load6, load_end } load_e; menuitem_t LoadMenu[]= { {1,"", M_LoadSelect,'1'}, {1,"", M_LoadSelect,'2'}, {1,"", M_LoadSelect,'3'}, {1,"", M_LoadSelect,'4'}, {1,"", M_LoadSelect,'5'}, {1,"", M_LoadSelect,'6'} }; menu_t LoadDef = { load_end, &MainDef, LoadMenu, M_DrawLoad, 80,54, 0 }; //============================================= // // SAVE GAME MENU // //============================================= menuitem_t SaveMenu[]= { {1,"", M_SaveSelect,'1'}, {1,"", M_SaveSelect,'2'}, {1,"", M_SaveSelect,'3'}, {1,"", M_SaveSelect,'4'}, {1,"", M_SaveSelect,'5'}, {1,"", M_SaveSelect,'6'} }; menu_t SaveDef = { load_end, &MainDef, SaveMenu, M_DrawSave, 80,54, 0 }; //============================================= // // M_ReadSaveStrings - read the strings from the // savegame files // //============================================= void M_ReadSaveStrings(void) { int handle; int count; int i; char name[256]; for (i = 0;i < load_end;i++) { if (M_CheckParm("-cdrom")) sprintf(name,"c:\\doomdata\\"SAVEGAMENAME"%d.dsg",i); else sprintf(name,SAVEGAMENAME"%d.dsg",i); handle = open (name, O_RDONLY | 0, 0666); if (handle == -1) { strcpy(&savegamestrings[i][0],EMPTYSTRING); LoadMenu[i].status = 0; continue; } count = read (handle, &savegamestrings[i], SAVESTRINGSIZE); close (handle); LoadMenu[i].status = 1; } } //============================================= // // M_LoadGame // //============================================= void M_DrawLoad(void) { int i; V_DrawPatchDirect (72,28,0,W_CacheLumpName("M_LOADG",PU_CACHE)); for (i = 0;i < load_end; i++) { M_DrawSaveLoadBorder(LoadDef.x,LoadDef.y+LINEHEIGHT*i); M_WriteText(LoadDef.x,LoadDef.y+LINEHEIGHT*i,savegamestrings[i]); } } // // Draw border for the savegame description // void M_DrawSaveLoadBorder(int x,int y) { int i; V_DrawPatchDirect (x-8,y+7,0,W_CacheLumpName("M_LSLEFT",PU_CACHE)); for (i = 0;i < 24;i++) { V_DrawPatchDirect (x,y+7,0,W_CacheLumpName("M_LSCNTR",PU_CACHE)); x += 8; } V_DrawPatchDirect (x,y+7,0,W_CacheLumpName("M_LSRGHT",PU_CACHE)); } // // User wants to load this game // void M_LoadSelect(int choice) { char name[256]; if (M_CheckParm("-cdrom")) sprintf(name,"c:\\doomdata\\"SAVEGAMENAME"%d.dsg",choice); else sprintf(name,SAVEGAMENAME"%d.dsg",choice); G_LoadGame (name); M_ClearMenus (); } // // Selected from DOOM menu // void M_LoadGame (int choice) { if (netgame) { M_StartMessage(LOADNET,NULL,false); return; } M_SetupNextMenu(&LoadDef); M_ReadSaveStrings(); } //============================================= // // M_SaveGame // //============================================= void M_DrawSave(void) { int i; V_DrawPatchDirect (72,28,0,W_CacheLumpName("M_SAVEG",PU_CACHE)); for (i = 0;i < load_end; i++) { M_DrawSaveLoadBorder(LoadDef.x,LoadDef.y+LINEHEIGHT*i); M_WriteText(LoadDef.x,LoadDef.y+LINEHEIGHT*i,savegamestrings[i]); } if (saveStringEnter) { i = M_StringWidth(savegamestrings[saveSlot]); M_WriteText(LoadDef.x + i,LoadDef.y+LINEHEIGHT*saveSlot,"_"); } } // // M_Responder calls this when user is finished // void M_DoSave(int slot) { G_SaveGame (slot,savegamestrings[slot]); M_ClearMenus (); // PICK QUICKSAVE SLOT YET? if (quickSaveSlot == -2) quickSaveSlot = slot; } // // User wants to save. Start string input for M_Responder // void M_SaveSelect(int choice) { saveStringEnter = 1; // we're going to be intercepting all chars saveSlot = choice; strcpy(saveOldString,savegamestrings[choice]); if (!strcmp(savegamestrings[choice],EMPTYSTRING)) savegamestrings[choice][0] = 0; saveCharIndex = strlen(savegamestrings[choice]); } // // Selected from DOOM menu // void M_SaveGame (int choice) { if (!usergame) { M_StartMessage(SAVEDEAD,NULL,false); return; } if (gamestate != GS_LEVEL) return; M_SetupNextMenu(&SaveDef); M_ReadSaveStrings(); } //============================================= // // M_QuickSave // //============================================= char tempstring[80]; void M_QuickSaveResponse(int ch) { if (ch == 'y') { M_DoSave(quickSaveSlot); S_StartSound(NULL,sfx_swtchx); } } void M_QuickSave(void) { if (!usergame) { S_StartSound(NULL,sfx_oof); return; } if (gamestate != GS_LEVEL) return; if (quickSaveSlot < 0) { M_StartControlPanel(); M_ReadSaveStrings(); M_SetupNextMenu(&SaveDef); quickSaveSlot = -2; // means to pick a slot now return; } sprintf(tempstring,QSPROMPT,savegamestrings[quickSaveSlot]); M_StartMessage(tempstring,M_QuickSaveResponse,true); } //============================================= // // M_QuickLoad // //============================================= void M_QuickLoadResponse(int ch) { if (ch == 'y') { M_LoadSelect(quickSaveSlot); S_StartSound(NULL,sfx_swtchx); } } void M_QuickLoad(void) { if (netgame) { M_StartMessage(QLOADNET,NULL,false); return; } if (quickSaveSlot < 0) { M_StartMessage(QSAVESPOT,NULL,false); return; } sprintf(tempstring,QLPROMPT,savegamestrings[quickSaveSlot]); M_StartMessage(tempstring,M_QuickLoadResponse,true); } //============================================= // // Read This Menus // //============================================= void M_DrawReadThis1(void) { inhelpscreens = true; V_DrawPatchDirect (0,0,0,W_CacheLumpName("HELP2",PU_CACHE)); } void M_DrawReadThis2(void) { inhelpscreens = true; V_DrawPatchDirect (0,0,0,W_CacheLumpName("HELP1",PU_CACHE)); } void M_DrawReadThisRetail(void) { inhelpscreens = true; V_DrawPatchDirect (0,0,0,W_CacheLumpName("HELP",PU_CACHE)); } //============================================= // // Change Sfx & Music volumes // //============================================= void M_DrawSound(void) { V_DrawPatchDirect (60,38,0,W_CacheLumpName("M_SVOL",PU_CACHE)); M_DrawThermo(SoundDef.x,SoundDef.y+LINEHEIGHT*(sfx_vol+1), 16,sfxVolume); M_DrawThermo(SoundDef.x,SoundDef.y+LINEHEIGHT*(music_vol+1), 16,musicVolume); } void M_Sound(int choice) { M_SetupNextMenu(&SoundDef); } void M_SfxVol(int choice) { switch(choice) { case 0: if (sfxVolume) sfxVolume--; break; case 1: if (sfxVolume < 15) sfxVolume++; break; } S_SetSfxVolume(sfxVolume*8); } void M_MusicVol(int choice) { switch(choice) { case 0: if (musicVolume) musicVolume--; break; case 1: if (musicVolume < 15) musicVolume++; break; } S_SetMusicVolume(musicVolume*8); } //============================================= // // M_DrawMainMenu // //============================================= void M_DrawMainMenu(void) { V_DrawPatchDirect (94,2,0,W_CacheLumpName("M_DOOM",PU_CACHE)); } //============================================= // // M_NewGame // //============================================= void M_DrawNewGame(void) { V_DrawPatchDirect (96,14,0,W_CacheLumpName("M_NEWG",PU_CACHE)); V_DrawPatchDirect (54,38,0,W_CacheLumpName("M_SKILL",PU_CACHE)); } void M_NewGame(int choice) { if (netgame && !demoplayback) { M_StartMessage(NEWGAME,NULL,false); return; } if (commercial) M_SetupNextMenu(&NewDef); else M_SetupNextMenu(&EpiDef); } //============================================= // // M_Episode // //============================================= int epi; void M_DrawEpisode(void) { V_DrawPatchDirect (54,38,0,W_CacheLumpName("M_EPISOD",PU_CACHE)); } void M_VerifyNightmare(int ch) { if (ch != 'y') return; G_DeferedInitNew(nightmare,epi+1,1); M_ClearMenus (); } void M_ChooseSkill(int choice) { if (choice == nightmare) { M_StartMessage(NIGHTMARE,M_VerifyNightmare,true); return; } G_DeferedInitNew(choice,epi+1,1); M_ClearMenus (); } void M_Episode(int choice) { if (shareware && choice) { M_StartMessage(SWSTRING,NULL,false); M_SetupNextMenu(&ReadDef1); return; } epi = choice; M_SetupNextMenu(&NewDef); } //============================================= // // M_Options // //============================================= char detailNames[2][9] = {"M_GDHIGH","M_GDLOW"}; char msgNames[2][9] = {"M_MSGOFF","M_MSGON"}; void M_DrawOptions(void) { V_DrawPatchDirect (108,15,0,W_CacheLumpName("M_OPTTTL",PU_CACHE)); V_DrawPatchDirect (OptionsDef.x + 175,OptionsDef.y+LINEHEIGHT*detail,0, W_CacheLumpName(detailNames[detailLevel],PU_CACHE)); V_DrawPatchDirect (OptionsDef.x + 120,OptionsDef.y+LINEHEIGHT*messages,0, W_CacheLumpName(msgNames[showMessages],PU_CACHE)); M_DrawThermo(OptionsDef.x,OptionsDef.y+LINEHEIGHT*(mousesens+1), 10,mouseSensitivity); M_DrawThermo(OptionsDef.x,OptionsDef.y+LINEHEIGHT*(scrnsize+1), 9,screenSize); } void M_Options(int choice) { M_SetupNextMenu(&OptionsDef); } //============================================= // // Toggle messages on/off // //============================================= void M_ChangeMessages(int choice) { showMessages = 1 - showMessages; if (!showMessages) players[consoleplayer].message = MSGOFF; else players[consoleplayer].message = MSGON ; message_dontfuckwithme = true; } //============================================= // // M_EndGame // //============================================= void M_EndGameResponse(int ch) { if (ch != 'y') return; currentMenu->lastOn = itemOn; M_ClearMenus (); D_StartTitle (); } void M_EndGame(int choice) { if (!usergame) { S_StartSound(NULL,sfx_oof); return; } if (netgame) { M_StartMessage(NETEND,NULL,false); return; } M_StartMessage(ENDGAME,M_EndGameResponse,true); } //============================================= // // M_ReadThis // //============================================= void M_ReadThis(int choice) { M_SetupNextMenu(&ReadDef1); } void M_ReadThis2(int choice) { M_SetupNextMenu(&ReadDef2); } void M_FinishReadThis(int choice) { M_SetupNextMenu(&MainDef); } //============================================= // // M_QuitDOOM // //============================================= int quitsounds[8] = { sfx_pldeth, sfx_dmpain, sfx_popain, sfx_slop, sfx_telept, sfx_posit1, sfx_posit3, sfx_sgtatk }; int quitsounds2[8] = { sfx_vilact, sfx_getpow, sfx_boscub, sfx_slop, sfx_skeswg, sfx_kntdth, sfx_bspact, sfx_sgtatk }; void M_QuitResponse(int ch) { if (ch != 'y') return; if (!netgame) { if (commercial) S_StartSound(NULL,quitsounds2[(gametic>>2)&7]); else S_StartSound(NULL,quitsounds[(gametic>>2)&7]); I_WaitVBL(105); } I_Quit (); } void M_QuitDOOM(int choice) { if (commercial) { if (french) sprintf(endstring,"%s\n\n"DOSY, endmsg2[0]); else sprintf(endstring,"%s\n\n"DOSY, endmsg2[(gametic>>2)&7]); } else sprintf(endstring,"%s\n\n"DOSY, endmsg[(gametic>>2)&7]); M_StartMessage(endstring,M_QuitResponse,true); } void M_ChangeSensitivity(int choice) { switch(choice) { case 0: if (mouseSensitivity) mouseSensitivity--; break; case 1: if (mouseSensitivity < 9) mouseSensitivity++; break; } } void M_ChangeDetail(int choice) { detailLevel = 1 - detailLevel; R_SetViewSize (screenblocks, detailLevel); if (!detailLevel) players[consoleplayer].message = DETAILHI; else players[consoleplayer].message = DETAILLO ; } void M_SizeDisplay(int choice) { switch(choice) { case 0: if (screenSize > 0) { screenblocks--; screenSize--; } break; case 1: if (screenSize < 8) { screenblocks++; screenSize++; } break; } R_SetViewSize (screenblocks, detailLevel); } //============================================= //============================================= // // Menu Functions // //============================================= //============================================= void M_DrawThermo(int x,int y,int thermWidth,int thermDot) { int xx,i; xx = x; V_DrawPatchDirect (xx,y,0,W_CacheLumpName("M_THERML",PU_CACHE)); xx += 8; for (i=0;ix - 10, menu->y+item*LINEHEIGHT - 1, 0, W_CacheLumpName("M_CELL1",PU_CACHE)); } void M_DrawSelCell(menu_t *menu,int item) { V_DrawPatchDirect (menu->x - 10, menu->y+item*LINEHEIGHT - 1, 0, W_CacheLumpName("M_CELL2",PU_CACHE)); } void M_StartMessage(char *string,void *routine,boolean input) { messageLastMenuActive = menuactive; menuactive = 0; messageToPrint = 1; messageString = string; messageRoutine = routine; messageNeedsInput = input; menuactive = true; return; } void M_StopMessage(void) { menuactive = messageLastMenuActive; messageToPrint = 0; } //========================================================================= // // Find string width from hu_font chars // //========================================================================= int M_StringWidth(char *string) { int i; int w = 0; int c; for (i = 0;i < strlen(string);i++) { c = toupper(string[i]) - HU_FONTSTART; if (c < 0 || c >= HU_FONTSIZE) w += 4; else w += SHORT (hu_font[c]->width); } return w; } //========================================================================= // // Find string height from hu_font chars // //========================================================================= int M_StringHeight(char *string) { int i; int h; int height = SHORT(hu_font[0]->height); h = height; for (i = 0;i < strlen(string);i++) if (string[i] == '\n') h += height; return h; } //========================================================================= // // Write a string using the hu_font // //========================================================================= void M_WriteText(int x, int y, char *string) { int w; char *ch; int c; int cx; int cy; ch = string; cx = x; cy = y; while(1) { c = *ch++; if (!c) break; if (c == '\n') { cx = x; cy += 12; continue; } c = toupper(c) - HU_FONTSTART; if (c < 0 || c>= HU_FONTSIZE) { cx += 4; continue; } w = SHORT (hu_font[c]->width); if (cx+w > SCREENWIDTH) break; V_DrawPatchDirect(cx, cy, 0, hu_font[c]); cx+=w; } } /* =============================================================================== CONTROL PANEL =============================================================================== */ /* ===================== = = M_Responder = ====================== */ boolean M_Responder (event_t *ev) { int ch; int i; static int joywait = 0; static int mousewait = 0; static int mousey = 0; static int lasty = 0; static int mousex = 0; static int lastx = 0; ch = -1; if (ev->type == ev_joystick && joywait < I_GetTime()) { if (ev->data3 == -1) { ch = KEY_UPARROW; joywait = I_GetTime() + 5; } else if (ev->data3 == 1) { ch = KEY_DOWNARROW; joywait = I_GetTime() + 5; } if (ev->data2 == -1) { ch = KEY_LEFTARROW; joywait = I_GetTime() + 2; } else if (ev->data2 == 1) { ch = KEY_RIGHTARROW; joywait = I_GetTime() + 2; } if (ev->data1&1) { ch = KEY_ENTER; joywait = I_GetTime() + 5; } if (ev->data1&2) { ch = KEY_BACKSPACE; joywait = I_GetTime() + 5; } } else if (ev->type == ev_mouse && mousewait < I_GetTime()) { mousey += ev->data3; if (mousey < lasty-30) { ch = KEY_DOWNARROW; mousewait = I_GetTime() + 5; mousey = lasty -= 30; } else if (mousey > lasty+30) { ch = KEY_UPARROW; mousewait = I_GetTime() + 5; mousey = lasty += 30; } mousex += ev->data2; if (mousex < lastx-30) { ch = KEY_LEFTARROW; mousewait = I_GetTime() + 5; mousex = lastx -= 30; } else if (mousex > lastx+30) { ch = KEY_RIGHTARROW; mousewait = I_GetTime() + 5; mousex = lastx += 30; } if (ev->data1&1) { ch = KEY_ENTER; mousewait = I_GetTime() + 15; } if (ev->data1&2) { ch = KEY_BACKSPACE; mousewait = I_GetTime() + 15; } } else if (ev->type == ev_keydown) { ch = ev->data1; } if (ch == -1) return false; // // Save Game string input // if (saveStringEnter) { switch(ch) { case KEY_BACKSPACE: if (saveCharIndex > 0) { saveCharIndex--; savegamestrings[saveSlot][saveCharIndex] = 0; } break; case KEY_ESCAPE: saveStringEnter = 0; strcpy(&savegamestrings[saveSlot][0],saveOldString); break; case KEY_ENTER: saveStringEnter = 0; if (savegamestrings[saveSlot][0]) M_DoSave(saveSlot); break; default: ch = toupper(ch); if (ch != 32) if (ch-HU_FONTSTART < 0 || ch-HU_FONTSTART >= HU_FONTSIZE) break; if (ch >= 32 && ch <= 127 && saveCharIndex < SAVESTRINGSIZE-1 && M_StringWidth(savegamestrings[saveSlot]) < (SAVESTRINGSIZE-2)*8) { savegamestrings[saveSlot][saveCharIndex++] = ch; savegamestrings[saveSlot][saveCharIndex] = 0; } break; } return true; } // // Take care of any messages that need input // if (messageToPrint) { if (messageNeedsInput == true && !(ch == ' ' || ch == 'n' || ch == 'y' || ch == KEY_ESCAPE)) return false; menuactive = messageLastMenuActive; messageToPrint = 0; if (messageRoutine) messageRoutine(ch); menuactive = false; S_StartSound(NULL,sfx_swtchx); return true; } if (devparm && ch == KEY_F1) { G_ScreenShot (); return true; } // // F-Keys // if (!menuactive) switch(ch) { case KEY_MINUS: // Screen size down if (automapactive || chat_on) return false; M_SizeDisplay(0); S_StartSound(NULL,sfx_stnmov); return true; case KEY_EQUALS: // Screen size up if (automapactive || chat_on) return false; M_SizeDisplay(1); S_StartSound(NULL,sfx_stnmov); return true; case KEY_F1: // Help key M_StartControlPanel (); currentMenu = &ReadDef1; itemOn = 0; S_StartSound(NULL,sfx_swtchn); return true; case KEY_F2: // Save M_StartControlPanel(); S_StartSound(NULL,sfx_swtchn); M_SaveGame(0); return true; case KEY_F3: // Load M_StartControlPanel(); S_StartSound(NULL,sfx_swtchn); M_LoadGame(0); return true; case KEY_F4: // Sound Volume M_StartControlPanel (); currentMenu = &SoundDef; itemOn = sfx_vol; S_StartSound(NULL,sfx_swtchn); return true; case KEY_F5: // Detail toggle M_ChangeDetail(0); S_StartSound(NULL,sfx_swtchn); return true; case KEY_F6: // Quicksave S_StartSound(NULL,sfx_swtchn); M_QuickSave(); return true; case KEY_F7: // End game S_StartSound(NULL,sfx_swtchn); M_EndGame(0); return true; case KEY_F8: // Toggle messages M_ChangeMessages(0); S_StartSound(NULL,sfx_swtchn); return true; case KEY_F9: // Quickload S_StartSound(NULL,sfx_swtchn); M_QuickLoad(); return true; case KEY_F10: // Quit DOOM S_StartSound(NULL,sfx_swtchn); M_QuitDOOM(0); return true; case KEY_F11: // gamma toggle usegamma++; if (usegamma > 4) usegamma = 0; players[consoleplayer].message = gammamsg[usegamma]; I_SetPalette (W_CacheLumpName ("PLAYPAL",PU_CACHE)); return true; } // // Pop-up menu? // if (!menuactive) { if (ch == KEY_ESCAPE) { M_StartControlPanel (); S_StartSound(NULL,sfx_swtchn); return true; } return false; } // // Keys usable within menu // switch (ch) { case KEY_DOWNARROW: do { if (itemOn+1 > currentMenu->numitems-1) itemOn = 0; else itemOn++; S_StartSound(NULL,sfx_pstop); } while(currentMenu->menuitems[itemOn].status==-1); return true; case KEY_UPARROW: do { if (!itemOn) itemOn = currentMenu->numitems-1; else itemOn--; S_StartSound(NULL,sfx_pstop); } while(currentMenu->menuitems[itemOn].status==-1); return true; case KEY_LEFTARROW: if (currentMenu->menuitems[itemOn].routine && currentMenu->menuitems[itemOn].status == 2) { S_StartSound(NULL,sfx_stnmov); currentMenu->menuitems[itemOn].routine(0); } return true; case KEY_RIGHTARROW: if (currentMenu->menuitems[itemOn].routine && currentMenu->menuitems[itemOn].status == 2) { S_StartSound(NULL,sfx_stnmov); currentMenu->menuitems[itemOn].routine(1); } return true; case KEY_ENTER: if (currentMenu->menuitems[itemOn].routine && currentMenu->menuitems[itemOn].status) { currentMenu->lastOn = itemOn; if (currentMenu->menuitems[itemOn].status == 2) { currentMenu->menuitems[itemOn].routine(1); // right arrow S_StartSound(NULL,sfx_stnmov); } else { currentMenu->menuitems[itemOn].routine(itemOn); S_StartSound(NULL,sfx_pistol); } } return true; case KEY_ESCAPE: currentMenu->lastOn = itemOn; M_ClearMenus (); S_StartSound(NULL,sfx_swtchx); return true; case KEY_BACKSPACE: currentMenu->lastOn = itemOn; if (currentMenu->prevMenu) { currentMenu = currentMenu->prevMenu; itemOn = currentMenu->lastOn; S_StartSound(NULL,sfx_swtchn); } return true; default: for (i = itemOn+1;i < currentMenu->numitems;i++) if (currentMenu->menuitems[i].alphaKey == ch) { itemOn = i; S_StartSound(NULL,sfx_pstop); return true; } for (i = 0;i <= itemOn;i++) if (currentMenu->menuitems[i].alphaKey == ch) { itemOn = i; S_StartSound(NULL,sfx_pstop); return true; } break; } return false; } /* ===================== = = M_StartControlPanel = ====================== */ void M_StartControlPanel (void) { if (menuactive) return; // intro might call this repeatedly menuactive = 1; currentMenu = &MainDef; // JDC itemOn = currentMenu->lastOn; // JDC } /* ============================================================================== = = M_Drawer = = Called after the view has been rendered, but before it has been blitted. = ============================================================================== */ void M_Drawer (void) { static short x,y; short i,max; char string[40]; int start; inhelpscreens = false; // // Horiz. & Vertically center string and print it. // if (messageToPrint) { start = 0; y = 100 - M_StringHeight(messageString)/2; while(*(messageString+start)) { for (i = 0;i < strlen(messageString+start);i++) if (*(messageString+start+i) == '\n') { memset(string,0,40); strncpy(string,messageString+start,i); start += i+1; break; } if (i == strlen(messageString+start)) { strcpy(string,messageString+start); start += i; } x = 160 - M_StringWidth(string)/2; M_WriteText(x,y,string); y += SHORT(hu_font[0]->height); } return; } if (!menuactive) return; if (currentMenu->routine) currentMenu->routine(); // call Draw routine // // DRAW MENU // x = currentMenu->x; y = currentMenu->y; max = currentMenu->numitems; for (i=0;imenuitems[i].name[0]) V_DrawPatchDirect (x,y,0, W_CacheLumpName(currentMenu->menuitems[i].name ,PU_CACHE)); y += LINEHEIGHT; } // // DRAW SKULL // V_DrawPatchDirect(x + SKULLXOFF,currentMenu->y - 5 + itemOn*LINEHEIGHT, 0, W_CacheLumpName(skullName[whichSkull],PU_CACHE)); } /* ===================== = = M_ClearMenus = ====================== */ void M_ClearMenus (void) { menuactive = 0; // if (!netgame && usergame && paused) // sendpause = true; } //============================================= // // M_SetupNextMenu // //============================================= void M_SetupNextMenu(menu_t *menudef) { currentMenu = menudef; itemOn = currentMenu->lastOn; } /* ===================== = = M_Ticker = ====================== */ void M_Ticker (void) { if (--skullAnimCounter <= 0) { whichSkull ^= 1; skullAnimCounter = 8; } } /* ===================== = = M_Init = ====================== */ void M_Init (void) { currentMenu = &MainDef; menuactive = 0; itemOn = currentMenu->lastOn; whichSkull = 0; skullAnimCounter = 10; screenSize = screenblocks - 3; messageToPrint = 0; messageString = NULL; messageLastMenuActive = menuactive; quickSaveSlot = -1; if (commercial) { MainMenu[readthis] = MainMenu[quitdoom]; MainDef.numitems--; MainDef.y += 8; NewDef.prevMenu = &MainDef; ReadDef1.routine = M_DrawReadThisRetail; ReadDef1.x = 330; ReadDef1.y = 165; ReadMenu1[0].routine = M_FinishReadThis; } } \ No newline at end of file diff --git a/M_MISC.C b/M_MISC.C new file mode 100644 index 0000000..6bad4de --- /dev/null +++ b/M_MISC.C @@ -0,0 +1 @@ +// M_misc.c #ifdef __NeXT__ #include #else #include #include //#include #include #include #endif #include #include "doomdef.h" #include "hu_stuff.h" int myargc; char **myargv; /* ==================== = = M_DrawText = = Returns the final X coordinate = HU_Init must have been called to init the font ==================== */ extern patch_t *hu_font[HU_FONTSIZE]; int M_DrawText (int x, int y, boolean direct, char *string) { int c,w; while (*string) { c = toupper(*string) - HU_FONTSTART; string++; if (c < 0 || c> HU_FONTSIZE) { x += 4; continue; } w = SHORT (hu_font[c]->width); if (x+w > SCREENWIDTH) break; if (direct) V_DrawPatchDirect(x, y, 0, hu_font[c]); else V_DrawPatch(x, y, 0, hu_font[c]); x+=w; } return x; } /* ================= = = M_CheckParm = = Checks for the given parameter in the program's command line arguments = = Returns the argument number (1 to argc-1) or 0 if not present = ================= */ int M_CheckParm (char *check) { int i; for (i = 1;ibox[BOXRIGHT]) box[BOXRIGHT] = x; if (ybox[BOXTOP]) box[BOXTOP] = y; } /* ================== = = M_WriteFile = ================== */ #ifndef O_BINARY #define O_BINARY 0 #endif boolean M_WriteFile (char const *name, void *source, int length) { int handle, count; handle = open (name, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666); if (handle == -1) return false; count = write (handle, source, length); close (handle); if (count < length) return false; return true; } /* ================== = = M_ReadFile = ================== */ int M_ReadFile (char const *name, byte **buffer) { int handle, count, length; struct stat fileinfo; byte *buf; handle = open (name, O_RDONLY | O_BINARY, 0666); if (handle == -1) I_Error ("Couldn't read file %s", name); if (fstat (handle,&fileinfo) == -1) I_Error ("Couldn't read file %s", name); length = fileinfo.st_size; buf = Z_Malloc (length, PU_STATIC, NULL); count = read (handle, buf, length); close (handle); if (count < length) I_Error ("Couldn't read file %s", name); *buffer = buf; return length; } /* ============================================================================== DEFAULTS ============================================================================== */ int usemouse; int usejoystick; extern int key_right, key_left, key_up, key_down; extern int key_strafeleft, key_straferight; extern int key_fire, key_use, key_strafe, key_speed; extern int mousebfire; extern int mousebstrafe; extern int mousebforward; extern int joybfire; extern int joybstrafe; extern int joybuse; extern int joybspeed; extern int viewwidth, viewheight; extern int mouseSensitivity; extern int showMessages; extern int sfxVolume; extern int musicVolume; extern int detailLevel; extern int screenblocks; extern int showMessages; // machine-independent sound params extern int numChannels; #ifdef __WATCOMC__ // machine-dependent sound params extern int snd_DesiredMusicDevice; extern int snd_DesiredSfxDevice; extern int snd_SBport, snd_SBirq, snd_SBdma; extern int snd_Mport; #endif #ifdef NORMALUNIX extern char *sndserver_filename; extern int mb_used; #endif #ifdef LINUX char *mousetype; char *mousedev; #endif extern char *chat_macros[]; typedef struct { char *name; int *location; int defaultvalue; int scantranslate; // PC scan code hack int untranslated; // lousy hack } default_t; default_t defaults[] = { {"mouse_sensitivity",&mouseSensitivity, 5}, {"sfx_volume",&sfxVolume, 8}, {"music_volume",&musicVolume, 8}, {"show_messages",&showMessages, 1}, #ifdef __WATCOMC__ #define SC_UPARROW 0x48 #define SC_DOWNARROW 0x50 #define SC_LEFTARROW 0x4b #define SC_RIGHTARROW 0x4d #define SC_RCTRL 0x1d #define SC_RALT 0x38 #define SC_RSHIFT 0x36 #define SC_SPACE 0x39 #define SC_COMMA 0x33 #define SC_PERIOD 0x34 {"key_right",&key_right, SC_RIGHTARROW,1}, {"key_left",&key_left, SC_LEFTARROW,1}, {"key_up",&key_up, SC_UPARROW,1}, {"key_down",&key_down, SC_DOWNARROW,1}, {"key_strafeleft",&key_strafeleft, SC_COMMA,1}, {"key_straferight",&key_straferight, SC_PERIOD,1}, {"key_fire",&key_fire, SC_RCTRL,1}, {"key_use",&key_use, SC_SPACE,1}, {"key_strafe",&key_strafe, SC_RALT,1}, {"key_speed",&key_speed, SC_RSHIFT,1}, #endif #ifdef __NeXT__ {"key_right",&key_right, KEY_RIGHTARROW}, {"key_left",&key_left, KEY_LEFTARROW}, {"key_up",&key_up, KEY_UPARROW}, {"key_down",&key_down, KEY_DOWNARROW}, {"key_strafeleft",&key_strafeleft, ','}, {"key_straferight",&key_straferight, '.'}, {"key_fire",&key_fire, ' ',1}, {"key_use",&key_use, 'x',1}, {"key_strafe",&key_strafe, 'c',1}, {"key_speed",&key_speed, 'z',1}, #endif #ifdef NORMALUNIX {"key_right",&key_right, KEY_RIGHTARROW}, {"key_left",&key_left, KEY_LEFTARROW}, {"key_up",&key_up, KEY_UPARROW}, {"key_down",&key_down, KEY_DOWNARROW}, {"key_strafeleft",&key_strafeleft, ','}, {"key_straferight",&key_straferight, '.'}, {"key_fire",&key_fire, KEY_RCTRL}, {"key_use",&key_use, ' '}, {"key_strafe",&key_strafe, KEY_RALT}, {"key_speed",&key_speed, KEY_RSHIFT}, {"sndserver", (int *) &sndserver_filename, (int) "sndserver"}, {"mb_used", &mb_used, 2}, #endif #ifdef LINUX {"mousedev", (int*)&mousedev, (int)"/dev/ttyS0"}, {"mousetype", (int*)&mousetype, (int)"microsoft"}, #endif {"use_mouse",&usemouse, 1}, {"mouseb_fire",&mousebfire,0}, {"mouseb_strafe",&mousebstrafe,1}, {"mouseb_forward",&mousebforward,2}, {"use_joystick",&usejoystick, 0}, {"joyb_fire",&joybfire,0}, {"joyb_strafe",&joybstrafe,1}, {"joyb_use",&joybuse,3}, {"joyb_speed",&joybspeed,2}, {"screenblocks",&screenblocks, 9}, {"detaillevel",&detailLevel, 0}, {"snd_channels",&numChannels, 3}, #ifdef __WATCOMC__ {"snd_musicdevice", &snd_DesiredMusicDevice, 0}, {"snd_sfxdevice", &snd_DesiredSfxDevice, 0}, {"snd_sbport", &snd_SBport, 0x220}, {"snd_sbirq", &snd_SBirq, 5}, {"snd_sbdma", &snd_SBdma, 1}, {"snd_mport", &snd_Mport, 0x330}, #endif {"usegamma",&usegamma, 0}, {"chatmacro0", (int *) &chat_macros[0], (int) HUSTR_CHATMACRO0 }, {"chatmacro1", (int *) &chat_macros[1], (int) HUSTR_CHATMACRO1 }, {"chatmacro2", (int *) &chat_macros[2], (int) HUSTR_CHATMACRO2 }, {"chatmacro3", (int *) &chat_macros[3], (int) HUSTR_CHATMACRO3 }, {"chatmacro4", (int *) &chat_macros[4], (int) HUSTR_CHATMACRO4 }, {"chatmacro5", (int *) &chat_macros[5], (int) HUSTR_CHATMACRO5 }, {"chatmacro6", (int *) &chat_macros[6], (int) HUSTR_CHATMACRO6 }, {"chatmacro7", (int *) &chat_macros[7], (int) HUSTR_CHATMACRO7 }, {"chatmacro8", (int *) &chat_macros[8], (int) HUSTR_CHATMACRO8 }, {"chatmacro9", (int *) &chat_macros[9], (int) HUSTR_CHATMACRO9 } }; int numdefaults; char *defaultfile; /* ============== = = M_SaveDefaults = ============== */ void M_SaveDefaults (void) { int i,v; FILE *f; f = fopen (defaultfile, "w"); if (!f) return; // can't write the file, but don't complain for (i=0 ; i -0xfff && defaults[i].defaultvalue < 0xfff) { v = *defaults[i].location; fprintf (f,"%s\t\t%i\n",defaults[i].name,v); } else { fprintf (f,"%s\t\t\"%s\"\n",defaults[i].name, * (char **) (defaults[i].location)); } } fclose (f); } /* ============== = = M_LoadDefaults = ============== */ extern byte scantokey[128]; void M_LoadDefaults (void) { int i, len; FILE *f; char def[80]; char strparm[100]; char *newstring; int parm; boolean isstring; // // set everything to base values // numdefaults = sizeof(defaults)/sizeof(defaults[0]); for (i=0 ; imanufacturer = 0x0a; // PCX id pcx->version = 5; // 256 color pcx->encoding = 1; // uncompressed pcx->bits_per_pixel = 8; // 256 color pcx->xmin = 0; pcx->ymin = 0; pcx->xmax = SHORT(width-1); pcx->ymax = SHORT(height-1); pcx->hres = SHORT(width); pcx->vres = SHORT(height); memset (pcx->palette,0,sizeof(pcx->palette)); pcx->color_planes = 1; // chunky image pcx->bytes_per_line = SHORT(width); pcx->palette_type = SHORT(2); // not a grey scale memset (pcx->filler,0,sizeof(pcx->filler)); // // pack the image // pack = &pcx->data; for (i=0 ; idirection) { case 0: // IN STASIS break; case 1: // UP res = T_MovePlane(ceiling->sector,ceiling->speed, ceiling->topheight,false,1,ceiling->direction); if (!(leveltime&7)) switch(ceiling->type) { case silentCrushAndRaise: break; default: S_StartSound((mobj_t *)&ceiling->sector->soundorg, sfx_stnmov); } if (res == pastdest) switch(ceiling->type) { case raiseToHighest: P_RemoveActiveCeiling(ceiling); break; case silentCrushAndRaise: S_StartSound((mobj_t *)&ceiling->sector->soundorg, sfx_pstop); case fastCrushAndRaise: case crushAndRaise: ceiling->direction = -1; break; default: break; } break; case -1: // DOWN res = T_MovePlane(ceiling->sector,ceiling->speed, ceiling->bottomheight,ceiling->crush,1,ceiling->direction); if (!(leveltime&7)) switch(ceiling->type) { case silentCrushAndRaise: break; default: S_StartSound((mobj_t *)&ceiling->sector->soundorg, sfx_stnmov); } if (res == pastdest) switch(ceiling->type) { case silentCrushAndRaise: S_StartSound((mobj_t *)&ceiling->sector->soundorg, sfx_pstop); case crushAndRaise: ceiling->speed = CEILSPEED; case fastCrushAndRaise: ceiling->direction = 1; break; case lowerAndCrush: case lowerToFloor: P_RemoveActiveCeiling(ceiling); break; default: break; } else if (res == crushed) switch(ceiling->type) { case silentCrushAndRaise: case crushAndRaise: case lowerAndCrush: ceiling->speed = CEILSPEED / 8; break; default: break; } break; } } //================================================================== // // EV_DoCeiling // Move a ceiling up/down and all around! // //================================================================== int EV_DoCeiling (line_t *line, ceiling_e type) { int secnum,rtn; sector_t *sec; ceiling_t *ceiling; secnum = -1; rtn = 0; // // Reactivate in-stasis ceilings...for certain types. // switch(type) { case fastCrushAndRaise: case silentCrushAndRaise: case crushAndRaise: P_ActivateInStasisCeiling(line); default: break; } while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0) { sec = §ors[secnum]; if (sec->specialdata) continue; // // new door thinker // rtn = 1; ceiling = Z_Malloc (sizeof(*ceiling), PU_LEVSPEC, 0); P_AddThinker (&ceiling->thinker); sec->specialdata = ceiling; ceiling->thinker.function = (think_t) T_MoveCeiling; ceiling->sector = sec; ceiling->crush = false; switch(type) { case fastCrushAndRaise: ceiling->crush = true; ceiling->topheight = sec->ceilingheight; ceiling->bottomheight = sec->floorheight + (8*FRACUNIT); ceiling->direction = -1; ceiling->speed = CEILSPEED * 2; break; case silentCrushAndRaise: case crushAndRaise: ceiling->crush = true; ceiling->topheight = sec->ceilingheight; case lowerAndCrush: case lowerToFloor: ceiling->bottomheight = sec->floorheight; if (type != lowerToFloor) ceiling->bottomheight += 8*FRACUNIT; ceiling->direction = -1; ceiling->speed = CEILSPEED; break; case raiseToHighest: ceiling->topheight = P_FindHighestCeilingSurrounding(sec); ceiling->direction = 1; ceiling->speed = CEILSPEED; break; } ceiling->tag = sec->tag; ceiling->type = type; P_AddActiveCeiling(ceiling); } return rtn; } //================================================================== // // Add an active ceiling // //================================================================== void P_AddActiveCeiling(ceiling_t *c) { int i; for (i = 0; i < MAXCEILINGS;i++) if (activeceilings[i] == NULL) { activeceilings[i] = c; return; } } //================================================================== // // Remove a ceiling's thinker // //================================================================== void P_RemoveActiveCeiling(ceiling_t *c) { int i; for (i = 0;i < MAXCEILINGS;i++) if (activeceilings[i] == c) { activeceilings[i]->sector->specialdata = NULL; P_RemoveThinker (&activeceilings[i]->thinker); activeceilings[i] = NULL; break; } } //================================================================== // // Restart a ceiling that's in-stasis // //================================================================== void P_ActivateInStasisCeiling(line_t *line) { int i; for (i = 0;i < MAXCEILINGS;i++) if (activeceilings[i] && (activeceilings[i]->tag == line->tag) && (activeceilings[i]->direction == 0)) { activeceilings[i]->direction = activeceilings[i]->olddirection; activeceilings[i]->thinker.function = (think_t) T_MoveCeiling; } } //================================================================== // // EV_CeilingCrushStop // Stop a ceiling from crushing! // //================================================================== int EV_CeilingCrushStop(line_t *line) { int i; int rtn; rtn = 0; for (i = 0;i < MAXCEILINGS;i++) if (activeceilings[i] && (activeceilings[i]->tag == line->tag) && (activeceilings[i]->direction != 0)) { activeceilings[i]->olddirection = activeceilings[i]->direction; activeceilings[i]->thinker.function = NULL; activeceilings[i]->direction = 0; // in-stasis rtn = 1; } return rtn; } \ No newline at end of file diff --git a/P_DOORS.C b/P_DOORS.C new file mode 100644 index 0000000..774f047 --- /dev/null +++ b/P_DOORS.C @@ -0,0 +1 @@ +#include "doomdef.h" #include "p_local.h" #if 0 //================================================================== // // Sliding door frame information // //================================================================== slidename_t slideFrameNames[MAXSLIDEDOORS] = { {"GDOORF1","GDOORF2","GDOORF3","GDOORF4", // front "GDOORB1","GDOORB2","GDOORB3","GDOORB4"}, // back {"\0","\0","\0","\0"} }; #endif //================================================================== //================================================================== // // VERTICAL DOORS // //================================================================== //================================================================== //================================================================== // // T_VerticalDoor // //================================================================== void T_VerticalDoor (vldoor_t *door) { result_e res; switch(door->direction) { case 0: // WAITING if (!--door->topcountdown) switch(door->type) { case blazeRaise: door->direction = -1; // time to go back down S_StartSound((mobj_t *)&door->sector->soundorg, sfx_bdcls); break; case normal: door->direction = -1; // time to go back down S_StartSound((mobj_t *)&door->sector->soundorg, sfx_dorcls); break; case close30ThenOpen: door->direction = 1; S_StartSound((mobj_t *)&door->sector->soundorg, sfx_doropn); break; default: break; } break; case 2: // INITIAL WAIT if (!--door->topcountdown) switch(door->type) { case raiseIn5Mins: door->direction = 1; door->type = normal; S_StartSound((mobj_t *)&door->sector->soundorg, sfx_doropn); break; default: break; } break; case -1: // DOWN res = T_MovePlane(door->sector,door->speed, door->sector->floorheight,false,1,door->direction); if (res == pastdest) switch(door->type) { case blazeRaise: case blazeClose: door->sector->specialdata = NULL; P_RemoveThinker (&door->thinker); // unlink and free S_StartSound((mobj_t *)&door->sector->soundorg, sfx_bdcls); break; case normal: case close: door->sector->specialdata = NULL; P_RemoveThinker (&door->thinker); // unlink and free break; case close30ThenOpen: door->direction = 0; door->topcountdown = 35*30; break; default: break; } else if (res == crushed) { switch(door->type) { case blazeClose: case close: // DON'T GO BACK UP! break; default: door->direction = 1; S_StartSound((mobj_t *)&door->sector-> soundorg,sfx_doropn); break; } } break; case 1: // UP res = T_MovePlane(door->sector,door->speed, door->topheight,false,1,door->direction); if (res == pastdest) switch(door->type) { case blazeRaise: case normal: door->direction = 0; // wait at top door->topcountdown = door->topwait; break; case close30ThenOpen: case blazeOpen: case open: door->sector->specialdata = NULL; P_RemoveThinker (&door->thinker); // unlink and free break; default: break; } break; } } //================================================================== // // EV_DoLockedDoor // Move a locked door up/down // //================================================================== int EV_DoLockedDoor (line_t *line, vldoor_e type, mobj_t *thing) { player_t *p; p = thing->player; if (!p) return 0; switch(line->special) { case 99: // Blue Lock case 133: if ( !p ) return 0; if (!p->cards[it_bluecard] && !p->cards[it_blueskull]) { p->message = PD_BLUEO; S_StartSound(NULL,sfx_oof); return 0; } break; case 134: // Red Lock case 135: if ( !p ) return 0; if (!p->cards[it_redcard] && !p->cards[it_redskull]) { p->message = PD_REDO; S_StartSound(NULL,sfx_oof); return 0; } break; case 136: // Yellow Lock case 137: if ( !p ) return 0; if (!p->cards[it_yellowcard] && !p->cards[it_yellowskull]) { p->message = PD_YELLOWO; S_StartSound(NULL,sfx_oof); return 0; } break; } return EV_DoDoor(line,type); } int EV_DoDoor (line_t *line, vldoor_e type) { int secnum,rtn; sector_t *sec; vldoor_t *door; secnum = -1; rtn = 0; while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0) { sec = §ors[secnum]; if (sec->specialdata) continue; // // new door thinker // rtn = 1; door = Z_Malloc (sizeof(*door), PU_LEVSPEC, 0); P_AddThinker (&door->thinker); sec->specialdata = door; door->thinker.function = (think_t) T_VerticalDoor; door->sector = sec; door->type = type; door->topwait = VDOORWAIT; door->speed = VDOORSPEED; switch(type) { case blazeClose: door->topheight = P_FindLowestCeilingSurrounding(sec); door->topheight -= 4*FRACUNIT; door->direction = -1; door->speed = VDOORSPEED * 4; S_StartSound((mobj_t *)&door->sector->soundorg,sfx_bdcls); break; case close: door->topheight = P_FindLowestCeilingSurrounding(sec); door->topheight -= 4*FRACUNIT; door->direction = -1; S_StartSound((mobj_t *)&door->sector->soundorg,sfx_dorcls); break; case close30ThenOpen: door->topheight = sec->ceilingheight; door->direction = -1; S_StartSound((mobj_t *)&door->sector->soundorg,sfx_dorcls); break; case blazeRaise: case blazeOpen: door->direction = 1; door->topheight = P_FindLowestCeilingSurrounding(sec); door->topheight -= 4*FRACUNIT; door->speed = VDOORSPEED * 4; if (door->topheight != sec->ceilingheight) S_StartSound((mobj_t *)&door->sector->soundorg,sfx_bdopn); break; case normal: case open: door->direction = 1; door->topheight = P_FindLowestCeilingSurrounding(sec); door->topheight -= 4*FRACUNIT; if (door->topheight != sec->ceilingheight) S_StartSound((mobj_t *)&door->sector->soundorg,sfx_doropn); break; default: break; } } return rtn; } //================================================================== // // EV_VerticalDoor : open a door manually, no tag value // //================================================================== void EV_VerticalDoor (line_t *line, mobj_t *thing) { player_t *player; int secnum; sector_t *sec; vldoor_t *door; int side; side = 0; // only front sides can be used // // Check for locks // player = thing->player; switch(line->special) { case 26: // Blue Lock case 32: if ( !player ) return; if (!player->cards[it_bluecard] && !player->cards[it_blueskull]) { player->message = PD_BLUEK; S_StartSound(NULL,sfx_oof); return; } break; case 27: // Yellow Lock case 34: if ( !player ) return; if (!player->cards[it_yellowcard] && !player->cards[it_yellowskull]) { player->message = PD_YELLOWK; S_StartSound(NULL,sfx_oof); return; } break; case 28: // Red Lock case 33: if ( !player ) return; if (!player->cards[it_redcard] && !player->cards[it_redskull]) { player->message = PD_REDK; S_StartSound(NULL,sfx_oof); return; } break; } // if the sector has an active thinker, use it sec = sides[ line->sidenum[side^1]] .sector; secnum = sec-sectors; if (sec->specialdata) { door = sec->specialdata; switch(line->special) { case 1: // ONLY FOR "RAISE" DOORS, NOT "OPEN"s case 26: case 27: case 28: case 117: if (door->direction == -1) door->direction = 1; // go back up else { if (!thing->player) return; // JDC: bad guys never close doors door->direction = -1; // start going down immediately } return; } } // for proper sound switch(line->special) { case 117: // BLAZING DOOR RAISE case 118: // BLAZING DOOR OPEN S_StartSound((mobj_t *)&sec->soundorg,sfx_bdopn); break; case 1: // NORMAL DOOR SOUND case 31: S_StartSound((mobj_t *)&sec->soundorg,sfx_doropn); break; default: // LOCKED DOOR SOUND S_StartSound((mobj_t *)&sec->soundorg,sfx_doropn); break; } // // new door thinker // door = Z_Malloc (sizeof(*door), PU_LEVSPEC, 0); P_AddThinker (&door->thinker); sec->specialdata = door; door->thinker.function = (think_t) T_VerticalDoor; door->sector = sec; door->direction = 1; door->speed = VDOORSPEED; door->topwait = VDOORWAIT; switch(line->special) { case 1: case 26: case 27: case 28: door->type = normal; break; case 31: case 32: case 33: case 34: door->type = open; line->special = 0; break; case 117: // blazing door raise door->type = blazeRaise; door->speed = VDOORSPEED*4; break; case 118: // blazing door open door->type = blazeOpen; line->special = 0; door->speed = VDOORSPEED*4; break; } // // find the top and bottom of the movement range // door->topheight = P_FindLowestCeilingSurrounding(sec); door->topheight -= 4*FRACUNIT; } //================================================================== // // Spawn a door that closes after 30 seconds // //================================================================== void P_SpawnDoorCloseIn30 (sector_t *sec) { vldoor_t *door; door = Z_Malloc ( sizeof(*door), PU_LEVSPEC, 0); P_AddThinker (&door->thinker); sec->specialdata = door; sec->special = 0; door->thinker.function = (think_t) T_VerticalDoor; door->sector = sec; door->direction = 0; door->type = normal; door->speed = VDOORSPEED; door->topcountdown = 30 * 35; } //================================================================== // // Spawn a door that opens after 5 minutes // //================================================================== void P_SpawnDoorRaiseIn5Mins (sector_t *sec, int secnum) { vldoor_t *door; door = Z_Malloc ( sizeof(*door), PU_LEVSPEC, 0); P_AddThinker (&door->thinker); sec->specialdata = door; sec->special = 0; door->thinker.function = (think_t) T_VerticalDoor; door->sector = sec; door->direction = 2; door->type = raiseIn5Mins; door->speed = VDOORSPEED; door->topheight = P_FindLowestCeilingSurrounding(sec); door->topheight -= 4*FRACUNIT; door->topwait = VDOORWAIT; door->topcountdown = 5 * 60 * 35; } #if 0 // ABANDONED TO THE MISTS OF TIME!!! //================================================================== // // EV_SlidingDoor : slide a door horizontally // (animate midtexture, then set noblocking line) // //================================================================== slideframe_t slideFrames[MAXSLIDEDOORS]; void P_InitSlidingDoorFrames(void) { int i; int f1; int f2; int f3; int f4; // DOOM II ONLY... if (!commercial) return; for (i = 0;i < MAXSLIDEDOORS; i++) { if (!slideFrameNames[i].frontFrame1[0]) break; f1 = R_TextureNumForName(slideFrameNames[i].frontFrame1); f2 = R_TextureNumForName(slideFrameNames[i].frontFrame2); f3 = R_TextureNumForName(slideFrameNames[i].frontFrame3); f4 = R_TextureNumForName(slideFrameNames[i].frontFrame4); slideFrames[i].frontFrames[0] = f1; slideFrames[i].frontFrames[1] = f2; slideFrames[i].frontFrames[2] = f3; slideFrames[i].frontFrames[3] = f4; f1 = R_TextureNumForName(slideFrameNames[i].backFrame1); f2 = R_TextureNumForName(slideFrameNames[i].backFrame2); f3 = R_TextureNumForName(slideFrameNames[i].backFrame3); f4 = R_TextureNumForName(slideFrameNames[i].backFrame4); slideFrames[i].backFrames[0] = f1; slideFrames[i].backFrames[1] = f2; slideFrames[i].backFrames[2] = f3; slideFrames[i].backFrames[3] = f4; } } // // Return index into "slideFrames" array for which door type to use // int P_FindSlidingDoorType(line_t *line) { int i; int val; for (i = 0;i < MAXSLIDEDOORS;i++) { val = sides[line->sidenum[0]].midtexture; if (val == slideFrames[i].frontFrames[0]) return i; } return -1; } void T_SlidingDoor (slidedoor_t *door) { switch(door->status) { case sd_opening: if (!door->timer--) { // IF DOOR IS DONE OPENING... if (++door->frame == SNUMFRAMES) { sides[door->line->sidenum[0]].midtexture = 0; sides[door->line->sidenum[1]].midtexture = 0; door->line->flags &= ML_BLOCKING^0xff; if (door->type == sdt_openOnly) { door->frontsector->specialdata = NULL; P_RemoveThinker (&door->thinker); break; } door->timer = SDOORWAIT; door->status = sd_waiting; } else // IF DOOR NEEDS TO ANIMATE TO NEXT FRAME... { door->timer = SWAITTICS; sides[door->line->sidenum[0]].midtexture = slideFrames[door->whichDoorIndex]. frontFrames[door->frame]; sides[door->line->sidenum[1]].midtexture = slideFrames[door->whichDoorIndex]. backFrames[door->frame]; } } break; case sd_waiting: // IF DOOR IS DONE WAITING... if (!door->timer--) { // CAN DOOR CLOSE? if (door->frontsector->thinglist != NULL || door->backsector->thinglist != NULL) { door->timer = SDOORWAIT; break; } //door->frame = SNUMFRAMES-1; door->status = sd_closing; door->timer = SWAITTICS; } break; case sd_closing: if (!door->timer--) { // IF DOOR IS DONE CLOSING... if (--door->frame < 0) { door->line->flags |= ML_BLOCKING; door->frontsector->specialdata = NULL; P_RemoveThinker (&door->thinker); break; } else // IF DOOR NEEDS TO ANIMATE TO NEXT FRAME... { door->timer = SWAITTICS; sides[door->line->sidenum[0]].midtexture = slideFrames[door->whichDoorIndex]. frontFrames[door->frame]; sides[door->line->sidenum[1]].midtexture = slideFrames[door->whichDoorIndex]. backFrames[door->frame]; } } break; } } void EV_SlidingDoor (line_t *line, mobj_t *thing) { sector_t *sec; slidedoor_t *door; // DOOM II ONLY... if (!commercial) return; // // Make sure door isn't already being animated // sec = line->frontsector; door = NULL; if (sec->specialdata) { if (!thing->player) return; door = sec->specialdata; if (door->type == sdt_openAndClose) { if (door->status == sd_waiting) door->status = sd_closing; } else return; } // // Init sliding door vars // if (!door) { door = Z_Malloc (sizeof(*door), PU_LEVSPEC, 0); P_AddThinker (&door->thinker); sec->specialdata = door; door->type = sdt_openAndClose; door->status = sd_opening; door->whichDoorIndex = P_FindSlidingDoorType(line); if (door->whichDoorIndex < 0) I_Error("EV_SlidingDoor: Can't use texture for sliding door!"); door->frontsector = sec; door->backsector = line->backsector; door->thinker.function = T_SlidingDoor; door->timer = SWAITTICS; door->frame = 0; door->line = line; } } #endif \ No newline at end of file diff --git a/P_ENEMY.C b/P_ENEMY.C new file mode 100644 index 0000000..3a39dda --- /dev/null +++ b/P_ENEMY.C @@ -0,0 +1 @@ +// P_enemy.c #include "doomdef.h" #include "p_local.h" void A_Fall (mobj_t *actor); /* =============================================================================== ENEMY THINKING enemies are allways spawned with targetplayer = -1, threshold = 0 Most monsters are spawned unaware of all players, but some can be made preaware =============================================================================== */ /* ================= = = P_NoiseAlert = = If a monster yells at a player, it will alert other monsters to the player = ================= */ mobj_t *soundtarget; void P_RecursiveSound (sector_t *sec, int soundblocks) { int i; line_t *check; sector_t *other; // wake up all monsters in this sector if (sec->validcount == validcount && sec->soundtraversed <= soundblocks+1) return; // already flooded sec->validcount = validcount; sec->soundtraversed = soundblocks+1; sec->soundtarget = soundtarget; for (i=0 ;ilinecount ; i++) { check = sec->lines[i]; if (! (check->flags & ML_TWOSIDED) ) continue; P_LineOpening (check); if (openrange <= 0) continue; // closed door if ( sides[ check->sidenum[0] ].sector == sec) other = sides[ check->sidenum[1] ] .sector; else other = sides[ check->sidenum[0] ].sector; if (check->flags & ML_SOUNDBLOCK) { if (!soundblocks) P_RecursiveSound (other, 1); } else P_RecursiveSound (other, soundblocks); } } /* ================= = = P_NoiseAlert = = If a monster yells at a player, it will alert other monsters to the player = ================= */ void P_NoiseAlert (mobj_t *target, mobj_t *emmiter) { soundtarget = target; validcount++; P_RecursiveSound (emmiter->subsector->sector, 0); } /* ================ = = P_CheckMeleeRange = ================ */ boolean P_CheckMeleeRange (mobj_t *actor) { mobj_t *pl; fixed_t dist; if (!actor->target) return false; pl = actor->target; dist = P_AproxDistance (pl->x-actor->x, pl->y-actor->y); if (dist >= MELEERANGE-20*FRACUNIT+pl->info->radius) return false; if (! P_CheckSight (actor, actor->target) ) return false; return true; } /* ================ = = P_CheckMissileRange = ================ */ boolean P_CheckMissileRange (mobj_t *actor) { fixed_t dist; if (! P_CheckSight (actor, actor->target) ) return false; if ( actor->flags & MF_JUSTHIT ) { // the target just hit the enemy, so fight back! actor->flags &= ~MF_JUSTHIT; return true; } if (actor->reactiontime) return false; // don't attack yet // OPTIMIZE: get this from a global checksight dist = P_AproxDistance ( actor->x-actor->target->x, actor->y-actor->target->y) - 64*FRACUNIT; if (!actor->info->meleestate) dist -= 128*FRACUNIT; // no melee attack, so fire more dist >>= 16; if (actor->type == MT_VILE) { if (dist > 14*64) return false; // too far away } if (actor->type == MT_UNDEAD) { if (dist < 196) return false; // close for fist attack dist >>= 1; } if (actor->type == MT_CYBORG || actor->type == MT_SPIDER || actor->type == MT_SKULL) dist >>= 1; if (dist > 200) dist = 200; if (actor->type == MT_CYBORG && dist > 160) dist = 160; if (P_Random () < dist) return false; return true; } /* ================ = = P_Move = = Move in the current direction = returns false if the move is blocked ================ */ fixed_t xspeed[8] = {FRACUNIT,47000,0,-47000,-FRACUNIT,-47000,0,47000}; fixed_t yspeed[8] = {0,47000,FRACUNIT,47000,0,-47000,-FRACUNIT,-47000}; #define MAXSPECIALCROSS 8 extern line_t *spechit[MAXSPECIALCROSS]; extern int numspechit; boolean P_Move (mobj_t *actor) { fixed_t tryx, tryy; line_t *ld; boolean try, good; if (actor->movedir == DI_NODIR) return false; if ((unsigned)actor->movedir >= 8) I_Error ("Weird actor->movedir!"); tryx = actor->x + actor->info->speed*xspeed[actor->movedir]; tryy = actor->y + actor->info->speed*yspeed[actor->movedir]; try = P_TryMove (actor, tryx, tryy); if (!try) { // open any specials if (actor->flags & MF_FLOAT && floatok) { // must adjust height if (actor->z < tmfloorz) actor->z += FLOATSPEED; else actor->z -= FLOATSPEED; actor->flags |= MF_INFLOAT; return true; } if (!numspechit) return false; actor->movedir = DI_NODIR; good = false; while (numspechit--) { ld = spechit[numspechit]; // if the special isn't a door that can be opened, return false if (P_UseSpecialLine (actor, ld,0)) good = true; } return good; } else { actor->flags &= ~MF_INFLOAT; } if (! (actor->flags & MF_FLOAT) ) actor->z = actor->floorz; return true; } /* ================================== = = TryWalk = = Attempts to move actoron in its current (ob->moveangle) direction. = = If blocked by either a wall or an actor returns FALSE = If move is either clear or blocked only by a door, returns TRUE and sets = If a door is in the way, an OpenDoor call is made to start it opening. = ================================== */ boolean P_TryWalk (mobj_t *actor) { if (!P_Move (actor)) { return false; } actor->movecount = P_Random()&15; return true; } /* ================ = = P_NewChaseDir = ================ */ dirtype_t opposite[] = {DI_WEST, DI_SOUTHWEST, DI_SOUTH, DI_SOUTHEAST, DI_EAST, DI_NORTHEAST, DI_NORTH, DI_NORTHWEST, DI_NODIR}; dirtype_t diags[] = {DI_NORTHWEST,DI_NORTHEAST,DI_SOUTHWEST,DI_SOUTHEAST}; void P_NewChaseDir (mobj_t *actor) { fixed_t deltax,deltay; dirtype_t d[3]; dirtype_t tdir, olddir, turnaround; if (!actor->target) I_Error ("P_NewChaseDir: called with no target"); olddir = actor->movedir; turnaround=opposite[olddir]; deltax = actor->target->x - actor->x; deltay = actor->target->y - actor->y; if (deltax>10*FRACUNIT) d[1]= DI_EAST; else if (deltax<-10*FRACUNIT) d[1]= DI_WEST; else d[1]=DI_NODIR; if (deltay<-10*FRACUNIT) d[2]= DI_SOUTH; else if (deltay>10*FRACUNIT) d[2]= DI_NORTH; else d[2]=DI_NODIR; // try direct route if (d[1] != DI_NODIR && d[2] != DI_NODIR) { actor->movedir = diags[((deltay<0)<<1)+(deltax>0)]; if (actor->movedir != turnaround && P_TryWalk(actor)) return; } // try other directions if (P_Random() > 200 || abs(deltay)>abs(deltax)) { tdir=d[1]; d[1]=d[2]; d[2]=tdir; } if (d[1]==turnaround) d[1]=DI_NODIR; if (d[2]==turnaround) d[2]=DI_NODIR; if (d[1]!=DI_NODIR) { actor->movedir = d[1]; if (P_TryWalk(actor)) return; /*either moved forward or attacked*/ } if (d[2]!=DI_NODIR) { actor->movedir =d[2]; if (P_TryWalk(actor)) return; } /* there is no direct path to the player, so pick another direction */ if (olddir!=DI_NODIR) { actor->movedir =olddir; if (P_TryWalk(actor)) return; } if (P_Random()&1) /*randomly determine direction of search*/ { for (tdir=DI_EAST ; tdir<=DI_SOUTHEAST ; tdir++) { if (tdir!=turnaround) { actor->movedir =tdir; if ( P_TryWalk(actor) ) return; } } } else { for (tdir=DI_SOUTHEAST ; tdir != (DI_EAST-1) ;tdir--) { if (tdir!=turnaround) { actor->movedir =tdir; if ( P_TryWalk(actor) ) return; } } } if (turnaround != DI_NODIR) { actor->movedir =turnaround; if ( P_TryWalk(actor) ) return; } actor->movedir = DI_NODIR; // can't move } /* ================ = = P_LookForPlayers = = If allaround is false, only look 180 degrees in front = returns true if a player is targeted ================ */ boolean P_LookForPlayers (mobj_t *actor, boolean allaround) { int c, stop; player_t *player; sector_t *sector; angle_t an; fixed_t dist; sector = actor->subsector->sector; c = 0; stop = (actor->lastlook-1)&3; for ( ; ; actor->lastlook = (actor->lastlook+1)&3 ) { if (!playeringame[actor->lastlook]) continue; if (c++ == 2 || actor->lastlook == stop) return false; // done looking player = &players[actor->lastlook]; if (player->health <= 0) continue; // dead if (!P_CheckSight (actor, player->mo)) continue; // out of sight if (!allaround) { an = R_PointToAngle2 (actor->x, actor->y, player->mo->x, player->mo->y) - actor->angle; if (an > ANG90 && an < ANG270) { dist = P_AproxDistance (player->mo->x - actor->x, player->mo->y - actor->y); // if real close, react anyway if (dist > MELEERANGE) continue; // behind back } } actor->target = player->mo; return true; } return false; } //============================================================================= /* ============== = = A_KeenDie = ============== */ void A_KeenDie (mobj_t *mo) { thinker_t *th; mobj_t *mo2; line_t junk; A_Fall (mo); // // scan the remaining thinkers to see if all Keens are dead // for (th = thinkercap.next ; th != &thinkercap ; th=th->next) { if (th->function != P_MobjThinker) continue; mo2 = (mobj_t *)th; if (mo2 != mo && mo2->type == mo->type && mo2->health > 0) return; // other Keen not dead } junk.tag = 666; EV_DoDoor(&junk,open); } /* =============================================================================== ACTION ROUTINES =============================================================================== */ /* ============== = = A_Look = = Stay in state until a player is sighted = ============== */ void A_Look (mobj_t *actor) { mobj_t *targ; actor->threshold = 0; // any shot will wake up targ = actor->subsector->sector->soundtarget; if (targ && (targ->flags & MF_SHOOTABLE) ) { actor->target = targ; if ( actor->flags & MF_AMBUSH ) { if (P_CheckSight (actor, actor->target)) goto seeyou; } else goto seeyou; } if (!P_LookForPlayers (actor, false) ) return; // go into chase state seeyou: if (actor->info->seesound) { int sound; switch (actor->info->seesound) { case sfx_posit1: case sfx_posit2: case sfx_posit3: sound = sfx_posit1+P_Random()%3; break; case sfx_bgsit1: case sfx_bgsit2: sound = sfx_bgsit1+P_Random()%2; break; default: sound = actor->info->seesound; break; } if (actor->type==MT_SPIDER || actor->type == MT_CYBORG) S_StartSound (NULL, sound); // full volume else S_StartSound (actor, sound); } P_SetMobjState (actor, actor->info->seestate); } /* ============== = = A_Chase = = Actor has a melee attack, so it tries to close as fast as possible = ============== */ void A_Chase (mobj_t *actor) { int delta; if (actor->reactiontime) actor->reactiontime--; // // modify target threshold // if (actor->threshold) { if (!actor->target || actor->target->health <= 0) actor->threshold = 0; else actor->threshold--; } // // turn towards movement direction if not there yet // if (actor->movedir < 8) { actor->angle &= (7<<29); delta = actor->angle - (actor->movedir << 29); if (delta > 0) actor->angle -= ANG90/2; else if (delta < 0) actor->angle += ANG90/2; } if (!actor->target || !(actor->target->flags&MF_SHOOTABLE)) { // look for a new target if (P_LookForPlayers(actor,true)) return; // got a new target P_SetMobjState (actor, actor->info->spawnstate); return; } // // don't attack twice in a row // if (actor->flags & MF_JUSTATTACKED) { actor->flags &= ~MF_JUSTATTACKED; if (gameskill != sk_nightmare && !fastparm) P_NewChaseDir (actor); return; } // // check for melee attack // if (actor->info->meleestate && P_CheckMeleeRange (actor)) { if (actor->info->attacksound) S_StartSound (actor, actor->info->attacksound); P_SetMobjState (actor, actor->info->meleestate); return; } // // check for missile attack // if (actor->info->missilestate) { if (gameskill < sk_nightmare && !fastparm && actor->movecount) goto nomissile; if (!P_CheckMissileRange (actor)) goto nomissile; P_SetMobjState (actor, actor->info->missilestate); actor->flags |= MF_JUSTATTACKED; return; } nomissile: // // possibly choose another target // if (netgame && !actor->threshold && !P_CheckSight (actor, actor->target) ) { if (P_LookForPlayers(actor,true)) return; // got a new target } // // chase towards player // if (--actor->movecount<0 || !P_Move (actor)) { P_NewChaseDir (actor); } // // make active sound // if (actor->info->activesound && P_Random () < 3) S_StartSound (actor, actor->info->activesound); } /* ============== = = A_FaceTarget = ============== */ void A_FaceTarget (mobj_t *actor) { if (!actor->target) return; actor->flags &= ~MF_AMBUSH; actor->angle = R_PointToAngle2 (actor->x, actor->y , actor->target->x, actor->target->y); if (actor->target->flags & MF_SHADOW) actor->angle += (P_Random()-P_Random())<<21; } /* ============== = = A_PosAttack = ============== */ void A_PosAttack (mobj_t *actor) { int angle, damage, slope; if (!actor->target) return; A_FaceTarget (actor); angle = actor->angle; slope = P_AimLineAttack (actor, angle, MISSILERANGE); S_StartSound (actor, sfx_pistol); angle += (P_Random()-P_Random())<<20; damage = ((P_Random()%5)+1)*3; P_LineAttack (actor, angle, MISSILERANGE, slope, damage); } void A_SPosAttack (mobj_t *actor) { int i; int angle, bangle, damage, slope; if (!actor->target) return; S_StartSound (actor, sfx_shotgn); A_FaceTarget (actor); bangle = actor->angle; slope = P_AimLineAttack (actor, bangle, MISSILERANGE); for (i=0 ; i<3 ; i++) { angle = bangle + ((P_Random()-P_Random())<<20); damage = ((P_Random()%5)+1)*3; P_LineAttack (actor, angle, MISSILERANGE, slope, damage); } } void A_CPosAttack (mobj_t *actor) { int angle, bangle, damage, slope; if (!actor->target) return; S_StartSound (actor, sfx_shotgn); A_FaceTarget (actor); bangle = actor->angle; slope = P_AimLineAttack (actor, bangle, MISSILERANGE); angle = bangle + ((P_Random()-P_Random())<<20); damage = ((P_Random()%5)+1)*3; P_LineAttack (actor, angle, MISSILERANGE, slope, damage); } void A_CPosRefire (mobj_t *actor) { // keep firing unless target got out of sight A_FaceTarget (actor); if (P_Random () < 40) return; if (!actor->target || actor->target->health <= 0 || !P_CheckSight (actor, actor->target) ) P_SetMobjState (actor, actor->info->seestate); } void A_SpidRefire (mobj_t *actor) { // keep firing unless target got out of sight A_FaceTarget (actor); if (P_Random () < 10) return; if (!actor->target || actor->target->health <= 0 || !P_CheckSight (actor, actor->target) ) P_SetMobjState (actor, actor->info->seestate); } void A_BspiAttack (mobj_t *actor) { if (!actor->target) return; A_FaceTarget (actor); // // launch a missile // P_SpawnMissile (actor, actor->target, MT_ARACHPLAZ); } /* ============== = = A_TroopAttack = ============== */ void A_TroopAttack (mobj_t *actor) { int damage; if (!actor->target) return; A_FaceTarget (actor); if (P_CheckMeleeRange (actor)) { S_StartSound (actor, sfx_claw); damage = (P_Random()%8+1)*3; P_DamageMobj (actor->target, actor, actor, damage); return; } // // launch a missile // P_SpawnMissile (actor, actor->target, MT_TROOPSHOT); } void A_SargAttack (mobj_t *actor) { int damage; if (!actor->target) return; A_FaceTarget (actor); if (P_CheckMeleeRange (actor)) { damage = ((P_Random()%10)+1)*4; P_DamageMobj (actor->target, actor, actor, damage); } } void A_HeadAttack (mobj_t *actor) { int damage; if (!actor->target) return; A_FaceTarget (actor); if (P_CheckMeleeRange (actor)) { damage = (P_Random()%6+1)*10; P_DamageMobj (actor->target, actor, actor, damage); return; } // // launch a missile // P_SpawnMissile (actor, actor->target, MT_HEADSHOT); } void A_CyberAttack (mobj_t *actor) { if (!actor->target) return; A_FaceTarget (actor); P_SpawnMissile (actor, actor->target, MT_ROCKET); } void A_BruisAttack (mobj_t *actor) { int damage; if (!actor->target) return; if (P_CheckMeleeRange (actor)) { S_StartSound (actor, sfx_claw); damage = (P_Random()%8+1)*10; P_DamageMobj (actor->target, actor, actor, damage); return; } // // launch a missile // P_SpawnMissile (actor, actor->target, MT_BRUISERSHOT); } //=========================================================================== /* ================ = = A_SkelMissile = ================ */ void A_SkelMissile (mobj_t *actor) { mobj_t *mo; if (!actor->target) return; A_FaceTarget (actor); actor->z += 16*FRACUNIT; // so missile spawns higher mo = P_SpawnMissile (actor, actor->target, MT_TRACER); actor->z -= 16*FRACUNIT; // back to normal mo->x += mo->momx; mo->y += mo->momy; mo->tracer = actor->target; } int TRACEANGLE = 0xc000000; void A_Tracer (mobj_t *actor) { angle_t exact; fixed_t dist, slope; mobj_t *dest; mobj_t *th; if (gametic & 3) return; // // spawn a puff of smoke behind the rocket // P_SpawnPuff (actor->x, actor->y, actor->z); th = P_SpawnMobj (actor->x-actor->momx , actor->y-actor->momy ,actor->z, MT_SMOKE); th->momz = FRACUNIT; th->tics -= P_Random()&3; if (th->tics < 1) th->tics = 1; // // adjust direction // dest = actor->tracer; if (!dest || dest->health <= 0) return; // // change angle // exact = R_PointToAngle2 (actor->x, actor->y , dest->x, dest->y); if (exact != actor->angle) { if (exact - actor->angle > 0x80000000) { actor->angle -= TRACEANGLE; if (exact - actor->angle < 0x80000000) actor->angle = exact; } else { actor->angle += TRACEANGLE; if (exact - actor->angle > 0x80000000) actor->angle = exact; } } exact = actor->angle>>ANGLETOFINESHIFT; actor->momx = FixedMul (actor->info->speed, finecosine[exact]); actor->momy = FixedMul (actor->info->speed, finesine[exact]); // // change slope // dist = P_AproxDistance (dest->x - actor->x, dest->y - actor->y); dist = dist / actor->info->speed; if (dist < 1) dist = 1; slope = (dest->z+40*FRACUNIT - actor->z) / dist; if (slope < actor->momz) actor->momz -= FRACUNIT/8; else actor->momz += FRACUNIT/8; } void A_SkelWhoosh (mobj_t *actor) { if (!actor->target) return; A_FaceTarget (actor); S_StartSound (actor,sfx_skeswg); } void A_SkelFist (mobj_t *actor) { int damage; if (!actor->target) return; A_FaceTarget (actor); if (P_CheckMeleeRange (actor)) { damage = ((P_Random()%10)+1)*6; S_StartSound (actor, sfx_skepch); P_DamageMobj (actor->target, actor, actor, damage); } } //=========================================================================== /* ================== = = PIT_VileCheck = ================== */ mobj_t *corpsehit; mobj_t *vileobj; fixed_t viletryx, viletryy; boolean PIT_VileCheck (mobj_t *thing) { int maxdist; boolean check; if (!(thing->flags & MF_CORPSE) ) return true; // not a monster if (thing->tics != -1) return true; // not lying still yet if (thing->info->raisestate == S_NULL) return true; // monster doesn't have a raise state maxdist = thing->info->radius + mobjinfo[MT_VILE].radius; if ( abs(thing->x - viletryx) > maxdist || abs(thing->y - viletryy) > maxdist ) return true; // not actually touching corpsehit = thing; corpsehit->momx = corpsehit->momy = 0; corpsehit->height <<= 2; check = P_CheckPosition (corpsehit, corpsehit->x, corpsehit->y); corpsehit->height >>= 2; if (!check) return true; // doesn't fit here return false; // got one, so stop checking } /* ============== = = A_VileChase = = Check for ressurecting a body = ============== */ void A_VileChase (mobj_t *actor) { int xl, xh, yl, yh; int bx,by; mobjinfo_t *info; mobj_t *temp; if (actor->movedir != DI_NODIR) { // // check for corpses to raise // viletryx = actor->x + actor->info->speed*xspeed[actor->movedir]; viletryy = actor->y + actor->info->speed*yspeed[actor->movedir]; xl = (viletryx - bmaporgx - MAXRADIUS*2)>>MAPBLOCKSHIFT; xh = (viletryx - bmaporgx + MAXRADIUS*2)>>MAPBLOCKSHIFT; yl = (viletryy - bmaporgy - MAXRADIUS*2)>>MAPBLOCKSHIFT; yh = (viletryy - bmaporgy + MAXRADIUS*2)>>MAPBLOCKSHIFT; vileobj = actor; for (bx=xl ; bx<=xh ; bx++) for (by=yl ; by<=yh ; by++) if (!P_BlockThingsIterator(bx,by,PIT_VileCheck)) { // got one! temp = actor->target; actor->target = corpsehit; A_FaceTarget (actor); actor->target = temp; P_SetMobjState (actor, S_VILE_HEAL1); S_StartSound (corpsehit, sfx_slop); info = corpsehit->info; P_SetMobjState (corpsehit,info->raisestate); corpsehit->height <<= 2; corpsehit->flags = info->flags; corpsehit->health = info->spawnhealth; corpsehit->target = NULL; return; } } A_Chase (actor); } /* ================ = = A_VileStart = ================ */ void A_VileStart (mobj_t *actor) { S_StartSound (actor, sfx_vilatk); } /* ================ = = A_Fire = = Keep fire in front of player unless out of sight ================ */ void A_Fire (mobj_t *actor); void A_StartFire (mobj_t *actor) { S_StartSound(actor,sfx_flamst); A_Fire(actor); } void A_FireCrackle (mobj_t *actor) { S_StartSound(actor,sfx_flame); A_Fire(actor); } void A_Fire (mobj_t *actor) { mobj_t *dest; unsigned an; dest = actor->tracer; if (!dest) return; // don't move it if the vile lost sight if (!P_CheckSight (actor->target, dest) ) return; an = dest->angle >> ANGLETOFINESHIFT; P_UnsetThingPosition (actor); actor->x = dest->x + FixedMul (24*FRACUNIT, finecosine[an]); actor->y = dest->y + FixedMul (24*FRACUNIT, finesine[an]); actor->z = dest->z; P_SetThingPosition (actor); } /* ================ = = A_VileTarget = = Spawn the hellfire ================ */ void A_VileTarget (mobj_t *actor) { mobj_t *fog; if (!actor->target) return; A_FaceTarget (actor); fog = P_SpawnMobj (actor->target->x, actor->target->x, actor->target->z, MT_FIRE); actor->tracer = fog; fog->target = actor; fog->tracer = actor->target; A_Fire (fog); } /* ================ = = A_VileAttack = ================ */ void A_VileAttack (mobj_t *actor) { mobj_t *fire; int an; if (!actor->target) return; A_FaceTarget (actor); if (!P_CheckSight (actor, actor->target) ) return; S_StartSound (actor, sfx_barexp); P_DamageMobj (actor->target, actor, actor, 20); actor->target->momz = 1000*FRACUNIT/actor->target->info->mass; an = actor->angle >> ANGLETOFINESHIFT; fire = actor->tracer; if (!fire) return; // move the fire between the vile and the player fire->x = actor->target->x - FixedMul (24*FRACUNIT, finecosine[an]); fire->y = actor->target->y - FixedMul (24*FRACUNIT, finesine[an]); P_RadiusAttack (fire, actor, 70 ); } //=========================================================================== #define FATSPREAD (ANG90/8) void A_FatRaise (mobj_t *actor) { A_FaceTarget (actor); S_StartSound (actor, sfx_manatk); } void A_FatAttack1 (mobj_t *actor) { mobj_t *mo; int an; A_FaceTarget (actor); actor->angle += FATSPREAD; P_SpawnMissile (actor, actor->target, MT_FATSHOT); mo = P_SpawnMissile (actor, actor->target, MT_FATSHOT); mo->angle += FATSPREAD; an = mo->angle >> ANGLETOFINESHIFT; mo->momx = FixedMul (mo->info->speed, finecosine[an]); mo->momy = FixedMul (mo->info->speed, finesine[an]); } void A_FatAttack2 (mobj_t *actor) { mobj_t *mo; int an; A_FaceTarget (actor); actor->angle -= FATSPREAD; P_SpawnMissile (actor, actor->target, MT_FATSHOT); mo = P_SpawnMissile (actor, actor->target, MT_FATSHOT); mo->angle -= FATSPREAD*2; an = mo->angle >> ANGLETOFINESHIFT; mo->momx = FixedMul (mo->info->speed, finecosine[an]); mo->momy = FixedMul (mo->info->speed, finesine[an]); } void A_FatAttack3 (mobj_t *actor) { mobj_t *mo; int an; A_FaceTarget (actor); mo = P_SpawnMissile (actor, actor->target, MT_FATSHOT); mo->angle -= FATSPREAD/2; an = mo->angle >> ANGLETOFINESHIFT; mo->momx = FixedMul (mo->info->speed, finecosine[an]); mo->momy = FixedMul (mo->info->speed, finesine[an]); mo = P_SpawnMissile (actor, actor->target, MT_FATSHOT); mo->angle += FATSPREAD/2; an = mo->angle >> ANGLETOFINESHIFT; mo->momx = FixedMul (mo->info->speed, finecosine[an]); mo->momy = FixedMul (mo->info->speed, finesine[an]); } //=========================================================================== /* ================== = = SkullAttack = = Fly at the player like a missile = ================== */ #define SKULLSPEED (20*FRACUNIT) void A_SkullAttack (mobj_t *actor) { mobj_t *dest; angle_t an; int dist; if (!actor->target) return; dest = actor->target; actor->flags |= MF_SKULLFLY; S_StartSound (actor, actor->info->attacksound); A_FaceTarget (actor); an = actor->angle >> ANGLETOFINESHIFT; actor->momx = FixedMul (SKULLSPEED, finecosine[an]); actor->momy = FixedMul (SKULLSPEED, finesine[an]); dist = P_AproxDistance (dest->x - actor->x, dest->y - actor->y); dist = dist / SKULLSPEED; if (dist < 1) dist = 1; actor->momz = (dest->z+(dest->height>>1) - actor->z) / dist; } //=========================================================================== /* ================== = = A_PainShootSkull = = Spawn a lost soul and launch it at the target = ================== */ void A_PainShootSkull (mobj_t *actor, angle_t angle) { fixed_t x,y,z; mobj_t *newmobj; angle_t an; int prestep; int count; thinker_t *currentthinker; // // if there are allready 20 skulls on the level, don't spit another one // count = 0; currentthinker = thinkercap.next; while (currentthinker != &thinkercap) { if (currentthinker->function == P_MobjThinker && ((mobj_t *)currentthinker)->type == MT_SKULL) count++; currentthinker = currentthinker->next; } if (count > 20) return; an = angle >> ANGLETOFINESHIFT; prestep = 4*FRACUNIT + 3*(actor->info->radius + mobjinfo[MT_SKULL].radius)/2; x = actor->x + FixedMul (prestep, finecosine[an]); y = actor->y + FixedMul (prestep, finesine[an]); z = actor->z + 8*FRACUNIT; newmobj = P_SpawnMobj (x , y, z, MT_SKULL); if (!P_TryMove (newmobj, newmobj->x, newmobj->y)) { P_DamageMobj (newmobj,actor,actor,10000); // kill it immediately return; } newmobj->target = actor->target; A_SkullAttack (newmobj); } /* ================== = = A_PainAttack = = Spawn a lost soul and launch it at the target = ================== */ void A_PainAttack (mobj_t *actor) { if (!actor->target) return; A_FaceTarget (actor); A_PainShootSkull (actor, actor->angle); } void A_PainDie (mobj_t *actor) { A_Fall (actor); A_PainShootSkull (actor, actor->angle+ANG90); A_PainShootSkull (actor, actor->angle+ANG180); A_PainShootSkull (actor, actor->angle+ANG270); } //=========================================================================== void A_Scream (mobj_t *actor) { int sound; switch (actor->info->deathsound) { case 0: return; case sfx_podth1: case sfx_podth2: case sfx_podth3: sound = sfx_podth1 + P_Random ()%3; break; case sfx_bgdth1: case sfx_bgdth2: sound = sfx_bgdth1 + P_Random ()%2; break; default: sound = actor->info->deathsound; break; } if (actor->type==MT_SPIDER || actor->type == MT_CYBORG) S_StartSound (NULL, sound); // full volume else S_StartSound (actor, sound); } void A_XScream (mobj_t *actor) { S_StartSound (actor, sfx_slop); } void A_Pain (mobj_t *actor) { if (actor->info->painsound) S_StartSound (actor, actor->info->painsound); } void A_Fall (mobj_t *actor) { // actor is on ground, it can be walked over actor->flags &= ~MF_SOLID; } /* ================ = = A_Explode = ================ */ void A_Explode (mobj_t *thingy) { P_RadiusAttack ( thingy, thingy->target, 128 ); } /* ================ = = A_BossDeath = = Possibly trigger special effects if on first boss level ================ */ void A_BossDeath (mobj_t *mo) { thinker_t *th; mobj_t *mo2; line_t junk; int i; if (commercial) { if (gamemap != 7) return; if ((mo->type != MT_FATSO) && (mo->type != MT_BABY)) return; } else { if (gamemap != 8) return; // bruisers apear on other levels if (mo->type == MT_BRUISER && gameepisode != 1) return; // bruisers aren't bosses on other episodes } // // make sure there is a player alive for victory // for (i=0 ; i 0) break; if (i==MAXPLAYERS) return; // no one left alive, so don't end game // // scan the remaining thinkers to see if all bosses are dead // for (th = thinkercap.next ; th != &thinkercap ; th=th->next) { if (th->function != P_MobjThinker) continue; mo2 = (mobj_t *)th; if (mo2 != mo && mo2->type == mo->type && mo2->health > 0) return; // other boss not dead } // // victory! // if (commercial) { if (gamemap == 7) { if (mo->type == MT_FATSO) { junk.tag = 666; EV_DoFloor(&junk,lowerFloorToLowest); return; } if (mo->type == MT_BABY) { junk.tag = 667; EV_DoFloor(&junk,raiseToTexture); return; } } } else { if (gameepisode == 1) { junk.tag = 666; EV_DoFloor (&junk, lowerFloorToLowest); return; } } G_ExitLevel (); } void A_Hoof (mobj_t *mo) { S_StartSound (mo, sfx_hoof); A_Chase (mo); } void A_Metal (mobj_t *mo) { S_StartSound (mo, sfx_metal); A_Chase (mo); } void A_BabyMetal (mobj_t *mo) { S_StartSound (mo, sfx_bspwlk); A_Chase (mo); } void A_OpenShotgun2 (player_t *player, pspdef_t *psp) { S_StartSound (player->mo, sfx_dbopn); } void A_LoadShotgun2 (player_t *player, pspdef_t *psp) { S_StartSound (player->mo, sfx_dbload); } void A_ReFire (player_t *player, pspdef_t *psp); void A_CloseShotgun2 (player_t *player, pspdef_t *psp) { S_StartSound (player->mo, sfx_dbcls); A_ReFire(player,psp); } //============================================================================= mobj_t *braintargets[32]; int numbraintargets; int braintargeton; void A_BrainAwake (mobj_t *mo) { thinker_t *thinker; mobj_t *m; // find all the target spots numbraintargets = 0; braintargeton = 0; thinker = thinkercap.next; for (thinker = thinkercap.next ; thinker != &thinkercap ; thinker = thinker->next) { if (thinker->function != P_MobjThinker) continue; // not a mobj m = (mobj_t *)thinker; if (m->type == MT_BOSSTARGET ) { braintargets[numbraintargets] = m; numbraintargets++; } } S_StartSound (NULL,sfx_bossit); } void A_BrainPain (mobj_t *mo) { S_StartSound (NULL,sfx_bospn); } void A_BrainScream (mobj_t *mo) { int x,y,z; mobj_t *th; for (x=mo->x - 196*FRACUNIT ; x< mo->x + 320*FRACUNIT ; x+= FRACUNIT*8) { y = mo->y - 320*FRACUNIT; z = 128 + P_Random()*2*FRACUNIT; th = P_SpawnMobj (x,y,z, MT_ROCKET); th->momz = P_Random()*512; P_SetMobjState (th, S_BRAINEXPLODE1); th->tics -= P_Random()&7; if (th->tics < 1) th->tics = 1; } S_StartSound (NULL,sfx_bosdth); } void A_BrainExplode (mobj_t *mo) { int x,y,z; mobj_t *th; x = mo->x + (P_Random () - P_Random ())*2048; y = mo->y; z = 128 + P_Random()*2*FRACUNIT; th = P_SpawnMobj (x,y,z, MT_ROCKET); th->momz = P_Random()*512; P_SetMobjState (th, S_BRAINEXPLODE1); th->tics -= P_Random()&7; if (th->tics < 1) th->tics = 1; } void A_BrainDie (mobj_t *mo) { G_ExitLevel (); } void A_BrainSpit (mobj_t *mo) { mobj_t *targ; mobj_t *newmobj; static int easy = 0; easy ^= 1; if (gameskill <= sk_easy && (!easy)) return; // shoot a cube at current target targ = braintargets[braintargeton]; braintargeton = (braintargeton+1)%numbraintargets; // spawn brain missile newmobj = P_SpawnMissile (mo, targ, MT_SPAWNSHOT); newmobj->target = targ; newmobj->reactiontime = ((targ->y - mo->y)/newmobj->momy) / newmobj->state->tics; S_StartSound(NULL, sfx_bospit); } void A_SpawnFly (mobj_t *mo); void A_SpawnSound (mobj_t *mo) // travelling cube sound { S_StartSound (mo,sfx_boscub); A_SpawnFly(mo); } void A_SpawnFly (mobj_t *mo) { mobj_t *newmobj; mobj_t *fog; mobj_t *targ; int r; mobjtype_t type; if (--mo->reactiontime) return; // still flying targ = mo->target; // teleport fog fog = P_SpawnMobj (targ->x, targ->y, targ->z, MT_SPAWNFIRE); S_StartSound (fog, sfx_telept); // monster r = P_Random (); if ( r<50 ) type = MT_TROOP; else if (r<90) type = MT_SERGEANT; else if (r<120) type = MT_SHADOWS; else if (r<130) type = MT_PAIN; else if (r<160) type = MT_HEAD; else if (r<162) type = MT_VILE; else if (r<172) type = MT_UNDEAD; else if (r<192) type = MT_BABY; else if (r<222) type = MT_FATSO; else if (r<246) type = MT_KNIGHT; else type = MT_BRUISER; newmobj = P_SpawnMobj (targ->x, targ->y, targ->z, type); if (P_LookForPlayers (newmobj, true) ) P_SetMobjState (newmobj, newmobj->info->seestate); // telefrag anything in this spot P_TeleportMove (newmobj, newmobj->x, newmobj->y); // remove self P_RemoveMobj (mo); } void A_PlayerScream (mobj_t *mo) { int sound = sfx_pldeth; if (commercial && // IF THE PLAYER DIES LESS THAN -50% WITHOUT GIBBING mo->health < -50) sound = sfx_pdiehi; S_StartSound (mo, sound); } \ No newline at end of file diff --git a/P_FLOOR.C b/P_FLOOR.C new file mode 100644 index 0000000..e03f39d --- /dev/null +++ b/P_FLOOR.C @@ -0,0 +1 @@ +#include "doomdef.h" #include "p_local.h" //================================================================== //================================================================== // // FLOORS // //================================================================== //================================================================== //================================================================== // // Move a plane (floor or ceiling) and check for crushing // //================================================================== result_e T_MovePlane(sector_t *sector,fixed_t speed, fixed_t dest,boolean crush,int floorOrCeiling,int direction) { boolean flag; fixed_t lastpos; switch(floorOrCeiling) { case 0: // FLOOR switch(direction) { case -1: // DOWN if (sector->floorheight - speed < dest) { lastpos = sector->floorheight; sector->floorheight = dest; flag = P_ChangeSector(sector,crush); if (flag == true) { sector->floorheight =lastpos; P_ChangeSector(sector,crush); //return crushed; } return pastdest; } else { lastpos = sector->floorheight; sector->floorheight -= speed; flag = P_ChangeSector(sector,crush); if (flag == true) { sector->floorheight = lastpos; P_ChangeSector(sector,crush); return crushed; } } break; case 1: // UP if (sector->floorheight + speed > dest) { lastpos = sector->floorheight; sector->floorheight = dest; flag = P_ChangeSector(sector,crush); if (flag == true) { sector->floorheight = lastpos; P_ChangeSector(sector,crush); //return crushed; } return pastdest; } else // COULD GET CRUSHED { lastpos = sector->floorheight; sector->floorheight += speed; flag = P_ChangeSector(sector,crush); if (flag == true) { if (crush == true) return crushed; sector->floorheight = lastpos; P_ChangeSector(sector,crush); return crushed; } } break; } break; case 1: // CEILING switch(direction) { case -1: // DOWN if (sector->ceilingheight - speed < dest) { lastpos = sector->ceilingheight; sector->ceilingheight = dest; flag = P_ChangeSector(sector,crush); if (flag == true) { sector->ceilingheight = lastpos; P_ChangeSector(sector,crush); //return crushed; } return pastdest; } else // COULD GET CRUSHED { lastpos = sector->ceilingheight; sector->ceilingheight -= speed; flag = P_ChangeSector(sector,crush); if (flag == true) { if (crush == true) return crushed; sector->ceilingheight = lastpos; P_ChangeSector(sector,crush); return crushed; } } break; case 1: // UP if (sector->ceilingheight + speed > dest) { lastpos = sector->ceilingheight; sector->ceilingheight = dest; flag = P_ChangeSector(sector,crush); if (flag == true) { sector->ceilingheight = lastpos; P_ChangeSector(sector,crush); //return crushed; } return pastdest; } else { lastpos = sector->ceilingheight; sector->ceilingheight += speed; flag = P_ChangeSector(sector,crush); #if 0 if (flag == true) { sector->ceilingheight = lastpos; P_ChangeSector(sector,crush); return crushed; } #endif } break; } break; } return ok; } //================================================================== // // MOVE A FLOOR TO IT'S DESTINATION (UP OR DOWN) // //================================================================== void T_MoveFloor(floormove_t *floor) { result_e res; res = T_MovePlane(floor->sector,floor->speed, floor->floordestheight,floor->crush,0,floor->direction); if (!(leveltime&7)) S_StartSound((mobj_t *)&floor->sector->soundorg,sfx_stnmov); if (res == pastdest) { floor->sector->specialdata = NULL; if (floor->direction == 1) switch(floor->type) { case donutRaise: floor->sector->special = floor->newspecial; floor->sector->floorpic = floor->texture; default: break; } else if (floor->direction == -1) switch(floor->type) { case lowerAndChange: floor->sector->special = floor->newspecial; floor->sector->floorpic = floor->texture; default: break; } P_RemoveThinker(&floor->thinker); S_StartSound((mobj_t *)&floor->sector->soundorg,sfx_pstop); } } //================================================================== // // HANDLE FLOOR TYPES // //================================================================== int EV_DoFloor(line_t *line,floor_e floortype) { int secnum; int rtn; int i; sector_t *sec; floormove_t *floor; secnum = -1; rtn = 0; while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0) { sec = §ors[secnum]; // ALREADY MOVING? IF SO, KEEP GOING... if (sec->specialdata) continue; // // new floor thinker // rtn = 1; floor = Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0); P_AddThinker (&floor->thinker); sec->specialdata = floor; floor->thinker.function = (think_t) T_MoveFloor; floor->type = floortype; floor->crush = false; switch(floortype) { case lowerFloor: floor->direction = -1; floor->sector = sec; floor->speed = FLOORSPEED; floor->floordestheight = P_FindHighestFloorSurrounding(sec); break; case lowerFloorToLowest: floor->direction = -1; floor->sector = sec; floor->speed = FLOORSPEED; floor->floordestheight = P_FindLowestFloorSurrounding(sec); break; case turboLower: floor->direction = -1; floor->sector = sec; floor->speed = FLOORSPEED * 4; floor->floordestheight = P_FindHighestFloorSurrounding(sec); if (floor->floordestheight != sec->floorheight) floor->floordestheight += 8*FRACUNIT; break; case raiseFloorCrush: floor->crush = true; case raiseFloor: floor->direction = 1; floor->sector = sec; floor->speed = FLOORSPEED; floor->floordestheight = P_FindLowestCeilingSurrounding(sec); if (floor->floordestheight > sec->ceilingheight) floor->floordestheight = sec->ceilingheight; floor->floordestheight -= (8*FRACUNIT)* (floortype == raiseFloorCrush); break; case raiseFloorTurbo: floor->direction = 1; floor->sector = sec; floor->speed = FLOORSPEED*4; floor->floordestheight = P_FindNextHighestFloor(sec,sec->floorheight); break; case raiseFloorToNearest: floor->direction = 1; floor->sector = sec; floor->speed = FLOORSPEED; floor->floordestheight = P_FindNextHighestFloor(sec,sec->floorheight); break; case raiseFloor24: floor->direction = 1; floor->sector = sec; floor->speed = FLOORSPEED; floor->floordestheight = floor->sector->floorheight + 24 * FRACUNIT; break; case raiseFloor512: floor->direction = 1; floor->sector = sec; floor->speed = FLOORSPEED; floor->floordestheight = floor->sector->floorheight + 512 * FRACUNIT; break; case raiseFloor24AndChange: floor->direction = 1; floor->sector = sec; floor->speed = FLOORSPEED; floor->floordestheight = floor->sector->floorheight + 24 * FRACUNIT; sec->floorpic = line->frontsector->floorpic; sec->special = line->frontsector->special; break; case raiseToTexture: { int minsize = MAXINT; side_t *side; floor->direction = 1; floor->sector = sec; floor->speed = FLOORSPEED; for (i = 0; i < sec->linecount; i++) if (twoSided (secnum, i) ) { side = getSide(secnum,i,0); if (side->bottomtexture >= 0) if (textureheight[side->bottomtexture] < minsize) minsize = textureheight[side->bottomtexture]; side = getSide(secnum,i,1); if (side->bottomtexture >= 0) if (textureheight[side->bottomtexture] < minsize) minsize = textureheight[side->bottomtexture]; } floor->floordestheight = floor->sector->floorheight + minsize; } break; case lowerAndChange: floor->direction = -1; floor->sector = sec; floor->speed = FLOORSPEED; floor->floordestheight = P_FindLowestFloorSurrounding(sec); floor->texture = sec->floorpic; for (i = 0; i < sec->linecount; i++) if ( twoSided(secnum, i) ) { if (getSide(secnum,i,0)->sector-sectors == secnum) { sec = getSector(secnum,i,1); if (sec->floorheight == floor->floordestheight) { floor->texture = sec->floorpic; floor->newspecial = sec->special; break; } } else { sec = getSector(secnum,i,0); if (sec->floorheight == floor->floordestheight) { floor->texture = sec->floorpic; floor->newspecial = sec->special; break; } } } default: break; } } return rtn; } //================================================================== // // BUILD A STAIRCASE! // //================================================================== int EV_BuildStairs(line_t *line,stair_e type) { int secnum; int height; int i; int newsecnum; int texture; int ok; int rtn; sector_t *sec, *tsec; floormove_t *floor; fixed_t stairsize; fixed_t speed; secnum = -1; rtn = 0; while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0) { sec = §ors[secnum]; // ALREADY MOVING? IF SO, KEEP GOING... if (sec->specialdata) continue; // // new floor thinker // rtn = 1; floor = Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0); P_AddThinker (&floor->thinker); sec->specialdata = floor; floor->thinker.function = (think_t) T_MoveFloor; floor->direction = 1; floor->sector = sec; switch(type) { case build8: speed = FLOORSPEED/4; stairsize = 8*FRACUNIT; break; case turbo16: speed = FLOORSPEED*4; stairsize = 16*FRACUNIT; break; } floor->speed = speed; height = sec->floorheight + stairsize; floor->floordestheight = height; texture = sec->floorpic; // // Find next sector to raise // 1. Find 2-sided line with same sector side[0] // 2. Other side is the next sector to raise // do { ok = 0; for (i = 0;i < sec->linecount;i++) { if ( !((sec->lines[i])->flags & ML_TWOSIDED) ) continue; tsec = (sec->lines[i])->frontsector; newsecnum = tsec-sectors; if (secnum != newsecnum) continue; tsec = (sec->lines[i])->backsector; newsecnum = tsec - sectors; if (tsec->floorpic != texture) continue; height += stairsize; if (tsec->specialdata) continue; sec = tsec; secnum = newsecnum; floor = Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0); P_AddThinker (&floor->thinker); sec->specialdata = floor; floor->thinker.function = (think_t) T_MoveFloor; floor->direction = 1; floor->sector = sec; floor->speed = speed; floor->floordestheight = height; ok = 1; break; } } while(ok); } return rtn; } \ No newline at end of file diff --git a/P_INTER.C b/P_INTER.C new file mode 100644 index 0000000..86486a1 --- /dev/null +++ b/P_INTER.C @@ -0,0 +1 @@ +// P_inter.c #include "doomdef.h" #include "p_local.h" #define BONUSADD 6 // a weapon is found with two clip loads, a big item has five clip loads int maxammo[NUMAMMO] = {200, 50, 300, 50}; int clipammo[NUMAMMO] = {10, 4, 20, 1}; /* =============================================================================== GET STUFF =============================================================================== */ /* =================== = = P_GiveAmmo = = Num is the number of clip loads, not the individual count (0= 1/2 clip) = Returns false if the ammo can't be picked up at all =================== */ boolean P_GiveAmmo (player_t *player, ammotype_t ammo, int num) { int oldammo; if (ammo == am_noammo) return false; if (ammo < 0 || ammo > NUMAMMO) I_Error ("P_GiveAmmo: bad type %i", ammo); if ( player->ammo[ammo] == player->maxammo[ammo] ) return false; if (num) num *= clipammo[ammo]; else num = clipammo[ammo]/2; if (gameskill == sk_baby || gameskill == sk_nightmare) num <<= 1; // give double ammo in trainer mode oldammo = player->ammo[ammo]; player->ammo[ammo] += num; if (player->ammo[ammo] > player->maxammo[ammo]) player->ammo[ammo] = player->maxammo[ammo]; if (oldammo) return true; // don't change up weapons, player was lower on // purpose switch (ammo) { case am_clip: if (player->readyweapon == wp_fist) { if (player->weaponowned[wp_chaingun]) player->pendingweapon = wp_chaingun; else player->pendingweapon = wp_pistol; } break; case am_shell: if (player->readyweapon == wp_fist || player->readyweapon == wp_pistol) { if (player->weaponowned[wp_shotgun]) player->pendingweapon = wp_shotgun; } break; case am_cell: if (player->readyweapon == wp_fist || player->readyweapon == wp_pistol) { if (player->weaponowned[wp_plasma]) player->pendingweapon = wp_plasma; } break; case am_misl: if (player->readyweapon == wp_fist) { if (player->weaponowned[wp_missile]) player->pendingweapon = wp_missile; } default: break; } return true; } /* =================== = = P_GiveWeapon = = The weapon name may have a MF_DROPPED flag ored in =================== */ boolean P_GiveWeapon (player_t *player, weapontype_t weapon, boolean dropped) { boolean gaveammo, gaveweapon; if ( (netgame && deathmatch!=2) && !dropped) { // leave placed weapons forever on net games if (player->weaponowned[weapon]) return false; player->bonuscount += BONUSADD; player->weaponowned[weapon] = true; if (deathmatch) P_GiveAmmo (player, weaponinfo[weapon].ammo, 5); else P_GiveAmmo (player, weaponinfo[weapon].ammo, 2); player->pendingweapon = weapon; if (player == &players[consoleplayer]) S_StartSound (NULL, sfx_wpnup); return false; } if (weaponinfo[weapon].ammo != am_noammo) { // give one clip with a dropped weapon, two clips with a found weapon if (dropped) gaveammo = P_GiveAmmo (player, weaponinfo[weapon].ammo, 1); else gaveammo = P_GiveAmmo (player, weaponinfo[weapon].ammo, 2); } else gaveammo = false; if (player->weaponowned[weapon]) gaveweapon = false; else { gaveweapon = true; player->weaponowned[weapon] = true; player->pendingweapon = weapon; } return gaveweapon || gaveammo; } /* =================== = = P_GiveBody = = Returns false if the body isn't needed at all =================== */ boolean P_GiveBody (player_t *player, int num) { if (player->health >= MAXHEALTH) return false; player->health += num; if (player->health > MAXHEALTH) player->health = MAXHEALTH; player->mo->health = player->health; return true; } /* =================== = = P_GiveArmor = = Returns false if the armor is worse than the current armor =================== */ boolean P_GiveArmor (player_t *player, int armortype) { int hits; hits = armortype*100; if (player->armorpoints >= hits) return false; // don't pick up player->armortype = armortype; player->armorpoints = hits; return true; } /* =================== = = P_GiveCard = =================== */ void P_GiveCard (player_t *player, card_t card) { if (player->cards[card]) return; player->bonuscount = BONUSADD; player->cards[card] = 1; } /* =================== = = P_GivePower = =================== */ boolean P_GivePower (player_t *player, powertype_t power) { if (power == pw_invulnerability) { player->powers[power] = INVULNTICS; return true; } if (power == pw_invisibility) { player->powers[power] = INVISTICS; player->mo->flags |= MF_SHADOW; return true; } if (power == pw_infrared) { player->powers[power] = INFRATICS; return true; } if (power == pw_ironfeet) { player->powers[power] = IRONTICS; return true; } if (power == pw_strength) { P_GiveBody (player, 100); player->powers[power] = 1; return true; } if (player->powers[power]) return false; // already got it player->powers[power] = 1; return true; } /* ================== = = P_TouchSpecialThing = ================== */ void P_TouchSpecialThing (mobj_t *special, mobj_t *toucher) { player_t *player; int i; fixed_t delta; int sound; delta = special->z - toucher->z; if (delta > toucher->height || delta < -8*FRACUNIT) return; // out of reach sound = sfx_itemup; player = toucher->player; if (toucher->health <= 0) return; // can happen with a sliding player corpse switch (special->sprite) { // // armor // case SPR_ARM1: if (!P_GiveArmor (player, 1)) return; player->message = GOTARMOR; break; case SPR_ARM2: if (!P_GiveArmor (player, 2)) return; player->message = GOTMEGA; break; // // bonus items // case SPR_BON1: player->health++; // can go over 100% if (player->health > 200) player->health = 200; player->mo->health = player->health; player->message = GOTHTHBONUS; break; case SPR_BON2: player->armorpoints++; // can go over 100% if (player->armorpoints > 200) player->armorpoints = 200; if (!player->armortype) player->armortype = 1; player->message = GOTARMBONUS; break; case SPR_SOUL: player->health += 100; if (player->health > 200) player->health = 200; player->mo->health = player->health; player->message = GOTSUPER; sound = sfx_getpow; break; case SPR_MEGA: if (!commercial) return; player->health = 200; player->mo->health = player->health; P_GiveArmor (player,2); player->message = GOTMSPHERE; sound = sfx_getpow; break; // // cards // leave cards for everyone case SPR_BKEY: if (!player->cards[it_bluecard]) player->message = GOTBLUECARD; P_GiveCard (player, it_bluecard); if (!netgame) break; return; case SPR_YKEY: if (!player->cards[it_yellowcard]) player->message = GOTYELWCARD; P_GiveCard (player, it_yellowcard); if (!netgame) break; return; case SPR_RKEY: if (!player->cards[it_redcard]) player->message = GOTREDCARD; P_GiveCard (player, it_redcard); if (!netgame) break; return; case SPR_BSKU: if (!player->cards[it_blueskull]) player->message = GOTBLUESKUL; P_GiveCard (player, it_blueskull); if (!netgame) break; return; case SPR_YSKU: if (!player->cards[it_yellowskull]) player->message = GOTYELWSKUL; P_GiveCard (player, it_yellowskull); if (!netgame) break; return; case SPR_RSKU: if (!player->cards[it_redskull]) player->message = GOTREDSKULL; P_GiveCard (player, it_redskull); if (!netgame) break; return; // // heals // case SPR_STIM: if (!P_GiveBody (player, 10)) return; player->message = GOTSTIM; break; case SPR_MEDI: if (!P_GiveBody (player, 25)) return; if (player->health < 25) player->message = GOTMEDINEED; else player->message = GOTMEDIKIT; break; // // power ups // case SPR_PINV: if (!P_GivePower (player, pw_invulnerability)) return; player->message = GOTINVUL; sound = sfx_getpow; break; case SPR_PSTR: if (!P_GivePower (player, pw_strength)) return; player->message = GOTBERSERK; if (player->readyweapon != wp_fist) player->pendingweapon = wp_fist; sound = sfx_getpow; break; case SPR_PINS: if (!P_GivePower (player, pw_invisibility)) return; player->message = GOTINVIS; sound = sfx_getpow; break; case SPR_SUIT: if (!P_GivePower (player, pw_ironfeet)) return; player->message = GOTSUIT; sound = sfx_getpow; break; case SPR_PMAP: if (!P_GivePower (player, pw_allmap)) return; player->message = GOTMAP; sound = sfx_getpow; break; case SPR_PVIS: if (!P_GivePower (player, pw_infrared)) return; player->message = GOTVISOR; sound = sfx_getpow; break; // // ammo // case SPR_CLIP: if (special->flags & MF_DROPPED) { if (!P_GiveAmmo (player,am_clip,0)) return; } else { if (!P_GiveAmmo (player,am_clip,1)) return; } player->message = GOTCLIP; break; case SPR_AMMO: if (!P_GiveAmmo (player, am_clip,5)) return; player->message = GOTCLIPBOX; break; case SPR_ROCK: if (!P_GiveAmmo (player, am_misl,1)) return; player->message = GOTROCKET; break; case SPR_BROK: if (!P_GiveAmmo (player, am_misl,5)) return; player->message = GOTROCKBOX; break; case SPR_CELL: if (!P_GiveAmmo (player, am_cell,1)) return; player->message = GOTCELL; break; case SPR_CELP: if (!P_GiveAmmo (player, am_cell,5)) return; player->message = GOTCELLBOX; break; case SPR_SHEL: if (!P_GiveAmmo (player, am_shell,1)) return; player->message = GOTSHELLS; break; case SPR_SBOX: if (!P_GiveAmmo (player, am_shell,5)) return; player->message = GOTSHELLBOX; break; case SPR_BPAK: if (!player->backpack) { for (i=0 ; imaxammo[i] *= 2; player->backpack = true; } for (i=0 ; imessage = GOTBACKPACK; break; // // weapons // case SPR_BFUG: if (!P_GiveWeapon (player, wp_bfg, false) ) return; player->message = GOTBFG9000; sound = sfx_wpnup; break; case SPR_MGUN: if (!P_GiveWeapon (player, wp_chaingun, special->flags&MF_DROPPED) ) return; player->message = GOTCHAINGUN; sound = sfx_wpnup; break; case SPR_CSAW: if (!P_GiveWeapon (player, wp_chainsaw, false) ) return; player->message = GOTCHAINSAW; sound = sfx_wpnup; break; case SPR_LAUN: if (!P_GiveWeapon (player, wp_missile, false) ) return; player->message = GOTLAUNCHER; sound = sfx_wpnup; break; case SPR_PLAS: if (!P_GiveWeapon (player, wp_plasma, false) ) return; player->message = GOTPLASMA; sound = sfx_wpnup; break; case SPR_SHOT: if (!P_GiveWeapon (player, wp_shotgun, special->flags&MF_DROPPED ) ) return; player->message = GOTSHOTGUN; sound = sfx_wpnup; break; case SPR_SGN2: if (!P_GiveWeapon (player, wp_supershotgun, special->flags&MF_DROPPED ) ) return; player->message = GOTSHOTGUN2; sound = sfx_wpnup; break; default: I_Error ("P_SpecialThing: Unknown gettable thing"); } if (special->flags & MF_COUNTITEM) player->itemcount++; P_RemoveMobj (special); player->bonuscount += BONUSADD; if (player == &players[consoleplayer]) S_StartSound (NULL, sound); } /* ============== = = KillMobj = ============== */ void P_KillMobj (mobj_t *source, mobj_t *target) { mobjtype_t item; mobj_t *mo; target->flags &= ~(MF_SHOOTABLE|MF_FLOAT|MF_SKULLFLY); if (target->type != MT_SKULL) target->flags &= ~MF_NOGRAVITY; target->flags |= MF_CORPSE|MF_DROPOFF; target->height >>= 2; if (source && source->player) { if (target->flags & MF_COUNTKILL) source->player->killcount++; // count for intermission if (target->player) source->player->frags[target->player-players]++; } else if (!netgame && (target->flags & MF_COUNTKILL) ) players[0].killcount++; // count all monster deaths, even // those caused by other monsters if (target->player) { if (!source) // count environment kills against you target->player->frags[target->player-players]++; target->flags &= ~MF_SOLID; target->player->playerstate = PST_DEAD; P_DropWeapon (target->player); if (target->player == &players[consoleplayer] && automapactive) AM_Stop (); // don't die in auto map } if (target->health < -target->info->spawnhealth && target->info->xdeathstate) P_SetMobjState (target, target->info->xdeathstate); else P_SetMobjState (target, target->info->deathstate); target->tics -= P_Random()&3; if (target->tics < 1) target->tics = 1; // I_StartSound (&actor->r, actor->info->deathsound); // // drop stuff // switch (target->type) { case MT_WOLFSS: case MT_POSSESSED: item = MT_CLIP; break; case MT_SHOTGUY: item = MT_SHOTGUN; break; case MT_CHAINGUY: item = MT_CHAINGUN; break; default: return; } mo = P_SpawnMobj (target->x,target->y,ONFLOORZ, item); mo->flags |= MF_DROPPED; // special versions of items } /* ================= = = P_DamageMobj = = Damages both enemies and players = inflictor is the thing that caused the damage = creature or missile, can be NULL (slime, etc) = source is the thing to target after taking damage = creature or NULL = Source and inflictor are the same for melee attacks = source can be null for barrel explosions and other environmental stuff ================== */ void P_DamageMobj (mobj_t *target, mobj_t *inflictor, mobj_t *source, int damage) { unsigned ang; int saved; player_t *player; fixed_t thrust; int temp; if ( !(target->flags & MF_SHOOTABLE) ) return; // shouldn't happen... if (target->health <= 0) return; if ( target->flags & MF_SKULLFLY ) { target->momx = target->momy = target->momz = 0; } player = target->player; if (player && gameskill == sk_baby) damage >>= 1; // take half damage in trainer mode // // kick away unless using the chainsaw // if (inflictor && !(target->flags & MF_NOCLIP) && (!source || !source->player || source->player->readyweapon != wp_chainsaw)) { ang = R_PointToAngle2 ( inflictor->x, inflictor->y ,target->x, target->y); thrust = damage*(FRACUNIT>>3)*100/target->info->mass; // make fall forwards sometimes if ( damage < 40 && damage > target->health && target->z - inflictor->z > 64*FRACUNIT && (P_Random ()&1) ) { ang += ANG180; thrust *= 4; } ang >>= ANGLETOFINESHIFT; target->momx += FixedMul (thrust, finecosine[ang]); target->momy += FixedMul (thrust, finesine[ang]); } // // player specific // if (player) { // end of game hell hack if (target->subsector->sector->special == 11 && damage >= target->health) damage = target->health - 1; if ( damage < 1000 && ( (player->cheats&CF_GODMODE)||player->powers[pw_invulnerability] ) ) return; if (player->armortype) { if (player->armortype == 1) saved = damage/3; else saved = damage/2; if (player->armorpoints <= saved) { // armor is used up saved = player->armorpoints; player->armortype = 0; } player->armorpoints -= saved; damage -= saved; } player->health -= damage; // mirror mobj health here for Dave if (player->health < 0) player->health = 0; player->attacker = source; player->damagecount += damage; // add damage after armor / invuln if (player->damagecount > 100) player->damagecount = 100; // teleport stomp does 10k points... temp = damage < 100 ? damage : 100; if (player == &players[consoleplayer]) I_Tactile (40,10,40+temp*2); } // // do the damage // target->health -= damage; if (target->health <= 0) { P_KillMobj (source, target); return; } if ( (P_Random () < target->info->painchance) && !(target->flags&MF_SKULLFLY) ) { target->flags |= MF_JUSTHIT; // fight back! P_SetMobjState (target, target->info->painstate); } target->reactiontime = 0; // we're awake now... if ( (!target->threshold || target->type == MT_VILE) && source && source != target && source->type != MT_VILE) { // if not intent on another player, chase after this one target->target = source; target->threshold = BASETHRESHOLD; if (target->state == &states[target->info->spawnstate] && target->info->seestate != S_NULL) P_SetMobjState (target, target->info->seestate); } } \ No newline at end of file diff --git a/P_LIGHTS.C b/P_LIGHTS.C new file mode 100644 index 0000000..5135d66 --- /dev/null +++ b/P_LIGHTS.C @@ -0,0 +1 @@ +#include "doomdef.h" #include "p_local.h" //================================================================== //================================================================== // // FIRELIGHT FLICKER // //================================================================== //================================================================== //================================================================== // // T_FireFlicker // //================================================================== void T_FireFlicker (fireflicker_t *flick) { int amount; if (--flick->count) return; amount = (P_Random()&3)*16; if (flick->sector->lightlevel - amount < flick->minlight) flick->sector->lightlevel = flick->minlight; else flick->sector->lightlevel = flick->maxlight - amount; flick->count = 4; } //================================================================== // // P_SpawnFireFlicker // //================================================================== void P_SpawnFireFlicker (sector_t *sector) { fireflicker_t *flick; sector->special = 0; // nothing special about it during gameplay flick = Z_Malloc ( sizeof(*flick), PU_LEVSPEC, 0); P_AddThinker (&flick->thinker); flick->thinker.function = (think_t) T_FireFlicker; flick->sector = sector; flick->maxlight = sector->lightlevel; flick->minlight = P_FindMinSurroundingLight(sector,sector->lightlevel)+16; flick->count = 4; } //================================================================== //================================================================== // // BROKEN LIGHT FLASHING // //================================================================== //================================================================== //================================================================== // // T_LightFlash // // After the map has been loaded, scan each sector for specials // that spawn thinkers // //================================================================== void T_LightFlash (lightflash_t *flash) { if (--flash->count) return; if (flash->sector->lightlevel == flash->maxlight) { flash-> sector->lightlevel = flash->minlight; flash->count = (P_Random()&flash->mintime)+1; } else { flash-> sector->lightlevel = flash->maxlight; flash->count = (P_Random()&flash->maxtime)+1; } } //================================================================== // // P_SpawnLightFlash // // After the map has been loaded, scan each sector for specials that spawn thinkers // //================================================================== void P_SpawnLightFlash (sector_t *sector) { lightflash_t *flash; sector->special = 0; // nothing special about it during gameplay flash = Z_Malloc ( sizeof(*flash), PU_LEVSPEC, 0); P_AddThinker (&flash->thinker); flash->thinker.function = (think_t) T_LightFlash; flash->sector = sector; flash->maxlight = sector->lightlevel; flash->minlight = P_FindMinSurroundingLight(sector,sector->lightlevel); flash->maxtime = 64; flash->mintime = 7; flash->count = (P_Random()&flash->maxtime)+1; } //================================================================== // // STROBE LIGHT FLASHING // //================================================================== //================================================================== // // T_StrobeFlash // // After the map has been loaded, scan each sector for specials that spawn thinkers // //================================================================== void T_StrobeFlash (strobe_t *flash) { if (--flash->count) return; if (flash->sector->lightlevel == flash->minlight) { flash-> sector->lightlevel = flash->maxlight; flash->count = flash->brighttime; } else { flash-> sector->lightlevel = flash->minlight; flash->count =flash->darktime; } } //================================================================== // // P_SpawnLightFlash // // After the map has been loaded, scan each sector for specials that spawn thinkers // //================================================================== void P_SpawnStrobeFlash (sector_t *sector,int fastOrSlow, int inSync) { strobe_t *flash; flash = Z_Malloc ( sizeof(*flash), PU_LEVSPEC, 0); P_AddThinker (&flash->thinker); flash->sector = sector; flash->darktime = fastOrSlow; flash->brighttime = STROBEBRIGHT; flash->thinker.function = (think_t) T_StrobeFlash; flash->maxlight = sector->lightlevel; flash->minlight = P_FindMinSurroundingLight(sector, sector->lightlevel); if (flash->minlight == flash->maxlight) flash->minlight = 0; sector->special = 0; // nothing special about it during gameplay if (!inSync) flash->count = (P_Random()&7)+1; else flash->count = 1; } //================================================================== // // Start strobing lights (usually from a trigger) // //================================================================== void EV_StartLightStrobing(line_t *line) { int secnum; sector_t *sec; secnum = -1; while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0) { sec = §ors[secnum]; if (sec->specialdata) continue; P_SpawnStrobeFlash (sec,SLOWDARK, 0); } } //================================================================== // // TURN LINE'S TAG LIGHTS OFF // //================================================================== void EV_TurnTagLightsOff(line_t *line) { int i; int j; int min; sector_t *sector; sector_t *tsec; line_t *templine; sector = sectors; for (j = 0;j < numsectors; j++, sector++) if (sector->tag == line->tag) { min = sector->lightlevel; for (i = 0;i < sector->linecount; i++) { templine = sector->lines[i]; tsec = getNextSector(templine,sector); if (!tsec) continue; if (tsec->lightlevel < min) min = tsec->lightlevel; } sector->lightlevel = min; } } //================================================================== // // TURN LINE'S TAG LIGHTS ON // //================================================================== void EV_LightTurnOn(line_t *line, int bright) { int i; int j; sector_t *sector; sector_t *temp; line_t *templine; sector = sectors; for (i=0;itag == line->tag) { // // bright = 0 means to search for highest // light level surrounding sector // if (!bright) { for (j = 0;j < sector->linecount; j++) { templine = sector->lines[j]; temp = getNextSector(templine,sector); if (!temp) continue; if (temp->lightlevel > bright) bright = temp->lightlevel; } } sector-> lightlevel = bright; } } //================================================================== // // Spawn glowing light // //================================================================== void T_Glow(glow_t *g) { switch(g->direction) { case -1: // DOWN g->sector->lightlevel -= GLOWSPEED; if (g->sector->lightlevel <= g->minlight) { g->sector->lightlevel += GLOWSPEED; g->direction = 1; } break; case 1: // UP g->sector->lightlevel += GLOWSPEED; if (g->sector->lightlevel >= g->maxlight) { g->sector->lightlevel -= GLOWSPEED; g->direction = -1; } break; } } void P_SpawnGlowingLight(sector_t *sector) { glow_t *g; g = Z_Malloc( sizeof(*g), PU_LEVSPEC, 0); P_AddThinker(&g->thinker); g->sector = sector; g->minlight = P_FindMinSurroundingLight(sector,sector->lightlevel); g->maxlight = sector->lightlevel; g->thinker.function = (think_t) T_Glow; g->direction = -1; sector->special = 0; } \ No newline at end of file diff --git a/P_LOCAL.H b/P_LOCAL.H new file mode 100644 index 0000000..3275668 --- /dev/null +++ b/P_LOCAL.H @@ -0,0 +1 @@ +// P_local.h #ifndef __P_LOCAL__ #define __P_LOCAL__ #ifndef __R_LOCAL__ #include "r_local.h" #endif #define FLOATSPEED (FRACUNIT*4) #define MAXHEALTH 100 #define VIEWHEIGHT (41*FRACUNIT) // mapblocks are used to check movement against lines and things #define MAPBLOCKUNITS 128 #define MAPBLOCKSIZE (MAPBLOCKUNITS*FRACUNIT) #define MAPBLOCKSHIFT (FRACBITS+7) #define MAPBMASK (MAPBLOCKSIZE-1) #define MAPBTOFRAC (MAPBLOCKSHIFT-FRACBITS) // player radius for movement checking #define PLAYERRADIUS 16*FRACUNIT // MAXRADIUS is for precalculated sector block boxes // the spider demon is larger, but we don't have any moving sectors // nearby #define MAXRADIUS 32*FRACUNIT #define GRAVITY FRACUNIT #define MAXMOVE (30*FRACUNIT) #define USERANGE (64*FRACUNIT) #define MELEERANGE (64*FRACUNIT) #define MISSILERANGE (32*64*FRACUNIT) typedef enum { DI_EAST, DI_NORTHEAST, DI_NORTH, DI_NORTHWEST, DI_WEST, DI_SOUTHWEST, DI_SOUTH, DI_SOUTHEAST, DI_NODIR, NUMDIRS } dirtype_t; #define BASETHRESHOLD 100 // follow a player exlusively for 3 seconds /* =============================================================================== P_TICK =============================================================================== */ extern thinker_t thinkercap; // both the head and tail of the thinker list void P_InitThinkers (void); void P_AddThinker (thinker_t *thinker); void P_RemoveThinker (thinker_t *thinker); /* =============================================================================== P_PSPR =============================================================================== */ void P_SetupPsprites (player_t *curplayer); void P_MovePsprites (player_t *curplayer); void P_DropWeapon (player_t *player); /* =============================================================================== P_USER =============================================================================== */ void P_PlayerThink (player_t *player); /* =============================================================================== P_MOBJ =============================================================================== */ #define ONFLOORZ MININT #define ONCEILINGZ MAXINT #define ITEMQUESIZE 128 // for item respawning extern mapthing_t itemrespawnque[ITEMQUESIZE]; extern int itemrespawntime[ITEMQUESIZE]; extern int iquehead, iquetail; void P_RespawnSpecials (void); mobj_t *P_SpawnMobj (fixed_t x, fixed_t y, fixed_t z, mobjtype_t type); void P_RemoveMobj (mobj_t *th); boolean P_SetMobjState (mobj_t *mobj, statenum_t state); void P_MobjThinker (mobj_t *mobj); void P_SpawnPuff (fixed_t x, fixed_t y, fixed_t z); void P_SpawnBlood (fixed_t x, fixed_t y, fixed_t z, int damage); mobj_t *P_SpawnMissile (mobj_t *source, mobj_t *dest, mobjtype_t type); void P_SpawnPlayerMissile (mobj_t *source, mobjtype_t type); /* =============================================================================== P_ENEMY =============================================================================== */ void P_NoiseAlert (mobj_t *target, mobj_t *emmiter); /* =============================================================================== P_MAPUTL =============================================================================== */ typedef struct { fixed_t x,y, dx, dy; } divline_t; typedef struct { fixed_t frac; // along trace line boolean isaline; union { mobj_t *thing; line_t *line; } d; } intercept_t; #define MAXINTERCEPTS 128 extern intercept_t intercepts[MAXINTERCEPTS], *intercept_p; typedef boolean (*traverser_t) (intercept_t *in); fixed_t P_AproxDistance (fixed_t dx, fixed_t dy); int P_PointOnLineSide (fixed_t x, fixed_t y, line_t *line); int P_PointOnDivlineSide (fixed_t x, fixed_t y, divline_t *line); void P_MakeDivline (line_t *li, divline_t *dl); fixed_t P_InterceptVector (divline_t *v2, divline_t *v1); int P_BoxOnLineSide (fixed_t *tmbox, line_t *ld); extern fixed_t opentop, openbottom, openrange; extern fixed_t lowfloor; void P_LineOpening (line_t *linedef); boolean P_BlockLinesIterator (int x, int y, boolean(*func)(line_t*) ); boolean P_BlockThingsIterator (int x, int y, boolean(*func)(mobj_t*) ); #define PT_ADDLINES 1 #define PT_ADDTHINGS 2 #define PT_EARLYOUT 4 extern divline_t trace; boolean P_PathTraverse (fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2, int flags, boolean (*trav) (intercept_t *)); void P_UnsetThingPosition (mobj_t *thing); void P_SetThingPosition (mobj_t *thing); /* =============================================================================== P_MAP =============================================================================== */ extern boolean floatok; // if true, move would be ok if extern fixed_t tmfloorz, tmceilingz; // within tmfloorz - tmceilingz extern line_t *ceilingline; boolean P_CheckPosition (mobj_t *thing, fixed_t x, fixed_t y); boolean P_TryMove (mobj_t *thing, fixed_t x, fixed_t y); boolean P_TeleportMove (mobj_t *thing, fixed_t x, fixed_t y); void P_SlideMove (mobj_t *mo); boolean P_CheckSight (mobj_t *t1, mobj_t *t2); void P_UseLines (player_t *player); boolean P_ChangeSector (sector_t *sector, boolean crunch); extern mobj_t *linetarget; // who got hit (or NULL) fixed_t P_AimLineAttack (mobj_t *t1, angle_t angle, fixed_t distance); void P_LineAttack (mobj_t *t1, angle_t angle, fixed_t distance, fixed_t slope, int damage); void P_RadiusAttack (mobj_t *spot, mobj_t *source, int damage); /* =============================================================================== P_SETUP =============================================================================== */ extern byte *rejectmatrix; // for fast sight rejection extern short *blockmaplump; // offsets in blockmap are from here extern short *blockmap; extern int bmapwidth, bmapheight; // in mapblocks extern fixed_t bmaporgx, bmaporgy; // origin of block map extern mobj_t **blocklinks; // for thing chains /* =============================================================================== P_INTER =============================================================================== */ extern int maxammo[NUMAMMO]; extern int clipammo[NUMAMMO]; void P_TouchSpecialThing (mobj_t *special, mobj_t *toucher); void P_DamageMobj (mobj_t *target, mobj_t *inflictor, mobj_t *source, int damage); #include "p_spec.h" #endif // __P_LOCAL__ \ No newline at end of file diff --git a/P_MAP.C b/P_MAP.C new file mode 100644 index 0000000..268a816 --- /dev/null +++ b/P_MAP.C @@ -0,0 +1 @@ +// P_map.c #include "doomdef.h" #include "p_local.h" /* =============================================================================== NOTES: =============================================================================== */ /* =============================================================================== mobj_t NOTES mobj_ts are used to tell the refresh where to draw an image, tell the world simulation when objects are contacted, and tell the sound driver how to position a sound. The refresh uses the next and prev links to follow lists of things in sectors as they are being drawn. The sprite, frame, and angle elements determine which patch_t is used to draw the sprite if it is visible. The sprite and frame values are allmost allways set from state_t structures. The statescr.exe utility generates the states.h and states.c files that contain the sprite/frame numbers from the statescr.txt source file. The xyz origin point represents a point at the bottom middle of the sprite (between the feet of a biped). This is the default origin position for patch_ts grabbed with lumpy.exe. A walking creature will have its z equal to the floor it is standing on. The sound code uses the x,y, and subsector fields to do stereo positioning of any sound effited by the mobj_t. The play simulation uses the blocklinks, x,y,z, radius, height to determine when mobj_ts are touching each other, touching lines in the map, or hit by trace lines (gunshots, lines of sight, etc). The mobj_t->flags element has various bit flags used by the simulation. Every mobj_t is linked into a single sector based on it's origin coordinates. The subsector_t is found with R_PointInSubsector(x,y), and the sector_t can be found with subsector->sector. The sector links are only used by the rendering code, the play simulation does not care about them at all. Any mobj_t that needs to be acted upon be something else in the play world (block movement, be shot, etc) will also need to be linked into the blockmap. If the thing has the MF_NOBLOCK flag set, it will not use the block links. It can still interact with other things, but only as the instigator (missiles will run into other things, but nothing can run into a missile). Each block in the grid is 128*128 units, and knows about every line_t that it contains a piece of, and every interactable mobj_t that has it's origin contained. A valid mobj_t is a mobj_t that has the proper subsector_t filled in for it's xy coordinates and is linked into the subsector's sector or has the MF_NOSECTOR flag set (the subsector_t needs to be valid even if MF_NOSECTOR is set), and is linked into a blockmap block or has the MF_NOBLOCKMAP flag set. Links should only be modified by the P_[Un]SetThingPosition () functions. Do not change the MF_NO? flags while a thing is valid. =============================================================================== */ fixed_t tmbbox[4]; mobj_t *tmthing; int tmflags; fixed_t tmx, tmy; boolean floatok; // if true, move would be ok if // within tmfloorz - tmceilingz fixed_t tmfloorz, tmceilingz, tmdropoffz; // keep track of the line that lowers the ceiling, so missiles don't explode // against sky hack walls line_t *ceilingline; // keep track of special lines as they are hit, but don't process them // until the move is proven valid #define MAXSPECIALCROSS 8 line_t *spechit[MAXSPECIALCROSS]; int numspechit; /* =============================================================================== TELEPORT MOVE =============================================================================== */ /* ================== = = PIT_StompThing = ================== */ boolean PIT_StompThing (mobj_t *thing) { fixed_t blockdist; if (!(thing->flags & MF_SHOOTABLE) ) return true; blockdist = thing->radius + tmthing->radius; if ( abs(thing->x - tmx) >= blockdist || abs(thing->y - tmy) >= blockdist ) return true; // didn't hit it if (thing == tmthing) return true; // don't clip against self if ( !tmthing->player && gamemap != 30) return false; // monsters don't stomp things except on boss level P_DamageMobj (thing, tmthing, tmthing, 10000); return true; } /* =================== = = P_TeleportMove = =================== */ boolean P_TeleportMove (mobj_t *thing, fixed_t x, fixed_t y) { int xl,xh,yl,yh,bx,by; subsector_t *newsubsec; // // kill anything occupying the position // tmthing = thing; tmflags = thing->flags; tmx = x; tmy = y; tmbbox[BOXTOP] = y + tmthing->radius; tmbbox[BOXBOTTOM] = y - tmthing->radius; tmbbox[BOXRIGHT] = x + tmthing->radius; tmbbox[BOXLEFT] = x - tmthing->radius; newsubsec = R_PointInSubsector (x,y); ceilingline = NULL; // // the base floor / ceiling is from the subsector that contains the // point. Any contacted lines the step closer together will adjust them // tmfloorz = tmdropoffz = newsubsec->sector->floorheight; tmceilingz = newsubsec->sector->ceilingheight; validcount++; numspechit = 0; // // stomp on any things contacted // xl = (tmbbox[BOXLEFT] - bmaporgx - MAXRADIUS)>>MAPBLOCKSHIFT; xh = (tmbbox[BOXRIGHT] - bmaporgx + MAXRADIUS)>>MAPBLOCKSHIFT; yl = (tmbbox[BOXBOTTOM] - bmaporgy - MAXRADIUS)>>MAPBLOCKSHIFT; yh = (tmbbox[BOXTOP] - bmaporgy + MAXRADIUS)>>MAPBLOCKSHIFT; for (bx=xl ; bx<=xh ; bx++) for (by=yl ; by<=yh ; by++) if (!P_BlockThingsIterator(bx,by,PIT_StompThing)) return false; // // the move is ok, so link the thing into its new position // P_UnsetThingPosition (thing); thing->floorz = tmfloorz; thing->ceilingz = tmceilingz; thing->x = x; thing->y = y; P_SetThingPosition (thing); return true; } /* =============================================================================== MOVEMENT ITERATOR FUNCTIONS =============================================================================== */ /* ================== = = PIT_CheckLine = = Adjusts tmfloorz and tmceilingz as lines are contacted ================== */ boolean PIT_CheckLine (line_t *ld) { if (tmbbox[BOXRIGHT] <= ld->bbox[BOXLEFT] || tmbbox[BOXLEFT] >= ld->bbox[BOXRIGHT] || tmbbox[BOXTOP] <= ld->bbox[BOXBOTTOM] || tmbbox[BOXBOTTOM] >= ld->bbox[BOXTOP] ) return true; if (P_BoxOnLineSide (tmbbox, ld) != -1) return true; // a line has been hit /* = = The moving thing's destination position will cross the given line. = If this should not be allowed, return false. = If the line is special, keep track of it to process later if the move = is proven ok. NOTE: specials are NOT sorted by order, so two special lines = that are only 8 pixels apart could be crossed in either order. */ if (!ld->backsector) return false; // one sided line if (!(tmthing->flags & MF_MISSILE) ) { if ( ld->flags & ML_BLOCKING ) return false; // explicitly blocking everything if ( !tmthing->player && ld->flags & ML_BLOCKMONSTERS ) return false; // block monsters only } P_LineOpening (ld); // set openrange, opentop, openbottom // adjust floor / ceiling heights if (opentop < tmceilingz) { tmceilingz = opentop; ceilingline = ld; } if (openbottom > tmfloorz) tmfloorz = openbottom; if (lowfloor < tmdropoffz) tmdropoffz = lowfloor; // if contacted a special line, add it to the list if (ld->special) { spechit[numspechit] = ld; numspechit++; } return true; } /* ================== = = PIT_CheckThing = ================== */ boolean PIT_CheckThing (mobj_t *thing) { fixed_t blockdist; boolean solid; int damage; if (!(thing->flags & (MF_SOLID|MF_SPECIAL|MF_SHOOTABLE) )) return true; blockdist = thing->radius + tmthing->radius; if ( abs(thing->x - tmx) >= blockdist || abs(thing->y - tmy) >= blockdist ) return true; // didn't hit it if (thing == tmthing) return true; // don't clip against self // // check for skulls slamming into things // if (tmthing->flags & MF_SKULLFLY) { damage = ((P_Random()%8)+1)*tmthing->info->damage; P_DamageMobj (thing, tmthing, tmthing, damage); tmthing->flags &= ~MF_SKULLFLY; tmthing->momx = tmthing->momy = tmthing->momz = 0; P_SetMobjState (tmthing, tmthing->info->spawnstate); return false; // stop moving } // // missiles can hit other things // if (tmthing->flags & MF_MISSILE) { // see if it went over / under if (tmthing->z > thing->z + thing->height) return true; // overhead if (tmthing->z+tmthing->height < thing->z) return true; // underneath if (tmthing->target && ( tmthing->target->type == thing->type || (tmthing->target->type == MT_KNIGHT && thing->type == MT_BRUISER)|| (tmthing->target->type == MT_BRUISER && thing->type == MT_KNIGHT) ) ) { // don't hit same species as originator if (thing == tmthing->target) return true; if (thing->type != MT_PLAYER) return false; // explode, but do no damage // let players missile other players } if (! (thing->flags & MF_SHOOTABLE) ) return !(thing->flags & MF_SOLID); // didn't do any damage // damage / explode damage = ((P_Random()%8)+1)*tmthing->info->damage; P_DamageMobj (thing, tmthing, tmthing->target, damage); return false; // don't traverse any more } // // check for special pickup // if (thing->flags & MF_SPECIAL) { solid = thing->flags&MF_SOLID; if (tmflags&MF_PICKUP) P_TouchSpecialThing (thing, tmthing); // can remove thing return !solid; } return !(thing->flags & MF_SOLID); } /* =============================================================================== MOVEMENT CLIPPING =============================================================================== */ /* ================== = = P_CheckPosition = = This is purely informative, nothing is modified (except things picked up) in: a mobj_t (can be valid or invalid) a position to be checked (doesn't need to be related to the mobj_t->x,y) during: special things are touched if MF_PICKUP early out on solid lines? out: newsubsec floorz ceilingz tmdropoffz the lowest point contacted (monsters won't move to a dropoff) speciallines[] numspeciallines ================== */ boolean P_CheckPosition (mobj_t *thing, fixed_t x, fixed_t y) { int xl,xh,yl,yh,bx,by; subsector_t *newsubsec; tmthing = thing; tmflags = thing->flags; tmx = x; tmy = y; tmbbox[BOXTOP] = y + tmthing->radius; tmbbox[BOXBOTTOM] = y - tmthing->radius; tmbbox[BOXRIGHT] = x + tmthing->radius; tmbbox[BOXLEFT] = x - tmthing->radius; newsubsec = R_PointInSubsector (x,y); ceilingline = NULL; // // the base floor / ceiling is from the subsector that contains the // point. Any contacted lines the step closer together will adjust them // tmfloorz = tmdropoffz = newsubsec->sector->floorheight; tmceilingz = newsubsec->sector->ceilingheight; validcount++; numspechit = 0; if ( tmflags & MF_NOCLIP ) return true; // // check things first, possibly picking things up // the bounding box is extended by MAXRADIUS because mobj_ts are grouped // into mapblocks based on their origin point, and can overlap into adjacent // blocks by up to MAXRADIUS units // xl = (tmbbox[BOXLEFT] - bmaporgx - MAXRADIUS)>>MAPBLOCKSHIFT; xh = (tmbbox[BOXRIGHT] - bmaporgx + MAXRADIUS)>>MAPBLOCKSHIFT; yl = (tmbbox[BOXBOTTOM] - bmaporgy - MAXRADIUS)>>MAPBLOCKSHIFT; yh = (tmbbox[BOXTOP] - bmaporgy + MAXRADIUS)>>MAPBLOCKSHIFT; for (bx=xl ; bx<=xh ; bx++) for (by=yl ; by<=yh ; by++) if (!P_BlockThingsIterator(bx,by,PIT_CheckThing)) return false; // // check lines // xl = (tmbbox[BOXLEFT] - bmaporgx)>>MAPBLOCKSHIFT; xh = (tmbbox[BOXRIGHT] - bmaporgx)>>MAPBLOCKSHIFT; yl = (tmbbox[BOXBOTTOM] - bmaporgy)>>MAPBLOCKSHIFT; yh = (tmbbox[BOXTOP] - bmaporgy)>>MAPBLOCKSHIFT; for (bx=xl ; bx<=xh ; bx++) for (by=yl ; by<=yh ; by++) if (!P_BlockLinesIterator (bx,by,PIT_CheckLine)) return false; return true; } /* =================== = = P_TryMove = = Attempt to move to a new position, crossing special lines unless MF_TELEPORT = is set = =================== */ boolean P_TryMove (mobj_t *thing, fixed_t x, fixed_t y) { fixed_t oldx, oldy; int side, oldside; line_t *ld; floatok = false; if (!P_CheckPosition (thing, x, y)) return false; // solid wall or thing if ( !(thing->flags & MF_NOCLIP) ) { if (tmceilingz - tmfloorz < thing->height) return false; // doesn't fit floatok = true; if ( !(thing->flags&MF_TELEPORT) &&tmceilingz - thing->z < thing->height) return false; // mobj must lower itself to fit if ( !(thing->flags&MF_TELEPORT) && tmfloorz - thing->z > 24*FRACUNIT ) return false; // too big a step up if ( !(thing->flags&(MF_DROPOFF|MF_FLOAT)) && tmfloorz - tmdropoffz > 24*FRACUNIT ) return false; // don't stand over a dropoff } // // the move is ok, so link the thing into its new position // P_UnsetThingPosition (thing); oldx = thing->x; oldy = thing->y; thing->floorz = tmfloorz; thing->ceilingz = tmceilingz; thing->x = x; thing->y = y; P_SetThingPosition (thing); // // if any special lines were hit, do the effect // if (! (thing->flags&(MF_TELEPORT|MF_NOCLIP)) ) while (numspechit--) { // see if the line was crossed ld = spechit[numspechit]; side = P_PointOnLineSide (thing->x, thing->y, ld); oldside = P_PointOnLineSide (oldx, oldy, ld); if (side != oldside) { if (ld->special) P_CrossSpecialLine (ld-lines, oldside, thing); } } return true; } /* ================== = = P_ThingHeightClip = = Takes a valid thing and adjusts the thing->floorz, thing->ceilingz, = anf possibly thing->z = = This is called for all nearby monsters whenever a sector changes height = = If the thing doesn't fit, the z will be set to the lowest value and = false will be returned ================== */ boolean P_ThingHeightClip (mobj_t *thing) { boolean onfloor; onfloor = (thing->z == thing->floorz); P_CheckPosition (thing, thing->x, thing->y); // what about stranding a monster partially off an edge? thing->floorz = tmfloorz; thing->ceilingz = tmceilingz; if (onfloor) // walking monsters rise and fall with the floor thing->z = thing->floorz; else { // don't adjust a floating monster unless forced to if (thing->z+thing->height > thing->ceilingz) thing->z = thing->ceilingz - thing->height; } if (thing->ceilingz - thing->floorz < thing->height) return false; return true; } /* ============================================================================== SLIDE MOVE Allows the player to slide along any angled walls ============================================================================== */ fixed_t bestslidefrac, secondslidefrac; line_t *bestslideline, *secondslideline; mobj_t *slidemo; fixed_t tmxmove, tmymove; /* ================== = = P_HitSlideLine = = Adjusts the xmove / ymove so that the next move will slide along the wall ================== */ void P_HitSlideLine (line_t *ld) { int side; angle_t lineangle, moveangle, deltaangle; fixed_t movelen, newlen; if (ld->slopetype == ST_HORIZONTAL) { tmymove = 0; return; } if (ld->slopetype == ST_VERTICAL) { tmxmove = 0; return; } side = P_PointOnLineSide (slidemo->x, slidemo->y, ld); lineangle = R_PointToAngle2 (0,0, ld->dx, ld->dy); if (side == 1) lineangle += ANG180; moveangle = R_PointToAngle2 (0,0, tmxmove, tmymove); deltaangle = moveangle-lineangle; if (deltaangle > ANG180) deltaangle += ANG180; // I_Error ("SlideLine: ang>ANG180"); lineangle >>= ANGLETOFINESHIFT; deltaangle >>= ANGLETOFINESHIFT; movelen = P_AproxDistance (tmxmove, tmymove); newlen = FixedMul (movelen, finecosine[deltaangle]); tmxmove = FixedMul (newlen, finecosine[lineangle]); tmymove = FixedMul (newlen, finesine[lineangle]); } /* ============== = = PTR_SlideTraverse = ============== */ boolean PTR_SlideTraverse (intercept_t *in) { line_t *li; if (!in->isaline) I_Error ("PTR_SlideTraverse: not a line?"); li = in->d.line; if ( ! (li->flags & ML_TWOSIDED) ) { if (P_PointOnLineSide (slidemo->x, slidemo->y, li)) return true; // don't hit the back side goto isblocking; } P_LineOpening (li); // set openrange, opentop, openbottom if (openrange < slidemo->height) goto isblocking; // doesn't fit if (opentop - slidemo->z < slidemo->height) goto isblocking; // mobj is too high if (openbottom - slidemo->z > 24*FRACUNIT ) goto isblocking; // too big a step up return true; // this line doesn't block movement // the line does block movement, see if it is closer than best so far isblocking: if (in->frac < bestslidefrac) { secondslidefrac = bestslidefrac; secondslideline = bestslideline; bestslidefrac = in->frac; bestslideline = li; } return false; // stop } /* ================== = = P_SlideMove = = The momx / momy move is bad, so try to slide along a wall = = Find the first line hit, move flush to it, and slide along it = = This is a kludgy mess. ================== */ void P_SlideMove (mobj_t *mo) { fixed_t leadx, leady; fixed_t trailx, traily; fixed_t newx, newy; int hitcount; slidemo = mo; hitcount = 0; retry: if (++hitcount == 3) goto stairstep; // don't loop forever // // trace along the three leading corners // if (mo->momx > 0) { leadx = mo->x + mo->radius; trailx = mo->x - mo->radius; } else { leadx = mo->x - mo->radius; trailx = mo->x + mo->radius; } if (mo->momy > 0) { leady = mo->y + mo->radius; traily = mo->y - mo->radius; } else { leady = mo->y - mo->radius; traily = mo->y + mo->radius; } bestslidefrac = FRACUNIT+1; P_PathTraverse ( leadx, leady, leadx+mo->momx, leady+mo->momy, PT_ADDLINES, PTR_SlideTraverse ); P_PathTraverse ( trailx, leady, trailx+mo->momx, leady+mo->momy, PT_ADDLINES, PTR_SlideTraverse ); P_PathTraverse ( leadx, traily, leadx+mo->momx, traily+mo->momy, PT_ADDLINES, PTR_SlideTraverse ); // // move up to the wall // if (bestslidefrac == FRACUNIT+1) { // the move most have hit the middle, so stairstep stairstep: if (!P_TryMove (mo, mo->x, mo->y + mo->momy)) P_TryMove (mo, mo->x + mo->momx, mo->y); return; } bestslidefrac -= 0x800; // fudge a bit to make sure it doesn't hit if (bestslidefrac > 0) { newx = FixedMul (mo->momx, bestslidefrac); newy = FixedMul (mo->momy, bestslidefrac); if (!P_TryMove (mo, mo->x+newx, mo->y+newy)) goto stairstep; } // // now continue along the wall // bestslidefrac = FRACUNIT-(bestslidefrac+0x800); // remainder if (bestslidefrac > FRACUNIT) bestslidefrac = FRACUNIT; if (bestslidefrac <= 0) return; tmxmove = FixedMul (mo->momx, bestslidefrac); tmymove = FixedMul (mo->momy, bestslidefrac); P_HitSlideLine (bestslideline); // clip the moves mo->momx = tmxmove; mo->momy = tmymove; if (!P_TryMove (mo, mo->x+tmxmove, mo->y+tmymove)) { goto retry; } } /* ============================================================================== P_LineAttack ============================================================================== */ mobj_t *linetarget; // who got hit (or NULL) mobj_t *shootthing; fixed_t shootz; // height if not aiming up or down // ???: use slope for monsters? int la_damage; fixed_t attackrange; fixed_t aimslope; extern fixed_t topslope, bottomslope; // slopes to top and bottom of target /* =============================================================================== = = PTR_AimTraverse = = Sets linetaget and aimslope when a target is aimed at =============================================================================== */ boolean PTR_AimTraverse (intercept_t *in) { line_t *li; mobj_t *th; fixed_t slope, thingtopslope, thingbottomslope; fixed_t dist; if (in->isaline) { li = in->d.line; if ( !(li->flags & ML_TWOSIDED) ) return false; // stop // // crosses a two sided line // a two sided line will restrict the possible target ranges P_LineOpening (li); if (openbottom >= opentop) return false; // stop dist = FixedMul (attackrange, in->frac); if (li->frontsector->floorheight != li->backsector->floorheight) { slope = FixedDiv (openbottom - shootz , dist); if (slope > bottomslope) bottomslope = slope; } if (li->frontsector->ceilingheight != li->backsector->ceilingheight) { slope = FixedDiv (opentop - shootz , dist); if (slope < topslope) topslope = slope; } if (topslope <= bottomslope) return false; // stop return true; // shot continues } // // shoot a thing // th = in->d.thing; if (th == shootthing) return true; // can't shoot self if (!(th->flags&MF_SHOOTABLE)) return true; // corpse or something // check angles to see if the thing can be aimed at dist = FixedMul (attackrange, in->frac); thingtopslope = FixedDiv (th->z+th->height - shootz , dist); if (thingtopslope < bottomslope) return true; // shot over the thing thingbottomslope = FixedDiv (th->z - shootz, dist); if (thingbottomslope > topslope) return true; // shot under the thing // // this thing can be hit! // if (thingtopslope > topslope) thingtopslope = topslope; if (thingbottomslope < bottomslope) thingbottomslope = bottomslope; aimslope = (thingtopslope+thingbottomslope)/2; linetarget = th; return false; // don't go any farther } /* ============================================================================== = = PTR_ShootTraverse = ============================================================================== */ boolean PTR_ShootTraverse (intercept_t *in) { fixed_t x,y,z; fixed_t frac; line_t *li; mobj_t *th; fixed_t slope; fixed_t dist; fixed_t thingtopslope, thingbottomslope; if (in->isaline) { li = in->d.line; if (li->special) P_ShootSpecialLine (shootthing, li); if ( !(li->flags & ML_TWOSIDED) ) goto hitline; // // crosses a two sided line // P_LineOpening (li); dist = FixedMul (attackrange, in->frac); if (li->frontsector->floorheight != li->backsector->floorheight) { slope = FixedDiv (openbottom - shootz , dist); if (slope > aimslope) goto hitline; } if (li->frontsector->ceilingheight != li->backsector->ceilingheight) { slope = FixedDiv (opentop - shootz , dist); if (slope < aimslope) goto hitline; } return true; // shot continues // // hit line // hitline: // position a bit closer frac = in->frac - FixedDiv (4*FRACUNIT,attackrange); x = trace.x + FixedMul (trace.dx, frac); y = trace.y + FixedMul (trace.dy, frac); z = shootz + FixedMul (aimslope, FixedMul(frac, attackrange)); if (li->frontsector->ceilingpic == skyflatnum) { if (z > li->frontsector->ceilingheight) return false; // don't shoot the sky! if (li->backsector && li->backsector->ceilingpic == skyflatnum) return false; // it's a sky hack wall } P_SpawnPuff (x,y,z); return false; // don't go any farther } // // shoot a thing // th = in->d.thing; if (th == shootthing) return true; // can't shoot self if (!(th->flags&MF_SHOOTABLE)) return true; // corpse or something // check angles to see if the thing can be aimed at dist = FixedMul (attackrange, in->frac); thingtopslope = FixedDiv (th->z+th->height - shootz , dist); if (thingtopslope < aimslope) return true; // shot over the thing thingbottomslope = FixedDiv (th->z - shootz, dist); if (thingbottomslope > aimslope) return true; // shot under the thing // // hit thing // // position a bit closer frac = in->frac - FixedDiv (10*FRACUNIT,attackrange); x = trace.x + FixedMul (trace.dx, frac); y = trace.y + FixedMul (trace.dy, frac); z = shootz + FixedMul (aimslope, FixedMul(frac, attackrange)); if (in->d.thing->flags & MF_NOBLOOD) P_SpawnPuff (x,y,z); else P_SpawnBlood (x,y,z, la_damage); if (la_damage) P_DamageMobj (th, shootthing, shootthing, la_damage); return false; // don't go any farther } /* ================= = = P_AimLineAttack = ================= */ fixed_t P_AimLineAttack (mobj_t *t1, angle_t angle, fixed_t distance) { fixed_t x2, y2; angle >>= ANGLETOFINESHIFT; shootthing = t1; x2 = t1->x + (distance>>FRACBITS)*finecosine[angle]; y2 = t1->y + (distance>>FRACBITS)*finesine[angle]; shootz = t1->z + (t1->height>>1) + 8*FRACUNIT; topslope = 100*FRACUNIT/160; // can't shoot outside view angles bottomslope = -100*FRACUNIT/160; attackrange = distance; linetarget = NULL; P_PathTraverse ( t1->x, t1->y, x2, y2 , PT_ADDLINES|PT_ADDTHINGS, PTR_AimTraverse ); if (linetarget) return aimslope; return 0; } /* ================= = = P_LineAttack = = if damage == 0, it is just a test trace that will leave linetarget set = ================= */ void P_LineAttack (mobj_t *t1, angle_t angle, fixed_t distance, fixed_t slope, int damage) { fixed_t x2, y2; angle >>= ANGLETOFINESHIFT; shootthing = t1; la_damage = damage; x2 = t1->x + (distance>>FRACBITS)*finecosine[angle]; y2 = t1->y + (distance>>FRACBITS)*finesine[angle]; shootz = t1->z + (t1->height>>1) + 8*FRACUNIT; attackrange = distance; aimslope = slope; P_PathTraverse ( t1->x, t1->y, x2, y2 , PT_ADDLINES|PT_ADDTHINGS, PTR_ShootTraverse ); } /* ============================================================================== USE LINES ============================================================================== */ mobj_t *usething; boolean PTR_UseTraverse (intercept_t *in) { int side; if (!in->d.line->special) { P_LineOpening (in->d.line); if (openrange <= 0) { S_StartSound (usething, sfx_noway); return false; // can't use through a wall } return true ; // not a special line, but keep checking } side = 0; if (P_PointOnLineSide (usething->x, usething->y, in->d.line) == 1) side = 1; // return false; // don't use back side P_UseSpecialLine (usething, in->d.line, side); return false; // can't use for than one special line in a row } /* ================ = = P_UseLines = = Looks for special lines in front of the player to activate ================ */ void P_UseLines (player_t *player) { int angle; fixed_t x1, y1, x2, y2; usething = player->mo; angle = player->mo->angle >> ANGLETOFINESHIFT; x1 = player->mo->x; y1 = player->mo->y; x2 = x1 + (USERANGE>>FRACBITS)*finecosine[angle]; y2 = y1 + (USERANGE>>FRACBITS)*finesine[angle]; P_PathTraverse ( x1, y1, x2, y2, PT_ADDLINES, PTR_UseTraverse ); } /* ============================================================================== RADIUS ATTACK ============================================================================== */ mobj_t *bombsource; mobj_t *bombspot; int bombdamage; /* ================= = = PIT_RadiusAttack = = Source is the creature that casued the explosion at spot ================= */ boolean PIT_RadiusAttack (mobj_t *thing) { fixed_t dx, dy, dist; if (!(thing->flags & MF_SHOOTABLE) ) return true; if (thing->type == MT_CYBORG || thing->type == MT_SPIDER) return true; // cyborg takes no damage from concussion dx = abs(thing->x - bombspot->x); dy = abs(thing->y - bombspot->y); dist = dx>dy ? dx : dy; dist = (dist - thing->radius) >> FRACBITS; if (dist < 0) dist = 0; if (dist >= bombdamage) return true; // out of range if ( P_CheckSight (thing, bombspot) ) // must be in direct path P_DamageMobj (thing, bombspot, bombsource, bombdamage - dist); return true; } /* ================= = = P_RadiusAttack = = Source is the creature that casued the explosion at spot ================= */ void P_RadiusAttack (mobj_t *spot, mobj_t *source, int damage) { int x,y, xl, xh, yl, yh; fixed_t dist; dist = (damage+MAXRADIUS)<y + dist - bmaporgy)>>MAPBLOCKSHIFT; yl = (spot->y - dist - bmaporgy)>>MAPBLOCKSHIFT; xh = (spot->x + dist - bmaporgx)>>MAPBLOCKSHIFT; xl = (spot->x - dist - bmaporgx)>>MAPBLOCKSHIFT; bombspot = spot; bombsource = source; bombdamage = damage; for (y=yl ; y<=yh ; y++) for (x=xl ; x<=xh ; x++) P_BlockThingsIterator (x, y, PIT_RadiusAttack ); } /* ============================================================================== SECTOR HEIGHT CHANGING = After modifying a sectors floor or ceiling height, call this = routine to adjust the positions of all things that touch the = sector. = = If anything doesn't fit anymore, true will be returned. = If crunch is true, they will take damage as they are being crushed = If Crunch is false, you should set the sector height back the way it = was and call P_ChangeSector again to undo the changes ============================================================================== */ boolean crushchange; boolean nofit; /* =============== = = PIT_ChangeSector = =============== */ boolean PIT_ChangeSector (mobj_t *thing) { mobj_t *mo; if (P_ThingHeightClip (thing)) return true; // keep checking // crunch bodies to giblets if (thing->health <= 0) { P_SetMobjState (thing, S_GIBS); thing->flags &= ~MF_SOLID; thing->height = 0; thing->radius = 0; return true; // keep checking } // crunch dropped items if (thing->flags & MF_DROPPED) { P_RemoveMobj (thing); return true; // keep checking } if (! (thing->flags & MF_SHOOTABLE) ) return true; // assume it is bloody gibs or something nofit = true; if (crushchange && !(leveltime&3) ) { P_DamageMobj(thing,NULL,NULL,10); // spray blood in a random direction mo = P_SpawnMobj (thing->x, thing->y, thing->z + thing->height/2, MT_BLOOD); mo->momx = (P_Random() - P_Random ())<<12; mo->momy = (P_Random() - P_Random ())<<12; } return true; // keep checking (crush other things) } /* =============== = = P_ChangeSector = =============== */ boolean P_ChangeSector (sector_t *sector, boolean crunch) { int x,y; nofit = false; crushchange = crunch; // recheck heights for all things near the moving sector for (x=sector->blockbox[BOXLEFT] ; x<= sector->blockbox[BOXRIGHT] ; x++) for (y=sector->blockbox[BOXBOTTOM];y<= sector->blockbox[BOXTOP] ; y++) P_BlockThingsIterator (x, y, PIT_ChangeSector); return nofit; } \ No newline at end of file diff --git a/P_MAPUTL.C b/P_MAPUTL.C new file mode 100644 index 0000000..74675d0 --- /dev/null +++ b/P_MAPUTL.C @@ -0,0 +1 @@ + // P_maputl.c #include "doomdef.h" #include "p_local.h" /* =================== = = P_AproxDistance = = Gives an estimation of distance (not exact) = =================== */ fixed_t P_AproxDistance (fixed_t dx, fixed_t dy) { dx = abs(dx); dy = abs(dy); if (dx < dy) return dx+dy-(dx>>1); return dx+dy-(dy>>1); } /* ================== = = P_PointOnLineSide = = Returns 0 or 1 ================== */ int P_PointOnLineSide (fixed_t x, fixed_t y, line_t *line) { fixed_t dx,dy; fixed_t left, right; if (!line->dx) { if (x <= line->v1->x) return line->dy > 0; return line->dy < 0; } if (!line->dy) { if (y <= line->v1->y) return line->dx < 0; return line->dx > 0; } dx = (x - line->v1->x); dy = (y - line->v1->y); left = FixedMul ( line->dy>>FRACBITS , dx ); right = FixedMul ( dy , line->dx>>FRACBITS ); if (right < left) return 0; // front side return 1; // back side } /* ================= = = P_BoxOnLineSide = = Considers the line to be infinite = Returns side 0 or 1, -1 if box crosses the line ================= */ int P_BoxOnLineSide (fixed_t *tmbox, line_t *ld) { int p1, p2; switch (ld->slopetype) { case ST_HORIZONTAL: p1 = tmbox[BOXTOP] > ld->v1->y; p2 = tmbox[BOXBOTTOM] > ld->v1->y; if (ld->dx < 0) { p1 ^= 1; p2 ^= 1; } break; case ST_VERTICAL: p1 = tmbox[BOXRIGHT] < ld->v1->x; p2 = tmbox[BOXLEFT] < ld->v1->x; if (ld->dy < 0) { p1 ^= 1; p2 ^= 1; } break; case ST_POSITIVE: p1 = P_PointOnLineSide (tmbox[BOXLEFT], tmbox[BOXTOP], ld); p2 = P_PointOnLineSide (tmbox[BOXRIGHT], tmbox[BOXBOTTOM], ld); break; case ST_NEGATIVE: p1 = P_PointOnLineSide (tmbox[BOXRIGHT], tmbox[BOXTOP], ld); p2 = P_PointOnLineSide (tmbox[BOXLEFT], tmbox[BOXBOTTOM], ld); break; } if (p1 == p2) return p1; return -1; } /* ================== = = P_PointOnDivlineSide = = Returns 0 or 1 ================== */ int P_PointOnDivlineSide (fixed_t x, fixed_t y, divline_t *line) { fixed_t dx,dy; fixed_t left, right; if (!line->dx) { if (x <= line->x) return line->dy > 0; return line->dy < 0; } if (!line->dy) { if (y <= line->y) return line->dx < 0; return line->dx > 0; } dx = (x - line->x); dy = (y - line->y); // try to quickly decide by looking at sign bits if ( (line->dy ^ line->dx ^ dx ^ dy)&0x80000000 ) { if ( (line->dy ^ dx) & 0x80000000 ) return 1; // (left is negative) return 0; } left = FixedMul ( line->dy>>8, dx>>8 ); right = FixedMul ( dy>>8 , line->dx>>8 ); if (right < left) return 0; // front side return 1; // back side } /* ============== = = P_MakeDivline = ============== */ void P_MakeDivline (line_t *li, divline_t *dl) { dl->x = li->v1->x; dl->y = li->v1->y; dl->dx = li->dx; dl->dy = li->dy; } /* =============== = = P_InterceptVector = = Returns the fractional intercept point along the first divline = = This is only called by the addthings and addlines traversers =============== */ fixed_t P_InterceptVector (divline_t *v2, divline_t *v1) { #if 1 fixed_t frac, num, den; den = FixedMul (v1->dy>>8,v2->dx) - FixedMul(v1->dx>>8,v2->dy); if (den == 0) return 0; // I_Error ("P_InterceptVector: parallel"); num = FixedMul ( (v1->x - v2->x)>>8 ,v1->dy) + FixedMul ( (v2->y - v1->y)>>8 , v1->dx); frac = FixedDiv (num , den); return frac; #else float frac, num, den, v1x,v1y,v1dx,v1dy,v2x,v2y,v2dx,v2dy; v1x = (float)v1->x/FRACUNIT; v1y = (float)v1->y/FRACUNIT; v1dx = (float)v1->dx/FRACUNIT; v1dy = (float)v1->dy/FRACUNIT; v2x = (float)v2->x/FRACUNIT; v2y = (float)v2->y/FRACUNIT; v2dx = (float)v2->dx/FRACUNIT; v2dy = (float)v2->dy/FRACUNIT; den = v1dy*v2dx - v1dx*v2dy; if (den == 0) return 0; // parallel num = (v1x - v2x)*v1dy + (v2y - v1y)*v1dx; frac = num / den; return frac*FRACUNIT; #endif } /* ================== = = P_LineOpening = = Sets opentop and openbottom to the window through a two sided line = OPTIMIZE: keep this precalculated ================== */ fixed_t opentop, openbottom, openrange; fixed_t lowfloor; void P_LineOpening (line_t *linedef) { sector_t *front, *back; if (linedef->sidenum[1] == -1) { // single sided line openrange = 0; return; } front = linedef->frontsector; back = linedef->backsector; if (front->ceilingheight < back->ceilingheight) opentop = front->ceilingheight; else opentop = back->ceilingheight; if (front->floorheight > back->floorheight) { openbottom = front->floorheight; lowfloor = back->floorheight; } else { openbottom = back->floorheight; lowfloor = front->floorheight; } openrange = opentop - openbottom; } /* =============================================================================== THING POSITION SETTING =============================================================================== */ /* =================== = = P_UnsetThingPosition = = Unlinks a thing from block map and sectors = =================== */ void P_UnsetThingPosition (mobj_t *thing) { int blockx, blocky; if ( ! (thing->flags & MF_NOSECTOR) ) { // inert things don't need to be in blockmap // unlink from subsector if (thing->snext) thing->snext->sprev = thing->sprev; if (thing->sprev) thing->sprev->snext = thing->snext; else thing->subsector->sector->thinglist = thing->snext; } if ( ! (thing->flags & MF_NOBLOCKMAP) ) { // inert things don't need to be in blockmap // unlink from block map if (thing->bnext) thing->bnext->bprev = thing->bprev; if (thing->bprev) thing->bprev->bnext = thing->bnext; else { blockx = (thing->x - bmaporgx)>>MAPBLOCKSHIFT; blocky = (thing->y - bmaporgy)>>MAPBLOCKSHIFT; if (blockx>=0 && blockx < bmapwidth && blocky>=0 && blocky bnext; } } } /* =================== = = P_SetThingPosition = = Links a thing into both a block and a subsector based on it's x y = Sets thing->subsector properly = =================== */ void P_SetThingPosition (mobj_t *thing) { subsector_t *ss; sector_t *sec; int blockx, blocky; mobj_t **link; // // link into subsector // ss = R_PointInSubsector (thing->x,thing->y); thing->subsector = ss; if ( ! (thing->flags & MF_NOSECTOR) ) { // invisible things don't go into the sector links sec = ss->sector; thing->sprev = NULL; thing->snext = sec->thinglist; if (sec->thinglist) sec->thinglist->sprev = thing; sec->thinglist = thing; } // // link into blockmap // if ( ! (thing->flags & MF_NOBLOCKMAP) ) { // inert things don't need to be in blockmap blockx = (thing->x - bmaporgx)>>MAPBLOCKSHIFT; blocky = (thing->y - bmaporgy)>>MAPBLOCKSHIFT; if (blockx>=0 && blockx < bmapwidth && blocky>=0 && blocky bprev = NULL; thing->bnext = *link; if (*link) (*link)->bprev = thing; *link = thing; } else { // thing is off the map thing->bnext = thing->bprev = NULL; } } } /* =============================================================================== BLOCK MAP ITERATORS For each line/thing in the given mapblock, call the passed function. If the function returns false, exit with false without checking anything else. =============================================================================== */ /* ================== = = P_BlockLinesIterator = = The validcount flags are used to avoid checking lines = that are marked in multiple mapblocks, so increment validcount before = the first call to P_BlockLinesIterator, then make one or more calls to it =================== */ boolean P_BlockLinesIterator (int x, int y, boolean(*func)(line_t*) ) { int offset; short *list; line_t *ld; if (x<0 || y<0 || x>=bmapwidth || y>=bmapheight) return true; offset = y*bmapwidth+x; offset = *(blockmap+offset); for ( list = blockmaplump+offset ; *list != -1 ; list++) { ld = &lines[*list]; if (ld->validcount == validcount) continue; // line has already been checked ld->validcount = validcount; if ( !func(ld) ) return false; } return true; // everything was checked } /* ================== = = P_BlockThingsIterator = ================== */ boolean P_BlockThingsIterator (int x, int y, boolean(*func)(mobj_t*) ) { mobj_t *mobj; if (x<0 || y<0 || x>=bmapwidth || y>=bmapheight) return true; for (mobj = blocklinks[y*bmapwidth+x] ; mobj ; mobj = mobj->bnext) if (!func( mobj ) ) return false; return true; } /* =============================================================================== INTERCEPT ROUTINES =============================================================================== */ intercept_t intercepts[MAXINTERCEPTS], *intercept_p; divline_t trace; boolean earlyout; int ptflags; /* ================== = = PIT_AddLineIntercepts = = Looks for lines in the given block that intercept the given trace = to add to the intercepts list = A line is crossed if its endpoints are on opposite sides of the trace = Returns true if earlyout and a solid line hit ================== */ boolean PIT_AddLineIntercepts (line_t *ld) { int s1, s2; fixed_t frac; divline_t dl; // avoid precision problems with two routines if ( trace.dx > FRACUNIT*16 || trace.dy > FRACUNIT*16 || trace.dx < -FRACUNIT*16 || trace.dy < -FRACUNIT*16) { s1 = P_PointOnDivlineSide (ld->v1->x, ld->v1->y, &trace); s2 = P_PointOnDivlineSide (ld->v2->x, ld->v2->y, &trace); } else { s1 = P_PointOnLineSide (trace.x, trace.y, ld); s2 = P_PointOnLineSide (trace.x+trace.dx, trace.y+trace.dy, ld); } if (s1 == s2) return true; // line isn't crossed // // hit the line // P_MakeDivline (ld, &dl); frac = P_InterceptVector (&trace, &dl); if (frac < 0) return true; // behind source // try to early out the check if (earlyout && frac < FRACUNIT && !ld->backsector) return false; // stop checking intercept_p->frac = frac; intercept_p->isaline = true; intercept_p->d.line = ld; intercept_p++; return true; // continue } /* ================== = = PIT_AddThingIntercepts = ================== */ boolean PIT_AddThingIntercepts (mobj_t *thing) { fixed_t x1,y1, x2,y2; int s1, s2; boolean tracepositive; divline_t dl; fixed_t frac; tracepositive = (trace.dx ^ trace.dy)>0; // check a corner to corner crossection for hit if (tracepositive) { x1 = thing->x - thing->radius; y1 = thing->y + thing->radius; x2 = thing->x + thing->radius; y2 = thing->y - thing->radius; } else { x1 = thing->x - thing->radius; y1 = thing->y - thing->radius; x2 = thing->x + thing->radius; y2 = thing->y + thing->radius; } s1 = P_PointOnDivlineSide (x1, y1, &trace); s2 = P_PointOnDivlineSide (x2, y2, &trace); if (s1 == s2) return true; // line isn't crossed dl.x = x1; dl.y = y1; dl.dx = x2-x1; dl.dy = y2-y1; frac = P_InterceptVector (&trace, &dl); if (frac < 0) return true; // behind source intercept_p->frac = frac; intercept_p->isaline = false; intercept_p->d.thing = thing; intercept_p++; return true; // keep going } /* ==================== = = P_TraverseIntercepts = = Returns true if the traverser function returns true for all lines ==================== */ boolean P_TraverseIntercepts ( traverser_t func, fixed_t maxfrac ) { int count; fixed_t dist; intercept_t *scan, *in; count = intercept_p - intercepts; in = 0; // shut up compiler warning while (count--) { dist = MAXINT; for (scan = intercepts ; scanfrac < dist) { dist = scan->frac; in = scan; } if (dist > maxfrac) return true; // checked everything in range #if 0 { // don't check these yet, ther may be others inserted in = scan = intercepts; for ( scan = intercepts ; scanfrac > maxfrac) *in++ = *scan; intercept_p = in; return false; } #endif if ( !func (in) ) return false; // don't bother going farther in->frac = MAXINT; } return true; // everything was traversed } /* ================== = = P_PathTraverse = = Traces a line from x1,y1 to x2,y2, calling the traverser function for each = Returns true if the traverser function returns true for all lines ================== */ boolean P_PathTraverse (fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2, int flags, boolean (*trav) (intercept_t *)) { fixed_t xt1,yt1,xt2,yt2; fixed_t xstep,ystep; fixed_t partial; fixed_t xintercept, yintercept; int mapx, mapy, mapxstep, mapystep; int count; earlyout = flags & PT_EARLYOUT; validcount++; intercept_p = intercepts; if ( ((x1-bmaporgx)&(MAPBLOCKSIZE-1)) == 0) x1 += FRACUNIT; // don't side exactly on a line if ( ((y1-bmaporgy)&(MAPBLOCKSIZE-1)) == 0) y1 += FRACUNIT; // don't side exactly on a line trace.x = x1; trace.y = y1; trace.dx = x2 - x1; trace.dy = y2 - y1; x1 -= bmaporgx; y1 -= bmaporgy; xt1 = x1>>MAPBLOCKSHIFT; yt1 = y1>>MAPBLOCKSHIFT; x2 -= bmaporgx; y2 -= bmaporgy; xt2 = x2>>MAPBLOCKSHIFT; yt2 = y2>>MAPBLOCKSHIFT; if (xt2 > xt1) { mapxstep = 1; partial = FRACUNIT - ((x1>>MAPBTOFRAC)&(FRACUNIT-1)); ystep = FixedDiv (y2-y1,abs(x2-x1)); } else if (xt2 < xt1) { mapxstep = -1; partial = (x1>>MAPBTOFRAC)&(FRACUNIT-1); ystep = FixedDiv (y2-y1,abs(x2-x1)); } else { mapxstep = 0; partial = FRACUNIT; ystep = 256*FRACUNIT; } yintercept = (y1>>MAPBTOFRAC) + FixedMul (partial, ystep); if (yt2 > yt1) { mapystep = 1; partial = FRACUNIT - ((y1>>MAPBTOFRAC)&(FRACUNIT-1)); xstep = FixedDiv (x2-x1,abs(y2-y1)); } else if (yt2 < yt1) { mapystep = -1; partial = (y1>>MAPBTOFRAC)&(FRACUNIT-1); xstep = FixedDiv (x2-x1,abs(y2-y1)); } else { mapystep = 0; partial = FRACUNIT; xstep = 256*FRACUNIT; } xintercept = (x1>>MAPBTOFRAC) + FixedMul (partial, xstep); // // step through map blocks // Count is present to prevent a round off error from skipping the break mapx = xt1; mapy = yt1; for (count = 0 ; count < 64 ; count++) { if (flags & PT_ADDLINES) { if (!P_BlockLinesIterator (mapx, mapy,PIT_AddLineIntercepts)) return false; // early out } if (flags & PT_ADDTHINGS) { if (!P_BlockThingsIterator (mapx, mapy,PIT_AddThingIntercepts)) return false; // early out } if (mapx == xt2 && mapy == yt2) break; if ( (yintercept >> FRACBITS) == mapy) { yintercept += ystep; mapx += mapxstep; } else if ( (xintercept >> FRACBITS) == mapx) { xintercept += xstep; mapy += mapystep; } } // // go through the sorted list // return P_TraverseIntercepts ( trav, FRACUNIT ); } \ No newline at end of file diff --git a/P_MOBJ.C b/P_MOBJ.C new file mode 100644 index 0000000..7c928f3 --- /dev/null +++ b/P_MOBJ.C @@ -0,0 +1 @@ +// P_mobj.c #include "doomdef.h" #include "p_local.h" #include "sounds.h" void G_PlayerReborn (int player); void P_SpawnMapThing (mapthing_t *mthing); /* ================ = = P_SetMobjState = = Returns true if the mobj is still present ================ */ int test; boolean P_SetMobjState (mobj_t *mobj, statenum_t state) { state_t *st; do { if (state == S_NULL) { mobj->state = (state_t *) S_NULL; P_RemoveMobj (mobj); return false; } st = &states[state]; mobj->state = st; mobj->tics = st->tics; mobj->sprite = st->sprite; mobj->frame = st->frame; if (st->action) // call action functions when the state is set st->action (mobj); state = st->nextstate; } while (!mobj->tics); return true; } /* =================== = = P_ExplodeMissile = =================== */ void P_ExplodeMissile (mobj_t *mo) { mo->momx = mo->momy = mo->momz = 0; P_SetMobjState (mo, mobjinfo[mo->type].deathstate); mo->tics -= P_Random()&3; if (mo->tics < 1) mo->tics = 1; mo->flags &= ~MF_MISSILE; if (mo->info->deathsound) S_StartSound (mo, mo->info->deathsound); } /* =================== = = P_XYMovement = =================== */ #define STOPSPEED 0x1000 #define FRICTION 0xe800 void P_XYMovement (mobj_t *mo) { fixed_t ptryx, ptryy; player_t *player; fixed_t xmove, ymove; if (!mo->momx && !mo->momy) { if (mo->flags & MF_SKULLFLY) { // the skull slammed into something mo->flags &= ~MF_SKULLFLY; mo->momx = mo->momy = mo->momz = 0; P_SetMobjState (mo, mo->info->spawnstate); } return; } player = mo->player; if (mo->momx > MAXMOVE) mo->momx = MAXMOVE; else if (mo->momx < -MAXMOVE) mo->momx = -MAXMOVE; if (mo->momy > MAXMOVE) mo->momy = MAXMOVE; else if (mo->momy < -MAXMOVE) mo->momy = -MAXMOVE; xmove = mo->momx; ymove = mo->momy; do { if (xmove > MAXMOVE/2 || ymove > MAXMOVE/2) { ptryx = mo->x + xmove/2; ptryy = mo->y + ymove/2; xmove >>= 1; ymove >>= 1; } else { ptryx = mo->x + xmove; ptryy = mo->y + ymove; xmove = ymove = 0; } if (!P_TryMove (mo, ptryx, ptryy)) { // blocked move if (mo->player) { // try to slide along it P_SlideMove (mo); } else if (mo->flags & MF_MISSILE) { // explode a missile if (ceilingline && ceilingline->backsector && ceilingline->backsector->ceilingpic == skyflatnum) { // hack to prevent missiles exploding against the sky P_RemoveMobj (mo); return; } P_ExplodeMissile (mo); } else mo->momx = mo->momy = 0; } } while (xmove || ymove); // // slow down // if (player && player->cheats & CF_NOMOMENTUM) { // debug option for no sliding at all mo->momx = mo->momy = 0; return; } if (mo->flags & (MF_MISSILE | MF_SKULLFLY) ) return; // no friction for missiles ever if (mo->z > mo->floorz) return; // no friction when airborne if (mo->flags & MF_CORPSE) { // don't stop sliding if halfway off a step with some momentum if (mo->momx > FRACUNIT/4 || mo->momx < -FRACUNIT/4 || mo->momy > FRACUNIT/4 || mo->momy < -FRACUNIT/4) if (mo->floorz != mo->subsector->sector->floorheight) return; } if (mo->momx > -STOPSPEED && mo->momx < STOPSPEED && mo->momy > -STOPSPEED && mo->momy < STOPSPEED && (!player || (player->cmd.forwardmove== 0 && player->cmd.sidemove == 0 ) ) ) { // if in a walking frame, stop moving if ( player&&(unsigned)((player->mo->state - states)- S_PLAY_RUN1) < 4) P_SetMobjState (player->mo, S_PLAY); mo->momx = 0; mo->momy = 0; } else { mo->momx = FixedMul (mo->momx, FRICTION); mo->momy = FixedMul (mo->momy, FRICTION); } } /* =============== = = P_ZMovement = =============== */ void P_ZMovement (mobj_t *mo) { fixed_t dist, delta; // // check for smooth step up // if (mo->player && mo->z < mo->floorz) { mo->player->viewheight -= mo->floorz-mo->z; mo->player->deltaviewheight = (VIEWHEIGHT - mo->player->viewheight)>>3; } // // adjust height // mo->z += mo->momz; if ( mo->flags & MF_FLOAT && mo->target) { // float down towards target if too close if (! (mo->flags & MF_SKULLFLY) && ! (mo->flags & MF_INFLOAT) ) { dist = P_AproxDistance (mo->x - mo->target->x , mo->y - mo->target->y); delta =(mo->target->z + (mo->height>>1)) - mo->z; if (delta<0 && dist < -(delta*3) ) mo->z -= FLOATSPEED; else if (delta>0 && dist < (delta*3) ) mo->z += FLOATSPEED; } } // // clip movement // if (mo->z <= mo->floorz) { // hit the floor if (mo->momz < 0) { if (mo->player && mo->momz < -GRAVITY*8) // squat down { mo->player->deltaviewheight = mo->momz>>3; S_StartSound (mo, sfx_oof); } mo->momz = 0; } mo->z = mo->floorz; if (mo->flags & MF_SKULLFLY) { // the skull slammed into something mo->momz = -mo->momz; } if ( (mo->flags & MF_MISSILE) && !(mo->flags & MF_NOCLIP) ) { P_ExplodeMissile (mo); return; } } else if (! (mo->flags & MF_NOGRAVITY) ) { if (mo->momz == 0) mo->momz = -GRAVITY*2; else mo->momz -= GRAVITY; } if (mo->z + mo->height > mo->ceilingz) { // hit the ceiling if (mo->momz > 0) mo->momz = 0; mo->z = mo->ceilingz - mo->height; if (mo->flags & MF_SKULLFLY) { // the skull slammed into something mo->momz = -mo->momz; } if ( (mo->flags & MF_MISSILE) && !(mo->flags & MF_NOCLIP) ) { P_ExplodeMissile (mo); return; } } } /* ================ = = P_NightmareRespawn = ================ */ void P_NightmareRespawn (mobj_t *mobj) { fixed_t x,y,z; subsector_t *ss; mobj_t *mo; mapthing_t *mthing; x = mobj->spawnpoint.x << FRACBITS; y = mobj->spawnpoint.y << FRACBITS; if (!P_CheckPosition (mobj, x, y) ) return; // somthing is occupying it's position // spawn a teleport fog at old spot mo = P_SpawnMobj (mobj->x, mobj->y, mobj->subsector->sector->floorheight , MT_TFOG); S_StartSound (mo, sfx_telept); // spawn a teleport fog at the new spot ss = R_PointInSubsector (x,y); mo = P_SpawnMobj (x, y, ss->sector->floorheight , MT_TFOG); S_StartSound (mo, sfx_telept); // spawn the new monster mthing = &mobj->spawnpoint; // spawn it if (mobj->info->flags & MF_SPAWNCEILING) z = ONCEILINGZ; else z = ONFLOORZ; mo = P_SpawnMobj (x,y,z, mobj->type); mo->spawnpoint = mobj->spawnpoint; mo->angle = ANG45 * (mthing->angle/45); if (mthing->options & MTF_AMBUSH) mo->flags |= MF_AMBUSH; mo->reactiontime = 18; // remove the old monster P_RemoveMobj (mobj); } /* ================ = = P_MobjThinker = ================ */ void P_MobjThinker (mobj_t *mobj) { // // momentum movement // if (mobj->momx || mobj->momy || (mobj->flags&MF_SKULLFLY) ) { P_XYMovement (mobj); if (mobj->thinker.function == (think_t)-1) return; // mobj was removed } if ( (mobj->z != mobj->floorz) || mobj->momz) { P_ZMovement (mobj); if (mobj->thinker.function == (think_t)-1) return; // mobj was removed } // // cycle through states, calling action functions at transitions // if (mobj->tics != -1) { mobj->tics--; // you can cycle through multiple states in a tic if (!mobj->tics) if (!P_SetMobjState (mobj, mobj->state->nextstate) ) return; // freed itself } else { // check for nightmare respawn if (! (mobj->flags & MF_COUNTKILL) ) return; if (!respawnmonsters) return; mobj->movecount++; if (mobj->movecount < 12*35) return; if ( leveltime&31 ) return; if (P_Random () > 4) return; P_NightmareRespawn (mobj); } } /* =============== = = P_SpawnMobj = =============== */ mobj_t *P_SpawnMobj (fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) { mobj_t *mobj; state_t *st; mobjinfo_t *info; mobj = Z_Malloc (sizeof(*mobj), PU_LEVEL, NULL); memset (mobj, 0, sizeof (*mobj)); info = &mobjinfo[type]; mobj->type = type; mobj->info = info; mobj->x = x; mobj->y = y; mobj->radius = info->radius; mobj->height = info->height; mobj->flags = info->flags; mobj->health = info->spawnhealth; if (gameskill != sk_nightmare) mobj->reactiontime = info->reactiontime; mobj->lastlook = P_Random () % MAXPLAYERS; // do not set the state with P_SetMobjState, because action routines can't // be called yet st = &states[info->spawnstate]; mobj->state = st; mobj->tics = st->tics; mobj->sprite = st->sprite; mobj->frame = st->frame; // set subsector and/or block links P_SetThingPosition (mobj); mobj->floorz = mobj->subsector->sector->floorheight; mobj->ceilingz = mobj->subsector->sector->ceilingheight; if (z == ONFLOORZ) mobj->z = mobj->floorz; else if (z == ONCEILINGZ) mobj->z = mobj->ceilingz - mobj->info->height; else mobj->z = z; mobj->thinker.function = P_MobjThinker; P_AddThinker (&mobj->thinker); return mobj; } /* =============== = = P_RemoveMobj = =============== */ mapthing_t itemrespawnque[ITEMQUESIZE]; int itemrespawntime[ITEMQUESIZE]; int iquehead, iquetail; void P_RemoveMobj (mobj_t *mobj) { if ((mobj->flags & MF_SPECIAL) && !(mobj->flags & MF_DROPPED) && (mobj->type != MT_INV) && (mobj->type != MT_INS)) { itemrespawnque[iquehead] = mobj->spawnpoint; itemrespawntime[iquehead] = leveltime; iquehead = (iquehead+1)&(ITEMQUESIZE-1); if (iquehead == iquetail) // lose one off the end? iquetail = (iquetail+1)&(ITEMQUESIZE-1); } // unlink from sector and block lists P_UnsetThingPosition (mobj); // stop any playing sound S_StopSound (mobj); // free block P_RemoveThinker ((thinker_t *)mobj); } /* =============== = = P_RespawnSpecials = =============== */ void P_RespawnSpecials (void) { fixed_t x,y,z; subsector_t *ss; mobj_t *mo; mapthing_t *mthing; int i; if (deathmatch != 2) return; // only respawn items in deathmatch if (iquehead == iquetail) return; // nothing left to respawn if (leveltime - itemrespawntime[iquetail] < 30*35) return; // wait at least 30 seconds mthing = &itemrespawnque[iquetail]; x = mthing->x << FRACBITS; y = mthing->y << FRACBITS; // spawn a teleport fog at the new spot ss = R_PointInSubsector (x,y); mo = P_SpawnMobj (x, y, ss->sector->floorheight , MT_IFOG); S_StartSound (mo, sfx_itmbk); // find which type to spawn for (i=0 ; i< NUMMOBJTYPES ; i++) if (mthing->type == mobjinfo[i].doomednum) break; // spawn it if (mobjinfo[i].flags & MF_SPAWNCEILING) z = ONCEILINGZ; else z = ONFLOORZ; mo = P_SpawnMobj (x,y,z, i); mo->spawnpoint = *mthing; mo->angle = ANG45 * (mthing->angle/45); // pull it from the que iquetail = (iquetail+1)&(ITEMQUESIZE-1); } //============================================================================= /* ============ = = P_SpawnPlayer = = Called when a player is spawned on the level = Most of the player structure stays unchanged between levels ============ */ void P_SpawnPlayer (mapthing_t *mthing) { player_t *p; fixed_t x,y,z; mobj_t *mobj; int i; if (!playeringame[mthing->type-1]) return; // not playing p = &players[mthing->type-1]; if (p->playerstate == PST_REBORN) G_PlayerReborn (mthing->type-1); x = mthing->x << FRACBITS; y = mthing->y << FRACBITS; z = ONFLOORZ; mobj = P_SpawnMobj (x,y,z, MT_PLAYER); if (mthing->type > 1) // set color translations for player sprites mobj->flags |= (mthing->type-1)<angle = ANG45 * (mthing->angle/45); mobj->player = p; mobj->health = p->health; p->mo = mobj; p->playerstate = PST_LIVE; p->refire = 0; p->message = NULL; p->damagecount = 0; p->bonuscount = 0; p->extralight = 0; p->fixedcolormap = 0; p->viewheight = VIEWHEIGHT; P_SetupPsprites (p); // setup gun psprite if (deathmatch) for (i=0 ; icards[i] = true; // give all cards in death match mode if (mthing->type-1 == consoleplayer) { ST_Start (); // wake up the status bar HU_Start (); // wake up the heads up text } } /* ================= = = P_SpawnMapThing = = The fields of the mapthing should already be in host byte order ================== */ void P_SpawnMapThing (mapthing_t *mthing) { int i, bit; mobj_t *mobj; fixed_t x,y,z; // count deathmatch start positions if (mthing->type == 11) { if (deathmatch_p < &deathmatchstarts[10]) { memcpy (deathmatch_p, mthing, sizeof(*mthing)); deathmatch_p++; } return; } // check for players specially if (mthing->type <= 4) { // save spots for respawning in network games playerstarts[mthing->type-1] = *mthing; if (!deathmatch) P_SpawnPlayer (mthing); return; } // check for apropriate skill level if (!netgame && (mthing->options & 16) ) return; if (gameskill == sk_baby) bit = 1; else if (gameskill == sk_nightmare) bit = 4; else bit = 1<<(gameskill-1); if (!(mthing->options & bit) ) return; // find which type to spawn for (i=0 ; i< NUMMOBJTYPES ; i++) if (mthing->type == mobjinfo[i].doomednum) break; if (i==NUMMOBJTYPES) I_Error ("P_SpawnMapThing: Unknown type %i at (%i, %i)",mthing->type , mthing->x, mthing->y); // don't spawn keycards and players in deathmatch if (deathmatch && mobjinfo[i].flags & MF_NOTDMATCH) return; // don't spawn any monsters if -nomonsters if (nomonsters && ( i == MT_SKULL || (mobjinfo[i].flags & MF_COUNTKILL)) ) return; // spawn it x = mthing->x << FRACBITS; y = mthing->y << FRACBITS; if (mobjinfo[i].flags & MF_SPAWNCEILING) z = ONCEILINGZ; else z = ONFLOORZ; mobj = P_SpawnMobj (x,y,z, i); mobj->spawnpoint = *mthing; if (mobj->tics > 0) mobj->tics = 1 + (P_Random () % mobj->tics); if (mobj->flags & MF_COUNTKILL) totalkills++; if (mobj->flags & MF_COUNTITEM) totalitems++; mobj->angle = ANG45 * (mthing->angle/45); if (mthing->options & MTF_AMBUSH) mobj->flags |= MF_AMBUSH; } /* =============================================================================== GAME SPAWN FUNCTIONS =============================================================================== */ /* ================ = = P_SpawnPuff = ================ */ extern fixed_t attackrange; void P_SpawnPuff (fixed_t x, fixed_t y, fixed_t z) { mobj_t *th; z += ((P_Random()-P_Random())<<10); th = P_SpawnMobj (x,y,z, MT_PUFF); th->momz = FRACUNIT; th->tics -= P_Random()&3; if (th->tics < 1) th->tics = 1; // don't make punches spark on the wall if (attackrange == MELEERANGE) P_SetMobjState (th, S_PUFF3); } /* ================ = = P_SpawnBlood = ================ */ void P_SpawnBlood (fixed_t x, fixed_t y, fixed_t z, int damage) { mobj_t *th; z += ((P_Random()-P_Random())<<10); th = P_SpawnMobj (x,y,z, MT_BLOOD); th->momz = FRACUNIT*2; th->tics -= P_Random()&3; if (th->tics < 1) th->tics = 1; if (damage <= 12 && damage >= 9) P_SetMobjState (th,S_BLOOD2); else if (damage < 9) P_SetMobjState (th,S_BLOOD3); } /* ================ = = P_CheckMissileSpawn = = Moves the missile forward a bit and possibly explodes it right there = ================ */ void P_CheckMissileSpawn (mobj_t *th) { th->tics -= P_Random()&3; if (th->tics < 1) th->tics = 1; th->x += (th->momx>>1); th->y += (th->momy>>1); // move a little forward so an angle can // be computed if it immediately explodes th->z += (th->momz>>1); if (!P_TryMove (th, th->x, th->y)) P_ExplodeMissile (th); } /* ================ = = P_SpawnMissile = ================ */ mobj_t *P_SpawnMissile (mobj_t *source, mobj_t *dest, mobjtype_t type) { mobj_t *th; angle_t an; int dist; th = P_SpawnMobj (source->x,source->y, source->z + 4*8*FRACUNIT, type); if (th->info->seesound) S_StartSound (th, th->info->seesound); th->target = source; // where it came from an = R_PointToAngle2 (source->x, source->y, dest->x, dest->y); if (dest->flags & MF_SHADOW) an += (P_Random()-P_Random())<<20; // fuzzy player th->angle = an; an >>= ANGLETOFINESHIFT; th->momx = FixedMul (th->info->speed, finecosine[an]); th->momy = FixedMul (th->info->speed, finesine[an]); dist = P_AproxDistance (dest->x - source->x, dest->y - source->y); dist = dist / th->info->speed; if (dist < 1) dist = 1; th->momz = (dest->z - source->z) / dist; P_CheckMissileSpawn (th); return th; } /* ================ = = P_SpawnPlayerMissile = = Tries to aim at a nearby monster ================ */ void P_SpawnPlayerMissile (mobj_t *source, mobjtype_t type) { mobj_t *th; angle_t an; fixed_t x,y,z, slope; // // see which target is to be aimed at // an = source->angle; slope = P_AimLineAttack (source, an, 16*64*FRACUNIT); if (!linetarget) { an += 1<<26; slope = P_AimLineAttack (source, an, 16*64*FRACUNIT); if (!linetarget) { an -= 2<<26; slope = P_AimLineAttack (source, an, 16*64*FRACUNIT); } if (!linetarget) { an = source->angle; slope = 0; } } x = source->x; y = source->y; z = source->z + 4*8*FRACUNIT; th = P_SpawnMobj (x,y,z, type); if (th->info->seesound) S_StartSound (th, th->info->seesound); th->target = source; th->angle = an; th->momx = FixedMul (th->info->speed, finecosine[an>>ANGLETOFINESHIFT]); th->momy = FixedMul (th->info->speed, finesine[an>>ANGLETOFINESHIFT]); th->momz = FixedMul (th->info->speed, slope); P_CheckMissileSpawn (th); } \ No newline at end of file diff --git a/P_PLATS.C b/P_PLATS.C new file mode 100644 index 0000000..6b55eb8 --- /dev/null +++ b/P_PLATS.C @@ -0,0 +1 @@ +//================================================================== //================================================================== // // PLATFORM RAISING // //================================================================== //================================================================== #include "doomdef.h" #include "p_local.h" plat_t *activeplats[MAXPLATS]; //================================================================== // // Move a plat up and down // //================================================================== void T_PlatRaise(plat_t *plat) { result_e res; switch(plat->status) { case up: res = T_MovePlane(plat->sector,plat->speed, plat->high,plat->crush,0,1); if (plat->type == raiseAndChange || plat->type == raiseToNearestAndChange) if (!(leveltime&7)) S_StartSound((mobj_t *)&plat->sector->soundorg,sfx_stnmov); if (res == crushed && (!plat->crush)) { plat->count = plat->wait; plat->status = down; S_StartSound((mobj_t *)&plat->sector->soundorg,sfx_pstart); } else if (res == pastdest) { plat->count = plat->wait; plat->status = waiting; S_StartSound((mobj_t *)&plat->sector->soundorg,sfx_pstop); switch(plat->type) { case blazeDWUS: case downWaitUpStay: P_RemoveActivePlat(plat); break; case raiseAndChange: case raiseToNearestAndChange: P_RemoveActivePlat(plat); break; default: break; } } break; case down: res = T_MovePlane(plat->sector,plat->speed,plat->low,false,0,-1); if (res == pastdest) { plat->count = plat->wait; plat->status = waiting; S_StartSound((mobj_t *)&plat->sector->soundorg,sfx_pstop); } break; case waiting: if (!--plat->count) { if (plat->sector->floorheight == plat->low) plat->status = up; else plat->status = down; S_StartSound((mobj_t *)&plat->sector->soundorg,sfx_pstart); } case in_stasis: break; } } //================================================================== // // Do Platforms // "amount" is only used for SOME platforms. // //================================================================== int EV_DoPlat(line_t *line,plattype_e type,int amount) { plat_t *plat; int secnum; int rtn; sector_t *sec; secnum = -1; rtn = 0; // // Activate all plats that are in_stasis // switch(type) { case perpetualRaise: P_ActivateInStasis(line->tag); break; default: break; } while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0) { sec = §ors[secnum]; if (sec->specialdata) continue; // // Find lowest & highest floors around sector // rtn = 1; plat = Z_Malloc( sizeof(*plat), PU_LEVSPEC, 0); P_AddThinker(&plat->thinker); plat->type = type; plat->sector = sec; plat->sector->specialdata = plat; plat->thinker.function = (think_t) T_PlatRaise; plat->crush = false; plat->tag = line->tag; switch(type) { case raiseToNearestAndChange: plat->speed = PLATSPEED/2; sec->floorpic = sides[line->sidenum[0]].sector->floorpic; plat->high = P_FindNextHighestFloor(sec,sec->floorheight); plat->wait = 0; plat->status = up; sec->special = 0; // NO MORE DAMAGE, IF APPLICABLE S_StartSound((mobj_t *)&sec->soundorg,sfx_stnmov); break; case raiseAndChange: plat->speed = PLATSPEED/2; sec->floorpic = sides[line->sidenum[0]].sector->floorpic; plat->high = sec->floorheight + amount*FRACUNIT; plat->wait = 0; plat->status = up; S_StartSound((mobj_t *)&sec->soundorg,sfx_stnmov); break; case downWaitUpStay: plat->speed = PLATSPEED * 4; plat->low = P_FindLowestFloorSurrounding(sec); if (plat->low > sec->floorheight) plat->low = sec->floorheight; plat->high = sec->floorheight; plat->wait = 35*PLATWAIT; plat->status = down; S_StartSound((mobj_t *)&sec->soundorg,sfx_pstart); break; case blazeDWUS: plat->speed = PLATSPEED * 8; plat->low = P_FindLowestFloorSurrounding(sec); if (plat->low > sec->floorheight) plat->low = sec->floorheight; plat->high = sec->floorheight; plat->wait = 35*PLATWAIT; plat->status = down; S_StartSound((mobj_t *)&sec->soundorg,sfx_pstart); break; case perpetualRaise: plat->speed = PLATSPEED; plat->low = P_FindLowestFloorSurrounding(sec); if (plat->low > sec->floorheight) plat->low = sec->floorheight; plat->high = P_FindHighestFloorSurrounding(sec); if (plat->high < sec->floorheight) plat->high = sec->floorheight; plat->wait = 35*PLATWAIT; plat->status = P_Random()&1; S_StartSound((mobj_t *)&sec->soundorg,sfx_pstart); break; } P_AddActivePlat(plat); } return rtn; } void P_ActivateInStasis(int tag) { int i; for (i = 0;i < MAXPLATS;i++) if (activeplats[i] && (activeplats[i])->tag == tag && (activeplats[i])->status == in_stasis) { (activeplats[i])->status = (activeplats[i])->oldstatus; (activeplats[i])->thinker.function = (think_t) T_PlatRaise; } } void EV_StopPlat(line_t *line) { int j; for (j = 0;j < MAXPLATS;j++) if (activeplats[j] && ((activeplats[j])->status != in_stasis) && ((activeplats[j])->tag == line->tag)) { (activeplats[j])->oldstatus = (activeplats[j])->status; (activeplats[j])->status = in_stasis; (activeplats[j])->thinker.function = NULL; } } void P_AddActivePlat(plat_t *plat) { int i; for (i = 0;i < MAXPLATS;i++) if (activeplats[i] == NULL) { activeplats[i] = plat; return; } I_Error ("P_AddActivePlat: no more plats!"); } void P_RemoveActivePlat(plat_t *plat) { int i; for (i = 0;i < MAXPLATS;i++) if (plat == activeplats[i]) { (activeplats[i])->sector->specialdata = NULL; P_RemoveThinker(&(activeplats[i])->thinker); activeplats[i] = NULL; return; } I_Error ("P_RemoveActivePlat: can't find plat!"); } \ No newline at end of file diff --git a/P_PSPR.C b/P_PSPR.C new file mode 100644 index 0000000..09c237b --- /dev/null +++ b/P_PSPR.C @@ -0,0 +1 @@ +// P_pspr.c #include "doomdef.h" #include "p_local.h" #define LOWERSPEED FRACUNIT*6 #define RAISESPEED FRACUNIT*6 #define WEAPONBOTTOM 128*FRACUNIT #define WEAPONTOP 32*FRACUNIT #define BFGCELLS 40 // plasma cells for a bfg attack /* ================== = = P_SetPsprite = ================== */ void P_SetPsprite (player_t *player, int position, statenum_t stnum) { pspdef_t *psp; state_t *state; psp = &player->psprites[position]; do { if (!stnum) { psp->state = NULL; break; // object removed itself } state = &states[stnum]; psp->state = state; psp->tics = state->tics; // could be 0 if (state->misc1) { // coordinate set psp->sx = state->misc1 << FRACBITS; psp->sy = state->misc2 << FRACBITS; } // call action routine if (state->action) { state->action (player, psp); if (!psp->state) break; } stnum = psp->state->nextstate; } while (!psp->tics); // an initial state of 0 could cycle through } /* ================= = = P_CalcSwing = ================= */ fixed_t swingx, swingy; void P_CalcSwing (player_t *player) { fixed_t swing; int angle; // OPTIMIZE: tablify this swing = player->bob; angle = (FINEANGLES/70*leveltime)&FINEMASK; swingx = FixedMul ( swing, finesine[angle]); angle = (FINEANGLES/70*leveltime+FINEANGLES/2)&FINEMASK; swingy = -FixedMul ( swingx, finesine[angle]); } /* =============================================================================== PSPRITE ACTIONS =============================================================================== */ weaponinfo_t weaponinfo[NUMWEAPONS] = { { // fist /* ammo */ am_noammo, /* upstate */ S_PUNCHUP, /* downstate */ S_PUNCHDOWN, /* readystate */ S_PUNCH, /* atkstate */ S_PUNCH1, /* flashstate */ S_NULL }, { // pistol /* ammo */ am_clip, /* upstate */ S_PISTOLUP, /* downstate */ S_PISTOLDOWN, /* readystate */ S_PISTOL, /* atkstate */ S_PISTOL1, /* flashstate */ S_PISTOLFLASH }, { // shotgun /* ammo */ am_shell, /* upstate */ S_SGUNUP, /* downstate */ S_SGUNDOWN, /* readystate */ S_SGUN, /* atkstate */ S_SGUN1, /* flashstate */ S_SGUNFLASH1 }, { // chaingun /* ammo */ am_clip, /* upstate */ S_CHAINUP, /* downstate */ S_CHAINDOWN, /* readystate */ S_CHAIN, /* atkstate */ S_CHAIN1, /* flashstate */ S_CHAINFLASH1 }, { // missile /* ammo */ am_misl, /* upstate */ S_MISSILEUP, /* downstate */ S_MISSILEDOWN, /* readystate */ S_MISSILE, /* atkstate */ S_MISSILE1, /* flashstate */ S_MISSILEFLASH1 }, { // plasma /* ammo */ am_cell, /* upstate */ S_PLASMAUP, /* downstate */ S_PLASMADOWN, /* readystate */ S_PLASMA, /* atkstate */ S_PLASMA1, /* flashstate */ S_PLASMAFLASH1 }, { // bfg /* ammo */ am_cell, /* upstate */ S_BFGUP, /* downstate */ S_BFGDOWN, /* readystate */ S_BFG, /* atkstate */ S_BFG1, /* flashstate */ S_BFGFLASH1 }, { // saw /* ammo */ am_noammo, /* upstate */ S_SAWUP, /* downstate */ S_SAWDOWN, /* readystate */ S_SAW, /* atkstate */ S_SAW1, /* flashstate */ S_NULL }, { // super shotgun /* ammo */ am_shell, /* upstate */ S_DSGUNUP, /* downstate */ S_DSGUNDOWN, /* readystate */ S_DSGUN, /* atkstate */ S_DSGUN1, /* flashstate */ S_DSGUNFLASH1 }, }; /* ================ = = P_BringUpWeapon = = Starts bringing the pending weapon up from the bottom of the screen = Uses player ================ */ void P_BringUpWeapon (player_t *player) { statenum_t newstate; if (player->pendingweapon == wp_nochange) player->pendingweapon = player->readyweapon; if (player->pendingweapon == wp_chainsaw) S_StartSound (player->mo, sfx_sawup); newstate = weaponinfo[player->pendingweapon].upstate; player->pendingweapon = wp_nochange; player->psprites[ps_weapon].sy = WEAPONBOTTOM; P_SetPsprite (player, ps_weapon, newstate); } /* ================ = = P_CheckAmmo = = returns true if there is enough ammo to shoot = if not, selects the next weapon to use ================ */ boolean P_CheckAmmo (player_t *player) { ammotype_t ammo; int count; ammo = weaponinfo[player->readyweapon].ammo; if (player->readyweapon == wp_bfg) count = BFGCELLS; else if (player->readyweapon == wp_supershotgun) count = 2; else count = 1; if (ammo == am_noammo || player->ammo[ammo] >= count) return true; // out of ammo, pick a weapon to change to do { if (player->weaponowned[wp_plasma] && player->ammo[am_cell] && !shareware) player->pendingweapon = wp_plasma; else if (player->weaponowned[wp_supershotgun] && player->ammo[am_shell]>2 && commercial) player->pendingweapon = wp_supershotgun; else if (player->weaponowned[wp_chaingun] && player->ammo[am_clip]) player->pendingweapon = wp_chaingun; else if (player->weaponowned[wp_shotgun] && player->ammo[am_shell]) player->pendingweapon = wp_shotgun; else if (player->ammo[am_clip]) player->pendingweapon = wp_pistol; else if (player->weaponowned[wp_chainsaw]) player->pendingweapon = wp_chainsaw; else if (player->weaponowned[wp_missile] && player->ammo[am_misl]) player->pendingweapon = wp_missile; else if (player->weaponowned[wp_bfg] && player->ammo[am_cell]>40 && !shareware) player->pendingweapon = wp_bfg; else player->pendingweapon = wp_fist; } while (player->pendingweapon == wp_nochange); P_SetPsprite (player, ps_weapon , weaponinfo[player->readyweapon].downstate); return false; } /* ================ = = P_FireWeapon = ================ */ void P_FireWeapon (player_t *player) { statenum_t newstate; if (!P_CheckAmmo (player)) return; P_SetMobjState (player->mo, S_PLAY_ATK1); newstate = weaponinfo[player->readyweapon].atkstate; P_SetPsprite (player, ps_weapon, newstate); P_NoiseAlert (player->mo, player->mo); } /* ================ = = P_DropWeapon = = Player died, so put the weapon away ================ */ void P_DropWeapon (player_t *player) { P_SetPsprite (player, ps_weapon , weaponinfo[player->readyweapon].downstate); } /* ================= = = A_WeaponReady = = The player can fire the weapon or change to another weapon at this time = ================= */ void A_WeaponReady (player_t *player, pspdef_t *psp) { statenum_t newstate; int angle; // // get out of attack state // if (player->mo->state == &states[S_PLAY_ATK1] || player->mo->state == &states[S_PLAY_ATK2] ) P_SetMobjState (player->mo, S_PLAY); if (player->readyweapon == wp_chainsaw && psp->state == &states[S_SAW]) S_StartSound (player->mo, sfx_sawidl); // // check for change // if player is dead, put the weapon away // if (player->pendingweapon != wp_nochange || !player->health) { // change weapon (pending weapon should allready be validated) newstate = weaponinfo[player->readyweapon].downstate; P_SetPsprite (player, ps_weapon, newstate); return; } // // check for fire // // the missile launcher and bfg do not auto fire if (player->cmd.buttons & BT_ATTACK) { if ( !player->attackdown || (player->readyweapon != wp_missile && player->readyweapon != wp_bfg) ) { player->attackdown = true; P_FireWeapon (player); return; } } else player->attackdown = false; // // bob the weapon based on movement speed // angle = (128*leveltime)&FINEMASK; psp->sx = FRACUNIT + FixedMul (player->bob, finecosine[angle]); angle &= FINEANGLES/2-1; psp->sy = WEAPONTOP + FixedMul (player->bob, finesine[angle]); } /* ================= = = A_ReFire = = The player can re fire the weapon without lowering it entirely = ================= */ void A_ReFire (player_t *player, pspdef_t *psp) { // // check for fire (if a weaponchange is pending, let it go through instead) // if ( (player->cmd.buttons & BT_ATTACK) && player->pendingweapon == wp_nochange && player->health) { player->refire++; P_FireWeapon (player); } else { player->refire = 0; P_CheckAmmo (player); } } void A_CheckReload (player_t *player, pspdef_t *psp) { P_CheckAmmo (player); #if 0 if (player->ammo[am_shell]<2) P_SetPsprite (player, ps_weapon, S_DSNR1); #endif } /* ================= = = A_Lower = ================= */ void A_Lower (player_t *player, pspdef_t *psp) { psp->sy += LOWERSPEED; if (psp->sy < WEAPONBOTTOM ) return; if (player->playerstate == PST_DEAD) { psp->sy = WEAPONBOTTOM; return; // don't bring weapon back up } // // The old weapon has been lowered off the screen, so change the weapon // and start raising it // if (!player->health) { // player is dead, so keep the weapon off screen P_SetPsprite (player, ps_weapon, S_NULL); return; } player->readyweapon = player->pendingweapon; P_BringUpWeapon (player); } /* ================= = = A_Raise = ================= */ void A_Raise (player_t *player, pspdef_t *psp) { statenum_t newstate; psp->sy -= RAISESPEED; if (psp->sy > WEAPONTOP ) return; psp->sy = WEAPONTOP; // // the weapon has been raised all the way, so change to the ready state // newstate = weaponinfo[player->readyweapon].readystate; P_SetPsprite (player, ps_weapon, newstate); } /* ================ = = A_GunFlash = ================= */ void A_GunFlash (player_t *player, pspdef_t *psp) { P_SetMobjState (player->mo, S_PLAY_ATK2); P_SetPsprite (player,ps_flash,weaponinfo[player->readyweapon].flashstate); } /* =============================================================================== WEAPON ATTACKS =============================================================================== */ /* ================== = = A_Punch = ================== */ void A_Punch (player_t *player, pspdef_t *psp) { angle_t angle; int damage; int slope; damage = (P_Random ()%10+1)<<1; if (player->powers[pw_strength]) damage *= 10; angle = player->mo->angle; angle += (P_Random()-P_Random())<<18; slope = P_AimLineAttack (player->mo, angle, MELEERANGE); P_LineAttack (player->mo, angle, MELEERANGE, slope, damage); // turn to face target if (linetarget) { S_StartSound (player->mo, sfx_punch); player->mo->angle = R_PointToAngle2 (player->mo->x, player->mo->y, linetarget->x, linetarget->y); } } /* ================== = = A_Saw = ================== */ void A_Saw (player_t *player, pspdef_t *psp) { angle_t angle; int damage; int slope; damage = 2*(P_Random ()%10+1); angle = player->mo->angle; angle += (P_Random()-P_Random())<<18; // use meleerange + 1 se the puff doesn't skip the flash slope = P_AimLineAttack (player->mo, angle, MELEERANGE+1); P_LineAttack (player->mo, angle, MELEERANGE+1, slope, damage); if (!linetarget) { S_StartSound (player->mo, sfx_sawful); return; } S_StartSound (player->mo, sfx_sawhit); // turn to face target angle = R_PointToAngle2 (player->mo->x, player->mo->y, linetarget->x, linetarget->y); if (angle - player->mo->angle > ANG180) { if (angle - player->mo->angle < -ANG90/20) player->mo->angle = angle + ANG90/21; else player->mo->angle -= ANG90/20; } else { if (angle - player->mo->angle > ANG90/20) player->mo->angle = angle - ANG90/21; else player->mo->angle += ANG90/20; } player->mo->flags |= MF_JUSTATTACKED; } /* ================== = = A_FireMissile = ================== */ void A_FireMissile (player_t *player, pspdef_t *psp) { player->ammo[weaponinfo[player->readyweapon].ammo]--; P_SpawnPlayerMissile (player->mo, MT_ROCKET); } /* ================== = = A_FireBFG = ================== */ void A_FireBFG (player_t *player, pspdef_t *psp) { player->ammo[weaponinfo[player->readyweapon].ammo] -= BFGCELLS; P_SpawnPlayerMissile (player->mo, MT_BFG); } /* ================== = = A_FirePlasma = ================== */ void A_FirePlasma (player_t *player, pspdef_t *psp) { player->ammo[weaponinfo[player->readyweapon].ammo]--; P_SetPsprite (player,ps_flash ,weaponinfo[player->readyweapon].flashstate+(P_Random ()&1) ); P_SpawnPlayerMissile (player->mo, MT_PLASMA); } /* =============== = = P_BulletSlope = = Sets a slope so a near miss is at aproximately the height of the = intended target = =============== */ fixed_t bulletslope; void P_BulletSlope (mobj_t *mo) { angle_t an; // // see which target is to be aimed at // an = mo->angle; bulletslope = P_AimLineAttack (mo, an, 16*64*FRACUNIT); if (!linetarget) { an += 1<<26; bulletslope = P_AimLineAttack (mo, an, 16*64*FRACUNIT); if (!linetarget) { an -= 2<<26; bulletslope = P_AimLineAttack (mo, an, 16*64*FRACUNIT); } } } /* =============== = = P_GunShot = =============== */ void P_GunShot (mobj_t *mo, boolean accurate) { angle_t angle; int damage; damage = 5*(P_Random ()%3+1); angle = mo->angle; if (!accurate) angle += (P_Random()-P_Random())<<18; P_LineAttack (mo, angle, MISSILERANGE, bulletslope, damage); } /* ================== = = A_FirePistol = ================== */ void A_FirePistol (player_t *player, pspdef_t *psp) { S_StartSound (player->mo, sfx_pistol); P_SetMobjState (player->mo, S_PLAY_ATK2); player->ammo[weaponinfo[player->readyweapon].ammo]--; P_SetPsprite (player,ps_flash,weaponinfo[player->readyweapon].flashstate); P_BulletSlope (player->mo); P_GunShot (player->mo, !player->refire); } /* ================== = = A_FireShotgun = ================== */ void A_FireShotgun (player_t *player, pspdef_t *psp) { int i; S_StartSound (player->mo, sfx_shotgn); P_SetMobjState (player->mo, S_PLAY_ATK2); player->ammo[weaponinfo[player->readyweapon].ammo]--; P_SetPsprite (player,ps_flash,weaponinfo[player->readyweapon].flashstate); P_BulletSlope (player->mo); for (i=0 ; i<7 ; i++) P_GunShot (player->mo, false); } /* ================== = = A_FireShotgun2 = ================== */ void A_FireShotgun2 (player_t *player, pspdef_t *psp) { int i; angle_t angle; int damage; S_StartSound (player->mo, sfx_dshtgn); P_SetMobjState (player->mo, S_PLAY_ATK2); player->ammo[weaponinfo[player->readyweapon].ammo]-=2; P_SetPsprite (player,ps_flash,weaponinfo[player->readyweapon].flashstate); P_BulletSlope (player->mo); for (i=0 ; i<20 ; i++) { damage = 5*(P_Random ()%3+1); angle = player->mo->angle; angle += (P_Random()-P_Random())<<19; P_LineAttack (player->mo, angle, MISSILERANGE , bulletslope + ((P_Random()-P_Random())<<5), damage); } } /* ================== = = A_FireCGun = ================== */ void A_FireCGun (player_t *player, pspdef_t *psp) { S_StartSound (player->mo, sfx_pistol); if (!player->ammo[weaponinfo[player->readyweapon].ammo]) return; P_SetMobjState (player->mo, S_PLAY_ATK2); player->ammo[weaponinfo[player->readyweapon].ammo]--; P_SetPsprite (player,ps_flash,weaponinfo[player->readyweapon].flashstate + psp->state - &states[S_CHAIN1] ); P_BulletSlope (player->mo); P_GunShot (player->mo, !player->refire); } //============================================================================= void A_Light0 (player_t *player, pspdef_t *psp) { player->extralight = 0; } void A_Light1 (player_t *player, pspdef_t *psp) { player->extralight = 1; } void A_Light2 (player_t *player, pspdef_t *psp) { player->extralight = 2; } /* ================ = = A_BFGSpray = = Spawn a BFG explosion on every monster in view = ================= */ void A_BFGSpray (mobj_t *mo) { int i, j, damage; angle_t an; // offset angles from its attack angle for (i=0 ; i<40 ; i++) { an = mo->angle - ANG90/2 + ANG90/40*i; // mo->target is the originator (player) of the missile P_AimLineAttack (mo->target, an, 16*64*FRACUNIT); if (!linetarget) continue; P_SpawnMobj (linetarget->x, linetarget->y, linetarget->z + (linetarget->height>>2), MT_EXTRABFG); damage = 0; for (j=0;j<15;j++) damage += (P_Random()&7) + 1; P_DamageMobj (linetarget, mo->target,mo->target, damage); } } /* ================ = = A_BFGsound = ================= */ void A_BFGsound (player_t *player, pspdef_t *psp) { S_StartSound (player->mo, sfx_bfg); } //============================================================================= /* ================== = = P_SetupPsprites = = Called at start of level for each player ================== */ void P_SetupPsprites (player_t *player) { int i; // remove all psprites for (i=0 ; ipsprites[i].state = NULL; // spawn the gun player->pendingweapon = player->readyweapon; P_BringUpWeapon (player); } /* ================== = = P_MovePsprites = = Called every tic by player thinking routine ================== */ void P_MovePsprites (player_t *player) { int i; pspdef_t *psp; state_t *state; psp = &player->psprites[0]; for (i=0 ; istate) // a null state means not active { // drop tic count and possibly change state if (psp->tics != -1) // a -1 tic count never changes { psp->tics--; if (!psp->tics) P_SetPsprite (player, i, psp->state->nextstate); } } player->psprites[ps_flash].sx = player->psprites[ps_weapon].sx; player->psprites[ps_flash].sy = player->psprites[ps_weapon].sy; } \ No newline at end of file diff --git a/P_SETUP.C b/P_SETUP.C new file mode 100644 index 0000000..bde6940 --- /dev/null +++ b/P_SETUP.C @@ -0,0 +1 @@ +// P_main.c #include #include "doomdef.h" #include "p_local.h" void P_SpawnMapThing (mapthing_t *mthing); int numvertexes; vertex_t *vertexes; int numsegs; seg_t *segs; int numsectors; sector_t *sectors; int numsubsectors; subsector_t *subsectors; int numnodes; node_t *nodes; int numlines; line_t *lines; int numsides; side_t *sides; short *blockmaplump; // offsets in blockmap are from here short *blockmap; int bmapwidth, bmapheight; // in mapblocks fixed_t bmaporgx, bmaporgy; // origin of block map mobj_t **blocklinks; // for thing chains byte *rejectmatrix; // for fast sight rejection mapthing_t deathmatchstarts[10], *deathmatch_p; mapthing_t playerstarts[MAXPLAYERS]; /* ================= = = P_LoadVertexes = ================= */ void P_LoadVertexes (int lump) { byte *data; int i; mapvertex_t *ml; vertex_t *li; numvertexes = W_LumpLength (lump) / sizeof(mapvertex_t); vertexes = Z_Malloc (numvertexes*sizeof(vertex_t),PU_LEVEL,0); data = W_CacheLumpNum (lump,PU_STATIC); ml = (mapvertex_t *)data; li = vertexes; for (i=0 ; ix = SHORT(ml->x)<y = SHORT(ml->y)<v1 = &vertexes[SHORT(ml->v1)]; li->v2 = &vertexes[SHORT(ml->v2)]; li->angle = (SHORT(ml->angle))<<16; li->offset = (SHORT(ml->offset))<<16; linedef = SHORT(ml->linedef); ldef = &lines[linedef]; li->linedef = ldef; side = SHORT(ml->side); li->sidedef = &sides[ldef->sidenum[side]]; li->frontsector = sides[ldef->sidenum[side]].sector; if (ldef-> flags & ML_TWOSIDED) li->backsector = sides[ldef->sidenum[side^1]].sector; else li->backsector = 0; } Z_Free (data); } /* ================= = = P_LoadSubsectors = ================= */ void P_LoadSubsectors (int lump) { byte *data; int i; mapsubsector_t *ms; subsector_t *ss; numsubsectors = W_LumpLength (lump) / sizeof(mapsubsector_t); subsectors = Z_Malloc (numsubsectors*sizeof(subsector_t),PU_LEVEL,0); data = W_CacheLumpNum (lump,PU_STATIC); ms = (mapsubsector_t *)data; memset (subsectors,0, numsubsectors*sizeof(subsector_t)); ss = subsectors; for (i=0 ; inumlines = SHORT(ms->numsegs); ss->firstline = SHORT(ms->firstseg); } Z_Free (data); } /* ================= = = P_LoadSectors = ================= */ void P_LoadSectors (int lump) { byte *data; int i; mapsector_t *ms; sector_t *ss; numsectors = W_LumpLength (lump) / sizeof(mapsector_t); sectors = Z_Malloc (numsectors*sizeof(sector_t),PU_LEVEL,0); memset (sectors, 0, numsectors*sizeof(sector_t)); data = W_CacheLumpNum (lump,PU_STATIC); ms = (mapsector_t *)data; ss = sectors; for (i=0 ; ifloorheight = SHORT(ms->floorheight)<ceilingheight = SHORT(ms->ceilingheight)<floorpic = R_FlatNumForName(ms->floorpic); ss->ceilingpic = R_FlatNumForName(ms->ceilingpic); ss->lightlevel = SHORT(ms->lightlevel); ss->special = SHORT(ms->special); ss->tag = SHORT(ms->tag); ss->thinglist = NULL; } Z_Free (data); } /* ================= = = P_LoadNodes = ================= */ void P_LoadNodes (int lump) { byte *data; int i,j,k; mapnode_t *mn; node_t *no; numnodes = W_LumpLength (lump) / sizeof(mapnode_t); nodes = Z_Malloc (numnodes*sizeof(node_t),PU_LEVEL,0); data = W_CacheLumpNum (lump,PU_STATIC); mn = (mapnode_t *)data; no = nodes; for (i=0 ; ix = SHORT(mn->x)<y = SHORT(mn->y)<dx = SHORT(mn->dx)<dy = SHORT(mn->dy)<children[j] = SHORT(mn->children[j]); for (k=0 ; k<4 ; k++) no->bbox[j][k] = SHORT(mn->bbox[j][k])<type) { case 68: // Arachnotron case 64: // Archvile case 88: // Boss Brain case 89: // Boss Shooter case 69: // Hell Knight case 67: // Mancubus case 71: // Pain Elemental case 65: // Former Human Commando case 66: // Revenant case 84: // Wolf SS spawn = false; } if (spawn == false) break; mt->x = SHORT(mt->x); mt->y = SHORT(mt->y); mt->angle = SHORT(mt->angle); mt->type = SHORT(mt->type); mt->options = SHORT(mt->options); P_SpawnMapThing (mt); } Z_Free (data); } /* ================= = = P_LoadLineDefs = = Also counts secret lines for intermissions ================= */ void P_LoadLineDefs (int lump) { byte *data; int i; maplinedef_t *mld; line_t *ld; vertex_t *v1, *v2; numlines = W_LumpLength (lump) / sizeof(maplinedef_t); lines = Z_Malloc (numlines*sizeof(line_t),PU_LEVEL,0); memset (lines, 0, numlines*sizeof(line_t)); data = W_CacheLumpNum (lump,PU_STATIC); mld = (maplinedef_t *)data; ld = lines; for (i=0 ; iflags = SHORT(mld->flags); ld->special = SHORT(mld->special); ld->tag = SHORT(mld->tag); v1 = ld->v1 = &vertexes[SHORT(mld->v1)]; v2 = ld->v2 = &vertexes[SHORT(mld->v2)]; ld->dx = v2->x - v1->x; ld->dy = v2->y - v1->y; if (!ld->dx) ld->slopetype = ST_VERTICAL; else if (!ld->dy) ld->slopetype = ST_HORIZONTAL; else { if (FixedDiv (ld->dy , ld->dx) > 0) ld->slopetype = ST_POSITIVE; else ld->slopetype = ST_NEGATIVE; } if (v1->x < v2->x) { ld->bbox[BOXLEFT] = v1->x; ld->bbox[BOXRIGHT] = v2->x; } else { ld->bbox[BOXLEFT] = v2->x; ld->bbox[BOXRIGHT] = v1->x; } if (v1->y < v2->y) { ld->bbox[BOXBOTTOM] = v1->y; ld->bbox[BOXTOP] = v2->y; } else { ld->bbox[BOXBOTTOM] = v2->y; ld->bbox[BOXTOP] = v1->y; } ld->sidenum[0] = SHORT(mld->sidenum[0]); ld->sidenum[1] = SHORT(mld->sidenum[1]); if (ld->sidenum[0] != -1) ld->frontsector = sides[ld->sidenum[0]].sector; else ld->frontsector = 0; if (ld->sidenum[1] != -1) ld->backsector = sides[ld->sidenum[1]].sector; else ld->backsector = 0; } Z_Free (data); } /* ================= = = P_LoadSideDefs = ================= */ void P_LoadSideDefs (int lump) { byte *data; int i; mapsidedef_t *msd; side_t *sd; numsides = W_LumpLength (lump) / sizeof(mapsidedef_t); sides = Z_Malloc (numsides*sizeof(side_t),PU_LEVEL,0); memset (sides, 0, numsides*sizeof(side_t)); data = W_CacheLumpNum (lump,PU_STATIC); msd = (mapsidedef_t *)data; sd = sides; for (i=0 ; itextureoffset = SHORT(msd->textureoffset)<rowoffset = SHORT(msd->rowoffset)<toptexture = R_TextureNumForName(msd->toptexture); sd->bottomtexture = R_TextureNumForName(msd->bottomtexture); sd->midtexture = R_TextureNumForName(msd->midtexture); sd->sector = §ors[SHORT(msd->sector)]; } Z_Free (data); } /* ================= = = P_LoadBlockMap = ================= */ void P_LoadBlockMap (int lump) { int i, count; blockmaplump = W_CacheLumpNum (lump,PU_LEVEL); blockmap = blockmaplump+4; count = W_LumpLength (lump)/2; for (i=0 ; ifirstline]; ss->sector = seg->sidedef->sector; } // count number of lines in each sector li = lines; total = 0; for (i=0 ; ifrontsector->linecount++; if (li->backsector && li->backsector != li->frontsector) { li->backsector->linecount++; total++; } } // build line tables for each sector linebuffer = Z_Malloc (total*4, PU_LEVEL, 0); sector = sectors; for (i=0 ; ilines = linebuffer; li = lines; for (j=0 ; jfrontsector == sector || li->backsector == sector) { *linebuffer++ = li; M_AddToBox (bbox, li->v1->x, li->v1->y); M_AddToBox (bbox, li->v2->x, li->v2->y); } } if (linebuffer - sector->lines != sector->linecount) I_Error ("P_GroupLines: miscounted"); // set the degenmobj_t to the middle of the bounding box sector->soundorg.x = (bbox[BOXRIGHT]+bbox[BOXLEFT])/2; sector->soundorg.y = (bbox[BOXTOP]+bbox[BOXBOTTOM])/2; // adjust bounding box to map blocks block = (bbox[BOXTOP]-bmaporgy+MAXRADIUS)>>MAPBLOCKSHIFT; block = block >= bmapheight ? bmapheight-1 : block; sector->blockbox[BOXTOP]=block; block = (bbox[BOXBOTTOM]-bmaporgy-MAXRADIUS)>>MAPBLOCKSHIFT; block = block < 0 ? 0 : block; sector->blockbox[BOXBOTTOM]=block; block = (bbox[BOXRIGHT]-bmaporgx+MAXRADIUS)>>MAPBLOCKSHIFT; block = block >= bmapwidth ? bmapwidth-1 : block; sector->blockbox[BOXRIGHT]=block; block = (bbox[BOXLEFT]-bmaporgx-MAXRADIUS)>>MAPBLOCKSHIFT; block = block < 0 ? 0 : block; sector->blockbox[BOXLEFT]=block; } } //============================================================================= /* ================= = = P_SetupLevel = ================= */ void P_SetupLevel (int episode, int map, int playermask, skill_t skill) { int i; char lumpname[9]; int lumpnum; totalkills = totalitems = totalsecret = wminfo.maxfrags = 0; wminfo.partime = 180; for (i=0 ; idx) { if (x==node->x) return 2; if (x <= node->x) return node->dy > 0; return node->dy < 0; } if (!node->dy) { if (x==node->y) return 2; if (y <= node->y) return node->dx < 0; return node->dx > 0; } dx = (x - node->x); dy = (y - node->y); left = (node->dy>>FRACBITS) * (dx>>FRACBITS); right = (dy>>FRACBITS) * (node->dx>>FRACBITS); if (right < left) return 0; // front side if (left == right) return 2; return 1; // back side } /* =============== = = P_InterceptVector2 = = Returns the fractional intercept point along the first divline = = This is only called by the addthings and addlines traversers =============== */ fixed_t P_InterceptVector2 (divline_t *v2, divline_t *v1) { fixed_t frac, num, den; den = FixedMul (v1->dy>>8,v2->dx) - FixedMul(v1->dx>>8,v2->dy); if (den == 0) return 0; // I_Error ("P_InterceptVector: parallel"); num = FixedMul ( (v1->x - v2->x)>>8 ,v1->dy) + FixedMul ( (v2->y - v1->y)>>8 , v1->dx); frac = FixedDiv (num , den); return frac; } /* ================= = = P_CrossSubsector = = Returns true if strace crosses the given subsector successfuly ================= */ boolean P_CrossSubsector (int num) { seg_t *seg; line_t *line; int s1, s2; int count; subsector_t *sub; sector_t *front, *back; fixed_t opentop, openbottom; divline_t divl; vertex_t *v1, *v2; fixed_t frac, slope; #ifdef RANGECHECK if (num>=numsubsectors) I_Error ("P_CrossSubsector: ss %i with numss = %i",num, numsubsectors); #endif sub = &subsectors[num]; // // check lines // count = sub->numlines; seg = &segs[sub->firstline]; for ( ; count ; seg++, count--) { line = seg->linedef; if (line->validcount == validcount) continue; // allready checked other side line->validcount = validcount; v1 = line->v1; v2 = line->v2; s1 = P_DivlineSide (v1->x,v1->y, &strace); s2 = P_DivlineSide (v2->x, v2->y, &strace); if (s1 == s2) continue; // line isn't crossed divl.x = v1->x; divl.y = v1->y; divl.dx = v2->x - v1->x; divl.dy = v2->y - v1->y; s1 = P_DivlineSide (strace.x, strace.y, &divl); s2 = P_DivlineSide (t2x, t2y, &divl); if (s1 == s2) continue; // line isn't crossed if ( !(line->flags & ML_TWOSIDED) ) return false; // stop // // crosses a two sided line // front = seg->frontsector; back = seg->backsector; if (front->floorheight == back->floorheight && front->ceilingheight == back->ceilingheight) continue; // no wall to block sight with if (front->ceilingheight < back->ceilingheight) opentop = front->ceilingheight; else opentop = back->ceilingheight; if (front->floorheight > back->floorheight) openbottom = front->floorheight; else openbottom = back->floorheight; if (openbottom >= opentop) // quick test for totally closed doors return false; // stop frac = P_InterceptVector2 (&strace, &divl); if (front->floorheight != back->floorheight) { slope = FixedDiv (openbottom - sightzstart , frac); if (slope > bottomslope) bottomslope = slope; } if (front->ceilingheight != back->ceilingheight) { slope = FixedDiv (opentop - sightzstart , frac); if (slope < topslope) topslope = slope; } if (topslope <= bottomslope) return false; // stop } return true; // passed the subsector ok } /* ================= = = P_CrossBSPNode = = Returns true if strace crosses the given node successfuly ================= */ boolean P_CrossBSPNode (int bspnum) { node_t *bsp; int side; if (bspnum & NF_SUBSECTOR) { if (bspnum == -1) return P_CrossSubsector (0); else return P_CrossSubsector (bspnum&(~NF_SUBSECTOR)); } bsp = &nodes[bspnum]; // // decide which side the start point is on // side = P_DivlineSide (strace.x, strace.y, (divline_t *)bsp); if (side == 2) side = 0; // an "on" should cross both sides // cross the starting side if (!P_CrossBSPNode (bsp->children[side]) ) return false; // the partition plane is crossed here if (side == P_DivlineSide (t2x, t2y,(divline_t *)bsp)) return true; // the line doesn't touch the other side // cross the ending side return P_CrossBSPNode (bsp->children[side^1]); } /* ===================== = = P_CheckSight = = Returns true if a straight line between t1 and t2 is unobstructed = ===================== */ boolean P_CheckSight (mobj_t *t1, mobj_t *t2) { int s1, s2; int pnum, bytenum, bitnum; // // check for trivial rejection // s1 = (t1->subsector->sector - sectors); s2 = (t2->subsector->sector - sectors); pnum = s1*numsectors + s2; bytenum = pnum>>3; bitnum = 1 << (pnum&7); if (rejectmatrix[bytenum]&bitnum) { sightcounts[0]++; return false; // can't possibly be connected } // look from eyes of t1 to any part of t2 sightcounts[1]++; validcount++; sightzstart = t1->z + t1->height - (t1->height>>2); topslope = (t2->z+t2->height) - sightzstart; bottomslope = (t2->z) - sightzstart; strace.x = t1->x; strace.y = t1->y; t2x = t2->x; t2y = t2->y; strace.dx = t2->x - t1->x; strace.dy = t2->y - t1->y; return P_CrossBSPNode (numnodes-1); // the head node is the last node output } \ No newline at end of file diff --git a/P_SPEC.C b/P_SPEC.C new file mode 100644 index 0000000..9723369 --- /dev/null +++ b/P_SPEC.C @@ -0,0 +1 @@ +// P_Spec.c #include "doomdef.h" #include "p_local.h" /* =================== = = P_InitPicAnims = =================== */ animdef_t animdefs[] = { {false, "NUKAGE3", "NUKAGE1", 8}, {false, "FWATER4", "FWATER1", 8}, {false, "SWATER4", "SWATER1", 8}, {false, "LAVA4", "LAVA1", 8}, {false, "BLOOD3", "BLOOD1", 8}, {false, "RROCK08", "RROCK05", 8}, // DOOM II flat anims {false, "SLIME04", "SLIME01", 8}, {false, "SLIME08", "SLIME05", 8}, {false, "SLIME12", "SLIME09", 8}, {true, "BLODGR4", "BLODGR1", 8}, {true, "SLADRIP3", "SLADRIP1", 8}, {true, "BLODRIP4", "BLODRIP1", 8}, {true, "FIREWALL", "FIREWALA", 8}, {true, "GSTFONT3", "GSTFONT1", 8}, {true, "FIRELAVA", "FIRELAV3", 8}, {true, "FIREMAG3", "FIREMAG1", 8}, {true, "FIREBLU2", "FIREBLU1", 8}, {true, "ROCKRED3", "ROCKRED1", 8}, {true, "BFALL4", "BFALL1", 8}, {true, "SFALL4", "SFALL1", 8}, {true, "WFALL4", "WFALL1", 8}, {true, "DBRAIN4", "DBRAIN1", 8}, {-1} }; anim_t anims[MAXANIMS], *lastanim; void P_InitPicAnims (void) { int i; // // Init animation // lastanim = anims; for (i=0 ; animdefs[i].istexture != -1 ; i++) { if (animdefs[i].istexture) { if (R_CheckTextureNumForName(animdefs[i].startname) == -1) continue; // different episode lastanim->picnum = R_TextureNumForName (animdefs[i].endname); lastanim->basepic = R_TextureNumForName (animdefs[i].startname); } else { if (W_CheckNumForName(animdefs[i].startname) == -1) continue; lastanim->picnum = R_FlatNumForName (animdefs[i].endname); lastanim->basepic = R_FlatNumForName (animdefs[i].startname); } lastanim->istexture = animdefs[i].istexture; lastanim->numpics = lastanim->picnum - lastanim->basepic + 1; if (lastanim->numpics < 2) I_Error ("P_InitPicAnims: bad cycle from %s to %s" , animdefs[i].startname, animdefs[i].endname); lastanim->speed = animdefs[i].speed; lastanim++; } } /* ============================================================================== UTILITIES ============================================================================== */ // // Will return a side_t* given the number of the current sector, // the line number, and the side (0/1) that you want. // side_t *getSide(int currentSector,int line, int side) { return &sides[ (sectors[currentSector].lines[line])->sidenum[side] ]; } // // Will return a sector_t* given the number of the current sector, // the line number and the side (0/1) that you want. // sector_t *getSector(int currentSector,int line,int side) { return sides[ (sectors[currentSector].lines[line])->sidenum[side] ].sector; } // // Given the sector number and the line number, will tell you whether // the line is two-sided or not. // int twoSided(int sector,int line) { return (sectors[sector].lines[line])->flags & ML_TWOSIDED; } //================================================================== // // Return sector_t * of sector next to current. NULL if not two-sided line // //================================================================== sector_t *getNextSector(line_t *line,sector_t *sec) { if (!(line->flags & ML_TWOSIDED)) return NULL; if (line->frontsector == sec) return line->backsector; return line->frontsector; } //================================================================== // // FIND LOWEST FLOOR HEIGHT IN SURROUNDING SECTORS // //================================================================== fixed_t P_FindLowestFloorSurrounding(sector_t *sec) { int i; line_t *check; sector_t *other; fixed_t floor = sec->floorheight; for (i=0 ;i < sec->linecount ; i++) { check = sec->lines[i]; other = getNextSector(check,sec); if (!other) continue; if (other->floorheight < floor) floor = other->floorheight; } return floor; } //================================================================== // // FIND HIGHEST FLOOR HEIGHT IN SURROUNDING SECTORS // //================================================================== fixed_t P_FindHighestFloorSurrounding(sector_t *sec) { int i; line_t *check; sector_t *other; fixed_t floor = -500*FRACUNIT; for (i=0 ;i < sec->linecount ; i++) { check = sec->lines[i]; other = getNextSector(check,sec); if (!other) continue; if (other->floorheight > floor) floor = other->floorheight; } return floor; } //================================================================== // // FIND NEXT HIGHEST FLOOR IN SURROUNDING SECTORS // //================================================================== fixed_t P_FindNextHighestFloor(sector_t *sec,int currentheight) { int i; int h; int min; line_t *check; sector_t *other; fixed_t height = currentheight; fixed_t heightlist[20]; // 20 adjoining sectors max! for (i =0,h = 0 ;i < sec->linecount ; i++) { check = sec->lines[i]; other = getNextSector(check,sec); if (!other) continue; if (other->floorheight > height) heightlist[h++] = other->floorheight; } // // Find lowest height in list // if (!h) return currentheight; min = heightlist[0]; for (i = 1;i < h;i++) if (heightlist[i] < min) min = heightlist[i]; return min; } //================================================================== // // FIND LOWEST CEILING IN THE SURROUNDING SECTORS // //================================================================== fixed_t P_FindLowestCeilingSurrounding(sector_t *sec) { int i; line_t *check; sector_t *other; fixed_t height = MAXINT; for (i=0 ;i < sec->linecount ; i++) { check = sec->lines[i]; other = getNextSector(check,sec); if (!other) continue; if (other->ceilingheight < height) height = other->ceilingheight; } return height; } //================================================================== // // FIND HIGHEST CEILING IN THE SURROUNDING SECTORS // //================================================================== fixed_t P_FindHighestCeilingSurrounding(sector_t *sec) { int i; line_t *check; sector_t *other; fixed_t height = 0; for (i=0 ;i < sec->linecount ; i++) { check = sec->lines[i]; other = getNextSector(check,sec); if (!other) continue; if (other->ceilingheight > height) height = other->ceilingheight; } return height; } //================================================================== // // RETURN NEXT SECTOR # THAT LINE TAG REFERS TO // //================================================================== int P_FindSectorFromLineTag(line_t *line,int start) { int i; for (i=start+1;itag) return i; return -1; } //================================================================== // // Find minimum light from an adjacent sector // //================================================================== int P_FindMinSurroundingLight(sector_t *sector,int max) { int i; int min; line_t *line; sector_t *check; min = max; for (i=0 ; i < sector->linecount ; i++) { line = sector->lines[i]; check = getNextSector(line,sector); if (!check) continue; if (check->lightlevel < min) min = check->lightlevel; } return min; } /* ============================================================================== EVENTS Events are operations triggered by using, crossing, or shooting special lines, or by timed thinkers ============================================================================== */ /* =============================================================================== = = P_CrossSpecialLine - TRIGGER = = Called every time a thing origin is about to cross = a line with a non 0 special = =============================================================================== */ void P_CrossSpecialLine (int linenum, int side,mobj_t *thing) { line_t *line; int ok; line = &lines[linenum]; // // Triggers that other things can activate // if (!thing->player) { // Things that should NOT trigger specials... switch(thing->type) { case MT_ROCKET: case MT_PLASMA: case MT_BFG: case MT_TROOPSHOT: case MT_HEADSHOT: case MT_BRUISERSHOT: return; default: break; } ok = 0; switch(line->special) { case 39: // TELEPORT TRIGGER case 97: // TELEPORT RETRIGGER case 125: // TELEPORT MONSTERONLY TRIGGER case 126: // TELEPORT MONSTERONLY RETRIGGER case 4: // RAISE DOOR case 10: // PLAT DOWN-WAIT-UP-STAY TRIGGER case 88: // PLAT DOWN-WAIT-UP-STAY RETRIGGER ok = 1; break; } if (!ok) return; } switch (line->special) { //==================================================== // TRIGGERS //==================================================== case 2: // Open Door EV_DoDoor(line,open); line->special = 0; break; case 3: // Close Door EV_DoDoor(line,close); line->special = 0; break; case 4: // Raise Door EV_DoDoor(line,normal); line->special = 0; break; case 5: // Raise Floor EV_DoFloor(line,raiseFloor); line->special = 0; break; case 6: // Fast Ceiling Crush & Raise EV_DoCeiling(line,fastCrushAndRaise); line->special = 0; break; case 8: // Build Stairs EV_BuildStairs(line,build8); line->special = 0; break; case 10: // PlatDownWaitUp EV_DoPlat(line,downWaitUpStay,0); line->special = 0; break; case 12: // Light Turn On - brightest near EV_LightTurnOn(line,0); line->special = 0; break; case 13: // Light Turn On 255 EV_LightTurnOn(line,255); line->special = 0; break; case 16: // Close Door 30 EV_DoDoor(line,close30ThenOpen); line->special = 0; break; case 17: // Start Light Strobing EV_StartLightStrobing(line); line->special = 0; break; case 19: // Lower Floor EV_DoFloor(line,lowerFloor); line->special = 0; break; case 22: // Raise floor to nearest height and change texture EV_DoPlat(line,raiseToNearestAndChange,0); line->special = 0; break; case 25: // Ceiling Crush and Raise EV_DoCeiling(line,crushAndRaise); line->special = 0; break; case 30: // Raise floor to shortest texture height // on either side of lines EV_DoFloor(line,raiseToTexture); line->special = 0; break; case 35: // Lights Very Dark EV_LightTurnOn(line,35); line->special = 0; break; case 36: // Lower Floor (TURBO) EV_DoFloor(line,turboLower); line->special = 0; break; case 37: // LowerAndChange EV_DoFloor(line,lowerAndChange); line->special = 0; break; case 38: // Lower Floor To Lowest EV_DoFloor( line, lowerFloorToLowest ); line->special = 0; break; case 39: // TELEPORT! EV_Teleport( line, side, thing ); line->special = 0; break; case 40: // RaiseCeilingLowerFloor EV_DoCeiling( line, raiseToHighest ); EV_DoFloor( line, lowerFloorToLowest ); line->special = 0; break; case 44: // Ceiling Crush EV_DoCeiling( line, lowerAndCrush ); line->special = 0; break; case 52: // EXIT! G_ExitLevel (); break; case 53: // Perpetual Platform Raise EV_DoPlat(line,perpetualRaise,0); line->special = 0; break; case 54: // Platform Stop EV_StopPlat(line); line->special = 0; break; case 56: // Raise Floor Crush EV_DoFloor(line,raiseFloorCrush); line->special = 0; break; case 57: // Ceiling Crush Stop EV_CeilingCrushStop(line); line->special = 0; break; case 58: // Raise Floor 24 EV_DoFloor(line,raiseFloor24); line->special = 0; break; case 59: // Raise Floor 24 And Change EV_DoFloor(line,raiseFloor24AndChange); line->special = 0; break; case 104: // Turn lights off in sector(tag) EV_TurnTagLightsOff(line); line->special = 0; break; case 108: // Blazing Door Raise (faster than TURBO!) EV_DoDoor (line,blazeRaise); line->special = 0; break; case 109: // Blazing Door Open (faster than TURBO!) EV_DoDoor (line,blazeOpen); line->special = 0; break; case 100: // Build Stairs Turbo 16 EV_BuildStairs(line,turbo16); line->special = 0; break; case 110: // Blazing Door Close (faster than TURBO!) EV_DoDoor (line,blazeClose); line->special = 0; break; case 119: // Raise floor to nearest surr. floor EV_DoFloor(line,raiseFloorToNearest); line->special = 0; break; case 121: // Blazing PlatDownWaitUpStay EV_DoPlat(line,blazeDWUS,0); line->special = 0; break; case 124: // Secret EXIT G_SecretExitLevel (); break; case 125: // TELEPORT MonsterONLY if (!thing->player) { EV_Teleport( line, side, thing ); line->special = 0; } break; case 130: // Raise Floor Turbo EV_DoFloor(line,raiseFloorTurbo); line->special = 0; break; case 141: // Silent Ceiling Crush & Raise EV_DoCeiling(line,silentCrushAndRaise); line->special = 0; break; //==================================================== // RETRIGGERS //==================================================== case 72: // Ceiling Crush EV_DoCeiling( line, lowerAndCrush ); break; case 73: // Ceiling Crush and Raise EV_DoCeiling(line,crushAndRaise); break; case 74: // Ceiling Crush Stop EV_CeilingCrushStop(line); break; case 75: // Close Door EV_DoDoor(line,close); break; case 76: // Close Door 30 EV_DoDoor(line,close30ThenOpen); break; case 77: // Fast Ceiling Crush & Raise EV_DoCeiling(line,fastCrushAndRaise); break; case 79: // Lights Very Dark EV_LightTurnOn(line,35); break; case 80: // Light Turn On - brightest near EV_LightTurnOn(line,0); break; case 81: // Light Turn On 255 EV_LightTurnOn(line,255); break; case 82: // Lower Floor To Lowest EV_DoFloor( line, lowerFloorToLowest ); break; case 83: // Lower Floor EV_DoFloor(line,lowerFloor); break; case 84: // LowerAndChange EV_DoFloor(line,lowerAndChange); break; case 86: // Open Door EV_DoDoor(line,open); break; case 87: // Perpetual Platform Raise EV_DoPlat(line,perpetualRaise,0); break; case 88: // PlatDownWaitUp EV_DoPlat(line,downWaitUpStay,0); break; case 89: // Platform Stop EV_StopPlat(line); break; case 90: // Raise Door EV_DoDoor(line,normal); break; case 91: // Raise Floor EV_DoFloor(line,raiseFloor); break; case 92: // Raise Floor 24 EV_DoFloor(line,raiseFloor24); break; case 93: // Raise Floor 24 And Change EV_DoFloor(line,raiseFloor24AndChange); break; case 94: // Raise Floor Crush EV_DoFloor(line,raiseFloorCrush); break; case 95: // Raise floor to nearest height and change texture EV_DoPlat(line,raiseToNearestAndChange,0); break; case 96: // Raise floor to shortest texture height // on either side of lines EV_DoFloor(line,raiseToTexture); break; case 97: // TELEPORT! EV_Teleport( line, side, thing ); break; case 98: // Lower Floor (TURBO) EV_DoFloor(line,turboLower); break; case 105: // Blazing Door Raise (faster than TURBO!) EV_DoDoor (line,blazeRaise); break; case 106: // Blazing Door Open (faster than TURBO!) EV_DoDoor (line,blazeOpen); break; case 107: // Blazing Door Close (faster than TURBO!) EV_DoDoor (line,blazeClose); break; case 120: // Blazing PlatDownWaitUpStay EV_DoPlat(line,blazeDWUS,0); break; case 126: // TELEPORT MonsterONLY if (!thing->player) EV_Teleport( line, side, thing ); break; case 128: // Raise To Nearest Floor EV_DoFloor(line,raiseFloorToNearest); break; case 129: // Raise Floor Turbo EV_DoFloor(line,raiseFloorTurbo); break; } } /* =============================================================================== = = P_ShootSpecialLine - IMPACT SPECIALS = = Called when a thing shoots a special line = =============================================================================== */ void P_ShootSpecialLine ( mobj_t *thing, line_t *line) { int ok; // // Impacts that other things can activate // if (!thing->player) { ok = 0; switch(line->special) { case 46: // OPEN DOOR IMPACT ok = 1; break; } if (!ok) return; } switch(line->special) { case 24: // RAISE FLOOR EV_DoFloor(line,raiseFloor); P_ChangeSwitchTexture(line,0); break; case 46: // OPEN DOOR EV_DoDoor(line,open); P_ChangeSwitchTexture(line,1); break; case 47: // RAISE FLOOR NEAR AND CHANGE EV_DoPlat(line,raiseToNearestAndChange,0); P_ChangeSwitchTexture(line,0); break; } } /* =============================================================================== = = P_PlayerInSpecialSector = = Called every tic frame that the player origin is in a special sector = =============================================================================== */ void P_PlayerInSpecialSector (player_t *player) { sector_t *sector; sector = player->mo->subsector->sector; if (player->mo->z != sector->floorheight) return; // not all the way down yet switch (sector->special) { case 5: // HELLSLIME DAMAGE if (!player->powers[pw_ironfeet]) if (!(leveltime&0x1f)) P_DamageMobj (player->mo, NULL, NULL, 10); break; case 7: // NUKAGE DAMAGE if (!player->powers[pw_ironfeet]) if (!(leveltime&0x1f)) P_DamageMobj (player->mo, NULL, NULL, 5); break; case 16: // SUPER HELLSLIME DAMAGE case 4: // STROBE HURT if (!player->powers[pw_ironfeet] || (P_Random()<5) ) if (!(leveltime&0x1f)) P_DamageMobj (player->mo, NULL, NULL, 20); break; case 9: // SECRET SECTOR player->secretcount++; sector->special = 0; break; case 11: // EXIT SUPER DAMAGE! (for E1M8 finale) player->cheats &= ~CF_GODMODE; if (!(leveltime&0x1f)) P_DamageMobj (player->mo, NULL, NULL, 20); if (player->health <= 10) G_ExitLevel(); break; default: I_Error ("P_PlayerInSpecialSector: " "unknown special %i",sector->special); }; } /* =============================================================================== = = P_UpdateSpecials = = Animate planes, scroll walls, etc =============================================================================== */ boolean levelTimer; int levelTimeCount; void P_UpdateSpecials (void) { anim_t *anim; int pic; int i; line_t *line; // // LEVEL TIMER // if (levelTimer == true) { levelTimeCount--; if (!levelTimeCount) G_ExitLevel(); } // // ANIMATE FLATS AND TEXTURES GLOBALY // for (anim = anims ; anim < lastanim ; anim++) { for (i=anim->basepic ; ibasepic+anim->numpics ; i++) { pic = anim->basepic + ( (leveltime/anim->speed + i)%anim->numpics ); if (anim->istexture) texturetranslation[i] = pic; else flattranslation[i] = pic; } } // // ANIMATE LINE SPECIALS // for (i = 0; i < numlinespecials; i++) { line = linespeciallist[i]; switch(line->special) { case 48: // EFFECT FIRSTCOL SCROLL + sides[line->sidenum[0]].textureoffset += FRACUNIT; break; } } // // DO BUTTONS // for (i = 0; i < MAXBUTTONS; i++) if (buttonlist[i].btimer) { buttonlist[i].btimer--; if (!buttonlist[i].btimer) { switch(buttonlist[i].where) { case top: sides[buttonlist[i].line->sidenum[0]].toptexture = buttonlist[i].btexture; break; case middle: sides[buttonlist[i].line->sidenum[0]].midtexture = buttonlist[i].btexture; break; case bottom: sides[buttonlist[i].line->sidenum[0]].bottomtexture = buttonlist[i].btexture; break; } S_StartSound((mobj_t *)&buttonlist[i].soundorg,sfx_swtchn); memset(&buttonlist[i],0,sizeof(button_t)); } } } //============================================================ // // Special Stuff that can't be categorized // //============================================================ int EV_DoDonut(line_t *line) { sector_t *s1; sector_t *s2; sector_t *s3; int secnum; int rtn; int i; floormove_t *floor; secnum = -1; rtn = 0; while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0) { s1 = §ors[secnum]; // ALREADY MOVING? IF SO, KEEP GOING... if (s1->specialdata) continue; rtn = 1; s2 = getNextSector(s1->lines[0],s1); for (i = 0;i < s2->linecount;i++) { if ((!s2->lines[i]->flags & ML_TWOSIDED) || (s2->lines[i]->backsector == s1)) continue; s3 = s2->lines[i]->backsector; // // Spawn rising slime // floor = Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0); P_AddThinker (&floor->thinker); s2->specialdata = floor; floor->thinker.function = (think_t) T_MoveFloor; floor->type = donutRaise; floor->crush = false; floor->direction = 1; floor->sector = s2; floor->speed = FLOORSPEED / 2; floor->texture = s3->floorpic; floor->newspecial = 0; floor->floordestheight = s3->floorheight; // // Spawn lowering donut-hole // floor = Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0); P_AddThinker (&floor->thinker); s1->specialdata = floor; floor->thinker.function = (think_t) T_MoveFloor; floor->type = lowerFloor; floor->crush = false; floor->direction = -1; floor->sector = s1; floor->speed = FLOORSPEED / 2; floor->floordestheight = s3->floorheight; break; } } return rtn; } /* ============================================================================== SPECIAL SPAWNING ============================================================================== */ /* ================================================================================ = P_SpawnSpecials = = After the map has been loaded, scan for specials that = spawn thinkers = =============================================================================== */ short numlinespecials; line_t *linespeciallist[MAXLINEANIMS]; void P_SpawnSpecials (void) { sector_t *sector; int i; int episode; episode = 1; if (W_CheckNumForName("texture2") >= 0) episode = 2; // // See if -TIMER needs to be used // levelTimer = false; i = M_CheckParm("-avg"); if (i && deathmatch) { levelTimer = true; levelTimeCount = 20 * 60 * 35; } i = M_CheckParm("-timer"); if (i && deathmatch) { int time; time = atoi(myargv[i+1]) * 60 * 35; levelTimer = true; levelTimeCount = time; } // // Init special SECTORs // sector = sectors; for (i=0 ; ispecial) continue; switch (sector->special) { case 1: // FLICKERING LIGHTS P_SpawnLightFlash (sector); break; case 2: // STROBE FAST P_SpawnStrobeFlash(sector,FASTDARK,0); break; case 3: // STROBE SLOW P_SpawnStrobeFlash(sector,SLOWDARK,0); break; case 4: // STROBE FAST/DEATH SLIME P_SpawnStrobeFlash(sector,FASTDARK,0); sector->special = 4; break; case 8: // GLOWING LIGHT P_SpawnGlowingLight(sector); break; case 9: // SECRET SECTOR totalsecret++; break; case 10: // DOOR CLOSE IN 30 SECONDS P_SpawnDoorCloseIn30 (sector); break; case 12: // SYNC STROBE SLOW P_SpawnStrobeFlash (sector, SLOWDARK, 1); break; case 13: // SYNC STROBE FAST P_SpawnStrobeFlash (sector, FASTDARK, 1); break; case 14: // DOOR RAISE IN 5 MINUTES P_SpawnDoorRaiseIn5Mins (sector, i); break; case 17: P_SpawnFireFlicker(sector); break; } } // // Init line EFFECTs // numlinespecials = 0; for (i = 0;i < numlines; i++) switch(lines[i].special) { case 48: // EFFECT FIRSTCOL SCROLL+ linespeciallist[numlinespecials] = &lines[i]; numlinespecials++; break; } // // Init other misc stuff // for (i = 0;i < MAXCEILINGS;i++) activeceilings[i] = NULL; for (i = 0;i < MAXPLATS;i++) activeplats[i] = NULL; for (i = 0;i < MAXBUTTONS;i++) memset(&buttonlist[i],0,sizeof(button_t)); // P_InitSlidingDoorFrames(); } \ No newline at end of file diff --git a/P_SPEC.H b/P_SPEC.H new file mode 100644 index 0000000..002148d --- /dev/null +++ b/P_SPEC.H @@ -0,0 +1 @@ +// P_spec.h /* =============================================================================== P_SPEC =============================================================================== */ // // Animating textures and planes // typedef struct { boolean istexture; int picnum; int basepic; int numpics; int speed; } anim_t; // // source animation definition // typedef struct { boolean istexture; // if false, it's a flat char endname[9]; char startname[9]; int speed; } animdef_t; #define MAXANIMS 32 extern anim_t anims[MAXANIMS], *lastanim; // // End-level timer (-TIMER option) // extern boolean levelTimer; extern int levelTimeCount; // // Animating line specials // #define MAXLINEANIMS 64 extern short numlinespecials; extern line_t *linespeciallist[MAXLINEANIMS]; // Define values for map objects #define MO_TELEPORTMAN 14 // at game start void P_InitPicAnims (void); // at map load void P_SpawnSpecials (void); // every tic void P_UpdateSpecials (void); // when needed boolean P_UseSpecialLine ( mobj_t *thing, line_t *line,int side); void P_ShootSpecialLine ( mobj_t *thing, line_t *line); void P_CrossSpecialLine (int linenum, int side, mobj_t *thing); void P_PlayerInSpecialSector (player_t *player); int twoSided(int sector,int line); sector_t *getSector(int currentSector,int line,int side); side_t *getSide(int currentSector,int line, int side); fixed_t P_FindLowestFloorSurrounding(sector_t *sec); fixed_t P_FindHighestFloorSurrounding(sector_t *sec); fixed_t P_FindNextHighestFloor(sector_t *sec,int currentheight); fixed_t P_FindLowestCeilingSurrounding(sector_t *sec); fixed_t P_FindHighestCeilingSurrounding(sector_t *sec); int P_FindSectorFromLineTag(line_t *line,int start); int P_FindMinSurroundingLight(sector_t *sector,int max); sector_t *getNextSector(line_t *line,sector_t *sec); // // SPECIAL // int EV_DoDonut(line_t *line); /* =============================================================================== P_LIGHTS =============================================================================== */ typedef struct { thinker_t thinker; sector_t *sector; int count; int maxlight; int minlight; } fireflicker_t; typedef struct { thinker_t thinker; sector_t *sector; int count; int maxlight; int minlight; int maxtime; int mintime; } lightflash_t; typedef struct { thinker_t thinker; sector_t *sector; int count; int minlight; int maxlight; int darktime; int brighttime; } strobe_t; typedef struct { thinker_t thinker; sector_t *sector; int minlight; int maxlight; int direction; } glow_t; #define GLOWSPEED 8 #define STROBEBRIGHT 5 #define FASTDARK 15 #define SLOWDARK 35 void P_SpawnFireFlicker (sector_t *sector); void T_LightFlash (lightflash_t *flash); void P_SpawnLightFlash (sector_t *sector); void T_StrobeFlash (strobe_t *flash); void P_SpawnStrobeFlash (sector_t *sector, int fastOrSlow, int inSync); void EV_StartLightStrobing(line_t *line); void EV_TurnTagLightsOff(line_t *line); void EV_LightTurnOn(line_t *line, int bright); void T_Glow(glow_t *g); void P_SpawnGlowingLight(sector_t *sector); /* =============================================================================== P_SWITCH =============================================================================== */ typedef struct { char name1[9]; char name2[9]; short episode; } switchlist_t; typedef enum { top, middle, bottom } bwhere_e; typedef struct { line_t *line; bwhere_e where; int btexture; int btimer; mobj_t *soundorg; } button_t; #define MAXSWITCHES 50 // max # of wall switches in a level #define MAXBUTTONS 16 // 4 players, 4 buttons each at once, max. #define BUTTONTIME 35 // 1 second extern button_t buttonlist[MAXBUTTONS]; void P_ChangeSwitchTexture(line_t *line,int useAgain); void P_InitSwitchList(void); /* =============================================================================== P_PLATS =============================================================================== */ typedef enum { up, down, waiting, in_stasis } plat_e; typedef enum { perpetualRaise, downWaitUpStay, raiseAndChange, raiseToNearestAndChange, blazeDWUS } plattype_e; typedef struct { thinker_t thinker; sector_t *sector; fixed_t speed; fixed_t low; fixed_t high; int wait; int count; plat_e status; plat_e oldstatus; boolean crush; int tag; plattype_e type; } plat_t; #define PLATWAIT 3 #define PLATSPEED FRACUNIT #define MAXPLATS 30 extern plat_t *activeplats[MAXPLATS]; void T_PlatRaise(plat_t *plat); int EV_DoPlat(line_t *line,plattype_e type,int amount); void P_AddActivePlat(plat_t *plat); void P_RemoveActivePlat(plat_t *plat); void EV_StopPlat(line_t *line); void P_ActivateInStasis(int tag); /* =============================================================================== P_DOORS =============================================================================== */ typedef enum { normal, close30ThenOpen, close, open, raiseIn5Mins, blazeRaise, blazeOpen, blazeClose } vldoor_e; typedef struct { thinker_t thinker; vldoor_e type; sector_t *sector; fixed_t topheight; fixed_t speed; int direction; // 1 = up, 0 = waiting at top, -1 = down int topwait; // tics to wait at the top // (keep in case a door going down is reset) int topcountdown; // when it reaches 0, start going down } vldoor_t; #define VDOORSPEED FRACUNIT*2 #define VDOORWAIT 150 void EV_VerticalDoor (line_t *line, mobj_t *thing); int EV_DoDoor (line_t *line, vldoor_e type); int EV_DoLockedDoor (line_t *line, vldoor_e type, mobj_t *thing); void T_VerticalDoor (vldoor_t *door); void P_SpawnDoorCloseIn30 (sector_t *sec); void P_SpawnDoorRaiseIn5Mins (sector_t *sec, int secnum); #if 0 // // Sliding doors... // typedef enum { sd_opening, sd_waiting, sd_closing } sd_e; typedef enum { sdt_openOnly, sdt_closeOnly, sdt_openAndClose } sdt_e; typedef struct { thinker_t thinker; sdt_e type; line_t *line; int frame; int whichDoorIndex; int timer; sector_t *frontsector; sector_t *backsector; sd_e status; } slidedoor_t; typedef struct { char frontFrame1[9]; char frontFrame2[9]; char frontFrame3[9]; char frontFrame4[9]; char backFrame1[9]; char backFrame2[9]; char backFrame3[9]; char backFrame4[9]; } slidename_t; typedef struct { int frontFrames[4]; int backFrames[4]; } slideframe_t; #define SNUMFRAMES 4 // how many frames of anim #define SDOORWAIT 35*3 #define SWAITTICS 4 #define MAXSLIDEDOORS 5 // how many diff. types of anims void P_InitSlidingDoorFrames(void); void EV_SlidingDoor (line_t *line, mobj_t *thing); #endif /* =============================================================================== P_CEILNG =============================================================================== */ typedef enum { lowerToFloor, raiseToHighest, lowerAndCrush, crushAndRaise, fastCrushAndRaise, silentCrushAndRaise } ceiling_e; typedef struct { thinker_t thinker; ceiling_e type; sector_t *sector; fixed_t bottomheight, topheight; fixed_t speed; boolean crush; int direction; // 1 = up, 0 = waiting, -1 = down int tag; // ID int olddirection; } ceiling_t; #define CEILSPEED FRACUNIT #define CEILWAIT 150 #define MAXCEILINGS 30 extern ceiling_t *activeceilings[MAXCEILINGS]; int EV_DoCeiling (line_t *line, ceiling_e type); void T_MoveCeiling (ceiling_t *ceiling); void P_AddActiveCeiling(ceiling_t *c); void P_RemoveActiveCeiling(ceiling_t *c); int EV_CeilingCrushStop(line_t *line); void P_ActivateInStasisCeiling(line_t *line); /* =============================================================================== P_FLOOR =============================================================================== */ typedef enum { lowerFloor, // lower floor to highest surrounding floor lowerFloorToLowest, // lower floor to lowest surrounding floor turboLower, // lower floor to highest surrounding floor VERY FAST raiseFloor, // raise floor to lowest surrounding CEILING raiseFloorToNearest, // raise floor to next highest surrounding floor raiseToTexture, // raise floor to shortest height texture around it lowerAndChange, // lower floor to lowest surrounding floor and change // floorpic raiseFloor24, raiseFloor24AndChange, raiseFloorCrush, raiseFloorTurbo, // raise to next highest floor, turbo-speed donutRaise, raiseFloor512 } floor_e; typedef enum { build8, // slowly build by 8 turbo16 // quickly build by 16 } stair_e; typedef struct { thinker_t thinker; floor_e type; boolean crush; sector_t *sector; int direction; int newspecial; short texture; fixed_t floordestheight; fixed_t speed; } floormove_t; #define FLOORSPEED FRACUNIT typedef enum { ok, crushed, pastdest } result_e; result_e T_MovePlane(sector_t *sector,fixed_t speed, fixed_t dest,boolean crush,int floorOrCeiling,int direction); int EV_BuildStairs(line_t *line,stair_e type); int EV_DoFloor(line_t *line,floor_e floortype); void T_MoveFloor(floormove_t *floor); /* =============================================================================== P_TELEPT =============================================================================== */ int EV_Teleport( line_t *line,int side,mobj_t *thing ); \ No newline at end of file diff --git a/P_SWITCH.C b/P_SWITCH.C new file mode 100644 index 0000000..bfb7c43 --- /dev/null +++ b/P_SWITCH.C @@ -0,0 +1 @@ +#include "doomdef.h" #include "p_local.h" //================================================================== // // CHANGE THE TEXTURE OF A WALL SWITCH TO ITS OPPOSITE // //================================================================== switchlist_t alphSwitchList[] = { //====================================== // Doom shareware episode 1 switches //====================================== {"SW1BRCOM", "SW2BRCOM", 1}, {"SW1BRN1", "SW2BRN1", 1}, {"SW1BRN2", "SW2BRN2", 1}, {"SW1BRNGN", "SW2BRNGN", 1}, {"SW1BROWN", "SW2BROWN", 1}, {"SW1COMM", "SW2COMM", 1}, {"SW1COMP", "SW2COMP", 1}, {"SW1DIRT", "SW2DIRT", 1}, {"SW1EXIT", "SW2EXIT", 1}, {"SW1GRAY", "SW2GRAY", 1}, {"SW1GRAY1", "SW2GRAY1", 1}, {"SW1METAL", "SW2METAL", 1}, {"SW1PIPE", "SW2PIPE", 1}, {"SW1SLAD", "SW2SLAD", 1}, {"SW1STARG", "SW2STARG", 1}, {"SW1STON1", "SW2STON1", 1}, {"SW1STON2", "SW2STON2", 1}, {"SW1STONE", "SW2STONE", 1}, {"SW1STRTN", "SW2STRTN", 1}, //====================================== // Doom registered episodes 2&3 switches //====================================== {"SW1BLUE", "SW2BLUE", 2}, {"SW1CMT", "SW2CMT", 2}, {"SW1GARG", "SW2GARG", 2}, {"SW1GSTON", "SW2GSTON", 2}, {"SW1HOT", "SW2HOT", 2}, {"SW1LION", "SW2LION", 2}, {"SW1SATYR", "SW2SATYR", 2}, {"SW1SKIN", "SW2SKIN", 2}, {"SW1VINE", "SW2VINE", 2}, {"SW1WOOD", "SW2WOOD", 2}, //====================================== // Doom II switches //====================================== {"SW1PANEL", "SW2PANEL", 3}, {"SW1ROCK", "SW2ROCK", 3}, {"SW1MET2", "SW2MET2", 3}, {"SW1WDMET", "SW2WDMET", 3}, {"SW1BRIK", "SW2BRIK", 3}, {"SW1MOD1", "SW2MOD1", 3}, {"SW1ZIM", "SW2ZIM", 3}, {"SW1STON6", "SW2STON6", 3}, {"SW1TEK", "SW2TEK", 3}, {"SW1MARB", "SW2MARB", 3}, {"SW1SKULL", "SW2SKULL", 3}, {"\0", "\0", 0} }; int switchlist[MAXSWITCHES * 2]; int numswitches; button_t buttonlist[MAXBUTTONS]; /* =============== = = P_InitSwitchList = = Only called at game initialization = =============== */ void P_InitSwitchList(void) { int i; int index; int episode; episode = 1; if (registered) episode = 2; else if (commercial) episode = 3; for (index = 0,i = 0;i < MAXSWITCHES;i++) { if (!alphSwitchList[i].episode) { numswitches = index/2; switchlist[index] = -1; break; } if (alphSwitchList[i].episode <= episode) { #if 0 int value; if (R_CheckTextureNumForName(alphSwitchList[i].name1) < 0) { I_Error("Can't find switch texture '%s'!", alphSwitchList[i].name1); continue; } value = R_TextureNumForName(alphSwitchList[i].name1); #endif switchlist[index++] = R_TextureNumForName(alphSwitchList[i].name1); switchlist[index++] = R_TextureNumForName(alphSwitchList[i].name2); } } } //================================================================== // // Start a button counting down till it turns off. // //================================================================== void P_StartButton(line_t *line,bwhere_e w,int texture,int time) { int i; // // See if button is already pressed // for (i = 0;i < MAXBUTTONS;i++) if (buttonlist[i].btimer && buttonlist[i].line == line) return; for (i = 0;i < MAXBUTTONS;i++) if (!buttonlist[i].btimer) { buttonlist[i].line = line; buttonlist[i].where = w; buttonlist[i].btexture = texture; buttonlist[i].btimer = time; buttonlist[i].soundorg = (mobj_t *)&line->frontsector->soundorg; return; } I_Error("P_StartButton: no button slots left!"); } //================================================================== // // Function that changes wall texture. // Tell it if switch is ok to use again (1=yes, it's a button). // //================================================================== void P_ChangeSwitchTexture(line_t *line,int useAgain) { int texTop; int texMid; int texBot; int i; int sound; if (!useAgain) line->special = 0; texTop = sides[line->sidenum[0]].toptexture; texMid = sides[line->sidenum[0]].midtexture; texBot = sides[line->sidenum[0]].bottomtexture; sound = sfx_swtchn; if (line->special == 11) // EXIT SWITCH? sound = sfx_swtchx; for (i = 0;i < numswitches*2;i++) if (switchlist[i] == texTop) { S_StartSound(buttonlist->soundorg,sound); sides[line->sidenum[0]].toptexture = switchlist[i^1]; if (useAgain) P_StartButton(line,top,switchlist[i],BUTTONTIME); return; } else if (switchlist[i] == texMid) { S_StartSound(buttonlist->soundorg,sound); sides[line->sidenum[0]].midtexture = switchlist[i^1]; if (useAgain) P_StartButton(line, middle,switchlist[i],BUTTONTIME); return; } else if (switchlist[i] == texBot) { S_StartSound(buttonlist->soundorg,sound); sides[line->sidenum[0]].bottomtexture = switchlist[i^1]; if (useAgain) P_StartButton(line, bottom,switchlist[i],BUTTONTIME); return; } } /* ============================================================================== = = P_UseSpecialLine = = Called when a thing uses a special line = Only the front sides of lines are usable =============================================================================== */ boolean P_UseSpecialLine ( mobj_t *thing, line_t *line,int side) { // // Use the back sides of VERY SPECIAL lines... // if (side) switch(line->special) { case 124: // Sliding door open&close break; default: return false; } // // Switches that other things can activate // if (!thing->player) { if (line->flags & ML_SECRET) return false; // never open secret doors switch(line->special) { case 1: // MANUAL DOOR RAISE case 32: // MANUAL BLUE case 33: // MANUAL RED case 34: // MANUAL YELLOW break; default: return false; } } // // do something // switch (line->special) { //=============================================== // MANUALS //=============================================== case 1: // Vertical Door case 26: // Blue Door/Locked case 27: // Yellow Door /Locked case 28: // Red Door /Locked case 31: // Manual door open case 32: // Blue locked door open case 33: // Red locked door open case 34: // Yellow locked door open case 117: // Blazing door raise case 118: // Blazing door open EV_VerticalDoor (line, thing); break; // case 124: // Door Slide Open&Close // EV_SlidingDoor (line, thing); // break; //=============================================== // SWITCHES //=============================================== case 7: // Build Stairs if (EV_BuildStairs(line,build8)) P_ChangeSwitchTexture(line,0); break; case 9: // Change Donut if (EV_DoDonut(line)) P_ChangeSwitchTexture(line,0); break; case 11: // Exit level P_ChangeSwitchTexture(line,0); G_ExitLevel (); break; case 14: // Raise Floor 32 and change texture if (EV_DoPlat(line,raiseAndChange,32)) P_ChangeSwitchTexture(line,0); break; case 15: // Raise Floor 24 and change texture if (EV_DoPlat(line,raiseAndChange,24)) P_ChangeSwitchTexture(line,0); break; case 18: // Raise Floor to next highest floor if (EV_DoFloor(line, raiseFloorToNearest)) P_ChangeSwitchTexture(line,0); break; case 20: // Raise Plat next highest floor and change texture if (EV_DoPlat(line,raiseToNearestAndChange,0)) P_ChangeSwitchTexture(line,0); break; case 21: // PlatDownWaitUpStay if (EV_DoPlat(line,downWaitUpStay,0)) P_ChangeSwitchTexture(line,0); break; case 23: // Lower Floor to Lowest if (EV_DoFloor(line,lowerFloorToLowest)) P_ChangeSwitchTexture(line,0); break; case 29: // Raise Door if (EV_DoDoor(line,normal)) P_ChangeSwitchTexture(line,0); break; case 41: // Lower Ceiling to Floor if (EV_DoCeiling(line,lowerToFloor)) P_ChangeSwitchTexture(line,0); break; case 71: // Turbo Lower Floor if (EV_DoFloor(line,turboLower)) P_ChangeSwitchTexture(line,0); break; case 49: // Ceiling Crush And Raise if (EV_DoCeiling(line,crushAndRaise)) P_ChangeSwitchTexture(line,0); break; case 50: // Close Door if (EV_DoDoor(line,close)) P_ChangeSwitchTexture(line,0); break; case 51: // Secret EXIT P_ChangeSwitchTexture(line,0); G_SecretExitLevel (); break; case 55: // Raise Floor Crush if (EV_DoFloor(line,raiseFloorCrush)) P_ChangeSwitchTexture(line,0); break; case 101: // Raise Floor if (EV_DoFloor(line,raiseFloor)) P_ChangeSwitchTexture(line,0); break; case 102: // Lower Floor to Surrounding floor height if (EV_DoFloor(line,lowerFloor)) P_ChangeSwitchTexture(line,0); break; case 103: // Open Door if (EV_DoDoor(line,open)) P_ChangeSwitchTexture(line,0); break; case 111: // Blazing Door Raise (faster than TURBO!) if (EV_DoDoor (line,blazeRaise)) P_ChangeSwitchTexture(line,0); break; case 112: // Blazing Door Open (faster than TURBO!) if (EV_DoDoor (line,blazeOpen)) P_ChangeSwitchTexture(line,0); break; case 113: // Blazing Door Close (faster than TURBO!) if (EV_DoDoor (line,blazeClose)) P_ChangeSwitchTexture(line,0); break; case 122: // Blazing PlatDownWaitUpStay if (EV_DoPlat(line,blazeDWUS,0)) P_ChangeSwitchTexture(line,0); break; case 127: // Build Stairs Turbo 16 if (EV_BuildStairs(line,turbo16)) P_ChangeSwitchTexture(line,0); break; case 131: // Raise Floor Turbo if (EV_DoFloor(line,raiseFloorTurbo)) P_ChangeSwitchTexture(line,0); break; case 133: // BlzOpenDoor BLUE case 135: // BlzOpenDoor RED case 137: // BlzOpenDoor YELLOW if (EV_DoLockedDoor (line,blazeOpen,thing)) P_ChangeSwitchTexture(line,0); break; case 140: // Raise Floor 512 if (EV_DoFloor(line,raiseFloor512)) P_ChangeSwitchTexture(line,0); break; //=============================================== // BUTTONS //=============================================== case 42: // Close Door if (EV_DoDoor(line,close)) P_ChangeSwitchTexture(line,1); break; case 43: // Lower Ceiling to Floor if (EV_DoCeiling(line,lowerToFloor)) P_ChangeSwitchTexture(line,1); break; case 45: // Lower Floor to Surrounding floor height if (EV_DoFloor(line,lowerFloor)) P_ChangeSwitchTexture(line,1); break; case 60: // Lower Floor to Lowest if (EV_DoFloor(line,lowerFloorToLowest)) P_ChangeSwitchTexture(line,1); break; case 61: // Open Door if (EV_DoDoor(line,open)) P_ChangeSwitchTexture(line,1); break; case 62: // PlatDownWaitUpStay if (EV_DoPlat(line,downWaitUpStay,1)) P_ChangeSwitchTexture(line,1); break; case 63: // Raise Door if (EV_DoDoor(line,normal)) P_ChangeSwitchTexture(line,1); break; case 64: // Raise Floor to ceiling if (EV_DoFloor(line,raiseFloor)) P_ChangeSwitchTexture(line,1); break; case 66: // Raise Floor 24 and change texture if (EV_DoPlat(line,raiseAndChange,24)) P_ChangeSwitchTexture(line,1); break; case 67: // Raise Floor 32 and change texture if (EV_DoPlat(line,raiseAndChange,32)) P_ChangeSwitchTexture(line,1); break; case 65: // Raise Floor Crush if (EV_DoFloor(line,raiseFloorCrush)) P_ChangeSwitchTexture(line,1); break; case 68: // Raise Plat to next highest floor and change texture if (EV_DoPlat(line,raiseToNearestAndChange,0)) P_ChangeSwitchTexture(line,1); break; case 69: // Raise Floor to next highest floor if (EV_DoFloor(line, raiseFloorToNearest)) P_ChangeSwitchTexture(line,1); break; case 70: // Turbo Lower Floor if (EV_DoFloor(line,turboLower)) P_ChangeSwitchTexture(line,1); break; case 114: // Blazing Door Raise (faster than TURBO!) if (EV_DoDoor (line,blazeRaise)) P_ChangeSwitchTexture(line,1); break; case 115: // Blazing Door Open (faster than TURBO!) if (EV_DoDoor (line,blazeOpen)) P_ChangeSwitchTexture(line,1); break; case 116: // Blazing Door Close (faster than TURBO!) if (EV_DoDoor (line,blazeClose)) P_ChangeSwitchTexture(line,1); break; case 123: // Blazing PlatDownWaitUpStay if (EV_DoPlat(line,blazeDWUS,0)) P_ChangeSwitchTexture(line,1); break; case 132: // Raise Floor Turbo if (EV_DoFloor(line,raiseFloorTurbo)) P_ChangeSwitchTexture(line,1); break; case 99: // BlzOpenDoor BLUE case 134: // BlzOpenDoor RED case 136: // BlzOpenDoor YELLOW if (EV_DoLockedDoor (line,blazeOpen,thing)) P_ChangeSwitchTexture(line,1); break; case 138: // Light Turn On EV_LightTurnOn(line,255); P_ChangeSwitchTexture(line,1); break; case 139: // Light Turn Off EV_LightTurnOn(line,35); P_ChangeSwitchTexture(line,1); break; } return true; } \ No newline at end of file diff --git a/P_TELEPT.C b/P_TELEPT.C new file mode 100644 index 0000000..0718a3c --- /dev/null +++ b/P_TELEPT.C @@ -0,0 +1 @@ +#include "doomdef.h" #include "p_local.h" //================================================================== // // TELEPORTATION // //================================================================== int EV_Teleport( line_t *line,int side,mobj_t *thing ) { int i; int tag; mobj_t *m,*fog; unsigned an; thinker_t *thinker; sector_t *sector; fixed_t oldx, oldy, oldz; if (thing->flags & MF_MISSILE) return 0; // don't teleport missiles if (side == 1) // don't teleport if hit back of line, return 0; // so you can get out of teleporter tag = line->tag; for (i = 0; i < numsectors; i++) if (sectors[ i ].tag == tag ) { thinker = thinkercap.next; for (thinker = thinkercap.next ; thinker != &thinkercap ; thinker = thinker->next) { if (thinker->function != P_MobjThinker) continue; // not a mobj m = (mobj_t *)thinker; if (m->type != MT_TELEPORTMAN ) continue; // not a teleportman sector = m->subsector->sector; if (sector-sectors != i ) continue; // wrong sector oldx = thing->x; oldy = thing->y; oldz = thing->z; if (!P_TeleportMove (thing, m->x, m->y)) return 0; thing->z = thing->floorz; if (thing->player) thing->player->viewz = thing->z+thing->player->viewheight; // spawn teleport fog at source and destination fog = P_SpawnMobj (oldx, oldy, oldz, MT_TFOG); S_StartSound (fog, sfx_telept); an = m->angle >> ANGLETOFINESHIFT; fog = P_SpawnMobj (m->x+20*finecosine[an], m->y+20*finesine[an] , thing->z, MT_TFOG); S_StartSound (fog, sfx_telept); if (thing->player) thing->reactiontime = 18; // don't move for a bit thing->angle = m->angle; thing->momx = thing->momy = thing->momz = 0; return 1; } } return 0; } \ No newline at end of file diff --git a/P_TICK.C b/P_TICK.C new file mode 100644 index 0000000..56675a2 --- /dev/null +++ b/P_TICK.C @@ -0,0 +1 @@ +#include "doomdef.h" #include "p_local.h" // pads save_p to a 4-byte boundary so that the load/save works on SGI&Gecko #define PADSAVEP() save_p += (4 - ((int) save_p & 3)) & 3 int leveltime; //============================================================================= /* ==================== = = P_ArchivePlayers = ==================== */ void P_ArchivePlayers (void) { int i,j; player_t *dest; for (i=0 ; ipsprites[j].state) dest->psprites[j].state = (state_t *)(dest->psprites[j].state-states); } } } /* ==================== = = P_UnArchivePlayers = ==================== */ void P_UnArchivePlayers (void) { int i,j; for (i=0 ; ifloorheight >> FRACBITS; *put++ = sec->ceilingheight >> FRACBITS; *put++ = sec->floorpic; *put++ = sec->ceilingpic; *put++ = sec->lightlevel; *put++ = sec->special; // needed? *put++ = sec->tag; // needed? } // // do lines // for (i=0, li = lines ; iflags; *put++ = li->special; *put++ = li->tag; for (j=0 ; j<2 ; j++) { if (li->sidenum[j] == -1) continue; si = &sides[li->sidenum[j]]; *put++ = si->textureoffset >> FRACBITS; *put++ = si->rowoffset >> FRACBITS; *put++ = si->toptexture; *put++ = si->bottomtexture; *put++ = si->midtexture; } } save_p = (byte *)put; } /* ==================== = = P_UnArchiveWorld = ==================== */ void P_UnArchiveWorld (void) { int i,j; sector_t *sec; line_t *li; side_t *si; short *get; get = (short *)save_p; // // do sectors // for (i=0, sec = sectors ; ifloorheight = *get++ << FRACBITS; sec->ceilingheight = *get++ << FRACBITS; sec->floorpic = *get++; sec->ceilingpic = *get++; sec->lightlevel = *get++; sec->special = *get++; // needed? sec->tag = *get++; // needed? sec->specialdata = 0; sec->soundtarget = 0; } // // do lines // for (i=0, li = lines ; iflags = *get++; li->special = *get++; li->tag = *get++; for (j=0 ; j<2 ; j++) { if (li->sidenum[j] == -1) continue; si = &sides[li->sidenum[j]]; si->textureoffset = *get++ << FRACBITS; si->rowoffset = *get++ << FRACBITS; si->toptexture = *get++; si->bottomtexture = *get++; si->midtexture = *get++; } } save_p = (byte *)get; } //============================================================================= typedef enum { tc_end, tc_mobj } thinkerclass_t; /* ==================== = = P_ArchiveThinkers = ==================== */ void P_ArchiveThinkers (void) { thinker_t *th; mobj_t *mobj; // save off the current thinkers for (th = thinkercap.next ; th != &thinkercap ; th=th->next) { if (th->function == P_MobjThinker) { *save_p++ = tc_mobj; PADSAVEP(); mobj = (mobj_t *)save_p; memcpy (mobj, th, sizeof(*mobj)); save_p += sizeof(*mobj); mobj->state = (state_t *)(mobj->state - states); if (mobj->player) mobj->player = (player_t *)((mobj->player-players) + 1); continue; } // I_Error ("P_ArchiveThinkers: Unknown thinker function"); } // add a terminating marker *save_p++ = tc_end; } /* ==================== = = P_UnArchiveThinkers = ==================== */ void P_UnArchiveThinkers (void) { byte tclass; thinker_t *currentthinker, *next; mobj_t *mobj; // // remove all the current thinkers // currentthinker = thinkercap.next; while (currentthinker != &thinkercap) { next = currentthinker->next; if (currentthinker->function == P_MobjThinker) P_RemoveMobj ((mobj_t *)currentthinker); else Z_Free (currentthinker); currentthinker = next; } P_InitThinkers (); // read in saved thinkers while (1) { tclass = *save_p++; switch (tclass) { case tc_end: return; // end of list case tc_mobj: PADSAVEP(); mobj = Z_Malloc (sizeof(*mobj), PU_LEVEL, NULL); memcpy (mobj, save_p, sizeof(*mobj)); save_p += sizeof(*mobj); mobj->state = &states[(int)mobj->state]; mobj->target = NULL; if (mobj->player) { mobj->player = &players[(int)mobj->player-1]; mobj->player->mo = mobj; } P_SetThingPosition (mobj); mobj->info = &mobjinfo[mobj->type]; mobj->floorz = mobj->subsector->sector->floorheight; mobj->ceilingz = mobj->subsector->sector->ceilingheight; mobj->thinker.function = P_MobjThinker; P_AddThinker (&mobj->thinker); break; default: I_Error ("Unknown tclass %i in savegame",tclass); } } } //============================================================================= /* ==================== = = P_ArchiveSpecials = ==================== */ enum { tc_ceiling, tc_door, tc_floor, tc_plat, tc_flash, tc_strobe, tc_glow, tc_endspecials } specials_e; void P_ArchiveSpecials (void) { /* T_MoveCeiling, (ceiling_t: sector_t * swizzle), - active list T_VerticalDoor, (vldoor_t: sector_t * swizzle), T_MoveFloor, (floormove_t: sector_t * swizzle), T_LightFlash, (lightflash_t: sector_t * swizzle), T_StrobeFlash, (strobe_t: sector_t *), T_Glow, (glow_t: sector_t *), T_PlatRaise, (plat_t: sector_t *), - active list */ thinker_t *th; ceiling_t *ceiling; vldoor_t *door; floormove_t *floor; plat_t *plat; lightflash_t *flash; strobe_t *strobe; glow_t *glow; int i; // save off the current thinkers for (th = thinkercap.next ; th != &thinkercap ; th=th->next) { if (th->function == NULL) { for (i = 0; i < MAXCEILINGS;i++) if (activeceilings[i] == (ceiling_t *)th) break; if (isector = (sector_t *)(ceiling->sector - sectors); } continue; } if (th->function == T_MoveCeiling) { *save_p++ = tc_ceiling; PADSAVEP(); ceiling = (ceiling_t *)save_p; memcpy (ceiling, th, sizeof(*ceiling)); save_p += sizeof(*ceiling); ceiling->sector = (sector_t *)(ceiling->sector - sectors); continue; } if (th->function == T_VerticalDoor) { *save_p++ = tc_door; PADSAVEP(); door = (vldoor_t *)save_p; memcpy (door, th, sizeof(*door)); save_p += sizeof(*door); door->sector = (sector_t *)(door->sector - sectors); continue; } if (th->function == T_MoveFloor) { *save_p++ = tc_floor; PADSAVEP(); floor = (floormove_t *)save_p; memcpy (floor, th, sizeof(*floor)); save_p += sizeof(*floor); floor->sector = (sector_t *)(floor->sector - sectors); continue; } if (th->function == T_PlatRaise) { *save_p++ = tc_plat; PADSAVEP(); plat = (plat_t *)save_p; memcpy (plat, th, sizeof(*plat)); save_p += sizeof(*plat); plat->sector = (sector_t *)(plat->sector - sectors); continue; } if (th->function == T_LightFlash) { *save_p++ = tc_flash; PADSAVEP(); flash = (lightflash_t *)save_p; memcpy (flash, th, sizeof(*flash)); save_p += sizeof(*flash); flash->sector = (sector_t *)(flash->sector - sectors); continue; } if (th->function == T_StrobeFlash) { *save_p++ = tc_strobe; PADSAVEP(); strobe = (strobe_t *)save_p; memcpy (strobe, th, sizeof(*strobe)); save_p += sizeof(*strobe); strobe->sector = (sector_t *)(strobe->sector - sectors); continue; } if (th->function == T_Glow) { *save_p++ = tc_glow; PADSAVEP(); glow = (glow_t *)save_p; memcpy (glow, th, sizeof(*glow)); save_p += sizeof(*glow); glow->sector = (sector_t *)(glow->sector - sectors); continue; } } // add a terminating marker *save_p++ = tc_endspecials; } /* ==================== = = P_UnArchiveSpecials = ==================== */ void P_UnArchiveSpecials (void) { byte tclass; ceiling_t *ceiling; vldoor_t *door; floormove_t *floor; plat_t *plat; lightflash_t *flash; strobe_t *strobe; glow_t *glow; // read in saved thinkers while (1) { tclass = *save_p++; switch (tclass) { case tc_endspecials: return; // end of list case tc_ceiling: PADSAVEP(); ceiling = Z_Malloc (sizeof(*ceiling), PU_LEVEL, NULL); memcpy (ceiling, save_p, sizeof(*ceiling)); save_p += sizeof(*ceiling); ceiling->sector = §ors[(int)ceiling->sector]; ceiling->sector->specialdata = ceiling; if (ceiling->thinker.function) ceiling->thinker.function = T_MoveCeiling; P_AddThinker (&ceiling->thinker); P_AddActiveCeiling(ceiling); break; case tc_door: PADSAVEP(); door = Z_Malloc (sizeof(*door), PU_LEVEL, NULL); memcpy (door, save_p, sizeof(*door)); save_p += sizeof(*door); door->sector = §ors[(int)door->sector]; door->sector->specialdata = door; door->thinker.function = T_VerticalDoor; P_AddThinker (&door->thinker); break; case tc_floor: PADSAVEP(); floor = Z_Malloc (sizeof(*floor), PU_LEVEL, NULL); memcpy (floor, save_p, sizeof(*floor)); save_p += sizeof(*floor); floor->sector = §ors[(int)floor->sector]; floor->sector->specialdata = floor; floor->thinker.function = T_MoveFloor; P_AddThinker (&floor->thinker); break; case tc_plat: PADSAVEP(); plat = Z_Malloc (sizeof(*plat), PU_LEVEL, NULL); memcpy (plat, save_p, sizeof(*plat)); save_p += sizeof(*plat); plat->sector = §ors[(int)plat->sector]; plat->sector->specialdata = plat; if (plat->thinker.function) plat->thinker.function = T_PlatRaise; P_AddThinker (&plat->thinker); P_AddActivePlat(plat); break; case tc_flash: PADSAVEP(); flash = Z_Malloc (sizeof(*flash), PU_LEVEL, NULL); memcpy (flash, save_p, sizeof(*flash)); save_p += sizeof(*flash); flash->sector = §ors[(int)flash->sector]; flash->thinker.function = T_LightFlash; P_AddThinker (&flash->thinker); break; case tc_strobe: PADSAVEP(); strobe = Z_Malloc (sizeof(*strobe), PU_LEVEL, NULL); memcpy (strobe, save_p, sizeof(*strobe)); save_p += sizeof(*strobe); strobe->sector = §ors[(int)strobe->sector]; strobe->thinker.function = T_StrobeFlash; P_AddThinker (&strobe->thinker); break; case tc_glow: PADSAVEP(); glow = Z_Malloc (sizeof(*glow), PU_LEVEL, NULL); memcpy (glow, save_p, sizeof(*glow)); save_p += sizeof(*glow); glow->sector = §ors[(int)glow->sector]; glow->thinker.function = T_Glow; P_AddThinker (&glow->thinker); break; default: I_Error ("P_UnarchiveSpecials:Unknown tclass %i " "in savegame",tclass); } } } /* =============================================================================== THINKERS All thinkers should be allocated by Z_Malloc so they can be operated on uniformly. The actual structures will vary in size, but the first element must be thinker_t. =============================================================================== */ thinker_t thinkercap; // both the head and tail of the thinker list /* =============== = = P_InitThinkers = =============== */ void P_InitThinkers (void) { thinkercap.prev = thinkercap.next = &thinkercap; } /* =============== = = P_AddThinker = = Adds a new thinker at the end of the list = =============== */ void P_AddThinker (thinker_t *thinker) { thinkercap.prev->next = thinker; thinker->next = &thinkercap; thinker->prev = thinkercap.prev; thinkercap.prev = thinker; } /* =============== = = P_RemoveThinker = = Deallocation is lazy -- it will not actually be freed until its = thinking turn comes up = =============== */ void P_RemoveThinker (thinker_t *thinker) { thinker->function = (think_t)-1; } /* =============== = = P_AllocateThinker = = Allocates memory and adds a new thinker at the end of the list = =============== */ void P_AllocateThinker (thinker_t *thinker) { } /* =============== = = P_RunThinkers = =============== */ void P_RunThinkers (void) { thinker_t *currentthinker; currentthinker = thinkercap.next; while (currentthinker != &thinkercap) { if (currentthinker->function == (think_t)-1) { // time to remove it currentthinker->next->prev = currentthinker->prev; currentthinker->prev->next = currentthinker->next; Z_Free (currentthinker); } else { if (currentthinker->function) currentthinker->function (currentthinker); } currentthinker = currentthinker->next; } } //============================================================================= /* ================= = = P_Ticker = ================= */ //extern int soundVolume; extern int sfxVolume; extern int musicVolume; void P_Ticker (void) { int i; // // run the tic // if (paused) return; // pause if in menu and at least one tic has been run if ( !netgame && menuactive && !demoplayback && players[consoleplayer].viewz != 1) return; for (i=0 ; i>= ANGLETOFINESHIFT; player->mo->momx += FixedMul(move,finecosine[angle]); player->mo->momy += FixedMul(move,finesine[angle]); } /* ================== = = P_CalcHeight = = Calculate the walking / running height adjustment = ================== */ void P_CalcHeight (player_t *player) { int angle; fixed_t bob; // // regular movement bobbing (needs to be calculated for gun swing even // if not on ground) // OPTIMIZE: tablify angle player->bob = FixedMul (player->mo->momx, player->mo->momx)+ FixedMul (player->mo->momy,player->mo->momy); player->bob >>= 2; if (player->bob>MAXBOB) player->bob = MAXBOB; if ((player->cheats & CF_NOMOMENTUM) || !onground) { player->viewz = player->mo->z + VIEWHEIGHT; if (player->viewz > player->mo->ceilingz-4*FRACUNIT) player->viewz = player->mo->ceilingz-4*FRACUNIT; player->viewz = player->mo->z + player->viewheight; return; } angle = (FINEANGLES/20*leveltime)&FINEMASK; bob = FixedMul ( player->bob/2, finesine[angle]); // // move viewheight // if (player->playerstate == PST_LIVE) { player->viewheight += player->deltaviewheight; if (player->viewheight > VIEWHEIGHT) { player->viewheight = VIEWHEIGHT; player->deltaviewheight = 0; } if (player->viewheight < VIEWHEIGHT/2) { player->viewheight = VIEWHEIGHT/2; if (player->deltaviewheight <= 0) player->deltaviewheight = 1; } if (player->deltaviewheight) { player->deltaviewheight += FRACUNIT/4; if (!player->deltaviewheight) player->deltaviewheight = 1; } } player->viewz = player->mo->z + player->viewheight + bob; if (player->viewz > player->mo->ceilingz-4*FRACUNIT) player->viewz = player->mo->ceilingz-4*FRACUNIT; } /* ================= = = P_MovePlayer = ================= */ void P_MovePlayer (player_t *player) { ticcmd_t *cmd; cmd = &player->cmd; player->mo->angle += (cmd->angleturn<<16); // don't let the player control movement if not onground onground = (player->mo->z <= player->mo->floorz); if (cmd->forwardmove && onground) P_Thrust (player, player->mo->angle, cmd->forwardmove*2048); if (cmd->sidemove && onground) P_Thrust (player, player->mo->angle-ANG90, cmd->sidemove*2048); if ( (cmd->forwardmove || cmd->sidemove) && player->mo->state == &states[S_PLAY] ) P_SetMobjState (player->mo, S_PLAY_RUN1); } /* ================= = = P_DeathThink = ================= */ #define ANG5 (ANG90/18) void P_DeathThink (player_t *player) { angle_t angle, delta; P_MovePsprites (player); // fall to the ground if (player->viewheight > 6*FRACUNIT) player->viewheight -= FRACUNIT; if (player->viewheight < 6*FRACUNIT) player->viewheight = 6*FRACUNIT; player->deltaviewheight = 0; onground = (player->mo->z <= player->mo->floorz); P_CalcHeight (player); if (player->attacker && player->attacker != player->mo) { angle = R_PointToAngle2 (player->mo->x, player->mo->y , player->attacker->x, player->attacker->y); delta = angle - player->mo->angle; if (delta < ANG5 || delta > (unsigned)-ANG5) { // looking at killer, so fade damage flash down player->mo->angle = angle; if (player->damagecount) player->damagecount--; } else if (delta < ANG180) player->mo->angle += ANG5; else player->mo->angle -= ANG5; } else if (player->damagecount) player->damagecount--; if (player->cmd.buttons & BT_USE) player->playerstate = PST_REBORN; } /* ================= = = P_PlayerThink = ================= */ void P_PlayerThink (player_t *player) { ticcmd_t *cmd; weapontype_t newweapon; // fixme: do this in the cheat code if (player->cheats & CF_NOCLIP) player->mo->flags |= MF_NOCLIP; else player->mo->flags &= ~MF_NOCLIP; // // chain saw run forward // cmd = &player->cmd; if (player->mo->flags & MF_JUSTATTACKED) { cmd->angleturn = 0; cmd->forwardmove = 0xc800/512; cmd->sidemove = 0; player->mo->flags &= ~MF_JUSTATTACKED; } if (player->playerstate == PST_DEAD) { P_DeathThink (player); return; } // // move around // reactiontime is used to prevent movement for a bit after a teleport if (player->mo->reactiontime) player->mo->reactiontime--; else P_MovePlayer (player); P_CalcHeight (player); if (player->mo->subsector->sector->special) P_PlayerInSpecialSector (player); // // check for weapon change // if (cmd->buttons & BT_SPECIAL) cmd->buttons = 0; // a special event has no other buttons if (cmd->buttons & BT_CHANGE) { // the actual changing of the weapon is done when the weapon psprite // can do it (not in the middle of an attack) newweapon = (cmd->buttons&BT_WEAPONMASK)>>BT_WEAPONSHIFT; if (newweapon == wp_fist && player->weaponowned[wp_chainsaw] && !(player->readyweapon == wp_chainsaw && player->powers[pw_strength])) newweapon = wp_chainsaw; if (commercial && newweapon == wp_shotgun && player->weaponowned[wp_supershotgun] && player->readyweapon != wp_supershotgun) newweapon = wp_supershotgun; if (player->weaponowned[newweapon] && newweapon != player->readyweapon) { // don't go to plasma or BFG in shareware, even if cheated if ((newweapon != wp_plasma && newweapon != wp_bfg) || !shareware) { player->pendingweapon = newweapon; } } } // // check for use // if (cmd->buttons & BT_USE) { if (!player->usedown) { P_UseLines (player); player->usedown = true; } } else player->usedown = false; // // cycle psprites // P_MovePsprites (player); // // counters // if (player->powers[pw_strength]) player->powers[pw_strength]++; // strength counts up to diminish fade if (player->powers[pw_invulnerability]) player->powers[pw_invulnerability]--; if (player->powers[pw_invisibility]) if (! --player->powers[pw_invisibility] ) player->mo->flags &= ~MF_SHADOW; if (player->powers[pw_infrared]) player->powers[pw_infrared]--; if (player->powers[pw_ironfeet]) player->powers[pw_ironfeet]--; if (player->damagecount) player->damagecount--; if (player->bonuscount) player->bonuscount--; // // colormaps // if (player->powers[pw_invulnerability]) { if (player->powers[pw_invulnerability] > 4*32 || (player->powers[pw_invulnerability]&8) ) player->fixedcolormap = INVERSECOLORMAP; else player->fixedcolormap = 0; } else if (player->powers[pw_infrared]) { if (player->powers[pw_infrared] > 4*32 || (player->powers[pw_infrared]&8) ) player->fixedcolormap = 1; // almost full bright else player->fixedcolormap = 0; } else player->fixedcolormap = 0; } \ No newline at end of file diff --git a/R_BSP.C b/R_BSP.C new file mode 100644 index 0000000..90b1858 --- /dev/null +++ b/R_BSP.C @@ -0,0 +1 @@ +// R_bsp.c #include "doomdef.h" #include "r_local.h" seg_t *curline; side_t *sidedef; line_t *linedef; sector_t *frontsector, *backsector; drawseg_t drawsegs[MAXDRAWSEGS], *ds_p; void R_StoreWallRange (int start, int stop); /* ==================== = = R_ClearDrawSegs = ==================== */ void R_ClearDrawSegs (void) { ds_p = drawsegs; } //============================================================================= /* =============================================================================== = = ClipWallSegment = = Clips the given range of columns and includes it in the new clip list =============================================================================== */ typedef struct { int first, last; } cliprange_t; #define MAXSEGS 32 cliprange_t solidsegs[MAXSEGS], *newend; // newend is one past the last valid seg void R_ClipSolidWallSegment (int first, int last) { cliprange_t *next, *start; // find the first range that touches the range (adjacent pixels are touching) start = solidsegs; while (start->last < first-1) start++; if (first < start->first) { if (last < start->first-1) { // post is entirely visible (above start), so insert a new clippost R_StoreWallRange (first, last); next = newend; newend++; while (next != start) { *next = *(next-1); next--; } next->first = first; next->last = last; return; } // there is a fragment above *start R_StoreWallRange (first, start->first - 1); start->first = first; // adjust the clip size } if (last <= start->last) return; // bottom contained in start next = start; while (last >= (next+1)->first-1) { // there is a fragment between two posts R_StoreWallRange (next->last + 1, (next+1)->first - 1); next++; if (last <= next->last) { // bottom is contained in next start->last = next->last; // adjust the clip size goto crunch; } } // there is a fragment after *next R_StoreWallRange (next->last + 1, last); start->last = last; // adjust the clip size // remove start+1 to next from the clip list, // because start now covers their area crunch: if (next == start) return; // post just extended past the bottom of one post while (next++ != newend) // remove a post *++start = *next; newend = start+1; } /* =============================================================================== = = R_ClipPassWallSegment = = Clips the given range of columns, but does not includes it in the clip list =============================================================================== */ void R_ClipPassWallSegment (int first, int last) { cliprange_t *start; // find the first range that touches the range (adjacent pixels are touching) start = solidsegs; while (start->last < first-1) start++; if (first < start->first) { if (last < start->first-1) { // post is entirely visible (above start) R_StoreWallRange (first, last); return; } // there is a fragment above *start R_StoreWallRange (first, start->first - 1); } if (last <= start->last) return; // bottom contained in start while (last >= (start+1)->first-1) { // there is a fragment between two posts R_StoreWallRange (start->last + 1, (start+1)->first - 1); start++; if (last <= start->last) return; } // there is a fragment after *next R_StoreWallRange (start->last + 1, last); } /* ==================== = = R_ClearClipSegs = ==================== */ void R_ClearClipSegs (void) { solidsegs[0].first = -0x7fffffff; solidsegs[0].last = -1; solidsegs[1].first = viewwidth; solidsegs[1].last = 0x7fffffff; newend = solidsegs+2; } //============================================================================= /* ====================== = = R_AddLine = = Clips the given segment and adds any visible pieces to the line list = ====================== */ void R_AddLine (seg_t *line) { int x1, x2; angle_t angle1, angle2, span, tspan; #ifdef __NeXT__ RD_DrawLineCheck (line); #endif curline = line; // OPTIMIZE: quickly reject orthogonal back sides angle1 = R_PointToAngle (line->v1->x, line->v1->y); angle2 = R_PointToAngle (line->v2->x, line->v2->y); // // clip to view edges // OPTIMIZE: make constant out of 2*clipangle (FIELDOFVIEW) span = angle1 - angle2; if (span >= ANG180) return; // back side rw_angle1 = angle1; // global angle needed by segcalc angle1 -= viewangle; angle2 -= viewangle; tspan = angle1 + clipangle; if (tspan > 2*clipangle) { tspan -= 2*clipangle; if (tspan >= span) return; // totally off the left edge angle1 = clipangle; } tspan = clipangle - angle2; if (tspan > 2*clipangle) { tspan -= 2*clipangle; if (tspan >= span) return; // totally off the left edge angle2 = -clipangle; } // // the seg is in the view range, but not necessarily visible // angle1 = (angle1+ANG90)>>ANGLETOFINESHIFT; angle2 = (angle2+ANG90)>>ANGLETOFINESHIFT; x1 = viewangletox[angle1]; x2 = viewangletox[angle2]; if (x1 == x2) return; // does not cross a pixel backsector = line->backsector; if (!backsector) goto clipsolid; // single sided line if (backsector->ceilingheight <= frontsector->floorheight || backsector->floorheight >= frontsector->ceilingheight) goto clipsolid; // closed door if (backsector->ceilingheight != frontsector->ceilingheight || backsector->floorheight != frontsector->floorheight) goto clippass; // window // reject empty lines used for triggers and special events if (backsector->ceilingpic == frontsector->ceilingpic && backsector->floorpic == frontsector->floorpic && backsector->lightlevel == frontsector->lightlevel && curline->sidedef->midtexture == 0) return; clippass: R_ClipPassWallSegment (x1, x2-1); return; clipsolid: R_ClipSolidWallSegment (x1, x2-1); } //============================================================================ /* =============================================================================== = = R_CheckBBox = = Returns true if some part of the bbox might be visible = =============================================================================== */ int checkcoord[12][4] = { {3,0, 2,1}, {3,0, 2,0}, {3,1, 2,0}, {0}, {2,0, 2,1}, {0,0,0,0}, {3,1, 3,0}, {0}, {2,0, 3,1}, {2,1, 3,1}, {2,1, 3,0} }; boolean R_CheckBBox (fixed_t *bspcoord) { int boxx, boxy, boxpos; fixed_t x1, y1, x2, y2; angle_t angle1, angle2, span, tspan; cliprange_t *start; int sx1, sx2; #ifdef __NeXT__ RD_DrawBBox (bspcoord); #endif // find the corners of the box that define the edges from current viewpoint if (viewx <= bspcoord[BOXLEFT]) boxx = 0; else if (viewx < bspcoord[BOXRIGHT]) boxx = 1; else boxx = 2; if (viewy >= bspcoord[BOXTOP]) boxy = 0; else if (viewy > bspcoord[BOXBOTTOM]) boxy = 1; else boxy = 2; boxpos = (boxy<<2)+boxx; if (boxpos == 5) return true; x1 = bspcoord[checkcoord[boxpos][0]]; y1 = bspcoord[checkcoord[boxpos][1]]; x2 = bspcoord[checkcoord[boxpos][2]]; y2 = bspcoord[checkcoord[boxpos][3]]; #ifdef __NeXT__ // RD_DisplayLine (x1, y1, x2, y2, 0.1); #endif // // check clip list for an open space // angle1 = R_PointToAngle (x1, y1) - viewangle; angle2 = R_PointToAngle (x2, y2) - viewangle; span = angle1 - angle2; if (span >= ANG180) return true; // sitting on a line tspan = angle1 + clipangle; if (tspan > 2*clipangle) { tspan -= 2*clipangle; if (tspan >= span) return false; // totally off the left edge angle1 = clipangle; } tspan = clipangle - angle2; if (tspan > 2*clipangle) { tspan -= 2*clipangle; if (tspan >= span) return false; // totally off the left edge angle2 = -clipangle; } // find the first clippost that touches the source post (adjacent pixels are touching) angle1 = (angle1+ANG90)>>ANGLETOFINESHIFT; angle2 = (angle2+ANG90)>>ANGLETOFINESHIFT; sx1 = viewangletox[angle1]; sx2 = viewangletox[angle2]; if (sx1 == sx2) return false; // does not cross a pixel sx2--; start = solidsegs; while (start->last < sx2) start++; if (sx1 >= start->first && sx2 <= start->last) return false; // the clippost contains the new span return true; } /* ================ = = R_Subsector = = Draw one or more segments ================ */ void R_Subsector (int num) { int count; seg_t *line; subsector_t *sub; #ifdef RANGECHECK if (num>=numsubsectors) I_Error ("R_Subsector: ss %i with numss = %i",num, numsubsectors); #endif sscount++; sub = &subsectors[num]; frontsector = sub->sector; count = sub->numlines; line = &segs[sub->firstline]; if (frontsector->floorheight < viewz) floorplane = R_FindPlane (frontsector->floorheight, frontsector->floorpic, frontsector->lightlevel); else floorplane = NULL; if (frontsector->ceilingheight > viewz || frontsector->ceilingpic == skyflatnum) ceilingplane = R_FindPlane (frontsector->ceilingheight, frontsector->ceilingpic, frontsector->lightlevel); else ceilingplane = NULL; R_AddSprites (frontsector); while (count--) { R_AddLine (line); line++; } } /* =============================================================================== = = RenderBSPNode = =============================================================================== */ void R_RenderBSPNode (int bspnum) { node_t *bsp; int side; if (bspnum & NF_SUBSECTOR) { if (bspnum == -1) R_Subsector (0); else R_Subsector (bspnum&(~NF_SUBSECTOR)); return; } bsp = &nodes[bspnum]; #ifdef __NeXT__ RD_DrawNodeLine (bsp); #endif // // decide which side the view point is on // side = R_PointOnSide (viewx, viewy, bsp); R_RenderBSPNode (bsp->children[side]); // recursively divide front space if (R_CheckBBox (bsp->bbox[side^1])) // possibly divide back space R_RenderBSPNode (bsp->children[side^1]); } \ No newline at end of file diff --git a/R_DATA.C b/R_DATA.C new file mode 100644 index 0000000..4d6bf06 --- /dev/null +++ b/R_DATA.C @@ -0,0 +1 @@ +// R_data.c #include "doomdef.h" #include "r_local.h" #include "p_local.h" #ifdef NORMALUNIX #include #endif typedef struct { int originx; // block origin (allways UL), which has allready int originy; // accounted for the patch's internal origin int patch; } texpatch_t; // a maptexturedef_t describes a rectangular texture, which is composed of one // or more mappatch_t structures that arrange graphic patches typedef struct { char name[8]; // for switch changing, etc short width; short height; short patchcount; texpatch_t patches[1]; // [patchcount] drawn back to front // into the cached texture } texture_t; int firstflat, lastflat, numflats; int firstpatch, lastpatch, numpatches; int firstspritelump, lastspritelump, numspritelumps; int numtextures; texture_t **textures; int *texturewidthmask; fixed_t *textureheight; // needed for texture pegging int *texturecompositesize; short **texturecolumnlump; unsigned short **texturecolumnofs; byte **texturecomposite; int *flattranslation; // for global animation int *texturetranslation; // for global animation fixed_t *spritewidth; // needed for pre rendering fixed_t *spriteoffset; fixed_t *spritetopoffset; lighttable_t *colormaps; /* ============================================================================== MAPTEXTURE_T CACHING when a texture is first needed, it counts the number of composite columns required in the texture and allocates space for a column directory and any new columns. The directory will simply point inside other patches if there is only one patch in a given column, but any columns with multiple patches will have new column_ts generated. ============================================================================== */ /* =================== = = R_DrawColumnInCache = = Clip and draw a column from a patch into a cached post = =================== */ void R_DrawColumnInCache (column_t *patch, byte *cache, int originy, int cacheheight) { int count, position; byte *source, *dest; dest = (byte *)cache + 3; while (patch->topdelta != 0xff) { source = (byte *)patch + 3; count = patch->length; position = originy + patch->topdelta; if (position < 0) { count += position; position = 0; } if (position + count > cacheheight) count = cacheheight - position; if (count > 0) memcpy (cache + position, source, count); patch = (column_t *)( (byte *)patch + patch->length + 4); } } /* =================== = = R_GenerateComposite = =================== */ void R_GenerateComposite (int texnum) { byte *block; texture_t *texture; texpatch_t *patch; patch_t *realpatch; int x, x1, x2; int i; column_t *patchcol; short *collump; unsigned short *colofs; texture = textures[texnum]; block = Z_Malloc (texturecompositesize[texnum], PU_STATIC, &texturecomposite[texnum]); collump = texturecolumnlump[texnum]; colofs = texturecolumnofs[texnum]; // // composite the columns together // patch = texture->patches; for (i=0 , patch = texture->patches; ipatchcount ; i++, patch++) { realpatch = W_CacheLumpNum (patch->patch, PU_CACHE); x1 = patch->originx; x2 = x1 + SHORT(realpatch->width); if (x1<0) x = 0; else x = x1; if (x2 > texture->width) x2 = texture->width; for ( ; x= 0) continue; // column does not have multiple patches patchcol = (column_t *)((byte *)realpatch + LONG(realpatch->columnofs[x-x1])); R_DrawColumnInCache (patchcol, block + colofs[x], patch->originy, texture->height); } } // now that the texture has been built, it is purgable Z_ChangeTag (block, PU_CACHE); } /* =================== = = R_GenerateLookup = =================== */ void R_GenerateLookup (int texnum) { texture_t *texture; byte *patchcount; // [texture->width] texpatch_t *patch; patch_t *realpatch; int x, x1, x2; int i; short *collump; unsigned short *colofs; texture = textures[texnum]; texturecomposite[texnum] = 0; // composited not created yet texturecompositesize[texnum] = 0; collump = texturecolumnlump[texnum]; colofs = texturecolumnofs[texnum]; // // count the number of columns that are covered by more than one patch // fill in the lump / offset, so columns with only a single patch are // all done // patchcount = (byte *)alloca (texture->width); memset (patchcount, 0, texture->width); patch = texture->patches; for (i=0 , patch = texture->patches; ipatchcount ; i++, patch++) { realpatch = W_CacheLumpNum (patch->patch, PU_CACHE); x1 = patch->originx; x2 = x1 + SHORT(realpatch->width); if (x1 < 0) x = 0; else x = x1; if (x2 > texture->width) x2 = texture->width; for ( ; xpatch; colofs[x] = LONG(realpatch->columnofs[x-x1])+3; } } for (x=0 ; xwidth ; x++) { if (!patchcount[x]) { printf ("R_GenerateLookup: column without a patch (%s)\n", texture->name); return; } // I_Error ("R_GenerateLookup: column without a patch"); if (patchcount[x] > 1) { collump[x] = -1; // use the cached block colofs[x] = texturecompositesize[texnum]; if (texturecompositesize[texnum] > 0x10000-texture->height) I_Error ("R_GenerateLookup: texture %i is >64k",texnum); texturecompositesize[texnum] += texture->height; } } } /* ================ = = R_GetColumn = ================ */ byte *R_GetColumn (int tex, int col) { int lump, ofs; col &= texturewidthmask[tex]; lump = texturecolumnlump[tex][col]; ofs = texturecolumnofs[tex][col]; if (lump > 0) return (byte *)W_CacheLumpNum(lump,PU_CACHE)+ofs; if (!texturecomposite[tex]) R_GenerateComposite (tex); return texturecomposite[tex] + ofs; } /* ================== = = R_InitTextures = = Initializes the texture list with the textures from the world map = ================== */ void R_InitTextures (void) { maptexture_t *mtexture; texture_t *texture; mappatch_t *mpatch; texpatch_t *patch; int i,j; int *maptex, *maptex2, *maptex1; char name[9], *names, *name_p; int *patchlookup; int totalwidth; int nummappatches; int offset, maxoff, maxoff2; int numtextures1, numtextures2; int *directory; int temp1, temp2, temp3; // // load the patch names from pnames.lmp // name[8] = 0; names = W_CacheLumpName ("PNAMES", PU_STATIC); nummappatches = LONG ( *((int *)names) ); name_p = names+4; patchlookup = alloca (nummappatches*sizeof(*patchlookup)); for (i=0 ; i maxoff) I_Error ("R_InitTextures: bad texture directory"); mtexture = (maptexture_t *) ( (byte *)maptex + offset); texture = textures[i] = Z_Malloc (sizeof(texture_t) + sizeof(texpatch_t)*(SHORT(mtexture->patchcount)-1), PU_STATIC, 0); texture->width = SHORT(mtexture->width); texture->height = SHORT(mtexture->height); texture->patchcount = SHORT(mtexture->patchcount); memcpy (texture->name, mtexture->name, sizeof(texture->name)); mpatch = &mtexture->patches[0]; patch = &texture->patches[0]; for (j=0 ; jpatchcount ; j++, mpatch++, patch++) { patch->originx = SHORT(mpatch->originx); patch->originy = SHORT(mpatch->originy); patch->patch = patchlookup[SHORT(mpatch->patch)]; if (patch->patch == -1) I_Error ( "R_InitTextures: Missing patch in texture %s",texture->name); } texturecolumnlump[i] = Z_Malloc (texture->width*2, PU_STATIC,0); texturecolumnofs[i] = Z_Malloc (texture->width*2, PU_STATIC,0); j = 1; while (j*2 <= texture->width) j<<=1; texturewidthmask[i] = j-1; textureheight[i] = texture->height<width; } Z_Free (maptex1); if (maptex2) Z_Free (maptex2); // // precalculate whatever possible // for (i=0 ; iwidth)<leftoffset)<topoffset)<name, name, 8) ) return i; return -1; } /* ================ = = R_TextureNumForName = ================ */ int R_TextureNumForName (char *name) { int i; i = R_CheckTextureNumForName (name); if (i==-1) I_Error ("R_TextureNumForName: %s not found",name); return i; } /* ================= = = R_PrecacheLevel = = Preloads all relevent graphics for the level ================= */ int flatmemory, texturememory, spritememory; void R_PrecacheLevel (void) { char *flatpresent; char *texturepresent; char *spritepresent; int i,j,k, lump; texture_t *texture; thinker_t *th; spriteframe_t *sf; if (demoplayback) return; // // precache flats // flatpresent = alloca(numflats); memset (flatpresent,0,numflats); for (i=0 ; ipatchcount ; j++) { lump = texture->patches[j].patch; texturememory += lumpinfo[lump].size; W_CacheLumpNum(lump , PU_CACHE); } } // // precache sprites // spritepresent = alloca(numsprites); memset (spritepresent,0, numsprites); for (th = thinkercap.next ; th != &thinkercap ; th=th->next) { if (th->function == P_MobjThinker) spritepresent[((mobj_t *)th)->sprite] = 1; } spritememory = 0; for (i=0 ; ilump[k]; spritememory += lumpinfo[lump].size; W_CacheLumpNum(lump , PU_CACHE); } } } } \ No newline at end of file diff --git a/R_DRAW.C b/R_DRAW.C new file mode 100644 index 0000000..d2dfadf --- /dev/null +++ b/R_DRAW.C @@ -0,0 +1 @@ +// R_draw.c #include "doomdef.h" #include "r_local.h" /* All drawing to the view buffer is accomplished in this file. The other refresh files only know about ccordinates, not the architecture of the frame buffer. */ byte *viewimage; int viewwidth, scaledviewwidth, viewheight, viewwindowx, viewwindowy; byte *ylookup[MAXHEIGHT]; int columnofs[MAXWIDTH]; byte translations[3][256]; // color tables for different players /* ================== = = R_DrawColumn = = Source is the top of the column to scale = ================== */ lighttable_t *dc_colormap; int dc_x; int dc_yl; int dc_yh; fixed_t dc_iscale; fixed_t dc_texturemid; byte *dc_source; // first pixel in a column (possibly virtual) int dccount; // just for profiling #if (!defined(USEASM) && !defined(__WATCOMC__) && !defined(__i386) && !defined(__m68k)) void R_DrawColumn (void) { int count; byte *dest; fixed_t frac, fracstep; count = dc_yh - dc_yl; if (count < 0) return; #ifdef RANGECHECK if ((unsigned)dc_x >= SCREENWIDTH || dc_yl < 0 || dc_yh >= SCREENHEIGHT) I_Error ("R_DrawColumn: %i to %i at %i", dc_yl, dc_yh, dc_x); #endif dest = ylookup[dc_yl] + columnofs[dc_x]; fracstep = dc_iscale; frac = dc_texturemid + (dc_yl-centery)*fracstep; do { *dest = dc_colormap[dc_source[(frac>>FRACBITS)&127]]; dest += SCREENWIDTH; frac += fracstep; } while (count--); } #if 0 void R_DrawColumn (void) { int count; byte *source, *dest, *colormap; unsigned frac, fracstep,fracstep2,fracstep3,fracstep4; count = dc_yh - dc_yl + 1; source = dc_source; colormap = dc_colormap; dest = ylookup[dc_yl] + columnofs[dc_x]; fracstep = dc_iscale<<9; frac = (dc_texturemid + (dc_yl-centery)*dc_iscale)<<9; fracstep2 = fracstep+fracstep; fracstep3 = fracstep2+fracstep; fracstep4 = fracstep3+fracstep; while (count >= 8) { dest[0] = colormap[source[frac>>25]]; dest[SCREENWIDTH] = colormap[source[(frac+fracstep)>>25]]; dest[SCREENWIDTH*2] = colormap[source[(frac+fracstep2)>>25]]; dest[SCREENWIDTH*3] = colormap[source[(frac+fracstep3)>>25]]; frac += fracstep4; dest[SCREENWIDTH*4] = colormap[source[frac>>25]]; dest[SCREENWIDTH*5] = colormap[source[(frac+fracstep)>>25]]; dest[SCREENWIDTH*6] = colormap[source[(frac+fracstep2)>>25]]; dest[SCREENWIDTH*7] = colormap[source[(frac+fracstep3)>>25]]; frac += fracstep4; dest += SCREENWIDTH*8; count -= 8; } while (count > 0) { *dest = colormap[source[frac>>25]]; dest += SCREENWIDTH; frac += fracstep; count--; } } #endif #endif #ifndef __WATCOMC__ void R_DrawColumnLow (void) { int count; byte *dest; fixed_t frac, fracstep; count = dc_yh - dc_yl; if (count < 0) return; #ifdef RANGECHECK if ((unsigned)dc_x >= SCREENWIDTH || dc_yl < 0 || dc_yh >= SCREENHEIGHT) I_Error ("R_DrawColumn: %i to %i at %i", dc_yl, dc_yh, dc_x); // dccount++; #endif dest = ylookup[dc_yl] + columnofs[dc_x]; fracstep = dc_iscale; frac = dc_texturemid + (dc_yl-centery)*fracstep; do { *dest = dc_colormap[dc_source[(frac>>FRACBITS)&127]]; dest += SCREENWIDTH; frac += fracstep; } while (count--); } #endif #define FUZZTABLE 50 #ifdef __WATCOMC__ #define FUZZOFF (SCREENWIDTH/4) #else #define FUZZOFF (SCREENWIDTH) #endif int fuzzoffset[FUZZTABLE] = { FUZZOFF,-FUZZOFF,FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,-FUZZOFF,-FUZZOFF,-FUZZOFF,FUZZOFF,-FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,-FUZZOFF,-FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,FUZZOFF }; int fuzzpos = 0; void R_DrawFuzzColumn (void) { int count; byte *dest; fixed_t frac, fracstep; if (!dc_yl) dc_yl = 1; if (dc_yh == viewheight-1) dc_yh = viewheight - 2; count = dc_yh - dc_yl; if (count < 0) return; #ifdef RANGECHECK if ((unsigned)dc_x >= SCREENWIDTH || dc_yl < 0 || dc_yh >= SCREENHEIGHT) I_Error ("R_DrawFuzzColumn: %i to %i at %i", dc_yl, dc_yh, dc_x); #endif #ifdef __WATCOMC__ if (detailshift) { if (dc_x & 1) { outpw (GC_INDEX,GC_READMAP+(2<<8) ); outp (SC_INDEX+1,12); } else { outpw (GC_INDEX,GC_READMAP); outp (SC_INDEX+1,3); } dest = destview + dc_yl*80 + (dc_x>>1); } else { outpw (GC_INDEX,GC_READMAP+((dc_x&3)<<8) ); outp (SC_INDEX+1,1<<(dc_x&3)); dest = destview + dc_yl*80 + (dc_x>>2); } #else dest = ylookup[dc_yl] + columnofs[dc_x]; #endif fracstep = dc_iscale; frac = dc_texturemid + (dc_yl-centery)*fracstep; do { *dest = colormaps[6*256+dest[fuzzoffset[fuzzpos]]]; if (++fuzzpos == FUZZTABLE) fuzzpos = 0; #ifdef __WATCOMC__ dest += SCREENWIDTH/4; #else dest += SCREENWIDTH; #endif frac += fracstep; } while (count--); } /* ======================== = = R_DrawTranslatedColumn = ======================== */ byte *dc_translation; byte *translationtables; void R_DrawTranslatedColumn (void) { int count; byte *dest; fixed_t frac, fracstep; count = dc_yh - dc_yl; if (count < 0) return; #ifdef RANGECHECK if ((unsigned)dc_x >= SCREENWIDTH || dc_yl < 0 || dc_yh >= SCREENHEIGHT) I_Error ("R_DrawColumn: %i to %i at %i", dc_yl, dc_yh, dc_x); #endif #ifdef __WATCOMC__ if (detailshift) { if (dc_x & 1) outp (SC_INDEX+1,12); else outp (SC_INDEX+1,3); dest = destview + dc_yl*80 + (dc_x>>1); } else { outp (SC_INDEX+1,1<<(dc_x&3)); dest = destview + dc_yl*80 + (dc_x>>2); } #else dest = ylookup[dc_yl] + columnofs[dc_x]; #endif fracstep = dc_iscale; frac = dc_texturemid + (dc_yl-centery)*fracstep; do { *dest = dc_colormap[dc_translation[dc_source[frac>>FRACBITS]]]; #ifdef __WATCOMC__ dest += SCREENWIDTH/4; #else dest += SCREENWIDTH; #endif frac += fracstep; } while (count--); } /* ==================== = = R_InitTranslationTables = ==================== */ void R_InitTranslationTables (void) { int i; translationtables = Z_Malloc (256*3+255, PU_STATIC, 0); translationtables = (byte *)(( (int)translationtables + 255 )& ~255); // // translate just the 16 green colors // for (i=0 ; i<256 ; i++) { if (i >= 0x70 && i<= 0x7f) { // green, gray, brown, red translationtables[i] = 0x60 + (i&0xf); translationtables [i+256] = 0x40 + (i&0xf); translationtables [i+512] = 0x20 + (i&0xf); } else translationtables[i] = translationtables[i+256] = translationtables[i+512] = i; } } /* ================ = = R_DrawSpan = ================ */ int ds_y; int ds_x1; int ds_x2; lighttable_t *ds_colormap; fixed_t ds_xfrac; fixed_t ds_yfrac; fixed_t ds_xstep; fixed_t ds_ystep; byte *ds_source; // start of a 64*64 tile image int dscount; // just for profiling #if (!defined(USEASM) && !defined(__WATCOMC__) && !defined(__i386) && !defined(__m68k)) void R_DrawSpan (void) { fixed_t xfrac, yfrac; byte *dest; int count, spot; #ifdef RANGECHECK if (ds_x2 < ds_x1 || ds_x1<0 || ds_x2>=SCREENWIDTH || (unsigned)ds_y>SCREENHEIGHT) I_Error ("R_DrawSpan: %i to %i at %i",ds_x1,ds_x2,ds_y); // dscount++; #endif xfrac = ds_xfrac; yfrac = ds_yfrac; dest = ylookup[ds_y] + columnofs[ds_x1]; count = ds_x2 - ds_x1; do { spot = ((yfrac>>(16-6))&(63*64)) + ((xfrac>>16)&63); *dest++ = ds_colormap[ds_source[spot]]; xfrac += ds_xstep; yfrac += ds_ystep; } while (count--); } #if 0 void R_DrawSpan (void) { unsigned position, step; byte *source,*colormap,*dest; unsigned count, spot; unsigned value, temp; unsigned xtemp, ytemp; position = ((ds_xfrac<<10)&0xffff0000) | ((ds_yfrac>>6)&0xffff); step = ((ds_xstep<<10)&0xffff0000) | ((ds_ystep>>6)&0xffff); source = ds_source; colormap = ds_colormap; dest = ylookup[ds_y] + columnofs[ds_x1]; count = ds_x2 - ds_x1 + 1; while (count >= 4) { ytemp = position>>4; ytemp = ytemp & 4032; xtemp = position>>26; spot = xtemp | ytemp; position += step; dest[0] = colormap[source[spot]]; ytemp = position>>4; ytemp = ytemp & 4032; xtemp = position>>26; spot = xtemp | ytemp; position += step; dest[1] = colormap[source[spot]]; ytemp = position>>4; ytemp = ytemp & 4032; xtemp = position>>26; spot = xtemp | ytemp; position += step; dest[2] = colormap[source[spot]]; ytemp = position>>4; ytemp = ytemp & 4032; xtemp = position>>26; spot = xtemp | ytemp; position += step; dest[3] = colormap[source[spot]]; count -= 4; dest += 4; } while (count > 0) { ytemp = position>>4; ytemp = ytemp & 4032; xtemp = position>>26; spot = xtemp | ytemp; position += step; *dest++ = colormap[source[spot]]; count--; } } #endif #endif #ifndef __WATCOMC__ void R_DrawSpanLow (void) { fixed_t xfrac, yfrac; byte *dest; int count, spot; #ifdef RANGECHECK if (ds_x2 < ds_x1 || ds_x1<0 || ds_x2>=SCREENWIDTH || (unsigned)ds_y>SCREENHEIGHT) I_Error ("R_DrawSpan: %i to %i at %i",ds_x1,ds_x2,ds_y); // dscount++; #endif xfrac = ds_xfrac; yfrac = ds_yfrac; dest = ylookup[ds_y] + columnofs[ds_x1]; count = ds_x2 - ds_x1; do { spot = ((yfrac>>(16-6))&(63*64)) + ((xfrac>>16)&63); *dest++ = ds_colormap[ds_source[spot]]; xfrac += ds_xstep; yfrac += ds_ystep; } while (count--); } #endif /* ================ = = R_InitBuffer = ================= */ void R_InitBuffer (int width, int height) { int i; viewwindowx = (SCREENWIDTH-width) >> 1; for (i=0 ; i> 1; for (i=0 ; i>2); dest = destscreen + (ofs>>2); for (i=(count>>2)-1 ; i>=0 ; i--) dest[i] = src[i]; // set write mode 0 outp (GC_INDEX,GC_MODE); outp (GC_INDEX+1,inp(GC_INDEX+1)&~1); #else memcpy (screens[0]+ofs, screens[1]+ofs, count); #endif } /* ================== = = R_DrawViewBorder = = Draws the border around the view for different size windows ================== */ void V_MarkRect (int x, int y, int width, int height); void R_DrawViewBorder (void) { int top, side, ofs, i; if (scaledviewwidth == SCREENWIDTH) return; top = ((SCREENHEIGHT-SBARHEIGHT)-viewheight)/2; side = (SCREENWIDTH-scaledviewwidth)/2; // copy top and one line of left side R_VideoErase (0, top*SCREENWIDTH+side); // copy one line of right side and bottom ofs = (viewheight+top)*SCREENWIDTH-side; R_VideoErase (ofs, top*SCREENWIDTH+side); // copy sides using wraparound ofs = top*SCREENWIDTH + SCREENWIDTH-side; side <<= 1; for (i=1 ; i8 bit display #define MAXVISPLANES 128 #define MAXOPENINGS SCREENWIDTH*64 typedef struct { fixed_t height; int picnum; int lightlevel; int minx, maxx; byte pad1; // leave pads for [minx-1]/[maxx+1] byte top[SCREENWIDTH]; byte pad2; byte pad3; byte bottom[SCREENWIDTH]; byte pad4; } visplane_t; typedef struct drawseg_s { seg_t *curline; int x1, x2; fixed_t scale1, scale2, scalestep; int silhouette; // 0=none, 1=bottom, 2=top, 3=both fixed_t bsilheight; // don't clip sprites above this fixed_t tsilheight; // don't clip sprites below this // pointers to lists for sprite clipping short *sprtopclip; // adjusted so [x1] is first value short *sprbottomclip; // adjusted so [x1] is first value short *maskedtexturecol; // adjusted so [x1] is first value } drawseg_t; #define SIL_NONE 0 #define SIL_BOTTOM 1 #define SIL_TOP 2 #define SIL_BOTH 3 #define MAXDRAWSEGS 256 // A vissprite_t is a thing that will be drawn during a refresh typedef struct vissprite_s { struct vissprite_s *prev, *next; int x1, x2; fixed_t gx, gy; // for line side calculation fixed_t gz, gzt; // global bottom / top for silhouette clipping fixed_t startfrac; // horizontal position of x1 fixed_t scale; fixed_t xiscale; // negative if flipped fixed_t texturemid; int patch; lighttable_t *colormap; int mobjflags; // for color translation and shadow draw } vissprite_t; extern visplane_t *floorplane, *ceilingplane; // Sprites are patches with a special naming convention so they can be // recognized by R_InitSprites. The sprite and frame specified by a // thing_t is range checked at run time. // a sprite is a patch_t that is assumed to represent a three dimensional // object and may have multiple rotations pre drawn. Horizontal flipping // is used to save space. Some sprites will only have one picture used // for all views. typedef struct { boolean rotate; // if false use 0 for any position short lump[8]; // lump to use for view angles 0-7 byte flip[8]; // flip (1 = flip) to use for view angles 0-7 } spriteframe_t; typedef struct { int numframes; spriteframe_t *spriteframes; } spritedef_t; extern spritedef_t *sprites; extern int numsprites; //============================================================================= extern int numvertexes; extern vertex_t *vertexes; extern int numsegs; extern seg_t *segs; extern int numsectors; extern sector_t *sectors; extern int numsubsectors; extern subsector_t *subsectors; extern int numnodes; extern node_t *nodes; extern int numlines; extern line_t *lines; extern int numsides; extern side_t *sides; extern fixed_t viewx, viewy, viewz; extern angle_t viewangle; extern player_t *viewplayer; extern angle_t clipangle; extern int viewangletox[FINEANGLES/2]; extern angle_t xtoviewangle[SCREENWIDTH+1]; extern fixed_t finetangent[FINEANGLES/2]; extern fixed_t rw_distance; extern angle_t rw_normalangle; // // R_main.c // extern int viewwidth, viewheight, viewwindowx, viewwindowy; extern int centerx, centery; extern fixed_t centerxfrac; extern fixed_t centeryfrac; extern fixed_t projection; extern int validcount; extern int sscount, linecount, loopcount; extern lighttable_t *scalelight[LIGHTLEVELS][MAXLIGHTSCALE]; extern lighttable_t *scalelightfixed[MAXLIGHTSCALE]; extern lighttable_t *zlight[LIGHTLEVELS][MAXLIGHTZ]; extern int extralight; extern lighttable_t *fixedcolormap; extern fixed_t viewcos, viewsin; extern int detailshift; // 0 = high, 1 = low extern void (*colfunc) (void); extern void (*basecolfunc) (void); extern void (*fuzzcolfunc) (void); extern void (*spanfunc) (void); int R_PointOnSide (fixed_t x, fixed_t y, node_t *node); int R_PointOnSegSide (fixed_t x, fixed_t y, seg_t *line); angle_t R_PointToAngle (fixed_t x, fixed_t y); angle_t R_PointToAngle2 (fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2); fixed_t R_PointToDist (fixed_t x, fixed_t y); fixed_t R_ScaleFromGlobalAngle (angle_t visangle); subsector_t *R_PointInSubsector (fixed_t x, fixed_t y); void R_AddPointToBox (int x, int y, fixed_t *box); // // R_bsp.c // extern seg_t *curline; extern side_t *sidedef; extern line_t *linedef; extern sector_t *frontsector, *backsector; extern int rw_x; extern int rw_stopx; extern boolean segtextured; extern boolean markfloor; // false if the back side is the same plane extern boolean markceiling; extern boolean skymap; extern drawseg_t drawsegs[MAXDRAWSEGS], *ds_p; extern lighttable_t **hscalelight, **vscalelight, **dscalelight; typedef void (*drawfunc_t) (int start, int stop); void R_ClearClipSegs (void); void R_ClearDrawSegs (void); void R_InitSkyMap (void); void R_RenderBSPNode (int bspnum); // // R_segs.c // extern int rw_angle1; // angle to line origin void R_RenderMaskedSegRange (drawseg_t *ds, int x1, int x2); // // R_plane.c // typedef void (*planefunction_t) (int top, int bottom); extern planefunction_t floorfunc, ceilingfunc; extern int skyflatnum; extern short openings[MAXOPENINGS], *lastopening; extern short floorclip[SCREENWIDTH]; extern short ceilingclip[SCREENWIDTH]; extern fixed_t yslope[SCREENHEIGHT]; extern fixed_t distscale[SCREENWIDTH]; void R_InitPlanes (void); void R_ClearPlanes (void); void R_MapPlane (int y, int x1, int x2); void R_MakeSpans (int x, int t1, int b1, int t2, int b2); void R_DrawPlanes (void); visplane_t *R_FindPlane (fixed_t height, int picnum, int lightlevel); visplane_t *R_CheckPlane (visplane_t *pl, int start, int stop); // // R_debug.m // extern int drawbsp; void RD_OpenMapWindow (void); void RD_ClearMapWindow (void); void RD_DisplayLine (int x1, int y1, int x2, int y2, float gray); void RD_DrawNodeLine (node_t *node); void RD_DrawLineCheck (seg_t *line); void RD_DrawLine (seg_t *line); void RD_DrawBBox (fixed_t *bbox); // // R_data.c // extern fixed_t *textureheight; // needed for texture pegging extern fixed_t *spritewidth; // needed for pre rendering (fracs) extern fixed_t *spriteoffset; extern fixed_t *spritetopoffset; extern lighttable_t *colormaps; extern int viewwidth, scaledviewwidth, viewheight; extern int firstflat; extern int *flattranslation; // for global animation extern int *texturetranslation; // for global animation extern int firstspritelump, lastspritelump, numspritelumps; byte *R_GetColumn (int tex, int col); void R_InitData (void); void R_PrecacheLevel (void); // // R_things.c // #define MAXVISSPRITES 128 extern vissprite_t vissprites[MAXVISSPRITES], *vissprite_p; extern vissprite_t vsprsortedhead; // constant arrays used for psprite clipping and initializing clipping extern short negonearray[SCREENWIDTH]; extern short screenheightarray[SCREENWIDTH]; // vars for R_DrawMaskedColumn extern short *mfloorclip; extern short *mceilingclip; extern fixed_t spryscale; extern fixed_t sprtopscreen; extern fixed_t pspritescale, pspriteiscale; void R_DrawMaskedColumn (column_t *column); void R_SortVisSprites (void); void R_AddSprites (sector_t *sec); void R_AddPSprites (void); void R_DrawSprites (void); void R_InitSprites (char **namelist); void R_ClearSprites (void); void R_DrawMasked (void); void R_ClipVisSprite (vissprite_t *vis, int xl, int xh); //============================================================================= // // R_draw.c // //============================================================================= extern lighttable_t *dc_colormap; extern int dc_x; extern int dc_yl; extern int dc_yh; extern fixed_t dc_iscale; extern fixed_t dc_texturemid; extern byte *dc_source; // first pixel in a column void R_DrawColumn (void); void R_DrawColumnLow (void); void R_DrawFuzzColumn (void); void R_DrawFuzzColumnLow (void); void R_DrawTranslatedColumn (void); void R_DrawTranslatedColumnLow (void); extern int ds_y; extern int ds_x1; extern int ds_x2; extern lighttable_t *ds_colormap; extern fixed_t ds_xfrac; extern fixed_t ds_yfrac; extern fixed_t ds_xstep; extern fixed_t ds_ystep; extern byte *ds_source; // start of a 64*64 tile image extern byte *translationtables; extern byte *dc_translation; void R_DrawSpan (void); void R_DrawSpanLow (void); void R_InitBuffer (int width, int height); void R_InitTranslationTables (void); #endif // __R_LOCAL__ \ No newline at end of file diff --git a/R_MAIN.C b/R_MAIN.C new file mode 100644 index 0000000..20b8e0b --- /dev/null +++ b/R_MAIN.C @@ -0,0 +1 @@ +// R_main.c #include #include "doomdef.h" #include "r_local.h" /* */ int viewangleoffset; int validcount = 1; // increment every time a check is made lighttable_t *fixedcolormap; extern lighttable_t **walllights; int centerx, centery; fixed_t centerxfrac, centeryfrac; fixed_t projection; int framecount; // just for profiling purposes int sscount, linecount, loopcount; fixed_t viewx, viewy, viewz; angle_t viewangle; fixed_t viewcos, viewsin; player_t *viewplayer; int detailshift; // 0 = high, 1 = low // // precalculated math tables // angle_t clipangle; // The viewangletox[viewangle + FINEANGLES/4] lookup maps the visible view // angles to screen X coordinates, flattening the arc to a flat projection // plane. There will be many angles mapped to the same X. int viewangletox[FINEANGLES/2]; // The xtoviewangleangle[] table maps a screen pixel to the lowest viewangle // that maps back to x ranges from clipangle to -clipangle angle_t xtoviewangle[SCREENWIDTH+1]; // the finetangentgent[angle+FINEANGLES/4] table holds the fixed_t tangent // values for view angles, ranging from MININT to 0 to MAXINT. // fixed_t finetangent[FINEANGLES/2]; // fixed_t finesine[5*FINEANGLES/4]; fixed_t *finecosine = &finesine[FINEANGLES/4]; lighttable_t *scalelight[LIGHTLEVELS][MAXLIGHTSCALE]; lighttable_t *scalelightfixed[MAXLIGHTSCALE]; lighttable_t *zlight[LIGHTLEVELS][MAXLIGHTZ]; int extralight; // bumped light from gun blasts void (*colfunc) (void); void (*basecolfunc) (void); void (*fuzzcolfunc) (void); void (*transcolfunc) (void); void (*spanfunc) (void); /* =================== = = R_AddPointToBox = =================== */ void R_AddPointToBox (int x, int y, fixed_t *box) { if (x< box[BOXLEFT]) box[BOXLEFT] = x; if (x> box[BOXRIGHT]) box[BOXRIGHT] = x; if (y< box[BOXBOTTOM]) box[BOXBOTTOM] = y; if (y> box[BOXTOP]) box[BOXTOP] = y; } /* =============================================================================== = = R_PointOnSide = = Returns side 0 (front) or 1 (back) =============================================================================== */ int R_PointOnSide (fixed_t x, fixed_t y, node_t *node) { fixed_t dx,dy; fixed_t left, right; if (!node->dx) { if (x <= node->x) return node->dy > 0; return node->dy < 0; } if (!node->dy) { if (y <= node->y) return node->dx < 0; return node->dx > 0; } dx = (x - node->x); dy = (y - node->y); // try to quickly decide by looking at sign bits if ( (node->dy ^ node->dx ^ dx ^ dy)&0x80000000 ) { if ( (node->dy ^ dx) & 0x80000000 ) return 1; // (left is negative) return 0; } left = FixedMul ( node->dy>>FRACBITS , dx ); right = FixedMul ( dy , node->dx>>FRACBITS ); if (right < left) return 0; // front side return 1; // back side } int R_PointOnSegSide (fixed_t x, fixed_t y, seg_t *line) { fixed_t lx, ly; fixed_t ldx, ldy; fixed_t dx,dy; fixed_t left, right; lx = line->v1->x; ly = line->v1->y; ldx = line->v2->x - lx; ldy = line->v2->y - ly; if (!ldx) { if (x <= lx) return ldy > 0; return ldy < 0; } if (!ldy) { if (y <= ly) return ldx < 0; return ldx > 0; } dx = (x - lx); dy = (y - ly); // try to quickly decide by looking at sign bits if ( (ldy ^ ldx ^ dx ^ dy)&0x80000000 ) { if ( (ldy ^ dx) & 0x80000000 ) return 1; // (left is negative) return 0; } left = FixedMul ( ldy>>FRACBITS , dx ); right = FixedMul ( dy , ldx>>FRACBITS ); if (right < left) return 0; // front side return 1; // back side } /* =============================================================================== = = R_PointToAngle = =============================================================================== */ // to get a global angle from cartesian coordinates, the coordinates are // flipped until they are in the first octant of the coordinate system, then // the y (<=x) is scaled and divided by x to get a tangent (slope) value // which is looked up in the tantoangle[] table. The +1 size is to handle // the case when x==y without additional checking. #define SLOPERANGE 2048 #define SLOPEBITS 11 #define DBITS (FRACBITS-SLOPEBITS) extern int tantoangle[SLOPERANGE+1]; // get from tables.c // int tantoangle[SLOPERANGE+1]; int SlopeDiv (unsigned num, unsigned den) { unsigned ans; if (den < 512) return SLOPERANGE; ans = (num<<3)/(den>>8); return ans <= SLOPERANGE ? ans : SLOPERANGE; } angle_t R_PointToAngle (fixed_t x, fixed_t y) { x -= viewx; y -= viewy; if ( (!x) && (!y) ) return 0; if (x>= 0) { // x >=0 if (y>= 0) { // y>= 0 if (x>y) return tantoangle[ SlopeDiv(y,x)]; // octant 0 else return ANG90-1-tantoangle[ SlopeDiv(x,y)]; // octant 1 } else { // y<0 y = -y; if (x>y) return -tantoangle[SlopeDiv(y,x)]; // octant 8 else return ANG270+tantoangle[ SlopeDiv(x,y)]; // octant 7 } } else { // x<0 x = -x; if (y>= 0) { // y>= 0 if (x>y) return ANG180-1-tantoangle[ SlopeDiv(y,x)]; // octant 3 else return ANG90+ tantoangle[ SlopeDiv(x,y)]; // octant 2 } else { // y<0 y = -y; if (x>y) return ANG180+tantoangle[ SlopeDiv(y,x)]; // octant 4 else return ANG270-1-tantoangle[ SlopeDiv(x,y)]; // octant 5 } } return 0; } angle_t R_PointToAngle2 (fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2) { viewx = x1; viewy = y1; return R_PointToAngle (x2, y2); } fixed_t R_PointToDist (fixed_t x, fixed_t y) { int angle; fixed_t dx, dy, temp; fixed_t dist; dx = abs(x - viewx); dy = abs(y - viewy); if (dy>dx) { temp = dx; dx = dy; dy = temp; } angle = (tantoangle[ FixedDiv(dy,dx)>>DBITS ]+ANG90) >> ANGLETOFINESHIFT; dist = FixedDiv (dx, finesine[angle] ); // use as cosine return dist; } /* ================= = = R_InitPointToAngle = ================= */ void R_InitPointToAngle (void) { // now getting from tables.c #if 0 int i; long t; float f; // // slope (tangent) to angle lookup // for (i=0 ; i<=SLOPERANGE ; i++) { f = atan( (float)i/SLOPERANGE )/(3.141592657*2); t = 0xffffffff*f; tantoangle[i] = t; } #endif } //============================================================================= /* ================ = = R_ScaleFromGlobalAngle = = Returns the texture mapping scale for the current line at the given angle = rw_distance must be calculated first ================ */ fixed_t R_ScaleFromGlobalAngle (angle_t visangle) { fixed_t scale; int anglea, angleb; int sinea, sineb; fixed_t num,den; #if 0 { fixed_t dist,z; fixed_t sinv, cosv; sinv = finesine[(visangle-rw_normalangle)>>ANGLETOFINESHIFT]; dist = FixedDiv (rw_distance, sinv); cosv = finecosine[(viewangle-visangle)>>ANGLETOFINESHIFT]; z = abs(FixedMul (dist, cosv)); scale = FixedDiv(projection, z); return scale; } #endif anglea = ANG90 + (visangle-viewangle); angleb = ANG90 + (visangle-rw_normalangle); // bothe sines are allways positive sinea = finesine[anglea>>ANGLETOFINESHIFT]; sineb = finesine[angleb>>ANGLETOFINESHIFT]; num = FixedMul(projection,sineb)< num>>16) { scale = FixedDiv (num, den); if (scale > 64*FRACUNIT) scale = 64*FRACUNIT; else if (scale < 256) scale = 256; } else scale = 64*FRACUNIT; return scale; } /* ================= = = R_InitTables = ================= */ void R_InitTables (void) { // now getting from tables.c #if 0 int i; float a, fv; int t; // // viewangle tangent table // for (i=0 ; i FRACUNIT*2) t = -1; else if (finetangent[i] < -FRACUNIT*2) t = viewwidth+1; else { t = FixedMul (finetangent[i], focallength); t = (centerxfrac - t+FRACUNIT-1)>>FRACBITS; if (t < -1) t = -1; else if (t>viewwidth+1) t = viewwidth+1; } viewangletox[i] = t; } // // scan viewangletox[] to generate xtoviewangleangle[] // // xtoviewangle will give the smallest view angle that maps to x for (x=0;x<=viewwidth;x++) { i = 0; while (viewangletox[i]>x) i++; xtoviewangle[x] = (i<>= LIGHTSCALESHIFT; level = startmap - scale/DISTMAP; if (level < 0) level = 0; if (level >= NUMCOLORMAPS) level = NUMCOLORMAPS-1; zlight[i][j] = colormaps + level*256; } } } /* ============== = = R_SetViewSize = = Don't really change anything here, because i might be in the middle of = a refresh. The change will take effect next refresh. = ============== */ boolean setsizeneeded; int setblocks, setdetail; void R_SetViewSize (int blocks, int detail) { setsizeneeded = true; setblocks = blocks; setdetail = detail; } /* ============== = = R_ExecuteSetViewSize = ============== */ void R_ExecuteSetViewSize (void) { fixed_t cosadj, dy; int i,j, level, startmap; setsizeneeded = false; if (setblocks == 11) { scaledviewwidth = SCREENWIDTH; viewheight = SCREENHEIGHT; } else { scaledviewwidth = setblocks*32; viewheight = (setblocks*168/10)&~7; } detailshift = setdetail; viewwidth = scaledviewwidth>>detailshift; centery = viewheight/2; centerx = viewwidth/2; centerxfrac = centerx<>ANGLETOFINESHIFT]); distscale[i] = FixedDiv (FRACUNIT,cosadj); } // // Calculate the light levels to use for each level / scale combination // for (i=0 ; i< LIGHTLEVELS ; i++) { startmap = ((LIGHTLEVELS-1-i)*2)*NUMCOLORMAPS/LIGHTLEVELS; for (j=0 ; j= NUMCOLORMAPS) level = NUMCOLORMAPS-1; scalelight[i][j] = colormaps + level*256; } } } /* ============== = = R_Init = ============== */ extern int detailLevel; extern int screenblocks; void R_Init (void) { R_InitData (); printf ("."); R_InitPointToAngle (); printf ("."); R_InitTables (); // viewwidth / viewheight / detailLevel are set by the defaults printf ("."); R_SetViewSize (screenblocks, detailLevel); R_InitPlanes (); printf ("."); R_InitLightTables (); printf ("."); R_InitSkyMap (); printf ("."); R_InitTranslationTables (); framecount = 0; } /* ============== = = R_PointInSubsector = ============== */ subsector_t *R_PointInSubsector (fixed_t x, fixed_t y) { node_t *node; int side, nodenum; if (!numnodes) // single subsector is a special case return subsectors; nodenum = numnodes-1; while (! (nodenum & NF_SUBSECTOR) ) { node = &nodes[nodenum]; side = R_PointOnSide (x, y, node); nodenum = node->children[side]; } return &subsectors[nodenum & ~NF_SUBSECTOR]; } /* ============== = = R_SetupFrame = ============== */ void R_SetupFrame (player_t *player) { int i; //drawbsp = 1; viewplayer = player; viewx = player->mo->x; viewy = player->mo->y; viewangle = player->mo->angle + viewangleoffset; extralight = player->extralight; viewz = player->viewz; #if 0 viewx =-57333519; viewy =-57380407; viewz = 5832704; viewangle =3128950784; #endif viewsin = finesine[viewangle>>ANGLETOFINESHIFT]; viewcos = finecosine[viewangle>>ANGLETOFINESHIFT]; sscount = 0; if (player->fixedcolormap) { fixedcolormap = colormaps + player->fixedcolormap*256* sizeof(lighttable_t); walllights = scalelightfixed; for (i=0 ; i>2)+viewwindowy*80; #endif #if 0 { static int frame; memset (screens[0], frame, SCREENWIDTH*SCREENHEIGHT); frame++; } #endif } /* ============== = = R_RenderView = ============== */ void R_RenderPlayerView (player_t *player) { R_SetupFrame (player); R_ClearClipSegs (); R_ClearDrawSegs (); R_ClearPlanes (); R_ClearSprites (); NetUpdate (); // check for new console commands R_RenderBSPNode (numnodes-1); // the head node is the last node output NetUpdate (); // check for new console commands R_DrawPlanes (); NetUpdate (); // check for new console commands R_DrawMasked (); NetUpdate (); // check for new console commands } \ No newline at end of file diff --git a/R_PLANE.C b/R_PLANE.C new file mode 100644 index 0000000..4334cfc --- /dev/null +++ b/R_PLANE.C @@ -0,0 +1 @@ +// R_planes.c #include "doomdef.h" #include "r_local.h" planefunction_t floorfunc, ceilingfunc; // // sky mapping // int skyflatnum; int skytexture; int skytexturemid; // // opening // visplane_t visplanes[MAXVISPLANES], *lastvisplane; visplane_t *floorplane, *ceilingplane; short openings[MAXOPENINGS], *lastopening; // // clip values are the solid pixel bounding the range // floorclip starts out SCREENHEIGHT // ceilingclip starts out -1 // short floorclip[SCREENWIDTH]; short ceilingclip[SCREENWIDTH]; // // spanstart holds the start of a plane span // initialized to 0 at start // int spanstart[SCREENHEIGHT]; int spanstop[SCREENHEIGHT]; // // texture mapping // lighttable_t **planezlight; fixed_t planeheight; fixed_t yslope[SCREENHEIGHT]; fixed_t distscale[SCREENWIDTH]; fixed_t basexscale, baseyscale; fixed_t cachedheight[SCREENHEIGHT]; fixed_t cacheddistance[SCREENHEIGHT]; fixed_t cachedxstep[SCREENHEIGHT]; fixed_t cachedystep[SCREENHEIGHT]; /* ================ = = R_InitSkyMap = = Called whenever the view size changes = ================ */ void R_InitSkyMap (void) { skyflatnum = R_FlatNumForName ("F_SKY1"); skytexturemid = 100*FRACUNIT; } /* ==================== = = R_InitPlanes = = Only at game startup ==================== */ void R_InitPlanes (void) { } /* ================ = = R_MapPlane = global vars: planeheight ds_source basexscale baseyscale viewx viewy BASIC PRIMITIVE ================ */ void R_MapPlane (int y, int x1, int x2) { angle_t angle; fixed_t distance, length; unsigned index; #ifdef RANGECHECK if (x2 < x1 || x1<0 || x2>=viewwidth || (unsigned)y>viewheight) I_Error ("R_MapPlane: %i, %i at %i",x1,x2,y); #endif if (planeheight != cachedheight[y]) { cachedheight[y] = planeheight; distance = cacheddistance[y] = FixedMul (planeheight, yslope[y]); ds_xstep = cachedxstep[y] = FixedMul (distance,basexscale); ds_ystep = cachedystep[y] = FixedMul (distance,baseyscale); } else { distance = cacheddistance[y]; ds_xstep = cachedxstep[y]; ds_ystep = cachedystep[y]; } length = FixedMul (distance,distscale[x1]); angle = (viewangle + xtoviewangle[x1])>>ANGLETOFINESHIFT; ds_xfrac = viewx + FixedMul(finecosine[angle], length); ds_yfrac = -viewy - FixedMul(finesine[angle], length); if (fixedcolormap) ds_colormap = fixedcolormap; else { index = distance >> LIGHTZSHIFT; if (index >= MAXLIGHTZ ) index = MAXLIGHTZ-1; ds_colormap = planezlight[index]; } ds_y = y; ds_x1 = x1; ds_x2 = x2; spanfunc (); // high or low detail } //============================================================================= /* ==================== = = R_ClearPlanes = = At begining of frame ==================== */ void R_ClearPlanes (void) { int i; angle_t angle; // // opening / clipping determination // for (i=0 ; i>ANGLETOFINESHIFT; // left to right mapping // scale will be unit scale at SCREENWIDTH/2 distance basexscale = FixedDiv (finecosine[angle],centerxfrac); baseyscale = -FixedDiv (finesine[angle],centerxfrac); } /* =============== = = R_FindPlane = =============== */ visplane_t *R_FindPlane (fixed_t height, int picnum, int lightlevel) { visplane_t *check; if (picnum == skyflatnum) { height = 0; // all skys map together lightlevel = 0; } for (check=visplanes; checkheight && picnum == check->picnum && lightlevel == check->lightlevel) break; if (check < lastvisplane) return check; if (lastvisplane - visplanes == MAXVISPLANES) I_Error ("R_FindPlane: no more visplanes"); lastvisplane++; check->height = height; check->picnum = picnum; check->lightlevel = lightlevel; check->minx = SCREENWIDTH; check->maxx = -1; memset (check->top,0xff,sizeof(check->top)); return check; } /* =============== = = R_CheckPlane = =============== */ visplane_t *R_CheckPlane (visplane_t *pl, int start, int stop) { int intrl, intrh; int unionl, unionh; int x; if (start < pl->minx) { intrl = pl->minx; unionl = start; } else { unionl = pl->minx; intrl = start; } if (stop > pl->maxx) { intrh = pl->maxx; unionh = stop; } else { unionh = pl->maxx; intrh = stop; } for (x=intrl ; x<= intrh ; x++) if (pl->top[x] != 0xff) break; if (x > intrh) { pl->minx = unionl; pl->maxx = unionh; return pl; // use the same one } // make a new visplane lastvisplane->height = pl->height; lastvisplane->picnum = pl->picnum; lastvisplane->lightlevel = pl->lightlevel; pl = lastvisplane++; pl->minx = start; pl->maxx = stop; memset (pl->top,0xff,sizeof(pl->top)); return pl; } //============================================================================= /* ================ = = R_MakeSpans = ================ */ void R_MakeSpans (int x, int t1, int b1, int t2, int b2) { while (t1 < t2 && t1<=b1) { R_MapPlane (t1,spanstart[t1],x-1); t1++; } while (b1 > b2 && b1>=t1) { R_MapPlane (b1,spanstart[b1],x-1); b1--; } while (t2 < t1 && t2<=b2) { spanstart[t2] = x; t2++; } while (b2 > b1 && b2>=t2) { spanstart[b2] = x; b2--; } } /* ================ = = R_DrawPlanes = = At the end of each frame ================ */ void R_DrawPlanes (void) { visplane_t *pl; int light; int x, stop; int angle; #ifdef RANGECHECK if (ds_p - drawsegs > MAXDRAWSEGS) I_Error ("R_DrawPlanes: drawsegs overflow (%i)", ds_p - drawsegs); if (lastvisplane - visplanes > MAXVISPLANES) I_Error ("R_DrawPlanes: visplane overflow (%i)", lastvisplane - visplanes); if (lastopening - openings > MAXOPENINGS) I_Error ("R_DrawPlanes: opening overflow (%i)", lastopening - openings); #endif for (pl = visplanes ; pl < lastvisplane ; pl++) { if (pl->minx > pl->maxx) continue; // // sky flat // if (pl->picnum == skyflatnum) { dc_iscale = pspriteiscale>>detailshift; dc_colormap = colormaps;// sky is allways drawn full bright dc_texturemid = skytexturemid; for (x=pl->minx ; x <= pl->maxx ; x++) { dc_yl = pl->top[x]; dc_yh = pl->bottom[x]; if (dc_yl <= dc_yh) { angle = (viewangle + xtoviewangle[x])>>ANGLETOSKYSHIFT; dc_x = x; dc_source = R_GetColumn(skytexture, angle); colfunc (); } } continue; } // // regular flat // ds_source = W_CacheLumpNum(firstflat + flattranslation[pl->picnum],PU_STATIC); planeheight = abs(pl->height-viewz); light = (pl->lightlevel >> LIGHTSEGSHIFT)+extralight; if (light >= LIGHTLEVELS) light = LIGHTLEVELS-1; if (light < 0) light = 0; planezlight = zlight[light]; pl->top[pl->maxx+1] = 0xff; pl->top[pl->minx-1] = 0xff; stop = pl->maxx + 1; for (x=pl->minx ; x<= stop ; x++) R_MakeSpans (x,pl->top[x-1],pl->bottom[x-1] ,pl->top[x],pl->bottom[x]); Z_ChangeTag (ds_source, PU_CACHE); } } \ No newline at end of file diff --git a/R_SEGS.C b/R_SEGS.C new file mode 100644 index 0000000..3a3c20f --- /dev/null +++ b/R_SEGS.C @@ -0,0 +1 @@ +// R_segs.c #include "doomdef.h" #include "r_local.h" // OPTIMIZE: closed two sided lines as single sided boolean segtextured; // true if any of the segs textures might be vis boolean markfloor; // false if the back side is the same plane boolean markceiling; boolean maskedtexture; int toptexture, bottomtexture, midtexture; angle_t rw_normalangle; int rw_angle1; // angle to line origin // // wall // int rw_x; int rw_stopx; angle_t rw_centerangle; fixed_t rw_offset; fixed_t rw_distance; fixed_t rw_scale; fixed_t rw_scalestep; fixed_t rw_midtexturemid; fixed_t rw_toptexturemid; fixed_t rw_bottomtexturemid; int worldtop, worldbottom, worldhigh, worldlow; fixed_t pixhigh, pixlow; fixed_t pixhighstep, pixlowstep; fixed_t topfrac, topstep; fixed_t bottomfrac, bottomstep; lighttable_t **walllights; short *maskedtexturecol; /* ================ = = R_RenderMaskedSegRange = ================ */ void R_RenderMaskedSegRange (drawseg_t *ds, int x1, int x2) { unsigned index; column_t *col; int lightnum; int texnum; // // calculate light table // use different light tables for horizontal / vertical / diagonal // OPTIMIZE: get rid of LIGHTSEGSHIFT globally curline = ds->curline; frontsector = curline->frontsector; backsector = curline->backsector; texnum = texturetranslation[curline->sidedef->midtexture]; lightnum = (frontsector->lightlevel >> LIGHTSEGSHIFT)+extralight; if (curline->v1->y == curline->v2->y) lightnum--; else if (curline->v1->x == curline->v2->x) lightnum++; if (lightnum < 0) walllights = scalelight[0]; else if (lightnum >= LIGHTLEVELS) walllights = scalelight[LIGHTLEVELS-1]; else walllights = scalelight[lightnum]; maskedtexturecol = ds->maskedtexturecol; rw_scalestep = ds->scalestep; spryscale = ds->scale1 + (x1 - ds->x1)*rw_scalestep; mfloorclip = ds->sprbottomclip; mceilingclip = ds->sprtopclip; // // find positioning // if (curline->linedef->flags & ML_DONTPEGBOTTOM) { dc_texturemid = frontsector->floorheight > backsector->floorheight ? frontsector->floorheight : backsector->floorheight; dc_texturemid = dc_texturemid + textureheight[texnum] - viewz; } else { dc_texturemid =frontsector->ceilingheightceilingheight ? frontsector->ceilingheight : backsector->ceilingheight; dc_texturemid = dc_texturemid - viewz; } dc_texturemid += curline->sidedef->rowoffset; if (fixedcolormap) dc_colormap = fixedcolormap; // // draw the columns // for (dc_x = x1 ; dc_x <= x2 ; dc_x++) { // calculate lighting if (maskedtexturecol[dc_x] != MAXSHORT) { if (!fixedcolormap) { index = spryscale>>LIGHTSCALESHIFT; if (index >= MAXLIGHTSCALE ) index = MAXLIGHTSCALE-1; dc_colormap = walllights[index]; } sprtopscreen = centeryfrac - FixedMul(dc_texturemid, spryscale); dc_iscale = 0xffffffffu / (unsigned)spryscale; // // draw the texture // col = (column_t *)( (byte *)R_GetColumn(texnum,maskedtexturecol[dc_x]) -3); R_DrawMaskedColumn (col); maskedtexturecol[dc_x] = MAXSHORT; } spryscale += rw_scalestep; } } /* ================ = = R_RenderSegLoop = = Draws zero, one, or two textures (and possibly a masked texture) for walls = Can draw or mark the starting pixel of floor and ceiling textures = = CALLED: CORE LOOPING ROUTINE ================ */ #define HEIGHTBITS 12 #define HEIGHTUNIT (1<>HEIGHTBITS; if (yl < ceilingclip[rw_x]+1) yl = ceilingclip[rw_x]+1; // no space above wall if (markceiling) { top = ceilingclip[rw_x]+1; bottom = yl-1; if (bottom >= floorclip[rw_x]) bottom = floorclip[rw_x]-1; if (top <= bottom) { ceilingplane->top[rw_x] = top; ceilingplane->bottom[rw_x] = bottom; } } yh = bottomfrac>>HEIGHTBITS; if (yh >= floorclip[rw_x]) yh = floorclip[rw_x]-1; if (markfloor) { top = yh+1; bottom = floorclip[rw_x]-1; if (top <= ceilingclip[rw_x]) top = ceilingclip[rw_x]+1; if (top <= bottom) { floorplane->top[rw_x] = top; floorplane->bottom[rw_x] = bottom; } } // // texturecolumn and lighting are independent of wall tiers // if (segtextured) { // calculate texture offset angle = (rw_centerangle + xtoviewangle[rw_x])>>ANGLETOFINESHIFT; texturecolumn = rw_offset-FixedMul(finetangent[angle],rw_distance); texturecolumn >>= FRACBITS; // calculate lighting index = rw_scale>>LIGHTSCALESHIFT; if (index >= MAXLIGHTSCALE ) index = MAXLIGHTSCALE-1; dc_colormap = walllights[index]; dc_x = rw_x; dc_iscale = 0xffffffffu / (unsigned)rw_scale; } // // draw the wall tiers // if (midtexture) { // single sided line dc_yl = yl; dc_yh = yh; dc_texturemid = rw_midtexturemid; dc_source = R_GetColumn(midtexture,texturecolumn); colfunc (); ceilingclip[rw_x] = viewheight; floorclip[rw_x] = -1; } else { // two sided line if (toptexture) { // top wall mid = pixhigh>>HEIGHTBITS; pixhigh += pixhighstep; if (mid >= floorclip[rw_x]) mid = floorclip[rw_x]-1; if (mid >= yl) { dc_yl = yl; dc_yh = mid; dc_texturemid = rw_toptexturemid; dc_source = R_GetColumn(toptexture,texturecolumn); colfunc (); ceilingclip[rw_x] = mid; } else ceilingclip[rw_x] = yl-1; } else { // no top wall if (markceiling) ceilingclip[rw_x] = yl-1; } if (bottomtexture) { // bottom wall mid = (pixlow+HEIGHTUNIT-1)>>HEIGHTBITS; pixlow += pixlowstep; if (mid <= ceilingclip[rw_x]) mid = ceilingclip[rw_x]+1; // no space above wall if (mid <= yh) { dc_yl = mid; dc_yh = yh; dc_texturemid = rw_bottomtexturemid; dc_source = R_GetColumn(bottomtexture, texturecolumn); colfunc (); floorclip[rw_x] = mid; } else floorclip[rw_x] = yh+1; } else { // no bottom wall if (markfloor) floorclip[rw_x] = yh+1; } if (maskedtexture) { // save texturecol for backdrawing of masked mid texture maskedtexturecol[rw_x] = texturecolumn; } } rw_scale += rw_scalestep; topfrac += topstep; bottomfrac += bottomstep; } } /* ===================== = = R_StoreWallRange = = A wall segment will be drawn between start and stop pixels (inclusive) = ====================== */ void R_StoreWallRange (int start, int stop) { fixed_t hyp; fixed_t sineval; angle_t distangle, offsetangle; fixed_t vtop; int lightnum; if (ds_p == &drawsegs[MAXDRAWSEGS]) return; // don't overflow and crash #ifdef RANGECHECK if (start >=viewwidth || start > stop) I_Error ("Bad R_RenderWallRange: %i to %i", start , stop); #endif #ifdef __NeXT__ RD_DrawLine (curline); #endif sidedef = curline->sidedef; linedef = curline->linedef; // mark the segment as visible for auto map linedef->flags |= ML_MAPPED; // // calculate rw_distance for scale calculation // rw_normalangle = curline->angle + ANG90; offsetangle = abs(rw_normalangle-rw_angle1); if (offsetangle > ANG90) offsetangle = ANG90; distangle = ANG90 - offsetangle; hyp = R_PointToDist (curline->v1->x, curline->v1->y); sineval = finesine[distangle>>ANGLETOFINESHIFT]; rw_distance = FixedMul (hyp, sineval); ds_p->x1 = rw_x = start; ds_p->x2 = stop; ds_p->curline = curline; rw_stopx = stop+1; // // calculate scale at both ends and step // ds_p->scale1 = rw_scale = R_ScaleFromGlobalAngle (viewangle + xtoviewangle[start]); if (stop > start ) { ds_p->scale2 = R_ScaleFromGlobalAngle (viewangle + xtoviewangle[stop]); ds_p->scalestep = rw_scalestep = (ds_p->scale2 - rw_scale) / (stop-start); } else { // // try to fix the stretched line bug // #if 0 if (rw_distance < FRACUNIT/2) { fixed_t trx,try; fixed_t gxt,gyt; trx = curline->v1->x - viewx; try = curline->v1->y - viewy; gxt = FixedMul(trx,viewcos); gyt = -FixedMul(try,viewsin); ds_p->scale1 = FixedDiv(projection, gxt-gyt)<scale2 = ds_p->scale1; } // // calculate texture boundaries and decide if floor / ceiling marks // are needed // worldtop = frontsector->ceilingheight - viewz; worldbottom = frontsector->floorheight - viewz; midtexture = toptexture = bottomtexture = maskedtexture = 0; ds_p->maskedtexturecol = NULL; if (!backsector) { // // single sided line // midtexture = texturetranslation[sidedef->midtexture]; // a single sided line is terminal, so it must mark ends markfloor = markceiling = true; if (linedef->flags & ML_DONTPEGBOTTOM) { vtop = frontsector->floorheight + textureheight[sidedef->midtexture]; rw_midtexturemid = vtop - viewz; // bottom of texture at bottom } else rw_midtexturemid = worldtop; // top of texture at top rw_midtexturemid += sidedef->rowoffset; ds_p->silhouette = SIL_BOTH; ds_p->sprtopclip = screenheightarray; ds_p->sprbottomclip = negonearray; ds_p->bsilheight = MAXINT; ds_p->tsilheight = MININT; } else { // // two sided line // ds_p->sprtopclip = ds_p->sprbottomclip = NULL; ds_p->silhouette = 0; if (frontsector->floorheight > backsector->floorheight) { ds_p->silhouette = SIL_BOTTOM; ds_p->bsilheight = frontsector->floorheight; } else if (backsector->floorheight > viewz) { ds_p->silhouette = SIL_BOTTOM; ds_p->bsilheight = MAXINT; // ds_p->sprbottomclip = negonearray; } if (frontsector->ceilingheight < backsector->ceilingheight) { ds_p->silhouette |= SIL_TOP; ds_p->tsilheight = frontsector->ceilingheight; } else if (backsector->ceilingheight < viewz) { ds_p->silhouette |= SIL_TOP; ds_p->tsilheight = MININT; // ds_p->sprtopclip = screenheightarray; } if (backsector->ceilingheight <= frontsector->floorheight) { ds_p->sprbottomclip = negonearray; ds_p->bsilheight = MAXINT; ds_p->silhouette |= SIL_BOTTOM; } if (backsector->floorheight >= frontsector->ceilingheight) { ds_p->sprtopclip = screenheightarray; ds_p->tsilheight = MININT; ds_p->silhouette |= SIL_TOP; } worldhigh = backsector->ceilingheight - viewz; worldlow = backsector->floorheight - viewz; // hack to allow height changes in outdoor areas if (frontsector->ceilingpic == skyflatnum && backsector->ceilingpic == skyflatnum) worldtop = worldhigh; if (worldlow != worldbottom || backsector->floorpic != frontsector->floorpic || backsector->lightlevel != frontsector->lightlevel) markfloor = true; else markfloor = false; // same plane on both sides if (worldhigh != worldtop || backsector->ceilingpic != frontsector->ceilingpic || backsector->lightlevel != frontsector->lightlevel) markceiling = true; else markceiling = false; // same plane on both sides if (backsector->ceilingheight <= frontsector->floorheight || backsector->floorheight >= frontsector->ceilingheight) markceiling = markfloor = true; // closed door if (worldhigh < worldtop) { // top texture toptexture = texturetranslation[sidedef->toptexture]; if (linedef->flags & ML_DONTPEGTOP) rw_toptexturemid = worldtop; // top of texture at top else { vtop = backsector->ceilingheight + textureheight[sidedef->toptexture]; rw_toptexturemid = vtop - viewz; // bottom of texture } } if (worldlow > worldbottom) { // bottom texture bottomtexture = texturetranslation[sidedef->bottomtexture]; if (linedef->flags & ML_DONTPEGBOTTOM ) { // bottom of texture at bottom rw_bottomtexturemid = worldtop;// top of texture at top } else // top of texture at top rw_bottomtexturemid = worldlow; } rw_toptexturemid += sidedef->rowoffset; rw_bottomtexturemid += sidedef->rowoffset; // // allocate space for masked texture tables // if (sidedef->midtexture) { // masked midtexture maskedtexture = true; ds_p->maskedtexturecol = maskedtexturecol = lastopening - rw_x; lastopening += rw_stopx - rw_x; } } // // calculate rw_offset (only needed for textured lines) // segtextured = midtexture | toptexture | bottomtexture | maskedtexture; if (segtextured) { offsetangle = rw_normalangle-rw_angle1; if (offsetangle > ANG180) offsetangle = -offsetangle; if (offsetangle > ANG90) offsetangle = ANG90; sineval = finesine[offsetangle >>ANGLETOFINESHIFT]; rw_offset = FixedMul (hyp, sineval); if (rw_normalangle-rw_angle1 < ANG180) rw_offset = -rw_offset; rw_offset += sidedef->textureoffset + curline->offset; rw_centerangle = ANG90 + viewangle - rw_normalangle; // // calculate light table // use different light tables for horizontal / vertical / diagonal // OPTIMIZE: get rid of LIGHTSEGSHIFT globally if (!fixedcolormap) { lightnum = (frontsector->lightlevel >> LIGHTSEGSHIFT)+extralight; if (curline->v1->y == curline->v2->y) lightnum--; else if (curline->v1->x == curline->v2->x) lightnum++; if (lightnum < 0) walllights = scalelight[0]; else if (lightnum >= LIGHTLEVELS) walllights = scalelight[LIGHTLEVELS-1]; else walllights = scalelight[lightnum]; } } // // if a floor / ceiling plane is on the wrong side of the view plane // it is definately invisible and doesn't need to be marked // if (frontsector->floorheight >= viewz) markfloor = false; // above view plane if (frontsector->ceilingheight <= viewz && frontsector->ceilingpic != skyflatnum) markceiling = false; // below view plane // // calculate incremental stepping values for texture edges // worldtop >>= 4; worldbottom >>= 4; topstep = -FixedMul (rw_scalestep, worldtop); topfrac = (centeryfrac>>4) - FixedMul (worldtop, rw_scale); bottomstep = -FixedMul (rw_scalestep,worldbottom); bottomfrac = (centeryfrac>>4) - FixedMul (worldbottom, rw_scale); if (backsector) { worldhigh >>= 4; worldlow >>= 4; if (worldhigh < worldtop) { pixhigh = (centeryfrac>>4) - FixedMul (worldhigh, rw_scale); pixhighstep = -FixedMul (rw_scalestep,worldhigh); } if (worldlow > worldbottom) { pixlow = (centeryfrac>>4) - FixedMul (worldlow, rw_scale); pixlowstep = -FixedMul (rw_scalestep,worldlow); } } // // render it // if (markceiling) ceilingplane = R_CheckPlane (ceilingplane, rw_x, rw_stopx-1); if (markfloor) floorplane = R_CheckPlane (floorplane, rw_x, rw_stopx-1); R_RenderSegLoop (); // // save sprite clipping info // if ( ((ds_p->silhouette & SIL_TOP) || maskedtexture) && !ds_p->sprtopclip) { memcpy (lastopening, ceilingclip+start, 2*(rw_stopx-start)); ds_p->sprtopclip = lastopening - start; lastopening += rw_stopx - start; } if ( ((ds_p->silhouette & SIL_BOTTOM) || maskedtexture) && !ds_p->sprbottomclip) { memcpy (lastopening, floorclip+start, 2*(rw_stopx-start)); ds_p->sprbottomclip = lastopening - start; lastopening += rw_stopx - start; } if (maskedtexture && !(ds_p->silhouette&SIL_TOP)) { ds_p->silhouette |= SIL_TOP; ds_p->tsilheight = MININT; } if (maskedtexture && !(ds_p->silhouette&SIL_BOTTOM)) { ds_p->silhouette |= SIL_BOTTOM; ds_p->bsilheight = MAXINT; } ds_p++; } \ No newline at end of file diff --git a/R_THINGS.C b/R_THINGS.C new file mode 100644 index 0000000..43d675e --- /dev/null +++ b/R_THINGS.C @@ -0,0 +1 @@ +// R_things.c #include #include #include "doomdef.h" #include "r_local.h" void R_DrawColumn (void); void R_DrawFuzzColumn (void); typedef struct { int x1, x2; int column; int topclip; int bottomclip; } maskdraw_t; /* Sprite rotation 0 is facing the viewer, rotation 1 is one angle turn CLOCKWISE around the axis. This is not the same as the angle, which increases counter clockwise (protractor). There was a lot of stuff grabbed wrong, so I changed it... */ fixed_t pspritescale, pspriteiscale; lighttable_t **spritelights; // constant arrays used for psprite clipping and initializing clipping short negonearray[SCREENWIDTH]; short screenheightarray[SCREENWIDTH]; /* =============================================================================== INITIALIZATION FUNCTIONS =============================================================================== */ // variables used to look up and range check thing_t sprites patches spritedef_t *sprites; int numsprites; spriteframe_t sprtemp[29]; int maxframe; char *spritename; /* ================= = = R_InstallSpriteLump = = Local function for R_InitSprites ================= */ void R_InstallSpriteLump (int lump, unsigned frame, unsigned rotation, boolean flipped) { int r; if (frame >= 29 || rotation > 8) I_Error ("R_InstallSpriteLump: Bad frame characters in lump %i", lump); if ((int)frame > maxframe) maxframe = frame; if (rotation == 0) { // the lump should be used for all rotations if (sprtemp[frame].rotate == false) I_Error ("R_InitSprites: Sprite %s frame %c has multip rot=0 lump" , spritename, 'A'+frame); if (sprtemp[frame].rotate == true) I_Error ("R_InitSprites: Sprite %s frame %c has rotations and a rot=0 lump" , spritename, 'A'+frame); sprtemp[frame].rotate = false; for (r=0 ; r<8 ; r++) { sprtemp[frame].lump[r] = lump - firstspritelump; sprtemp[frame].flip[r] = (byte)flipped; } return; } // the lump is only used for one rotation if (sprtemp[frame].rotate == false) I_Error ("R_InitSprites: Sprite %s frame %c has rotations and a rot=0 lump" , spritename, 'A'+frame); sprtemp[frame].rotate = true; rotation--; // make 0 based if (sprtemp[frame].lump[rotation] != -1) I_Error ("R_InitSprites: Sprite %s : %c : %c has two lumps mapped to it" ,spritename, 'A'+frame, '1'+rotation); sprtemp[frame].lump[rotation] = lump - firstspritelump; sprtemp[frame].flip[rotation] = (byte)flipped; } /* ================= = = R_InitSpriteDefs = = Pass a null terminated list of sprite names (4 chars exactly) to be used = Builds the sprite rotation matrixes to account for horizontally flipped = sprites. Will report an error if the lumps are inconsistant = Only called at startup = = Sprite lump names are 4 characters for the actor, a letter for the frame, = and a number for the rotation, A sprite that is flippable will have an = additional letter/number appended. The rotation character can be 0 to = signify no rotations ================= */ void R_InitSpriteDefs (char **namelist) { char **check; int i, l, intname, frame, rotation; int start, end; int patched; // count the number of sprite names check = namelist; while (*check != NULL) check++; numsprites = check-namelist; if (!numsprites) return; sprites = Z_Malloc(numsprites *sizeof(*sprites), PU_STATIC, NULL); start = firstspritelump-1; end = lastspritelump+1; // scan all the lump names for each of the names, noting the highest // frame letter // Just compare 4 characters as ints for (i=0 ; itopdelta != 0xff ; ) { // calculate unclipped screen coordinates for post topscreen = sprtopscreen + spryscale*column->topdelta; bottomscreen = topscreen + spryscale*column->length; dc_yl = (topscreen+FRACUNIT-1)>>FRACBITS; dc_yh = (bottomscreen-1)>>FRACBITS; if (dc_yh >= mfloorclip[dc_x]) dc_yh = mfloorclip[dc_x]-1; if (dc_yl <= mceilingclip[dc_x]) dc_yl = mceilingclip[dc_x]+1; if (dc_yl <= dc_yh) { dc_source = (byte *)column + 3; dc_texturemid = basetexturemid - (column->topdelta<topdelta; colfunc (); // either R_DrawColumn or R_DrawFuzzColumn } column = (column_t *)( (byte *)column + column->length + 4); } dc_texturemid = basetexturemid; } /* ================ = = R_DrawVisSprite = = mfloorclip and mceilingclip should also be set ================ */ void R_DrawVisSprite (vissprite_t *vis, int x1, int x2) { column_t *column; int texturecolumn; fixed_t frac; patch_t *patch; patch = W_CacheLumpNum (vis->patch+firstspritelump, PU_CACHE); dc_colormap = vis->colormap; if (!dc_colormap) colfunc = fuzzcolfunc; // NULL colormap = shadow draw else if (vis->mobjflags & MF_TRANSLATION) { colfunc = R_DrawTranslatedColumn; dc_translation = translationtables - 256 + ( (vis->mobjflags & MF_TRANSLATION) >> (MF_TRANSSHIFT-8) ); } dc_iscale = abs(vis->xiscale)>>detailshift; dc_texturemid = vis->texturemid; frac = vis->startfrac; spryscale = vis->scale; sprtopscreen = centeryfrac - FixedMul(dc_texturemid,spryscale); for (dc_x=vis->x1 ; dc_x<=vis->x2 ; dc_x++, frac += vis->xiscale) { texturecolumn = frac>>FRACBITS; #ifdef RANGECHECK if (texturecolumn < 0 || texturecolumn >= SHORT(patch->width)) I_Error ("R_DrawSpriteRange: bad texturecolumn"); #endif column = (column_t *) ((byte *)patch + LONG(patch->columnofs[texturecolumn])); R_DrawMaskedColumn (column); } colfunc = basecolfunc; } /* =================== = = R_ProjectSprite = = Generates a vissprite for a thing if it might be visible = =================== */ void R_ProjectSprite (mobj_t *thing) { fixed_t trx,try; fixed_t gxt,gyt; fixed_t tx,tz; fixed_t xscale; int x1, x2; spritedef_t *sprdef; spriteframe_t *sprframe; int lump; unsigned rot; boolean flip; int index; vissprite_t *vis; angle_t ang; fixed_t iscale; // // transform the origin point // trx = thing->x - viewx; try = thing->y - viewy; gxt = FixedMul(trx,viewcos); gyt = -FixedMul(try,viewsin); tz = gxt-gyt; if (tz < MINZ) return; // thing is behind view plane xscale = FixedDiv(projection, tz); gxt = -FixedMul(trx,viewsin); gyt = FixedMul(try,viewcos); tx = -(gyt+gxt); if (abs(tx)>(tz<<2)) return; // too far off the side // // decide which patch to use for sprite reletive to player // #ifdef RANGECHECK if ((unsigned)thing->sprite >= numsprites) I_Error ("R_ProjectSprite: invalid sprite number %i ",thing->sprite); #endif sprdef = &sprites[thing->sprite]; #ifdef RANGECHECK if ( (thing->frame&FF_FRAMEMASK) >= sprdef->numframes ) I_Error ("R_ProjectSprite: invalid sprite frame %i : %i " ,thing->sprite, thing->frame); #endif sprframe = &sprdef->spriteframes[ thing->frame & FF_FRAMEMASK]; if (sprframe->rotate) { // choose a different rotation based on player view ang = R_PointToAngle (thing->x, thing->y); rot = (ang-thing->angle+(unsigned)(ANG45/2)*9)>>29; lump = sprframe->lump[rot]; flip = (boolean)sprframe->flip[rot]; } else { // use single rotation for all views lump = sprframe->lump[0]; flip = (boolean)sprframe->flip[0]; } // // calculate edges of the shape // tx -= spriteoffset[lump]; x1 = (centerxfrac + FixedMul (tx,xscale) ) >>FRACBITS; if (x1 > viewwidth) return; // off the right side tx += spritewidth[lump]; x2 = ((centerxfrac + FixedMul (tx,xscale) ) >>FRACBITS) - 1; if (x2 < 0) return; // off the left side // // store information in a vissprite // vis = R_NewVisSprite (); vis->mobjflags = thing->flags; vis->scale = xscale<gx = thing->x; vis->gy = thing->y; vis->gz = thing->z; vis->gzt = thing->z + spritetopoffset[lump]; vis->texturemid = vis->gzt - viewz; vis->x1 = x1 < 0 ? 0 : x1; vis->x2 = x2 >= viewwidth ? viewwidth-1 : x2; iscale = FixedDiv (FRACUNIT, xscale); if (flip) { vis->startfrac = spritewidth[lump]-1; vis->xiscale = -iscale; } else { vis->startfrac = 0; vis->xiscale = iscale; } if (vis->x1 > x1) vis->startfrac += vis->xiscale*(vis->x1-x1); vis->patch = lump; // // get light level // if (thing->flags & MF_SHADOW) vis->colormap = NULL; // shadow draw else if (fixedcolormap) vis->colormap = fixedcolormap; // fixed map else if (thing->frame & FF_FULLBRIGHT) vis->colormap = colormaps; // full bright else { // diminished light index = xscale>>(LIGHTSCALESHIFT-detailshift); if (index >= MAXLIGHTSCALE) index = MAXLIGHTSCALE-1; vis->colormap = spritelights[index]; } } /* ======================== = = R_AddSprites = ======================== */ void R_AddSprites (sector_t *sec) { mobj_t *thing; int lightnum; if (sec->validcount == validcount) return; // already added sec->validcount = validcount; lightnum = (sec->lightlevel >> LIGHTSEGSHIFT)+extralight; if (lightnum < 0) spritelights = scalelight[0]; else if (lightnum >= LIGHTLEVELS) spritelights = scalelight[LIGHTLEVELS-1]; else spritelights = scalelight[lightnum]; for (thing = sec->thinglist ; thing ; thing = thing->snext) R_ProjectSprite (thing); } /* ======================== = = R_DrawPSprite = ======================== */ void R_DrawPSprite (pspdef_t *psp) { fixed_t tx; int x1, x2; spritedef_t *sprdef; spriteframe_t *sprframe; int lump; boolean flip; vissprite_t *vis, avis; // // decide which patch to use // #ifdef RANGECHECK if ( (unsigned)psp->state->sprite >= numsprites) I_Error ("R_ProjectSprite: invalid sprite number %i " , psp->state->sprite); #endif sprdef = &sprites[psp->state->sprite]; #ifdef RANGECHECK if ( (psp->state->frame & FF_FRAMEMASK) >= sprdef->numframes) I_Error ("R_ProjectSprite: invalid sprite frame %i : %i " , psp->state->sprite, psp->state->frame); #endif sprframe = &sprdef->spriteframes[ psp->state->frame & FF_FRAMEMASK ]; lump = sprframe->lump[0]; flip = (boolean)sprframe->flip[0]; // // calculate edges of the shape // tx = psp->sx-160*FRACUNIT; tx -= spriteoffset[lump]; x1 = (centerxfrac + FixedMul (tx,pspritescale) ) >>FRACBITS; if (x1 > viewwidth) return; // off the right side tx += spritewidth[lump]; x2 = ((centerxfrac + FixedMul (tx, pspritescale) ) >>FRACBITS) - 1; if (x2 < 0) return; // off the left side // // store information in a vissprite // vis = &avis; vis->mobjflags = 0; vis->texturemid = (BASEYCENTER<sy-spritetopoffset[lump]); vis->x1 = x1 < 0 ? 0 : x1; vis->x2 = x2 >= viewwidth ? viewwidth-1 : x2; vis->scale = pspritescale<xiscale = -pspriteiscale; vis->startfrac = spritewidth[lump]-1; } else { vis->xiscale = pspriteiscale; vis->startfrac = 0; } if (vis->x1 > x1) vis->startfrac += vis->xiscale*(vis->x1-x1); vis->patch = lump; if (viewplayer->powers[pw_invisibility] > 4*32 || viewplayer->powers[pw_invisibility] & 8) vis->colormap = NULL; // shadow draw else if (fixedcolormap) vis->colormap = fixedcolormap; // fixed color else if (psp->state->frame & FF_FULLBRIGHT) vis->colormap = colormaps; // full bright else vis->colormap = spritelights[MAXLIGHTSCALE-1]; // local light R_DrawVisSprite (vis, vis->x1, vis->x2); } /* ======================== = = R_DrawPlayerSprites = ======================== */ void R_DrawPlayerSprites (void) { int i, lightnum; pspdef_t *psp; // // get light level // lightnum = (viewplayer->mo->subsector->sector->lightlevel >> LIGHTSEGSHIFT) +extralight; if (lightnum < 0) spritelights = scalelight[0]; else if (lightnum >= LIGHTLEVELS) spritelights = scalelight[LIGHTLEVELS-1]; else spritelights = scalelight[lightnum]; // // clip to screen bounds // mfloorclip = screenheightarray; mceilingclip = negonearray; // // add all active psprites // for (i=0, psp=viewplayer->psprites ; istate) R_DrawPSprite (psp); } /* ======================== = = R_SortVisSprites = ======================== */ vissprite_t vsprsortedhead; void R_SortVisSprites (void) { int i, count; vissprite_t *ds, *best; vissprite_t unsorted; fixed_t bestscale; count = vissprite_p - vissprites; unsorted.next = unsorted.prev = &unsorted; if (!count) return; for (ds=vissprites ; dsnext = ds+1; ds->prev = ds-1; } vissprites[0].prev = &unsorted; unsorted.next = &vissprites[0]; (vissprite_p-1)->next = &unsorted; unsorted.prev = vissprite_p-1; // // pull the vissprites out by scale // best = 0; // shut up the compiler warning vsprsortedhead.next = vsprsortedhead.prev = &vsprsortedhead; for (i=0 ; inext) { if (ds->scale < bestscale) { bestscale = ds->scale; best = ds; } } best->next->prev = best->prev; best->prev->next = best->next; best->next = &vsprsortedhead; best->prev = vsprsortedhead.prev; vsprsortedhead.prev->next = best; vsprsortedhead.prev = best; } } /* ======================== = = R_DrawSprite = ======================== */ void R_DrawSprite (vissprite_t *spr) { drawseg_t *ds; short clipbot[SCREENWIDTH], cliptop[SCREENWIDTH]; int x, r1, r2; fixed_t scale, lowscale; int silhouette; for (x = spr->x1 ; x<=spr->x2 ; x++) clipbot[x] = cliptop[x] = -2; // // scan drawsegs from end to start for obscuring segs // the first drawseg that has a greater scale is the clip seg // for (ds=ds_p-1 ; ds >= drawsegs ; ds--) { // // determine if the drawseg obscures the sprite // if (ds->x1 > spr->x2 || ds->x2 < spr->x1 || (!ds->silhouette && !ds->maskedtexturecol) ) continue; // doesn't cover sprite r1 = ds->x1 < spr->x1 ? spr->x1 : ds->x1; r2 = ds->x2 > spr->x2 ? spr->x2 : ds->x2; if (ds->scale1 > ds->scale2) { lowscale = ds->scale2; scale = ds->scale1; } else { lowscale = ds->scale1; scale = ds->scale2; } if (scale < spr->scale || ( lowscale < spr->scale && !R_PointOnSegSide (spr->gx, spr->gy, ds->curline) ) ) { if (ds->maskedtexturecol) // masked mid texture R_RenderMaskedSegRange (ds, r1, r2); continue; // seg is behind sprite } // // clip this piece of the sprite // silhouette = ds->silhouette; if (spr->gz >= ds->bsilheight) silhouette &= ~SIL_BOTTOM; if (spr->gzt <= ds->tsilheight) silhouette &= ~SIL_TOP; if (silhouette == 1) { // bottom sil for (x=r1 ; x<=r2 ; x++) if (clipbot[x] == -2) clipbot[x] = ds->sprbottomclip[x]; } else if (silhouette == 2) { // top sil for (x=r1 ; x<=r2 ; x++) if (cliptop[x] == -2) cliptop[x] = ds->sprtopclip[x]; } else if (silhouette == 3) { // both for (x=r1 ; x<=r2 ; x++) { if (clipbot[x] == -2) clipbot[x] = ds->sprbottomclip[x]; if (cliptop[x] == -2) cliptop[x] = ds->sprtopclip[x]; } } } // // all clipping has been performed, so draw the sprite // // check for unclipped columns for (x = spr->x1 ; x<=spr->x2 ; x++) { if (clipbot[x] == -2) clipbot[x] = viewheight; if (cliptop[x] == -2) cliptop[x] = -1; } mfloorclip = clipbot; mceilingclip = cliptop; R_DrawVisSprite (spr, spr->x1, spr->x2); } /* ======================== = = R_DrawMasked = ======================== */ void R_DrawMasked (void) { vissprite_t *spr; drawseg_t *ds; R_SortVisSprites (); if (vissprite_p > vissprites) { // draw all vissprites back to front for (spr = vsprsortedhead.next ; spr != &vsprsortedhead ; spr=spr->next) R_DrawSprite (spr); } // // render any remaining masked mid textures // for (ds=ds_p-1 ; ds >= drawsegs ; ds--) if (ds->maskedtexturecol) R_RenderMaskedSegRange (ds, ds->x1, ds->x2); // // draw the psprites on top of everything // if (!viewangleoffset) // don't draw on side views R_DrawPlayerSprites (); } \ No newline at end of file diff --git a/SOUNDS.C b/SOUNDS.C new file mode 100644 index 0000000..3ba8800 --- /dev/null +++ b/SOUNDS.C @@ -0,0 +1 @@ +enum { false, true }; #include "sounds.h" /* * Information about all the music */ musicinfo_t S_music[] = { { 0 }, { "e1m1", 0 }, { "e1m2", 0 }, { "e1m3", 0 }, { "e1m4", 0 }, { "e1m5", 0 }, { "e1m6", 0 }, { "e1m7", 0 }, { "e1m8", 0 }, { "e1m9", 0 }, { "e2m1", 0 }, { "e2m2", 0 }, { "e2m3", 0 }, { "e2m4", 0 }, { "e2m5", 0 }, { "e2m6", 0 }, { "e2m7", 0 }, { "e2m8", 0 }, { "e2m9", 0 }, { "e3m1", 0 }, { "e3m2", 0 }, { "e3m3", 0 }, { "e3m4", 0 }, { "e3m5", 0 }, { "e3m6", 0 }, { "e3m7", 0 }, { "e3m8", 0 }, { "e3m9", 0 }, { "inter", 0 }, { "intro", 0 }, { "bunny", 0 }, { "victor", 0 }, { "introa", 0 }, { "runnin", 0 }, { "stalks", 0 }, { "countd", 0 }, { "betwee", 0 }, { "doom", 0 }, { "the_da", 0 }, { "shawn", 0 }, { "ddtblu", 0 }, { "in_cit", 0 }, { "dead", 0 }, { "stlks2", 0 }, { "theda2", 0 }, { "doom2", 0 }, { "ddtbl2", 0 }, { "runni2", 0 }, { "dead2", 0 }, { "stlks3", 0 }, { "romero", 0 }, { "shawn2", 0 }, { "messag", 0 }, { "count2", 0 }, { "ddtbl3", 0 }, { "ampie", 0 }, { "theda3", 0 }, { "adrian", 0 }, { "messg2", 0 }, { "romer2", 0 }, { "tense", 0 }, { "shawn3", 0 }, { "openin", 0 }, { "evil", 0 }, { "ultima", 0 }, { "read_m", 0 }, { "dm2ttl", 0 }, { "dm2int", 0 } }; /* * Information about all the sfx */ sfxinfo_t S_sfx[] = { { 0 }, { "pistol", false, 64, 0, -1, -1, 0 }, { "shotgn", false, 64, 0, -1, -1, 0 }, { "sgcock", false, 64, 0, -1, -1, 0 }, { "dshtgn", false, 64, 0, -1, -1, 0 }, { "dbopn", false, 64, 0, -1, -1, 0 }, { "dbcls", false, 64, 0, -1, -1, 0 }, { "dbload", false, 64, 0, -1, -1, 0 }, { "plasma", false, 64, 0, -1, -1, 0 }, { "bfg", false, 64, 0, -1, -1, 0 }, { "sawup", false, 64, 0, -1, -1, 0 }, { "sawidl", false, 118, 0, -1, -1, 0 }, { "sawful", false, 64, 0, -1, -1, 0 }, { "sawhit", false, 64, 0, -1, -1, 0 }, { "rlaunc", false, 64, 0, -1, -1, 0 }, { "rxplod", false, 70, 0, -1, -1, 0 }, { "firsht", false, 70, 0, -1, -1, 0 }, { "firxpl", false, 70, 0, -1, -1, 0 }, { "pstart", false, 100, 0, -1, -1, 0 }, { "pstop", false, 100, 0, -1, -1, 0 }, { "doropn", false, 100, 0, -1, -1, 0 }, { "dorcls", false, 100, 0, -1, -1, 0 }, { "stnmov", false, 119, 0, -1, -1, 0 }, { "swtchn", false, 78, 0, -1, -1, 0 }, { "swtchx", false, 78, 0, -1, -1, 0 }, { "plpain", false, 96, 0, -1, -1, 0 }, { "dmpain", false, 96, 0, -1, -1, 0 }, { "popain", false, 96, 0, -1, -1, 0 }, { "vipain", false, 96, 0, -1, -1, 0 }, { "mnpain", false, 96, 0, -1, -1, 0 }, { "pepain", false, 96, 0, -1, -1, 0 }, { "slop", false, 78, 0, -1, -1, 0 }, { "itemup", true, 78, 0, -1, -1, 0 }, { "wpnup", true, 78, 0, -1, -1, 0 }, { "oof", false, 96, 0, -1, -1, 0 }, { "telept", false, 32, 0, -1, -1, 0 }, { "posit1", true, 98, 0, -1, -1, 0 }, { "posit2", true, 98, 0, -1, -1, 0 }, { "posit3", true, 98, 0, -1, -1, 0 }, { "bgsit1", true, 98, 0, -1, -1, 0 }, { "bgsit2", true, 98, 0, -1, -1, 0 }, { "sgtsit", true, 98, 0, -1, -1, 0 }, { "cacsit", true, 98, 0, -1, -1, 0 }, { "brssit", true, 94, 0, -1, -1, 0 }, { "cybsit", true, 92, 0, -1, -1, 0 }, { "spisit", true, 90, 0, -1, -1, 0 }, { "bspsit", true, 90, 0, -1, -1, 0 }, { "kntsit", true, 90, 0, -1, -1, 0 }, { "vilsit", true, 90, 0, -1, -1, 0 }, { "mansit", true, 90, 0, -1, -1, 0 }, { "pesit", true, 90, 0, -1, -1, 0 }, { "sklatk", false, 70, 0, -1, -1, 0 }, { "sgtatk", false, 70, 0, -1, -1, 0 }, { "skepch", false, 70, 0, -1, -1, 0 }, { "vilatk", false, 70, 0, -1, -1, 0 }, { "claw", false, 70, 0, -1, -1, 0 }, { "skeswg", false, 70, 0, -1, -1, 0 }, { "pldeth", false, 32, 0, -1, -1, 0 }, { "pdiehi", false, 32, 0, -1, -1, 0 }, { "podth1", false, 70, 0, -1, -1, 0 }, { "podth2", false, 70, 0, -1, -1, 0 }, { "podth3", false, 70, 0, -1, -1, 0 }, { "bgdth1", false, 70, 0, -1, -1, 0 }, { "bgdth2", false, 70, 0, -1, -1, 0 }, { "sgtdth", false, 70, 0, -1, -1, 0 }, { "cacdth", false, 70, 0, -1, -1, 0 }, { "skldth", false, 70, 0, -1, -1, 0 }, { "brsdth", false, 32, 0, -1, -1, 0 }, { "cybdth", false, 32, 0, -1, -1, 0 }, { "spidth", false, 32, 0, -1, -1, 0 }, { "bspdth", false, 32, 0, -1, -1, 0 }, { "vildth", false, 32, 0, -1, -1, 0 }, { "kntdth", false, 32, 0, -1, -1, 0 }, { "pedth", false, 32, 0, -1, -1, 0 }, { "skedth", false, 32, 0, -1, -1, 0 }, { "posact", true, 120, 0, -1, -1, 0 }, { "bgact", true, 120, 0, -1, -1, 0 }, { "dmact", true, 120, 0, -1, -1, 0 }, { "bspact", true, 100, 0, -1, -1, 0 }, { "bspwlk", true, 100, 0, -1, -1, 0 }, { "vilact", true, 100, 0, -1, -1, 0 }, { "noway", false, 78, 0, -1, -1, 0 }, { "barexp", false, 60, 0, -1, -1, 0 }, { "punch", false, 64, 0, -1, -1, 0 }, { "hoof", false, 70, 0, -1, -1, 0 }, { "metal", false, 70, 0, -1, -1, 0 }, { "chgun", false, 64, &S_sfx[sfx_pistol], 150, 0, 0 }, { "tink", false, 60, 0, -1, -1, 0 }, { "bdopn", false, 100, 0, -1, -1, 0 }, { "bdcls", false, 100, 0, -1, -1, 0 }, { "itmbk", false, 100, 0, -1, -1, 0 }, { "flame", false, 32, 0, -1, -1, 0 }, { "flamst", false, 32, 0, -1, -1, 0 }, { "getpow", false, 60, 0, -1, -1, 0 }, { "bospit", false, 70, 0, -1, -1, 0 }, { "boscub", false, 70, 0, -1, -1, 0 }, { "bossit", false, 70, 0, -1, -1, 0 }, { "bospn", false, 70, 0, -1, -1, 0 }, { "bosdth", false, 70, 0, -1, -1, 0 }, { "manatk", false, 70, 0, -1, -1, 0 }, { "mandth", false, 70, 0, -1, -1, 0 }, { "sssit", false, 70, 0, -1, -1, 0 }, { "ssdth", false, 70, 0, -1, -1, 0 }, { "keenpn", false, 70, 0, -1, -1, 0 }, { "keendt", false, 70, 0, -1, -1, 0 }, { "skeact", false, 70, 0, -1, -1, 0 }, { "skesit", false, 70, 0, -1, -1, 0 }, { "skeatk", false, 70, 0, -1, -1, 0 }, { "radio", false, 60, 0, -1, -1, 0 } }; \ No newline at end of file diff --git a/SOUNDS.H b/SOUNDS.H new file mode 100644 index 0000000..879b35c --- /dev/null +++ b/SOUNDS.H @@ -0,0 +1 @@ +#ifndef __SOUNDSH__ #define __SOUNDSH__ #include "soundst.h" /* * Identifiers for all music in game. */ typedef enum { mus_None, mus_e1m1, mus_e1m2, mus_e1m3, mus_e1m4, mus_e1m5, mus_e1m6, mus_e1m7, mus_e1m8, mus_e1m9, mus_e2m1, mus_e2m2, mus_e2m3, mus_e2m4, mus_e2m5, mus_e2m6, mus_e2m7, mus_e2m8, mus_e2m9, mus_e3m1, mus_e3m2, mus_e3m3, mus_e3m4, mus_e3m5, mus_e3m6, mus_e3m7, mus_e3m8, mus_e3m9, mus_inter, mus_intro, mus_bunny, mus_victor, mus_introa, mus_runnin, mus_stalks, mus_countd, mus_betwee, mus_doom, mus_the_da, mus_shawn, mus_ddtblu, mus_in_cit, mus_dead, mus_stlks2, mus_theda2, mus_doom2, mus_ddtbl2, mus_runni2, mus_dead2, mus_stlks3, mus_romero, mus_shawn2, mus_messag, mus_count2, mus_ddtbl3, mus_ampie, mus_theda3, mus_adrian, mus_messg2, mus_romer2, mus_tense, mus_shawn3, mus_openin, mus_evil, mus_ultima, mus_read_m, mus_dm2ttl, mus_dm2int, NUMMUSIC } musicenum_t; /* * Identifiers for all sfx in game. */ typedef enum { sfx_None, sfx_pistol, sfx_shotgn, sfx_sgcock, sfx_dshtgn, sfx_dbopn, sfx_dbcls, sfx_dbload, sfx_plasma, sfx_bfg, sfx_sawup, sfx_sawidl, sfx_sawful, sfx_sawhit, sfx_rlaunc, sfx_rxplod, sfx_firsht, sfx_firxpl, sfx_pstart, sfx_pstop, sfx_doropn, sfx_dorcls, sfx_stnmov, sfx_swtchn, sfx_swtchx, sfx_plpain, sfx_dmpain, sfx_popain, sfx_vipain, sfx_mnpain, sfx_pepain, sfx_slop, sfx_itemup, sfx_wpnup, sfx_oof, sfx_telept, sfx_posit1, sfx_posit2, sfx_posit3, sfx_bgsit1, sfx_bgsit2, sfx_sgtsit, sfx_cacsit, sfx_brssit, sfx_cybsit, sfx_spisit, sfx_bspsit, sfx_kntsit, sfx_vilsit, sfx_mansit, sfx_pesit, sfx_sklatk, sfx_sgtatk, sfx_skepch, sfx_vilatk, sfx_claw, sfx_skeswg, sfx_pldeth, sfx_pdiehi, sfx_podth1, sfx_podth2, sfx_podth3, sfx_bgdth1, sfx_bgdth2, sfx_sgtdth, sfx_cacdth, sfx_skldth, sfx_brsdth, sfx_cybdth, sfx_spidth, sfx_bspdth, sfx_vildth, sfx_kntdth, sfx_pedth, sfx_skedth, sfx_posact, sfx_bgact, sfx_dmact, sfx_bspact, sfx_bspwlk, sfx_vilact, sfx_noway, sfx_barexp, sfx_punch, sfx_hoof, sfx_metal, sfx_chgun, sfx_tink, sfx_bdopn, sfx_bdcls, sfx_itmbk, sfx_flame, sfx_flamst, sfx_getpow, sfx_bospit, sfx_boscub, sfx_bossit, sfx_bospn, sfx_bosdth, sfx_manatk, sfx_mandth, sfx_sssit, sfx_ssdth, sfx_keenpn, sfx_keendt, sfx_skeact, sfx_skesit, sfx_skeatk, sfx_radio, NUMSFX } sfxenum_t; extern musicinfo_t S_music[]; extern sfxinfo_t S_sfx[]; #endif \ No newline at end of file diff --git a/SOUNDST.H b/SOUNDST.H new file mode 100644 index 0000000..87b0368 --- /dev/null +++ b/SOUNDST.H @@ -0,0 +1 @@ + #ifndef __SOUNDSTH__ #define __SOUNDSTH__ #define S_MAX_VOLUME 127 #define S_CLIPPING_DIST (1200*0x10000) // when to clip out sounds #define S_CLOSE_DIST (200*0x10000) // when sounds should be max'd out #define S_ATTENUATOR ((S_CLIPPING_DIST-S_CLOSE_DIST)>>FRACBITS) #define NORM_PITCH 128 #define NORM_PRIORITY 64 #define NORM_VOLUME snd_MaxVolume #define S_PITCH_PERTURB 1 #define NORM_SEP 128 #define S_STEREO_SWING (96*0x10000) #define S_IFRACVOL 30 // % attenuation from front to back #define NA 0 #define S_NUMCHANNELS 2 // See gensounds.h and gensounds.c for what soundst.h is made of. typedef struct { char *name; // up to 6-character name int lumpnum; // lump number of music void *data; // music data int handle; // music handle once registered } musicinfo_t; typedef struct sfxinfo_struct sfxinfo_t; struct sfxinfo_struct { char *name; // up to 6-character name int singularity; // Sfx singularity (only one at a time) int priority; // Sfx priority sfxinfo_t *link; // referenced sound if a link int pitch; // pitch if a link int volume; // volume if a link void *data; // sound data int usefulness; // this is checked every second to see if sound // can be thrown out (if 0, then decrement, if -1, // then throw out, if > 0, then it's in use) int lumpnum; // lump number of sfx }; typedef struct { sfxinfo_t *sfxinfo; // sound information (if null, channel avail.) void *origin; // origin of sound int handle; // handle of the sound being played } channel_t; enum {Music, Sfx, SfxLink}; enum {PC=1, Adlib=2, SB=4, Midi=8}; // cards available enum {sfxThrowOut=-1, sfxNotUsed=0}; // Initialize the sound code at start of level // void S_Start(void); // Start sound for thing at using from sounds.h // extern void S_StartSound(void *origin, int sound_id); // Will start a sound at a given volume. extern void S_StartSoundAtVolume(void *origin, int sound_id, int volume); // Stop sound for thing at // extern void S_StopSound(void *origin); // Start music using from sounds.h // extern void S_StartMusic(int music_id); // Start music using from sounds.h, and set whether looping // extern void S_ChangeMusic(int music_id, int looping); // Stops the music // extern void S_StopMusic(void); void S_PauseSound(void); void S_ResumeSound(void); // Updates music & sounds // extern void S_UpdateSounds(void *listener); void S_SetMusicVolume(int volume); void S_SetSfxVolume(int volume); // Initializes sound stuff, including volume // void S_Init(int , int); //-------- //SOUND IO //-------- #define FREQ_LOW 0x40 #define FREQ_NORM 0x80 #define FREQ_HIGH 0xff void I_SetMusicVolume(int volume); void I_SetSfxVolume(int volume); // MUSIC I/O // void I_PauseSong(int handle); void I_ResumeSong(int handle); void I_PlaySong(int handle, int looping); // called by anything that wishes to start music. // plays a song, and when the song is done, starts playing it again in // an endless loop. void I_StopSong(int handle); // stops a song over 3 seconds. int I_RegisterSong(void *data); // registers a song handle to song data void I_UnRegisterSong(int handle); // see above then think backwards int I_QrySongPlaying(int handle); // is the song playing? // SFX I/O // void I_SetChannels(int channels); int I_GetSfxLumpNum (sfxinfo_t *); int I_StartSound (int id, void *data, int vol, int sep, int pitch, int priority); // Starts a sound in a particular sound channel void I_UpdateSoundParams(int handle, int vol, int sep, int pitch); // Updates the volume, separation, and pitch of a sound channel void I_StopSound(int handle); // Stops a sound channel int I_SoundIsPlaying(int handle); // called by S_*()'s to see if a channel is still playing. Returns 0 // if no longer playing, 1 if playing. extern sfxinfo_t S_sfx[]; // the complete set of sound effects extern musicinfo_t S_music[]; // the complete set of music #endif \ No newline at end of file diff --git a/ST_LIB.C b/ST_LIB.C new file mode 100644 index 0000000..5d97dd7 --- /dev/null +++ b/ST_LIB.C @@ -0,0 +1 @@ +// ST_lib.c : the status bar widget code #include #include "doomdef.h" #include "st_stuff.h" #include "st_lib.h" #include "r_local.h" extern boolean automapactive; // in AM_map.c patch_t *sttminus; void STlib_init(void) { sttminus = (patch_t *) W_CacheLumpName("STTMINUS", PU_STATIC); } void STlib_initNum(st_number_t *n, int x, int y, patch_t **pl, int *num, boolean *on, int width) { n->x = x; n->y = y; n->oldnum = 0; n->width = width; n->num = num; n->on = on; n->p = pl; } // A fairly efficient way to draw a number based on differences from the // old number. void STlib_drawNum(st_number_t *n, boolean refresh) { int numdigits = n->width; int num = *n->num; int w = SHORT(n->p[0]->width), h = SHORT(n->p[0]->height); int x = n->x; int neg; n->oldnum = *n->num; neg = num < 0; if (neg) { if (numdigits == 2 && num < -9) num = -9; else if (numdigits == 3 && num < -99) num = -99; num = -num; } // clear the area x = n->x - numdigits*w; if (n->y - ST_Y < 0) I_Error("drawNum: n->y - ST_Y < 0"); V_CopyRect(x, n->y - ST_Y, BG, w*numdigits, h, x, n->y, FG); // if non-number, don't draw it if (num == 1994) return; x = n->x; // in the special case of 0, you draw 0 if (!num) V_DrawPatch(x - w, n->y, FG, n->p[ 0 ]); // draw the new number while (num && numdigits--) { x -= w; V_DrawPatch(x, n->y, FG, n->p[ num % 10 ]); num /= 10; } // draw a minus sign if necessary if (neg) V_DrawPatch(x - 8, n->y, FG, sttminus); } void STlib_updateNum(st_number_t *n, boolean refresh) { if (*n->on) STlib_drawNum(n, refresh); } void STlib_initPercent(st_percent_t *p, int x, int y, patch_t **pl, int *num, boolean *on, patch_t *percent) { STlib_initNum(&p->n, x, y, pl, num, on, 3); p->p = percent; } void STlib_updatePercent(st_percent_t *per, int refresh) { if (refresh && *per->n.on) V_DrawPatch(per->n.x, per->n.y, FG, per->p); STlib_updateNum(&per->n, refresh); } void STlib_initMultIcon(st_multicon_t *i, int x, int y, patch_t **il, int *inum, boolean *on) { i->x = x; i->y = y; i->oldinum = -1; i->inum = inum; i->on = on; i->p = il; } void STlib_updateMultIcon(st_multicon_t *mi, boolean refresh) { int w, h, x, y; if (*mi->on && (mi->oldinum != *mi->inum || refresh) && (*mi->inum!=-1)) { if (mi->oldinum != -1) { x = mi->x - SHORT(mi->p[mi->oldinum]->leftoffset); y = mi->y - SHORT(mi->p[mi->oldinum]->topoffset); w = SHORT(mi->p[mi->oldinum]->width); h = SHORT(mi->p[mi->oldinum]->height); if (y - ST_Y < 0) I_Error("updateMultIcon: y - ST_Y < 0"); V_CopyRect(x, y-ST_Y, BG, w, h, x, y, FG); } V_DrawPatch(mi->x, mi->y, FG, mi->p[*mi->inum]); mi->oldinum = *mi->inum; } } void STlib_initBinIcon(st_binicon_t *b, int x, int y, patch_t *i, boolean *val, boolean *on) { b->x = x; b->y = y; b->oldval = 0; b->val = val; b->on = on; b->p = i; } void STlib_updateBinIcon(st_binicon_t *bi, boolean refresh) { int x, y, w, h; if (*bi->on && (bi->oldval != *bi->val || refresh)) { x = bi->x - SHORT(bi->p->leftoffset); y = bi->y - SHORT(bi->p->topoffset); w = SHORT(bi->p->width); h = SHORT(bi->p->height); if (y - ST_Y < 0) I_Error("updateBinIcon: y - ST_Y < 0"); if (*bi->val) V_DrawPatch(bi->x, bi->y, FG, bi->p); else V_CopyRect(x, y-ST_Y, BG, w, h, x, y, FG); bi->oldval = *bi->val; } } \ No newline at end of file diff --git a/ST_LIB.H b/ST_LIB.H new file mode 100644 index 0000000..6458f09 --- /dev/null +++ b/ST_LIB.H @@ -0,0 +1 @@ +#ifndef __STLIB__ #define __STLIB__ // background and foreground screen numbers #define BG 4 #define FG 0 /* * Typedefs of widgets */ // Number widget typedef struct { int x, y; // upper right-hand corner of the number (right-justified) int width; // max # of digits in number int oldnum; // last number value int *num; // pointer to current value boolean *on; // pointer to boolean stating whether to update number patch_t **p; // list of patches for 0-9 int data; // user data } st_number_t; // Percent widget (child of number widget) typedef struct { st_number_t n; // number information patch_t *p; // percent sign graphic } st_percent_t; // Multiple Icon widget typedef struct { int x, y; // center-justified location of icons int oldinum; // last icon number int *inum; // pointer to current icon boolean *on; // pointer to boolean stating whether to update icon patch_t **p; // list of icons int data; // user data } st_multicon_t; // Binary Icon widget typedef struct { int x, y; // center-justified location of icon int oldval; // last icon value boolean *val; // pointer to current icon status boolean *on; // pointer to boolean stating whether to update icon patch_t *p; // icon int data; // user data } st_binicon_t; /* * Widget creation, access, and update routines */ // initializes widget library void STlib_init(void); // Number widget routines void STlib_initNum(st_number_t *n, int x, int y, patch_t **pl, int *num, boolean *on, int width); void STlib_updateNum(st_number_t *n, boolean refresh); // Percent widget routines void STlib_initPercent(st_percent_t *p, int x, int y, patch_t **pl, int *num, boolean *on, patch_t *percent); void STlib_updatePercent(st_percent_t *per, int refresh); // Multiple Icon widget routines void STlib_initMultIcon(st_multicon_t *mi, int x, int y, patch_t **il, int *inum, boolean *on); void STlib_updateMultIcon(st_multicon_t *mi, boolean refresh); // Binary Icon widget routines void STlib_initBinIcon(st_binicon_t *b, int x, int y, patch_t *i, boolean *val, boolean *on); void STlib_updateBinIcon(st_binicon_t *bi, boolean refresh); #endif \ No newline at end of file diff --git a/ST_STUFF.C b/ST_STUFF.C new file mode 100644 index 0000000..8f69bd2 --- /dev/null +++ b/ST_STUFF.C @@ -0,0 +1 @@ +// ST_stuff.c : the status bar code #include #include "doomdef.h" #include "st_stuff.h" #include "st_lib.h" #include "r_local.h" #include "p_local.h" #include "am_map.h" #include "dutils.h" /* * * STATUS BAR DATA * */ static player_t *plyr; // main player in game static boolean st_firsttime; // ST_Start() has just been called static int lu_palette; // lump number for PLAYPAL static int veryfirsttime = 1; // used to execute ST_Init() only once static unsigned int st_clock; // used for timing static int st_msgcounter=0; // used for making messages go away static st_chatstateenum_t st_chatstate; // used when in chat static st_stateenum_t st_gamestate; // whether in automap or first-person static boolean st_statusbaron; // whether left-side main status bar is active static boolean st_chat; // whether status bar chat is active static boolean st_oldchat; // value of st_chat before message popped up static boolean st_cursoron; // whether chat window has the cursor on static boolean st_notdeathmatch; // !deathmatch static boolean st_armson; // !deathmatch && st_statusbaron static boolean st_fragson; // !deathmatch static patch_t *sbar; // main bar left static patch_t *tallnum[10]; // 0-9, tall numbers static patch_t *tallpercent; // tall % sign static patch_t *shortnum[10]; // 0-9, short, yellow (,different!) numbers static patch_t *keys[NUMCARDS]; // 3 key-cards, 3 skulls static patch_t *faces[ST_NUMFACES]; // face status patches static patch_t *faceback; // face background static patch_t *armsbg; // main bar right static patch_t *arms[6][2]; // weapon ownership patches static st_number_t w_ready; // ready-weapon widget static st_number_t w_frags; // in deathmatch only, summary of frags stats static st_percent_t w_health; // health widget static st_binicon_t w_armsbg; // arms background static st_multicon_t w_arms[6]; // weapon ownership widgets static st_multicon_t w_faces; // face status widget static st_multicon_t w_keyboxes[3]; // keycard widgets static st_percent_t w_armor; // armor widget static st_number_t w_ammo[4]; // ammo widgets static st_number_t w_maxammo[4]; // max ammo widgets static int st_fragscount; // number of frags so far in deathmatch static int st_oldhealth = -1; // used to use appopriately pained face static boolean oldweaponsowned[NUMWEAPONS]; // used for evil grin static int st_facecount = 0; // count until face changes static int st_faceindex = 0; // current face index, used by w_faces static int keyboxes[3]; // holds key-type for each key box on bar static int st_randomnumber; // a random number per tick // massive bunches of cheat shit to keep it from being easy // to figure 'em out. unsigned char cheat_mus_seq[] = { 0xb2, 0x26, 0xb6, 0xae, 0xea, 1, 0, 0, 0xff }; unsigned char cheat_choppers_seq[] = { 0xb2, 0x26, 0xe2, 0x32, 0xf6, 0x2a, 0x2a, 0xa6, 0x6a, 0xea, 0xff }; unsigned char cheat_god_seq[] = { 0xb2, 0x26, 0x26, 0xaa, 0x26, 0xff }; // dqd unsigned char cheat_ammo_seq[] = { 0xb2, 0x26, 0xf2, 0x66, 0xa2, 0xff }; // kfa unsigned char cheat_ammonokey_seq[] = { 0xb2, 0x26, 0x66, 0xa2, 0xff }; // kfa unsigned char cheat_noclip_seq[] = { 0xb2, 0x26, 0xea, 0x2a, 0xb2, 0xea, 0x2a, 0xf6, 0x2a, 0x26, 0xff }; // spispopd unsigned char cheat_commercial_noclip_seq[] = { 0xb2, 0x26, 0xe2, 0x36, 0xb2, 0x2a, 0xff }; // idclip unsigned char cheat_powerup_seq[7][10] = { { 0xb2, 0x26, 0x62, 0xa6, 0x32, 0xf6, 0x36, 0x26, 0x6e, 0xff }, // beholdv { 0xb2, 0x26, 0x62, 0xa6, 0x32, 0xf6, 0x36, 0x26, 0xea, 0xff }, // beholds { 0xb2, 0x26, 0x62, 0xa6, 0x32, 0xf6, 0x36, 0x26, 0xb2, 0xff }, // beholdi { 0xb2, 0x26, 0x62, 0xa6, 0x32, 0xf6, 0x36, 0x26, 0x6a, 0xff }, // beholdr { 0xb2, 0x26, 0x62, 0xa6, 0x32, 0xf6, 0x36, 0x26, 0xa2, 0xff }, // beholda { 0xb2, 0x26, 0x62, 0xa6, 0x32, 0xf6, 0x36, 0x26, 0x36, 0xff }, // beholdl { 0xb2, 0x26, 0x62, 0xa6, 0x32, 0xf6, 0x36, 0x26, 0xff } // behold }; unsigned char cheat_clev_seq[] = {0xb2, 0x26, 0xe2, 0x36, 0xa6, 0x6e, 1, 0, 0, 0xff }; // clev unsigned char cheat_mypos_seq[] = { 0xb2, 0x26, 0xb6, 0xba, 0x2a, 0xf6, 0xea, 0xff }; // my position cheat cheatseq_t cheat_mus = { cheat_mus_seq, 0 }; cheatseq_t cheat_god = { cheat_god_seq, 0 }; cheatseq_t cheat_ammo = { cheat_ammo_seq, 0 }; cheatseq_t cheat_ammonokey = { cheat_ammonokey_seq, 0 }; cheatseq_t cheat_noclip = { cheat_noclip_seq, 0 }; cheatseq_t cheat_commercial_noclip = { cheat_commercial_noclip_seq, 0 }; cheatseq_t cheat_powerup[7] = { { cheat_powerup_seq[0], 0 }, { cheat_powerup_seq[1], 0 }, { cheat_powerup_seq[2], 0 }, { cheat_powerup_seq[3], 0 }, { cheat_powerup_seq[4], 0 }, { cheat_powerup_seq[5], 0 }, { cheat_powerup_seq[6], 0 } }; cheatseq_t cheat_choppers = { cheat_choppers_seq, 0 }; cheatseq_t cheat_clev = { cheat_clev_seq, 0 }; cheatseq_t cheat_mypos = { cheat_mypos_seq, 0 }; extern char *mapnames[]; /* * * STATUS BAR CODE * */ void ST_Stop(void); void ST_refreshBackground(void) { if (st_statusbaron) { V_DrawPatch(ST_X, 0, BG, sbar); if (netgame) V_DrawPatch(ST_FX, 0, BG, faceback); V_CopyRect(ST_X, 0, BG, ST_WIDTH, ST_HEIGHT, ST_X, ST_Y, FG); } } boolean ST_Responder (event_t *ev) { int i; boolean P_GivePower(player_t *, int); if (ev->type == ev_keyup && ((ev->data1 & 0xffff0000) == AM_MSGHEADER)) { switch(ev->data1) { case AM_MSGENTERED: st_gamestate = AutomapState; st_firsttime = true; break; case AM_MSGEXITED: // fprintf(stderr, "AM exited\n"); st_gamestate = FirstPersonState; break; } } // if a user keypress... else if (ev->type == ev_keydown) { if (!netgame) { if (gameskill != sk_nightmare) { // 'dqd' cheat for toggleable god mode if (cht_CheckCheat(&cheat_god, ev->data1)) { plyr->cheats ^= CF_GODMODE; if (plyr->cheats & CF_GODMODE) { if (plyr->mo) plyr->mo->health = 100; plyr->health = 100; plyr->message = STSTR_DQDON; } else plyr->message = STSTR_DQDOFF; } // 'fa' cheat for killer fucking arsenal else if (cht_CheckCheat(&cheat_ammonokey, ev->data1)) { plyr->armorpoints = 200; plyr->armortype = 2; for (i=0;iweaponowned[i] = true; for (i=0;iammo[i] = plyr->maxammo[i]; plyr->message = STSTR_FAADDED; } // 'kfa' cheat for killer fucking arsenal else if (cht_CheckCheat(&cheat_ammo, ev->data1)) { plyr->armorpoints = 200; plyr->armortype = 2; for (i=0;iweaponowned[i] = true; for (i=0;iammo[i] = plyr->maxammo[i]; for (i=0;icards[i] = true; plyr->message = STSTR_KFAADDED; } // 'mus' cheat for changing music else if (cht_CheckCheat(&cheat_mus, ev->data1)) { char buf[3]; int musnum; plyr->message = STSTR_MUS; cht_GetParam(&cheat_mus, buf); musnum = mus_runnin + (buf[0]-'0')*10 + buf[1]-'0' - 1; if (((buf[0]-'0')*10 + buf[1]-'0') > 35) plyr->message = STSTR_NOMUS; else S_ChangeMusic(musnum, 1); } // no clipping mode cheat else if (!commercial && cht_CheckCheat(&cheat_noclip, ev->data1)) { plyr->cheats ^= CF_NOCLIP; if (plyr->cheats & CF_NOCLIP) plyr->message = STSTR_NCON; else plyr->message = STSTR_NCOFF; } else if (commercial && cht_CheckCheat(&cheat_commercial_noclip, ev->data1)) { plyr->cheats ^= CF_NOCLIP; if (plyr->cheats & CF_NOCLIP) plyr->message = STSTR_NCON; else plyr->message = STSTR_NCOFF; } // 'behold?' power-up cheats for (i=0;i<6;i++) { if (cht_CheckCheat(&cheat_powerup[i], ev->data1)) { if (!plyr->powers[i]) P_GivePower(plyr, i); else if (i!=pw_strength) plyr->powers[i] = 1; else plyr->powers[i] = 0; plyr->message = STSTR_BEHOLDX; } } // 'behold' power-up menu if (cht_CheckCheat(&cheat_powerup[6], ev->data1)) { plyr->message = STSTR_BEHOLD; } // 'choppers' invulnerability & chainsaw else if (cht_CheckCheat(&cheat_choppers, ev->data1)) { plyr->weaponowned[wp_chainsaw] = true; plyr->powers[pw_invulnerability] = true; plyr->message = STSTR_CHOPPERS; } // 'mypos' for player position else if (cht_CheckCheat(&cheat_mypos, ev->data1)) { static char buf[ST_MSGWIDTH]; sprintf(buf, "ang=0x%x;x,y=(0x%x,0x%x)", players[consoleplayer].mo->angle, players[consoleplayer].mo->x, players[consoleplayer].mo->y); plyr->message = buf; } } // 'clev' change-level cheat if (cht_CheckCheat(&cheat_clev, ev->data1)) { char buf[3]; int epsd, map; cht_GetParam(&cheat_clev, buf); if (commercial) { epsd = 0; map = (buf[0] - '0')*10 + buf[1] - '0'; } else { epsd = buf[0] - '0'; map = buf[1] - '0'; } if ( (!commercial && (epsd > 0 && epsd < 4 && map > 0 && map < 10)) || (commercial && (map > 0 && map <= 40))) { plyr->message = STSTR_CLEV; G_DeferedInitNew(gameskill, epsd, map); } } } } return false; } int ST_calcPainOffset(void) { int health; static int lastcalc; static int oldhealth = -1; health = plyr->health > 100 ? 100 : plyr->health; if (health != oldhealth) { lastcalc = ST_FACESTRIDE * (((100 - health) * ST_NUMPAINFACES) / 101); oldhealth = health; } return lastcalc; } // this is a not-very-pretty routine which handles the face states // and their timing. the precedence of expressions is: // dead > evil grin > turned head > straight ahead void ST_updateFaceWidget(void) { int i; angle_t badguyangle, diffang; static int lastattackdown = -1; static int priority = 0; boolean doevilgrin; if (priority < 10) { // dead if (!plyr->health) { priority = 9; st_faceindex = ST_DEADFACE; st_facecount = 1; } } if (priority < 9) { // picking up bonus if (plyr->bonuscount) { doevilgrin = false; for (i=0;iweaponowned[i]) { doevilgrin = true; oldweaponsowned[i] = plyr->weaponowned[i]; } if (doevilgrin) // evil grin if just picked up weapon { priority = 8; st_facecount = ST_EVILGRINCOUNT; st_faceindex = ST_calcPainOffset() + ST_EVILGRINOFFSET; } } } if (priority < 8) { // being attacked if (plyr->damagecount && plyr->attacker && plyr->attacker != plyr->mo) { priority = 7; if (plyr->health - st_oldhealth > ST_MUCHPAIN) { st_facecount = ST_TURNCOUNT; st_faceindex = ST_calcPainOffset() + ST_OUCHOFFSET; } else { badguyangle = R_PointToAngle2(plyr->mo->x, plyr->mo->y, plyr->attacker->x, plyr->attacker->y); if (badguyangle > plyr->mo->angle) { diffang = badguyangle - plyr->mo->angle; i = diffang > ANG180; // whether right or left } else { diffang = plyr->mo->angle - badguyangle; i = diffang <= ANG180; // whether left or right } // confusing, aint it? st_facecount = ST_TURNCOUNT; st_faceindex = ST_calcPainOffset(); if (diffang < ANG45) st_faceindex += ST_RAMPAGEOFFSET; // head-on else if (i) st_faceindex += ST_TURNOFFSET; // turn face right else st_faceindex += ST_TURNOFFSET+1; // turn face left } } } if (priority < 7) { // getting hurt because of your own damn stupidity if (plyr->damagecount) { if (plyr->health - st_oldhealth > ST_MUCHPAIN) { priority = 7; st_facecount = ST_TURNCOUNT; st_faceindex = ST_calcPainOffset() + ST_OUCHOFFSET; } else { priority = 6; st_facecount = ST_TURNCOUNT; st_faceindex = ST_calcPainOffset() + ST_RAMPAGEOFFSET; } } } if (priority < 6) { // rapid firing if (plyr->attackdown) { if (lastattackdown==-1) lastattackdown = ST_RAMPAGEDELAY; else if (!--lastattackdown) { priority = 5; st_faceindex = ST_calcPainOffset() + ST_RAMPAGEOFFSET; st_facecount = 1; lastattackdown = 1; } } else lastattackdown = -1; } if (priority < 5) { // invulnerability if ((plyr->cheats & CF_GODMODE) || plyr->powers[pw_invulnerability]) { priority = 4; st_faceindex = ST_GODFACE; st_facecount = 1; } } // look left or look right if the facecount has timed out if (!st_facecount) { st_faceindex = ST_calcPainOffset() + (st_randomnumber % 3); st_facecount = ST_STRAIGHTFACECOUNT; priority = 0; } st_facecount--; } void ST_updateWidgets(void) { static int largeammo = 1994; // means "n/a" int i; // must redirect the pointer if the ready weapon has changed // if (w_ready.data != plyr->readyweapon) // { if (weaponinfo[plyr->readyweapon].ammo == am_noammo) w_ready.num = &largeammo; else w_ready.num = &plyr->ammo[weaponinfo[plyr->readyweapon].ammo]; /* { static int tic=0; static int dir=-1; if (!(tic&15)) plyr->ammo[weaponinfo[plyr->readyweapon].ammo]+=dir; if (plyr->ammo[weaponinfo[plyr->readyweapon].ammo] == -100) dir = 1; tic++; } */ w_ready.data = plyr->readyweapon; // if (*w_ready.on) STlib_updateNum(&w_ready, true); // refresh weapon change // } // update keycard multiple widgets for (i=0;i<3;i++) { keyboxes[i] = plyr->cards[i] ? i : -1; if (plyr->cards[i+3]) keyboxes[i] = i+3; } // refresh everything if this is him coming back to life ST_updateFaceWidget(); st_notdeathmatch = !deathmatch; // used by the w_armsbg widget st_armson = st_statusbaron && !deathmatch; // used by w_arms[] widgets st_fragson = deathmatch && st_statusbaron; // used by w_frags widget st_fragscount = 0; for (i=0 ; ifrags[i]; else st_fragscount -= plyr->frags[i]; } // get rid of chat window if up because of message if (!--st_msgcounter) st_chat = st_oldchat; } void ST_Ticker (void) { st_clock++; st_randomnumber = M_Random(); ST_updateWidgets(); st_oldhealth = plyr->health; } static int st_palette = 0; void ST_doPaletteStuff(void) { int palette; byte *pal; int cnt, bzc; cnt = plyr->damagecount; if (plyr->powers[pw_strength]) { // slowly fade the berzerk out bzc = 12 - (plyr->powers[pw_strength]>>6); if (bzc > cnt) cnt = bzc; } if (cnt) { palette = (cnt+7)>>3; if (palette >= NUMREDPALS) palette = NUMREDPALS-1; palette += STARTREDPALS; } else if (plyr->bonuscount) { palette = (plyr->bonuscount+7)>>3; if (palette >= NUMBONUSPALS) palette = NUMBONUSPALS-1; palette += STARTBONUSPALS; } else if ( plyr->powers[pw_ironfeet] > 4*32 || plyr->powers[pw_ironfeet]&8) palette = RADIATIONPAL; else palette = 0; if (palette != st_palette) { st_palette = palette; pal = (byte *) W_CacheLumpNum (lu_palette, PU_CACHE)+palette*768; I_SetPalette (pal); } } void ST_drawWidgets(boolean refresh) { int i; st_armson = st_statusbaron && !deathmatch; // used by w_arms[] widgets st_fragson = deathmatch && st_statusbaron; // used by w_frags widget STlib_updateNum(&w_ready, refresh); for (i=0;i<4;i++) { STlib_updateNum(&w_ammo[i], refresh); STlib_updateNum(&w_maxammo[i], refresh); } STlib_updatePercent(&w_health, refresh); STlib_updatePercent(&w_armor, refresh); STlib_updateBinIcon(&w_armsbg, refresh); for (i=0;i<6;i++) STlib_updateMultIcon(&w_arms[i], refresh); STlib_updateMultIcon(&w_faces, refresh); for (i=0;i<3;i++) STlib_updateMultIcon(&w_keyboxes[i], refresh); STlib_updateNum(&w_frags, refresh); } void ST_doRefresh(void) { st_firsttime = false; // draw status bar background to off-screen buff ST_refreshBackground(); // and refresh all widgets ST_drawWidgets(true); } void ST_diffDraw(void) { // update all widgets ST_drawWidgets(false); } void ST_Drawer (boolean fullscreen, boolean refresh) { st_statusbaron = (!fullscreen) || automapactive; st_firsttime = st_firsttime || refresh; // Do red-/gold-shifts from damage/items ST_doPaletteStuff(); // If just after ST_Start(), refresh all if (st_firsttime) ST_doRefresh(); // Otherwise, update as little as possible else ST_diffDraw(); } void ST_loadGraphics(void) { int i, j, facenum; char namebuf[9]; // Load the numbers, tall and short for (i=0;i<10;i++) { sprintf(namebuf, "STTNUM%d", i); tallnum[i] = (patch_t *) W_CacheLumpName(namebuf, PU_STATIC); sprintf(namebuf, "STYSNUM%d", i); shortnum[i] = (patch_t *) W_CacheLumpName(namebuf, PU_STATIC); } tallpercent = (patch_t *) W_CacheLumpName("STTPRCNT", PU_STATIC); // key cards for (i=0;iweaponowned[i]; for (i=0;i<3;i++) keyboxes[i] = -1; STlib_init(); } void ST_createWidgets(void) { int i; // ready weapon ammo STlib_initNum(&w_ready, ST_AMMOX, ST_AMMOY, tallnum, &plyr->ammo[weaponinfo[plyr->readyweapon].ammo], &st_statusbaron, ST_AMMOWIDTH); w_ready.data = plyr->readyweapon; // the last weapon type // health percentage STlib_initPercent(&w_health, ST_HEALTHX, ST_HEALTHY, tallnum, &plyr->health, &st_statusbaron, tallpercent); // arms background STlib_initBinIcon(&w_armsbg, ST_ARMSBGX, ST_ARMSBGY, armsbg, &st_notdeathmatch, &st_statusbaron); // weapons owned for(i=0;i<6;i++) { STlib_initMultIcon(&w_arms[i], ST_ARMSX+(i%3)*ST_ARMSXSPACE, ST_ARMSY+(i/3)*ST_ARMSYSPACE, arms[i], (int *) &plyr->weaponowned[i+1], &st_armson); } // frags sum STlib_initNum(&w_frags, ST_FRAGSX, ST_FRAGSY, tallnum, &st_fragscount, &st_fragson, ST_FRAGSWIDTH); // faces STlib_initMultIcon(&w_faces, ST_FACESX, ST_FACESY, faces, &st_faceindex, &st_statusbaron); // armor percentage - should be colored later STlib_initPercent(&w_armor, ST_ARMORX, ST_ARMORY, tallnum, &plyr->armorpoints, &st_statusbaron, tallpercent); // keyboxes 0-2 STlib_initMultIcon(&w_keyboxes[0], ST_KEY0X, ST_KEY0Y, keys, &keyboxes[0], &st_statusbaron); STlib_initMultIcon(&w_keyboxes[1], ST_KEY1X, ST_KEY1Y, keys, &keyboxes[1], &st_statusbaron); STlib_initMultIcon(&w_keyboxes[2], ST_KEY2X, ST_KEY2Y, keys, &keyboxes[2], &st_statusbaron); // ammo count (all four kinds) STlib_initNum(&w_ammo[0], ST_AMMO0X, ST_AMMO0Y, shortnum, &plyr->ammo[0], &st_statusbaron, ST_AMMO0WIDTH); STlib_initNum(&w_ammo[1], ST_AMMO1X, ST_AMMO1Y, shortnum, &plyr->ammo[1], &st_statusbaron, ST_AMMO1WIDTH); STlib_initNum(&w_ammo[2], ST_AMMO2X, ST_AMMO2Y, shortnum, &plyr->ammo[2], &st_statusbaron, ST_AMMO2WIDTH); STlib_initNum(&w_ammo[3], ST_AMMO3X, ST_AMMO3Y, shortnum, &plyr->ammo[3], &st_statusbaron, ST_AMMO3WIDTH); // max ammo count (all four kinds) STlib_initNum(&w_maxammo[0], ST_MAXAMMO0X, ST_MAXAMMO0Y, shortnum, &plyr->maxammo[0], &st_statusbaron, ST_MAXAMMO0WIDTH); STlib_initNum(&w_maxammo[1], ST_MAXAMMO1X, ST_MAXAMMO1Y, shortnum, &plyr->maxammo[1], &st_statusbaron, ST_MAXAMMO1WIDTH); STlib_initNum(&w_maxammo[2], ST_MAXAMMO2X, ST_MAXAMMO2Y, shortnum, &plyr->maxammo[2], &st_statusbaron, ST_MAXAMMO2WIDTH); STlib_initNum(&w_maxammo[3], ST_MAXAMMO3X, ST_MAXAMMO3Y, shortnum, &plyr->maxammo[3], &st_statusbaron, ST_MAXAMMO3WIDTH); } static boolean st_stopped = true; void ST_Start (void) { if (!st_stopped) ST_Stop(); ST_initData(); ST_createWidgets(); st_stopped = false; } void ST_Stop (void) { if (st_stopped) return; I_SetPalette (W_CacheLumpNum (lu_palette, PU_CACHE)); st_stopped = true; } void ST_Init (void) { veryfirsttime = 0; ST_loadData(); screens[4] = (byte *) Z_Malloc(ST_WIDTH*ST_HEIGHT, PU_STATIC, 0); } \ No newline at end of file diff --git a/ST_STUFF.H b/ST_STUFF.H new file mode 100644 index 0000000..f876756 --- /dev/null +++ b/ST_STUFF.H @@ -0,0 +1 @@ +#ifndef __STSTUFF_H__ #define __STSTUFF_H__ // For damage/bonus red-/gold-shifts #define STARTREDPALS 1 #define STARTBONUSPALS 9 #define NUMREDPALS 8 #define NUMBONUSPALS 4 #define RADIATIONPAL 13 // N/256*100% probability that the normal face state will change #define ST_FACEPROBABILITY 96 // for Responder #define ST_TOGGLECHAT KEY_ENTER // Location/size of status bar #define ST_WIDTH SCREENWIDTH #define ST_HEIGHT 32 #define ST_X 0 #define ST_X2 104 #define ST_Y (SCREENHEIGHT - ST_HEIGHT) #define ST_FX 143 #define ST_FY 169 // Should be set to patch width for tall numbers later on #define ST_TALLNUMWIDTH (tallnum[0]->width) // number of status faces #define ST_NUMPAINFACES 5 #define ST_NUMSTRAIGHTFACES 3 #define ST_NUMTURNFACES 2 #define ST_NUMSPECIALFACES 3 #define ST_FACESTRIDE (ST_NUMSTRAIGHTFACES+ST_NUMTURNFACES+ST_NUMSPECIALFACES) #define ST_NUMEXTRAFACES 2 #define ST_NUMFACES (ST_FACESTRIDE*ST_NUMPAINFACES+ST_NUMEXTRAFACES) #define ST_TURNOFFSET (ST_NUMSTRAIGHTFACES) #define ST_OUCHOFFSET (ST_TURNOFFSET + ST_NUMTURNFACES) #define ST_EVILGRINOFFSET (ST_OUCHOFFSET + 1) #define ST_RAMPAGEOFFSET (ST_EVILGRINOFFSET + 1) #define ST_GODFACE (ST_NUMPAINFACES*ST_FACESTRIDE) #define ST_DEADFACE (ST_GODFACE+1) #define ST_FACESX 143 #define ST_FACESY 168 #define ST_EVILGRINCOUNT (2*TICRATE) #define ST_STRAIGHTFACECOUNT (TICRATE/2) #define ST_TURNCOUNT (1*TICRATE) #define ST_OUCHCOUNT (1*TICRATE) #define ST_RAMPAGEDELAY (2*TICRATE) #define ST_MUCHPAIN 20 // location and size of statistics, justified according to widget type #define ST_AMMOWIDTH 3 // AMMO number pos. #define ST_AMMOX 44 #define ST_AMMOY 171 #define ST_HEALTHWIDTH 3 // HEALTH number pos. #define ST_HEALTHX 90 #define ST_HEALTHY 171 #define ST_ARMSX 111 #define ST_ARMSY 172 #define ST_ARMSBGX 104 #define ST_ARMSBGY 168 #define ST_ARMSXSPACE 12 #define ST_ARMSYSPACE 10 #define ST_FRAGSX 138 #define ST_FRAGSY 171 #define ST_FRAGSWIDTH 2 #define ST_ARMORWIDTH 3 // ARMOR number pos. #define ST_ARMORX 221 #define ST_ARMORY 171 #define ST_KEY0WIDTH 8 #define ST_KEY0HEIGHT 5 #define ST_KEY0X 239 #define ST_KEY0Y 171 #define ST_KEY1WIDTH ST_KEY0WIDTH #define ST_KEY1X 239 #define ST_KEY1Y 181 #define ST_KEY2WIDTH ST_KEY0WIDTH #define ST_KEY2X 239 #define ST_KEY2Y 191 #define ST_AMMO0WIDTH 3 #define ST_AMMO0HEIGHT 6 #define ST_AMMO0X 288 #define ST_AMMO0Y 173 #define ST_AMMO1WIDTH ST_AMMO0WIDTH #define ST_AMMO1X 288 #define ST_AMMO1Y 179 #define ST_AMMO2WIDTH ST_AMMO0WIDTH #define ST_AMMO2X 288 #define ST_AMMO2Y 191 #define ST_AMMO3WIDTH ST_AMMO0WIDTH #define ST_AMMO3X 288 #define ST_AMMO3Y 185 #define ST_MAXAMMO0WIDTH 3 #define ST_MAXAMMO0HEIGHT 5 #define ST_MAXAMMO0X 314 #define ST_MAXAMMO0Y 173 #define ST_MAXAMMO1WIDTH ST_MAXAMMO0WIDTH #define ST_MAXAMMO1X 314 #define ST_MAXAMMO1Y 179 #define ST_MAXAMMO2WIDTH ST_MAXAMMO0WIDTH #define ST_MAXAMMO2X 314 #define ST_MAXAMMO2Y 191 #define ST_MAXAMMO3WIDTH ST_MAXAMMO0WIDTH #define ST_MAXAMMO3X 314 #define ST_MAXAMMO3Y 185 #define ST_WEAPON0X 110 // pistol #define ST_WEAPON0Y 172 #define ST_WEAPON1X 122 // shotgun #define ST_WEAPON1Y 172 #define ST_WEAPON2X 134 // chain gun #define ST_WEAPON2Y 172 #define ST_WEAPON3X 110 // missile launcher #define ST_WEAPON3Y 181 #define ST_WEAPON4X 122 // plasma gun #define ST_WEAPON4Y 181 #define ST_WEAPON5X 134 // bfg #define ST_WEAPON5Y 181 #define ST_WPNSX 109 // WPNS title #define ST_WPNSY 191 #define ST_DETHX 109 // DETH title #define ST_DETHY 191 // incoming messages window location //#define ST_MSGTEXTX (viewwindowx) //#define ST_MSGTEXTY (viewwindowy+viewheight-18) #define ST_MSGTEXTX 0 #define ST_MSGTEXTY 0 #define ST_MSGWIDTH 52 // in characters #define ST_MSGHEIGHT 1 // in lines #define ST_OUTTEXTX 0 #define ST_OUTTEXTY 6 #define ST_OUTWIDTH 52 // in characters #define ST_OUTHEIGHT 1 // in lines #define ST_MAPWIDTH (strlen(mapnames[(gameepisode-1)*9+(gamemap-1)])) #define ST_MAPTITLEX (SCREENWIDTH - ST_MAPWIDTH * ST_CHATFONTWIDTH) #define ST_MAPTITLEY 0 #define ST_MAPHEIGHT 1 // states for status bar code typedef enum { AutomapState, FirstPersonState } st_stateenum_t; // states for the chat code typedef enum { StartChatState, WaitDestState, GetChatState } st_chatstateenum_t; extern weaponinfo_t weaponinfo[]; // found in P_pspr.c boolean ST_Responder(event_t *ev); #endif \ No newline at end of file diff --git a/SUN.C b/SUN.C new file mode 100644 index 0000000..d14017a --- /dev/null +++ b/SUN.C @@ -0,0 +1 @@ +#include "sndserver.h" #include #include #include #include #include #include #include #include #include #include "irix.h" int audio_fd; void myioctl(int fd, int command, void *arg) { int rc; extern int errno; rc = ioctl(fd, command, arg); if (rc < 0) { fprintf(stderr, "ioctl(dsp,%d,arg) failed\n", command); fprintf(stderr, "errno=%d\n", errno); } } void I_InitMusic(void) { } void I_InitSound(int samplerate, int samplesize) { int i; char *audio_filename = "/dev/audio"; audio_info_t audio_info; if (getenv("AUDIODEV")) audio_filename = getenv("AUDIODEV"); audio_fd = open(audio_filename, O_RDWR); if (audio_fd<0) fprintf(stderr, "Could not open %s\n", audio_filename); myioctl(audio_fd, AUDIO_GETINFO, &audio_info); AUDIO_INITINFO(&audio_info); audio_info.play.sample_rate = 11025; myioctl(audio_fd, AUDIO_SETINFO, &audio_info); AUDIO_INITINFO(&audio_info); audio_info.play.channels = 2; myioctl(audio_fd, AUDIO_SETINFO, &audio_info); AUDIO_INITINFO(&audio_info); audio_info.play.precision = 16; myioctl(audio_fd, AUDIO_SETINFO, &audio_info); AUDIO_INITINFO(&audio_info); audio_info.play.encoding = AUDIO_ENCODING_LINEAR; myioctl(audio_fd, AUDIO_SETINFO, &audio_info); AUDIO_INITINFO(&audio_info); audio_info.play.buffer_size = 1024; myioctl(audio_fd, AUDIO_SETINFO, &audio_info); } void I_SubmitOutputBuffer(void *samples, int samplecount) { /* myioctl(audio_fd, AUDIO_DRAIN, 0); */ write(audio_fd, samples, samplecount*4); } void I_ShutdownSound(void) { close(audio_fd); } void I_ShutdownMusic(void) { } \ No newline at end of file diff --git a/S_SOUND.C b/S_SOUND.C new file mode 100644 index 0000000..2072f21 --- /dev/null +++ b/S_SOUND.C @@ -0,0 +1 @@ +#include #include "doomdef.h" #include "p_local.h" static int snd_SfxVolume; // maximum volume of a sound effect static int snd_MusicVolume; // maximum volume of music static channel_t *channels; // the set of channels available static boolean mus_paused; // whether songs are mus_paused static musicinfo_t *mus_playing=0; // music currently being played // following is set by the defaults code in M_misc int numChannels; // number of channels available static int nextcleanup; void S_SetMusicVolume(int volume) { if (volume < 0 || volume > 127) I_Error("Attempt to set music volume at %d", volume); I_SetMusicVolume(127); I_SetMusicVolume(volume); snd_MusicVolume = volume; } void S_StopMusic(void) { if (mus_playing) { if (mus_paused) I_ResumeSong(mus_playing->handle); I_StopSong(mus_playing->handle); I_UnRegisterSong(mus_playing->handle); Z_ChangeTag(mus_playing->data, PU_CACHE); #ifdef __WATCOMC__ _dpmi_unlockregion(mus_playing->data, lumpinfo[mus_playing->lumpnum].size); #endif mus_playing->data = 0; mus_playing = 0; } } /* * Starts some music with the music id found in sounds.h */ void S_ChangeMusic(int musicnum, int looping) { musicinfo_t *music; char namebuf[9]; #ifdef __WATCOMC__ // a hack to use the adlib version of the intro music extern int snd_MusicDevice; if (snd_MusicDevice == 2 && musicnum == mus_intro) musicnum = mus_introa; #endif if (musicnum <= mus_None || musicnum >= NUMMUSIC) I_Error("Bad music number %d", musicnum); else music = &S_music[musicnum]; if (mus_playing == music) return; // shutdown old music S_StopMusic(); // get lumpnum if neccessary if (!music->lumpnum) { sprintf(namebuf, "d_%s", music->name); music->lumpnum = W_GetNumForName(namebuf); } // load & register it music->data = (void *) W_CacheLumpNum(music->lumpnum, PU_MUSIC); #ifdef __WATCOMC__ _dpmi_lockregion(music->data, lumpinfo[music->lumpnum].size); #endif music->handle = I_RegisterSong(music->data); // play it I_PlaySong(music->handle, looping); mus_playing = music; } void S_StartMusic(int m_id) { S_ChangeMusic(m_id, false); } void S_StopChannel(int cnum) { int i; channel_t *c = &channels[cnum]; if (c->sfxinfo) { // stop the sound playing if (I_SoundIsPlaying(c->handle)) { #ifdef SAWDEBUG if (c->sfxinfo == &S_sfx[sfx_sawful]) fprintf(stderr, "stopped\n"); #endif I_StopSound(c->handle); } // check to see if other channels are playing the sound for (i=0 ; isfxinfo == channels[i].sfxinfo) break; // degrade the sound data's usefulness c->sfxinfo->usefulness--; c->sfxinfo = 0; } } /* * Changes volume, stereo-separation, and pitch variables from the norm * of a sound effect to be played. If the sound is not audible, returns * a 0. Otherwise, modifies parameters and returns 1. */ int S_AdjustSoundParams(mobj_t *listener, mobj_t *source, int *vol, int *sep, int *pitch) { fixed_t approx_dist, adx, ady; angle_t angle; // calculate the sound's distance and clip it if necessary // adx = abs(listener->x - source->x); ady = abs(listener->y - source->y); approx_dist = adx + ady - ((adx < ady ? adx : ady)>>1); // _GG1_ p.428 if (gamemap != 8 && approx_dist > S_CLIPPING_DIST) return 0; // angle of source to listener angle = R_PointToAngle2(listener->x, listener->y, source->x, source->y); if (angle > listener->angle) angle = angle - listener->angle; else angle = angle + (0xffffffff - listener->angle); angle >>= ANGLETOFINESHIFT; // stereo separation *sep = 128 - (FixedMul(S_STEREO_SWING,finesine[angle])>>FRACBITS); // volume calculation if (approx_dist < S_CLOSE_DIST) *vol = snd_SfxVolume; else if (gamemap == 8) { if (approx_dist > S_CLIPPING_DIST) approx_dist = S_CLIPPING_DIST; *vol = 15 + ((snd_SfxVolume-15) * ((S_CLIPPING_DIST - approx_dist)>>FRACBITS)) / S_ATTENUATOR; } else *vol = (snd_SfxVolume * ((S_CLIPPING_DIST - approx_dist)>>FRACBITS)) / S_ATTENUATOR; // distance effect return (*vol > 0); } void S_SetSfxVolume(int volume) { if (volume < 0 || volume > 127) I_Error("Attempt to set sfx volume at %d", volume); snd_SfxVolume = volume; } void S_PauseSound(void) { if (mus_playing && !mus_paused) { I_PauseSong(mus_playing->handle); mus_paused = true; } } void S_ResumeSound(void) { if (mus_playing && mus_paused) { I_ResumeSong(mus_playing->handle); mus_paused = false; } } void S_StopSound(void *origin) { int cnum; for (cnum=0 ; cnumpriority >= sfxinfo->priority) break; // FUCK! No lower priority. Sorry, Charlie. if (cnum == numChannels) return -1; // Otherwise, kick out lower priority else S_StopChannel(cnum); } c = &channels[cnum]; // channel is decided to be cnum. c->sfxinfo = sfxinfo; c->origin = origin; return cnum; } void S_StartSoundAtVolume(void *origin_p, int sfx_id, int volume) { int rc, sep, pitch, priority; sfxinfo_t *sfx; int cnum; mobj_t *origin = (mobj_t *) origin_p; /* { static char buf[40]; sprintf(buf, "playing sound %d (%s)", sfx_id, S_sfx[sfx_id].name); players[consoleplayer].message = buf; } */ // check for bogus sound # if (sfx_id < 1 || sfx_id > NUMSFX) I_Error("Bad sfx #: %d", sfx_id); sfx = &S_sfx[sfx_id]; // Initialize sound parameters if (sfx->link) { pitch = sfx->pitch; priority = sfx->priority; volume += sfx->volume; if (volume < 1) return; if (volume > snd_SfxVolume) volume = snd_SfxVolume; } else { pitch = NORM_PITCH; priority = NORM_PRIORITY; } // Check to see if it's audible, and if not, modify the params if (origin && origin != players[consoleplayer].mo) { rc = S_AdjustSoundParams(players[consoleplayer].mo, origin, &volume, &sep, &pitch); if ( origin->x == players[consoleplayer].mo->x && origin->y == players[consoleplayer].mo->y) sep = NORM_SEP; if (!rc) return; } else { sep = NORM_SEP; } // hacks to vary the sfx pitches if (sfx_id >= sfx_sawup && sfx_id <= sfx_sawhit) { pitch += 8 - (M_Random()&15); if (pitch<0) pitch = 0; else if (pitch>255) pitch = 255; } else if (sfx_id != sfx_itemup && sfx_id != sfx_tink) { pitch += 16 - (M_Random()&31); if (pitch<0) pitch = 0; else if (pitch>255) pitch = 255; } // kill old sound S_StopSound(origin); // try to find a channel cnum = S_getChannel(origin, sfx); if (cnum<0) return; // get lumpnum if necessary if (sfx->lumpnum < 0) sfx->lumpnum = I_GetSfxLumpNum(sfx); // cache data if necessary if (!sfx->data) { sfx->data = (void *) W_CacheLumpNum(sfx->lumpnum, PU_MUSIC); #ifdef __WATCOMC__ _dpmi_lockregion(sfx->data, lumpinfo[sfx->lumpnum].size); #endif } // increase the usefulness if (sfx->usefulness++ < 0) sfx->usefulness = 1; channels[cnum].handle = I_StartSound(sfx_id, sfx->data, volume, sep, pitch, priority); } void S_StartSound(void *origin, int sfx_id) { #ifdef SAWDEBUG // if (sfx_id == sfx_sawful) sfx_id = sfx_itemup; #endif S_StartSoundAtVolume(origin, sfx_id, snd_SfxVolume); #ifdef SAWDEBUG { int i,n; static mobj_t *last_saw_origins[10] = {1,1,1,1,1,1,1,1,1,1}; static int first_saw=0; static int next_saw=0; if (sfx_id == sfx_sawidl || sfx_id == sfx_sawful || sfx_id == sfx_sawhit) { for (i=first_saw;i!=next_saw;i=(i+1)%10) if (last_saw_origins[i] != origin) fprintf(stderr, "old origin 0x%lx != origin 0x%lx for sfx %d\n", last_saw_origins[i], origin, sfx_id); last_saw_origins[next_saw] = origin; next_saw = (next_saw + 1) % 10; if (next_saw == first_saw) first_saw = (first_saw + 1) % 10; for (n=i=0; i1) { for (i=0; i nextcleanup) { for (i=1 ; i -1) if (--S_sfx[i].usefulness == -1) { Z_ChangeTag(S_sfx[i].data, PU_CACHE); #ifdef __WATCOMC__ _dpmi_unlockregion(S_sfx[i].data, lumpinfo[S_sfx[i].lumpnum].size); #endif S_sfx[i].data = 0; } } nextcleanup = gametic + 15; } for (cnum=0 ; cnumsfxinfo; if (c->sfxinfo) { if (I_SoundIsPlaying(c->handle)) { // initialize parameters volume = snd_SfxVolume; pitch = NORM_PITCH; sep = NORM_SEP; if (sfx->link) { pitch = sfx->pitch; volume += sfx->volume; if (volume < 1) { S_StopChannel(cnum); continue; } else if (volume > snd_SfxVolume) volume = snd_SfxVolume; } // check non-local sounds for distance clipping or modify their params if (c->origin && listener_p != c->origin) { audible = S_AdjustSoundParams(listener, c->origin, &volume, &sep, &pitch); if (!audible) { S_StopChannel(cnum); } else I_UpdateSoundParams(c->handle, volume, sep, pitch); } // if channel is allocated but sound has stopped, free it } else S_StopChannel(cnum); } } /* // kill music if it's a single-play && finished if ( mus_playing && !I_QrySongPlaying(mus_playing->handle) && !mus_paused ) S_StopMusic(); */ } void S_Init(int sfxVolume, int musicVolume) { int i; I_SetChannels(numChannels); S_SetSfxVolume(sfxVolume); S_SetMusicVolume(musicVolume); channels = (channel_t *) Z_Malloc(numChannels*sizeof(channel_t), PU_STATIC, 0); // free all channels for use for (i=0 ; i mus_e3m9) // HACK FOR COMMERCIAL // mnum -= mus_e3m9; S_ChangeMusic(mnum, true); nextcleanup = 15; } \ No newline at end of file diff --git a/T.C b/T.C new file mode 100644 index 0000000..b67361c --- /dev/null +++ b/T.C @@ -0,0 +1 @@ +#include main() { FILE *f; f=popen("sndserver -quiet", "w"); } \ No newline at end of file diff --git a/TABLES.C b/TABLES.C new file mode 100644 index 0000000..963079c --- /dev/null +++ b/TABLES.C @@ -0,0 +1 @@ +#include "doomdef.h" int finetangent[4096] = { -170910304,-56965752,-34178904,-24413316,-18988036,-15535599,-13145455,-11392683, -10052327,-8994149,-8137527,-7429880,-6835455,-6329090,-5892567,-5512368, -5178251,-4882318,-4618375,-4381502,-4167737,-3973855,-3797206,-3635590, -3487165,-3350381,-3223918,-3106651,-2997613,-2895966,-2800983,-2712030, -2628549,-2550052,-2476104,-2406322,-2340362,-2277919,-2218719,-2162516, -2109087,-2058233,-2009771,-1963536,-1919378,-1877161,-1836758,-1798063, -1760956,-1725348,-1691149,-1658278,-1626658,-1596220,-1566898,-1538632, -1511367,-1485049,-1459630,-1435065,-1411312,-1388330,-1366084,-1344537, -1323658,-1303416,-1283783,-1264730,-1246234,-1228269,-1210813,-1193846, -1177345,-1161294,-1145673,-1130465,-1115654,-1101225,-1087164,-1073455, -1060087,-1047046,-1034322,-1021901,-1009774,-997931,-986361,-975054, -964003,-953199,-942633,-932298,-922186,-912289,-902602,-893117, -883829,-874730,-865817,-857081,-848520,-840127,-831898,-823827, -815910,-808143,-800521,-793041,-785699,-778490,-771411,-764460, -757631,-750922,-744331,-737853,-731486,-725227,-719074,-713023, -707072,-701219,-695462,-689797,-684223,-678737,-673338,-668024, -662792,-657640,-652568,-647572,-642651,-637803,-633028,-628323, -623686,-619117,-614613,-610174,-605798,-601483,-597229,-593033, -588896,-584815,-580789,-576818,-572901,-569035,-565221,-561456, -557741,-554074,-550455,-546881,-543354,-539870,-536431,-533034, -529680,-526366,-523094,-519861,-516667,-513512,-510394,-507313, -504269,-501261,-498287,-495348,-492443,-489571,-486732,-483925, -481150,-478406,-475692,-473009,-470355,-467730,-465133,-462565, -460024,-457511,-455024,-452564,-450129,-447720,-445337,-442978, -440643,-438332,-436045,-433781,-431540,-429321,-427125,-424951, -422798,-420666,-418555,-416465,-414395,-412344,-410314,-408303, -406311,-404338,-402384,-400448,-398530,-396630,-394747,-392882, -391034,-389202,-387387,-385589,-383807,-382040,-380290,-378555, -376835,-375130,-373440,-371765,-370105,-368459,-366826,-365208, -363604,-362013,-360436,-358872,-357321,-355783,-354257,-352744, -351244,-349756,-348280,-346816,-345364,-343924,-342495,-341078, -339671,-338276,-336892,-335519,-334157,-332805,-331464,-330133, -328812,-327502,-326201,-324910,-323629,-322358,-321097,-319844, -318601,-317368,-316143,-314928,-313721,-312524,-311335,-310154, -308983,-307819,-306664,-305517,-304379,-303248,-302126,-301011, -299904,-298805,-297714,-296630,-295554,-294485,-293423,-292369, -291322,-290282,-289249,-288223,-287204,-286192,-285186,-284188, -283195,-282210,-281231,-280258,-279292,-278332,-277378,-276430, -275489,-274553,-273624,-272700,-271782,-270871,-269965,-269064, -268169,-267280,-266397,-265519,-264646,-263779,-262917,-262060, -261209,-260363,-259522,-258686,-257855,-257029,-256208,-255392, -254581,-253774,-252973,-252176,-251384,-250596,-249813,-249035, -248261,-247492,-246727,-245966,-245210,-244458,-243711,-242967, -242228,-241493,-240763,-240036,-239314,-238595,-237881,-237170, -236463,-235761,-235062,-234367,-233676,-232988,-232304,-231624, -230948,-230275,-229606,-228941,-228279,-227621,-226966,-226314, -225666,-225022,-224381,-223743,-223108,-222477,-221849,-221225, -220603,-219985,-219370,-218758,-218149,-217544,-216941,-216341, -215745,-215151,-214561,-213973,-213389,-212807,-212228,-211652, -211079,-210509,-209941,-209376,-208815,-208255,-207699,-207145, -206594,-206045,-205500,-204956,-204416,-203878,-203342,-202809, -202279,-201751,-201226,-200703,-200182,-199664,-199149,-198636, -198125,-197616,-197110,-196606,-196105,-195606,-195109,-194614, -194122,-193631,-193143,-192658,-192174,-191693,-191213,-190736, -190261,-189789,-189318,-188849,-188382,-187918,-187455,-186995, -186536,-186080,-185625,-185173,-184722,-184274,-183827,-183382, -182939,-182498,-182059,-181622,-181186,-180753,-180321,-179891, -179463,-179037,-178612,-178190,-177769,-177349,-176932,-176516, -176102,-175690,-175279,-174870,-174463,-174057,-173653,-173251, -172850,-172451,-172053,-171657,-171263,-170870,-170479,-170089, -169701,-169315,-168930,-168546,-168164,-167784,-167405,-167027, -166651,-166277,-165904,-165532,-165162,-164793,-164426,-164060, -163695,-163332,-162970,-162610,-162251,-161893,-161537,-161182, -160828,-160476,-160125,-159775,-159427,-159079,-158734,-158389, -158046,-157704,-157363,-157024,-156686,-156349,-156013,-155678, -155345,-155013,-154682,-154352,-154024,-153697,-153370,-153045, -152722,-152399,-152077,-151757,-151438,-151120,-150803,-150487, -150172,-149859,-149546,-149235,-148924,-148615,-148307,-148000, -147693,-147388,-147084,-146782,-146480,-146179,-145879,-145580, -145282,-144986,-144690,-144395,-144101,-143808,-143517,-143226, -142936,-142647,-142359,-142072,-141786,-141501,-141217,-140934, -140651,-140370,-140090,-139810,-139532,-139254,-138977,-138701, -138426,-138152,-137879,-137607,-137335,-137065,-136795,-136526, -136258,-135991,-135725,-135459,-135195,-134931,-134668,-134406, -134145,-133884,-133625,-133366,-133108,-132851,-132594,-132339, -132084,-131830,-131576,-131324,-131072,-130821,-130571,-130322, -130073,-129825,-129578,-129332,-129086,-128841,-128597,-128353, -128111,-127869,-127627,-127387,-127147,-126908,-126669,-126432, -126195,-125959,-125723,-125488,-125254,-125020,-124787,-124555, -124324,-124093,-123863,-123633,-123404,-123176,-122949,-122722, -122496,-122270,-122045,-121821,-121597,-121374,-121152,-120930, -120709,-120489,-120269,-120050,-119831,-119613,-119396,-119179, -118963,-118747,-118532,-118318,-118104,-117891,-117678,-117466, -117254,-117044,-116833,-116623,-116414,-116206,-115998,-115790, -115583,-115377,-115171,-114966,-114761,-114557,-114354,-114151, -113948,-113746,-113545,-113344,-113143,-112944,-112744,-112546, -112347,-112150,-111952,-111756,-111560,-111364,-111169,-110974, -110780,-110586,-110393,-110200,-110008,-109817,-109626,-109435, -109245,-109055,-108866,-108677,-108489,-108301,-108114,-107927, -107741,-107555,-107369,-107184,-107000,-106816,-106632,-106449, -106266,-106084,-105902,-105721,-105540,-105360,-105180,-105000, -104821,-104643,-104465,-104287,-104109,-103933,-103756,-103580, -103404,-103229,-103054,-102880,-102706,-102533,-102360,-102187, -102015,-101843,-101671,-101500,-101330,-101159,-100990,-100820, -100651,-100482,-100314,-100146,-99979,-99812,-99645,-99479, -99313,-99148,-98982,-98818,-98653,-98489,-98326,-98163, -98000,-97837,-97675,-97513,-97352,-97191,-97030,-96870, -96710,-96551,-96391,-96233,-96074,-95916,-95758,-95601, -95444,-95287,-95131,-94975,-94819,-94664,-94509,-94354, -94200,-94046,-93892,-93739,-93586,-93434,-93281,-93129, -92978,-92826,-92675,-92525,-92375,-92225,-92075,-91926, -91777,-91628,-91480,-91332,-91184,-91036,-90889,-90742, -90596,-90450,-90304,-90158,-90013,-89868,-89724,-89579, -89435,-89292,-89148,-89005,-88862,-88720,-88577,-88435, -88294,-88152,-88011,-87871,-87730,-87590,-87450,-87310, -87171,-87032,-86893,-86755,-86616,-86479,-86341,-86204, -86066,-85930,-85793,-85657,-85521,-85385,-85250,-85114, -84980,-84845,-84710,-84576,-84443,-84309,-84176,-84043, -83910,-83777,-83645,-83513,-83381,-83250,-83118,-82987, -82857,-82726,-82596,-82466,-82336,-82207,-82078,-81949, -81820,-81691,-81563,-81435,-81307,-81180,-81053,-80925, -80799,-80672,-80546,-80420,-80294,-80168,-80043,-79918, -79793,-79668,-79544,-79420,-79296,-79172,-79048,-78925, -78802,-78679,-78557,-78434,-78312,-78190,-78068,-77947, -77826,-77705,-77584,-77463,-77343,-77223,-77103,-76983, -76864,-76744,-76625,-76506,-76388,-76269,-76151,-76033, -75915,-75797,-75680,-75563,-75446,-75329,-75213,-75096, -74980,-74864,-74748,-74633,-74517,-74402,-74287,-74172, -74058,-73944,-73829,-73715,-73602,-73488,-73375,-73262, -73149,-73036,-72923,-72811,-72699,-72587,-72475,-72363, -72252,-72140,-72029,-71918,-71808,-71697,-71587,-71477, -71367,-71257,-71147,-71038,-70929,-70820,-70711,-70602, -70494,-70385,-70277,-70169,-70061,-69954,-69846,-69739, -69632,-69525,-69418,-69312,-69205,-69099,-68993,-68887, -68781,-68676,-68570,-68465,-68360,-68255,-68151,-68046, -67942,-67837,-67733,-67629,-67526,-67422,-67319,-67216, -67113,-67010,-66907,-66804,-66702,-66600,-66498,-66396, -66294,-66192,-66091,-65989,-65888,-65787,-65686,-65586, -65485,-65385,-65285,-65185,-65085,-64985,-64885,-64786, -64687,-64587,-64488,-64389,-64291,-64192,-64094,-63996, -63897,-63799,-63702,-63604,-63506,-63409,-63312,-63215, -63118,-63021,-62924,-62828,-62731,-62635,-62539,-62443, -62347,-62251,-62156,-62060,-61965,-61870,-61775,-61680, -61585,-61491,-61396,-61302,-61208,-61114,-61020,-60926, -60833,-60739,-60646,-60552,-60459,-60366,-60273,-60181, -60088,-59996,-59903,-59811,-59719,-59627,-59535,-59444, -59352,-59261,-59169,-59078,-58987,-58896,-58805,-58715, -58624,-58534,-58443,-58353,-58263,-58173,-58083,-57994, -57904,-57815,-57725,-57636,-57547,-57458,-57369,-57281, -57192,-57104,-57015,-56927,-56839,-56751,-56663,-56575, -56487,-56400,-56312,-56225,-56138,-56051,-55964,-55877, -55790,-55704,-55617,-55531,-55444,-55358,-55272,-55186, -55100,-55015,-54929,-54843,-54758,-54673,-54587,-54502, -54417,-54333,-54248,-54163,-54079,-53994,-53910,-53826, -53741,-53657,-53574,-53490,-53406,-53322,-53239,-53156, -53072,-52989,-52906,-52823,-52740,-52657,-52575,-52492, -52410,-52327,-52245,-52163,-52081,-51999,-51917,-51835, -51754,-51672,-51591,-51509,-51428,-51347,-51266,-51185, -51104,-51023,-50942,-50862,-50781,-50701,-50621,-50540, -50460,-50380,-50300,-50221,-50141,-50061,-49982,-49902, -49823,-49744,-49664,-49585,-49506,-49427,-49349,-49270, -49191,-49113,-49034,-48956,-48878,-48799,-48721,-48643, -48565,-48488,-48410,-48332,-48255,-48177,-48100,-48022, -47945,-47868,-47791,-47714,-47637,-47560,-47484,-47407, -47331,-47254,-47178,-47102,-47025,-46949,-46873,-46797, -46721,-46646,-46570,-46494,-46419,-46343,-46268,-46193, -46118,-46042,-45967,-45892,-45818,-45743,-45668,-45593, -45519,-45444,-45370,-45296,-45221,-45147,-45073,-44999, -44925,-44851,-44778,-44704,-44630,-44557,-44483,-44410, -44337,-44263,-44190,-44117,-44044,-43971,-43898,-43826, -43753,-43680,-43608,-43535,-43463,-43390,-43318,-43246, -43174,-43102,-43030,-42958,-42886,-42814,-42743,-42671, -42600,-42528,-42457,-42385,-42314,-42243,-42172,-42101, -42030,-41959,-41888,-41817,-41747,-41676,-41605,-41535, -41465,-41394,-41324,-41254,-41184,-41113,-41043,-40973, -40904,-40834,-40764,-40694,-40625,-40555,-40486,-40416, -40347,-40278,-40208,-40139,-40070,-40001,-39932,-39863, -39794,-39726,-39657,-39588,-39520,-39451,-39383,-39314, -39246,-39178,-39110,-39042,-38973,-38905,-38837,-38770, -38702,-38634,-38566,-38499,-38431,-38364,-38296,-38229, -38161,-38094,-38027,-37960,-37893,-37826,-37759,-37692, -37625,-37558,-37491,-37425,-37358,-37291,-37225,-37158, -37092,-37026,-36959,-36893,-36827,-36761,-36695,-36629, -36563,-36497,-36431,-36365,-36300,-36234,-36168,-36103, -36037,-35972,-35907,-35841,-35776,-35711,-35646,-35580, -35515,-35450,-35385,-35321,-35256,-35191,-35126,-35062, -34997,-34932,-34868,-34803,-34739,-34675,-34610,-34546, -34482,-34418,-34354,-34289,-34225,-34162,-34098,-34034, -33970,-33906,-33843,-33779,-33715,-33652,-33588,-33525, -33461,-33398,-33335,-33272,-33208,-33145,-33082,-33019, -32956,-32893,-32830,-32767,-32705,-32642,-32579,-32516, -32454,-32391,-32329,-32266,-32204,-32141,-32079,-32017, -31955,-31892,-31830,-31768,-31706,-31644,-31582,-31520, -31458,-31396,-31335,-31273,-31211,-31150,-31088,-31026, -30965,-30904,-30842,-30781,-30719,-30658,-30597,-30536, -30474,-30413,-30352,-30291,-30230,-30169,-30108,-30048, -29987,-29926,-29865,-29805,-29744,-29683,-29623,-29562, -29502,-29441,-29381,-29321,-29260,-29200,-29140,-29080, -29020,-28959,-28899,-28839,-28779,-28719,-28660,-28600, -28540,-28480,-28420,-28361,-28301,-28241,-28182,-28122, -28063,-28003,-27944,-27884,-27825,-27766,-27707,-27647, -27588,-27529,-27470,-27411,-27352,-27293,-27234,-27175, -27116,-27057,-26998,-26940,-26881,-26822,-26763,-26705, -26646,-26588,-26529,-26471,-26412,-26354,-26295,-26237, -26179,-26120,-26062,-26004,-25946,-25888,-25830,-25772, -25714,-25656,-25598,-25540,-25482,-25424,-25366,-25308, -25251,-25193,-25135,-25078,-25020,-24962,-24905,-24847, -24790,-24732,-24675,-24618,-24560,-24503,-24446,-24389, -24331,-24274,-24217,-24160,-24103,-24046,-23989,-23932, -23875,-23818,-23761,-23704,-23647,-23591,-23534,-23477, -23420,-23364,-23307,-23250,-23194,-23137,-23081,-23024, -22968,-22911,-22855,-22799,-22742,-22686,-22630,-22573, -22517,-22461,-22405,-22349,-22293,-22237,-22181,-22125, -22069,-22013,-21957,-21901,-21845,-21789,-21733,-21678, -21622,-21566,-21510,-21455,-21399,-21343,-21288,-21232, -21177,-21121,-21066,-21010,-20955,-20900,-20844,-20789, -20734,-20678,-20623,-20568,-20513,-20457,-20402,-20347, -20292,-20237,-20182,-20127,-20072,-20017,-19962,-19907, -19852,-19797,-19742,-19688,-19633,-19578,-19523,-19469, -19414,-19359,-19305,-19250,-19195,-19141,-19086,-19032, -18977,-18923,-18868,-18814,-18760,-18705,-18651,-18597, -18542,-18488,-18434,-18380,-18325,-18271,-18217,-18163, -18109,-18055,-18001,-17946,-17892,-17838,-17784,-17731, -17677,-17623,-17569,-17515,-17461,-17407,-17353,-17300, -17246,-17192,-17138,-17085,-17031,-16977,-16924,-16870, -16817,-16763,-16710,-16656,-16603,-16549,-16496,-16442, -16389,-16335,-16282,-16229,-16175,-16122,-16069,-16015, -15962,-15909,-15856,-15802,-15749,-15696,-15643,-15590, -15537,-15484,-15431,-15378,-15325,-15272,-15219,-15166, -15113,-15060,-15007,-14954,-14901,-14848,-14795,-14743, -14690,-14637,-14584,-14531,-14479,-14426,-14373,-14321, -14268,-14215,-14163,-14110,-14057,-14005,-13952,-13900, -13847,-13795,-13742,-13690,-13637,-13585,-13533,-13480, -13428,-13375,-13323,-13271,-13218,-13166,-13114,-13062, -13009,-12957,-12905,-12853,-12800,-12748,-12696,-12644, -12592,-12540,-12488,-12436,-12383,-12331,-12279,-12227, -12175,-12123,-12071,-12019,-11967,-11916,-11864,-11812, -11760,-11708,-11656,-11604,-11552,-11501,-11449,-11397, -11345,-11293,-11242,-11190,-11138,-11086,-11035,-10983, -10931,-10880,-10828,-10777,-10725,-10673,-10622,-10570, -10519,-10467,-10415,-10364,-10312,-10261,-10209,-10158, -10106,-10055,-10004,-9952,-9901,-9849,-9798,-9747, -9695,-9644,-9592,-9541,-9490,-9438,-9387,-9336, -9285,-9233,-9182,-9131,-9080,-9028,-8977,-8926, -8875,-8824,-8772,-8721,-8670,-8619,-8568,-8517, -8466,-8414,-8363,-8312,-8261,-8210,-8159,-8108, -8057,-8006,-7955,-7904,-7853,-7802,-7751,-7700, -7649,-7598,-7547,-7496,-7445,-7395,-7344,-7293, -7242,-7191,-7140,-7089,-7038,-6988,-6937,-6886, -6835,-6784,-6733,-6683,-6632,-6581,-6530,-6480, -6429,-6378,-6327,-6277,-6226,-6175,-6124,-6074, -6023,-5972,-5922,-5871,-5820,-5770,-5719,-5668, -5618,-5567,-5517,-5466,-5415,-5365,-5314,-5264, -5213,-5162,-5112,-5061,-5011,-4960,-4910,-4859, -4808,-4758,-4707,-4657,-4606,-4556,-4505,-4455, -4404,-4354,-4303,-4253,-4202,-4152,-4101,-4051, -4001,-3950,-3900,-3849,-3799,-3748,-3698,-3648, -3597,-3547,-3496,-3446,-3395,-3345,-3295,-3244, -3194,-3144,-3093,-3043,-2992,-2942,-2892,-2841, -2791,-2741,-2690,-2640,-2590,-2539,-2489,-2439, -2388,-2338,-2288,-2237,-2187,-2137,-2086,-2036, -1986,-1935,-1885,-1835,-1784,-1734,-1684,-1633, -1583,-1533,-1483,-1432,-1382,-1332,-1281,-1231, -1181,-1131,-1080,-1030,-980,-929,-879,-829, -779,-728,-678,-628,-578,-527,-477,-427, -376,-326,-276,-226,-175,-125,-75,-25, 25,75,125,175,226,276,326,376, 427,477,527,578,628,678,728,779, 829,879,929,980,1030,1080,1131,1181, 1231,1281,1332,1382,1432,1483,1533,1583, 1633,1684,1734,1784,1835,1885,1935,1986, 2036,2086,2137,2187,2237,2288,2338,2388, 2439,2489,2539,2590,2640,2690,2741,2791, 2841,2892,2942,2992,3043,3093,3144,3194, 3244,3295,3345,3395,3446,3496,3547,3597, 3648,3698,3748,3799,3849,3900,3950,4001, 4051,4101,4152,4202,4253,4303,4354,4404, 4455,4505,4556,4606,4657,4707,4758,4808, 4859,4910,4960,5011,5061,5112,5162,5213, 5264,5314,5365,5415,5466,5517,5567,5618, 5668,5719,5770,5820,5871,5922,5972,6023, 6074,6124,6175,6226,6277,6327,6378,6429, 6480,6530,6581,6632,6683,6733,6784,6835, 6886,6937,6988,7038,7089,7140,7191,7242, 7293,7344,7395,7445,7496,7547,7598,7649, 7700,7751,7802,7853,7904,7955,8006,8057, 8108,8159,8210,8261,8312,8363,8414,8466, 8517,8568,8619,8670,8721,8772,8824,8875, 8926,8977,9028,9080,9131,9182,9233,9285, 9336,9387,9438,9490,9541,9592,9644,9695, 9747,9798,9849,9901,9952,10004,10055,10106, 10158,10209,10261,10312,10364,10415,10467,10519, 10570,10622,10673,10725,10777,10828,10880,10931, 10983,11035,11086,11138,11190,11242,11293,11345, 11397,11449,11501,11552,11604,11656,11708,11760, 11812,11864,11916,11967,12019,12071,12123,12175, 12227,12279,12331,12383,12436,12488,12540,12592, 12644,12696,12748,12800,12853,12905,12957,13009, 13062,13114,13166,13218,13271,13323,13375,13428, 13480,13533,13585,13637,13690,13742,13795,13847, 13900,13952,14005,14057,14110,14163,14215,14268, 14321,14373,14426,14479,14531,14584,14637,14690, 14743,14795,14848,14901,14954,15007,15060,15113, 15166,15219,15272,15325,15378,15431,15484,15537, 15590,15643,15696,15749,15802,15856,15909,15962, 16015,16069,16122,16175,16229,16282,16335,16389, 16442,16496,16549,16603,16656,16710,16763,16817, 16870,16924,16977,17031,17085,17138,17192,17246, 17300,17353,17407,17461,17515,17569,17623,17677, 17731,17784,17838,17892,17946,18001,18055,18109, 18163,18217,18271,18325,18380,18434,18488,18542, 18597,18651,18705,18760,18814,18868,18923,18977, 19032,19086,19141,19195,19250,19305,19359,19414, 19469,19523,19578,19633,19688,19742,19797,19852, 19907,19962,20017,20072,20127,20182,20237,20292, 20347,20402,20457,20513,20568,20623,20678,20734, 20789,20844,20900,20955,21010,21066,21121,21177, 21232,21288,21343,21399,21455,21510,21566,21622, 21678,21733,21789,21845,21901,21957,22013,22069, 22125,22181,22237,22293,22349,22405,22461,22517, 22573,22630,22686,22742,22799,22855,22911,22968, 23024,23081,23137,23194,23250,23307,23364,23420, 23477,23534,23591,23647,23704,23761,23818,23875, 23932,23989,24046,24103,24160,24217,24274,24331, 24389,24446,24503,24560,24618,24675,24732,24790, 24847,24905,24962,25020,25078,25135,25193,25251, 25308,25366,25424,25482,25540,25598,25656,25714, 25772,25830,25888,25946,26004,26062,26120,26179, 26237,26295,26354,26412,26471,26529,26588,26646, 26705,26763,26822,26881,26940,26998,27057,27116, 27175,27234,27293,27352,27411,27470,27529,27588, 27647,27707,27766,27825,27884,27944,28003,28063, 28122,28182,28241,28301,28361,28420,28480,28540, 28600,28660,28719,28779,28839,28899,28959,29020, 29080,29140,29200,29260,29321,29381,29441,29502, 29562,29623,29683,29744,29805,29865,29926,29987, 30048,30108,30169,30230,30291,30352,30413,30474, 30536,30597,30658,30719,30781,30842,30904,30965, 31026,31088,31150,31211,31273,31335,31396,31458, 31520,31582,31644,31706,31768,31830,31892,31955, 32017,32079,32141,32204,32266,32329,32391,32454, 32516,32579,32642,32705,32767,32830,32893,32956, 33019,33082,33145,33208,33272,33335,33398,33461, 33525,33588,33652,33715,33779,33843,33906,33970, 34034,34098,34162,34225,34289,34354,34418,34482, 34546,34610,34675,34739,34803,34868,34932,34997, 35062,35126,35191,35256,35321,35385,35450,35515, 35580,35646,35711,35776,35841,35907,35972,36037, 36103,36168,36234,36300,36365,36431,36497,36563, 36629,36695,36761,36827,36893,36959,37026,37092, 37158,37225,37291,37358,37425,37491,37558,37625, 37692,37759,37826,37893,37960,38027,38094,38161, 38229,38296,38364,38431,38499,38566,38634,38702, 38770,38837,38905,38973,39042,39110,39178,39246, 39314,39383,39451,39520,39588,39657,39726,39794, 39863,39932,40001,40070,40139,40208,40278,40347, 40416,40486,40555,40625,40694,40764,40834,40904, 40973,41043,41113,41184,41254,41324,41394,41465, 41535,41605,41676,41747,41817,41888,41959,42030, 42101,42172,42243,42314,42385,42457,42528,42600, 42671,42743,42814,42886,42958,43030,43102,43174, 43246,43318,43390,43463,43535,43608,43680,43753, 43826,43898,43971,44044,44117,44190,44263,44337, 44410,44483,44557,44630,44704,44778,44851,44925, 44999,45073,45147,45221,45296,45370,45444,45519, 45593,45668,45743,45818,45892,45967,46042,46118, 46193,46268,46343,46419,46494,46570,46646,46721, 46797,46873,46949,47025,47102,47178,47254,47331, 47407,47484,47560,47637,47714,47791,47868,47945, 48022,48100,48177,48255,48332,48410,48488,48565, 48643,48721,48799,48878,48956,49034,49113,49191, 49270,49349,49427,49506,49585,49664,49744,49823, 49902,49982,50061,50141,50221,50300,50380,50460, 50540,50621,50701,50781,50862,50942,51023,51104, 51185,51266,51347,51428,51509,51591,51672,51754, 51835,51917,51999,52081,52163,52245,52327,52410, 52492,52575,52657,52740,52823,52906,52989,53072, 53156,53239,53322,53406,53490,53574,53657,53741, 53826,53910,53994,54079,54163,54248,54333,54417, 54502,54587,54673,54758,54843,54929,55015,55100, 55186,55272,55358,55444,55531,55617,55704,55790, 55877,55964,56051,56138,56225,56312,56400,56487, 56575,56663,56751,56839,56927,57015,57104,57192, 57281,57369,57458,57547,57636,57725,57815,57904, 57994,58083,58173,58263,58353,58443,58534,58624, 58715,58805,58896,58987,59078,59169,59261,59352, 59444,59535,59627,59719,59811,59903,59996,60088, 60181,60273,60366,60459,60552,60646,60739,60833, 60926,61020,61114,61208,61302,61396,61491,61585, 61680,61775,61870,61965,62060,62156,62251,62347, 62443,62539,62635,62731,62828,62924,63021,63118, 63215,63312,63409,63506,63604,63702,63799,63897, 63996,64094,64192,64291,64389,64488,64587,64687, 64786,64885,64985,65085,65185,65285,65385,65485, 65586,65686,65787,65888,65989,66091,66192,66294, 66396,66498,66600,66702,66804,66907,67010,67113, 67216,67319,67422,67526,67629,67733,67837,67942, 68046,68151,68255,68360,68465,68570,68676,68781, 68887,68993,69099,69205,69312,69418,69525,69632, 69739,69846,69954,70061,70169,70277,70385,70494, 70602,70711,70820,70929,71038,71147,71257,71367, 71477,71587,71697,71808,71918,72029,72140,72252, 72363,72475,72587,72699,72811,72923,73036,73149, 73262,73375,73488,73602,73715,73829,73944,74058, 74172,74287,74402,74517,74633,74748,74864,74980, 75096,75213,75329,75446,75563,75680,75797,75915, 76033,76151,76269,76388,76506,76625,76744,76864, 76983,77103,77223,77343,77463,77584,77705,77826, 77947,78068,78190,78312,78434,78557,78679,78802, 78925,79048,79172,79296,79420,79544,79668,79793, 79918,80043,80168,80294,80420,80546,80672,80799, 80925,81053,81180,81307,81435,81563,81691,81820, 81949,82078,82207,82336,82466,82596,82726,82857, 82987,83118,83250,83381,83513,83645,83777,83910, 84043,84176,84309,84443,84576,84710,84845,84980, 85114,85250,85385,85521,85657,85793,85930,86066, 86204,86341,86479,86616,86755,86893,87032,87171, 87310,87450,87590,87730,87871,88011,88152,88294, 88435,88577,88720,88862,89005,89148,89292,89435, 89579,89724,89868,90013,90158,90304,90450,90596, 90742,90889,91036,91184,91332,91480,91628,91777, 91926,92075,92225,92375,92525,92675,92826,92978, 93129,93281,93434,93586,93739,93892,94046,94200, 94354,94509,94664,94819,94975,95131,95287,95444, 95601,95758,95916,96074,96233,96391,96551,96710, 96870,97030,97191,97352,97513,97675,97837,98000, 98163,98326,98489,98653,98818,98982,99148,99313, 99479,99645,99812,99979,100146,100314,100482,100651, 100820,100990,101159,101330,101500,101671,101843,102015, 102187,102360,102533,102706,102880,103054,103229,103404, 103580,103756,103933,104109,104287,104465,104643,104821, 105000,105180,105360,105540,105721,105902,106084,106266, 106449,106632,106816,107000,107184,107369,107555,107741, 107927,108114,108301,108489,108677,108866,109055,109245, 109435,109626,109817,110008,110200,110393,110586,110780, 110974,111169,111364,111560,111756,111952,112150,112347, 112546,112744,112944,113143,113344,113545,113746,113948, 114151,114354,114557,114761,114966,115171,115377,115583, 115790,115998,116206,116414,116623,116833,117044,117254, 117466,117678,117891,118104,118318,118532,118747,118963, 119179,119396,119613,119831,120050,120269,120489,120709, 120930,121152,121374,121597,121821,122045,122270,122496, 122722,122949,123176,123404,123633,123863,124093,124324, 124555,124787,125020,125254,125488,125723,125959,126195, 126432,126669,126908,127147,127387,127627,127869,128111, 128353,128597,128841,129086,129332,129578,129825,130073, 130322,130571,130821,131072,131324,131576,131830,132084, 132339,132594,132851,133108,133366,133625,133884,134145, 134406,134668,134931,135195,135459,135725,135991,136258, 136526,136795,137065,137335,137607,137879,138152,138426, 138701,138977,139254,139532,139810,140090,140370,140651, 140934,141217,141501,141786,142072,142359,142647,142936, 143226,143517,143808,144101,144395,144690,144986,145282, 145580,145879,146179,146480,146782,147084,147388,147693, 148000,148307,148615,148924,149235,149546,149859,150172, 150487,150803,151120,151438,151757,152077,152399,152722, 153045,153370,153697,154024,154352,154682,155013,155345, 155678,156013,156349,156686,157024,157363,157704,158046, 158389,158734,159079,159427,159775,160125,160476,160828, 161182,161537,161893,162251,162610,162970,163332,163695, 164060,164426,164793,165162,165532,165904,166277,166651, 167027,167405,167784,168164,168546,168930,169315,169701, 170089,170479,170870,171263,171657,172053,172451,172850, 173251,173653,174057,174463,174870,175279,175690,176102, 176516,176932,177349,177769,178190,178612,179037,179463, 179891,180321,180753,181186,181622,182059,182498,182939, 183382,183827,184274,184722,185173,185625,186080,186536, 186995,187455,187918,188382,188849,189318,189789,190261, 190736,191213,191693,192174,192658,193143,193631,194122, 194614,195109,195606,196105,196606,197110,197616,198125, 198636,199149,199664,200182,200703,201226,201751,202279, 202809,203342,203878,204416,204956,205500,206045,206594, 207145,207699,208255,208815,209376,209941,210509,211079, 211652,212228,212807,213389,213973,214561,215151,215745, 216341,216941,217544,218149,218758,219370,219985,220603, 221225,221849,222477,223108,223743,224381,225022,225666, 226314,226966,227621,228279,228941,229606,230275,230948, 231624,232304,232988,233676,234367,235062,235761,236463, 237170,237881,238595,239314,240036,240763,241493,242228, 242967,243711,244458,245210,245966,246727,247492,248261, 249035,249813,250596,251384,252176,252973,253774,254581, 255392,256208,257029,257855,258686,259522,260363,261209, 262060,262917,263779,264646,265519,266397,267280,268169, 269064,269965,270871,271782,272700,273624,274553,275489, 276430,277378,278332,279292,280258,281231,282210,283195, 284188,285186,286192,287204,288223,289249,290282,291322, 292369,293423,294485,295554,296630,297714,298805,299904, 301011,302126,303248,304379,305517,306664,307819,308983, 310154,311335,312524,313721,314928,316143,317368,318601, 319844,321097,322358,323629,324910,326201,327502,328812, 330133,331464,332805,334157,335519,336892,338276,339671, 341078,342495,343924,345364,346816,348280,349756,351244, 352744,354257,355783,357321,358872,360436,362013,363604, 365208,366826,368459,370105,371765,373440,375130,376835, 378555,380290,382040,383807,385589,387387,389202,391034, 392882,394747,396630,398530,400448,402384,404338,406311, 408303,410314,412344,414395,416465,418555,420666,422798, 424951,427125,429321,431540,433781,436045,438332,440643, 442978,445337,447720,450129,452564,455024,457511,460024, 462565,465133,467730,470355,473009,475692,478406,481150, 483925,486732,489571,492443,495348,498287,501261,504269, 507313,510394,513512,516667,519861,523094,526366,529680, 533034,536431,539870,543354,546881,550455,554074,557741, 561456,565221,569035,572901,576818,580789,584815,588896, 593033,597229,601483,605798,610174,614613,619117,623686, 628323,633028,637803,642651,647572,652568,657640,662792, 668024,673338,678737,684223,689797,695462,701219,707072, 713023,719074,725227,731486,737853,744331,750922,757631, 764460,771411,778490,785699,793041,800521,808143,815910, 823827,831898,840127,848520,857081,865817,874730,883829, 893117,902602,912289,922186,932298,942633,953199,964003, 975054,986361,997931,1009774,1021901,1034322,1047046,1060087, 1073455,1087164,1101225,1115654,1130465,1145673,1161294,1177345, 1193846,1210813,1228269,1246234,1264730,1283783,1303416,1323658, 1344537,1366084,1388330,1411312,1435065,1459630,1485049,1511367, 1538632,1566898,1596220,1626658,1658278,1691149,1725348,1760956, 1798063,1836758,1877161,1919378,1963536,2009771,2058233,2109087, 2162516,2218719,2277919,2340362,2406322,2476104,2550052,2628549, 2712030,2800983,2895966,2997613,3106651,3223918,3350381,3487165, 3635590,3797206,3973855,4167737,4381502,4618375,4882318,5178251, 5512368,5892567,6329090,6835455,7429880,8137527,8994149,10052327, 11392683,13145455,15535599,18988036,24413316,34178904,56965752,170910304 }; int finesine[10240] = { 25,75,125,175,226,276,326,376, 427,477,527,578,628,678,728,779, 829,879,929,980,1030,1080,1130,1181, 1231,1281,1331,1382,1432,1482,1532,1583, 1633,1683,1733,1784,1834,1884,1934,1985, 2035,2085,2135,2186,2236,2286,2336,2387, 2437,2487,2537,2587,2638,2688,2738,2788, 2839,2889,2939,2989,3039,3090,3140,3190, 3240,3291,3341,3391,3441,3491,3541,3592, 3642,3692,3742,3792,3843,3893,3943,3993, 4043,4093,4144,4194,4244,4294,4344,4394, 4445,4495,4545,4595,4645,4695,4745,4796, 4846,4896,4946,4996,5046,5096,5146,5197, 5247,5297,5347,5397,5447,5497,5547,5597, 5647,5697,5748,5798,5848,5898,5948,5998, 6048,6098,6148,6198,6248,6298,6348,6398, 6448,6498,6548,6598,6648,6698,6748,6798, 6848,6898,6948,6998,7048,7098,7148,7198, 7248,7298,7348,7398,7448,7498,7548,7598, 7648,7697,7747,7797,7847,7897,7947,7997, 8047,8097,8147,8196,8246,8296,8346,8396, 8446,8496,8545,8595,8645,8695,8745,8794, 8844,8894,8944,8994,9043,9093,9143,9193, 9243,9292,9342,9392,9442,9491,9541,9591, 9640,9690,9740,9790,9839,9889,9939,9988, 10038,10088,10137,10187,10237,10286,10336,10386, 10435,10485,10534,10584,10634,10683,10733,10782, 10832,10882,10931,10981,11030,11080,11129,11179, 11228,11278,11327,11377,11426,11476,11525,11575, 11624,11674,11723,11773,11822,11872,11921,11970, 12020,12069,12119,12168,12218,12267,12316,12366, 12415,12464,12514,12563,12612,12662,12711,12760, 12810,12859,12908,12957,13007,13056,13105,13154, 13204,13253,13302,13351,13401,13450,13499,13548, 13597,13647,13696,13745,13794,13843,13892,13941, 13990,14040,14089,14138,14187,14236,14285,14334, 14383,14432,14481,14530,14579,14628,14677,14726, 14775,14824,14873,14922,14971,15020,15069,15118, 15167,15215,15264,15313,15362,15411,15460,15509, 15557,15606,15655,15704,15753,15802,15850,15899, 15948,15997,16045,16094,16143,16191,16240,16289, 16338,16386,16435,16484,16532,16581,16629,16678, 16727,16775,16824,16872,16921,16970,17018,17067, 17115,17164,17212,17261,17309,17358,17406,17455, 17503,17551,17600,17648,17697,17745,17793,17842, 17890,17939,17987,18035,18084,18132,18180,18228, 18277,18325,18373,18421,18470,18518,18566,18614, 18663,18711,18759,18807,18855,18903,18951,19000, 19048,19096,19144,19192,19240,19288,19336,19384, 19432,19480,19528,19576,19624,19672,19720,19768, 19816,19864,19912,19959,20007,20055,20103,20151, 20199,20246,20294,20342,20390,20438,20485,20533, 20581,20629,20676,20724,20772,20819,20867,20915, 20962,21010,21057,21105,21153,21200,21248,21295, 21343,21390,21438,21485,21533,21580,21628,21675, 21723,21770,21817,21865,21912,21960,22007,22054, 22102,22149,22196,22243,22291,22338,22385,22433, 22480,22527,22574,22621,22668,22716,22763,22810, 22857,22904,22951,22998,23045,23092,23139,23186, 23233,23280,23327,23374,23421,23468,23515,23562, 23609,23656,23703,23750,23796,23843,23890,23937, 23984,24030,24077,24124,24171,24217,24264,24311, 24357,24404,24451,24497,24544,24591,24637,24684, 24730,24777,24823,24870,24916,24963,25009,25056, 25102,25149,25195,25241,25288,25334,25381,25427, 25473,25520,25566,25612,25658,25705,25751,25797, 25843,25889,25936,25982,26028,26074,26120,26166, 26212,26258,26304,26350,26396,26442,26488,26534, 26580,26626,26672,26718,26764,26810,26856,26902, 26947,26993,27039,27085,27131,27176,27222,27268, 27313,27359,27405,27450,27496,27542,27587,27633, 27678,27724,27770,27815,27861,27906,27952,27997, 28042,28088,28133,28179,28224,28269,28315,28360, 28405,28451,28496,28541,28586,28632,28677,28722, 28767,28812,28858,28903,28948,28993,29038,29083, 29128,29173,29218,29263,29308,29353,29398,29443, 29488,29533,29577,29622,29667,29712,29757,29801, 29846,29891,29936,29980,30025,30070,30114,30159, 30204,30248,30293,30337,30382,30426,30471,30515, 30560,30604,30649,30693,30738,30782,30826,30871, 30915,30959,31004,31048,31092,31136,31181,31225, 31269,31313,31357,31402,31446,31490,31534,31578, 31622,31666,31710,31754,31798,31842,31886,31930, 31974,32017,32061,32105,32149,32193,32236,32280, 32324,32368,32411,32455,32499,32542,32586,32630, 32673,32717,32760,32804,32847,32891,32934,32978, 33021,33065,33108,33151,33195,33238,33281,33325, 33368,33411,33454,33498,33541,33584,33627,33670, 33713,33756,33799,33843,33886,33929,33972,34015, 34057,34100,34143,34186,34229,34272,34315,34358, 34400,34443,34486,34529,34571,34614,34657,34699, 34742,34785,34827,34870,34912,34955,34997,35040, 35082,35125,35167,35210,35252,35294,35337,35379, 35421,35464,35506,35548,35590,35633,35675,35717, 35759,35801,35843,35885,35927,35969,36011,36053, 36095,36137,36179,36221,36263,36305,36347,36388, 36430,36472,36514,36555,36597,36639,36681,36722, 36764,36805,36847,36889,36930,36972,37013,37055, 37096,37137,37179,37220,37262,37303,37344,37386, 37427,37468,37509,37551,37592,37633,37674,37715, 37756,37797,37838,37879,37920,37961,38002,38043, 38084,38125,38166,38207,38248,38288,38329,38370, 38411,38451,38492,38533,38573,38614,38655,38695, 38736,38776,38817,38857,38898,38938,38979,39019, 39059,39100,39140,39180,39221,39261,39301,39341, 39382,39422,39462,39502,39542,39582,39622,39662, 39702,39742,39782,39822,39862,39902,39942,39982, 40021,40061,40101,40141,40180,40220,40260,40300, 40339,40379,40418,40458,40497,40537,40576,40616, 40655,40695,40734,40773,40813,40852,40891,40931, 40970,41009,41048,41087,41127,41166,41205,41244, 41283,41322,41361,41400,41439,41478,41517,41556, 41595,41633,41672,41711,41750,41788,41827,41866, 41904,41943,41982,42020,42059,42097,42136,42174, 42213,42251,42290,42328,42366,42405,42443,42481, 42520,42558,42596,42634,42672,42711,42749,42787, 42825,42863,42901,42939,42977,43015,43053,43091, 43128,43166,43204,43242,43280,43317,43355,43393, 43430,43468,43506,43543,43581,43618,43656,43693, 43731,43768,43806,43843,43880,43918,43955,43992, 44029,44067,44104,44141,44178,44215,44252,44289, 44326,44363,44400,44437,44474,44511,44548,44585, 44622,44659,44695,44732,44769,44806,44842,44879, 44915,44952,44989,45025,45062,45098,45135,45171, 45207,45244,45280,45316,45353,45389,45425,45462, 45498,45534,45570,45606,45642,45678,45714,45750, 45786,45822,45858,45894,45930,45966,46002,46037, 46073,46109,46145,46180,46216,46252,46287,46323, 46358,46394,46429,46465,46500,46536,46571,46606, 46642,46677,46712,46747,46783,46818,46853,46888, 46923,46958,46993,47028,47063,47098,47133,47168, 47203,47238,47273,47308,47342,47377,47412,47446, 47481,47516,47550,47585,47619,47654,47688,47723, 47757,47792,47826,47860,47895,47929,47963,47998, 48032,48066,48100,48134,48168,48202,48237,48271, 48305,48338,48372,48406,48440,48474,48508,48542, 48575,48609,48643,48676,48710,48744,48777,48811, 48844,48878,48911,48945,48978,49012,49045,49078, 49112,49145,49178,49211,49244,49278,49311,49344, 49377,49410,49443,49476,49509,49542,49575,49608, 49640,49673,49706,49739,49771,49804,49837,49869, 49902,49935,49967,50000,50032,50065,50097,50129, 50162,50194,50226,50259,50291,50323,50355,50387, 50420,50452,50484,50516,50548,50580,50612,50644, 50675,50707,50739,50771,50803,50834,50866,50898, 50929,50961,50993,51024,51056,51087,51119,51150, 51182,51213,51244,51276,51307,51338,51369,51401, 51432,51463,51494,51525,51556,51587,51618,51649, 51680,51711,51742,51773,51803,51834,51865,51896, 51926,51957,51988,52018,52049,52079,52110,52140, 52171,52201,52231,52262,52292,52322,52353,52383, 52413,52443,52473,52503,52534,52564,52594,52624, 52653,52683,52713,52743,52773,52803,52832,52862, 52892,52922,52951,52981,53010,53040,53069,53099, 53128,53158,53187,53216,53246,53275,53304,53334, 53363,53392,53421,53450,53479,53508,53537,53566, 53595,53624,53653,53682,53711,53739,53768,53797, 53826,53854,53883,53911,53940,53969,53997,54026, 54054,54082,54111,54139,54167,54196,54224,54252, 54280,54308,54337,54365,54393,54421,54449,54477, 54505,54533,54560,54588,54616,54644,54672,54699, 54727,54755,54782,54810,54837,54865,54892,54920, 54947,54974,55002,55029,55056,55084,55111,55138, 55165,55192,55219,55246,55274,55300,55327,55354, 55381,55408,55435,55462,55489,55515,55542,55569, 55595,55622,55648,55675,55701,55728,55754,55781, 55807,55833,55860,55886,55912,55938,55965,55991, 56017,56043,56069,56095,56121,56147,56173,56199, 56225,56250,56276,56302,56328,56353,56379,56404, 56430,56456,56481,56507,56532,56557,56583,56608, 56633,56659,56684,56709,56734,56760,56785,56810, 56835,56860,56885,56910,56935,56959,56984,57009, 57034,57059,57083,57108,57133,57157,57182,57206, 57231,57255,57280,57304,57329,57353,57377,57402, 57426,57450,57474,57498,57522,57546,57570,57594, 57618,57642,57666,57690,57714,57738,57762,57785, 57809,57833,57856,57880,57903,57927,57950,57974, 57997,58021,58044,58067,58091,58114,58137,58160, 58183,58207,58230,58253,58276,58299,58322,58345, 58367,58390,58413,58436,58459,58481,58504,58527, 58549,58572,58594,58617,58639,58662,58684,58706, 58729,58751,58773,58795,58818,58840,58862,58884, 58906,58928,58950,58972,58994,59016,59038,59059, 59081,59103,59125,59146,59168,59190,59211,59233, 59254,59276,59297,59318,59340,59361,59382,59404, 59425,59446,59467,59488,59509,59530,59551,59572, 59593,59614,59635,59656,59677,59697,59718,59739, 59759,59780,59801,59821,59842,59862,59883,59903, 59923,59944,59964,59984,60004,60025,60045,60065, 60085,60105,60125,60145,60165,60185,60205,60225, 60244,60264,60284,60304,60323,60343,60363,60382, 60402,60421,60441,60460,60479,60499,60518,60537, 60556,60576,60595,60614,60633,60652,60671,60690, 60709,60728,60747,60766,60785,60803,60822,60841, 60859,60878,60897,60915,60934,60952,60971,60989, 61007,61026,61044,61062,61081,61099,61117,61135, 61153,61171,61189,61207,61225,61243,61261,61279, 61297,61314,61332,61350,61367,61385,61403,61420, 61438,61455,61473,61490,61507,61525,61542,61559, 61577,61594,61611,61628,61645,61662,61679,61696, 61713,61730,61747,61764,61780,61797,61814,61831, 61847,61864,61880,61897,61913,61930,61946,61963, 61979,61995,62012,62028,62044,62060,62076,62092, 62108,62125,62141,62156,62172,62188,62204,62220, 62236,62251,62267,62283,62298,62314,62329,62345, 62360,62376,62391,62407,62422,62437,62453,62468, 62483,62498,62513,62528,62543,62558,62573,62588, 62603,62618,62633,62648,62662,62677,62692,62706, 62721,62735,62750,62764,62779,62793,62808,62822, 62836,62850,62865,62879,62893,62907,62921,62935, 62949,62963,62977,62991,63005,63019,63032,63046, 63060,63074,63087,63101,63114,63128,63141,63155, 63168,63182,63195,63208,63221,63235,63248,63261, 63274,63287,63300,63313,63326,63339,63352,63365, 63378,63390,63403,63416,63429,63441,63454,63466, 63479,63491,63504,63516,63528,63541,63553,63565, 63578,63590,63602,63614,63626,63638,63650,63662, 63674,63686,63698,63709,63721,63733,63745,63756, 63768,63779,63791,63803,63814,63825,63837,63848, 63859,63871,63882,63893,63904,63915,63927,63938, 63949,63960,63971,63981,63992,64003,64014,64025, 64035,64046,64057,64067,64078,64088,64099,64109, 64120,64130,64140,64151,64161,64171,64181,64192, 64202,64212,64222,64232,64242,64252,64261,64271, 64281,64291,64301,64310,64320,64330,64339,64349, 64358,64368,64377,64387,64396,64405,64414,64424, 64433,64442,64451,64460,64469,64478,64487,64496, 64505,64514,64523,64532,64540,64549,64558,64566, 64575,64584,64592,64601,64609,64617,64626,64634, 64642,64651,64659,64667,64675,64683,64691,64699, 64707,64715,64723,64731,64739,64747,64754,64762, 64770,64777,64785,64793,64800,64808,64815,64822, 64830,64837,64844,64852,64859,64866,64873,64880, 64887,64895,64902,64908,64915,64922,64929,64936, 64943,64949,64956,64963,64969,64976,64982,64989, 64995,65002,65008,65015,65021,65027,65033,65040, 65046,65052,65058,65064,65070,65076,65082,65088, 65094,65099,65105,65111,65117,65122,65128,65133, 65139,65144,65150,65155,65161,65166,65171,65177, 65182,65187,65192,65197,65202,65207,65212,65217, 65222,65227,65232,65237,65242,65246,65251,65256, 65260,65265,65270,65274,65279,65283,65287,65292, 65296,65300,65305,65309,65313,65317,65321,65325, 65329,65333,65337,65341,65345,65349,65352,65356, 65360,65363,65367,65371,65374,65378,65381,65385, 65388,65391,65395,65398,65401,65404,65408,65411, 65414,65417,65420,65423,65426,65429,65431,65434, 65437,65440,65442,65445,65448,65450,65453,65455, 65458,65460,65463,65465,65467,65470,65472,65474, 65476,65478,65480,65482,65484,65486,65488,65490, 65492,65494,65496,65497,65499,65501,65502,65504, 65505,65507,65508,65510,65511,65513,65514,65515, 65516,65518,65519,65520,65521,65522,65523,65524, 65525,65526,65527,65527,65528,65529,65530,65530, 65531,65531,65532,65532,65533,65533,65534,65534, 65534,65535,65535,65535,65535,65535,65535,65535, 65535,65535,65535,65535,65535,65535,65535,65534, 65534,65534,65533,65533,65532,65532,65531,65531, 65530,65530,65529,65528,65527,65527,65526,65525, 65524,65523,65522,65521,65520,65519,65518,65516, 65515,65514,65513,65511,65510,65508,65507,65505, 65504,65502,65501,65499,65497,65496,65494,65492, 65490,65488,65486,65484,65482,65480,65478,65476, 65474,65472,65470,65467,65465,65463,65460,65458, 65455,65453,65450,65448,65445,65442,65440,65437, 65434,65431,65429,65426,65423,65420,65417,65414, 65411,65408,65404,65401,65398,65395,65391,65388, 65385,65381,65378,65374,65371,65367,65363,65360, 65356,65352,65349,65345,65341,65337,65333,65329, 65325,65321,65317,65313,65309,65305,65300,65296, 65292,65287,65283,65279,65274,65270,65265,65260, 65256,65251,65246,65242,65237,65232,65227,65222, 65217,65212,65207,65202,65197,65192,65187,65182, 65177,65171,65166,65161,65155,65150,65144,65139, 65133,65128,65122,65117,65111,65105,65099,65094, 65088,65082,65076,65070,65064,65058,65052,65046, 65040,65033,65027,65021,65015,65008,65002,64995, 64989,64982,64976,64969,64963,64956,64949,64943, 64936,64929,64922,64915,64908,64902,64895,64887, 64880,64873,64866,64859,64852,64844,64837,64830, 64822,64815,64808,64800,64793,64785,64777,64770, 64762,64754,64747,64739,64731,64723,64715,64707, 64699,64691,64683,64675,64667,64659,64651,64642, 64634,64626,64617,64609,64600,64592,64584,64575, 64566,64558,64549,64540,64532,64523,64514,64505, 64496,64487,64478,64469,64460,64451,64442,64433, 64424,64414,64405,64396,64387,64377,64368,64358, 64349,64339,64330,64320,64310,64301,64291,64281, 64271,64261,64252,64242,64232,64222,64212,64202, 64192,64181,64171,64161,64151,64140,64130,64120, 64109,64099,64088,64078,64067,64057,64046,64035, 64025,64014,64003,63992,63981,63971,63960,63949, 63938,63927,63915,63904,63893,63882,63871,63859, 63848,63837,63825,63814,63803,63791,63779,63768, 63756,63745,63733,63721,63709,63698,63686,63674, 63662,63650,63638,63626,63614,63602,63590,63578, 63565,63553,63541,63528,63516,63504,63491,63479, 63466,63454,63441,63429,63416,63403,63390,63378, 63365,63352,63339,63326,63313,63300,63287,63274, 63261,63248,63235,63221,63208,63195,63182,63168, 63155,63141,63128,63114,63101,63087,63074,63060, 63046,63032,63019,63005,62991,62977,62963,62949, 62935,62921,62907,62893,62879,62865,62850,62836, 62822,62808,62793,62779,62764,62750,62735,62721, 62706,62692,62677,62662,62648,62633,62618,62603, 62588,62573,62558,62543,62528,62513,62498,62483, 62468,62453,62437,62422,62407,62391,62376,62360, 62345,62329,62314,62298,62283,62267,62251,62236, 62220,62204,62188,62172,62156,62141,62125,62108, 62092,62076,62060,62044,62028,62012,61995,61979, 61963,61946,61930,61913,61897,61880,61864,61847, 61831,61814,61797,61780,61764,61747,61730,61713, 61696,61679,61662,61645,61628,61611,61594,61577, 61559,61542,61525,61507,61490,61473,61455,61438, 61420,61403,61385,61367,61350,61332,61314,61297, 61279,61261,61243,61225,61207,61189,61171,61153, 61135,61117,61099,61081,61062,61044,61026,61007, 60989,60971,60952,60934,60915,60897,60878,60859, 60841,60822,60803,60785,60766,60747,60728,60709, 60690,60671,60652,60633,60614,60595,60576,60556, 60537,60518,60499,60479,60460,60441,60421,60402, 60382,60363,60343,60323,60304,60284,60264,60244, 60225,60205,60185,60165,60145,60125,60105,60085, 60065,60045,60025,60004,59984,59964,59944,59923, 59903,59883,59862,59842,59821,59801,59780,59759, 59739,59718,59697,59677,59656,59635,59614,59593, 59572,59551,59530,59509,59488,59467,59446,59425, 59404,59382,59361,59340,59318,59297,59276,59254, 59233,59211,59190,59168,59146,59125,59103,59081, 59059,59038,59016,58994,58972,58950,58928,58906, 58884,58862,58840,58818,58795,58773,58751,58729, 58706,58684,58662,58639,58617,58594,58572,58549, 58527,58504,58481,58459,58436,58413,58390,58367, 58345,58322,58299,58276,58253,58230,58207,58183, 58160,58137,58114,58091,58067,58044,58021,57997, 57974,57950,57927,57903,57880,57856,57833,57809, 57785,57762,57738,57714,57690,57666,57642,57618, 57594,57570,57546,57522,57498,57474,57450,57426, 57402,57377,57353,57329,57304,57280,57255,57231, 57206,57182,57157,57133,57108,57083,57059,57034, 57009,56984,56959,56935,56910,56885,56860,56835, 56810,56785,56760,56734,56709,56684,56659,56633, 56608,56583,56557,56532,56507,56481,56456,56430, 56404,56379,56353,56328,56302,56276,56250,56225, 56199,56173,56147,56121,56095,56069,56043,56017, 55991,55965,55938,55912,55886,55860,55833,55807, 55781,55754,55728,55701,55675,55648,55622,55595, 55569,55542,55515,55489,55462,55435,55408,55381, 55354,55327,55300,55274,55246,55219,55192,55165, 55138,55111,55084,55056,55029,55002,54974,54947, 54920,54892,54865,54837,54810,54782,54755,54727, 54699,54672,54644,54616,54588,54560,54533,54505, 54477,54449,54421,54393,54365,54337,54308,54280, 54252,54224,54196,54167,54139,54111,54082,54054, 54026,53997,53969,53940,53911,53883,53854,53826, 53797,53768,53739,53711,53682,53653,53624,53595, 53566,53537,53508,53479,53450,53421,53392,53363, 53334,53304,53275,53246,53216,53187,53158,53128, 53099,53069,53040,53010,52981,52951,52922,52892, 52862,52832,52803,52773,52743,52713,52683,52653, 52624,52594,52564,52534,52503,52473,52443,52413, 52383,52353,52322,52292,52262,52231,52201,52171, 52140,52110,52079,52049,52018,51988,51957,51926, 51896,51865,51834,51803,51773,51742,51711,51680, 51649,51618,51587,51556,51525,51494,51463,51432, 51401,51369,51338,51307,51276,51244,51213,51182, 51150,51119,51087,51056,51024,50993,50961,50929, 50898,50866,50834,50803,50771,50739,50707,50675, 50644,50612,50580,50548,50516,50484,50452,50420, 50387,50355,50323,50291,50259,50226,50194,50162, 50129,50097,50065,50032,50000,49967,49935,49902, 49869,49837,49804,49771,49739,49706,49673,49640, 49608,49575,49542,49509,49476,49443,49410,49377, 49344,49311,49278,49244,49211,49178,49145,49112, 49078,49045,49012,48978,48945,48911,48878,48844, 48811,48777,48744,48710,48676,48643,48609,48575, 48542,48508,48474,48440,48406,48372,48338,48304, 48271,48237,48202,48168,48134,48100,48066,48032, 47998,47963,47929,47895,47860,47826,47792,47757, 47723,47688,47654,47619,47585,47550,47516,47481, 47446,47412,47377,47342,47308,47273,47238,47203, 47168,47133,47098,47063,47028,46993,46958,46923, 46888,46853,46818,46783,46747,46712,46677,46642, 46606,46571,46536,46500,46465,46429,46394,46358, 46323,46287,46252,46216,46180,46145,46109,46073, 46037,46002,45966,45930,45894,45858,45822,45786, 45750,45714,45678,45642,45606,45570,45534,45498, 45462,45425,45389,45353,45316,45280,45244,45207, 45171,45135,45098,45062,45025,44989,44952,44915, 44879,44842,44806,44769,44732,44695,44659,44622, 44585,44548,44511,44474,44437,44400,44363,44326, 44289,44252,44215,44178,44141,44104,44067,44029, 43992,43955,43918,43880,43843,43806,43768,43731, 43693,43656,43618,43581,43543,43506,43468,43430, 43393,43355,43317,43280,43242,43204,43166,43128, 43091,43053,43015,42977,42939,42901,42863,42825, 42787,42749,42711,42672,42634,42596,42558,42520, 42481,42443,42405,42366,42328,42290,42251,42213, 42174,42136,42097,42059,42020,41982,41943,41904, 41866,41827,41788,41750,41711,41672,41633,41595, 41556,41517,41478,41439,41400,41361,41322,41283, 41244,41205,41166,41127,41088,41048,41009,40970, 40931,40891,40852,40813,40773,40734,40695,40655, 40616,40576,40537,40497,40458,40418,40379,40339, 40300,40260,40220,40180,40141,40101,40061,40021, 39982,39942,39902,39862,39822,39782,39742,39702, 39662,39622,39582,39542,39502,39462,39422,39382, 39341,39301,39261,39221,39180,39140,39100,39059, 39019,38979,38938,38898,38857,38817,38776,38736, 38695,38655,38614,38573,38533,38492,38451,38411, 38370,38329,38288,38248,38207,38166,38125,38084, 38043,38002,37961,37920,37879,37838,37797,37756, 37715,37674,37633,37592,37551,37509,37468,37427, 37386,37344,37303,37262,37220,37179,37137,37096, 37055,37013,36972,36930,36889,36847,36805,36764, 36722,36681,36639,36597,36556,36514,36472,36430, 36388,36347,36305,36263,36221,36179,36137,36095, 36053,36011,35969,35927,35885,35843,35801,35759, 35717,35675,35633,35590,35548,35506,35464,35421, 35379,35337,35294,35252,35210,35167,35125,35082, 35040,34997,34955,34912,34870,34827,34785,34742, 34699,34657,34614,34571,34529,34486,34443,34400, 34358,34315,34272,34229,34186,34143,34100,34057, 34015,33972,33929,33886,33843,33799,33756,33713, 33670,33627,33584,33541,33498,33454,33411,33368, 33325,33281,33238,33195,33151,33108,33065,33021, 32978,32934,32891,32847,32804,32760,32717,32673, 32630,32586,32542,32499,32455,32411,32368,32324, 32280,32236,32193,32149,32105,32061,32017,31974, 31930,31886,31842,31798,31754,31710,31666,31622, 31578,31534,31490,31446,31402,31357,31313,31269, 31225,31181,31136,31092,31048,31004,30959,30915, 30871,30826,30782,30738,30693,30649,30604,30560, 30515,30471,30426,30382,30337,30293,30248,30204, 30159,30114,30070,30025,29980,29936,29891,29846, 29801,29757,29712,29667,29622,29577,29533,29488, 29443,29398,29353,29308,29263,29218,29173,29128, 29083,29038,28993,28948,28903,28858,28812,28767, 28722,28677,28632,28586,28541,28496,28451,28405, 28360,28315,28269,28224,28179,28133,28088,28042, 27997,27952,27906,27861,27815,27770,27724,27678, 27633,27587,27542,27496,27450,27405,27359,27313, 27268,27222,27176,27131,27085,27039,26993,26947, 26902,26856,26810,26764,26718,26672,26626,26580, 26534,26488,26442,26396,26350,26304,26258,26212, 26166,26120,26074,26028,25982,25936,25889,25843, 25797,25751,25705,25658,25612,25566,25520,25473, 25427,25381,25334,25288,25241,25195,25149,25102, 25056,25009,24963,24916,24870,24823,24777,24730, 24684,24637,24591,24544,24497,24451,24404,24357, 24311,24264,24217,24171,24124,24077,24030,23984, 23937,23890,23843,23796,23750,23703,23656,23609, 23562,23515,23468,23421,23374,23327,23280,23233, 23186,23139,23092,23045,22998,22951,22904,22857, 22810,22763,22716,22668,22621,22574,22527,22480, 22433,22385,22338,22291,22243,22196,22149,22102, 22054,22007,21960,21912,21865,21817,21770,21723, 21675,21628,21580,21533,21485,21438,21390,21343, 21295,21248,21200,21153,21105,21057,21010,20962, 20915,20867,20819,20772,20724,20676,20629,20581, 20533,20485,20438,20390,20342,20294,20246,20199, 20151,20103,20055,20007,19959,19912,19864,19816, 19768,19720,19672,19624,19576,19528,19480,19432, 19384,19336,19288,19240,19192,19144,19096,19048, 19000,18951,18903,18855,18807,18759,18711,18663, 18614,18566,18518,18470,18421,18373,18325,18277, 18228,18180,18132,18084,18035,17987,17939,17890, 17842,17793,17745,17697,17648,17600,17551,17503, 17455,17406,17358,17309,17261,17212,17164,17115, 17067,17018,16970,16921,16872,16824,16775,16727, 16678,16629,16581,16532,16484,16435,16386,16338, 16289,16240,16191,16143,16094,16045,15997,15948, 15899,15850,15802,15753,15704,15655,15606,15557, 15509,15460,15411,15362,15313,15264,15215,15167, 15118,15069,15020,14971,14922,14873,14824,14775, 14726,14677,14628,14579,14530,14481,14432,14383, 14334,14285,14236,14187,14138,14089,14040,13990, 13941,13892,13843,13794,13745,13696,13646,13597, 13548,13499,13450,13401,13351,13302,13253,13204, 13154,13105,13056,13007,12957,12908,12859,12810, 12760,12711,12662,12612,12563,12514,12464,12415, 12366,12316,12267,12218,12168,12119,12069,12020, 11970,11921,11872,11822,11773,11723,11674,11624, 11575,11525,11476,11426,11377,11327,11278,11228, 11179,11129,11080,11030,10981,10931,10882,10832, 10782,10733,10683,10634,10584,10534,10485,10435, 10386,10336,10286,10237,10187,10137,10088,10038, 9988,9939,9889,9839,9790,9740,9690,9640, 9591,9541,9491,9442,9392,9342,9292,9243, 9193,9143,9093,9043,8994,8944,8894,8844, 8794,8745,8695,8645,8595,8545,8496,8446, 8396,8346,8296,8246,8196,8147,8097,8047, 7997,7947,7897,7847,7797,7747,7697,7648, 7598,7548,7498,7448,7398,7348,7298,7248, 7198,7148,7098,7048,6998,6948,6898,6848, 6798,6748,6698,6648,6598,6548,6498,6448, 6398,6348,6298,6248,6198,6148,6098,6048, 5998,5948,5898,5848,5798,5748,5697,5647, 5597,5547,5497,5447,5397,5347,5297,5247, 5197,5146,5096,5046,4996,4946,4896,4846, 4796,4745,4695,4645,4595,4545,4495,4445, 4394,4344,4294,4244,4194,4144,4093,4043, 3993,3943,3893,3843,3792,3742,3692,3642, 3592,3541,3491,3441,3391,3341,3291,3240, 3190,3140,3090,3039,2989,2939,2889,2839, 2788,2738,2688,2638,2587,2537,2487,2437, 2387,2336,2286,2236,2186,2135,2085,2035, 1985,1934,1884,1834,1784,1733,1683,1633, 1583,1532,1482,1432,1382,1331,1281,1231, 1181,1130,1080,1030,980,929,879,829, 779,728,678,628,578,527,477,427, 376,326,276,226,175,125,75,25, -25,-75,-125,-175,-226,-276,-326,-376, -427,-477,-527,-578,-628,-678,-728,-779, -829,-879,-929,-980,-1030,-1080,-1130,-1181, -1231,-1281,-1331,-1382,-1432,-1482,-1532,-1583, -1633,-1683,-1733,-1784,-1834,-1884,-1934,-1985, -2035,-2085,-2135,-2186,-2236,-2286,-2336,-2387, -2437,-2487,-2537,-2588,-2638,-2688,-2738,-2788, -2839,-2889,-2939,-2989,-3039,-3090,-3140,-3190, -3240,-3291,-3341,-3391,-3441,-3491,-3541,-3592, -3642,-3692,-3742,-3792,-3843,-3893,-3943,-3993, -4043,-4093,-4144,-4194,-4244,-4294,-4344,-4394, -4445,-4495,-4545,-4595,-4645,-4695,-4745,-4796, -4846,-4896,-4946,-4996,-5046,-5096,-5146,-5197, -5247,-5297,-5347,-5397,-5447,-5497,-5547,-5597, -5647,-5697,-5748,-5798,-5848,-5898,-5948,-5998, -6048,-6098,-6148,-6198,-6248,-6298,-6348,-6398, -6448,-6498,-6548,-6598,-6648,-6698,-6748,-6798, -6848,-6898,-6948,-6998,-7048,-7098,-7148,-7198, -7248,-7298,-7348,-7398,-7448,-7498,-7548,-7598, -7648,-7697,-7747,-7797,-7847,-7897,-7947,-7997, -8047,-8097,-8147,-8196,-8246,-8296,-8346,-8396, -8446,-8496,-8545,-8595,-8645,-8695,-8745,-8794, -8844,-8894,-8944,-8994,-9043,-9093,-9143,-9193, -9243,-9292,-9342,-9392,-9442,-9491,-9541,-9591, -9640,-9690,-9740,-9790,-9839,-9889,-9939,-9988, -10038,-10088,-10137,-10187,-10237,-10286,-10336,-10386, -10435,-10485,-10534,-10584,-10634,-10683,-10733,-10782, -10832,-10882,-10931,-10981,-11030,-11080,-11129,-11179, -11228,-11278,-11327,-11377,-11426,-11476,-11525,-11575, -11624,-11674,-11723,-11773,-11822,-11872,-11921,-11970, -12020,-12069,-12119,-12168,-12218,-12267,-12316,-12366, -12415,-12464,-12514,-12563,-12612,-12662,-12711,-12760, -12810,-12859,-12908,-12957,-13007,-13056,-13105,-13154, -13204,-13253,-13302,-13351,-13401,-13450,-13499,-13548, -13597,-13647,-13696,-13745,-13794,-13843,-13892,-13941, -13990,-14040,-14089,-14138,-14187,-14236,-14285,-14334, -14383,-14432,-14481,-14530,-14579,-14628,-14677,-14726, -14775,-14824,-14873,-14922,-14971,-15020,-15069,-15118, -15167,-15215,-15264,-15313,-15362,-15411,-15460,-15509, -15557,-15606,-15655,-15704,-15753,-15802,-15850,-15899, -15948,-15997,-16045,-16094,-16143,-16191,-16240,-16289, -16338,-16386,-16435,-16484,-16532,-16581,-16629,-16678, -16727,-16775,-16824,-16872,-16921,-16970,-17018,-17067, -17115,-17164,-17212,-17261,-17309,-17358,-17406,-17455, -17503,-17551,-17600,-17648,-17697,-17745,-17793,-17842, -17890,-17939,-17987,-18035,-18084,-18132,-18180,-18228, -18277,-18325,-18373,-18421,-18470,-18518,-18566,-18614, -18663,-18711,-18759,-18807,-18855,-18903,-18951,-19000, -19048,-19096,-19144,-19192,-19240,-19288,-19336,-19384, -19432,-19480,-19528,-19576,-19624,-19672,-19720,-19768, -19816,-19864,-19912,-19959,-20007,-20055,-20103,-20151, -20199,-20246,-20294,-20342,-20390,-20438,-20485,-20533, -20581,-20629,-20676,-20724,-20772,-20819,-20867,-20915, -20962,-21010,-21057,-21105,-21153,-21200,-21248,-21295, -21343,-21390,-21438,-21485,-21533,-21580,-21628,-21675, -21723,-21770,-21817,-21865,-21912,-21960,-22007,-22054, -22102,-22149,-22196,-22243,-22291,-22338,-22385,-22433, -22480,-22527,-22574,-22621,-22668,-22716,-22763,-22810, -22857,-22904,-22951,-22998,-23045,-23092,-23139,-23186, -23233,-23280,-23327,-23374,-23421,-23468,-23515,-23562, -23609,-23656,-23703,-23750,-23796,-23843,-23890,-23937, -23984,-24030,-24077,-24124,-24171,-24217,-24264,-24311, -24357,-24404,-24451,-24497,-24544,-24591,-24637,-24684, -24730,-24777,-24823,-24870,-24916,-24963,-25009,-25056, -25102,-25149,-25195,-25241,-25288,-25334,-25381,-25427, -25473,-25520,-25566,-25612,-25658,-25705,-25751,-25797, -25843,-25889,-25936,-25982,-26028,-26074,-26120,-26166, -26212,-26258,-26304,-26350,-26396,-26442,-26488,-26534, -26580,-26626,-26672,-26718,-26764,-26810,-26856,-26902, -26947,-26993,-27039,-27085,-27131,-27176,-27222,-27268, -27313,-27359,-27405,-27450,-27496,-27542,-27587,-27633, -27678,-27724,-27770,-27815,-27861,-27906,-27952,-27997, -28042,-28088,-28133,-28179,-28224,-28269,-28315,-28360, -28405,-28451,-28496,-28541,-28586,-28632,-28677,-28722, -28767,-28812,-28858,-28903,-28948,-28993,-29038,-29083, -29128,-29173,-29218,-29263,-29308,-29353,-29398,-29443, -29488,-29533,-29577,-29622,-29667,-29712,-29757,-29801, -29846,-29891,-29936,-29980,-30025,-30070,-30114,-30159, -30204,-30248,-30293,-30337,-30382,-30426,-30471,-30515, -30560,-30604,-30649,-30693,-30738,-30782,-30826,-30871, -30915,-30959,-31004,-31048,-31092,-31136,-31181,-31225, -31269,-31313,-31357,-31402,-31446,-31490,-31534,-31578, -31622,-31666,-31710,-31754,-31798,-31842,-31886,-31930, -31974,-32017,-32061,-32105,-32149,-32193,-32236,-32280, -32324,-32368,-32411,-32455,-32499,-32542,-32586,-32630, -32673,-32717,-32760,-32804,-32847,-32891,-32934,-32978, -33021,-33065,-33108,-33151,-33195,-33238,-33281,-33325, -33368,-33411,-33454,-33498,-33541,-33584,-33627,-33670, -33713,-33756,-33799,-33843,-33886,-33929,-33972,-34015, -34057,-34100,-34143,-34186,-34229,-34272,-34315,-34358, -34400,-34443,-34486,-34529,-34571,-34614,-34657,-34699, -34742,-34785,-34827,-34870,-34912,-34955,-34997,-35040, -35082,-35125,-35167,-35210,-35252,-35294,-35337,-35379, -35421,-35464,-35506,-35548,-35590,-35633,-35675,-35717, -35759,-35801,-35843,-35885,-35927,-35969,-36011,-36053, -36095,-36137,-36179,-36221,-36263,-36305,-36347,-36388, -36430,-36472,-36514,-36555,-36597,-36639,-36681,-36722, -36764,-36805,-36847,-36889,-36930,-36972,-37013,-37055, -37096,-37137,-37179,-37220,-37262,-37303,-37344,-37386, -37427,-37468,-37509,-37551,-37592,-37633,-37674,-37715, -37756,-37797,-37838,-37879,-37920,-37961,-38002,-38043, -38084,-38125,-38166,-38207,-38248,-38288,-38329,-38370, -38411,-38451,-38492,-38533,-38573,-38614,-38655,-38695, -38736,-38776,-38817,-38857,-38898,-38938,-38979,-39019, -39059,-39100,-39140,-39180,-39221,-39261,-39301,-39341, -39382,-39422,-39462,-39502,-39542,-39582,-39622,-39662, -39702,-39742,-39782,-39822,-39862,-39902,-39942,-39982, -40021,-40061,-40101,-40141,-40180,-40220,-40260,-40299, -40339,-40379,-40418,-40458,-40497,-40537,-40576,-40616, -40655,-40695,-40734,-40773,-40813,-40852,-40891,-40931, -40970,-41009,-41048,-41087,-41127,-41166,-41205,-41244, -41283,-41322,-41361,-41400,-41439,-41478,-41517,-41556, -41595,-41633,-41672,-41711,-41750,-41788,-41827,-41866, -41904,-41943,-41982,-42020,-42059,-42097,-42136,-42174, -42213,-42251,-42290,-42328,-42366,-42405,-42443,-42481, -42520,-42558,-42596,-42634,-42672,-42711,-42749,-42787, -42825,-42863,-42901,-42939,-42977,-43015,-43053,-43091, -43128,-43166,-43204,-43242,-43280,-43317,-43355,-43393, -43430,-43468,-43506,-43543,-43581,-43618,-43656,-43693, -43731,-43768,-43806,-43843,-43880,-43918,-43955,-43992, -44029,-44067,-44104,-44141,-44178,-44215,-44252,-44289, -44326,-44363,-44400,-44437,-44474,-44511,-44548,-44585, -44622,-44659,-44695,-44732,-44769,-44806,-44842,-44879, -44915,-44952,-44989,-45025,-45062,-45098,-45135,-45171, -45207,-45244,-45280,-45316,-45353,-45389,-45425,-45462, -45498,-45534,-45570,-45606,-45642,-45678,-45714,-45750, -45786,-45822,-45858,-45894,-45930,-45966,-46002,-46037, -46073,-46109,-46145,-46180,-46216,-46252,-46287,-46323, -46358,-46394,-46429,-46465,-46500,-46536,-46571,-46606, -46642,-46677,-46712,-46747,-46783,-46818,-46853,-46888, -46923,-46958,-46993,-47028,-47063,-47098,-47133,-47168, -47203,-47238,-47273,-47308,-47342,-47377,-47412,-47446, -47481,-47516,-47550,-47585,-47619,-47654,-47688,-47723, -47757,-47792,-47826,-47860,-47895,-47929,-47963,-47998, -48032,-48066,-48100,-48134,-48168,-48202,-48236,-48271, -48304,-48338,-48372,-48406,-48440,-48474,-48508,-48542, -48575,-48609,-48643,-48676,-48710,-48744,-48777,-48811, -48844,-48878,-48911,-48945,-48978,-49012,-49045,-49078, -49112,-49145,-49178,-49211,-49244,-49278,-49311,-49344, -49377,-49410,-49443,-49476,-49509,-49542,-49575,-49608, -49640,-49673,-49706,-49739,-49771,-49804,-49837,-49869, -49902,-49935,-49967,-50000,-50032,-50065,-50097,-50129, -50162,-50194,-50226,-50259,-50291,-50323,-50355,-50387, -50420,-50452,-50484,-50516,-50548,-50580,-50612,-50644, -50675,-50707,-50739,-50771,-50803,-50834,-50866,-50898, -50929,-50961,-50993,-51024,-51056,-51087,-51119,-51150, -51182,-51213,-51244,-51276,-51307,-51338,-51369,-51401, -51432,-51463,-51494,-51525,-51556,-51587,-51618,-51649, -51680,-51711,-51742,-51773,-51803,-51834,-51865,-51896, -51926,-51957,-51988,-52018,-52049,-52079,-52110,-52140, -52171,-52201,-52231,-52262,-52292,-52322,-52353,-52383, -52413,-52443,-52473,-52503,-52534,-52564,-52594,-52624, -52653,-52683,-52713,-52743,-52773,-52803,-52832,-52862, -52892,-52922,-52951,-52981,-53010,-53040,-53069,-53099, -53128,-53158,-53187,-53216,-53246,-53275,-53304,-53334, -53363,-53392,-53421,-53450,-53479,-53508,-53537,-53566, -53595,-53624,-53653,-53682,-53711,-53739,-53768,-53797, -53826,-53854,-53883,-53911,-53940,-53969,-53997,-54026, -54054,-54082,-54111,-54139,-54167,-54196,-54224,-54252, -54280,-54308,-54337,-54365,-54393,-54421,-54449,-54477, -54505,-54533,-54560,-54588,-54616,-54644,-54672,-54699, -54727,-54755,-54782,-54810,-54837,-54865,-54892,-54920, -54947,-54974,-55002,-55029,-55056,-55084,-55111,-55138, -55165,-55192,-55219,-55246,-55274,-55300,-55327,-55354, -55381,-55408,-55435,-55462,-55489,-55515,-55542,-55569, -55595,-55622,-55648,-55675,-55701,-55728,-55754,-55781, -55807,-55833,-55860,-55886,-55912,-55938,-55965,-55991, -56017,-56043,-56069,-56095,-56121,-56147,-56173,-56199, -56225,-56250,-56276,-56302,-56328,-56353,-56379,-56404, -56430,-56456,-56481,-56507,-56532,-56557,-56583,-56608, -56633,-56659,-56684,-56709,-56734,-56760,-56785,-56810, -56835,-56860,-56885,-56910,-56935,-56959,-56984,-57009, -57034,-57059,-57083,-57108,-57133,-57157,-57182,-57206, -57231,-57255,-57280,-57304,-57329,-57353,-57377,-57402, -57426,-57450,-57474,-57498,-57522,-57546,-57570,-57594, -57618,-57642,-57666,-57690,-57714,-57738,-57762,-57785, -57809,-57833,-57856,-57880,-57903,-57927,-57950,-57974, -57997,-58021,-58044,-58067,-58091,-58114,-58137,-58160, -58183,-58207,-58230,-58253,-58276,-58299,-58322,-58345, -58367,-58390,-58413,-58436,-58459,-58481,-58504,-58527, -58549,-58572,-58594,-58617,-58639,-58662,-58684,-58706, -58729,-58751,-58773,-58795,-58818,-58840,-58862,-58884, -58906,-58928,-58950,-58972,-58994,-59016,-59038,-59059, -59081,-59103,-59125,-59146,-59168,-59190,-59211,-59233, -59254,-59276,-59297,-59318,-59340,-59361,-59382,-59404, -59425,-59446,-59467,-59488,-59509,-59530,-59551,-59572, -59593,-59614,-59635,-59656,-59677,-59697,-59718,-59739, -59759,-59780,-59801,-59821,-59842,-59862,-59883,-59903, -59923,-59944,-59964,-59984,-60004,-60025,-60045,-60065, -60085,-60105,-60125,-60145,-60165,-60185,-60205,-60225, -60244,-60264,-60284,-60304,-60323,-60343,-60363,-60382, -60402,-60421,-60441,-60460,-60479,-60499,-60518,-60537, -60556,-60576,-60595,-60614,-60633,-60652,-60671,-60690, -60709,-60728,-60747,-60766,-60785,-60803,-60822,-60841, -60859,-60878,-60897,-60915,-60934,-60952,-60971,-60989, -61007,-61026,-61044,-61062,-61081,-61099,-61117,-61135, -61153,-61171,-61189,-61207,-61225,-61243,-61261,-61279, -61297,-61314,-61332,-61350,-61367,-61385,-61403,-61420, -61438,-61455,-61473,-61490,-61507,-61525,-61542,-61559, -61577,-61594,-61611,-61628,-61645,-61662,-61679,-61696, -61713,-61730,-61747,-61764,-61780,-61797,-61814,-61831, -61847,-61864,-61880,-61897,-61913,-61930,-61946,-61963, -61979,-61995,-62012,-62028,-62044,-62060,-62076,-62092, -62108,-62125,-62141,-62156,-62172,-62188,-62204,-62220, -62236,-62251,-62267,-62283,-62298,-62314,-62329,-62345, -62360,-62376,-62391,-62407,-62422,-62437,-62453,-62468, -62483,-62498,-62513,-62528,-62543,-62558,-62573,-62588, -62603,-62618,-62633,-62648,-62662,-62677,-62692,-62706, -62721,-62735,-62750,-62764,-62779,-62793,-62808,-62822, -62836,-62850,-62865,-62879,-62893,-62907,-62921,-62935, -62949,-62963,-62977,-62991,-63005,-63019,-63032,-63046, -63060,-63074,-63087,-63101,-63114,-63128,-63141,-63155, -63168,-63182,-63195,-63208,-63221,-63235,-63248,-63261, -63274,-63287,-63300,-63313,-63326,-63339,-63352,-63365, -63378,-63390,-63403,-63416,-63429,-63441,-63454,-63466, -63479,-63491,-63504,-63516,-63528,-63541,-63553,-63565, -63578,-63590,-63602,-63614,-63626,-63638,-63650,-63662, -63674,-63686,-63698,-63709,-63721,-63733,-63745,-63756, -63768,-63779,-63791,-63803,-63814,-63825,-63837,-63848, -63859,-63871,-63882,-63893,-63904,-63915,-63927,-63938, -63949,-63960,-63971,-63981,-63992,-64003,-64014,-64025, -64035,-64046,-64057,-64067,-64078,-64088,-64099,-64109, -64120,-64130,-64140,-64151,-64161,-64171,-64181,-64192, -64202,-64212,-64222,-64232,-64242,-64252,-64261,-64271, -64281,-64291,-64301,-64310,-64320,-64330,-64339,-64349, -64358,-64368,-64377,-64387,-64396,-64405,-64414,-64424, -64433,-64442,-64451,-64460,-64469,-64478,-64487,-64496, -64505,-64514,-64523,-64532,-64540,-64549,-64558,-64566, -64575,-64584,-64592,-64601,-64609,-64617,-64626,-64634, -64642,-64651,-64659,-64667,-64675,-64683,-64691,-64699, -64707,-64715,-64723,-64731,-64739,-64747,-64754,-64762, -64770,-64777,-64785,-64793,-64800,-64808,-64815,-64822, -64830,-64837,-64844,-64852,-64859,-64866,-64873,-64880, -64887,-64895,-64902,-64908,-64915,-64922,-64929,-64936, -64943,-64949,-64956,-64963,-64969,-64976,-64982,-64989, -64995,-65002,-65008,-65015,-65021,-65027,-65033,-65040, -65046,-65052,-65058,-65064,-65070,-65076,-65082,-65088, -65094,-65099,-65105,-65111,-65117,-65122,-65128,-65133, -65139,-65144,-65150,-65155,-65161,-65166,-65171,-65177, -65182,-65187,-65192,-65197,-65202,-65207,-65212,-65217, -65222,-65227,-65232,-65237,-65242,-65246,-65251,-65256, -65260,-65265,-65270,-65274,-65279,-65283,-65287,-65292, -65296,-65300,-65305,-65309,-65313,-65317,-65321,-65325, -65329,-65333,-65337,-65341,-65345,-65349,-65352,-65356, -65360,-65363,-65367,-65371,-65374,-65378,-65381,-65385, -65388,-65391,-65395,-65398,-65401,-65404,-65408,-65411, -65414,-65417,-65420,-65423,-65426,-65429,-65431,-65434, -65437,-65440,-65442,-65445,-65448,-65450,-65453,-65455, -65458,-65460,-65463,-65465,-65467,-65470,-65472,-65474, -65476,-65478,-65480,-65482,-65484,-65486,-65488,-65490, -65492,-65494,-65496,-65497,-65499,-65501,-65502,-65504, -65505,-65507,-65508,-65510,-65511,-65513,-65514,-65515, -65516,-65518,-65519,-65520,-65521,-65522,-65523,-65524, -65525,-65526,-65527,-65527,-65528,-65529,-65530,-65530, -65531,-65531,-65532,-65532,-65533,-65533,-65534,-65534, -65534,-65535,-65535,-65535,-65535,-65535,-65535,-65535, -65535,-65535,-65535,-65535,-65535,-65535,-65535,-65534, -65534,-65534,-65533,-65533,-65532,-65532,-65531,-65531, -65530,-65530,-65529,-65528,-65527,-65527,-65526,-65525, -65524,-65523,-65522,-65521,-65520,-65519,-65518,-65516, -65515,-65514,-65513,-65511,-65510,-65508,-65507,-65505, -65504,-65502,-65501,-65499,-65497,-65496,-65494,-65492, -65490,-65488,-65486,-65484,-65482,-65480,-65478,-65476, -65474,-65472,-65470,-65467,-65465,-65463,-65460,-65458, -65455,-65453,-65450,-65448,-65445,-65442,-65440,-65437, -65434,-65431,-65429,-65426,-65423,-65420,-65417,-65414, -65411,-65408,-65404,-65401,-65398,-65395,-65391,-65388, -65385,-65381,-65378,-65374,-65371,-65367,-65363,-65360, -65356,-65352,-65349,-65345,-65341,-65337,-65333,-65329, -65325,-65321,-65317,-65313,-65309,-65305,-65300,-65296, -65292,-65287,-65283,-65279,-65274,-65270,-65265,-65260, -65256,-65251,-65246,-65242,-65237,-65232,-65227,-65222, -65217,-65212,-65207,-65202,-65197,-65192,-65187,-65182, -65177,-65171,-65166,-65161,-65155,-65150,-65144,-65139, -65133,-65128,-65122,-65117,-65111,-65105,-65099,-65094, -65088,-65082,-65076,-65070,-65064,-65058,-65052,-65046, -65040,-65033,-65027,-65021,-65015,-65008,-65002,-64995, -64989,-64982,-64976,-64969,-64963,-64956,-64949,-64943, -64936,-64929,-64922,-64915,-64908,-64902,-64895,-64887, -64880,-64873,-64866,-64859,-64852,-64844,-64837,-64830, -64822,-64815,-64808,-64800,-64793,-64785,-64777,-64770, -64762,-64754,-64747,-64739,-64731,-64723,-64715,-64707, -64699,-64691,-64683,-64675,-64667,-64659,-64651,-64642, -64634,-64626,-64617,-64609,-64601,-64592,-64584,-64575, -64566,-64558,-64549,-64540,-64532,-64523,-64514,-64505, -64496,-64487,-64478,-64469,-64460,-64451,-64442,-64433, -64424,-64414,-64405,-64396,-64387,-64377,-64368,-64358, -64349,-64339,-64330,-64320,-64310,-64301,-64291,-64281, -64271,-64261,-64252,-64242,-64232,-64222,-64212,-64202, -64192,-64181,-64171,-64161,-64151,-64140,-64130,-64120, -64109,-64099,-64088,-64078,-64067,-64057,-64046,-64035, -64025,-64014,-64003,-63992,-63981,-63971,-63960,-63949, -63938,-63927,-63915,-63904,-63893,-63882,-63871,-63859, -63848,-63837,-63825,-63814,-63803,-63791,-63779,-63768, -63756,-63745,-63733,-63721,-63709,-63698,-63686,-63674, -63662,-63650,-63638,-63626,-63614,-63602,-63590,-63578, -63565,-63553,-63541,-63528,-63516,-63504,-63491,-63479, -63466,-63454,-63441,-63429,-63416,-63403,-63390,-63378, -63365,-63352,-63339,-63326,-63313,-63300,-63287,-63274, -63261,-63248,-63235,-63221,-63208,-63195,-63182,-63168, -63155,-63141,-63128,-63114,-63101,-63087,-63074,-63060, -63046,-63032,-63019,-63005,-62991,-62977,-62963,-62949, -62935,-62921,-62907,-62893,-62879,-62865,-62850,-62836, -62822,-62808,-62793,-62779,-62764,-62750,-62735,-62721, -62706,-62692,-62677,-62662,-62648,-62633,-62618,-62603, -62588,-62573,-62558,-62543,-62528,-62513,-62498,-62483, -62468,-62453,-62437,-62422,-62407,-62391,-62376,-62360, -62345,-62329,-62314,-62298,-62283,-62267,-62251,-62236, -62220,-62204,-62188,-62172,-62156,-62141,-62125,-62108, -62092,-62076,-62060,-62044,-62028,-62012,-61995,-61979, -61963,-61946,-61930,-61913,-61897,-61880,-61864,-61847, -61831,-61814,-61797,-61780,-61764,-61747,-61730,-61713, -61696,-61679,-61662,-61645,-61628,-61611,-61594,-61577, -61559,-61542,-61525,-61507,-61490,-61473,-61455,-61438, -61420,-61403,-61385,-61367,-61350,-61332,-61314,-61297, -61279,-61261,-61243,-61225,-61207,-61189,-61171,-61153, -61135,-61117,-61099,-61081,-61062,-61044,-61026,-61007, -60989,-60971,-60952,-60934,-60915,-60897,-60878,-60859, -60841,-60822,-60803,-60785,-60766,-60747,-60728,-60709, -60690,-60671,-60652,-60633,-60614,-60595,-60576,-60556, -60537,-60518,-60499,-60479,-60460,-60441,-60421,-60402, -60382,-60363,-60343,-60323,-60304,-60284,-60264,-60244, -60225,-60205,-60185,-60165,-60145,-60125,-60105,-60085, -60065,-60045,-60025,-60004,-59984,-59964,-59944,-59923, -59903,-59883,-59862,-59842,-59821,-59801,-59780,-59759, -59739,-59718,-59697,-59677,-59656,-59635,-59614,-59593, -59572,-59551,-59530,-59509,-59488,-59467,-59446,-59425, -59404,-59382,-59361,-59340,-59318,-59297,-59276,-59254, -59233,-59211,-59189,-59168,-59146,-59125,-59103,-59081, -59059,-59038,-59016,-58994,-58972,-58950,-58928,-58906, -58884,-58862,-58840,-58818,-58795,-58773,-58751,-58729, -58706,-58684,-58662,-58639,-58617,-58594,-58572,-58549, -58527,-58504,-58481,-58459,-58436,-58413,-58390,-58367, -58345,-58322,-58299,-58276,-58253,-58230,-58207,-58183, -58160,-58137,-58114,-58091,-58067,-58044,-58021,-57997, -57974,-57950,-57927,-57903,-57880,-57856,-57833,-57809, -57785,-57762,-57738,-57714,-57690,-57666,-57642,-57618, -57594,-57570,-57546,-57522,-57498,-57474,-57450,-57426, -57402,-57377,-57353,-57329,-57304,-57280,-57255,-57231, -57206,-57182,-57157,-57133,-57108,-57083,-57059,-57034, -57009,-56984,-56959,-56935,-56910,-56885,-56860,-56835, -56810,-56785,-56760,-56734,-56709,-56684,-56659,-56633, -56608,-56583,-56557,-56532,-56507,-56481,-56456,-56430, -56404,-56379,-56353,-56328,-56302,-56276,-56250,-56225, -56199,-56173,-56147,-56121,-56095,-56069,-56043,-56017, -55991,-55965,-55938,-55912,-55886,-55860,-55833,-55807, -55781,-55754,-55728,-55701,-55675,-55648,-55622,-55595, -55569,-55542,-55515,-55489,-55462,-55435,-55408,-55381, -55354,-55327,-55300,-55274,-55246,-55219,-55192,-55165, -55138,-55111,-55084,-55056,-55029,-55002,-54974,-54947, -54920,-54892,-54865,-54837,-54810,-54782,-54755,-54727, -54699,-54672,-54644,-54616,-54588,-54560,-54533,-54505, -54477,-54449,-54421,-54393,-54365,-54337,-54308,-54280, -54252,-54224,-54196,-54167,-54139,-54111,-54082,-54054, -54026,-53997,-53969,-53940,-53911,-53883,-53854,-53826, -53797,-53768,-53739,-53711,-53682,-53653,-53624,-53595, -53566,-53537,-53508,-53479,-53450,-53421,-53392,-53363, -53334,-53304,-53275,-53246,-53216,-53187,-53158,-53128, -53099,-53069,-53040,-53010,-52981,-52951,-52922,-52892, -52862,-52832,-52803,-52773,-52743,-52713,-52683,-52653, -52624,-52594,-52564,-52534,-52503,-52473,-52443,-52413, -52383,-52353,-52322,-52292,-52262,-52231,-52201,-52171, -52140,-52110,-52079,-52049,-52018,-51988,-51957,-51926, -51896,-51865,-51834,-51803,-51773,-51742,-51711,-51680, -51649,-51618,-51587,-51556,-51525,-51494,-51463,-51432, -51401,-51369,-51338,-51307,-51276,-51244,-51213,-51182, -51150,-51119,-51087,-51056,-51024,-50993,-50961,-50929, -50898,-50866,-50834,-50803,-50771,-50739,-50707,-50675, -50644,-50612,-50580,-50548,-50516,-50484,-50452,-50420, -50387,-50355,-50323,-50291,-50259,-50226,-50194,-50162, -50129,-50097,-50065,-50032,-50000,-49967,-49935,-49902, -49869,-49837,-49804,-49771,-49739,-49706,-49673,-49640, -49608,-49575,-49542,-49509,-49476,-49443,-49410,-49377, -49344,-49311,-49278,-49244,-49211,-49178,-49145,-49112, -49078,-49045,-49012,-48978,-48945,-48911,-48878,-48844, -48811,-48777,-48744,-48710,-48676,-48643,-48609,-48575, -48542,-48508,-48474,-48440,-48406,-48372,-48338,-48305, -48271,-48237,-48202,-48168,-48134,-48100,-48066,-48032, -47998,-47963,-47929,-47895,-47860,-47826,-47792,-47757, -47723,-47688,-47654,-47619,-47585,-47550,-47516,-47481, -47446,-47412,-47377,-47342,-47307,-47273,-47238,-47203, -47168,-47133,-47098,-47063,-47028,-46993,-46958,-46923, -46888,-46853,-46818,-46783,-46747,-46712,-46677,-46642, -46606,-46571,-46536,-46500,-46465,-46429,-46394,-46358, -46323,-46287,-46251,-46216,-46180,-46145,-46109,-46073, -46037,-46002,-45966,-45930,-45894,-45858,-45822,-45786, -45750,-45714,-45678,-45642,-45606,-45570,-45534,-45498, -45462,-45425,-45389,-45353,-45316,-45280,-45244,-45207, -45171,-45135,-45098,-45062,-45025,-44989,-44952,-44915, -44879,-44842,-44806,-44769,-44732,-44695,-44659,-44622, -44585,-44548,-44511,-44474,-44437,-44400,-44363,-44326, -44289,-44252,-44215,-44178,-44141,-44104,-44067,-44029, -43992,-43955,-43918,-43880,-43843,-43806,-43768,-43731, -43693,-43656,-43618,-43581,-43543,-43506,-43468,-43430, -43393,-43355,-43317,-43280,-43242,-43204,-43166,-43128, -43091,-43053,-43015,-42977,-42939,-42901,-42863,-42825, -42787,-42749,-42711,-42672,-42634,-42596,-42558,-42520, -42481,-42443,-42405,-42366,-42328,-42290,-42251,-42213, -42174,-42136,-42097,-42059,-42020,-41982,-41943,-41904, -41866,-41827,-41788,-41750,-41711,-41672,-41633,-41595, -41556,-41517,-41478,-41439,-41400,-41361,-41322,-41283, -41244,-41205,-41166,-41127,-41087,-41048,-41009,-40970, -40931,-40891,-40852,-40813,-40773,-40734,-40695,-40655, -40616,-40576,-40537,-40497,-40458,-40418,-40379,-40339, -40299,-40260,-40220,-40180,-40141,-40101,-40061,-40021, -39982,-39942,-39902,-39862,-39822,-39782,-39742,-39702, -39662,-39622,-39582,-39542,-39502,-39462,-39422,-39382, -39341,-39301,-39261,-39221,-39180,-39140,-39100,-39059, -39019,-38979,-38938,-38898,-38857,-38817,-38776,-38736, -38695,-38655,-38614,-38573,-38533,-38492,-38451,-38411, -38370,-38329,-38288,-38248,-38207,-38166,-38125,-38084, -38043,-38002,-37961,-37920,-37879,-37838,-37797,-37756, -37715,-37674,-37633,-37592,-37550,-37509,-37468,-37427, -37386,-37344,-37303,-37262,-37220,-37179,-37137,-37096, -37055,-37013,-36972,-36930,-36889,-36847,-36805,-36764, -36722,-36681,-36639,-36597,-36556,-36514,-36472,-36430, -36388,-36347,-36305,-36263,-36221,-36179,-36137,-36095, -36053,-36011,-35969,-35927,-35885,-35843,-35801,-35759, -35717,-35675,-35633,-35590,-35548,-35506,-35464,-35421, -35379,-35337,-35294,-35252,-35210,-35167,-35125,-35082, -35040,-34997,-34955,-34912,-34870,-34827,-34785,-34742, -34699,-34657,-34614,-34571,-34529,-34486,-34443,-34400, -34358,-34315,-34272,-34229,-34186,-34143,-34100,-34057, -34015,-33972,-33929,-33886,-33843,-33799,-33756,-33713, -33670,-33627,-33584,-33541,-33498,-33454,-33411,-33368, -33325,-33281,-33238,-33195,-33151,-33108,-33065,-33021, -32978,-32934,-32891,-32847,-32804,-32760,-32717,-32673, -32630,-32586,-32542,-32499,-32455,-32411,-32368,-32324, -32280,-32236,-32193,-32149,-32105,-32061,-32017,-31974, -31930,-31886,-31842,-31798,-31754,-31710,-31666,-31622, -31578,-31534,-31490,-31446,-31402,-31357,-31313,-31269, -31225,-31181,-31136,-31092,-31048,-31004,-30959,-30915, -30871,-30826,-30782,-30738,-30693,-30649,-30604,-30560, -30515,-30471,-30426,-30382,-30337,-30293,-30248,-30204, -30159,-30114,-30070,-30025,-29980,-29936,-29891,-29846, -29801,-29757,-29712,-29667,-29622,-29577,-29533,-29488, -29443,-29398,-29353,-29308,-29263,-29218,-29173,-29128, -29083,-29038,-28993,-28948,-28903,-28858,-28812,-28767, -28722,-28677,-28632,-28586,-28541,-28496,-28451,-28405, -28360,-28315,-28269,-28224,-28179,-28133,-28088,-28042, -27997,-27952,-27906,-27861,-27815,-27770,-27724,-27678, -27633,-27587,-27542,-27496,-27450,-27405,-27359,-27313, -27268,-27222,-27176,-27131,-27085,-27039,-26993,-26947, -26902,-26856,-26810,-26764,-26718,-26672,-26626,-26580, -26534,-26488,-26442,-26396,-26350,-26304,-26258,-26212, -26166,-26120,-26074,-26028,-25982,-25936,-25889,-25843, -25797,-25751,-25705,-25658,-25612,-25566,-25520,-25473, -25427,-25381,-25334,-25288,-25241,-25195,-25149,-25102, -25056,-25009,-24963,-24916,-24870,-24823,-24777,-24730, -24684,-24637,-24591,-24544,-24497,-24451,-24404,-24357, -24311,-24264,-24217,-24171,-24124,-24077,-24030,-23984, -23937,-23890,-23843,-23796,-23750,-23703,-23656,-23609, -23562,-23515,-23468,-23421,-23374,-23327,-23280,-23233, -23186,-23139,-23092,-23045,-22998,-22951,-22904,-22857, -22810,-22763,-22716,-22668,-22621,-22574,-22527,-22480, -22432,-22385,-22338,-22291,-22243,-22196,-22149,-22102, -22054,-22007,-21960,-21912,-21865,-21817,-21770,-21723, -21675,-21628,-21580,-21533,-21485,-21438,-21390,-21343, -21295,-21248,-21200,-21153,-21105,-21057,-21010,-20962, -20915,-20867,-20819,-20772,-20724,-20676,-20629,-20581, -20533,-20485,-20438,-20390,-20342,-20294,-20246,-20199, -20151,-20103,-20055,-20007,-19959,-19912,-19864,-19816, -19768,-19720,-19672,-19624,-19576,-19528,-19480,-19432, -19384,-19336,-19288,-19240,-19192,-19144,-19096,-19048, -19000,-18951,-18903,-18855,-18807,-18759,-18711,-18663, -18614,-18566,-18518,-18470,-18421,-18373,-18325,-18277, -18228,-18180,-18132,-18084,-18035,-17987,-17939,-17890, -17842,-17793,-17745,-17697,-17648,-17600,-17551,-17503, -17455,-17406,-17358,-17309,-17261,-17212,-17164,-17115, -17067,-17018,-16970,-16921,-16872,-16824,-16775,-16727, -16678,-16629,-16581,-16532,-16484,-16435,-16386,-16338, -16289,-16240,-16191,-16143,-16094,-16045,-15997,-15948, -15899,-15850,-15802,-15753,-15704,-15655,-15606,-15557, -15509,-15460,-15411,-15362,-15313,-15264,-15215,-15167, -15118,-15069,-15020,-14971,-14922,-14873,-14824,-14775, -14726,-14677,-14628,-14579,-14530,-14481,-14432,-14383, -14334,-14285,-14236,-14187,-14138,-14089,-14040,-13990, -13941,-13892,-13843,-13794,-13745,-13696,-13647,-13597, -13548,-13499,-13450,-13401,-13351,-13302,-13253,-13204, -13154,-13105,-13056,-13007,-12957,-12908,-12859,-12810, -12760,-12711,-12662,-12612,-12563,-12514,-12464,-12415, -12366,-12316,-12267,-12217,-12168,-12119,-12069,-12020, -11970,-11921,-11872,-11822,-11773,-11723,-11674,-11624, -11575,-11525,-11476,-11426,-11377,-11327,-11278,-11228, -11179,-11129,-11080,-11030,-10981,-10931,-10882,-10832, -10782,-10733,-10683,-10634,-10584,-10534,-10485,-10435, -10386,-10336,-10286,-10237,-10187,-10137,-10088,-10038, -9988,-9939,-9889,-9839,-9790,-9740,-9690,-9640, -9591,-9541,-9491,-9442,-9392,-9342,-9292,-9243, -9193,-9143,-9093,-9043,-8994,-8944,-8894,-8844, -8794,-8745,-8695,-8645,-8595,-8545,-8496,-8446, -8396,-8346,-8296,-8246,-8196,-8147,-8097,-8047, -7997,-7947,-7897,-7847,-7797,-7747,-7697,-7648, -7598,-7548,-7498,-7448,-7398,-7348,-7298,-7248, -7198,-7148,-7098,-7048,-6998,-6948,-6898,-6848, -6798,-6748,-6698,-6648,-6598,-6548,-6498,-6448, -6398,-6348,-6298,-6248,-6198,-6148,-6098,-6048, -5998,-5948,-5898,-5848,-5798,-5747,-5697,-5647, -5597,-5547,-5497,-5447,-5397,-5347,-5297,-5247, -5197,-5146,-5096,-5046,-4996,-4946,-4896,-4846, -4796,-4745,-4695,-4645,-4595,-4545,-4495,-4445, -4394,-4344,-4294,-4244,-4194,-4144,-4093,-4043, -3993,-3943,-3893,-3843,-3792,-3742,-3692,-3642, -3592,-3541,-3491,-3441,-3391,-3341,-3291,-3240, -3190,-3140,-3090,-3039,-2989,-2939,-2889,-2839, -2788,-2738,-2688,-2638,-2588,-2537,-2487,-2437, -2387,-2336,-2286,-2236,-2186,-2135,-2085,-2035, -1985,-1934,-1884,-1834,-1784,-1733,-1683,-1633, -1583,-1532,-1482,-1432,-1382,-1331,-1281,-1231, -1181,-1130,-1080,-1030,-980,-929,-879,-829, -779,-728,-678,-628,-578,-527,-477,-427, -376,-326,-276,-226,-175,-125,-75,-25, 25,75,125,175,226,276,326,376, 427,477,527,578,628,678,728,779, 829,879,929,980,1030,1080,1130,1181, 1231,1281,1331,1382,1432,1482,1532,1583, 1633,1683,1733,1784,1834,1884,1934,1985, 2035,2085,2135,2186,2236,2286,2336,2387, 2437,2487,2537,2587,2638,2688,2738,2788, 2839,2889,2939,2989,3039,3090,3140,3190, 3240,3291,3341,3391,3441,3491,3542,3592, 3642,3692,3742,3792,3843,3893,3943,3993, 4043,4093,4144,4194,4244,4294,4344,4394, 4445,4495,4545,4595,4645,4695,4745,4796, 4846,4896,4946,4996,5046,5096,5146,5197, 5247,5297,5347,5397,5447,5497,5547,5597, 5647,5697,5747,5798,5848,5898,5948,5998, 6048,6098,6148,6198,6248,6298,6348,6398, 6448,6498,6548,6598,6648,6698,6748,6798, 6848,6898,6948,6998,7048,7098,7148,7198, 7248,7298,7348,7398,7448,7498,7548,7598, 7648,7697,7747,7797,7847,7897,7947,7997, 8047,8097,8147,8196,8246,8296,8346,8396, 8446,8496,8545,8595,8645,8695,8745,8794, 8844,8894,8944,8994,9043,9093,9143,9193, 9243,9292,9342,9392,9442,9491,9541,9591, 9640,9690,9740,9790,9839,9889,9939,9988, 10038,10088,10137,10187,10237,10286,10336,10386, 10435,10485,10534,10584,10634,10683,10733,10782, 10832,10882,10931,10981,11030,11080,11129,11179, 11228,11278,11327,11377,11426,11476,11525,11575, 11624,11674,11723,11773,11822,11872,11921,11970, 12020,12069,12119,12168,12218,12267,12316,12366, 12415,12464,12514,12563,12612,12662,12711,12760, 12810,12859,12908,12957,13007,13056,13105,13154, 13204,13253,13302,13351,13401,13450,13499,13548, 13597,13647,13696,13745,13794,13843,13892,13941, 13990,14040,14089,14138,14187,14236,14285,14334, 14383,14432,14481,14530,14579,14628,14677,14726, 14775,14824,14873,14922,14971,15020,15069,15118, 15167,15215,15264,15313,15362,15411,15460,15509, 15557,15606,15655,15704,15753,15802,15850,15899, 15948,15997,16045,16094,16143,16191,16240,16289, 16338,16386,16435,16484,16532,16581,16629,16678, 16727,16775,16824,16872,16921,16970,17018,17067, 17115,17164,17212,17261,17309,17358,17406,17455, 17503,17551,17600,17648,17697,17745,17793,17842, 17890,17939,17987,18035,18084,18132,18180,18228, 18277,18325,18373,18421,18470,18518,18566,18614, 18663,18711,18759,18807,18855,18903,18951,19000, 19048,19096,19144,19192,19240,19288,19336,19384, 19432,19480,19528,19576,19624,19672,19720,19768, 19816,19864,19912,19959,20007,20055,20103,20151, 20199,20246,20294,20342,20390,20438,20485,20533, 20581,20629,20676,20724,20772,20819,20867,20915, 20962,21010,21057,21105,21153,21200,21248,21295, 21343,21390,21438,21485,21533,21580,21628,21675, 21723,21770,21817,21865,21912,21960,22007,22054, 22102,22149,22196,22243,22291,22338,22385,22432, 22480,22527,22574,22621,22668,22716,22763,22810, 22857,22904,22951,22998,23045,23092,23139,23186, 23233,23280,23327,23374,23421,23468,23515,23562, 23609,23656,23703,23750,23796,23843,23890,23937, 23984,24030,24077,24124,24171,24217,24264,24311, 24357,24404,24451,24497,24544,24591,24637,24684, 24730,24777,24823,24870,24916,24963,25009,25056, 25102,25149,25195,25241,25288,25334,25381,25427, 25473,25520,25566,25612,25658,25705,25751,25797, 25843,25889,25936,25982,26028,26074,26120,26166, 26212,26258,26304,26350,26396,26442,26488,26534, 26580,26626,26672,26718,26764,26810,26856,26902, 26947,26993,27039,27085,27131,27176,27222,27268, 27313,27359,27405,27450,27496,27542,27587,27633, 27678,27724,27770,27815,27861,27906,27952,27997, 28042,28088,28133,28179,28224,28269,28315,28360, 28405,28451,28496,28541,28586,28632,28677,28722, 28767,28812,28858,28903,28948,28993,29038,29083, 29128,29173,29218,29263,29308,29353,29398,29443, 29488,29533,29577,29622,29667,29712,29757,29801, 29846,29891,29936,29980,30025,30070,30114,30159, 30204,30248,30293,30337,30382,30427,30471,30516, 30560,30604,30649,30693,30738,30782,30826,30871, 30915,30959,31004,31048,31092,31136,31181,31225, 31269,31313,31357,31402,31446,31490,31534,31578, 31622,31666,31710,31754,31798,31842,31886,31930, 31974,32017,32061,32105,32149,32193,32236,32280, 32324,32368,32411,32455,32499,32542,32586,32630, 32673,32717,32760,32804,32847,32891,32934,32978, 33021,33065,33108,33151,33195,33238,33281,33325, 33368,33411,33454,33498,33541,33584,33627,33670, 33713,33756,33799,33843,33886,33929,33972,34015, 34057,34100,34143,34186,34229,34272,34315,34358, 34400,34443,34486,34529,34571,34614,34657,34699, 34742,34785,34827,34870,34912,34955,34997,35040, 35082,35125,35167,35210,35252,35294,35337,35379, 35421,35464,35506,35548,35590,35633,35675,35717, 35759,35801,35843,35885,35927,35969,36011,36053, 36095,36137,36179,36221,36263,36305,36347,36388, 36430,36472,36514,36556,36597,36639,36681,36722, 36764,36805,36847,36889,36930,36972,37013,37055, 37096,37137,37179,37220,37262,37303,37344,37386, 37427,37468,37509,37551,37592,37633,37674,37715, 37756,37797,37838,37879,37920,37961,38002,38043, 38084,38125,38166,38207,38248,38288,38329,38370, 38411,38451,38492,38533,38573,38614,38655,38695, 38736,38776,38817,38857,38898,38938,38979,39019, 39059,39100,39140,39180,39221,39261,39301,39341, 39382,39422,39462,39502,39542,39582,39622,39662, 39702,39742,39782,39822,39862,39902,39942,39982, 40021,40061,40101,40141,40180,40220,40260,40299, 40339,40379,40418,40458,40497,40537,40576,40616, 40655,40695,40734,40773,40813,40852,40891,40931, 40970,41009,41048,41087,41127,41166,41205,41244, 41283,41322,41361,41400,41439,41478,41517,41556, 41595,41633,41672,41711,41750,41788,41827,41866, 41904,41943,41982,42020,42059,42097,42136,42174, 42213,42251,42290,42328,42366,42405,42443,42481, 42520,42558,42596,42634,42672,42711,42749,42787, 42825,42863,42901,42939,42977,43015,43053,43091, 43128,43166,43204,43242,43280,43317,43355,43393, 43430,43468,43506,43543,43581,43618,43656,43693, 43731,43768,43806,43843,43880,43918,43955,43992, 44029,44067,44104,44141,44178,44215,44252,44289, 44326,44363,44400,44437,44474,44511,44548,44585, 44622,44659,44695,44732,44769,44806,44842,44879, 44915,44952,44989,45025,45062,45098,45135,45171, 45207,45244,45280,45316,45353,45389,45425,45462, 45498,45534,45570,45606,45642,45678,45714,45750, 45786,45822,45858,45894,45930,45966,46002,46037, 46073,46109,46145,46180,46216,46252,46287,46323, 46358,46394,46429,46465,46500,46536,46571,46606, 46642,46677,46712,46747,46783,46818,46853,46888, 46923,46958,46993,47028,47063,47098,47133,47168, 47203,47238,47273,47308,47342,47377,47412,47446, 47481,47516,47550,47585,47619,47654,47688,47723, 47757,47792,47826,47861,47895,47929,47963,47998, 48032,48066,48100,48134,48168,48202,48237,48271, 48305,48338,48372,48406,48440,48474,48508,48542, 48575,48609,48643,48676,48710,48744,48777,48811, 48844,48878,48911,48945,48978,49012,49045,49078, 49112,49145,49178,49211,49244,49278,49311,49344, 49377,49410,49443,49476,49509,49542,49575,49608, 49640,49673,49706,49739,49771,49804,49837,49869, 49902,49935,49967,50000,50032,50064,50097,50129, 50162,50194,50226,50259,50291,50323,50355,50387, 50420,50452,50484,50516,50548,50580,50612,50644, 50675,50707,50739,50771,50803,50834,50866,50898, 50929,50961,50993,51024,51056,51087,51119,51150, 51182,51213,51244,51276,51307,51338,51369,51401, 51432,51463,51494,51525,51556,51587,51618,51649, 51680,51711,51742,51773,51803,51834,51865,51896, 51926,51957,51988,52018,52049,52079,52110,52140, 52171,52201,52231,52262,52292,52322,52353,52383, 52413,52443,52473,52503,52534,52564,52594,52624, 52653,52683,52713,52743,52773,52803,52832,52862, 52892,52922,52951,52981,53010,53040,53069,53099, 53128,53158,53187,53216,53246,53275,53304,53334, 53363,53392,53421,53450,53479,53508,53537,53566, 53595,53624,53653,53682,53711,53739,53768,53797, 53826,53854,53883,53912,53940,53969,53997,54026, 54054,54082,54111,54139,54167,54196,54224,54252, 54280,54309,54337,54365,54393,54421,54449,54477, 54505,54533,54560,54588,54616,54644,54672,54699, 54727,54755,54782,54810,54837,54865,54892,54920, 54947,54974,55002,55029,55056,55084,55111,55138, 55165,55192,55219,55246,55274,55300,55327,55354, 55381,55408,55435,55462,55489,55515,55542,55569, 55595,55622,55648,55675,55701,55728,55754,55781, 55807,55833,55860,55886,55912,55938,55965,55991, 56017,56043,56069,56095,56121,56147,56173,56199, 56225,56250,56276,56302,56328,56353,56379,56404, 56430,56456,56481,56507,56532,56557,56583,56608, 56633,56659,56684,56709,56734,56760,56785,56810, 56835,56860,56885,56910,56935,56959,56984,57009, 57034,57059,57083,57108,57133,57157,57182,57206, 57231,57255,57280,57304,57329,57353,57377,57402, 57426,57450,57474,57498,57522,57546,57570,57594, 57618,57642,57666,57690,57714,57738,57762,57785, 57809,57833,57856,57880,57903,57927,57950,57974, 57997,58021,58044,58067,58091,58114,58137,58160, 58183,58207,58230,58253,58276,58299,58322,58345, 58367,58390,58413,58436,58459,58481,58504,58527, 58549,58572,58594,58617,58639,58662,58684,58706, 58729,58751,58773,58795,58818,58840,58862,58884, 58906,58928,58950,58972,58994,59016,59038,59059, 59081,59103,59125,59146,59168,59190,59211,59233, 59254,59276,59297,59318,59340,59361,59382,59404, 59425,59446,59467,59488,59509,59530,59551,59572, 59593,59614,59635,59656,59677,59697,59718,59739, 59759,59780,59801,59821,59842,59862,59883,59903, 59923,59944,59964,59984,60004,60025,60045,60065, 60085,60105,60125,60145,60165,60185,60205,60225, 60244,60264,60284,60304,60323,60343,60363,60382, 60402,60421,60441,60460,60479,60499,60518,60537, 60556,60576,60595,60614,60633,60652,60671,60690, 60709,60728,60747,60766,60785,60803,60822,60841, 60859,60878,60897,60915,60934,60952,60971,60989, 61007,61026,61044,61062,61081,61099,61117,61135, 61153,61171,61189,61207,61225,61243,61261,61279, 61297,61314,61332,61350,61367,61385,61403,61420, 61438,61455,61473,61490,61507,61525,61542,61559, 61577,61594,61611,61628,61645,61662,61679,61696, 61713,61730,61747,61764,61780,61797,61814,61831, 61847,61864,61880,61897,61913,61930,61946,61963, 61979,61995,62012,62028,62044,62060,62076,62092, 62108,62125,62141,62156,62172,62188,62204,62220, 62236,62251,62267,62283,62298,62314,62329,62345, 62360,62376,62391,62407,62422,62437,62453,62468, 62483,62498,62513,62528,62543,62558,62573,62588, 62603,62618,62633,62648,62662,62677,62692,62706, 62721,62735,62750,62764,62779,62793,62808,62822, 62836,62850,62865,62879,62893,62907,62921,62935, 62949,62963,62977,62991,63005,63019,63032,63046, 63060,63074,63087,63101,63114,63128,63141,63155, 63168,63182,63195,63208,63221,63235,63248,63261, 63274,63287,63300,63313,63326,63339,63352,63365, 63378,63390,63403,63416,63429,63441,63454,63466, 63479,63491,63504,63516,63528,63541,63553,63565, 63578,63590,63602,63614,63626,63638,63650,63662, 63674,63686,63698,63709,63721,63733,63745,63756, 63768,63779,63791,63803,63814,63825,63837,63848, 63859,63871,63882,63893,63904,63915,63927,63938, 63949,63960,63971,63981,63992,64003,64014,64025, 64035,64046,64057,64067,64078,64088,64099,64109, 64120,64130,64140,64151,64161,64171,64181,64192, 64202,64212,64222,64232,64242,64252,64261,64271, 64281,64291,64301,64310,64320,64330,64339,64349, 64358,64368,64377,64387,64396,64405,64414,64424, 64433,64442,64451,64460,64469,64478,64487,64496, 64505,64514,64523,64532,64540,64549,64558,64566, 64575,64584,64592,64600,64609,64617,64626,64634, 64642,64651,64659,64667,64675,64683,64691,64699, 64707,64715,64723,64731,64739,64747,64754,64762, 64770,64777,64785,64793,64800,64808,64815,64822, 64830,64837,64844,64852,64859,64866,64873,64880, 64887,64895,64902,64908,64915,64922,64929,64936, 64943,64949,64956,64963,64969,64976,64982,64989, 64995,65002,65008,65015,65021,65027,65033,65040, 65046,65052,65058,65064,65070,65076,65082,65088, 65094,65099,65105,65111,65117,65122,65128,65133, 65139,65144,65150,65155,65161,65166,65171,65177, 65182,65187,65192,65197,65202,65207,65212,65217, 65222,65227,65232,65237,65242,65246,65251,65256, 65260,65265,65270,65274,65279,65283,65287,65292, 65296,65300,65305,65309,65313,65317,65321,65325, 65329,65333,65337,65341,65345,65349,65352,65356, 65360,65363,65367,65371,65374,65378,65381,65385, 65388,65391,65395,65398,65401,65404,65408,65411, 65414,65417,65420,65423,65426,65429,65431,65434, 65437,65440,65442,65445,65448,65450,65453,65455, 65458,65460,65463,65465,65467,65470,65472,65474, 65476,65478,65480,65482,65484,65486,65488,65490, 65492,65494,65496,65497,65499,65501,65502,65504, 65505,65507,65508,65510,65511,65513,65514,65515, 65516,65518,65519,65520,65521,65522,65523,65524, 65525,65526,65527,65527,65528,65529,65530,65530, 65531,65531,65532,65532,65533,65533,65534,65534, 65534,65535,65535,65535,65535,65535,65535,65535 }; int tantoangle[2049] = { 0,333772,667544,1001315,1335086,1668857,2002626,2336395, 2670163,3003929,3337694,3671457,4005219,4338979,4672736,5006492, 5340245,5673995,6007743,6341488,6675230,7008968,7342704,7676435, 8010164,8343888,8677609,9011325,9345037,9678744,10012447,10346145, 10679838,11013526,11347209,11680887,12014558,12348225,12681885,13015539, 13349187,13682829,14016464,14350092,14683714,15017328,15350936,15684536, 16018129,16351714,16685291,17018860,17352422,17685974,18019518,18353054, 18686582,19020100,19353610,19687110,20020600,20354080,20687552,21021014, 21354466,21687906,22021338,22354758,22688168,23021568,23354956,23688332, 24021698,24355052,24688396,25021726,25355046,25688352,26021648,26354930, 26688200,27021456,27354702,27687932,28021150,28354356,28687548,29020724, 29353888,29687038,30020174,30353296,30686404,31019496,31352574,31685636, 32018684,32351718,32684734,33017736,33350722,33683692,34016648,34349584, 34682508,35015412,35348300,35681172,36014028,36346868,36679688,37012492, 37345276,37678044,38010792,38343524,38676240,39008936,39341612,39674272, 40006912,40339532,40672132,41004716,41337276,41669820,42002344,42334848, 42667332,42999796,43332236,43664660,43997060,44329444,44661800,44994140, 45326456,45658752,45991028,46323280,46655512,46987720,47319908,47652072, 47984212,48316332,48648428,48980500,49312548,49644576,49976580,50308556, 50640512,50972444,51304352,51636236,51968096,52299928,52631740,52963524, 53295284,53627020,53958728,54290412,54622068,54953704,55285308,55616888, 55948444,56279972,56611472,56942948,57274396,57605816,57937212,58268576, 58599916,58931228,59262512,59593768,59924992,60256192,60587364,60918508, 61249620,61580704,61911760,62242788,62573788,62904756,63235692,63566604, 63897480,64228332,64559148,64889940,65220696,65551424,65882120,66212788, 66543420,66874024,67204600,67535136,67865648,68196120,68526568,68856984, 69187360,69517712,69848024,70178304,70508560,70838776,71168960,71499112, 71829224,72159312,72489360,72819376,73149360,73479304,73809216,74139096, 74468936,74798744,75128520,75458264,75787968,76117632,76447264,76776864, 77106424,77435952,77765440,78094888,78424304,78753688,79083032,79412336, 79741608,80070840,80400032,80729192,81058312,81387392,81716432,82045440, 82374408,82703336,83032224,83361080,83689896,84018664,84347400,84676096, 85004760,85333376,85661952,85990488,86318984,86647448,86975864,87304240, 87632576,87960872,88289128,88617344,88945520,89273648,89601736,89929792, 90257792,90585760,90913688,91241568,91569408,91897200,92224960,92552672, 92880336,93207968,93535552,93863088,94190584,94518040,94845448,95172816, 95500136,95827416,96154648,96481832,96808976,97136080,97463136,97790144, 98117112,98444032,98770904,99097736,99424520,99751256,100077944,100404592, 100731192,101057744,101384248,101710712,102037128,102363488,102689808,103016080, 103342312,103668488,103994616,104320696,104646736,104972720,105298656,105624552, 105950392,106276184,106601928,106927624,107253272,107578872,107904416,108229920, 108555368,108880768,109206120,109531416,109856664,110181872,110507016,110832120, 111157168,111482168,111807112,112132008,112456856,112781648,113106392,113431080, 113755720,114080312,114404848,114729328,115053760,115378136,115702464,116026744, 116350960,116675128,116999248,117323312,117647320,117971272,118295176,118619024, 118942816,119266560,119590248,119913880,120237456,120560984,120884456,121207864, 121531224,121854528,122177784,122500976,122824112,123147200,123470224,123793200, 124116120,124438976,124761784,125084528,125407224,125729856,126052432,126374960, 126697424,127019832,127342184,127664472,127986712,128308888,128631008,128953072, 129275080,129597024,129918912,130240744,130562520,130884232,131205888,131527480, 131849016,132170496,132491912,132813272,133134576,133455816,133776992,134098120, 134419184,134740176,135061120,135382000,135702816,136023584,136344272,136664912, 136985488,137306016,137626464,137946864,138267184,138587456,138907664,139227808, 139547904,139867920,140187888,140507776,140827616,141147392,141467104,141786752, 142106336,142425856,142745312,143064720,143384048,143703312,144022512,144341664, 144660736,144979744,145298704,145617584,145936400,146255168,146573856,146892480, 147211040,147529536,147847968,148166336,148484640,148802880,149121056,149439152, 149757200,150075168,150393072,150710912,151028688,151346400,151664048,151981616, 152299136,152616576,152933952,153251264,153568496,153885680,154202784,154519824, 154836784,155153696,155470528,155787296,156104000,156420624,156737200,157053696, 157370112,157686480,158002768,158318976,158635136,158951216,159267232,159583168, 159899040,160214848,160530592,160846256,161161840,161477376,161792832,162108208, 162423520,162738768,163053952,163369040,163684080,163999040,164313936,164628752, 164943504,165258176,165572784,165887312,166201776,166516160,166830480,167144736, 167458912,167773008,168087040,168400992,168714880,169028688,169342432,169656096, 169969696,170283216,170596672,170910032,171223344,171536576,171849728,172162800, 172475808,172788736,173101600,173414384,173727104,174039728,174352288,174664784, 174977200,175289536,175601792,175913984,176226096,176538144,176850096,177161984, 177473792,177785536,178097200,178408784,178720288,179031728,179343088,179654368, 179965568,180276704,180587744,180898720,181209616,181520448,181831184,182141856, 182452448,182762960,183073408,183383760,183694048,184004240,184314368,184624416, 184934400,185244288,185554096,185863840,186173504,186483072,186792576,187102000, 187411344,187720608,188029808,188338912,188647936,188956896,189265760,189574560, 189883264,190191904,190500448,190808928,191117312,191425632,191733872,192042016, 192350096,192658096,192966000,193273840,193581584,193889264,194196848,194504352, 194811792,195119136,195426400,195733584,196040688,196347712,196654656,196961520, 197268304,197574992,197881616,198188144,198494592,198800960,199107248,199413456, 199719584,200025616,200331584,200637456,200943248,201248960,201554576,201860128, 202165584,202470960,202776256,203081456,203386592,203691632,203996592,204301472, 204606256,204910976,205215600,205520144,205824592,206128960,206433248,206737456, 207041584,207345616,207649568,207953424,208257216,208560912,208864512,209168048, 209471488,209774832,210078112,210381296,210684384,210987408,211290336,211593184, 211895936,212198608,212501184,212803680,213106096,213408432,213710672,214012816, 214314880,214616864,214918768,215220576,215522288,215823920,216125472,216426928, 216728304,217029584,217330784,217631904,217932928,218233856,218534704,218835472, 219136144,219436720,219737216,220037632,220337952,220638192,220938336,221238384, 221538352,221838240,222138032,222437728,222737344,223036880,223336304,223635664, 223934912,224234096,224533168,224832160,225131072,225429872,225728608,226027232, 226325776,226624240,226922608,227220880,227519056,227817152,228115168,228413088, 228710912,229008640,229306288,229603840,229901312,230198688,230495968,230793152, 231090256,231387280,231684192,231981024,232277760,232574416,232870960,233167440, 233463808,233760096,234056288,234352384,234648384,234944304,235240128,235535872, 235831504,236127056,236422512,236717888,237013152,237308336,237603424,237898416, 238193328,238488144,238782864,239077488,239372016,239666464,239960816,240255072, 240549232,240843312,241137280,241431168,241724960,242018656,242312256,242605776, 242899200,243192512,243485744,243778896,244071936,244364880,244657744,244950496, 245243168,245535744,245828224,246120608,246412912,246705104,246997216,247289216, 247581136,247872960,248164688,248456320,248747856,249039296,249330640,249621904, 249913056,250204128,250495088,250785968,251076736,251367424,251658016,251948512, 252238912,252529200,252819408,253109520,253399536,253689456,253979280,254269008, 254558640,254848176,255137632,255426976,255716224,256005376,256294432,256583392, 256872256,257161024,257449696,257738272,258026752,258315136,258603424,258891600, 259179696,259467696,259755600,260043392,260331104,260618704,260906224,261193632, 261480960,261768176,262055296,262342320,262629248,262916080,263202816,263489456, 263776000,264062432,264348784,264635024,264921168,265207216,265493168,265779024, 266064784,266350448,266636000,266921472,267206832,267492096,267777264,268062336, 268347312,268632192,268916960,269201632,269486208,269770688,270055072,270339360, 270623552,270907616,271191616,271475488,271759296,272042976,272326560,272610048, 272893440,273176736,273459936,273743040,274026048,274308928,274591744,274874432, 275157024,275439520,275721920,276004224,276286432,276568512,276850528,277132416, 277414240,277695936,277977536,278259040,278540448,278821728,279102944,279384032, 279665056,279945952,280226752,280507456,280788064,281068544,281348960,281629248, 281909472,282189568,282469568,282749440,283029248,283308960,283588544,283868032, 284147424,284426720,284705920,284985024,285264000,285542912,285821696,286100384, 286378976,286657440,286935840,287214112,287492320,287770400,288048384,288326240, 288604032,288881696,289159264,289436768,289714112,289991392,290268576,290545632, 290822592,291099456,291376224,291652896,291929440,292205888,292482272,292758528, 293034656,293310720,293586656,293862496,294138240,294413888,294689440,294964864, 295240192,295515424,295790560,296065600,296340512,296615360,296890080,297164704, 297439200,297713632,297987936,298262144,298536256,298810240,299084160,299357952, 299631648,299905248,300178720,300452128,300725408,300998592,301271680,301544640, 301817536,302090304,302362976,302635520,302908000,303180352,303452608,303724768, 303996800,304268768,304540608,304812320,305083968,305355520,305626944,305898272, 306169472,306440608,306711616,306982528,307253344,307524064,307794656,308065152, 308335552,308605856,308876032,309146112,309416096,309685984,309955744,310225408, 310494976,310764448,311033824,311303072,311572224,311841280,312110208,312379040, 312647776,312916416,313184960,313453376,313721696,313989920,314258016,314526016, 314793920,315061728,315329408,315597024,315864512,316131872,316399168,316666336, 316933408,317200384,317467232,317733984,318000640,318267200,318533632,318799968, 319066208,319332352,319598368,319864288,320130112,320395808,320661408,320926912, 321192320,321457632,321722816,321987904,322252864,322517760,322782528,323047200, 323311744,323576192,323840544,324104800,324368928,324632992,324896928,325160736, 325424448,325688096,325951584,326215008,326478304,326741504,327004608,327267584, 327530464,327793248,328055904,328318496,328580960,328843296,329105568,329367712, 329629760,329891680,330153536,330415264,330676864,330938400,331199808,331461120, 331722304,331983392,332244384,332505280,332766048,333026752,333287296,333547776, 333808128,334068384,334328544,334588576,334848512,335108352,335368064,335627712, 335887200,336146624,336405920,336665120,336924224,337183200,337442112,337700864, 337959552,338218112,338476576,338734944,338993184,339251328,339509376,339767296, 340025120,340282848,340540480,340797984,341055392,341312704,341569888,341826976, 342083968,342340832,342597600,342854272,343110848,343367296,343623648,343879904, 344136032,344392064,344648000,344903808,345159520,345415136,345670656,345926048, 346181344,346436512,346691616,346946592,347201440,347456224,347710880,347965440, 348219872,348474208,348728448,348982592,349236608,349490528,349744320,349998048, 350251648,350505152,350758528,351011808,351264992,351518048,351771040,352023872, 352276640,352529280,352781824,353034272,353286592,353538816,353790944,354042944, 354294880,354546656,354798368,355049952,355301440,355552800,355804096,356055264, 356306304,356557280,356808128,357058848,357309504,357560032,357810464,358060768, 358311008,358561088,358811104,359060992,359310784,359560480,359810048,360059520, 360308896,360558144,360807296,361056352,361305312,361554144,361802880,362051488, 362300032,362548448,362796736,363044960,363293056,363541024,363788928,364036704, 364284384,364531936,364779392,365026752,365274016,365521152,365768192,366015136, 366261952,366508672,366755296,367001792,367248192,367494496,367740704,367986784, 368232768,368478656,368724416,368970080,369215648,369461088,369706432,369951680, 370196800,370441824,370686752,370931584,371176288,371420896,371665408,371909792, 372154080,372398272,372642336,372886304,373130176,373373952,373617600,373861152, 374104608,374347936,374591168,374834304,375077312,375320224,375563040,375805760, 376048352,376290848,376533248,376775520,377017696,377259776,377501728,377743584, 377985344,378227008,378468544,378709984,378951328,379192544,379433664,379674688, 379915584,380156416,380397088,380637696,380878176,381118560,381358848,381599040, 381839104,382079072,382318912,382558656,382798304,383037856,383277280,383516640, 383755840,383994976,384233984,384472896,384711712,384950400,385188992,385427488, 385665888,385904160,386142336,386380384,386618368,386856224,387093984,387331616, 387569152,387806592,388043936,388281152,388518272,388755296,388992224,389229024, 389465728,389702336,389938816,390175200,390411488,390647680,390883744,391119712, 391355584,391591328,391826976,392062528,392297984,392533312,392768544,393003680, 393238720,393473632,393708448,393943168,394177760,394412256,394646656,394880960, 395115136,395349216,395583200,395817088,396050848,396284512,396518080,396751520, 396984864,397218112,397451264,397684288,397917248,398150080,398382784,398615424, 398847936,399080320,399312640,399544832,399776928,400008928,400240832,400472608, 400704288,400935872,401167328,401398720,401629984,401861120,402092192,402323136, 402553984,402784736,403015360,403245888,403476320,403706656,403936896,404167008, 404397024,404626944,404856736,405086432,405316032,405545536,405774912,406004224, 406233408,406462464,406691456,406920320,407149088,407377760,407606336,407834784, 408063136,408291392,408519520,408747584,408975520,409203360,409431072,409658720, 409886240,410113664,410340992,410568192,410795296,411022304,411249216,411476032, 411702720,411929312,412155808,412382176,412608480,412834656,413060736,413286720, 413512576,413738336,413964000,414189568,414415040,414640384,414865632,415090784, 415315840,415540800,415765632,415990368,416215008,416439552,416663968,416888288, 417112512,417336640,417560672,417784576,418008384,418232096,418455712,418679200, 418902624,419125920,419349120,419572192,419795200,420018080,420240864,420463552, 420686144,420908608,421130976,421353280,421575424,421797504,422019488,422241344, 422463104,422684768,422906336,423127776,423349120,423570400,423791520,424012576, 424233536,424454368,424675104,424895744,425116288,425336736,425557056,425777280, 425997408,426217440,426437376,426657184,426876928,427096544,427316064,427535488, 427754784,427974016,428193120,428412128,428631040,428849856,429068544,429287168, 429505664,429724064,429942368,430160576,430378656,430596672,430814560,431032352, 431250048,431467616,431685120,431902496,432119808,432336992,432554080,432771040, 432987936,433204736,433421408,433637984,433854464,434070848,434287104,434503296, 434719360,434935360,435151232,435367008,435582656,435798240,436013696,436229088, 436444352,436659520,436874592,437089568,437304416,437519200,437733856,437948416, 438162880,438377248,438591520,438805696,439019744,439233728,439447584,439661344, 439875008,440088576,440302048,440515392,440728672,440941824,441154880,441367872, 441580736,441793472,442006144,442218720,442431168,442643552,442855808,443067968, 443280032,443492000,443703872,443915648,444127296,444338880,444550336,444761696, 444972992,445184160,445395232,445606176,445817056,446027840,446238496,446449088, 446659552,446869920,447080192,447290400,447500448,447710432,447920320,448130112, 448339776,448549376,448758848,448968224,449177536,449386720,449595808,449804800, 450013664,450222464,450431168,450639776,450848256,451056640,451264960,451473152, 451681248,451889248,452097152,452304960,452512672,452720288,452927808,453135232, 453342528,453549760,453756864,453963904,454170816,454377632,454584384,454791008, 454997536,455203968,455410304,455616544,455822688,456028704,456234656,456440512, 456646240,456851904,457057472,457262912,457468256,457673536,457878688,458083744, 458288736,458493600,458698368,458903040,459107616,459312096,459516480,459720768, 459924960,460129056,460333056,460536960,460740736,460944448,461148064,461351584, 461554976,461758304,461961536,462164640,462367680,462570592,462773440,462976160, 463178816,463381344,463583776,463786144,463988384,464190560,464392608,464594560, 464796448,464998208,465199872,465401472,465602944,465804320,466005600,466206816, 466407904,466608896,466809824,467010624,467211328,467411936,467612480,467812896, 468013216,468213440,468413600,468613632,468813568,469013440,469213184,469412832, 469612416,469811872,470011232,470210528,470409696,470608800,470807776,471006688, 471205472,471404192,471602784,471801312,471999712,472198048,472396288,472594400, 472792448,472990400,473188256,473385984,473583648,473781216,473978688,474176064, 474373344,474570528,474767616,474964608,475161504,475358336,475555040,475751648, 475948192,476144608,476340928,476537184,476733312,476929376,477125344,477321184, 477516960,477712640,477908224,478103712,478299104,478494400,478689600,478884704, 479079744,479274656,479469504,479664224,479858880,480053408,480247872,480442240, 480636512,480830656,481024736,481218752,481412640,481606432,481800128,481993760, 482187264,482380704,482574016,482767264,482960416,483153472,483346432,483539296, 483732064,483924768,484117344,484309856,484502240,484694560,484886784,485078912, 485270944,485462880,485654720,485846464,486038144,486229696,486421184,486612576, 486803840,486995040,487186176,487377184,487568096,487758912,487949664,488140320, 488330880,488521312,488711712,488901984,489092160,489282240,489472256,489662176, 489851968,490041696,490231328,490420896,490610336,490799712,490988960,491178144, 491367232,491556224,491745120,491933920,492122656,492311264,492499808,492688256, 492876608,493064864,493253056,493441120,493629120,493817024,494004832,494192544, 494380160,494567712,494755136,494942496,495129760,495316928,495504000,495691008, 495877888,496064704,496251424,496438048,496624608,496811040,496997408,497183680, 497369856,497555936,497741920,497927840,498113632,498299360,498484992,498670560, 498856000,499041376,499226656,499411840,499596928,499781920,499966848,500151680, 500336416,500521056,500705600,500890080,501074464,501258752,501442944,501627040, 501811072,501995008,502178848,502362592,502546240,502729824,502913312,503096704, 503280000,503463232,503646368,503829408,504012352,504195200,504377984,504560672, 504743264,504925760,505108192,505290496,505472736,505654912,505836960,506018944, 506200832,506382624,506564320,506745952,506927488,507108928,507290272,507471552, 507652736,507833824,508014816,508195744,508376576,508557312,508737952,508918528, 509099008,509279392,509459680,509639904,509820032,510000064,510180000,510359872, 510539648,510719328,510898944,511078432,511257856,511437216,511616448,511795616, 511974688,512153664,512332576,512511392,512690112,512868768,513047296,513225792, 513404160,513582432,513760640,513938784,514116800,514294752,514472608,514650368, 514828064,515005664,515183168,515360608,515537952,515715200,515892352,516069440, 516246432,516423328,516600160,516776896,516953536,517130112,517306592,517482976, 517659264,517835488,518011616,518187680,518363648,518539520,518715296,518891008, 519066624,519242144,519417600,519592960,519768256,519943424,520118528,520293568, 520468480,520643328,520818112,520992800,521167392,521341888,521516320,521690656, 521864896,522039072,522213152,522387168,522561056,522734912,522908640,523082304, 523255872,523429376,523602784,523776096,523949312,524122464,524295552,524468512, 524641440,524814240,524986976,525159616,525332192,525504640,525677056,525849344, 526021568,526193728,526365792,526537760,526709632,526881440,527053152,527224800, 527396352,527567840,527739200,527910528,528081728,528252864,528423936,528594880, 528765760,528936576,529107296,529277920,529448480,529618944,529789344,529959648, 530129856,530300000,530470048,530640000,530809888,530979712,531149440,531319072, 531488608,531658080,531827488,531996800,532166016,532335168,532504224,532673184, 532842080,533010912,533179616,533348288,533516832,533685312,533853728,534022048, 534190272,534358432,534526496,534694496,534862400,535030240,535197984,535365632, 535533216,535700704,535868128,536035456,536202720,536369888,536536992,536704000, 536870912 }; \ No newline at end of file diff --git a/V_VIDEO.C b/V_VIDEO.C new file mode 100644 index 0000000..5815741 --- /dev/null +++ b/V_VIDEO.C @@ -0,0 +1 @@ +// V_video.c #include "doomdef.h" #define SC_INDEX 0x3c4 byte *screens[5]; // [SCREENWIDTH*SCREENHEIGHT]; int dirtybox[4]; byte gammatable[5][256] = { {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255}, {2,4,5,7,8,10,11,12,14,15,16,18,19,20,21,23,24,25,26,27,29,30,31,32,33,34,36,37,38,39,40,41,42,44,45,46,47,48,49,50,51,52,54,55,56,57,58,59,60,61,62,63,64,65,66,67,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,163,164,165,166,167,168,169,170,171,172,173,174,175,175,176,177,178,179,180,181,182,183,184,185,186,186,187,188,189,190,191,192,193,194,195,196,196,197,198,199,200,201,202,203,204,205,205,206,207,208,209,210,211,212,213,214,214,215,216,217,218,219,220,221,222,222,223,224,225,226,227,228,229,230,230,231,232,233,234,235,236,237,237,238,239,240,241,242,243,244,245,245,246,247,248,249,250,251,252,252,253,254,255}, {4,7,9,11,13,15,17,19,21,22,24,26,27,29,30,32,33,35,36,38,39,40,42,43,45,46,47,48,50,51,52,54,55,56,57,59,60,61,62,63,65,66,67,68,69,70,72,73,74,75,76,77,78,79,80,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,133,134,135,136,137,138,139,140,141,142,143,144,144,145,146,147,148,149,150,151,152,153,153,154,155,156,157,158,159,160,160,161,162,163,164,165,166,166,167,168,169,170,171,172,172,173,174,175,176,177,178,178,179,180,181,182,183,183,184,185,186,187,188,188,189,190,191,192,193,193,194,195,196,197,197,198,199,200,201,201,202,203,204,205,206,206,207,208,209,210,210,211,212,213,213,214,215,216,217,217,218,219,220,221,221,222,223,224,224,225,226,227,228,228,229,230,231,231,232,233,234,235,235,236,237,238,238,239,240,241,241,242,243,244,244,245,246,247,247,248,249,250,251,251,252,253,254,254,255}, {8,12,16,19,22,24,27,29,31,34,36,38,40,41,43,45,47,49,50,52,53,55,57,58,60,61,63,64,65,67,68,70,71,72,74,75,76,77,79,80,81,82,84,85,86,87,88,90,91,92,93,94,95,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,135,136,137,138,139,140,141,142,143,143,144,145,146,147,148,149,150,150,151,152,153,154,155,155,156,157,158,159,160,160,161,162,163,164,165,165,166,167,168,169,169,170,171,172,173,173,174,175,176,176,177,178,179,180,180,181,182,183,183,184,185,186,186,187,188,189,189,190,191,192,192,193,194,195,195,196,197,197,198,199,200,200,201,202,202,203,204,205,205,206,207,207,208,209,210,210,211,212,212,213,214,214,215,216,216,217,218,219,219,220,221,221,222,223,223,224,225,225,226,227,227,228,229,229,230,231,231,232,233,233,234,235,235,236,237,237,238,238,239,240,240,241,242,242,243,244,244,245,246,246,247,247,248,249,249,250,251,251,252,253,253,254,254,255}, {16,23,28,32,36,39,42,45,48,50,53,55,57,60,62,64,66,68,69,71,73,75,76,78,80,81,83,84,86,87,89,90,92,93,94,96,97,98,100,101,102,103,105,106,107,108,109,110,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,128,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,143,144,145,146,147,148,149,150,150,151,152,153,154,155,155,156,157,158,159,159,160,161,162,163,163,164,165,166,166,167,168,169,169,170,171,172,172,173,174,175,175,176,177,177,178,179,180,180,181,182,182,183,184,184,185,186,187,187,188,189,189,190,191,191,192,193,193,194,195,195,196,196,197,198,198,199,200,200,201,202,202,203,203,204,205,205,206,207,207,208,208,209,210,210,211,211,212,213,213,214,214,215,216,216,217,217,218,219,219,220,220,221,221,222,223,223,224,224,225,225,226,227,227,228,228,229,229,230,230,231,232,232,233,233,234,234,235,235,236,236,237,237,238,239,239,240,240,241,241,242,242,243,243,244,244,245,245,246,246,247,247,248,248,249,249,250,250,251,251,252,252,253,254,254,255,255} }; int usegamma; /* ================== = = V_MarkRect = ================== */ void V_MarkRect (int x, int y, int width, int height) { M_AddToBox (dirtybox, x, y); M_AddToBox (dirtybox, x+width-1, y+height-1); } /* ================== = = V_CopyRect = ================== */ void V_CopyRect (int srcx, int srcy, int srcscrn, int width, int height, int destx, int desty, int destscrn) { byte *src, *dest; #ifdef RANGECHECK if (srcx<0||srcx+width >SCREENWIDTH || srcy<0 || srcy+height>SCREENHEIGHT ||destx<0||destx+width >SCREENWIDTH || desty<0 || desty+height>SCREENHEIGHT || (unsigned)srcscrn>4 || (unsigned)destscrn>4) I_Error ("Bad V_CopyRect"); #endif V_MarkRect (destx, desty, width, height); src = screens[srcscrn]+SCREENWIDTH*srcy+srcx; dest = screens[destscrn]+SCREENWIDTH*desty+destx; for ( ; height>0 ; height--) { memcpy (dest, src, width); src += SCREENWIDTH; dest += SCREENWIDTH; } } /* ================== = = V_DrawPatch = = Masks a column based masked pic to the screen. = ================== */ void V_DrawPatch (int x, int y, int scrn, patch_t *patch) { int count,col; column_t *column; byte *desttop, *dest, *source; int w; y -= SHORT(patch->topoffset); x -= SHORT(patch->leftoffset); #ifdef RANGECHECK if (x<0||x+SHORT(patch->width) >SCREENWIDTH || y<0 || y+SHORT(patch->height)>SCREENHEIGHT || (unsigned)scrn>4) I_Error ("Bad V_DrawPatch"); #endif if (!scrn) V_MarkRect (x, y, SHORT(patch->width), SHORT(patch->height)); col = 0; desttop = screens[scrn]+y*SCREENWIDTH+x; w = SHORT(patch->width); for ( ; colcolumnofs[col])); // step through the posts in a column while (column->topdelta != 0xff ) { source = (byte *)column + 3; dest = desttop + column->topdelta*SCREENWIDTH; count = column->length; while (count--) { *dest = *source++; dest += SCREENWIDTH; } column = (column_t *)( (byte *)column + column->length + 4 ); } } } /* ================== = = V_DrawPatchFlipped = = Masks a column based masked pic to the screen. = ================== */ void V_DrawPatchFlipped (int x, int y, int scrn, patch_t *patch) { int count,col; column_t *column; byte *desttop, *dest, *source; int w; y -= SHORT(patch->topoffset); x -= SHORT(patch->leftoffset); #ifdef RANGECHECK if (x<0||x+SHORT(patch->width) >SCREENWIDTH || y<0 || y+SHORT(patch->height)>SCREENHEIGHT || (unsigned)scrn>4) I_Error ("Bad V_DrawPatch"); #endif if (!scrn) V_MarkRect (x, y, SHORT(patch->width), SHORT(patch->height)); col = 0; desttop = screens[scrn]+y*SCREENWIDTH+x; w = SHORT(patch->width); for ( ; colcolumnofs[w-1-col])); // step through the posts in a column while (column->topdelta != 0xff ) { source = (byte *)column + 3; dest = desttop + column->topdelta*SCREENWIDTH; count = column->length; while (count--) { *dest = *source++; dest += SCREENWIDTH; } column = (column_t *)( (byte *)column + column->length + 4 ); } } } /* ================== = = V_DrawPatchDirect = = Draws directly to the screen on the pc ================== */ void V_DrawPatchDirect (int x, int y, int scrn, patch_t *patch) { #ifndef __WATCOMC__ V_DrawPatch (x,y,scrn, patch); #else int count,col; column_t *column; byte *desttop, *dest, *source; int w; y -= SHORT(patch->topoffset); x -= SHORT(patch->leftoffset); #ifdef RANGECHECK if (x<0||x+SHORT(patch->width) >SCREENWIDTH || y<0 || y+SHORT(patch->height)>SCREENHEIGHT || (unsigned)scrn>4) I_Error ("Bad V_DrawPatchDirect"); #endif // V_MarkRect (x, y, SHORT(patch->width), SHORT(patch->height)); desttop = destscreen + y*SCREENWIDTH/4 + (x>>2); w = SHORT(patch->width); for ( col = 0 ; colcolumnofs[col])); // step through the posts in a column while (column->topdelta != 0xff ) { source = (byte *)column + 3; dest = desttop + column->topdelta*SCREENWIDTH/4; count = column->length; while (count--) { *dest = *source++; dest += SCREENWIDTH/4; } column = (column_t *)( (byte *)column + column->length + 4 ); } if ( ((++x)&3) == 0 ) desttop++; // go to next byte, not next plane } #endif } /* =============== = = V_DrawBlock = = draw a linear block of pixels into the view buffer =============== */ void V_DrawBlock (int x, int y, int scrn, int width, int height, byte *src) { byte *dest; #ifdef RANGECHECK if (x<0||x+width >SCREENWIDTH || y<0 || y+height>SCREENHEIGHT || (unsigned)scrn>4 ) I_Error ("Bad V_DrawBlock"); #endif V_MarkRect (x, y, width, height); dest = screens[scrn] + y*SCREENWIDTH+x; while (height--) { memcpy (dest, src, width); src += width; dest += SCREENWIDTH; } } /* =============== = = V_GetBlock = = gets a linear block of pixels from the view buffer =============== */ void V_GetBlock (int x, int y, int scrn, int width, int height, byte *dest) { byte *src; #ifdef RANGECHECK if (x<0||x+width >SCREENWIDTH || y<0 || y+height>SCREENHEIGHT || (unsigned)scrn>4 ) I_Error ("Bad V_DrawBlock"); #endif src = screens[scrn] + y*SCREENWIDTH+x; while (height--) { memcpy (dest, src, width); src += SCREENWIDTH; dest += width; } } /* =============== = = V_Init = =============== */ void V_Init (void) { int i; byte *base; // stick these in low dos memory on PCs base = I_AllocLow (SCREENWIDTH*SCREENHEIGHT*4); for (i=0 ; i<4 ; i++) screens[i] = base + i*SCREENWIDTH*SCREENHEIGHT; } \ No newline at end of file diff --git a/WADREAD.C b/WADREAD.C new file mode 100644 index 0000000..bfc8786 --- /dev/null +++ b/WADREAD.C @@ -0,0 +1 @@ +#include #include #include #include #include #include #include #include #include "sndserver.h" #include "wadread.h" int *sfxlengths; typedef struct wadinfo_struct { char identification[4]; int numlumps; int infotableofs; } wadinfo_t; typedef struct filelump_struct { int filepos; int size; char name[8]; } filelump_t; typedef struct lumpinfo_struct { int handle; int filepos; int size; char name[8]; } lumpinfo_t; lumpinfo_t *lumpinfo; int numlumps; void **lumpcache; #define strcmpi strcasecmp #ifndef __BIG_ENDIAN__ #define LONG(x) (x) #define SHORT(x) (x) #else #define LONG(x) ((long)SwapLONG((unsigned long) (x))) #define SHORT(x) ((short)SwapSHORT((unsigned short) (x))) unsigned long SwapLONG(unsigned long x) { return (x>>24) | ((x>>8) & 0xff00) | ((x<<8) & 0xff0000) | (x<<24); } unsigned short SwapSHORT(unsigned short x) { return (x>>8) | (x<<8); } #endif static void derror(char *msg) { fprintf(stderr, "\nwadread error: %s\n", msg); exit(-1); } void strupr (char *s) { while (*s) *s++ = toupper(*s); } int filelength (int handle) { struct stat fileinfo; if (fstat (handle,&fileinfo) == -1) fprintf (stderr, "Error fstating\n"); return fileinfo.st_size; } void openwad(char *wadname) { int wadfile, tableoffset, tablelength, tablefilelength; int i; wadinfo_t header; filelump_t *filetable; // open and read the wadfile header wadfile = open(wadname, O_RDONLY); if (wadfile < 0) derror("Could not open wadfile"); read(wadfile, &header, sizeof header); if (strncmp(header.identification, "IWAD", 4)) derror("wadfile has weirdo header"); numlumps = LONG(header.numlumps); tableoffset = LONG(header.infotableofs); tablelength = numlumps * sizeof(lumpinfo_t); tablefilelength = numlumps * sizeof(filelump_t); lumpinfo = (lumpinfo_t *) malloc(tablelength); filetable = (filelump_t *) ((char*)lumpinfo + tablelength - tablefilelength); // get the lumpinfo table lseek(wadfile, tableoffset, SEEK_SET); read(wadfile, filetable, tablefilelength); // process the table to make the endianness right and shift it down for (i=0 ; iwidth)/2 + 32*!dofrags) #define NG_SPACINGX 64 // DEATHMATCH STUFF #define DM_MATRIXX 42 #define DM_MATRIXY 68 #define DM_SPACINGX 40 #define DM_TOTALSX 269 #define DM_KILLERSX 10 #define DM_KILLERSY 100 #define DM_VICTIMSX 5 #define DM_VICTIMSY 50 static point_t lnodes[NUMEPISODES][NUMMAPS] = { // Episode 0 World Map { { 185, 164 }, // location of level 0 (CJ) { 148, 143 }, // location of level 1 (CJ) { 69, 122 }, // location of level 2 (CJ) { 209, 102 }, // location of level 3 (CJ) { 116, 89 }, // location of level 4 (CJ) { 166, 55 }, // location of level 5 (CJ) { 71, 56 }, // location of level 6 (CJ) { 135, 29 }, // location of level 7 (CJ) { 71, 24 } // location of level 8 (CJ) }, // Episode 1 World Map should go here { { 254, 25 }, // location of level 0 (CJ) { 97, 50 }, // location of level 1 (CJ) { 188, 64 }, // location of level 2 (CJ) { 128, 78 }, // location of level 3 (CJ) { 214, 92 }, // location of level 4 (CJ) { 133, 130 }, // location of level 5 (CJ) { 208, 136 }, // location of level 6 (CJ) { 148, 140 }, // location of level 7 (CJ) { 235, 158 } // location of level 8 (CJ) }, // Episode 2 World Map should go here { { 156, 168 }, // location of level 0 (CJ) { 48, 154 }, // location of level 1 (CJ) { 174, 95 }, // location of level 2 (CJ) { 265, 75 }, // location of level 3 (CJ) { 130, 48 }, // location of level 4 (CJ) { 279, 23 }, // location of level 5 (CJ) { 198, 48 }, // location of level 6 (CJ) { 140, 25 }, // location of level 7 (CJ) { 281, 136 } // location of level 8 (CJ) } }; // animation locations for episode 0 (1) static anim_t epsd0animinfo[] = { { ANIM_ALWAYS, TICRATE/3, 3, { 224, 104 } }, { ANIM_ALWAYS, TICRATE/3, 3, { 184, 160 } }, { ANIM_ALWAYS, TICRATE/3, 3, { 112, 136 } }, { ANIM_ALWAYS, TICRATE/3, 3, { 72, 112 } }, { ANIM_ALWAYS, TICRATE/3, 3, { 88, 96 } }, { ANIM_ALWAYS, TICRATE/3, 3, { 64, 48 } }, { ANIM_ALWAYS, TICRATE/3, 3, { 192, 40 } }, { ANIM_ALWAYS, TICRATE/3, 3, { 136, 16 } }, { ANIM_ALWAYS, TICRATE/3, 3, { 80, 16 } }, { ANIM_ALWAYS, TICRATE/3, 3, { 64, 24 } } }; static anim_t epsd1animinfo[] = { { ANIM_LEVEL, TICRATE/3, 1, { 128, 136 }, 1 }, { ANIM_LEVEL, TICRATE/3, 1, { 128, 136 }, 2 }, { ANIM_LEVEL, TICRATE/3, 1, { 128, 136 }, 3 }, { ANIM_LEVEL, TICRATE/3, 1, { 128, 136 }, 4 }, { ANIM_LEVEL, TICRATE/3, 1, { 128, 136 }, 5 }, { ANIM_LEVEL, TICRATE/3, 1, { 128, 136 }, 6 }, { ANIM_LEVEL, TICRATE/3, 1, { 128, 136 }, 7 }, { ANIM_LEVEL, TICRATE/3, 3, { 192, 144 }, 8 }, { ANIM_LEVEL, TICRATE/3, 1, { 128, 136 }, 8 } }; static anim_t epsd2animinfo[] = { { ANIM_ALWAYS, TICRATE/3, 3, { 104, 168 } }, { ANIM_ALWAYS, TICRATE/3, 3, { 40, 136 } }, { ANIM_ALWAYS, TICRATE/3, 3, { 160, 96 } }, { ANIM_ALWAYS, TICRATE/3, 3, { 104, 80 } }, { ANIM_ALWAYS, TICRATE/3, 3, { 120, 32 } }, { ANIM_ALWAYS, TICRATE/4, 3, { 40, 0 } } }; static int NUMANIMS[NUMEPISODES] = { sizeof(epsd0animinfo)/sizeof(anim_t), sizeof(epsd1animinfo)/sizeof(anim_t), sizeof(epsd2animinfo)/sizeof(anim_t) }; static anim_t *anims[NUMEPISODES] = { epsd0animinfo, epsd1animinfo, epsd2animinfo }; #endif \ No newline at end of file diff --git a/WI_STUFF.C b/WI_STUFF.C new file mode 100644 index 0000000..51ab0e5 --- /dev/null +++ b/WI_STUFF.C @@ -0,0 +1 @@ +#include "wi_data.h" #include "dutils.h" #include "r_local.h" #include // // GENERAL DATA // static int acceleratestage; // used to accelerate or skip a stage static int me; // wbs->pnum static stateenum_t state; // specifies current state static wbstartstruct_t *wbs; // contains information passed into intermission static wbplayerstruct_t *plrs; // wbs->plyr[] static int cnt; // used for general timing static int bcnt; // used for timing of background animation static int firstrefresh; // signals to refresh everything for one frame static int cnt_kills[MAXPLAYERS], cnt_items[MAXPLAYERS], cnt_secret[MAXPLAYERS]; static int cnt_time, cnt_par; static int cnt_pause; static int NUMCMAPS; // # of commercial levels // GRAPHICS static patch_t *bg; // background (map of levels) static patch_t *yah[2]; // You Are Here graphic static patch_t *splat; // splat static patch_t *percent, *colon; // %, : graphics static patch_t *num[10]; // 0-9 graphic static patch_t *wiminus; // minus sign static patch_t *finished; // "Finished!" graphics static patch_t *entering; // "Entering" graphic static patch_t *sp_secret; // "secret" static patch_t *kills, *secret, *items, *frags; // "Kills", "Scrt", "Items", "Frags" static patch_t *time, *par, *sucks; static patch_t *killers, *victims; // "killers", "victims" static patch_t *total, *star, *bstar; // "Total", your face, your dead face static patch_t *p[MAXPLAYERS]; // "red P[1..MAXPLAYERS]" static patch_t *bp[MAXPLAYERS]; // "gray P[1..MAXPLAYERS]" static patch_t **lnames; // Name graphics of each level (centered) // // CODE // // slam background static unsigned char *background=0; void WI_slamBackground(void) { memcpy(screens[0], screens[1], SCREENWIDTH * SCREENHEIGHT); V_MarkRect (0, 0, SCREENWIDTH, SCREENHEIGHT); } // The ticker is used to detect keys because of timing issues in netgames boolean WI_Responder(event_t *ev) { return false; } // Draws " Finished!" void WI_drawLF(void) { int y = WI_TITLEY; // draw V_DrawPatch((SCREENWIDTH - SHORT(lnames[wbs->last]->width))/2, y, FB, lnames[wbs->last]); // draw "Finished!" y += (5*SHORT(lnames[wbs->last]->height))/4; V_DrawPatch((SCREENWIDTH - SHORT(finished->width))/2, y, FB, finished); } // draws Entering void WI_drawEL(void) { int y = WI_TITLEY; // draw "Entering" V_DrawPatch((SCREENWIDTH - SHORT(entering->width))/2, y, FB, entering); // draw level y += (5*SHORT(lnames[wbs->next]->height))/4; V_DrawPatch((SCREENWIDTH - SHORT(lnames[wbs->next]->width))/2, y, FB, lnames[wbs->next]); } void WI_drawOnLnode(int n, patch_t *c[]) { int i, left, top, right, bottom; boolean fits = false; i = 0; do { left = lnodes[wbs->epsd][n].x - SHORT(c[i]->leftoffset); top = lnodes[wbs->epsd][n].y - SHORT(c[i]->topoffset); right = left + SHORT(c[i]->width); bottom = top + SHORT(c[i]->height); if (left >= 0 && right < SCREENWIDTH && top >= 0 && bottom < SCREENHEIGHT) fits = true; else i++; } while (!fits && i!=2); if (fits && i<2) { V_DrawPatch(lnodes[wbs->epsd][n].x, lnodes[wbs->epsd][n].y, FB, c[i]); } else printf("Could not place patch on level %d", n+1); // DEBUG } void WI_initAnimatedBack(void) { int i; anim_t *a; if (commercial) return; for (i=0;iepsd];i++) { a = &anims[wbs->epsd][i]; // init variables a->ctr = -1; // specify the next time to draw it if (a->type == ANIM_ALWAYS) a->nexttic = bcnt + 1 + (M_Random()%a->period); else if (a->type == ANIM_RANDOM) a->nexttic = bcnt + 1 + a->data2+(M_Random()%a->data1); else if (a->type == ANIM_LEVEL) a->nexttic = bcnt + 1; } } void WI_updateAnimatedBack(void) { int i; anim_t *a; if (commercial) return; for (i=0;iepsd];i++) { a = &anims[wbs->epsd][i]; if (bcnt == a->nexttic) { switch (a->type) { case ANIM_ALWAYS: if (++a->ctr >= a->nanims) a->ctr = 0; a->nexttic = bcnt + a->period; break; case ANIM_RANDOM: a->ctr++; if (a->ctr == a->nanims) { a->ctr = -1; a->nexttic = bcnt+a->data2+(M_Random()%a->data1); } else a->nexttic = bcnt + a->period; break; case ANIM_LEVEL: // gawd-awful hack for level anims if (!(state == StatCount && i == 7) && wbs->next == a->data1) { a->ctr++; if (a->ctr == a->nanims) a->ctr--; a->nexttic = bcnt + a->period; } break; } } } } void WI_drawAnimatedBack(void) { int i; anim_t *a; if (commercial) return; for (i=0 ; iepsd] ; i++) { a = &anims[wbs->epsd][i]; if (a->ctr >= 0) V_DrawPatch(a->loc.x, a->loc.y, FB, a->p[a->ctr]); } } // // draws a number. if digits > 0, then use that many digits minimum, // otherwise only use as many as necessary. Returns new x position. // int WI_drawNum(int x, int y, int n, int digits) { int fontwidth = SHORT(num[0]->width); int neg; int temp; if (digits < 0) { if (!n) digits = 1; // make variable-length 0's 1 digit long else { // figure out # of digits in # digits = 0; temp = n; while (temp) { temp /= 10; digits++; } } } neg = n < 0; if (neg) n = -n; // if non-number, don't draw it if (n == 1994) return 0; // draw the new number while (digits--) { x -= fontwidth; V_DrawPatch(x, y, FB, num[ n % 10 ]); n /= 10; } // draw a minus sign if necessary if (neg) V_DrawPatch(x-=8, y, FB, wiminus); return x; } void WI_drawPercent(int x, int y, int p) { if (p < 0) return; V_DrawPatch(x, y, FB, percent); WI_drawNum(x, y, p, -1); } void WI_drawTime(int x, int y, int t) { int div, n; if (t<0) return; if (t <= 61*59) { div = 1; do { n = (t / div) % 60; x = WI_drawNum(x, y, n, 2) - SHORT(colon->width); div *= 60; if (div==60 || t / div) V_DrawPatch(x, y, FB, colon); // draw } while (t / div); } else V_DrawPatch(x - SHORT(sucks->width), y, FB, sucks); // "sucks" } void WI_End(void) { void WI_unloadData(void); WI_unloadData(); } void WI_initNoState(void) { state = NoState; acceleratestage = 0; cnt = 10; } void WI_updateNoState(void) { WI_updateAnimatedBack(); if (!--cnt) { WI_End(); G_WorldDone(); } } static boolean snl_pointeron = false; void WI_initShowNextLoc(void) { state = ShowNextLoc; acceleratestage = 0; cnt = SHOWNEXTLOCDELAY * TICRATE; WI_initAnimatedBack(); } void WI_updateShowNextLoc(void) { WI_updateAnimatedBack(); if (!--cnt || acceleratestage) WI_initNoState(); else snl_pointeron = (cnt & 31) < 20; } void WI_drawShowNextLoc(void) { int i, last; WI_slamBackground(); WI_drawAnimatedBack(); // draw animated background if (!commercial) { last = (wbs->last == 8) ? wbs->next - 1 : wbs->last; for (i=0 ; i<=last ; i++) WI_drawOnLnode(i, &splat); // draw a splat on taken cities. if (wbs->didsecret) WI_drawOnLnode(8, &splat); // splat the secret level if (snl_pointeron) WI_drawOnLnode(wbs->next, yah); // draw flashing ptr } if (!commercial || wbs->next != 30) WI_drawEL(); // draws which level you're entering.. } void WI_drawNoState(void) { snl_pointeron = true; WI_drawShowNextLoc(); } int WI_fragSum(int playernum) { int i, frags = 0; for (i=0 ; i 99) dm_frags[i][j] = 99; if (dm_frags[i][j] < -99) dm_frags[i][j] = -99; stillticking = true; } dm_totals[i] = WI_fragSum(i); if (dm_totals[i] > 99) dm_totals[i] = 99; if (dm_totals[i] < -99) dm_totals[i] = -99; } if (!stillticking) { S_StartSound(0, sfx_barexp); dm_state++; } } else if (dm_state == 4) { if (acceleratestage) { S_StartSound(0, sfx_slop); if (commercial) WI_initNoState(); else WI_initShowNextLoc(); } } else if (dm_state & 1) { if (!--cnt_pause) { dm_state++; cnt_pause = TICRATE; } } } void WI_drawDeathmatchStats(void) { int i, j, x, y, w; int lh; // line height lh = WI_SPACINGY; WI_slamBackground(); WI_drawAnimatedBack(); // draw animated background WI_drawLF(); // draw stat titles (top line) V_DrawPatch(DM_TOTALSX-SHORT(total->width)/2, DM_MATRIXY-WI_SPACINGY+10, FB, total); V_DrawPatch(DM_KILLERSX, DM_KILLERSY, FB, killers); V_DrawPatch(DM_VICTIMSX, DM_VICTIMSY, FB, victims); // draw P?'s. x = DM_MATRIXX + DM_SPACINGX; y = DM_MATRIXY; for (i=0 ; iwidth)/2, DM_MATRIXY - WI_SPACINGY, FB, p[i]); V_DrawPatch(DM_MATRIXX-SHORT(p[i]->width)/2, y, FB, p[i]); if (i == me) { V_DrawPatch(x-SHORT(p[i]->width)/2, DM_MATRIXY - WI_SPACINGY, FB, bstar); V_DrawPatch(DM_MATRIXX-SHORT(p[i]->width)/2, y, FB, star); } } else { // V_DrawPatch(x-SHORT(bp[i]->width)/2, DM_MATRIXY - WI_SPACINGY, FB, bp[i]); // V_DrawPatch(DM_MATRIXX-SHORT(bp[i]->width)/2, y, FB, bp[i]); } x += DM_SPACINGX; y += WI_SPACINGY; } // draw stats y = DM_MATRIXY+10; w = SHORT(num[0]->width); for (i=0 ; imaxkills; cnt_items[i] = (plrs[i].sitems * 100) / wbs->maxitems; cnt_secret[i] = (plrs[i].ssecret * 100) / wbs->maxsecret; if (dofrags) cnt_frags[i] = WI_fragSum(i); } S_StartSound(0, sfx_barexp); ng_state = 10; } if (ng_state == 2) { if (!(bcnt&3)) S_StartSound(0, sfx_pistol); stillticking = false; for (i=0 ; i= (plrs[i].skills * 100) / wbs->maxkills) cnt_kills[i] = (plrs[i].skills * 100) / wbs->maxkills; else stillticking = true; } if (!stillticking) { S_StartSound(0, sfx_barexp); ng_state++; } } else if (ng_state == 4) { if (!(bcnt&3)) S_StartSound(0, sfx_pistol); stillticking = false; for (i=0 ; i= (plrs[i].sitems * 100) / wbs->maxitems) cnt_items[i] = (plrs[i].sitems * 100) / wbs->maxitems; else stillticking = true; } if (!stillticking) { S_StartSound(0, sfx_barexp); ng_state++; } } else if (ng_state == 6) { if (!(bcnt&3)) S_StartSound(0, sfx_pistol); stillticking = false; for (i=0 ; i= (plrs[i].ssecret * 100) / wbs->maxsecret) cnt_secret[i] = (plrs[i].ssecret * 100) / wbs->maxsecret; else stillticking = true; } if (!stillticking) { S_StartSound(0, sfx_barexp); ng_state += 1 + 2*!dofrags; } } else if (ng_state == 8) { if (!(bcnt&3)) S_StartSound(0, sfx_pistol); stillticking = false; for (i=0 ; i= (fsum = WI_fragSum(i))) cnt_frags[i] = fsum; else stillticking = true; } if (!stillticking) { S_StartSound(0, sfx_pldeth); ng_state++; } } else if (ng_state == 10) { if (acceleratestage) { S_StartSound(0, sfx_sgcock); if (commercial) WI_initNoState(); else WI_initShowNextLoc(); } } else if (ng_state & 1) { if (!--cnt_pause) { ng_state++; cnt_pause = TICRATE; } } } void WI_drawNetgameStats(void) { int i, x, y, pwidth = SHORT(percent->width); WI_slamBackground(); WI_drawAnimatedBack(); // draw animated background WI_drawLF(); // draw stat titles (top line) V_DrawPatch(NG_STATSX+NG_SPACINGX-SHORT(kills->width), NG_STATSY, FB, kills); V_DrawPatch(NG_STATSX+2*NG_SPACINGX-SHORT(items->width), NG_STATSY, FB, items); V_DrawPatch(NG_STATSX+3*NG_SPACINGX-SHORT(secret->width), NG_STATSY, FB, secret); if (dofrags) V_DrawPatch(NG_STATSX+4*NG_SPACINGX-SHORT(frags->width), NG_STATSY, FB, frags); // draw stats y = NG_STATSY + SHORT(kills->height); for (i=0 ; iwidth), y, FB, p[i]); if (i == me) V_DrawPatch(x-SHORT(p[i]->width), y, FB, star); x += NG_SPACINGX; WI_drawPercent(x-pwidth, y+10, cnt_kills[i]); x += NG_SPACINGX; WI_drawPercent(x-pwidth, y+10, cnt_items[i]); x += NG_SPACINGX; WI_drawPercent(x-pwidth, y+10, cnt_secret[i]); x += NG_SPACINGX; if (dofrags) WI_drawNum(x, y+10, cnt_frags[i], -1); y += WI_SPACINGY; } } static int sp_state; void WI_initStats(void) { state = StatCount; acceleratestage = 0; sp_state = 1; cnt_kills[0] = cnt_items[0] = cnt_secret[0] = -1; cnt_time = cnt_par = -1; cnt_pause = TICRATE; WI_initAnimatedBack(); } void WI_updateStats(void) { WI_updateAnimatedBack(); if (acceleratestage && sp_state != 10) { acceleratestage = 0; cnt_kills[0] = (plrs[me].skills * 100) / wbs->maxkills; cnt_items[0] = (plrs[me].sitems * 100) / wbs->maxitems; cnt_secret[0] = (plrs[me].ssecret * 100) / wbs->maxsecret; cnt_time = plrs[me].stime / TICRATE; cnt_par = wbs->partime / TICRATE; S_StartSound(0, sfx_barexp); sp_state = 10; } if (sp_state == 2) { cnt_kills[0] += 2; if (!(bcnt&3)) S_StartSound(0, sfx_pistol); if (cnt_kills[0] >= (plrs[me].skills * 100) / wbs->maxkills) { cnt_kills[0] = (plrs[me].skills * 100) / wbs->maxkills; S_StartSound(0, sfx_barexp); sp_state++; } } else if (sp_state == 4) { cnt_items[0] += 2; if (!(bcnt&3)) S_StartSound(0, sfx_pistol); if (cnt_items[0] >= (plrs[me].sitems * 100) / wbs->maxitems) { cnt_items[0] = (plrs[me].sitems * 100) / wbs->maxitems; S_StartSound(0, sfx_barexp); sp_state++; } } else if (sp_state == 6) { cnt_secret[0] += 2; if (!(bcnt&3)) S_StartSound(0, sfx_pistol); if (cnt_secret[0] >= (plrs[me].ssecret * 100) / wbs->maxsecret) { cnt_secret[0] = (plrs[me].ssecret * 100) / wbs->maxsecret; S_StartSound(0, sfx_barexp); sp_state++; } } else if (sp_state == 8) { if (!(bcnt&3)) S_StartSound(0, sfx_pistol); cnt_time += 3; if (cnt_time >= plrs[me].stime / TICRATE) cnt_time = plrs[me].stime / TICRATE; cnt_par += 3; if (cnt_par >= wbs->partime / TICRATE) { cnt_par = wbs->partime / TICRATE; if (cnt_time >= plrs[me].stime / TICRATE) { S_StartSound(0, sfx_barexp); sp_state++; } } } else if (sp_state == 10) { if (acceleratestage) { S_StartSound(0, sfx_sgcock); if (commercial) WI_initNoState(); else WI_initShowNextLoc(); } } else if (sp_state & 1) { if (!--cnt_pause) { sp_state++; cnt_pause = TICRATE; } } } void WI_drawStats(void) { int lh; // line height lh = (3*SHORT(num[0]->height))/2; WI_slamBackground(); WI_drawAnimatedBack(); // draw animated background WI_drawLF(); V_DrawPatch(SP_STATSX, SP_STATSY, FB, kills); WI_drawPercent(SCREENWIDTH - SP_STATSX, SP_STATSY, cnt_kills[0]); V_DrawPatch(SP_STATSX, SP_STATSY+lh, FB, items); WI_drawPercent(SCREENWIDTH - SP_STATSX, SP_STATSY+lh, cnt_items[0]); V_DrawPatch(SP_STATSX, SP_STATSY+2*lh, FB, sp_secret); WI_drawPercent(SCREENWIDTH - SP_STATSX, SP_STATSY+2*lh, cnt_secret[0]); V_DrawPatch(SP_TIMEX, SP_TIMEY, FB, time); WI_drawTime(SCREENWIDTH/2 - SP_TIMEX, SP_TIMEY, cnt_time); V_DrawPatch(SCREENWIDTH/2 + SP_TIMEX, SP_TIMEY, FB, par); WI_drawTime(SCREENWIDTH - SP_TIMEX, SP_TIMEY, cnt_par); } void WI_checkForAccelerate(void) { int i; player_t *player; // check for button presses to skip delays for (i=0, player = players ; icmd.buttons & BT_ATTACK) { if (!player->attackdown) acceleratestage = 1; player->attackdown = true; } else player->attackdown = false; if (player->cmd.buttons & BT_USE) { if (!player->usedown) acceleratestage = 1; player->usedown = true; } else player->usedown = false; } } // Updates stuff each tick void WI_Ticker(void) { bcnt++; // counter for general background animation if (bcnt == 1) { commercial ? S_ChangeMusic(mus_dm2int, true): S_ChangeMusic(mus_inter, true); // intermission music } WI_checkForAccelerate(); switch (state) { case StatCount: if (deathmatch) WI_updateDeathmatchStats(); else if (netgame) WI_updateNetgameStats(); else WI_updateStats(); break; case ShowNextLoc: WI_updateShowNextLoc(); break; case NoState: WI_updateNoState(); break; } } void WI_loadData(void) { int i, j; char name[9]; anim_t *a; unsigned char *pic = screens[1]; if (commercial) strcpy(name, "INTERPIC"); else sprintf(name, "WIMAP%d", wbs->epsd); bg = W_CacheLumpName(name, PU_CACHE); // background V_DrawPatch(0, 0, 1, bg); /* if (commercial) // if (0) { // darken the background image while (pic != screens[1] + SCREENHEIGHT*SCREENWIDTH) { *pic = colormaps[256*25 + *pic]; pic++; } } */ if (commercial) { #if 0 int level_start; level_start = GetNumForName("CLVSTART")+1; NUMCMAPS = W_GetNumForName("CLVEND") - level_start + 1; lnames = (patch_t **) Z_Malloc(sizeof(patch_t*) * NUMCMAPS, PU_STATIC, 0); for (i=0 ; iepsd, i); lnames[i] = W_CacheLumpName(name, PU_STATIC); } yah[0] = W_CacheLumpName("WIURH0", PU_STATIC); // you are here yah[1] = W_CacheLumpName("WIURH1", PU_STATIC); // you are here (alt.) splat = W_CacheLumpName("WISPLAT", PU_STATIC); // splat for (j=0;jepsd];j++) { a = &anims[wbs->epsd][j]; for (i=0;inanims;i++) { if (wbs->epsd != 1 || j != 8) // MONDO HACK! { sprintf(name, "WIA%d%.2d%.2d", wbs->epsd, j, i); // animations a->p[i] = W_CacheLumpName(name, PU_STATIC); } else { a->p[i] = anims[1][4].p[i]; // HACK ALERT! } } } } wiminus = W_CacheLumpName("WIMINUS", PU_STATIC); // minus sign for (i=0;i<10;i++) { sprintf(name, "WINUM%d", i); // numbers 0-9 num[i] = W_CacheLumpName(name, PU_STATIC); } percent = W_CacheLumpName("WIPCNT", PU_STATIC); // percent sign finished = W_CacheLumpName("WIF", PU_STATIC); // "finished" entering = W_CacheLumpName("WIENTER", PU_STATIC); // "entering" kills = W_CacheLumpName("WIOSTK", PU_STATIC); // "kills" secret = W_CacheLumpName("WIOSTS", PU_STATIC); // "scrt" sp_secret = W_CacheLumpName("WISCRT2", PU_STATIC); // "secret" if (french) { if (netgame && !deathmatch) items = W_CacheLumpName("WIOBJ", PU_STATIC); // "items" else items = W_CacheLumpName("WIOSTI", PU_STATIC); // "items" } else items = W_CacheLumpName("WIOSTI", PU_STATIC); // "items" frags = W_CacheLumpName("WIFRGS", PU_STATIC); // "frgs" colon = W_CacheLumpName("WICOLON", PU_STATIC); // ":" time = W_CacheLumpName("WITIME", PU_STATIC); // "time" sucks = W_CacheLumpName("WISUCKS", PU_STATIC); // "sucks" par = W_CacheLumpName("WIPAR", PU_STATIC); // "par" killers = W_CacheLumpName("WIKILRS", PU_STATIC); // "killers" (vertical) victims = W_CacheLumpName("WIVCTMS", PU_STATIC); // "victims" (horiz) total = W_CacheLumpName("WIMSTT", PU_STATIC); // "total" star = W_CacheLumpName("STFST01", PU_STATIC); // your face bstar = W_CacheLumpName("STFDEAD0", PU_STATIC); // dead face for (i=0 ; iepsd];j++) { if (wbs->epsd != 1 || j != 8) for (i=0;iepsd][j].nanims;i++) Z_ChangeTag(anims[wbs->epsd][j].p[i], PU_CACHE); } } Z_Free(lnames); Z_ChangeTag(percent, PU_CACHE); Z_ChangeTag(colon, PU_CACHE); Z_ChangeTag(finished, PU_CACHE); Z_ChangeTag(entering, PU_CACHE); Z_ChangeTag(kills, PU_CACHE); Z_ChangeTag(secret, PU_CACHE); Z_ChangeTag(sp_secret, PU_CACHE); Z_ChangeTag(items, PU_CACHE); Z_ChangeTag(frags, PU_CACHE); Z_ChangeTag(time, PU_CACHE); Z_ChangeTag(sucks, PU_CACHE); Z_ChangeTag(par, PU_CACHE); Z_ChangeTag(victims, PU_CACHE); Z_ChangeTag(killers, PU_CACHE); Z_ChangeTag(total, PU_CACHE); // Z_ChangeTag(star, PU_CACHE); // Z_ChangeTag(bstar, PU_CACHE); for (i=0 ; iepsd, 0, 2); RNGCHECK(wbs->last, 0, 8); RNGCHECK(wbs->next, 0, 8); } RNGCHECK(wbs->pnum, 0, MAXPLAYERS); RNGCHECK(wbs->pnum, 0, MAXPLAYERS); #endif acceleratestage = 0; cnt = bcnt = 0; firstrefresh = 1; me = wbs->pnum; plrs = wbs->plyr; if (!wbs->maxkills) wbs->maxkills = 1; if (!wbs->maxitems) wbs->maxitems = 1; if (!wbs->maxsecret) wbs->maxsecret = 1; if (wbs->epsd > 2) wbs->epsd -= 3; } void WI_Start(wbstartstruct_t *wbstartstruct) { WI_initVariables(wbstartstruct); WI_loadData(); if (deathmatch) WI_initDeathmatchStats(); else if (netgame) WI_initNetgameStats(); else WI_initStats(); } \ No newline at end of file diff --git a/WI_STUFF.H b/WI_STUFF.H new file mode 100644 index 0000000..e2e1024 --- /dev/null +++ b/WI_STUFF.H @@ -0,0 +1 @@ +#ifndef __WBSTUFF__ #define __WBSTUFF__ #include "doomdef.h" #define NUMEPISODES 3 #define NUMMAPS 9 #define PAUSELEN (TICRATE*2) // in tics #define SCORESTEP 100 #define SHOWNEXTLOCDELAY 4 // in seconds #define SHOWLASTLOCDELAY SHOWNEXTLOCDELAY // in seconds #define ANIMPERIOD 32 // in tics #define STARDIST 10 // pixel distance from "(YOU)" to "PLAYER N" #define FB 0 #define WK 1 // States for the intermission typedef enum { NoState = -1, StatCount, ShowNextLoc } stateenum_t; // States for single-player #define SP_KILLS 0 #define SP_ITEMS 2 #define SP_SECRET 4 #define SP_FRAGS 6 #define SP_TIME 8 #define SP_PAR ST_TIME #define SP_PAUSE 1 typedef struct { int x, y; } point_t; typedef enum { ANIM_ALWAYS, ANIM_RANDOM, ANIM_LEVEL } animenum_t; typedef struct { animenum_t type; int period; // period in tics between animations int nanims; // number of animation frames point_t loc;// location of animation int data1; // ALWAYS: n/a, RANDOM: period deviation (<256), LEVEL: level int data2; // ALWAYS: n/a, RANDOM: random base period, LEVEL: n/a patch_t *p[3]; // actual graphics for frames of animations // following must be initialized to zero before use! int nexttic;// next value of bcnt (used in conjunction with period) int lastdrawn; // last drawn animation frame int ctr; // next frame number to animate int state; // used by RANDOM and LEVEL when animating } anim_t; #endif \ No newline at end of file diff --git a/W_WAD.C b/W_WAD.C new file mode 100644 index 0000000..96c08e1 --- /dev/null +++ b/W_WAD.C @@ -0,0 +1 @@ +// W_wad.c #ifdef NeXT #include #include // next doesn't need a binary flag in open call #define O_BINARY 0 #endif #ifdef __WATCOMC__ #include #include #include #include #endif #ifdef NORMALUNIX #include #include #include #include #define O_BINARY 0 #endif #include "doomdef.h" //=============== // TYPES //=============== typedef struct { char identification[4]; // should be IWAD int numlumps; int infotableofs; } wadinfo_t; typedef struct { int filepos; int size; char name[8]; } filelump_t; //============= // GLOBALS //============= lumpinfo_t *lumpinfo; // location of each lump on disk int numlumps; void **lumpcache; //=================== #ifndef __WATCOMC__ #define strcmpi strcasecmp void strupr (char *s) { while (*s) { *s = toupper(*s); s++; } } /* ================ = = filelength = ================ */ int filelength (int handle) { struct stat fileinfo; if (fstat (handle,&fileinfo) == -1) I_Error ("Error fstating"); return fileinfo.st_size; } #endif void ExtractFileBase (char *path, char *dest) { char *src; int length; src = path + strlen(path) - 1; // // back up until a \ or the start // while (src != path && *(src-1) != '\\' && *(src-1) != '/') src--; // // copy up to eight characters // memset (dest,0,8); length = 0; while (*src && *src != '.') { if (++length == 9) I_Error ("Filename base of %s >8 chars",path); *dest++ = toupper((int)*src++); } } /* ============================================================================ LUMP BASED ROUTINES ============================================================================ */ /* ==================== = = W_AddFile = = All files are optional, but at least one file must be found = Files with a .wad extension are wadlink files with multiple lumps = Other files are single lumps with the base filename for the lump name = = If filename starts with a tilde, the file is handled specialy to = allow map reloads ==================== */ // the reload feature is a fragile hack... int reloadlump; char *reloadname; void W_AddFile (char *filename) { wadinfo_t header; lumpinfo_t *lump_p; unsigned i; int handle, length; int startlump; filelump_t *fileinfo, singleinfo; int storehandle; // // open the file and add to directory // if (filename[0] == '~') { filename++; reloadname = filename; reloadlump = numlumps; } if ( (handle = open (filename,O_RDONLY | O_BINARY)) == -1) { printf (" couldn't open %s\n",filename); return; } printf (" adding %s\n",filename); startlump = numlumps; if (strcmpi (filename+strlen(filename)-3 , "wad" ) ) { // single lump file fileinfo = &singleinfo; singleinfo.filepos = 0; singleinfo.size = LONG(filelength(handle)); ExtractFileBase (filename, singleinfo.name); numlumps++; } else { // WAD file read (handle, &header, sizeof(header)); if (strncmp(header.identification,"IWAD",4)) { if (strncmp(header.identification,"PWAD",4)) I_Error ("Wad file %s doesn't have IWAD or PWAD id\n" ,filename); modifiedgame = true; // homebrew levels } header.numlumps = LONG(header.numlumps); header.infotableofs = LONG(header.infotableofs); length = header.numlumps*sizeof(filelump_t); fileinfo = alloca (length); lseek (handle, header.infotableofs, SEEK_SET); read (handle, fileinfo, length); numlumps += header.numlumps; } // // Fill in lumpinfo // lumpinfo = realloc (lumpinfo, numlumps*sizeof(lumpinfo_t)); if (!lumpinfo) I_Error ("Couldn't realloc lumpinfo"); lump_p = &lumpinfo[startlump]; storehandle = reloadname ? -1 : handle; for (i=startlump ; ihandle = storehandle; lump_p->position = LONG(fileinfo->filepos); lump_p->size = LONG(fileinfo->size); strncpy (lump_p->name, fileinfo->name, 8); } if (reloadname) close (handle); } /* ==================== = = W_Reload = = Flushes any of the reloadable lumps in memory and reloads the directory ==================== */ void W_Reload (void) { wadinfo_t header; int lumpcount; lumpinfo_t *lump_p; unsigned i; int handle, length; filelump_t *fileinfo; if (!reloadname) return; if ( (handle = open (reloadname,O_RDONLY | O_BINARY)) == -1) I_Error ("W_Reload: couldn't open %s",reloadname); read (handle, &header, sizeof(header)); lumpcount = LONG(header.numlumps); header.infotableofs = LONG(header.infotableofs); length = lumpcount*sizeof(filelump_t); fileinfo = alloca (length); lseek (handle, header.infotableofs, SEEK_SET); read (handle, fileinfo, length); // // Fill in lumpinfo // lump_p = &lumpinfo[reloadlump]; for (i=reloadlump ; iposition = LONG(fileinfo->filepos); lump_p->size = LONG(fileinfo->size); } close (handle); } /* ==================== = = W_InitMultipleFiles = = Pass a null terminated list of files to use. = = All files are optional, but at least one file must be found = = Files with a .wad extension are idlink files with multiple lumps = = Other files are single lumps with the base filename for the lump name = = Lump names can appear multiple times. The name searcher looks backwards, = so a later file can override an earlier one. = ==================== */ void W_InitMultipleFiles (char **filenames) { int size; // // open all the files, load headers, and count lumps // numlumps = 0; lumpinfo = malloc(1); // will be realloced as lumps are added for ( ; *filenames ; filenames++) W_AddFile (*filenames); if (!numlumps) I_Error ("W_InitFiles: no files found"); // // set up caching // size = numlumps * sizeof(*lumpcache); lumpcache = malloc (size); if (!lumpcache) I_Error ("Couldn't allocate lumpcache"); memset (lumpcache,0, size); } /* ==================== = = W_InitFile = = Just initialize from a single file = ==================== */ void W_InitFile (char *filename) { char *names[2]; names[0] = filename; names[1] = NULL; W_InitMultipleFiles (names); } /* ==================== = = W_NumLumps = ==================== */ int W_NumLumps (void) { return numlumps; } /* ==================== = = W_CheckNumForName = = Returns -1 if name not found = ==================== */ int W_CheckNumForName (char *name) { union { char s[9]; int x[2]; } name8; int v1,v2; lumpinfo_t *lump_p; // make the name into two integers for easy compares strncpy (name8.s,name,8); name8.s[8] = 0; // in case the name was a fill 8 chars strupr (name8.s); // case insensitive v1 = name8.x[0]; v2 = name8.x[1]; // scan backwards so patch lump files take precedence lump_p = lumpinfo + numlumps; while (lump_p-- != lumpinfo) if ( *(int *)lump_p->name == v1 && *(int *)&lump_p->name[4] == v2) return lump_p - lumpinfo; return -1; } /* ==================== = = W_GetNumForName = = Calls W_CheckNumForName, but bombs out if not found = ==================== */ int W_GetNumForName (char *name) { int i; i = W_CheckNumForName (name); if (i != -1) return i; I_Error ("W_GetNumForName: %s not found!",name); return -1; } /* ==================== = = W_LumpLength = = Returns the buffer size needed to load the given lump = ==================== */ int W_LumpLength (int lump) { if (lump >= numlumps) I_Error ("W_LumpLength: %i >= numlumps",lump); return lumpinfo[lump].size; } /* ==================== = = W_ReadLump = = Loads the lump into the given buffer, which must be >= W_LumpLength() = ==================== */ void W_ReadLump (int lump, void *dest) { int c; lumpinfo_t *l; int handle; if (lump >= numlumps) I_Error ("W_ReadLump: %i >= numlumps",lump); l = lumpinfo+lump; I_BeginRead (); if (l->handle == -1) { // reloadable file, so use open / read / close if ( (handle = open (reloadname,O_RDONLY | O_BINARY)) == -1) I_Error ("W_ReadLump: couldn't open %s",reloadname); } else handle = l->handle; lseek (handle, l->position, SEEK_SET); c = read (handle, dest, l->size); if (c < l->size) I_Error ("W_ReadLump: only read %i of %i on lump %i",c,l->size,lump); if (l->handle == -1) close (handle); I_EndRead (); } /* ==================== = = W_CacheLumpNum = ==================== */ void *W_CacheLumpNum (int lump, int tag) { byte *ptr; if ((unsigned)lump >= numlumps) I_Error ("W_CacheLumpNum: %i >= numlumps",lump); if (!lumpcache[lump]) { // read the lump in //printf ("cache miss on lump %i\n",lump); ptr = Z_Malloc (W_LumpLength (lump), tag, &lumpcache[lump]); W_ReadLump (lump, lumpcache[lump]); } else { //printf ("cache hit on lump %i\n",lump); Z_ChangeTag (lumpcache[lump],tag); } return lumpcache[lump]; } /* ==================== = = W_CacheLumpName = ==================== */ void *W_CacheLumpName (char *name, int tag) { return W_CacheLumpNum (W_GetNumForName(name), tag); } /* ==================== = = W_Profile = ==================== */ int info[2500][10]; int profilecount; void W_Profile (void) { int i; memblock_t *block; void *ptr; char ch; FILE *f; int j; char name[9]; for (i=0 ; itag < PU_PURGELEVEL) ch = 'S'; else ch = 'P'; } info[i][profilecount] = ch; } profilecount++; f = fopen ("waddump.txt","w"); name[8] = 0; for (i=0 ; i #include "doomdef.h" /* ============================================================================== ZONE MEMORY ALLOCATION There is never any space between memblocks, and there will never be two contiguous free memblocks. The rover can be left pointing at a non-empty block It is of no value to free a cachable block, because it will get overwritten automatically if needed ============================================================================== */ #define ZONEID 0x1d4a11 typedef struct { int size; // total bytes malloced, including header memblock_t blocklist; // start / end cap for linked list memblock_t *rover; } memzone_t; memzone_t *mainzone; /* ======================== = = Z_ClearZone = ======================== */ void Z_ClearZone (memzone_t *zone) { memblock_t *block; // set the entire zone to one free block zone->blocklist.next = zone->blocklist.prev = block = (memblock_t *)( (byte *)zone + sizeof(memzone_t) ); zone->blocklist.user = (void *)zone; zone->blocklist.tag = PU_STATIC; zone->rover = block; block->prev = block->next = &zone->blocklist; block->user = NULL; // free block block->size = zone->size - sizeof(memzone_t); } /* ======================== = = Z_Init = ======================== */ void Z_Init (void) { memblock_t *block; int size; mainzone = (memzone_t *)I_ZoneBase (&size); mainzone->size = size; // set the entire zone to one free block mainzone->blocklist.next = mainzone->blocklist.prev = block = (memblock_t *)( (byte *)mainzone + sizeof(memzone_t) ); mainzone->blocklist.user = (void *)mainzone; mainzone->blocklist.tag = PU_STATIC; mainzone->rover = block; block->prev = block->next = &mainzone->blocklist; block->user = NULL; // free block block->size = mainzone->size - sizeof(memzone_t); } /* ======================== = = Z_Free = ======================== */ void Z_Free (void *ptr) { memblock_t *block, *other; block = (memblock_t *) ( (byte *)ptr - sizeof(memblock_t)); if (block->id != ZONEID) I_Error ("Z_Free: freed a pointer without ZONEID"); if (block->user > (void **)0x100) // smaller values are not pointers *block->user = 0; // clear the user's mark block->user = NULL; // mark as free block->tag = 0; block->id = 0; other = block->prev; if (!other->user) { // merge with previous free block other->size += block->size; other->next = block->next; other->next->prev = other; if (block == mainzone->rover) mainzone->rover = other; block = other; } other = block->next; if (!other->user) { // merge the next free block onto the end block->size += other->size; block->next = other->next; block->next->prev = block; if (other == mainzone->rover) mainzone->rover = block; } } /* ======================== = = Z_Malloc = = You can pass a NULL user if the tag is < PU_PURGELEVEL ======================== */ #define MINFRAGMENT 64 void *Z_Malloc (int size, int tag, void *user) { int extra; memblock_t *start, *rover, *newblock, *base; size = (size + 3) & ~3; // // scan through the block list looking for the first free block // of sufficient size, throwing out any purgable blocks along the way // size += sizeof(memblock_t); // account for size of block header // // if there is a free block behind the rover, back up over them // base = mainzone->rover; if (!base->prev->user) base = base->prev; rover = base; start = base->prev; do { if (rover == start) // scaned all the way around the list I_Error ("Z_Malloc: failed on allocation of %i bytes",size); if (rover->user) { if (rover->tag < PU_PURGELEVEL) // hit a block that can't be purged, so move base past it base = rover = rover->next; else { // free the rover block (adding the size to base) base = base->prev; // the rover can be the base block Z_Free ((byte *)rover+sizeof(memblock_t)); base = base->next; rover = base->next; } } else rover = rover->next; } while (base->user || base->size < size); // // found a block big enough // extra = base->size - size; if (extra > MINFRAGMENT) { // there will be a free fragment after the allocated block newblock = (memblock_t *) ((byte *)base + size ); newblock->size = extra; newblock->user = NULL; // free block newblock->tag = 0; newblock->prev = base; newblock->next = base->next; newblock->next->prev = newblock; base->next = newblock; base->size = size; } if (user) { base->user = user; // mark as an in use block *(void **)user = (void *) ((byte *)base + sizeof(memblock_t)); } else { if (tag >= PU_PURGELEVEL) I_Error ("Z_Malloc: an owner is required for purgable blocks"); base->user = (void *)2; // mark as in use, but unowned } base->tag = tag; mainzone->rover = base->next; // next allocation will start looking here base->id = ZONEID; return (void *) ((byte *)base + sizeof(memblock_t)); } /* ======================== = = Z_FreeTags = ======================== */ void Z_FreeTags (int lowtag, int hightag) { memblock_t *block, *next; for (block = mainzone->blocklist.next ; block != &mainzone->blocklist ; block = next) { next = block->next; // get link before freeing if (!block->user) continue; // free block if (block->tag >= lowtag && block->tag <= hightag) Z_Free ( (byte *)block+sizeof(memblock_t)); } } /* ======================== = = Z_DumpHeap = ======================== */ void Z_DumpHeap (int lowtag, int hightag) { memblock_t *block; printf ("zone size: %i location: %p\n",mainzone->size,mainzone); printf ("tag range: %i to %i\n",lowtag, hightag); for (block = mainzone->blocklist.next ; ; block = block->next) { if (block->tag >= lowtag && block->tag <= hightag) printf ("block:%p size:%7i user:%p tag:%3i\n", block, block->size, block->user, block->tag); if (block->next == &mainzone->blocklist) break; // all blocks have been hit if ( (byte *)block + block->size != (byte *)block->next) printf ("ERROR: block size does not touch the next block\n"); if ( block->next->prev != block) printf ("ERROR: next block doesn't have proper back link\n"); if (!block->user && !block->next->user) printf ("ERROR: two consecutive free blocks\n"); } } /* ======================== = = Z_FileDumpHeap = ======================== */ void Z_FileDumpHeap (FILE *f) { memblock_t *block; fprintf (f,"zone size: %i location: %p\n",mainzone->size,mainzone); for (block = mainzone->blocklist.next ; ; block = block->next) { fprintf (f,"block:%p size:%7i user:%p tag:%3i\n", block, block->size, block->user, block->tag); if (block->next == &mainzone->blocklist) break; // all blocks have been hit if ( (byte *)block + block->size != (byte *)block->next) fprintf (f,"ERROR: block size does not touch the next block\n"); if ( block->next->prev != block) fprintf (f,"ERROR: next block doesn't have proper back link\n"); if (!block->user && !block->next->user) fprintf (f,"ERROR: two consecutive free blocks\n"); } } /* ======================== = = Z_CheckHeap = ======================== */ void Z_CheckHeap (void) { memblock_t *block; for (block = mainzone->blocklist.next ; ; block = block->next) { if (block->next == &mainzone->blocklist) break; // all blocks have been hit if ( (byte *)block + block->size != (byte *)block->next) I_Error ("Z_CheckHeap: block size does not touch the next block\n"); if ( block->next->prev != block) I_Error ("Z_CheckHeap: next block doesn't have proper back link\n"); if (!block->user && !block->next->user) I_Error ("Z_CheckHeap: two consecutive free blocks\n"); } } /* ======================== = = Z_ChangeTag = ======================== */ void Z_ChangeTag2 (void *ptr, int tag) { memblock_t *block; block = (memblock_t *) ( (byte *)ptr - sizeof(memblock_t)); if (block->id != ZONEID) I_Error ("Z_ChangeTag: freed a pointer without ZONEID"); if (tag >= PU_PURGELEVEL && (unsigned)block->user < 0x100) I_Error ("Z_ChangeTag: an owner is required for purgable blocks"); block->tag = tag; } /* ======================== = = Z_FreeMemory = ======================== */ int Z_FreeMemory (void) { memblock_t *block; int free; free = 0; for (block = mainzone->blocklist.next ; block != &mainzone->blocklist ; block = block->next) if (!block->user || block->tag >= PU_PURGELEVEL) free += block->size; return free; } \ No newline at end of file