ref: c137d2ad74b9b46c93411ce7fcae6d7041777d07
parent: 8cca9182aef2badfe25cdfe19451903c4016eec0
author: Simon Howard <[email protected]>
date: Sat Sep 6 14:32:11 EDT 2008
Move doom-specific files to a separate directory. Subversion-branch: /branches/raven-branch Subversion-revision: 1201
--- a/configure.in
+++ b/configure.in
@@ -79,6 +79,7 @@
setup/Makefile
man/Makefile
src/Makefile
+src/doom/Makefile
src/heretic/Makefile
src/hexen/Makefile
pcsound/Makefile
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,11 +1,11 @@
-SUBDIRS=heretic hexen
+SUBDIRS=doom heretic hexen
gamesdir = $(prefix)/games
games_PROGRAMS = chocolate-doom chocolate-server
-AM_CFLAGS = -I../textscreen -I../pcsound @SDL_CFLAGS@ @SDLMIXER_CFLAGS@ @SDLNET_CFLAGS@
+AM_CFLAGS = -Idoom -I../textscreen -I../pcsound @SDL_CFLAGS@ @SDLMIXER_CFLAGS@ @SDLNET_CFLAGS@
DEDSERV_FILES=\
d_dedicated.c \
@@ -26,31 +26,13 @@
chocolate_server_LDADD = @LDFLAGS@ @SDL_LIBS@ @SDLNET_LIBS@
MAIN_SOURCE_FILES=\
-am_map.c am_map.h \
-d_englsh.h \
-d_event.h \
-d_items.c d_items.h \
-d_iwad.c d_iwad.h \
-d_main.c d_main.h \
-d_net.c d_net.h \
-doomdata.h \
-doomdef.c doomdef.h \
+ d_event.h \
doomkeys.h \
doomfeatures.h \
-doomstat.c doomstat.h \
doomtype.h \
-d_player.h \
-dstrings.c dstrings.h \
-d_textur.h \
-d_think.h \
d_ticcmd.h \
-f_finale.c f_finale.h \
f_wipe.c f_wipe.h \
-g_game.c g_game.h \
-hu_lib.c hu_lib.h \
-hu_stuff.c hu_stuff.h \
i_main.c \
-info.c info.h \
i_joystick.c i_joystick.h \
i_scale.c i_scale.h \
i_swap.h \
@@ -62,49 +44,13 @@
m_cheat.c m_cheat.h \
m_config.c m_config.h \
m_fixed.c m_fixed.h \
-m_menu.c m_menu.h \
m_misc.c m_misc.h \
md5.c md5.h \
memio.c memio.h \
m_random.c m_random.h \
-p_ceilng.c \
-p_doors.c \
-p_enemy.c \
-p_floor.c \
-p_inter.c p_inter.h \
-p_lights.c \
-p_local.h \
-p_map.c \
-p_maputl.c \
-p_mobj.c p_mobj.h \
-p_plats.c \
-p_pspr.c p_pspr.h \
-p_saveg.c p_saveg.h \
-p_setup.c p_setup.h \
-p_sight.c \
-p_spec.c p_spec.h \
-p_switch.c \
-p_telept.c \
-p_tick.c p_tick.h \
-p_user.c \
-r_bsp.c r_bsp.h \
-r_data.c r_data.h \
-r_defs.h \
-r_draw.c r_draw.h \
-r_local.h \
-r_main.c r_main.h \
-r_plane.c r_plane.h \
-r_segs.c r_segs.h \
-r_sky.c r_sky.h \
-r_state.h \
-r_things.c r_things.h \
-sounds.c sounds.h \
s_sound.c s_sound.h \
-st_lib.c st_lib.h \
-st_stuff.c st_stuff.h \
tables.c tables.h \
v_video.c v_video.h \
-wi_stuff.c wi_stuff.h \
w_checksum.c w_checksum.h \
w_wad.c w_wad.h \
w_file.c w_file.h \
@@ -171,7 +117,13 @@
chocolate_doom_SOURCES=$(SOURCE_FILES)
endif
-chocolate_doom_LDADD = ../textscreen/libtextscreen.a ../pcsound/libpcsound.a @LDFLAGS@ @SDL_LIBS@ @SDLMIXER_LIBS@ @SDLNET_LIBS@
+chocolate_doom_LDADD = doom/libdoom.a \
+ ../textscreen/libtextscreen.a \
+ ../pcsound/libpcsound.a \
+ @LDFLAGS@ \
+ @SDL_LIBS@ \
+ @SDLMIXER_LIBS@ \
+ @SDLNET_LIBS@
EXTRA_DIST = \
icon.c \
--- a/src/am_map.c
+++ /dev/null
@@ -1,1373 +1,0 @@
-// Emacs style mode select -*- C++ -*-
-//-----------------------------------------------------------------------------
-//
-// Copyright(C) 1993-1996 Id Software, Inc.
-// Copyright(C) 2005 Simon Howard
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-// 02111-1307, USA.
-//
-//
-// DESCRIPTION: the automap code
-//
-//-----------------------------------------------------------------------------
-
-
-#include <stdio.h>
-
-#include "deh_main.h"
-
-#include "z_zone.h"
-#include "doomdef.h"
-#include "st_stuff.h"
-#include "p_local.h"
-#include "w_wad.h"
-
-#include "m_cheat.h"
-#include "i_system.h"
-
-// Needs access to LFB.
-#include "v_video.h"
-
-// State.
-#include "doomstat.h"
-#include "r_state.h"
-
-// Data.
-#include "dstrings.h"
-
-#include "am_map.h"
-
-
-// For use if I do walls with outsides/insides
-#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
-
-// 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;
-
-
-
-//
-// The vector graphics for the automap.
-// A line drawing of the player pointing right,
-// starting from the middle.
-//
-#define R ((8*PLAYERRADIUS)/7)
-mline_t player_arrow[] = {
- { { -R+R/8, 0 }, { R, 0 } }, // -----
- { { R, 0 }, { R-R/2, R/4 } }, // ----->
- { { R, 0 }, { R-R/2, -R/4 } },
- { { -R+R/8, 0 }, { -R-R/8, R/4 } }, // >---->
- { { -R+R/8, 0 }, { -R-R/8, -R/4 } },
- { { -R+3*R/8, 0 }, { -R+R/8, R/4 } }, // >>--->
- { { -R+3*R/8, 0 }, { -R+R/8, -R/4 } }
-};
-#undef R
-
-#define R ((8*PLAYERRADIUS)/7)
-mline_t cheat_player_arrow[] = {
- { { -R+R/8, 0 }, { R, 0 } }, // -----
- { { R, 0 }, { R-R/2, R/6 } }, // ----->
- { { R, 0 }, { R-R/2, -R/6 } },
- { { -R+R/8, 0 }, { -R-R/8, R/6 } }, // >----->
- { { -R+R/8, 0 }, { -R-R/8, -R/6 } },
- { { -R+3*R/8, 0 }, { -R+R/8, R/6 } }, // >>----->
- { { -R+3*R/8, 0 }, { -R+R/8, -R/6 } },
- { { -R/2, 0 }, { -R/2, -R/6 } }, // >>-d--->
- { { -R/2, -R/6 }, { -R/2+R/6, -R/6 } },
- { { -R/2+R/6, -R/6 }, { -R/2+R/6, R/4 } },
- { { -R/6, 0 }, { -R/6, -R/6 } }, // >>-dd-->
- { { -R/6, -R/6 }, { 0, -R/6 } },
- { { 0, -R/6 }, { 0, R/4 } },
- { { R/6, R/4 }, { R/6, -R/7 } }, // >>-ddt->
- { { R/6, -R/7 }, { R/6+R/32, -R/7-R/32 } },
- { { R/6+R/32, -R/7-R/32 }, { R/6+R/10, -R/7 } }
-};
-#undef R
-
-#define R (FRACUNIT)
-mline_t triangle_guy[] = {
- { { (fixed_t)(-.867*R), (fixed_t)(-.5*R) }, { (fixed_t)(.867*R ), (fixed_t)(-.5*R) } },
- { { (fixed_t)(.867*R ), (fixed_t)(-.5*R) }, { (fixed_t)(0 ), (fixed_t)(R ) } },
- { { (fixed_t)(0 ), (fixed_t)(R ) }, { (fixed_t)(-.867*R), (fixed_t)(-.5*R) } }
-};
-#undef R
-
-#define R (FRACUNIT)
-mline_t thintriangle_guy[] = {
- { { (fixed_t)(-.5*R), (fixed_t)(-.7*R) }, { (fixed_t)(R ), (fixed_t)(0 ) } },
- { { (fixed_t)(R ), (fixed_t)(0 ) }, { (fixed_t)(-.5*R), (fixed_t)(.7*R ) } },
- { { (fixed_t)(-.5*R), (fixed_t)(.7*R ) }, { (fixed_t)(-.5*R), (fixed_t)(-.7*R) } }
-};
-#undef R
-
-
-
-
-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;
-
-// location of window on screen
-static int f_x;
-static int f_y;
-
-// size of window on screen
-static int f_w;
-static int f_h;
-
-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;
-static fixed_t m_h;
-
-// based on level size
-static fixed_t min_x;
-static fixed_t min_y;
-static fixed_t max_x;
-static fixed_t max_y;
-
-static fixed_t max_w; // max_x-min_x,
-static fixed_t max_h; // max_y-min_y
-
-// based on player size
-static fixed_t min_w;
-static fixed_t min_h;
-
-
-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 = (fixed_t)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
-
-cheatseq_t cheat_amap = CHEAT("iddt", 0);
-
-static boolean stopped = true;
-
-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?-INT_MAX:INT_MAX);
- else is->islp = FixedDiv(dx, dy);
- if (!dx) is->slp = (dy<0?-INT_MAX:INT_MAX);
- 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<<FRACBITS, m_w);
- scale_ftom = FixedDiv(FRACUNIT, scale_mtof);
-}
-
-//
-// adds a marker at the current location
-//
-void AM_addMark(void)
-{
- markpoints[markpointnum].x = m_x + m_w/2;
- markpoints[markpointnum].y = m_y + m_h/2;
- markpointnum = (markpointnum + 1) % AM_NUMMARKPOINTS;
-
-}
-
-//
-// Determines bounding box of all vertices,
-// sets global variables controlling zoom range.
-//
-void AM_findMinMaxBoundaries(void)
-{
- int i;
- fixed_t a;
- fixed_t b;
-
- min_x = min_y = INT_MAX;
- max_x = max_y = -INT_MAX;
-
- for (i=0;i<numvertexes;i++)
- {
- if (vertexes[i].x < min_x)
- min_x = vertexes[i].x;
- else if (vertexes[i].x > 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; // const? never changed?
- min_h = 2*PLAYERRADIUS;
-
- a = FixedDiv(f_w<<FRACBITS, max_w);
- b = FixedDiv(f_h<<FRACBITS, max_h);
-
- min_scale_mtof = a < b ? a : b;
- max_scale_mtof = FixedDiv(f_h<<FRACBITS, 2*PLAYERRADIUS);
-
-}
-
-
-//
-//
-//
-void AM_changeWindowLoc(void)
-{
- if (m_paninc.x || m_paninc.y)
- {
- followplayer = 0;
- f_oldloc.x = INT_MAX;
- }
-
- m_x += m_paninc.x;
- m_y += m_paninc.y;
-
- if (m_x + m_w/2 > 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, 0, 0 };
-
- automapactive = true;
- fb = screens[0];
-
- f_oldloc.x = INT_MAX;
- 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[consoleplayer])
- {
- plr = &players[consoleplayer];
- }
- else
- {
- plr = &players[0];
-
- for (pnum=0;pnum<MAXPLAYERS;pnum++)
- {
- if (playeringame[pnum])
- {
- plr = &players[pnum];
- break;
- }
- }
- }
-
- m_x = plr->mo->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, DEH_String("AMMNUM%d"), i);
- marknums[i] = W_CacheLumpName(namebuf, PU_STATIC);
- }
-
-}
-
-void AM_unloadPics(void)
-{
- int i;
- char namebuf[9];
-
- for (i=0;i<10;i++)
- {
- sprintf(namebuf, DEH_String("AMMNUM%d"), i);
- W_ReleaseLumpName(namebuf);
- }
-}
-
-void AM_clearMarks(void)
-{
- int i;
-
- for (i=0;i<AM_NUMMARKPOINTS;i++)
- markpoints[i].x = -1; // means empty
- markpointnum = 0;
-}
-
-//
-// should be called at the start of every level
-// right now, i figure it out myself
-//
-void AM_LevelInit(void)
-{
- leveljuststarted = 0;
-
- f_x = f_y = 0;
- f_w = finit_width;
- f_h = finit_height;
-
- AM_clearMarks();
-
- AM_findMinMaxBoundaries();
- scale_mtof = FixedDiv(min_scale_mtof, (int) (0.7*FRACUNIT));
- if (scale_mtof > max_scale_mtof)
- scale_mtof = min_scale_mtof;
- scale_ftom = FixedDiv(FRACUNIT, scale_mtof);
-}
-
-
-
-
-//
-//
-//
-void AM_Stop (void)
-{
- static event_t st_notify = { 0, ev_keyup, AM_MSGEXITED, 0 };
-
- 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();
-}
-
-
-//
-// Handle events (user inputs) in automap mode
-//
-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 = INT_MAX;
- if (followplayer)
- plr->message = DEH_String(AMSTR_FOLLOWON);
- else
- plr->message = DEH_String(AMSTR_FOLLOWOFF);
- break;
- case AM_GRIDKEY:
- grid = !grid;
- if (grid)
- plr->message = DEH_String(AMSTR_GRIDON);
- else
- plr->message = DEH_String(AMSTR_GRIDOFF);
- break;
- case AM_MARKKEY:
- sprintf(buffer, "%s %d", DEH_String(AMSTR_MARKEDSPOT), markpointnum);
- plr->message = buffer;
- AM_addMark();
- break;
- case AM_CLEARMARKKEY:
- AM_clearMarks();
- plr->message = DEH_String(AMSTR_MARKSCLEARED);
- break;
- default:
- cheatstate=0;
- rc = false;
- }
- if (!deathmatch && cht_CheckCheat(&cheat_amap, ev->data2))
- {
- 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;
-
-}
-
-
-//
-// Zooming
-//
-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_x2 = m_x + m_w;
- m_y2 = m_y + m_h;
- 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;
-
- }
-
-}
-
-//
-//
-//
-void AM_updateLightLev(void)
-{
- static int 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 == arrlen(litelevels)) litelevelscnt = 0;
- nexttic = amclock + 6 - (amclock % 6);
- }
-
-}
-
-
-//
-// Updates on Game Tick
-//
-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();
-
-}
-
-
-//
-// Clear automap frame buffer.
-//
-void AM_clearFB(int color)
-{
- memset(fb, color, f_w*f_h);
-}
-
-
-//
-// Automap clipping of lines.
-//
-// Based on Cohen-Sutherland clipping algorithm but with a slightly
-// faster reject and precalculated slopes. If the speed is needed,
-// use a hash algorithm to handle the common cases.
-//
-boolean
-AM_clipMline
-( mline_t* ml,
- fline_t* fl )
-{
- enum
- {
- LEFT =1,
- RIGHT =2,
- BOTTOM =4,
- TOP =8
- };
-
- register int outcode1 = 0;
- register int outcode2 = 0;
- register int outside;
-
- fpoint_t tmp;
- int dx;
- int 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;
- }
- else
- {
- tmp.x = 0;
- tmp.y = 0;
- }
-
- if (outside == outcode1)
- {
- fl->a = tmp;
- DOOUTCODE(outcode1, fl->a.x, fl->a.y);
- }
- else
- {
- fl->b = tmp;
- DOOUTCODE(outcode2, fl->b.x, fl->b.y);
- }
-
- if (outcode1 & outcode2)
- return false; // trivially outside
- }
-
- return true;
-}
-#undef DOOUTCODE
-
-
-//
-// Classic Bresenham w/ whatever optimizations needed for speed
-//
-void
-AM_drawFline
-( fline_t* fl,
- int color )
-{
- register int x;
- register int y;
- register int dx;
- register int dy;
- register int sx;
- register int sy;
- register int ax;
- register int ay;
- register int d;
-
- static int fuck = 0;
-
- // For debugging only
- if ( fl->a.x < 0 || fl->a.x >= 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, DEH_String("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;
- }
- }
-}
-
-
-//
-// Clip lines, draw visible part sof lines.
-//
-void
-AM_drawMline
-( mline_t* ml,
- int color )
-{
- static fline_t fl;
-
- if (AM_clipMline(ml, &fl))
- AM_drawFline(&fl, color); // draws it on frame buffer using fb coords
-}
-
-
-
-//
-// Draws flat (floor/ceiling tile) aligned grid lines.
-//
-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<<FRACBITS))
- start += (MAPBLOCKUNITS<<FRACBITS)
- - ((start-bmaporgx)%(MAPBLOCKUNITS<<FRACBITS));
- end = m_x + m_w;
-
- // draw vertical gridlines
- ml.a.y = m_y;
- ml.b.y = m_y+m_h;
- for (x=start; x<end; x+=(MAPBLOCKUNITS<<FRACBITS))
- {
- ml.a.x = x;
- ml.b.x = x;
- AM_drawMline(&ml, color);
- }
-
- // Figure out start of horizontal gridlines
- start = m_y;
- if ((start-bmaporgy)%(MAPBLOCKUNITS<<FRACBITS))
- start += (MAPBLOCKUNITS<<FRACBITS)
- - ((start-bmaporgy)%(MAPBLOCKUNITS<<FRACBITS));
- end = m_y + m_h;
-
- // draw horizontal gridlines
- ml.a.x = m_x;
- ml.b.x = m_x + m_w;
- for (y=start; y<end; y+=(MAPBLOCKUNITS<<FRACBITS))
- {
- ml.a.y = y;
- ml.b.y = y;
- AM_drawMline(&ml, color);
- }
-
-}
-
-//
-// Determines visible lines, draws them.
-// This is LineDef based, not LineSeg based.
-//
-void AM_drawWalls(void)
-{
- int i;
- static mline_t l;
-
- for (i=0;i<numlines;i++)
- {
- l.a.x = lines[i].v1->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);
- }
- }
-}
-
-
-//
-// Rotation in 2D.
-// Used to rotate player arrow line character.
-//
-void
-AM_rotate
-( fixed_t* x,
- fixed_t* y,
- angle_t a )
-{
- fixed_t tmpx;
-
- tmpx =
- FixedMul(*x,finecosine[a>>ANGLETOFINESHIFT])
- - FixedMul(*y,finesine[a>>ANGLETOFINESHIFT]);
-
- *y =
- FixedMul(*x,finesine[a>>ANGLETOFINESHIFT])
- + FixedMul(*y,finecosine[a>>ANGLETOFINESHIFT]);
-
- *x = tmpx;
-}
-
-void
-AM_drawLineCharacter
-( mline_t* lineguy,
- int lineguylines,
- fixed_t scale,
- angle_t angle,
- int color,
- fixed_t x,
- fixed_t y )
-{
- int i;
- mline_t l;
-
- for (i=0;i<lineguylines;i++)
- {
- l.a.x = lineguy[i].a.x;
- l.a.y = lineguy[i].a.y;
-
- if (scale)
- {
- l.a.x = FixedMul(scale, l.a.x);
- l.a.y = FixedMul(scale, l.a.y);
- }
-
- if (angle)
- AM_rotate(&l.a.x, &l.a.y, angle);
-
- l.a.x += x;
- l.a.y += y;
-
- l.b.x = lineguy[i].b.x;
- l.b.y = lineguy[i].b.y;
-
- if (scale)
- {
- l.b.x = FixedMul(scale, l.b.x);
- l.b.y = FixedMul(scale, l.b.y);
- }
-
- if (angle)
- AM_rotate(&l.b.x, &l.b.y, angle);
-
- l.b.x += x;
- l.b.y += y;
-
- AM_drawMline(&l, color);
- }
-}
-
-void AM_drawPlayers(void)
-{
- int i;
- player_t* p;
- static int their_colors[] = { GREENS, GRAYS, BROWNS, REDS };
- int their_color = -1;
- int color;
-
- if (!netgame)
- {
- if (cheating)
- AM_drawLineCharacter
- (cheat_player_arrow, arrlen(cheat_player_arrow), 0,
- plr->mo->angle, WHITE, plr->mo->x, plr->mo->y);
- else
- AM_drawLineCharacter
- (player_arrow, arrlen(player_arrow), 0, plr->mo->angle,
- WHITE, plr->mo->x, plr->mo->y);
- return;
- }
-
- for (i=0;i<MAXPLAYERS;i++)
- {
- their_color++;
- p = &players[i];
-
- if ( (deathmatch && !singledemo) && p != plr)
- continue;
-
- if (!playeringame[i])
- continue;
-
- if (p->powers[pw_invisibility])
- color = 246; // *close* to black
- else
- color = their_colors[their_color];
-
- AM_drawLineCharacter
- (player_arrow, arrlen(player_arrow), 0, p->mo->angle,
- color, p->mo->x, p->mo->y);
- }
-
-}
-
-void
-AM_drawThings
-( int colors,
- int colorrange)
-{
- int i;
- mobj_t* t;
-
- for (i=0;i<numsectors;i++)
- {
- t = sectors[i].thinglist;
- while (t)
- {
- AM_drawLineCharacter
- (thintriangle_guy, arrlen(thintriangle_guy),
- 16<<FRACBITS, t->angle, colors+lightlev, t->x, t->y);
- t = t->snext;
- }
- }
-}
-
-void AM_drawMarks(void)
-{
- int i, fx, fy, w, h;
-
- for (i=0;i<AM_NUMMARKPOINTS;i++)
- {
- if (markpoints[i].x != -1)
- {
- // w = SHORT(marknums[i]->width);
- // 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);
-
-}
--- a/src/am_map.h
+++ /dev/null
@@ -1,57 +1,0 @@
-// Emacs style mode select -*- C++ -*-
-//-----------------------------------------------------------------------------
-//
-// Copyright(C) 1993-1996 Id Software, Inc.
-// Copyright(C) 2005 Simon Howard
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-// 02111-1307, USA.
-//
-// DESCRIPTION:
-// AutoMap module.
-//
-//-----------------------------------------------------------------------------
-
-#ifndef __AMMAP_H__
-#define __AMMAP_H__
-
-#include "d_event.h"
-#include "m_cheat.h"
-
-// Used by ST StatusBar stuff.
-#define AM_MSGHEADER (('a'<<24)+('m'<<16))
-#define AM_MSGENTERED (AM_MSGHEADER | ('e'<<8))
-#define AM_MSGEXITED (AM_MSGHEADER | ('x'<<8))
-
-
-// Called by main loop.
-boolean AM_Responder (event_t* ev);
-
-// Called by main loop.
-void AM_Ticker (void);
-
-// Called by main loop,
-// called instead of view drawer if automap active.
-void AM_Drawer (void);
-
-// Called to force the automap to quit
-// if the level is completed while it is up.
-void AM_Stop (void);
-
-
-extern cheatseq_t cheat_amap;
-
-
-#endif
--- a/src/d_englsh.h
+++ /dev/null
@@ -1,701 +1,0 @@
-// Emacs style mode select -*- C++ -*-
-//-----------------------------------------------------------------------------
-//
-// Copyright(C) 1993-1996 Id Software, Inc.
-// Copyright(C) 2005 Simon Howard
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-// 02111-1307, USA.
-//
-// DESCRIPTION:
-// Printed strings for translation.
-// English language support (default).
-//
-//-----------------------------------------------------------------------------
-
-#ifndef __D_ENGLSH__
-#define __D_ENGLSH__
-
-//
-// 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
-
-#define DOSY "(press y to quit to dos.)"
-
-#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_E4M1 "E4M1: Hell Beneath"
-#define HUSTR_E4M2 "E4M2: Perfect Hatred"
-#define HUSTR_E4M3 "E4M3: Sever The Wicked"
-#define HUSTR_E4M4 "E4M4: Unruly Evil"
-#define HUSTR_E4M5 "E4M5: They Will Repent"
-#define HUSTR_E4M6 "E4M6: Against Thee Wickedly"
-#define HUSTR_E4M7 "E4M7: And Hell Followed"
-#define HUSTR_E4M8 "E4M8: Unto The Cruel"
-#define HUSTR_E4M9 "E4M9: Fear"
-
-#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 PHUSTR_1 "level 1: congo"
-#define PHUSTR_2 "level 2: well of souls"
-#define PHUSTR_3 "level 3: aztec"
-#define PHUSTR_4 "level 4: caged"
-#define PHUSTR_5 "level 5: ghost town"
-#define PHUSTR_6 "level 6: baron's lair"
-#define PHUSTR_7 "level 7: caughtyard"
-#define PHUSTR_8 "level 8: realm"
-#define PHUSTR_9 "level 9: abattoire"
-#define PHUSTR_10 "level 10: onslaught"
-#define PHUSTR_11 "level 11: hunted"
-
-#define PHUSTR_12 "level 12: speed"
-#define PHUSTR_13 "level 13: the crypt"
-#define PHUSTR_14 "level 14: genesis"
-#define PHUSTR_15 "level 15: the twilight"
-#define PHUSTR_16 "level 16: the omen"
-#define PHUSTR_17 "level 17: compound"
-#define PHUSTR_18 "level 18: neurosphere"
-#define PHUSTR_19 "level 19: nme"
-#define PHUSTR_20 "level 20: the death domain"
-
-#define PHUSTR_21 "level 21: slayer"
-#define PHUSTR_22 "level 22: impossible mission"
-#define PHUSTR_23 "level 23: tombstone"
-#define PHUSTR_24 "level 24: the final frontier"
-#define PHUSTR_25 "level 25: the temple of darkness"
-#define PHUSTR_26 "level 26: bunker"
-#define PHUSTR_27 "level 27: anti-christ"
-#define PHUSTR_28 "level 28: the sewers"
-#define PHUSTR_29 "level 29: odyssey of noises"
-#define PHUSTR_30 "level 30: the gateway of hell"
-
-#define PHUSTR_31 "level 31: cyberden"
-#define PHUSTR_32 "level 32: go 2 it"
-
-#define THUSTR_1 "level 1: system control"
-#define THUSTR_2 "level 2: human bbq"
-#define THUSTR_3 "level 3: power control"
-#define THUSTR_4 "level 4: wormhole"
-#define THUSTR_5 "level 5: hanger"
-#define THUSTR_6 "level 6: open season"
-#define THUSTR_7 "level 7: prison"
-#define THUSTR_8 "level 8: metal"
-#define THUSTR_9 "level 9: stronghold"
-#define THUSTR_10 "level 10: redemption"
-#define THUSTR_11 "level 11: storage facility"
-
-#define THUSTR_12 "level 12: crater"
-#define THUSTR_13 "level 13: nukage processing"
-#define THUSTR_14 "level 14: steel works"
-#define THUSTR_15 "level 15: dead zone"
-#define THUSTR_16 "level 16: deepest reaches"
-#define THUSTR_17 "level 17: processing area"
-#define THUSTR_18 "level 18: mill"
-#define THUSTR_19 "level 19: shipping/respawning"
-#define THUSTR_20 "level 20: central processing"
-
-#define THUSTR_21 "level 21: administration center"
-#define THUSTR_22 "level 22: habitat"
-#define THUSTR_23 "level 23: lunar mining project"
-#define THUSTR_24 "level 24: quarry"
-#define THUSTR_25 "level 25: baron's den"
-#define THUSTR_26 "level 26: ballistyx"
-#define THUSTR_27 "level 27: mount pain"
-#define THUSTR_28 "level 28: heck"
-#define THUSTR_29 "level 29: river styx"
-#define THUSTR_30 "level 30: last call"
-
-#define THUSTR_31 "level 31: pharaoh"
-#define THUSTR_32 "level 32: caribbean"
-
-#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 ..."
-
-
-#define E4TEXT \
-"the spider mastermind must have sent forth\n"\
-"its legions of hellspawn before your\n"\
-"final confrontation with that terrible\n"\
-"beast from hell. but you stepped forward\n"\
-"and brought forth eternal damnation and\n"\
-"suffering upon the horde as a true hero\n"\
-"would in the face of something so evil.\n"\
-"\n"\
-"besides, someone was gonna pay for what\n"\
-"happened to daisy, your pet rabbit.\n"\
-"\n"\
-"but now, you see spread before you more\n"\
-"potential pain and gibbitude as a nation\n"\
-"of demons run amok among our cities.\n"\
-"\n"\
-"next stop, hell on earth!"
-
-
-// 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"
-
-
-// after map 06
-
-#define P1TEXT \
-"You gloat over the steaming carcass of the\n"\
-"Guardian. With its death, you've wrested\n"\
-"the Accelerator from the stinking claws\n"\
-"of Hell. You relax and glance around the\n"\
-"room. Damn! There was supposed to be at\n"\
-"least one working prototype, but you can't\n"\
-"see it. The demons must have taken it.\n"\
-"\n"\
-"You must find the prototype, or all your\n"\
-"struggles will have been wasted. Keep\n"\
-"moving, keep fighting, keep killing.\n"\
-"Oh yes, keep living, too."
-
-
-// after map 11
-
-#define P2TEXT \
-"Even the deadly Arch-Vile labyrinth could\n"\
-"not stop you, and you've gotten to the\n"\
-"prototype Accelerator which is soon\n"\
-"efficiently and permanently deactivated.\n"\
-"\n"\
-"You're good at that kind of thing."
-
-
-// after map 20
-
-#define P3TEXT \
-"You've bashed and battered your way into\n"\
-"the heart of the devil-hive. Time for a\n"\
-"Search-and-Destroy mission, aimed at the\n"\
-"Gatekeeper, whose foul offspring is\n"\
-"cascading to Earth. Yeah, he's bad. But\n"\
-"you know who's worse!\n"\
-"\n"\
-"Grinning evilly, you check your gear, and\n"\
-"get ready to give the bastard a little Hell\n"\
-"of your own making!"
-
-// after map 30
-
-#define P4TEXT \
-"The Gatekeeper's evil face is splattered\n"\
-"all over the place. As its tattered corpse\n"\
-"collapses, an inverted Gate forms and\n"\
-"sucks down the shards of the last\n"\
-"prototype Accelerator, not to mention the\n"\
-"few remaining demons. You're done. Hell\n"\
-"has gone back to pounding bad dead folks \n"\
-"instead of good live ones. Remember to\n"\
-"tell your grandkids to put a rocket\n"\
-"launcher in your coffin. If you go to Hell\n"\
-"when you die, you'll need it for some\n"\
-"final cleaning-up ..."
-
-// before map 31
-
-#define P5TEXT \
-"You've found the second-hardest level we\n"\
-"got. Hope you have a saved game a level or\n"\
-"two previous. If not, be prepared to die\n"\
-"aplenty. For master marines only."
-
-// before map 32
-
-#define P6TEXT \
-"Betcha wondered just what WAS the hardest\n"\
-"level we had ready for ya? Now you know.\n"\
-"No one gets out alive."
-
-
-#define T1TEXT \
-"You've fought your way out of the infested\n"\
-"experimental labs. It seems that UAC has\n"\
-"once again gulped it down. With their\n"\
-"high turnover, it must be hard for poor\n"\
-"old UAC to buy corporate health insurance\n"\
-"nowadays..\n"\
-"\n"\
-"Ahead lies the military complex, now\n"\
-"swarming with diseased horrors hot to get\n"\
-"their teeth into you. With luck, the\n"\
-"complex still has some warlike ordnance\n"\
-"laying around."
-
-
-#define T2TEXT \
-"You hear the grinding of heavy machinery\n"\
-"ahead. You sure hope they're not stamping\n"\
-"out new hellspawn, but you're ready to\n"\
-"ream out a whole herd if you have to.\n"\
-"They might be planning a blood feast, but\n"\
-"you feel about as mean as two thousand\n"\
-"maniacs packed into one mad killer.\n"\
-"\n"\
-"You don't plan to go down easy."
-
-
-#define T3TEXT \
-"The vista opening ahead looks real damn\n"\
-"familiar. Smells familiar, too -- like\n"\
-"fried excrement. You didn't like this\n"\
-"place before, and you sure as hell ain't\n"\
-"planning to like it now. The more you\n"\
-"brood on it, the madder you get.\n"\
-"Hefting your gun, an evil grin trickles\n"\
-"onto your face. Time to take some names."
-
-#define T4TEXT \
-"Suddenly, all is silent, from one horizon\n"\
-"to the other. The agonizing echo of Hell\n"\
-"fades away, the nightmare sky turns to\n"\
-"blue, the heaps of monster corpses start \n"\
-"to evaporate along with the evil stench \n"\
-"that filled the air. Jeeze, maybe you've\n"\
-"done it. Have you really won?\n"\
-"\n"\
-"Something rumbles in the distance.\n"\
-"A blue light begins to glow inside the\n"\
-"ruined skull of the demon-spitter."
-
-
-#define T5TEXT \
-"What now? Looks totally different. Kind\n"\
-"of like King Tut's condo. Well,\n"\
-"whatever's here can't be any worse\n"\
-"than usual. Can it? Or maybe it's best\n"\
-"to let sleeping gods lie.."
-
-
-#define T6TEXT \
-"Time for a vacation. You've burst the\n"\
-"bowels of hell and by golly you're ready\n"\
-"for a break. You mutter to yourself,\n"\
-"Maybe someone else can kick Hell's ass\n"\
-"next time around. Ahead lies a quiet town,\n"\
-"with peaceful flowing water, quaint\n"\
-"buildings, and presumably no Hellspawn.\n"\
-"\n"\
-"As you step off the transport, you hear\n"\
-"the stomp of a cyberdemon's iron shoe."
-
-
-
-//
-// 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"
-
-
-#endif
--- a/src/d_items.c
+++ /dev/null
@@ -1,136 +1,0 @@
-// Emacs style mode select -*- C++ -*-
-//-----------------------------------------------------------------------------
-//
-// Copyright(C) 1993-1996 Id Software, Inc.
-// Copyright(C) 2005 Simon Howard
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-// 02111-1307, USA.
-//
-// DESCRIPTION:
-//
-//-----------------------------------------------------------------------------
-
-
-// We are referring to sprite numbers.
-#include "info.h"
-
-#include "d_items.h"
-
-
-//
-// PSPRITE ACTIONS for waepons.
-// This struct controls the weapon animations.
-//
-// Each entry is:
-// ammo/amunition type
-// upstate
-// downstate
-// readystate
-// atkstate, i.e. attack/fire/hit frame
-// flashstate, muzzle flash
-//
-weaponinfo_t weaponinfo[NUMWEAPONS] =
-{
- {
- // fist
- am_noammo,
- S_PUNCHUP,
- S_PUNCHDOWN,
- S_PUNCH,
- S_PUNCH1,
- S_NULL
- },
- {
- // pistol
- am_clip,
- S_PISTOLUP,
- S_PISTOLDOWN,
- S_PISTOL,
- S_PISTOL1,
- S_PISTOLFLASH
- },
- {
- // shotgun
- am_shell,
- S_SGUNUP,
- S_SGUNDOWN,
- S_SGUN,
- S_SGUN1,
- S_SGUNFLASH1
- },
- {
- // chaingun
- am_clip,
- S_CHAINUP,
- S_CHAINDOWN,
- S_CHAIN,
- S_CHAIN1,
- S_CHAINFLASH1
- },
- {
- // missile launcher
- am_misl,
- S_MISSILEUP,
- S_MISSILEDOWN,
- S_MISSILE,
- S_MISSILE1,
- S_MISSILEFLASH1
- },
- {
- // plasma rifle
- am_cell,
- S_PLASMAUP,
- S_PLASMADOWN,
- S_PLASMA,
- S_PLASMA1,
- S_PLASMAFLASH1
- },
- {
- // bfg 9000
- am_cell,
- S_BFGUP,
- S_BFGDOWN,
- S_BFG,
- S_BFG1,
- S_BFGFLASH1
- },
- {
- // chainsaw
- am_noammo,
- S_SAWUP,
- S_SAWDOWN,
- S_SAW,
- S_SAW1,
- S_NULL
- },
- {
- // super shotgun
- am_shell,
- S_DSGUNUP,
- S_DSGUNDOWN,
- S_DSGUN,
- S_DSGUN1,
- S_DSGUNFLASH1
- },
-};
-
-
-
-
-
-
-
-
--- a/src/d_items.h
+++ /dev/null
@@ -1,49 +1,0 @@
-// Emacs style mode select -*- C++ -*-
-//-----------------------------------------------------------------------------
-//
-// Copyright(C) 1993-1996 Id Software, Inc.
-// Copyright(C) 2005 Simon Howard
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-// 02111-1307, USA.
-//
-// DESCRIPTION:
-// Items: key cards, artifacts, weapon, ammunition.
-//
-//-----------------------------------------------------------------------------
-
-
-#ifndef __D_ITEMS__
-#define __D_ITEMS__
-
-#include "doomdef.h"
-
-
-
-// Weapon info: sprite frames, ammunition use.
-typedef struct
-{
- ammotype_t ammo;
- int upstate;
- int downstate;
- int readystate;
- int atkstate;
- int flashstate;
-
-} weaponinfo_t;
-
-extern weaponinfo_t weaponinfo[NUMWEAPONS];
-
-#endif
--- a/src/d_iwad.c
+++ /dev/null
@@ -1,912 +1,0 @@
-// Emacs style mode select -*- C++ -*-
-//-----------------------------------------------------------------------------
-//
-// Copyright(C) 2006 Simon Howard
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-// 02111-1307, USA.
-//
-// DESCRIPTION:
-// Search for and locate an IWAD file, and initialise according
-// to the IWAD type.
-//
-//-----------------------------------------------------------------------------
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <ctype.h>
-#include <string.h>
-
-#include "deh_main.h"
-#include "doomdef.h"
-#include "doomstat.h"
-#include "i_system.h"
-#include "m_argv.h"
-#include "m_config.h"
-#include "m_misc.h"
-#include "w_wad.h"
-#include "z_zone.h"
-
-// Array of locations to search for IWAD files
-//
-// "128 IWAD search directories should be enough for anybody".
-
-#define MAX_IWAD_DIRS 128
-
-static boolean iwad_dirs_built = false;
-static char *iwad_dirs[MAX_IWAD_DIRS];
-static int num_iwad_dirs = 0;
-
-static void AddIWADDir(char *dir)
-{
- if (num_iwad_dirs < MAX_IWAD_DIRS)
- {
- iwad_dirs[num_iwad_dirs] = dir;
- ++num_iwad_dirs;
- }
-}
-
-// This is Windows-specific code that automatically finds the location
-// of installed IWAD files. The registry is inspected to find special
-// keys installed by the Windows installers for various CD versions
-// of Doom. From these keys we can deduce where to find an IWAD.
-
-#ifdef _WIN32
-
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>
-
-typedef struct
-{
- HKEY root;
- char *path;
- char *value;
-} registry_value_t;
-
-#define UNINSTALLER_STRING "\\uninstl.exe /S "
-
-// Keys installed by the various CD editions. These are actually the
-// commands to invoke the uninstaller and look like this:
-//
-// C:\Program Files\Path\uninstl.exe /S C:\Program Files\Path
-//
-// With some munging we can find where Doom was installed.
-
-static registry_value_t uninstall_values[] =
-{
- // Ultimate Doom, CD version (Depths of Doom trilogy)
-
- {
- HKEY_LOCAL_MACHINE,
- "Software\\Microsoft\\Windows\\CurrentVersion\\"
- "Uninstall\\Ultimate Doom for Windows 95",
- "UninstallString",
- },
-
- // Doom II, CD version (Depths of Doom trilogy)
-
- {
- HKEY_LOCAL_MACHINE,
- "Software\\Microsoft\\Windows\\CurrentVersion\\"
- "Uninstall\\Doom II for Windows 95",
- "UninstallString",
- },
-
- // Final Doom
-
- {
- HKEY_LOCAL_MACHINE,
- "Software\\Microsoft\\Windows\\CurrentVersion\\"
- "Uninstall\\Final Doom for Windows 95",
- "UninstallString",
- },
-
- // Shareware version
-
- {
- HKEY_LOCAL_MACHINE,
- "Software\\Microsoft\\Windows\\CurrentVersion\\"
- "Uninstall\\Doom Shareware for Windows 95",
- "UninstallString",
- },
-};
-
-// Value installed by the Collector's Edition when it is installed
-
-static registry_value_t collectors_edition_value =
-{
- HKEY_LOCAL_MACHINE,
- "Software\\Activision\\DOOM Collector's Edition\\v1.0",
- "INSTALLPATH",
-};
-
-// Subdirectories of the above install path, where IWADs are installed.
-
-static char *collectors_edition_subdirs[] =
-{
- "Doom2",
- "Final Doom",
- "Ultimate Doom",
-};
-
-// Location where Steam is installed
-
-static registry_value_t steam_install_location =
-{
- HKEY_LOCAL_MACHINE,
- "Software\\Valve\\Steam",
- "InstallPath",
-};
-
-// Subdirs of the steam install directory where IWADs are found
-
-static char *steam_install_subdirs[] =
-{
- "steamapps\\common\\doom 2\\base",
- "steamapps\\common\\final doom\\base",
- "steamapps\\common\\ultimate doom\\base",
-};
-
-static char *GetRegistryString(registry_value_t *reg_val)
-{
- HKEY key;
- DWORD len;
- DWORD valtype;
- char *result;
-
- // Open the key (directory where the value is stored)
-
- if (RegOpenKeyEx(reg_val->root, reg_val->path, 0, KEY_READ, &key)
- != ERROR_SUCCESS)
- {
- return NULL;
- }
-
- // Find the type and length of the string
-
- if (RegQueryValueEx(key, reg_val->value, NULL, &valtype, NULL, &len)
- != ERROR_SUCCESS)
- {
- return NULL;
- }
-
- // Only accept strings
-
- if (valtype != REG_SZ)
- {
- return NULL;
- }
-
- // Allocate a buffer for the value and read the value
-
- result = malloc(len);
-
- if (RegQueryValueEx(key, reg_val->value, NULL, &valtype, (unsigned char *) result, &len)
- != ERROR_SUCCESS)
- {
- free(result);
- return NULL;
- }
-
- // Close the key
-
- RegCloseKey(key);
-
- return result;
-}
-
-// Check for the uninstall strings from the CD versions
-
-static void CheckUninstallStrings(void)
-{
- unsigned int i;
-
- for (i=0; i<arrlen(uninstall_values); ++i)
- {
- char *val;
- char *path;
- char *unstr;
-
- val = GetRegistryString(&uninstall_values[i]);
-
- if (val == NULL)
- {
- continue;
- }
-
- unstr = strstr(val, UNINSTALLER_STRING);
-
- if (unstr == NULL)
- {
- free(val);
- }
- else
- {
- path = unstr + strlen(UNINSTALLER_STRING);
-
- AddIWADDir(path);
- }
- }
-}
-
-// Check for Doom: Collector's Edition
-
-static void CheckCollectorsEdition(void)
-{
- char *install_path;
- char *subpath;
- unsigned int i;
-
- install_path = GetRegistryString(&collectors_edition_value);
-
- if (install_path == NULL)
- {
- return;
- }
-
- for (i=0; i<arrlen(collectors_edition_subdirs); ++i)
- {
- subpath = malloc(strlen(install_path)
- + strlen(collectors_edition_subdirs[i])
- + 5);
-
- sprintf(subpath, "%s\\%s", install_path, collectors_edition_subdirs[i]);
-
- AddIWADDir(subpath);
- }
-
- free(install_path);
-}
-
-
-// Check for Doom downloaded via Steam
-
-static void CheckSteamEdition(void)
-{
- char *install_path;
- char *subpath;
- size_t i;
-
- install_path = GetRegistryString(&steam_install_location);
-
- if (install_path == NULL)
- {
- return;
- }
-
- for (i=0; i<arrlen(steam_install_subdirs); ++i)
- {
- subpath = malloc(strlen(install_path)
- + strlen(steam_install_subdirs[i]) + 5);
-
- sprintf(subpath, "%s\\%s", install_path, steam_install_subdirs[i]);
-
- AddIWADDir(subpath);
- }
-}
-
-// Default install directories for DOS Doom
-
-static void CheckDOSDefaults(void)
-{
- // These are the default install directories used by the deice
- // installer program:
-
- AddIWADDir("\\doom2"); // Doom II
- AddIWADDir("\\plutonia"); // Final Doom
- AddIWADDir("\\tnt");
- AddIWADDir("\\doom_se"); // Ultimate Doom
- AddIWADDir("\\doom"); // Shareware / Registered Doom
- AddIWADDir("\\dooms"); // Shareware versions
- AddIWADDir("\\doomsw");
-}
-
-#endif
-
-static struct
-{
- char *name;
- GameMission_t mission;
-} iwads[] = {
- {"doom2.wad", doom2},
- {"plutonia.wad", pack_plut},
- {"tnt.wad", pack_tnt},
- {"doom.wad", doom},
- {"doom1.wad", doom},
- {"chex.wad", doom},
-};
-
-// Hack for chex quest mode
-
-static void CheckChex(char *iwad_name)
-{
- if (!strcmp(iwad_name, "chex.wad"))
- {
- gameversion = exe_chex;
- }
-}
-
-// Search a directory to try to find an IWAD
-// Returns the location of the IWAD if found, otherwise NULL.
-
-static char *SearchDirectoryForIWAD(char *dir)
-{
- size_t i;
-
- for (i=0; i<arrlen(iwads); ++i)
- {
- char *filename;
- char *iwadname;
-
- iwadname = DEH_String(iwads[i].name);
-
- filename = malloc(strlen(dir) + strlen(iwadname) + 3);
-
- if (!strcmp(dir, "."))
- {
- strcpy(filename, iwadname);
- }
- else
- {
- sprintf(filename, "%s%c%s", dir, DIR_SEPARATOR, iwadname);
- }
-
- if (M_FileExists(filename))
- {
- CheckChex(iwads[i].name);
- gamemission = iwads[i].mission;
-
- return filename;
- }
-
- free(filename);
- }
-
- return NULL;
-}
-
-// When given an IWAD with the '-iwad' parameter,
-// attempt to identify it by its name.
-
-static void IdentifyIWADByName(char *name)
-{
- size_t i;
-
- gamemission = none;
-
- for (i=0; i<arrlen(iwads); ++i)
- {
- char *iwadname;
-
- iwadname = DEH_String(iwads[i].name);
-
- if (strlen(name) < strlen(iwadname))
- continue;
-
- // Check if it ends in this IWAD name.
-
- if (!strcasecmp(name + strlen(name) - strlen(iwadname),
- iwadname))
- {
- CheckChex(iwads[i].name);
- gamemission = iwads[i].mission;
- break;
- }
- }
-}
-
-//
-// Add directories from the list in the DOOMWADPATH environment variable.
-//
-
-static void AddDoomWadPath(void)
-{
- char *doomwadpath;
- char *p;
-
- // Check the DOOMWADPATH environment variable.
-
- doomwadpath = getenv("DOOMWADPATH");
-
- if (doomwadpath == NULL)
- {
- return;
- }
-
- doomwadpath = strdup(doomwadpath);
-
- // Add the initial directory
-
- AddIWADDir(doomwadpath);
-
- // Split into individual dirs within the list.
-
- p = doomwadpath;
-
- for (;;)
- {
- p = strchr(p, PATH_SEPARATOR);
-
- if (p != NULL)
- {
- // Break at the separator and store the right hand side
- // as another iwad dir
-
- *p = '\0';
- p += 1;
-
- AddIWADDir(p);
- }
- else
- {
- break;
- }
- }
-}
-
-
-//
-// Build a list of IWAD files
-//
-
-static void BuildIWADDirList(void)
-{
- char *doomwaddir;
-
- if (iwad_dirs_built)
- {
- return;
- }
-
- // Look in the current directory. Doom always does this.
-
- AddIWADDir(".");
-
- // Add DOOMWADDIR if it is in the environment
-
- doomwaddir = getenv("DOOMWADDIR");
-
- if (doomwaddir != NULL)
- {
- AddIWADDir(doomwaddir);
- }
-
- // Add dirs from DOOMWADPATH
-
- AddDoomWadPath();
-
-#ifdef _WIN32
-
- // Search the registry and find where IWADs have been installed.
-
- CheckUninstallStrings();
- CheckCollectorsEdition();
- CheckSteamEdition();
- CheckDOSDefaults();
-
-#else
-
- // Standard places where IWAD files are installed under Unix.
-
- AddIWADDir("/usr/share/games/doom");
- AddIWADDir("/usr/local/share/games/doom");
-
-#endif
-
- // Don't run this function again.
-
- iwad_dirs_built = true;
-}
-
-//
-// Searches WAD search paths for an WAD with a specific filename.
-//
-
-char *D_FindWADByName(char *name)
-{
- char *buf;
- int i;
- boolean exists;
-
- // Absolute path?
-
- if (M_FileExists(name))
- {
- return name;
- }
-
- BuildIWADDirList();
-
- // Search through all IWAD paths for a file with the given name.
-
- for (i=0; i<num_iwad_dirs; ++i)
- {
- // Construct a string for the full path
-
- buf = malloc(strlen(iwad_dirs[i]) + strlen(name) + 5);
- sprintf(buf, "%s%c%s", iwad_dirs[i], DIR_SEPARATOR, name);
-
- exists = M_FileExists(buf);
-
- if (exists)
- {
- return buf;
- }
-
- free(buf);
- }
-
- // File not found
-
- return NULL;
-}
-
-//
-// D_TryWADByName
-//
-// Searches for a WAD by its filename, or passes through the filename
-// if not found.
-//
-
-char *D_TryFindWADByName(char *filename)
-{
- char *result;
-
- result = D_FindWADByName(filename);
-
- if (result != NULL)
- {
- return result;
- }
- else
- {
- return filename;
- }
-}
-
-//
-// FindIWAD
-// Checks availability of IWAD files by name,
-// to determine whether registered/commercial features
-// should be executed (notably loading PWADs).
-//
-
-char *D_FindIWAD(void)
-{
- char *result;
- char *iwadfile;
- int iwadparm;
- int i;
-
- // Check for the -iwad parameter
-
- //!
- // Specify an IWAD file to use.
- //
- // @arg <file>
- //
-
- iwadparm = M_CheckParm("-iwad");
-
- if (iwadparm)
- {
- // Search through IWAD dirs for an IWAD with the given name.
-
- iwadfile = myargv[iwadparm + 1];
-
- result = D_FindWADByName(iwadfile);
-
- if (result == NULL)
- {
- I_Error("IWAD file '%s' not found!", iwadfile);
- }
-
- IdentifyIWADByName(result);
- }
- else
- {
- // Search through the list and look for an IWAD
-
- result = NULL;
-
- BuildIWADDirList();
-
- for (i=0; result == NULL && i<num_iwad_dirs; ++i)
- {
- result = SearchDirectoryForIWAD(iwad_dirs[i]);
- }
- }
-
- return result;
-}
-
-//
-// Get the IWAD name used for savegames.
-//
-
-static char *SaveGameIWADName(void)
-{
- size_t i;
-
- // Chex quest hack
-
- if (gameversion == exe_chex)
- {
- return "chex.wad";
- }
-
- // Find what subdirectory to use for savegames
- //
- // They should be stored in something like
- // ~/.chocolate-doom/savegames/doom.wad/
- //
- // The directory depends on the IWAD, so that savegames for
- // different IWADs are kept separate.
- //
- // Note that we match on gamemission rather than on IWAD name.
- // This ensures that doom1.wad and doom.wad saves are stored
- // in the same place.
-
- for (i=0; i<arrlen(iwads); ++i)
- {
- if (gamemission == iwads[i].mission)
- {
- return iwads[i].name;
- }
- }
-
- return NULL;
-}
-//
-// SetSaveGameDir
-//
-// Chooses the directory used to store saved games.
-//
-
-void D_SetSaveGameDir(void)
-{
- char *iwad_name;
-
- if (!strcmp(configdir, ""))
- {
- // Use the current directory, just like configdir.
-
- savegamedir = strdup("");
- }
- else
- {
- // Directory for savegames
-
- iwad_name = SaveGameIWADName();
-
- if (iwad_name == NULL)
- {
- iwad_name = "unknown.wad";
- }
-
- savegamedir = Z_Malloc(strlen(configdir) + 30, PU_STATIC, 0);
- sprintf(savegamedir, "%ssavegames%c%s%c", configdir,
- DIR_SEPARATOR, iwad_name, DIR_SEPARATOR);
-
- M_MakeDirectory(savegamedir);
- }
-}
-
-// Strings for dehacked replacements of the startup banner
-//
-// These are from the original source: some of them are perhaps
-// not used in any dehacked patches
-
-static char *banners[] =
-{
- // doom1.wad
- " "
- "DOOM Shareware Startup v%i.%i"
- " ",
- // doom.wad
- " "
- "DOOM Registered Startup v%i.%i"
- " ",
- // Registered DOOM uses this
- " "
- "DOOM System Startup v%i.%i"
- " ",
- // doom.wad (Ultimate DOOM)
- " "
- "The Ultimate DOOM Startup v%i.%i"
- " ",
- // doom2.wad
- " "
- "DOOM 2: Hell on Earth v%i.%i"
- " ",
- // tnt.wad
- " "
- "DOOM 2: TNT - Evilution v%i.%i"
- " ",
- // plutonia.wad
- " "
- "DOOM 2: Plutonia Experiment v%i.%i"
- " ",
-};
-
-//
-// Get game name: if the startup banner has been replaced, use that.
-// Otherwise, use the name given
-//
-
-static char *GetGameName(char *gamename)
-{
- size_t i;
- char *deh_sub;
-
- for (i=0; i<arrlen(banners); ++i)
- {
- // Has the banner been replaced?
-
- deh_sub = DEH_String(banners[i]);
-
- if (deh_sub != banners[i])
- {
- // Has been replaced
- // We need to expand via printf to include the Doom version
- // number
- // We also need to cut off spaces to get the basic name
-
- gamename = Z_Malloc(strlen(deh_sub) + 10, PU_STATIC, 0);
- sprintf(gamename, deh_sub, DOOM_VERSION / 100, DOOM_VERSION % 100);
-
- while (gamename[0] != '\0' && isspace(gamename[0]))
- strcpy(gamename, gamename+1);
-
- while (gamename[0] != '\0' && isspace(gamename[strlen(gamename)-1]))
- gamename[strlen(gamename) - 1] = '\0';
-
- return gamename;
- }
- }
-
- return gamename;
-}
-
-
-//
-// Find out what version of Doom is playing.
-//
-
-void D_IdentifyVersion(void)
-{
- // gamemission is set up by the D_FindIWAD function. But if
- // we specify '-iwad', we have to identify using
- // IdentifyIWADByName. However, if the iwad does not match
- // any known IWAD name, we may have a dilemma. Try to
- // identify by its contents.
-
- if (gamemission == none)
- {
- unsigned int i;
-
- for (i=0; i<numlumps; ++i)
- {
- if (!strncasecmp(lumpinfo[i].name, "MAP01", 8))
- {
- gamemission = doom2;
- break;
- }
- else if (!strncasecmp(lumpinfo[i].name, "E1M1", 8))
- {
- gamemission = doom;
- break;
- }
- }
-
- if (gamemission == none)
- {
- // Still no idea. I don't think this is going to work.
-
- I_Error("Unknown or invalid IWAD file.");
- }
- }
-
- // Make sure gamemode is set up correctly
-
- if (gamemission == doom)
- {
- // Doom 1. But which version?
-
- if (W_CheckNumForName("E4M1") > 0)
- {
- // Ultimate Doom
-
- gamemode = retail;
- }
- else if (W_CheckNumForName("E3M1") > 0)
- {
- gamemode = registered;
- }
- else
- {
- gamemode = shareware;
- }
- }
- else
- {
- // Doom 2 of some kind.
-
- gamemode = commercial;
- }
-}
-
-// Set the gamedescription string
-
-void D_SetGameDescription(void)
-{
- gamedescription = "Unknown";
-
- if (gamemission == doom)
- {
- // Doom 1. But which version?
-
- if (gamemode == retail)
- {
- // Ultimate Doom
-
- gamedescription = GetGameName("The Ultimate DOOM");
- }
- else if (gamemode == registered)
- {
- gamedescription = GetGameName("DOOM Registered");
- }
- else if (gamemode == shareware)
- {
- gamedescription = GetGameName("DOOM Shareware");
- }
- }
- else
- {
- // Doom 2 of some kind. But which mission?
-
- if (gamemission == doom2)
- gamedescription = GetGameName("DOOM 2: Hell on Earth");
- else if (gamemission == pack_plut)
- gamedescription = GetGameName("DOOM 2: Plutonia Experiment");
- else if (gamemission == pack_tnt)
- gamedescription = GetGameName("DOOM 2: TNT - Evilution");
- }
-}
-
-// Clever hack: Setup can invoke Doom to determine which IWADs are installed.
-// Doom searches install paths and exits with the return code being a
-// bitmask of the installed IWAD files.
-
-void D_FindInstalledIWADs(void)
-{
- unsigned int i;
- int result;
-
- BuildIWADDirList();
-
- result = 0;
-
- for (i=0; i<arrlen(iwads); ++i)
- {
- if (D_FindWADByName(iwads[i].name) != NULL)
- {
- result |= 1 << i;
- }
- }
-
- exit(result);
-}
-
--- a/src/d_iwad.h
+++ /dev/null
@@ -1,39 +1,0 @@
-// Emacs style mode select -*- C++ -*-
-//-----------------------------------------------------------------------------
-//
-// Copyright(C) 2006 Simon Howard
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-// 02111-1307, USA.
-//
-// DESCRIPTION:
-// Find IWAD and initialise according to IWAD type.
-//
-//-----------------------------------------------------------------------------
-
-
-#ifndef __D_IWAD__
-#define __D_IWAD__
-
-char *D_FindWADByName(char *filename);
-char *D_TryFindWADByName(char *filename);
-char *D_FindIWAD(void);
-void D_SetSaveGameDir(void);
-void D_IdentifyVersion(void);
-void D_SetGameDescription(void);
-void D_FindInstalledIWADs(void);
-
-#endif
-
--- a/src/d_main.c
+++ /dev/null
@@ -1,1525 +1,0 @@
-// Emacs style mode select -*- C++ -*-
-//-----------------------------------------------------------------------------
-//
-// Copyright(C) 1993-1996 Id Software, Inc.
-// Copyright(C) 2005 Simon Howard
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-// 02111-1307, USA.
-//
-// DESCRIPTION:
-// DOOM main program (D_DoomMain) and game loop (D_DoomLoop),
-// plus functions to determine game mode (shareware, registered),
-// parse command line parameters, configure game parameters (turbo),
-// and call the startup functions.
-//
-//-----------------------------------------------------------------------------
-
-
-#include <ctype.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "config.h"
-#include "deh_main.h"
-#include "doomdef.h"
-#include "doomstat.h"
-
-#include "dstrings.h"
-#include "doomfeatures.h"
-#include "sounds.h"
-
-#include "d_iwad.h"
-
-#include "z_zone.h"
-#include "w_wad.h"
-#include "w_merge.h"
-#include "s_sound.h"
-#include "v_video.h"
-
-#include "f_finale.h"
-#include "f_wipe.h"
-
-#include "m_argv.h"
-#include "m_config.h"
-#include "m_misc.h"
-#include "m_menu.h"
-#include "p_saveg.h"
-
-#include "i_system.h"
-#include "i_timer.h"
-#include "i_video.h"
-
-#include "g_game.h"
-
-#include "hu_stuff.h"
-#include "wi_stuff.h"
-#include "st_stuff.h"
-#include "am_map.h"
-#include "net_client.h"
-#include "net_dedicated.h"
-#include "net_query.h"
-
-#include "p_setup.h"
-#include "r_local.h"
-
-
-#include "d_main.h"
-
-//
-// D-DoomLoop()
-// 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,
-// calls I_GetTime, I_StartFrame, and I_StartTic
-//
-void D_DoomLoop (void);
-
-// Location where savegames are stored
-
-char * savegamedir;
-
-// location of IWAD and WAD files
-
-char * iwadfile;
-
-
-boolean devparm; // started game with -devparm
-boolean nomonsters; // checkparm of -nomonsters
-boolean respawnparm; // checkparm of -respawn
-boolean fastparm; // checkparm of -fast
-
-boolean singletics = false; // debug flag to cancel adaptiveness
-
-
-// If true, game is running as a screensaver
-
-boolean screensaver_mode = false;
-
-
-//extern int soundVolume;
-//extern int sfxVolume;
-//extern int musicVolume;
-
-extern boolean inhelpscreens;
-
-skill_t startskill;
-int startepisode;
-int startmap;
-boolean autostart;
-int startloadgame;
-
-FILE* debugfile;
-
-boolean advancedemo;
-
-// Store demo, do not accept any inputs
-
-boolean storedemo;
-
-
-char wadfile[1024]; // primary wad file
-char mapdir[1024]; // directory of development maps
-
-
-void D_CheckNetGame (void);
-void D_ProcessEvents (void);
-void G_BuildTiccmd (ticcmd_t* cmd);
-void D_DoAdvanceDemo (void);
-
-
-//
-// EVENT HANDLING
-//
-// Events are asynchronous inputs generally generated by the game user.
-// Events can be discarded if no responder claims them
-//
-
-#define MAXEVENTS 64
-
-static event_t events[MAXEVENTS];
-static int eventhead;
-static int eventtail;
-
-
-//
-// D_PostEvent
-// Called by the I/O functions when input is detected
-//
-void D_PostEvent (event_t* ev)
-{
- events[eventhead] = *ev;
- eventhead = (eventhead + 1) % MAXEVENTS;
-}
-
-// Read an event from the queue.
-
-event_t *D_PopEvent(void)
-{
- event_t *result;
-
- // No more events waiting.
-
- if (eventtail == eventhead)
- {
- return NULL;
- }
-
- result = &events[eventtail];
-
- // Advance to the next event in the queue.
-
- eventtail = (eventtail + 1) % MAXEVENTS;
-
- return result;
-}
-
-
-//
-// D_ProcessEvents
-// Send all the events of the given timestamp down the responder chain
-//
-void D_ProcessEvents (void)
-{
- event_t* ev;
-
- // IF STORE DEMO, DO NOT ACCEPT INPUT
- if (storedemo)
- return;
-
- while ((ev = D_PopEvent()) != NULL)
- {
- if (M_Responder (ev))
- continue; // menu ate the event
- G_Responder (ev);
- }
-}
-
-
-
-
-//
-// 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;
- int tics;
- int wipestart;
- int y;
- boolean done;
- boolean wipe;
- boolean 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 (DEH_String("PLAYPAL"),PU_CACHE));
-
- // see if the border needs to be initially drawn
- if (gamestate == GS_LEVEL && oldgamestate != GS_LEVEL)
- {
- viewactivestate = false; // view was not 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--;
- }
-
- }
-
- if (testcontrols)
- {
- // Box showing current mouse speed
-
- G_DrawMouseSpeedBox();
- }
-
- 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 (DEH_String("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;
- I_Sleep(1);
- } while (tics <= 0);
-
- 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");
- }
-
- TryRunTics();
-
- I_InitGraphics ();
-
- R_ExecuteSetViewSize();
-
- D_StartGameLoop();
-
- if (testcontrols)
- {
- wipegamestate = gamestate;
- }
-
- while (1)
- {
- // frame syncronous IO operations
- I_StartFrame ();
-
- // 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
-
- // Update display, next frame, with current state.
- if (screenvisible)
- 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;
-}
-
-
-//
-// This cycles through the demo sequences.
-// FIXME - version dependend demo numbers?
-//
-void D_DoAdvanceDemo (void)
-{
- players[consoleplayer].playerstate = PST_LIVE; // not reborn
- advancedemo = false;
- usergame = false; // no save / end game here
- paused = false;
- gameaction = ga_nothing;
-
- if ( gamemode == retail )
- demosequence = (demosequence+1)%7;
- else
- demosequence = (demosequence+1)%6;
-
- switch (demosequence)
- {
- case 0:
- if ( gamemode == commercial )
- pagetic = TICRATE * 11;
- else
- pagetic = 170;
- gamestate = GS_DEMOSCREEN;
- pagename = DEH_String("TITLEPIC");
- if ( gamemode == commercial )
- S_StartMusic(mus_dm2ttl);
- else
- S_StartMusic (mus_intro);
- break;
- case 1:
- G_DeferedPlayDemo(DEH_String("demo1"));
- break;
- case 2:
- pagetic = 200;
- gamestate = GS_DEMOSCREEN;
- pagename = DEH_String("CREDIT");
- break;
- case 3:
- G_DeferedPlayDemo(DEH_String("demo2"));
- break;
- case 4:
- gamestate = GS_DEMOSCREEN;
- if ( gamemode == commercial)
- {
- pagetic = TICRATE * 11;
- pagename = DEH_String("TITLEPIC");
- S_StartMusic(mus_dm2ttl);
- }
- else
- {
- pagetic = 200;
-
- if ( gamemode == retail )
- pagename = DEH_String("CREDIT");
- else
- pagename = DEH_String("HELP2");
- }
- break;
- case 5:
- G_DeferedPlayDemo(DEH_String("demo3"));
- break;
- // THE DEFINITIVE DOOM Special Edition demo
- case 6:
- G_DeferedPlayDemo(DEH_String("demo4"));
- break;
- }
-}
-
-
-
-//
-// D_StartTitle
-//
-void D_StartTitle (void)
-{
- gameaction = ga_nothing;
- demosequence = -1;
- D_AdvanceDemo ();
-}
-
-
-
-
-// print title for every printed line
-char title[128];
-
-
-static boolean D_AddFile(char *filename)
-{
- wad_file_t *handle;
-
- printf(" adding %s\n", filename);
- handle = W_AddFile(filename);
-
- return handle != NULL;
-}
-// Startup banner
-
-void PrintBanner(char *msg)
-{
- int i;
- int spaces = 35 - (strlen(msg) / 2);
-
- for (i=0; i<spaces; ++i)
- putchar(' ');
-
- puts(msg);
-}
-
-// Copyright message banners
-// Some dehacked mods replace these. These are only displayed if they are
-// replaced by dehacked.
-
-static char *copyright_banners[] =
-{
- "===========================================================================\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",
-
- "===========================================================================\n"
- " Commercial product - do not distribute!\n"
- " Please report software piracy to the SPA: 1-800-388-PIR8\n"
- "===========================================================================\n",
-
- "===========================================================================\n"
- " Shareware!\n"
- "===========================================================================\n"
-};
-
-// Prints a message only if it has been modified by dehacked.
-
-void PrintDehackedBanners(void)
-{
- size_t i;
-
- for (i=0; i<arrlen(copyright_banners); ++i)
- {
- char *deh_s;
-
- deh_s = DEH_String(copyright_banners[i]);
-
- if (deh_s != copyright_banners[i])
- {
- printf("%s", deh_s);
-
- // Make sure the modified banner always ends in a newline character.
- // If it doesn't, add a newline. This fixes av.wad.
-
- if (deh_s[strlen(deh_s) - 1] != '\n')
- {
- printf("\n");
- }
- }
- }
-}
-
-static struct
-{
- char *description;
- char *cmdline;
- GameVersion_t version;
-} gameversions[] = {
- {"Doom 1.9", "1.9", exe_doom_1_9},
- {"Ultimate Doom", "ultimate", exe_ultimate},
- {"Final Doom", "final", exe_final},
- {"Chex Quest", "chex", exe_chex},
- { NULL, NULL, 0},
-};
-
-// Initialise the game version
-
-static void InitGameVersion(void)
-{
- int p;
- int i;
-
- //!
- // @arg <version>
- // @category compat
- //
- // Emulate a specific version of Doom. Valid values are "1.9",
- // "ultimate" and "final".
- //
-
- p = M_CheckParm("-gameversion");
-
- if (p > 0)
- {
- for (i=0; gameversions[i].description != NULL; ++i)
- {
- if (!strcmp(myargv[p+1], gameversions[i].cmdline))
- {
- gameversion = gameversions[i].version;
- break;
- }
- }
-
- if (gameversions[i].description == NULL)
- {
- printf("Supported game versions:\n");
-
- for (i=0; gameversions[i].description != NULL; ++i)
- {
- printf("\t%s (%s)\n", gameversions[i].cmdline,
- gameversions[i].description);
- }
-
- I_Error("Unknown game version '%s'", myargv[p+1]);
- }
- }
- else
- {
- // Determine automatically
-
- if (gameversion == exe_chex)
- {
- // Already determined
- }
- else if (gamemode == shareware || gamemode == registered)
- {
- // original
-
- gameversion = exe_doom_1_9;
- }
- else if (gamemode == retail)
- {
- gameversion = exe_ultimate;
- }
- else if (gamemode == commercial)
- {
- if (gamemission == doom2)
- {
- gameversion = exe_doom_1_9;
- }
- else
- {
- // Final Doom: tnt or plutonia
-
- gameversion = exe_final;
- }
- }
- }
-
- // The original exe does not support retail - 4th episode not supported
-
- if (gameversion < exe_ultimate && gamemode == retail)
- {
- gamemode = registered;
- }
-
- // EXEs prior to the Final Doom exes do not support Final Doom.
-
- if (gameversion < exe_final && gamemode == commercial)
- {
- gamemission = doom2;
- }
-}
-
-void PrintGameVersion(void)
-{
- int i;
-
- for (i=0; gameversions[i].description != NULL; ++i)
- {
- if (gameversions[i].version == gameversion)
- {
- printf("Emulating the behavior of the "
- "'%s' executable.\n", gameversions[i].description);
- break;
- }
- }
-}
-
-// Load the Chex Quest dehacked file, if we are in Chex mode.
-
-static void LoadChexDeh(void)
-{
- char *chex_deh;
-
- if (gameversion == exe_chex)
- {
- chex_deh = D_FindWADByName("chex.deh");
-
- if (chex_deh == NULL)
- {
- I_Error("Unable to find Chex Quest dehacked file (chex.deh).\n"
- "The dehacked file is required in order to emulate\n"
- "chex.exe correctly. It can be found in your nearest\n"
- "/idgames repository mirror at:\n\n"
- " utils/exe_edit/patches/chexdeh.zip");
- }
-
- if (!DEH_LoadFile(chex_deh))
- {
- I_Error("Failed to load chex.deh needed for emulating chex.exe.");
- }
- }
-}
-
-//
-// D_DoomMain
-//
-void D_DoomMain (void)
-{
- int p;
- char file[256];
- char demolumpname[9];
-
- M_FindResponseFile ();
-
- // Undocumented "search for IWADs" parameter used by the setup
- // tool.
-
- if (M_CheckParm("-findiwads") > 0)
- {
- D_FindInstalledIWADs();
- }
-
- // print banner
-
- PrintBanner(PACKAGE_STRING);
-
- printf (DEH_String("Z_Init: Init zone memory allocation daemon. \n"));
- Z_Init ();
-
-#ifdef FEATURE_MULTIPLAYER
- //!
- // @category net
- //
- // Start a dedicated server, routing packets but not participating
- // in the game itself.
- //
-
- if (M_CheckParm("-dedicated") > 0)
- {
- printf("Dedicated server mode.\n");
- NET_DedicatedServer();
-
- // Never returns
- }
-
- //!
- // @arg <address>
- // @category net
- //
- // Query the status of the server running on the given IP
- // address.
- //
-
- p = M_CheckParm("-query");
-
- if (p > 0)
- {
- NET_QueryAddress(myargv[p+1]);
- }
-
- //!
- // @category net
- //
- // Search the local LAN for running servers.
- //
-
- if (M_CheckParm("-search"))
- NET_LANQuery();
-
-#endif
-
-#ifdef FEATURE_DEHACKED
- printf("DEH_Init: Init Dehacked support.\n");
- DEH_Init();
-#endif
-
- iwadfile = D_FindIWAD();
-
- // None found?
-
- if (iwadfile == NULL)
- {
- I_Error("Game mode indeterminate. No IWAD file was found. Try\n"
- "specifying one with the '-iwad' command line parameter.\n");
- }
-
- setbuf (stdout, NULL);
- modifiedgame = false;
-
- //!
- // @vanilla
- //
- // Disable monsters.
- //
-
- nomonsters = M_CheckParm ("-nomonsters");
-
- //!
- // @vanilla
- //
- // Monsters respawn after being killed.
- //
-
- respawnparm = M_CheckParm ("-respawn");
-
- //!
- // @vanilla
- //
- // Monsters move faster.
- //
-
- fastparm = M_CheckParm ("-fast");
-
- //!
- // @vanilla
- //
- // Developer mode. F1 saves a screenshot in the current working
- // directory.
- //
-
- devparm = M_CheckParm ("-devparm");
-
- //!
- // @category net
- // @vanilla
- //
- // Start a deathmatch game.
- //
-
- if (M_CheckParm ("-deathmatch"))
- deathmatch = 1;
-
- //!
- // @category net
- // @vanilla
- //
- // Start a deathmatch 2.0 game. Weapons do not stay in place and
- // all items respawn after 30 seconds.
- //
-
- if (M_CheckParm ("-altdeath"))
- deathmatch = 2;
-
- if (devparm)
- printf(DEH_String(D_DEVSTR));
-
- // find which dir to use for config files
-
- M_SetConfigDir();
-
- //!
- // @arg <x>
- // @vanilla
- //
- // Turbo mode. The player's speed is multiplied by x%. If unspecified,
- // x defaults to 200. Values are rounded up to 10 and down to 400.
- //
-
- if ( (p=M_CheckParm ("-turbo")) )
- {
- int scale = 200;
- extern int forwardmove[2];
- extern int sidemove[2];
-
- if (p<myargc-1)
- scale = atoi (myargv[p+1]);
- if (scale < 10)
- scale = 10;
- if (scale > 400)
- scale = 400;
- printf (DEH_String("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;
- }
-
- // init subsystems
- printf (DEH_String("V_Init: allocate screens.\n"));
- V_Init ();
-
- printf (DEH_String("M_LoadDefaults: Load system defaults.\n"));
- M_LoadDefaults (); // load before initing other systems
-
- printf (DEH_String("W_Init: Init WADfiles.\n"));
- D_AddFile(iwadfile);
-
-#ifdef FEATURE_WAD_MERGE
-
- // Merged PWADs are loaded first, because they are supposed to be
- // modified IWADs.
-
- //!
- // @arg <files>
- // @category mod
- //
- // Simulates the behavior of deutex's -merge option, merging a PWAD
- // into the main IWAD. Multiple files may be specified.
- //
-
- p = M_CheckParm("-merge");
-
- if (p > 0)
- {
- for (p = p + 1; p<myargc && myargv[p][0] != '-'; ++p)
- {
- char *filename;
-
- filename = D_TryFindWADByName(myargv[p]);
-
- printf(" merging %s\n", filename);
- W_MergeFile(filename);
- }
- }
-
- // NWT-style merging:
-
- // NWT's -merge option:
-
- //!
- // @arg <files>
- // @category mod
- //
- // Simulates the behavior of NWT's -merge option. Multiple files
- // may be specified.
-
- p = M_CheckParm("-nwtmerge");
-
- if (p > 0)
- {
- for (p = p + 1; p<myargc && myargv[p][0] != '-'; ++p)
- {
- char *filename;
-
- filename = D_TryFindWADByName(myargv[p]);
-
- printf(" performing NWT-style merge of %s\n", filename);
- W_NWTDashMerge(filename);
- }
- }
-
- // Add flats
-
- //!
- // @arg <files>
- // @category mod
- //
- // Simulates the behavior of NWT's -af option, merging flats into
- // the main IWAD directory. Multiple files may be specified.
- //
-
- p = M_CheckParm("-af");
-
- if (p > 0)
- {
- for (p = p + 1; p<myargc && myargv[p][0] != '-'; ++p)
- {
- char *filename;
-
- filename = D_TryFindWADByName(myargv[p]);
-
- printf(" merging flats from %s\n", filename);
- W_NWTMergeFile(filename, W_NWT_MERGE_FLATS);
- }
- }
-
- //!
- // @arg <files>
- // @category mod
- //
- // Simulates the behavior of NWT's -as option, merging sprites
- // into the main IWAD directory. Multiple files may be specified.
- //
-
- p = M_CheckParm("-as");
-
- if (p > 0)
- {
- for (p = p + 1; p<myargc && myargv[p][0] != '-'; ++p)
- {
- char *filename;
-
- filename = D_TryFindWADByName(myargv[p]);
-
- printf(" merging sprites from %s\n", filename);
- W_NWTMergeFile(filename, W_NWT_MERGE_SPRITES);
- }
- }
-
- //!
- // @arg <files>
- // @category mod
- //
- // Equivalent to "-af <files> -as <files>".
- //
-
- p = M_CheckParm("-aa");
-
- if (p > 0)
- {
- for (p = p + 1; p<myargc && myargv[p][0] != '-'; ++p)
- {
- char *filename;
-
- filename = D_TryFindWADByName(myargv[p]);
-
- printf(" merging sprites and flats from %s\n", filename);
- W_NWTMergeFile(filename, W_NWT_MERGE_SPRITES | W_NWT_MERGE_FLATS);
- }
- }
-
-#endif
-
- //!
- // @arg <files>
- // @vanilla
- //
- // Load the specified PWAD files.
- //
-
- 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] != '-')
- {
- char *filename;
-
- filename = D_TryFindWADByName(myargv[p]);
-
- D_AddFile(filename);
- }
- }
-
- // Debug:
-// W_PrintDirectory();
-
- // 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
-
- // Map name handling.
- switch (gamemode )
- {
- case shareware:
- case retail:
- case registered:
- 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]);
- break;
-
- case commercial:
- default:
- 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);
- break;
- }
- D_AddFile (file);
- }
-
- //!
- // @arg <demo>
- // @category demo
- // @vanilla
- //
- // Play back the demo named demo.lmp.
- //
-
- p = M_CheckParm ("-playdemo");
-
- if (!p)
- {
- //!
- // @arg <demo>
- // @category demo
- // @vanilla
- //
- // Play back the demo named demo.lmp, determining the framerate
- // of the screen.
- //
- p = M_CheckParm ("-timedemo");
-
- }
-
- if (p && p < myargc-1)
- {
- if (!strcasecmp(myargv[p+1] + strlen(myargv[p+1]) - 4, ".lmp"))
- {
- strcpy(file, myargv[p + 1]);
- }
- else
- {
- sprintf (file,"%s.lmp", myargv[p+1]);
- }
-
- if (D_AddFile (file))
- {
- strncpy(demolumpname, lumpinfo[numlumps - 1].name, 8);
- demolumpname[8] = '\0';
-
- printf("Playing demo %s.\n", file);
- }
- else
- {
- // If file failed to load, still continue trying to play
- // the demo in the same way as Vanilla Doom. This makes
- // tricks like "-playdemo demo1" possible.
-
- strncpy(demolumpname, myargv[p + 1], 8);
- demolumpname[8] = '\0';
- }
-
- }
-
- // Generate the WAD hash table. Speed things up a bit.
-
- W_GenerateHashTable();
-
- D_IdentifyVersion();
- InitGameVersion();
- LoadChexDeh();
- D_SetGameDescription();
- D_SetSaveGameDir();
-
- // Check for -file in shareware
- if (modifiedgame)
- {
- // These are the lumps that will be checked in IWAD,
- // if any one is not present, execution will be aborted.
- 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 ( gamemode == shareware)
- I_Error(DEH_String("\nYou cannot -file with the shareware "
- "version. Register!"));
-
- // Check for fake IWAD with right name,
- // but w/o all the lumps of the registered version.
- if (gamemode == registered)
- for (i = 0;i < 23; i++)
- if (W_CheckNumForName(name[i])<0)
- I_Error(DEH_String("\nThis is not the registered version."));
- }
-
- // get skill / episode / map from parms
- startskill = sk_medium;
- startepisode = 1;
- startmap = 1;
- autostart = false;
-
- //!
- // @arg <skill>
- // @vanilla
- //
- // Set the game skill, 1-5 (1: easiest, 5: hardest). A skill of
- // 0 disables all monsters.
- //
-
- p = M_CheckParm ("-skill");
-
- if (p && p < myargc-1)
- {
- startskill = myargv[p+1][0]-'1';
- autostart = true;
- }
-
- //!
- // @arg <n>
- // @vanilla
- //
- // Start playing on episode n (1-4)
- //
-
- p = M_CheckParm ("-episode");
-
- if (p && p < myargc-1)
- {
- startepisode = myargv[p+1][0]-'0';
- startmap = 1;
- autostart = true;
- }
-
- timelimit = 0;
-
- //!
- // @arg <n>
- // @category net
- // @vanilla
- //
- // For multiplayer games: exit each level after n minutes.
- //
-
- p = M_CheckParm ("-timer");
-
- if (p && p < myargc-1 && deathmatch)
- {
- timelimit = atoi(myargv[p+1]);
- printf("timer: %i\n", timelimit);
- }
-
- //!
- // @category net
- // @vanilla
- //
- // Austin Virtual Gaming: end levels after 20 minutes.
- //
-
- p = M_CheckParm ("-avg");
-
- if (p && p < myargc-1 && deathmatch)
- {
- printf(DEH_String("Austin Virtual Gaming: Levels will end "
- "after 20 minutes\n"));
- timelimit = 20;
- }
-
- //!
- // @arg [<x> <y> | <xy>]
- // @vanilla
- //
- // Start a game immediately, warping to ExMy (Doom 1) or MAPxy
- // (Doom 2)
- //
-
- p = M_CheckParm ("-warp");
-
- if (p && p < myargc-1)
- {
- if (gamemode == commercial)
- startmap = atoi (myargv[p+1]);
- else
- {
- startepisode = myargv[p+1][0]-'0';
-
- if (p + 2 < myargc)
- {
- startmap = myargv[p+2][0]-'0';
- }
- else
- {
- startmap = 1;
- }
- }
- autostart = true;
- }
-
- // Undocumented:
- // Invoked by setup to test the controls.
-
- p = M_CheckParm("-testcontrols");
-
- if (p > 0)
- {
- startepisode = 1;
- startmap = 1;
- autostart = true;
- testcontrols = true;
- }
-
- // Check for load game parameter
- // We do this here and save the slot number, so that the network code
- // can override it or send the load slot to other players.
-
- //!
- // @arg <s>
- // @vanilla
- //
- // Load the game in slot s.
- //
-
- p = M_CheckParm ("-loadgame");
-
- if (p && p < myargc-1)
- {
- startloadgame = atoi(myargv[p+1]);
- }
- else
- {
- // Not loading a game
- startloadgame = -1;
- }
-
- //!
- // @category video
- //
- // Disable vertical mouse movement.
- //
-
- if (M_CheckParm("-novert"))
- novert = true;
-
- //!
- // @category video
- //
- // Enable vertical mouse movement.
- //
-
- if (M_CheckParm("-nonovert"))
- novert = false;
-
- if (W_CheckNumForName("SS_START") >= 0
- || W_CheckNumForName("FF_END") >= 0)
- {
- printf ("===========================================================================\n");
- printf(" WARNING: The loaded WAD file contains modified sprites or\n"
- " floor textures. You may want to use the '-merge' command\n"
- " line option instead of '-file'.\n");
- }
-
- printf ("===========================================================================\n");
-
- PrintBanner(gamedescription);
-
-
- printf (
- "===========================================================================\n"
- " " PACKAGE_NAME " is free software, covered by the GNU General Public\n"
- " License. There is NO warranty; not even for MERCHANTABILITY or FITNESS\n"
- " FOR A PARTICULAR PURPOSE. You are welcome to change and distribute\n"
- " copies under certain conditions. See the source for more information.\n"
-
- "===========================================================================\n"
- );
-
- PrintDehackedBanners();
-
- printf (DEH_String("M_Init: Init miscellaneous info.\n"));
- M_Init ();
-
- printf (DEH_String("R_Init: Init DOOM refresh daemon - "));
- R_Init ();
-
- printf (DEH_String("\nP_Init: Init Playloop state.\n"));
- P_Init ();
-
- printf (DEH_String("I_Init: Setting up machine state.\n"));
- I_Init ();
-
-#ifdef FEATURE_MULTIPLAYER
- printf ("NET_Init: Initialise network subsystem.\n");
- NET_Init ();
-#endif
-
- printf (DEH_String("S_Init: Setting up sound.\n"));
- S_Init (sfxVolume * 8, musicVolume * 8);
-
- printf (DEH_String("D_CheckNetGame: Checking network game status.\n"));
- D_CheckNetGame ();
-
- PrintGameVersion();
-
- printf (DEH_String("HU_Init: Setting up heads up display.\n"));
- HU_Init ();
-
- printf (DEH_String("ST_Init: Init status bar.\n"));
- ST_Init ();
-
- // If Doom II without a MAP01 lump, this is a store demo.
- // Moved this here so that MAP01 isn't constantly looked up
- // in the main loop.
-
- if (gamemode == commercial && W_CheckNumForName("map01") < 0)
- storedemo = true;
-
- //!
- // @arg <x>
- // @category demo
- // @vanilla
- //
- // Record a demo named x.lmp.
- //
-
- p = M_CheckParm ("-record");
-
- if (p && p < myargc-1)
- {
- G_RecordDemo (myargv[p+1]);
- autostart = true;
- }
-
- p = M_CheckParm ("-playdemo");
- if (p && p < myargc-1)
- {
- singledemo = true; // quit after one demo
- G_DeferedPlayDemo (demolumpname);
- D_DoomLoop (); // never returns
- }
-
- p = M_CheckParm ("-timedemo");
- if (p && p < myargc-1)
- {
- G_TimeDemo (demolumpname);
- D_DoomLoop (); // never returns
- }
-
- if (startloadgame >= 0)
- {
- strcpy(file, P_SaveGameFile(startloadgame));
- G_LoadGame (file);
- }
-
- if (gameaction != ga_loadgame )
- {
- if (autostart || netgame)
- G_InitNew (startskill, startepisode, startmap);
- else
- D_StartTitle (); // start up intro loop
- }
-
- D_DoomLoop (); // never returns
-}
-
--- a/src/d_main.h
+++ /dev/null
@@ -1,66 +1,0 @@
-// Emacs style mode select -*- C++ -*-
-//-----------------------------------------------------------------------------
-//
-// Copyright(C) 1993-1996 Id Software, Inc.
-// Copyright(C) 2005 Simon Howard
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-// 02111-1307, USA.
-//
-// DESCRIPTION:
-// System specific interface stuff.
-//
-//-----------------------------------------------------------------------------
-
-
-#ifndef __D_MAIN__
-#define __D_MAIN__
-
-#include "d_event.h"
-
-
-
-
-//
-// D_DoomMain()
-// Not a globally visible function, just included for source reference,
-// calls all startup code, parses command line options.
-// If not overrided by user input, calls N_AdvanceDemo.
-//
-void D_DoomMain (void);
-
-// Called by IO functions when input is detected.
-void D_PostEvent (event_t *ev);
-
-// Read an event from the event queue
-
-event_t *D_PopEvent(void);
-
-// Read events from all input devices
-
-void D_ProcessEvents (void);
-
-
-//
-// BASE LEVEL
-//
-void D_PageTicker (void);
-void D_PageDrawer (void);
-void D_AdvanceDemo (void);
-void D_DoAdvanceDemo (void);
-void D_StartTitle (void);
-
-
-#endif
--- a/src/d_net.c
+++ /dev/null
@@ -1,620 +1,0 @@
-// Emacs style mode select -*- C++ -*-
-//-----------------------------------------------------------------------------
-//
-// Copyright(C) 1993-1996 Id Software, Inc.
-// Copyright(C) 2005 Simon Howard
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-// 02111-1307, USA.
-//
-// DESCRIPTION:
-// DOOM Network game communication and protocol,
-// all OS independend parts.
-//
-//-----------------------------------------------------------------------------
-
-
-
-#include "doomfeatures.h"
-
-#include "d_main.h"
-#include "m_argv.h"
-#include "m_menu.h"
-#include "i_system.h"
-#include "i_timer.h"
-#include "i_video.h"
-#include "g_game.h"
-#include "doomdef.h"
-#include "doomstat.h"
-
-#include "deh_main.h"
-
-#include "net_client.h"
-#include "net_gui.h"
-#include "net_io.h"
-#include "net_query.h"
-#include "net_server.h"
-#include "net_sdl.h"
-#include "net_loop.h"
-
-
-//
-// NETWORKING
-//
-// gametic is the tic about to (or currently being) run
-// maketic is the tick that hasn't had control made for it yet
-// nettics[] has the maketics for all players
-//
-// a gametic cannot be run until nettics[] > gametic for all players
-//
-
-ticcmd_t netcmds[MAXPLAYERS][BACKUPTICS];
-int nettics[MAXPLAYERS];
-
-int maketic;
-
-// Used for original sync code.
-
-int lastnettic;
-int skiptics = 0;
-
-// Reduce the bandwidth needed by sampling game input less and transmitting
-// less. If ticdup is 2, sample half normal, 3 = one third normal, etc.
-
-int ticdup;
-
-// Send this many extra (backup) tics in each packet.
-
-int extratics;
-
-// Amount to offset the timer for game sync.
-
-fixed_t offsetms;
-
-// Use new client syncronisation code
-
-boolean net_cl_new_sync = true;
-
-// Connected but not participating in the game (observer)
-
-boolean drone = false;
-
-// 35 fps clock adjusted by offsetms milliseconds
-
-static int GetAdjustedTime(void)
-{
- int time_ms;
-
- time_ms = I_GetTimeMS();
-
- if (net_cl_new_sync)
- {
- // Use the adjustments from net_client.c only if we are
- // using the new sync mode.
-
- time_ms += (offsetms / FRACUNIT);
- }
-
- return (time_ms * TICRATE) / 1000;
-}
-
-//
-// NetUpdate
-// Builds ticcmds for console player,
-// sends out a packet
-//
-int lasttime;
-
-void NetUpdate (void)
-{
- int nowtime;
- int newtics;
- int i;
- int gameticdiv;
-
- // If we are running with singletics (timing a demo), this
- // is all done separately.
-
- if (singletics)
- return;
-
-#ifdef FEATURE_MULTIPLAYER
-
- // Run network subsystems
-
- NET_CL_Run();
- NET_SV_Run();
-
-#endif
-
- // check time
- nowtime = GetAdjustedTime() / ticdup;
- newtics = nowtime - lasttime;
-
- lasttime = nowtime;
-
- if (skiptics <= newtics)
- {
- newtics -= skiptics;
- skiptics = 0;
- }
- else
- {
- skiptics -= newtics;
- newtics = 0;
- }
-
- // build new ticcmds for console player
- gameticdiv = gametic/ticdup;
-
- for (i=0 ; i<newtics ; i++)
- {
- ticcmd_t cmd;
-
- I_StartTic ();
- D_ProcessEvents ();
-
- // Always run the menu
-
- M_Ticker ();
-
- if (drone)
- {
- // In drone mode, do not generate any ticcmds.
-
- continue;
- }
-
- if (net_cl_new_sync)
- {
- // If playing single player, do not allow tics to buffer
- // up very far
-
- if ((!netgame || demoplayback) && maketic - gameticdiv > 2)
- break;
-
- // Never go more than ~200ms ahead
-
- if (maketic - gameticdiv > 8)
- break;
- }
- else
- {
- if (maketic - gameticdiv >= 5)
- break;
- }
-
- //printf ("mk:%i ",maketic);
- G_BuildTiccmd(&cmd);
-
-#ifdef FEATURE_MULTIPLAYER
-
- if (netgame && !demoplayback)
- {
- NET_CL_SendTiccmd(&cmd, maketic);
- }
-
-#endif
- netcmds[consoleplayer][maketic % BACKUPTICS] = cmd;
-
- ++maketic;
- nettics[consoleplayer] = maketic;
- }
-}
-
-//
-// Start game loop
-//
-// Called after the screen is set but before the game starts running.
-//
-
-void D_StartGameLoop(void)
-{
- lasttime = GetAdjustedTime() / ticdup;
-}
-
-
-//
-// D_CheckNetGame
-// Works out player numbers among the net participants
-//
-extern int viewangleoffset;
-
-void D_CheckNetGame (void)
-{
- int i;
- int num_players;
-
- // default values for single player
-
- consoleplayer = 0;
- netgame = false;
- ticdup = 1;
- extratics = 1;
- lowres_turn = false;
- offsetms = 0;
-
- for (i=0; i<MAXPLAYERS; i++)
- {
- playeringame[i] = false;
- nettics[i] = 0;
- }
-
- playeringame[0] = true;
-
-#ifdef FEATURE_MULTIPLAYER
-
- {
- net_addr_t *addr = NULL;
-
- //!
- // @category net
- //
- // Start a multiplayer server, listening for connections.
- //
-
- if (M_CheckParm("-server") > 0)
- {
- NET_SV_Init();
- NET_SV_AddModule(&net_loop_server_module);
- NET_SV_AddModule(&net_sdl_module);
-
- net_loop_client_module.InitClient();
- addr = net_loop_client_module.ResolveAddress(NULL);
- }
- else
- {
- //!
- // @category net
- //
- // Automatically search the local LAN for a multiplayer
- // server and join it.
- //
-
- i = M_CheckParm("-autojoin");
-
- if (i > 0)
- {
- addr = NET_FindLANServer();
-
- if (addr == NULL)
- {
- I_Error("No server found on local LAN");
- }
- }
-
- //!
- // @arg <address>
- // @category net
- //
- // Connect to a multiplayer server running on the given
- // address.
- //
-
- i = M_CheckParm("-connect");
-
- if (i > 0)
- {
- net_sdl_module.InitClient();
- addr = net_sdl_module.ResolveAddress(myargv[i+1]);
-
- if (addr == NULL)
- {
- I_Error("Unable to resolve '%s'\n", myargv[i+1]);
- }
- }
- }
-
- if (addr != NULL)
- {
- if (M_CheckParm("-drone") > 0)
- {
- drone = true;
- }
-
- //!
- // @category net
- //
- // Run as the left screen in three screen mode.
- //
-
- if (M_CheckParm("-left") > 0)
- {
- viewangleoffset = ANG90;
- drone = true;
- }
-
- //!
- // @category net
- //
- // Run as the right screen in three screen mode.
- //
-
- if (M_CheckParm("-right") > 0)
- {
- viewangleoffset = ANG270;
- drone = true;
- }
-
- if (!NET_CL_Connect(addr))
- {
- I_Error("D_CheckNetGame: Failed to connect to %s\n",
- NET_AddrToString(addr));
- }
-
- printf("D_CheckNetGame: Connected to %s\n", NET_AddrToString(addr));
-
- NET_WaitForStart();
- }
- }
-
-#endif
-
- num_players = 0;
-
- for (i=0; i<MAXPLAYERS; ++i)
- {
- if (playeringame[i])
- ++num_players;
- }
-
- printf (DEH_String("startskill %i deathmatch: %i startmap: %i startepisode: %i\n"),
- startskill, deathmatch, startmap, startepisode);
-
- printf(DEH_String("player %i of %i (%i nodes)\n"),
- consoleplayer+1, num_players, num_players);
-
- // Show players here; the server might have specified a time limit
-
- if (timelimit > 0)
- {
- printf(DEH_String("Levels will end after %d minute"),timelimit);
- if (timelimit > 1)
- printf("s");
- printf(".\n");
- }
-}
-
-
-//
-// D_QuitNetGame
-// Called before quitting to leave a net game
-// without hanging the other players
-//
-void D_QuitNetGame (void)
-{
- if (debugfile)
- fclose (debugfile);
-
-#ifdef FEATURE_MULTIPLAYER
-
- NET_SV_Shutdown();
- NET_CL_Disconnect();
-
-#endif
-
-}
-
-// Returns true if there are currently any players in the game.
-
-static boolean PlayersInGame(void)
-{
- int i;
-
- for (i=0; i<MAXPLAYERS; ++i)
- {
- if (playeringame[i])
- {
- return true;
- }
- }
-
- return false;
-}
-
-static int GetLowTic(void)
-{
- int i;
- int lowtic;
-
- if (net_client_connected)
- {
- lowtic = INT_MAX;
-
- for (i=0; i<MAXPLAYERS; ++i)
- {
- if (playeringame[i])
- {
- if (nettics[i] < lowtic)
- lowtic = nettics[i];
- }
- }
- }
- else
- {
- lowtic = maketic;
- }
-
- return lowtic;
-}
-
-//
-// TryRunTics
-//
-int oldnettics;
-int frametics[4];
-int frameon;
-int frameskip[4];
-int oldnettics;
-
-extern boolean advancedemo;
-
-void TryRunTics (void)
-{
- int i;
- int lowtic;
- int entertic;
- static int oldentertics;
- int realtics;
- int availabletics;
- int counts;
-
- // get real tics
- entertic = I_GetTime() / ticdup;
- realtics = entertic - oldentertics;
- oldentertics = entertic;
-
- // get available tics
- NetUpdate ();
-
- lowtic = GetLowTic();
-
- availabletics = lowtic - gametic/ticdup;
-
- // decide how many tics to run
-
- if (net_cl_new_sync)
- {
- counts = availabletics;
- }
- else
- {
- // 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 (!demoplayback)
- {
- int keyplayer = -1;
-
- // ideally maketic should be 1 - 3 tics above lowtic
- // if we are consistantly slower, speed up time
-
- for (i=0 ; i<MAXPLAYERS ; i++)
- {
- if (playeringame[i])
- {
- keyplayer = i;
- break;
- }
- }
-
- if (keyplayer < 0)
- {
- // If there are no players, we can never advance anyway
-
- return;
- }
-
- if (consoleplayer == keyplayer)
- {
- // the key player does not adapt
- }
- else
- {
- if (maketic <= nettics[keyplayer])
- {
- lasttime--;
- // printf ("-");
- }
-
- frameskip[frameon & 3] = (oldnettics > nettics[keyplayer]);
- oldnettics = maketic;
-
- if (frameskip[0] && frameskip[1] && frameskip[2] && frameskip[3])
- {
- skiptics = 1;
- // printf ("+");
- }
- }
- }
- }
-
- if (counts < 1)
- counts = 1;
-
- // wait for new tics if needed
-
- while (!PlayersInGame() || lowtic < gametic/ticdup + counts)
- {
- NetUpdate ();
-
- lowtic = GetLowTic();
-
- if (lowtic < gametic/ticdup)
- I_Error ("TryRunTics: lowtic < gametic");
-
- // Don't stay in this loop forever. The menu is still running,
- // so return to update the screen
-
- if (I_GetTime() / ticdup - entertic > 0)
- {
- return;
- }
-
- I_Sleep(1);
- }
-
- // run the count * ticdup dics
- while (counts--)
- {
- for (i=0 ; i<ticdup ; i++)
- {
- // check that there are players in the game. if not, we cannot
- // run a tic.
-
- if (!PlayersInGame())
- {
- return;
- }
-
- if (gametic/ticdup > lowtic)
- I_Error ("gametic>lowtic");
- if (advancedemo)
- D_DoAdvanceDemo ();
-
- 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 ; j<MAXPLAYERS ; j++)
- {
- cmd = &netcmds[j][buf];
- cmd->chatchar = 0;
- if (cmd->buttons & BT_SPECIAL)
- cmd->buttons = 0;
- }
- }
- }
- NetUpdate (); // check for new console commands
- }
-}
-
--- a/src/d_net.h
+++ /dev/null
@@ -1,57 +1,0 @@
-// Emacs style mode select -*- C++ -*-
-//-----------------------------------------------------------------------------
-//
-// Copyright(C) 1993-1996 Id Software, Inc.
-// Copyright(C) 2005 Simon Howard
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-// 02111-1307, USA.
-//
-// DESCRIPTION:
-// Networking stuff.
-//
-//-----------------------------------------------------------------------------
-
-
-#ifndef __D_NET__
-#define __D_NET__
-
-#include "d_player.h"
-
-#define MAXNETNODES 8
-
-// Networking and tick handling related.
-#define BACKUPTICS 128
-
-extern int extratics;
-
-// Create any new ticcmds and broadcast to other players.
-void NetUpdate (void);
-
-// Broadcasts special packets to other players
-// to notify of game exit
-void D_QuitNetGame (void);
-
-//? how many ticks to run?
-void TryRunTics (void);
-
-// Called at start of game loop to initialise timers
-void D_StartGameLoop(void);
-
-extern boolean drone;
-extern boolean net_cl_new_sync;
-
-#endif
-
--- a/src/d_player.h
+++ /dev/null
@@ -1,216 +1,0 @@
-// Emacs style mode select -*- C++ -*-
-//-----------------------------------------------------------------------------
-//
-// Copyright(C) 1993-1996 Id Software, Inc.
-// Copyright(C) 2005 Simon Howard
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-// 02111-1307, USA.
-//
-// DESCRIPTION:
-//
-//
-//-----------------------------------------------------------------------------
-
-
-#ifndef __D_PLAYER__
-#define __D_PLAYER__
-
-
-// The player data structure depends on a number
-// of other structs: items (internal inventory),
-// animation states (closely tied to the sprites
-// used to represent them, unfortunately).
-#include "d_items.h"
-#include "p_pspr.h"
-
-// In addition, the player is just a special
-// case of the generic moving object/actor.
-#include "p_mobj.h"
-
-// Finally, for odd reasons, the player input
-// is buffered within the player data struct,
-// as commands per game tick.
-#include "d_ticcmd.h"
-
-
-
-
-
-//
-// Player states.
-//
-typedef enum
-{
- // Playing or camping.
- PST_LIVE,
- // Dead on the ground, view follows killer.
- PST_DEAD,
- // Ready to restart/respawn???
- PST_REBORN
-
-} playerstate_t;
-
-
-//
-// Player internal flags, for cheats and debug.
-//
-typedef enum
-{
- // No clipping, walk through barriers.
- CF_NOCLIP = 1,
- // No damage, no health loss.
- CF_GODMODE = 2,
- // Not really a cheat, just a debug aid.
- CF_NOMOMENTUM = 4
-
-} cheat_t;
-
-
-//
-// Extended player object info: player_t
-//
-typedef struct player_s
-{
- mobj_t* mo;
- playerstate_t playerstate;
- ticcmd_t cmd;
-
- // Determine POV,
- // including viewpoint bobbing during movement.
- // Focal origin above r.z
- fixed_t viewz;
- // Base height above floor for viewz.
- fixed_t viewheight;
- // Bob/squat speed.
- fixed_t deltaviewheight;
- // bounded/scaled total momentum.
- fixed_t bob;
-
- // This is only used between levels,
- // mo->health is used during levels.
- int health;
- int armorpoints;
- // Armor type is 0-2.
- int armortype;
-
- // Power ups. invinc and invis are tic counters.
- int powers[NUMPOWERS];
- boolean cards[NUMCARDS];
- boolean backpack;
-
- // Frags, kills of other players.
- int frags[MAXPLAYERS];
- weapontype_t readyweapon;
-
- // Is wp_nochange if not changing.
- weapontype_t pendingweapon;
-
- boolean weaponowned[NUMWEAPONS];
- int ammo[NUMAMMO];
- int maxammo[NUMAMMO];
-
- // True if button down last tic.
- int attackdown;
- int usedown;
-
- // Bit flags, for cheats and debug.
- // See cheat_t, above.
- int cheats;
-
- // Refired shots are less accurate.
- int refire;
-
- // For intermission stats.
- int killcount;
- int itemcount;
- int secretcount;
-
- // Hint messages.
- char* message;
-
- // For screen flashing (red or bright).
- int damagecount;
- int bonuscount;
-
- // Who did damage (NULL for floors/ceilings).
- mobj_t* attacker;
-
- // So gun flashes light up areas.
- int extralight;
-
- // Current PLAYPAL, ???
- // can be set to REDCOLORMAP for pain, etc.
- int fixedcolormap;
-
- // Player skin colorshift,
- // 0-3 for which color to draw player.
- int colormap;
-
- // Overlay view sprites (gun, etc).
- pspdef_t psprites[NUMPSPRITES];
-
- // True if secret level has been done.
- boolean didsecret;
-
-} player_t;
-
-
-//
-// INTERMISSION
-// Structure passed e.g. to WI_Start(wb)
-//
-typedef struct
-{
- boolean in; // whether the player is in game
-
- // Player stats, kills, collected items etc.
- int skills;
- int sitems;
- int ssecret;
- int stime;
- int frags[4];
- int score; // current score on entry, modified on return
-
-} wbplayerstruct_t;
-
-typedef struct
-{
- int epsd; // episode # (0-2)
-
- // if true, splash the secret level
- boolean didsecret;
-
- // previous and next levels, origin 0
- int last;
- int next;
-
- int maxkills;
- int maxitems;
- int maxsecret;
- int maxfrags;
-
- // the par time
- int partime;
-
- // index of this player in game
- int pnum;
-
- wbplayerstruct_t plyr[MAXPLAYERS];
-
-} wbstartstruct_t;
-
-
-#endif
--- a/src/d_textur.h
+++ /dev/null
@@ -1,51 +1,0 @@
-// Emacs style mode select -*- C++ -*-
-//-----------------------------------------------------------------------------
-//
-// Copyright(C) 1993-1996 Id Software, Inc.
-// Copyright(C) 2005 Simon Howard
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-// 02111-1307, USA.
-//
-// DESCRIPTION:
-// Typedefs related to to textures etc.,
-// isolated here to make it easier separating modules.
-//
-//-----------------------------------------------------------------------------
-
-
-#ifndef __D_TEXTUR__
-#define __D_TEXTUR__
-
-#include "doomtype.h"
-
-
-
-
-//
-// Flats?
-//
-// a pic is an unmasked block of pixels
-typedef struct
-{
- byte width;
- byte height;
- byte data;
-} pic_t;
-
-
-
-
-#endif
--- a/src/d_think.h
+++ /dev/null
@@ -1,76 +1,0 @@
-// Emacs style mode select -*- C++ -*-
-//-----------------------------------------------------------------------------
-//
-// Copyright(C) 1993-1996 Id Software, Inc.
-// Copyright(C) 2005 Simon Howard
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-// 02111-1307, USA.
-//
-// DESCRIPTION:
-// MapObj data. Map Objects or mobjs are actors, entities,
-// thinker, take-your-pick... anything that moves, acts, or
-// suffers state changes of more or less violent nature.
-//
-//-----------------------------------------------------------------------------
-
-
-#ifndef __D_THINK__
-#define __D_THINK__
-
-
-
-
-
-//
-// Experimental stuff.
-// To compile this as "ANSI C with classes"
-// we will need to handle the various
-// action functions cleanly.
-//
-typedef void (*actionf_v)();
-typedef void (*actionf_p1)( void* );
-typedef void (*actionf_p2)( void*, void* );
-
-typedef union
-{
- actionf_v acv;
- actionf_p1 acp1;
- actionf_p2 acp2;
-
-} actionf_t;
-
-
-
-
-
-// Historically, "think_t" is yet another
-// function pointer to a routine to handle
-// an actor.
-typedef actionf_t think_t;
-
-
-// Doubly linked list of actors.
-typedef struct thinker_s
-{
- struct thinker_s* prev;
- struct thinker_s* next;
- think_t function;
-
-} thinker_t;
-
-
-
-#endif
--- /dev/null
+++ b/src/doom/am_map.c
@@ -1,0 +1,1373 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+//
+// DESCRIPTION: the automap code
+//
+//-----------------------------------------------------------------------------
+
+
+#include <stdio.h>
+
+#include "deh_main.h"
+
+#include "z_zone.h"
+#include "doomdef.h"
+#include "st_stuff.h"
+#include "p_local.h"
+#include "w_wad.h"
+
+#include "m_cheat.h"
+#include "i_system.h"
+
+// Needs access to LFB.
+#include "v_video.h"
+
+// State.
+#include "doomstat.h"
+#include "r_state.h"
+
+// Data.
+#include "dstrings.h"
+
+#include "am_map.h"
+
+
+// For use if I do walls with outsides/insides
+#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
+
+// 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;
+
+
+
+//
+// The vector graphics for the automap.
+// A line drawing of the player pointing right,
+// starting from the middle.
+//
+#define R ((8*PLAYERRADIUS)/7)
+mline_t player_arrow[] = {
+ { { -R+R/8, 0 }, { R, 0 } }, // -----
+ { { R, 0 }, { R-R/2, R/4 } }, // ----->
+ { { R, 0 }, { R-R/2, -R/4 } },
+ { { -R+R/8, 0 }, { -R-R/8, R/4 } }, // >---->
+ { { -R+R/8, 0 }, { -R-R/8, -R/4 } },
+ { { -R+3*R/8, 0 }, { -R+R/8, R/4 } }, // >>--->
+ { { -R+3*R/8, 0 }, { -R+R/8, -R/4 } }
+};
+#undef R
+
+#define R ((8*PLAYERRADIUS)/7)
+mline_t cheat_player_arrow[] = {
+ { { -R+R/8, 0 }, { R, 0 } }, // -----
+ { { R, 0 }, { R-R/2, R/6 } }, // ----->
+ { { R, 0 }, { R-R/2, -R/6 } },
+ { { -R+R/8, 0 }, { -R-R/8, R/6 } }, // >----->
+ { { -R+R/8, 0 }, { -R-R/8, -R/6 } },
+ { { -R+3*R/8, 0 }, { -R+R/8, R/6 } }, // >>----->
+ { { -R+3*R/8, 0 }, { -R+R/8, -R/6 } },
+ { { -R/2, 0 }, { -R/2, -R/6 } }, // >>-d--->
+ { { -R/2, -R/6 }, { -R/2+R/6, -R/6 } },
+ { { -R/2+R/6, -R/6 }, { -R/2+R/6, R/4 } },
+ { { -R/6, 0 }, { -R/6, -R/6 } }, // >>-dd-->
+ { { -R/6, -R/6 }, { 0, -R/6 } },
+ { { 0, -R/6 }, { 0, R/4 } },
+ { { R/6, R/4 }, { R/6, -R/7 } }, // >>-ddt->
+ { { R/6, -R/7 }, { R/6+R/32, -R/7-R/32 } },
+ { { R/6+R/32, -R/7-R/32 }, { R/6+R/10, -R/7 } }
+};
+#undef R
+
+#define R (FRACUNIT)
+mline_t triangle_guy[] = {
+ { { (fixed_t)(-.867*R), (fixed_t)(-.5*R) }, { (fixed_t)(.867*R ), (fixed_t)(-.5*R) } },
+ { { (fixed_t)(.867*R ), (fixed_t)(-.5*R) }, { (fixed_t)(0 ), (fixed_t)(R ) } },
+ { { (fixed_t)(0 ), (fixed_t)(R ) }, { (fixed_t)(-.867*R), (fixed_t)(-.5*R) } }
+};
+#undef R
+
+#define R (FRACUNIT)
+mline_t thintriangle_guy[] = {
+ { { (fixed_t)(-.5*R), (fixed_t)(-.7*R) }, { (fixed_t)(R ), (fixed_t)(0 ) } },
+ { { (fixed_t)(R ), (fixed_t)(0 ) }, { (fixed_t)(-.5*R), (fixed_t)(.7*R ) } },
+ { { (fixed_t)(-.5*R), (fixed_t)(.7*R ) }, { (fixed_t)(-.5*R), (fixed_t)(-.7*R) } }
+};
+#undef R
+
+
+
+
+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;
+
+// location of window on screen
+static int f_x;
+static int f_y;
+
+// size of window on screen
+static int f_w;
+static int f_h;
+
+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;
+static fixed_t m_h;
+
+// based on level size
+static fixed_t min_x;
+static fixed_t min_y;
+static fixed_t max_x;
+static fixed_t max_y;
+
+static fixed_t max_w; // max_x-min_x,
+static fixed_t max_h; // max_y-min_y
+
+// based on player size
+static fixed_t min_w;
+static fixed_t min_h;
+
+
+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 = (fixed_t)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
+
+cheatseq_t cheat_amap = CHEAT("iddt", 0);
+
+static boolean stopped = true;
+
+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?-INT_MAX:INT_MAX);
+ else is->islp = FixedDiv(dx, dy);
+ if (!dx) is->slp = (dy<0?-INT_MAX:INT_MAX);
+ 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<<FRACBITS, m_w);
+ scale_ftom = FixedDiv(FRACUNIT, scale_mtof);
+}
+
+//
+// adds a marker at the current location
+//
+void AM_addMark(void)
+{
+ markpoints[markpointnum].x = m_x + m_w/2;
+ markpoints[markpointnum].y = m_y + m_h/2;
+ markpointnum = (markpointnum + 1) % AM_NUMMARKPOINTS;
+
+}
+
+//
+// Determines bounding box of all vertices,
+// sets global variables controlling zoom range.
+//
+void AM_findMinMaxBoundaries(void)
+{
+ int i;
+ fixed_t a;
+ fixed_t b;
+
+ min_x = min_y = INT_MAX;
+ max_x = max_y = -INT_MAX;
+
+ for (i=0;i<numvertexes;i++)
+ {
+ if (vertexes[i].x < min_x)
+ min_x = vertexes[i].x;
+ else if (vertexes[i].x > 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; // const? never changed?
+ min_h = 2*PLAYERRADIUS;
+
+ a = FixedDiv(f_w<<FRACBITS, max_w);
+ b = FixedDiv(f_h<<FRACBITS, max_h);
+
+ min_scale_mtof = a < b ? a : b;
+ max_scale_mtof = FixedDiv(f_h<<FRACBITS, 2*PLAYERRADIUS);
+
+}
+
+
+//
+//
+//
+void AM_changeWindowLoc(void)
+{
+ if (m_paninc.x || m_paninc.y)
+ {
+ followplayer = 0;
+ f_oldloc.x = INT_MAX;
+ }
+
+ m_x += m_paninc.x;
+ m_y += m_paninc.y;
+
+ if (m_x + m_w/2 > 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, 0, 0 };
+
+ automapactive = true;
+ fb = screens[0];
+
+ f_oldloc.x = INT_MAX;
+ 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[consoleplayer])
+ {
+ plr = &players[consoleplayer];
+ }
+ else
+ {
+ plr = &players[0];
+
+ for (pnum=0;pnum<MAXPLAYERS;pnum++)
+ {
+ if (playeringame[pnum])
+ {
+ plr = &players[pnum];
+ break;
+ }
+ }
+ }
+
+ m_x = plr->mo->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, DEH_String("AMMNUM%d"), i);
+ marknums[i] = W_CacheLumpName(namebuf, PU_STATIC);
+ }
+
+}
+
+void AM_unloadPics(void)
+{
+ int i;
+ char namebuf[9];
+
+ for (i=0;i<10;i++)
+ {
+ sprintf(namebuf, DEH_String("AMMNUM%d"), i);
+ W_ReleaseLumpName(namebuf);
+ }
+}
+
+void AM_clearMarks(void)
+{
+ int i;
+
+ for (i=0;i<AM_NUMMARKPOINTS;i++)
+ markpoints[i].x = -1; // means empty
+ markpointnum = 0;
+}
+
+//
+// should be called at the start of every level
+// right now, i figure it out myself
+//
+void AM_LevelInit(void)
+{
+ leveljuststarted = 0;
+
+ f_x = f_y = 0;
+ f_w = finit_width;
+ f_h = finit_height;
+
+ AM_clearMarks();
+
+ AM_findMinMaxBoundaries();
+ scale_mtof = FixedDiv(min_scale_mtof, (int) (0.7*FRACUNIT));
+ if (scale_mtof > max_scale_mtof)
+ scale_mtof = min_scale_mtof;
+ scale_ftom = FixedDiv(FRACUNIT, scale_mtof);
+}
+
+
+
+
+//
+//
+//
+void AM_Stop (void)
+{
+ static event_t st_notify = { 0, ev_keyup, AM_MSGEXITED, 0 };
+
+ 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();
+}
+
+
+//
+// Handle events (user inputs) in automap mode
+//
+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 = INT_MAX;
+ if (followplayer)
+ plr->message = DEH_String(AMSTR_FOLLOWON);
+ else
+ plr->message = DEH_String(AMSTR_FOLLOWOFF);
+ break;
+ case AM_GRIDKEY:
+ grid = !grid;
+ if (grid)
+ plr->message = DEH_String(AMSTR_GRIDON);
+ else
+ plr->message = DEH_String(AMSTR_GRIDOFF);
+ break;
+ case AM_MARKKEY:
+ sprintf(buffer, "%s %d", DEH_String(AMSTR_MARKEDSPOT), markpointnum);
+ plr->message = buffer;
+ AM_addMark();
+ break;
+ case AM_CLEARMARKKEY:
+ AM_clearMarks();
+ plr->message = DEH_String(AMSTR_MARKSCLEARED);
+ break;
+ default:
+ cheatstate=0;
+ rc = false;
+ }
+ if (!deathmatch && cht_CheckCheat(&cheat_amap, ev->data2))
+ {
+ 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;
+
+}
+
+
+//
+// Zooming
+//
+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_x2 = m_x + m_w;
+ m_y2 = m_y + m_h;
+ 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;
+
+ }
+
+}
+
+//
+//
+//
+void AM_updateLightLev(void)
+{
+ static int 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 == arrlen(litelevels)) litelevelscnt = 0;
+ nexttic = amclock + 6 - (amclock % 6);
+ }
+
+}
+
+
+//
+// Updates on Game Tick
+//
+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();
+
+}
+
+
+//
+// Clear automap frame buffer.
+//
+void AM_clearFB(int color)
+{
+ memset(fb, color, f_w*f_h);
+}
+
+
+//
+// Automap clipping of lines.
+//
+// Based on Cohen-Sutherland clipping algorithm but with a slightly
+// faster reject and precalculated slopes. If the speed is needed,
+// use a hash algorithm to handle the common cases.
+//
+boolean
+AM_clipMline
+( mline_t* ml,
+ fline_t* fl )
+{
+ enum
+ {
+ LEFT =1,
+ RIGHT =2,
+ BOTTOM =4,
+ TOP =8
+ };
+
+ register int outcode1 = 0;
+ register int outcode2 = 0;
+ register int outside;
+
+ fpoint_t tmp;
+ int dx;
+ int 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;
+ }
+ else
+ {
+ tmp.x = 0;
+ tmp.y = 0;
+ }
+
+ if (outside == outcode1)
+ {
+ fl->a = tmp;
+ DOOUTCODE(outcode1, fl->a.x, fl->a.y);
+ }
+ else
+ {
+ fl->b = tmp;
+ DOOUTCODE(outcode2, fl->b.x, fl->b.y);
+ }
+
+ if (outcode1 & outcode2)
+ return false; // trivially outside
+ }
+
+ return true;
+}
+#undef DOOUTCODE
+
+
+//
+// Classic Bresenham w/ whatever optimizations needed for speed
+//
+void
+AM_drawFline
+( fline_t* fl,
+ int color )
+{
+ register int x;
+ register int y;
+ register int dx;
+ register int dy;
+ register int sx;
+ register int sy;
+ register int ax;
+ register int ay;
+ register int d;
+
+ static int fuck = 0;
+
+ // For debugging only
+ if ( fl->a.x < 0 || fl->a.x >= 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, DEH_String("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;
+ }
+ }
+}
+
+
+//
+// Clip lines, draw visible part sof lines.
+//
+void
+AM_drawMline
+( mline_t* ml,
+ int color )
+{
+ static fline_t fl;
+
+ if (AM_clipMline(ml, &fl))
+ AM_drawFline(&fl, color); // draws it on frame buffer using fb coords
+}
+
+
+
+//
+// Draws flat (floor/ceiling tile) aligned grid lines.
+//
+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<<FRACBITS))
+ start += (MAPBLOCKUNITS<<FRACBITS)
+ - ((start-bmaporgx)%(MAPBLOCKUNITS<<FRACBITS));
+ end = m_x + m_w;
+
+ // draw vertical gridlines
+ ml.a.y = m_y;
+ ml.b.y = m_y+m_h;
+ for (x=start; x<end; x+=(MAPBLOCKUNITS<<FRACBITS))
+ {
+ ml.a.x = x;
+ ml.b.x = x;
+ AM_drawMline(&ml, color);
+ }
+
+ // Figure out start of horizontal gridlines
+ start = m_y;
+ if ((start-bmaporgy)%(MAPBLOCKUNITS<<FRACBITS))
+ start += (MAPBLOCKUNITS<<FRACBITS)
+ - ((start-bmaporgy)%(MAPBLOCKUNITS<<FRACBITS));
+ end = m_y + m_h;
+
+ // draw horizontal gridlines
+ ml.a.x = m_x;
+ ml.b.x = m_x + m_w;
+ for (y=start; y<end; y+=(MAPBLOCKUNITS<<FRACBITS))
+ {
+ ml.a.y = y;
+ ml.b.y = y;
+ AM_drawMline(&ml, color);
+ }
+
+}
+
+//
+// Determines visible lines, draws them.
+// This is LineDef based, not LineSeg based.
+//
+void AM_drawWalls(void)
+{
+ int i;
+ static mline_t l;
+
+ for (i=0;i<numlines;i++)
+ {
+ l.a.x = lines[i].v1->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);
+ }
+ }
+}
+
+
+//
+// Rotation in 2D.
+// Used to rotate player arrow line character.
+//
+void
+AM_rotate
+( fixed_t* x,
+ fixed_t* y,
+ angle_t a )
+{
+ fixed_t tmpx;
+
+ tmpx =
+ FixedMul(*x,finecosine[a>>ANGLETOFINESHIFT])
+ - FixedMul(*y,finesine[a>>ANGLETOFINESHIFT]);
+
+ *y =
+ FixedMul(*x,finesine[a>>ANGLETOFINESHIFT])
+ + FixedMul(*y,finecosine[a>>ANGLETOFINESHIFT]);
+
+ *x = tmpx;
+}
+
+void
+AM_drawLineCharacter
+( mline_t* lineguy,
+ int lineguylines,
+ fixed_t scale,
+ angle_t angle,
+ int color,
+ fixed_t x,
+ fixed_t y )
+{
+ int i;
+ mline_t l;
+
+ for (i=0;i<lineguylines;i++)
+ {
+ l.a.x = lineguy[i].a.x;
+ l.a.y = lineguy[i].a.y;
+
+ if (scale)
+ {
+ l.a.x = FixedMul(scale, l.a.x);
+ l.a.y = FixedMul(scale, l.a.y);
+ }
+
+ if (angle)
+ AM_rotate(&l.a.x, &l.a.y, angle);
+
+ l.a.x += x;
+ l.a.y += y;
+
+ l.b.x = lineguy[i].b.x;
+ l.b.y = lineguy[i].b.y;
+
+ if (scale)
+ {
+ l.b.x = FixedMul(scale, l.b.x);
+ l.b.y = FixedMul(scale, l.b.y);
+ }
+
+ if (angle)
+ AM_rotate(&l.b.x, &l.b.y, angle);
+
+ l.b.x += x;
+ l.b.y += y;
+
+ AM_drawMline(&l, color);
+ }
+}
+
+void AM_drawPlayers(void)
+{
+ int i;
+ player_t* p;
+ static int their_colors[] = { GREENS, GRAYS, BROWNS, REDS };
+ int their_color = -1;
+ int color;
+
+ if (!netgame)
+ {
+ if (cheating)
+ AM_drawLineCharacter
+ (cheat_player_arrow, arrlen(cheat_player_arrow), 0,
+ plr->mo->angle, WHITE, plr->mo->x, plr->mo->y);
+ else
+ AM_drawLineCharacter
+ (player_arrow, arrlen(player_arrow), 0, plr->mo->angle,
+ WHITE, plr->mo->x, plr->mo->y);
+ return;
+ }
+
+ for (i=0;i<MAXPLAYERS;i++)
+ {
+ their_color++;
+ p = &players[i];
+
+ if ( (deathmatch && !singledemo) && p != plr)
+ continue;
+
+ if (!playeringame[i])
+ continue;
+
+ if (p->powers[pw_invisibility])
+ color = 246; // *close* to black
+ else
+ color = their_colors[their_color];
+
+ AM_drawLineCharacter
+ (player_arrow, arrlen(player_arrow), 0, p->mo->angle,
+ color, p->mo->x, p->mo->y);
+ }
+
+}
+
+void
+AM_drawThings
+( int colors,
+ int colorrange)
+{
+ int i;
+ mobj_t* t;
+
+ for (i=0;i<numsectors;i++)
+ {
+ t = sectors[i].thinglist;
+ while (t)
+ {
+ AM_drawLineCharacter
+ (thintriangle_guy, arrlen(thintriangle_guy),
+ 16<<FRACBITS, t->angle, colors+lightlev, t->x, t->y);
+ t = t->snext;
+ }
+ }
+}
+
+void AM_drawMarks(void)
+{
+ int i, fx, fy, w, h;
+
+ for (i=0;i<AM_NUMMARKPOINTS;i++)
+ {
+ if (markpoints[i].x != -1)
+ {
+ // w = SHORT(marknums[i]->width);
+ // 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);
+
+}
--- /dev/null
+++ b/src/doom/am_map.h
@@ -1,0 +1,57 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION:
+// AutoMap module.
+//
+//-----------------------------------------------------------------------------
+
+#ifndef __AMMAP_H__
+#define __AMMAP_H__
+
+#include "d_event.h"
+#include "m_cheat.h"
+
+// Used by ST StatusBar stuff.
+#define AM_MSGHEADER (('a'<<24)+('m'<<16))
+#define AM_MSGENTERED (AM_MSGHEADER | ('e'<<8))
+#define AM_MSGEXITED (AM_MSGHEADER | ('x'<<8))
+
+
+// Called by main loop.
+boolean AM_Responder (event_t* ev);
+
+// Called by main loop.
+void AM_Ticker (void);
+
+// Called by main loop,
+// called instead of view drawer if automap active.
+void AM_Drawer (void);
+
+// Called to force the automap to quit
+// if the level is completed while it is up.
+void AM_Stop (void);
+
+
+extern cheatseq_t cheat_amap;
+
+
+#endif
--- /dev/null
+++ b/src/doom/d_englsh.h
@@ -1,0 +1,701 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION:
+// Printed strings for translation.
+// English language support (default).
+//
+//-----------------------------------------------------------------------------
+
+#ifndef __D_ENGLSH__
+#define __D_ENGLSH__
+
+//
+// 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
+
+#define DOSY "(press y to quit to dos.)"
+
+#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_E4M1 "E4M1: Hell Beneath"
+#define HUSTR_E4M2 "E4M2: Perfect Hatred"
+#define HUSTR_E4M3 "E4M3: Sever The Wicked"
+#define HUSTR_E4M4 "E4M4: Unruly Evil"
+#define HUSTR_E4M5 "E4M5: They Will Repent"
+#define HUSTR_E4M6 "E4M6: Against Thee Wickedly"
+#define HUSTR_E4M7 "E4M7: And Hell Followed"
+#define HUSTR_E4M8 "E4M8: Unto The Cruel"
+#define HUSTR_E4M9 "E4M9: Fear"
+
+#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 PHUSTR_1 "level 1: congo"
+#define PHUSTR_2 "level 2: well of souls"
+#define PHUSTR_3 "level 3: aztec"
+#define PHUSTR_4 "level 4: caged"
+#define PHUSTR_5 "level 5: ghost town"
+#define PHUSTR_6 "level 6: baron's lair"
+#define PHUSTR_7 "level 7: caughtyard"
+#define PHUSTR_8 "level 8: realm"
+#define PHUSTR_9 "level 9: abattoire"
+#define PHUSTR_10 "level 10: onslaught"
+#define PHUSTR_11 "level 11: hunted"
+
+#define PHUSTR_12 "level 12: speed"
+#define PHUSTR_13 "level 13: the crypt"
+#define PHUSTR_14 "level 14: genesis"
+#define PHUSTR_15 "level 15: the twilight"
+#define PHUSTR_16 "level 16: the omen"
+#define PHUSTR_17 "level 17: compound"
+#define PHUSTR_18 "level 18: neurosphere"
+#define PHUSTR_19 "level 19: nme"
+#define PHUSTR_20 "level 20: the death domain"
+
+#define PHUSTR_21 "level 21: slayer"
+#define PHUSTR_22 "level 22: impossible mission"
+#define PHUSTR_23 "level 23: tombstone"
+#define PHUSTR_24 "level 24: the final frontier"
+#define PHUSTR_25 "level 25: the temple of darkness"
+#define PHUSTR_26 "level 26: bunker"
+#define PHUSTR_27 "level 27: anti-christ"
+#define PHUSTR_28 "level 28: the sewers"
+#define PHUSTR_29 "level 29: odyssey of noises"
+#define PHUSTR_30 "level 30: the gateway of hell"
+
+#define PHUSTR_31 "level 31: cyberden"
+#define PHUSTR_32 "level 32: go 2 it"
+
+#define THUSTR_1 "level 1: system control"
+#define THUSTR_2 "level 2: human bbq"
+#define THUSTR_3 "level 3: power control"
+#define THUSTR_4 "level 4: wormhole"
+#define THUSTR_5 "level 5: hanger"
+#define THUSTR_6 "level 6: open season"
+#define THUSTR_7 "level 7: prison"
+#define THUSTR_8 "level 8: metal"
+#define THUSTR_9 "level 9: stronghold"
+#define THUSTR_10 "level 10: redemption"
+#define THUSTR_11 "level 11: storage facility"
+
+#define THUSTR_12 "level 12: crater"
+#define THUSTR_13 "level 13: nukage processing"
+#define THUSTR_14 "level 14: steel works"
+#define THUSTR_15 "level 15: dead zone"
+#define THUSTR_16 "level 16: deepest reaches"
+#define THUSTR_17 "level 17: processing area"
+#define THUSTR_18 "level 18: mill"
+#define THUSTR_19 "level 19: shipping/respawning"
+#define THUSTR_20 "level 20: central processing"
+
+#define THUSTR_21 "level 21: administration center"
+#define THUSTR_22 "level 22: habitat"
+#define THUSTR_23 "level 23: lunar mining project"
+#define THUSTR_24 "level 24: quarry"
+#define THUSTR_25 "level 25: baron's den"
+#define THUSTR_26 "level 26: ballistyx"
+#define THUSTR_27 "level 27: mount pain"
+#define THUSTR_28 "level 28: heck"
+#define THUSTR_29 "level 29: river styx"
+#define THUSTR_30 "level 30: last call"
+
+#define THUSTR_31 "level 31: pharaoh"
+#define THUSTR_32 "level 32: caribbean"
+
+#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 ..."
+
+
+#define E4TEXT \
+"the spider mastermind must have sent forth\n"\
+"its legions of hellspawn before your\n"\
+"final confrontation with that terrible\n"\
+"beast from hell. but you stepped forward\n"\
+"and brought forth eternal damnation and\n"\
+"suffering upon the horde as a true hero\n"\
+"would in the face of something so evil.\n"\
+"\n"\
+"besides, someone was gonna pay for what\n"\
+"happened to daisy, your pet rabbit.\n"\
+"\n"\
+"but now, you see spread before you more\n"\
+"potential pain and gibbitude as a nation\n"\
+"of demons run amok among our cities.\n"\
+"\n"\
+"next stop, hell on earth!"
+
+
+// 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"
+
+
+// after map 06
+
+#define P1TEXT \
+"You gloat over the steaming carcass of the\n"\
+"Guardian. With its death, you've wrested\n"\
+"the Accelerator from the stinking claws\n"\
+"of Hell. You relax and glance around the\n"\
+"room. Damn! There was supposed to be at\n"\
+"least one working prototype, but you can't\n"\
+"see it. The demons must have taken it.\n"\
+"\n"\
+"You must find the prototype, or all your\n"\
+"struggles will have been wasted. Keep\n"\
+"moving, keep fighting, keep killing.\n"\
+"Oh yes, keep living, too."
+
+
+// after map 11
+
+#define P2TEXT \
+"Even the deadly Arch-Vile labyrinth could\n"\
+"not stop you, and you've gotten to the\n"\
+"prototype Accelerator which is soon\n"\
+"efficiently and permanently deactivated.\n"\
+"\n"\
+"You're good at that kind of thing."
+
+
+// after map 20
+
+#define P3TEXT \
+"You've bashed and battered your way into\n"\
+"the heart of the devil-hive. Time for a\n"\
+"Search-and-Destroy mission, aimed at the\n"\
+"Gatekeeper, whose foul offspring is\n"\
+"cascading to Earth. Yeah, he's bad. But\n"\
+"you know who's worse!\n"\
+"\n"\
+"Grinning evilly, you check your gear, and\n"\
+"get ready to give the bastard a little Hell\n"\
+"of your own making!"
+
+// after map 30
+
+#define P4TEXT \
+"The Gatekeeper's evil face is splattered\n"\
+"all over the place. As its tattered corpse\n"\
+"collapses, an inverted Gate forms and\n"\
+"sucks down the shards of the last\n"\
+"prototype Accelerator, not to mention the\n"\
+"few remaining demons. You're done. Hell\n"\
+"has gone back to pounding bad dead folks \n"\
+"instead of good live ones. Remember to\n"\
+"tell your grandkids to put a rocket\n"\
+"launcher in your coffin. If you go to Hell\n"\
+"when you die, you'll need it for some\n"\
+"final cleaning-up ..."
+
+// before map 31
+
+#define P5TEXT \
+"You've found the second-hardest level we\n"\
+"got. Hope you have a saved game a level or\n"\
+"two previous. If not, be prepared to die\n"\
+"aplenty. For master marines only."
+
+// before map 32
+
+#define P6TEXT \
+"Betcha wondered just what WAS the hardest\n"\
+"level we had ready for ya? Now you know.\n"\
+"No one gets out alive."
+
+
+#define T1TEXT \
+"You've fought your way out of the infested\n"\
+"experimental labs. It seems that UAC has\n"\
+"once again gulped it down. With their\n"\
+"high turnover, it must be hard for poor\n"\
+"old UAC to buy corporate health insurance\n"\
+"nowadays..\n"\
+"\n"\
+"Ahead lies the military complex, now\n"\
+"swarming with diseased horrors hot to get\n"\
+"their teeth into you. With luck, the\n"\
+"complex still has some warlike ordnance\n"\
+"laying around."
+
+
+#define T2TEXT \
+"You hear the grinding of heavy machinery\n"\
+"ahead. You sure hope they're not stamping\n"\
+"out new hellspawn, but you're ready to\n"\
+"ream out a whole herd if you have to.\n"\
+"They might be planning a blood feast, but\n"\
+"you feel about as mean as two thousand\n"\
+"maniacs packed into one mad killer.\n"\
+"\n"\
+"You don't plan to go down easy."
+
+
+#define T3TEXT \
+"The vista opening ahead looks real damn\n"\
+"familiar. Smells familiar, too -- like\n"\
+"fried excrement. You didn't like this\n"\
+"place before, and you sure as hell ain't\n"\
+"planning to like it now. The more you\n"\
+"brood on it, the madder you get.\n"\
+"Hefting your gun, an evil grin trickles\n"\
+"onto your face. Time to take some names."
+
+#define T4TEXT \
+"Suddenly, all is silent, from one horizon\n"\
+"to the other. The agonizing echo of Hell\n"\
+"fades away, the nightmare sky turns to\n"\
+"blue, the heaps of monster corpses start \n"\
+"to evaporate along with the evil stench \n"\
+"that filled the air. Jeeze, maybe you've\n"\
+"done it. Have you really won?\n"\
+"\n"\
+"Something rumbles in the distance.\n"\
+"A blue light begins to glow inside the\n"\
+"ruined skull of the demon-spitter."
+
+
+#define T5TEXT \
+"What now? Looks totally different. Kind\n"\
+"of like King Tut's condo. Well,\n"\
+"whatever's here can't be any worse\n"\
+"than usual. Can it? Or maybe it's best\n"\
+"to let sleeping gods lie.."
+
+
+#define T6TEXT \
+"Time for a vacation. You've burst the\n"\
+"bowels of hell and by golly you're ready\n"\
+"for a break. You mutter to yourself,\n"\
+"Maybe someone else can kick Hell's ass\n"\
+"next time around. Ahead lies a quiet town,\n"\
+"with peaceful flowing water, quaint\n"\
+"buildings, and presumably no Hellspawn.\n"\
+"\n"\
+"As you step off the transport, you hear\n"\
+"the stomp of a cyberdemon's iron shoe."
+
+
+
+//
+// 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"
+
+
+#endif
--- /dev/null
+++ b/src/doom/d_items.c
@@ -1,0 +1,136 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION:
+//
+//-----------------------------------------------------------------------------
+
+
+// We are referring to sprite numbers.
+#include "info.h"
+
+#include "d_items.h"
+
+
+//
+// PSPRITE ACTIONS for waepons.
+// This struct controls the weapon animations.
+//
+// Each entry is:
+// ammo/amunition type
+// upstate
+// downstate
+// readystate
+// atkstate, i.e. attack/fire/hit frame
+// flashstate, muzzle flash
+//
+weaponinfo_t weaponinfo[NUMWEAPONS] =
+{
+ {
+ // fist
+ am_noammo,
+ S_PUNCHUP,
+ S_PUNCHDOWN,
+ S_PUNCH,
+ S_PUNCH1,
+ S_NULL
+ },
+ {
+ // pistol
+ am_clip,
+ S_PISTOLUP,
+ S_PISTOLDOWN,
+ S_PISTOL,
+ S_PISTOL1,
+ S_PISTOLFLASH
+ },
+ {
+ // shotgun
+ am_shell,
+ S_SGUNUP,
+ S_SGUNDOWN,
+ S_SGUN,
+ S_SGUN1,
+ S_SGUNFLASH1
+ },
+ {
+ // chaingun
+ am_clip,
+ S_CHAINUP,
+ S_CHAINDOWN,
+ S_CHAIN,
+ S_CHAIN1,
+ S_CHAINFLASH1
+ },
+ {
+ // missile launcher
+ am_misl,
+ S_MISSILEUP,
+ S_MISSILEDOWN,
+ S_MISSILE,
+ S_MISSILE1,
+ S_MISSILEFLASH1
+ },
+ {
+ // plasma rifle
+ am_cell,
+ S_PLASMAUP,
+ S_PLASMADOWN,
+ S_PLASMA,
+ S_PLASMA1,
+ S_PLASMAFLASH1
+ },
+ {
+ // bfg 9000
+ am_cell,
+ S_BFGUP,
+ S_BFGDOWN,
+ S_BFG,
+ S_BFG1,
+ S_BFGFLASH1
+ },
+ {
+ // chainsaw
+ am_noammo,
+ S_SAWUP,
+ S_SAWDOWN,
+ S_SAW,
+ S_SAW1,
+ S_NULL
+ },
+ {
+ // super shotgun
+ am_shell,
+ S_DSGUNUP,
+ S_DSGUNDOWN,
+ S_DSGUN,
+ S_DSGUN1,
+ S_DSGUNFLASH1
+ },
+};
+
+
+
+
+
+
+
+
--- /dev/null
+++ b/src/doom/d_items.h
@@ -1,0 +1,49 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION:
+// Items: key cards, artifacts, weapon, ammunition.
+//
+//-----------------------------------------------------------------------------
+
+
+#ifndef __D_ITEMS__
+#define __D_ITEMS__
+
+#include "doomdef.h"
+
+
+
+// Weapon info: sprite frames, ammunition use.
+typedef struct
+{
+ ammotype_t ammo;
+ int upstate;
+ int downstate;
+ int readystate;
+ int atkstate;
+ int flashstate;
+
+} weaponinfo_t;
+
+extern weaponinfo_t weaponinfo[NUMWEAPONS];
+
+#endif
--- /dev/null
+++ b/src/doom/d_iwad.c
@@ -1,0 +1,912 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 2006 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION:
+// Search for and locate an IWAD file, and initialise according
+// to the IWAD type.
+//
+//-----------------------------------------------------------------------------
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <string.h>
+
+#include "deh_main.h"
+#include "doomdef.h"
+#include "doomstat.h"
+#include "i_system.h"
+#include "m_argv.h"
+#include "m_config.h"
+#include "m_misc.h"
+#include "w_wad.h"
+#include "z_zone.h"
+
+// Array of locations to search for IWAD files
+//
+// "128 IWAD search directories should be enough for anybody".
+
+#define MAX_IWAD_DIRS 128
+
+static boolean iwad_dirs_built = false;
+static char *iwad_dirs[MAX_IWAD_DIRS];
+static int num_iwad_dirs = 0;
+
+static void AddIWADDir(char *dir)
+{
+ if (num_iwad_dirs < MAX_IWAD_DIRS)
+ {
+ iwad_dirs[num_iwad_dirs] = dir;
+ ++num_iwad_dirs;
+ }
+}
+
+// This is Windows-specific code that automatically finds the location
+// of installed IWAD files. The registry is inspected to find special
+// keys installed by the Windows installers for various CD versions
+// of Doom. From these keys we can deduce where to find an IWAD.
+
+#ifdef _WIN32
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+
+typedef struct
+{
+ HKEY root;
+ char *path;
+ char *value;
+} registry_value_t;
+
+#define UNINSTALLER_STRING "\\uninstl.exe /S "
+
+// Keys installed by the various CD editions. These are actually the
+// commands to invoke the uninstaller and look like this:
+//
+// C:\Program Files\Path\uninstl.exe /S C:\Program Files\Path
+//
+// With some munging we can find where Doom was installed.
+
+static registry_value_t uninstall_values[] =
+{
+ // Ultimate Doom, CD version (Depths of Doom trilogy)
+
+ {
+ HKEY_LOCAL_MACHINE,
+ "Software\\Microsoft\\Windows\\CurrentVersion\\"
+ "Uninstall\\Ultimate Doom for Windows 95",
+ "UninstallString",
+ },
+
+ // Doom II, CD version (Depths of Doom trilogy)
+
+ {
+ HKEY_LOCAL_MACHINE,
+ "Software\\Microsoft\\Windows\\CurrentVersion\\"
+ "Uninstall\\Doom II for Windows 95",
+ "UninstallString",
+ },
+
+ // Final Doom
+
+ {
+ HKEY_LOCAL_MACHINE,
+ "Software\\Microsoft\\Windows\\CurrentVersion\\"
+ "Uninstall\\Final Doom for Windows 95",
+ "UninstallString",
+ },
+
+ // Shareware version
+
+ {
+ HKEY_LOCAL_MACHINE,
+ "Software\\Microsoft\\Windows\\CurrentVersion\\"
+ "Uninstall\\Doom Shareware for Windows 95",
+ "UninstallString",
+ },
+};
+
+// Value installed by the Collector's Edition when it is installed
+
+static registry_value_t collectors_edition_value =
+{
+ HKEY_LOCAL_MACHINE,
+ "Software\\Activision\\DOOM Collector's Edition\\v1.0",
+ "INSTALLPATH",
+};
+
+// Subdirectories of the above install path, where IWADs are installed.
+
+static char *collectors_edition_subdirs[] =
+{
+ "Doom2",
+ "Final Doom",
+ "Ultimate Doom",
+};
+
+// Location where Steam is installed
+
+static registry_value_t steam_install_location =
+{
+ HKEY_LOCAL_MACHINE,
+ "Software\\Valve\\Steam",
+ "InstallPath",
+};
+
+// Subdirs of the steam install directory where IWADs are found
+
+static char *steam_install_subdirs[] =
+{
+ "steamapps\\common\\doom 2\\base",
+ "steamapps\\common\\final doom\\base",
+ "steamapps\\common\\ultimate doom\\base",
+};
+
+static char *GetRegistryString(registry_value_t *reg_val)
+{
+ HKEY key;
+ DWORD len;
+ DWORD valtype;
+ char *result;
+
+ // Open the key (directory where the value is stored)
+
+ if (RegOpenKeyEx(reg_val->root, reg_val->path, 0, KEY_READ, &key)
+ != ERROR_SUCCESS)
+ {
+ return NULL;
+ }
+
+ // Find the type and length of the string
+
+ if (RegQueryValueEx(key, reg_val->value, NULL, &valtype, NULL, &len)
+ != ERROR_SUCCESS)
+ {
+ return NULL;
+ }
+
+ // Only accept strings
+
+ if (valtype != REG_SZ)
+ {
+ return NULL;
+ }
+
+ // Allocate a buffer for the value and read the value
+
+ result = malloc(len);
+
+ if (RegQueryValueEx(key, reg_val->value, NULL, &valtype, (unsigned char *) result, &len)
+ != ERROR_SUCCESS)
+ {
+ free(result);
+ return NULL;
+ }
+
+ // Close the key
+
+ RegCloseKey(key);
+
+ return result;
+}
+
+// Check for the uninstall strings from the CD versions
+
+static void CheckUninstallStrings(void)
+{
+ unsigned int i;
+
+ for (i=0; i<arrlen(uninstall_values); ++i)
+ {
+ char *val;
+ char *path;
+ char *unstr;
+
+ val = GetRegistryString(&uninstall_values[i]);
+
+ if (val == NULL)
+ {
+ continue;
+ }
+
+ unstr = strstr(val, UNINSTALLER_STRING);
+
+ if (unstr == NULL)
+ {
+ free(val);
+ }
+ else
+ {
+ path = unstr + strlen(UNINSTALLER_STRING);
+
+ AddIWADDir(path);
+ }
+ }
+}
+
+// Check for Doom: Collector's Edition
+
+static void CheckCollectorsEdition(void)
+{
+ char *install_path;
+ char *subpath;
+ unsigned int i;
+
+ install_path = GetRegistryString(&collectors_edition_value);
+
+ if (install_path == NULL)
+ {
+ return;
+ }
+
+ for (i=0; i<arrlen(collectors_edition_subdirs); ++i)
+ {
+ subpath = malloc(strlen(install_path)
+ + strlen(collectors_edition_subdirs[i])
+ + 5);
+
+ sprintf(subpath, "%s\\%s", install_path, collectors_edition_subdirs[i]);
+
+ AddIWADDir(subpath);
+ }
+
+ free(install_path);
+}
+
+
+// Check for Doom downloaded via Steam
+
+static void CheckSteamEdition(void)
+{
+ char *install_path;
+ char *subpath;
+ size_t i;
+
+ install_path = GetRegistryString(&steam_install_location);
+
+ if (install_path == NULL)
+ {
+ return;
+ }
+
+ for (i=0; i<arrlen(steam_install_subdirs); ++i)
+ {
+ subpath = malloc(strlen(install_path)
+ + strlen(steam_install_subdirs[i]) + 5);
+
+ sprintf(subpath, "%s\\%s", install_path, steam_install_subdirs[i]);
+
+ AddIWADDir(subpath);
+ }
+}
+
+// Default install directories for DOS Doom
+
+static void CheckDOSDefaults(void)
+{
+ // These are the default install directories used by the deice
+ // installer program:
+
+ AddIWADDir("\\doom2"); // Doom II
+ AddIWADDir("\\plutonia"); // Final Doom
+ AddIWADDir("\\tnt");
+ AddIWADDir("\\doom_se"); // Ultimate Doom
+ AddIWADDir("\\doom"); // Shareware / Registered Doom
+ AddIWADDir("\\dooms"); // Shareware versions
+ AddIWADDir("\\doomsw");
+}
+
+#endif
+
+static struct
+{
+ char *name;
+ GameMission_t mission;
+} iwads[] = {
+ {"doom2.wad", doom2},
+ {"plutonia.wad", pack_plut},
+ {"tnt.wad", pack_tnt},
+ {"doom.wad", doom},
+ {"doom1.wad", doom},
+ {"chex.wad", doom},
+};
+
+// Hack for chex quest mode
+
+static void CheckChex(char *iwad_name)
+{
+ if (!strcmp(iwad_name, "chex.wad"))
+ {
+ gameversion = exe_chex;
+ }
+}
+
+// Search a directory to try to find an IWAD
+// Returns the location of the IWAD if found, otherwise NULL.
+
+static char *SearchDirectoryForIWAD(char *dir)
+{
+ size_t i;
+
+ for (i=0; i<arrlen(iwads); ++i)
+ {
+ char *filename;
+ char *iwadname;
+
+ iwadname = DEH_String(iwads[i].name);
+
+ filename = malloc(strlen(dir) + strlen(iwadname) + 3);
+
+ if (!strcmp(dir, "."))
+ {
+ strcpy(filename, iwadname);
+ }
+ else
+ {
+ sprintf(filename, "%s%c%s", dir, DIR_SEPARATOR, iwadname);
+ }
+
+ if (M_FileExists(filename))
+ {
+ CheckChex(iwads[i].name);
+ gamemission = iwads[i].mission;
+
+ return filename;
+ }
+
+ free(filename);
+ }
+
+ return NULL;
+}
+
+// When given an IWAD with the '-iwad' parameter,
+// attempt to identify it by its name.
+
+static void IdentifyIWADByName(char *name)
+{
+ size_t i;
+
+ gamemission = none;
+
+ for (i=0; i<arrlen(iwads); ++i)
+ {
+ char *iwadname;
+
+ iwadname = DEH_String(iwads[i].name);
+
+ if (strlen(name) < strlen(iwadname))
+ continue;
+
+ // Check if it ends in this IWAD name.
+
+ if (!strcasecmp(name + strlen(name) - strlen(iwadname),
+ iwadname))
+ {
+ CheckChex(iwads[i].name);
+ gamemission = iwads[i].mission;
+ break;
+ }
+ }
+}
+
+//
+// Add directories from the list in the DOOMWADPATH environment variable.
+//
+
+static void AddDoomWadPath(void)
+{
+ char *doomwadpath;
+ char *p;
+
+ // Check the DOOMWADPATH environment variable.
+
+ doomwadpath = getenv("DOOMWADPATH");
+
+ if (doomwadpath == NULL)
+ {
+ return;
+ }
+
+ doomwadpath = strdup(doomwadpath);
+
+ // Add the initial directory
+
+ AddIWADDir(doomwadpath);
+
+ // Split into individual dirs within the list.
+
+ p = doomwadpath;
+
+ for (;;)
+ {
+ p = strchr(p, PATH_SEPARATOR);
+
+ if (p != NULL)
+ {
+ // Break at the separator and store the right hand side
+ // as another iwad dir
+
+ *p = '\0';
+ p += 1;
+
+ AddIWADDir(p);
+ }
+ else
+ {
+ break;
+ }
+ }
+}
+
+
+//
+// Build a list of IWAD files
+//
+
+static void BuildIWADDirList(void)
+{
+ char *doomwaddir;
+
+ if (iwad_dirs_built)
+ {
+ return;
+ }
+
+ // Look in the current directory. Doom always does this.
+
+ AddIWADDir(".");
+
+ // Add DOOMWADDIR if it is in the environment
+
+ doomwaddir = getenv("DOOMWADDIR");
+
+ if (doomwaddir != NULL)
+ {
+ AddIWADDir(doomwaddir);
+ }
+
+ // Add dirs from DOOMWADPATH
+
+ AddDoomWadPath();
+
+#ifdef _WIN32
+
+ // Search the registry and find where IWADs have been installed.
+
+ CheckUninstallStrings();
+ CheckCollectorsEdition();
+ CheckSteamEdition();
+ CheckDOSDefaults();
+
+#else
+
+ // Standard places where IWAD files are installed under Unix.
+
+ AddIWADDir("/usr/share/games/doom");
+ AddIWADDir("/usr/local/share/games/doom");
+
+#endif
+
+ // Don't run this function again.
+
+ iwad_dirs_built = true;
+}
+
+//
+// Searches WAD search paths for an WAD with a specific filename.
+//
+
+char *D_FindWADByName(char *name)
+{
+ char *buf;
+ int i;
+ boolean exists;
+
+ // Absolute path?
+
+ if (M_FileExists(name))
+ {
+ return name;
+ }
+
+ BuildIWADDirList();
+
+ // Search through all IWAD paths for a file with the given name.
+
+ for (i=0; i<num_iwad_dirs; ++i)
+ {
+ // Construct a string for the full path
+
+ buf = malloc(strlen(iwad_dirs[i]) + strlen(name) + 5);
+ sprintf(buf, "%s%c%s", iwad_dirs[i], DIR_SEPARATOR, name);
+
+ exists = M_FileExists(buf);
+
+ if (exists)
+ {
+ return buf;
+ }
+
+ free(buf);
+ }
+
+ // File not found
+
+ return NULL;
+}
+
+//
+// D_TryWADByName
+//
+// Searches for a WAD by its filename, or passes through the filename
+// if not found.
+//
+
+char *D_TryFindWADByName(char *filename)
+{
+ char *result;
+
+ result = D_FindWADByName(filename);
+
+ if (result != NULL)
+ {
+ return result;
+ }
+ else
+ {
+ return filename;
+ }
+}
+
+//
+// FindIWAD
+// Checks availability of IWAD files by name,
+// to determine whether registered/commercial features
+// should be executed (notably loading PWADs).
+//
+
+char *D_FindIWAD(void)
+{
+ char *result;
+ char *iwadfile;
+ int iwadparm;
+ int i;
+
+ // Check for the -iwad parameter
+
+ //!
+ // Specify an IWAD file to use.
+ //
+ // @arg <file>
+ //
+
+ iwadparm = M_CheckParm("-iwad");
+
+ if (iwadparm)
+ {
+ // Search through IWAD dirs for an IWAD with the given name.
+
+ iwadfile = myargv[iwadparm + 1];
+
+ result = D_FindWADByName(iwadfile);
+
+ if (result == NULL)
+ {
+ I_Error("IWAD file '%s' not found!", iwadfile);
+ }
+
+ IdentifyIWADByName(result);
+ }
+ else
+ {
+ // Search through the list and look for an IWAD
+
+ result = NULL;
+
+ BuildIWADDirList();
+
+ for (i=0; result == NULL && i<num_iwad_dirs; ++i)
+ {
+ result = SearchDirectoryForIWAD(iwad_dirs[i]);
+ }
+ }
+
+ return result;
+}
+
+//
+// Get the IWAD name used for savegames.
+//
+
+static char *SaveGameIWADName(void)
+{
+ size_t i;
+
+ // Chex quest hack
+
+ if (gameversion == exe_chex)
+ {
+ return "chex.wad";
+ }
+
+ // Find what subdirectory to use for savegames
+ //
+ // They should be stored in something like
+ // ~/.chocolate-doom/savegames/doom.wad/
+ //
+ // The directory depends on the IWAD, so that savegames for
+ // different IWADs are kept separate.
+ //
+ // Note that we match on gamemission rather than on IWAD name.
+ // This ensures that doom1.wad and doom.wad saves are stored
+ // in the same place.
+
+ for (i=0; i<arrlen(iwads); ++i)
+ {
+ if (gamemission == iwads[i].mission)
+ {
+ return iwads[i].name;
+ }
+ }
+
+ return NULL;
+}
+//
+// SetSaveGameDir
+//
+// Chooses the directory used to store saved games.
+//
+
+void D_SetSaveGameDir(void)
+{
+ char *iwad_name;
+
+ if (!strcmp(configdir, ""))
+ {
+ // Use the current directory, just like configdir.
+
+ savegamedir = strdup("");
+ }
+ else
+ {
+ // Directory for savegames
+
+ iwad_name = SaveGameIWADName();
+
+ if (iwad_name == NULL)
+ {
+ iwad_name = "unknown.wad";
+ }
+
+ savegamedir = Z_Malloc(strlen(configdir) + 30, PU_STATIC, 0);
+ sprintf(savegamedir, "%ssavegames%c%s%c", configdir,
+ DIR_SEPARATOR, iwad_name, DIR_SEPARATOR);
+
+ M_MakeDirectory(savegamedir);
+ }
+}
+
+// Strings for dehacked replacements of the startup banner
+//
+// These are from the original source: some of them are perhaps
+// not used in any dehacked patches
+
+static char *banners[] =
+{
+ // doom1.wad
+ " "
+ "DOOM Shareware Startup v%i.%i"
+ " ",
+ // doom.wad
+ " "
+ "DOOM Registered Startup v%i.%i"
+ " ",
+ // Registered DOOM uses this
+ " "
+ "DOOM System Startup v%i.%i"
+ " ",
+ // doom.wad (Ultimate DOOM)
+ " "
+ "The Ultimate DOOM Startup v%i.%i"
+ " ",
+ // doom2.wad
+ " "
+ "DOOM 2: Hell on Earth v%i.%i"
+ " ",
+ // tnt.wad
+ " "
+ "DOOM 2: TNT - Evilution v%i.%i"
+ " ",
+ // plutonia.wad
+ " "
+ "DOOM 2: Plutonia Experiment v%i.%i"
+ " ",
+};
+
+//
+// Get game name: if the startup banner has been replaced, use that.
+// Otherwise, use the name given
+//
+
+static char *GetGameName(char *gamename)
+{
+ size_t i;
+ char *deh_sub;
+
+ for (i=0; i<arrlen(banners); ++i)
+ {
+ // Has the banner been replaced?
+
+ deh_sub = DEH_String(banners[i]);
+
+ if (deh_sub != banners[i])
+ {
+ // Has been replaced
+ // We need to expand via printf to include the Doom version
+ // number
+ // We also need to cut off spaces to get the basic name
+
+ gamename = Z_Malloc(strlen(deh_sub) + 10, PU_STATIC, 0);
+ sprintf(gamename, deh_sub, DOOM_VERSION / 100, DOOM_VERSION % 100);
+
+ while (gamename[0] != '\0' && isspace(gamename[0]))
+ strcpy(gamename, gamename+1);
+
+ while (gamename[0] != '\0' && isspace(gamename[strlen(gamename)-1]))
+ gamename[strlen(gamename) - 1] = '\0';
+
+ return gamename;
+ }
+ }
+
+ return gamename;
+}
+
+
+//
+// Find out what version of Doom is playing.
+//
+
+void D_IdentifyVersion(void)
+{
+ // gamemission is set up by the D_FindIWAD function. But if
+ // we specify '-iwad', we have to identify using
+ // IdentifyIWADByName. However, if the iwad does not match
+ // any known IWAD name, we may have a dilemma. Try to
+ // identify by its contents.
+
+ if (gamemission == none)
+ {
+ unsigned int i;
+
+ for (i=0; i<numlumps; ++i)
+ {
+ if (!strncasecmp(lumpinfo[i].name, "MAP01", 8))
+ {
+ gamemission = doom2;
+ break;
+ }
+ else if (!strncasecmp(lumpinfo[i].name, "E1M1", 8))
+ {
+ gamemission = doom;
+ break;
+ }
+ }
+
+ if (gamemission == none)
+ {
+ // Still no idea. I don't think this is going to work.
+
+ I_Error("Unknown or invalid IWAD file.");
+ }
+ }
+
+ // Make sure gamemode is set up correctly
+
+ if (gamemission == doom)
+ {
+ // Doom 1. But which version?
+
+ if (W_CheckNumForName("E4M1") > 0)
+ {
+ // Ultimate Doom
+
+ gamemode = retail;
+ }
+ else if (W_CheckNumForName("E3M1") > 0)
+ {
+ gamemode = registered;
+ }
+ else
+ {
+ gamemode = shareware;
+ }
+ }
+ else
+ {
+ // Doom 2 of some kind.
+
+ gamemode = commercial;
+ }
+}
+
+// Set the gamedescription string
+
+void D_SetGameDescription(void)
+{
+ gamedescription = "Unknown";
+
+ if (gamemission == doom)
+ {
+ // Doom 1. But which version?
+
+ if (gamemode == retail)
+ {
+ // Ultimate Doom
+
+ gamedescription = GetGameName("The Ultimate DOOM");
+ }
+ else if (gamemode == registered)
+ {
+ gamedescription = GetGameName("DOOM Registered");
+ }
+ else if (gamemode == shareware)
+ {
+ gamedescription = GetGameName("DOOM Shareware");
+ }
+ }
+ else
+ {
+ // Doom 2 of some kind. But which mission?
+
+ if (gamemission == doom2)
+ gamedescription = GetGameName("DOOM 2: Hell on Earth");
+ else if (gamemission == pack_plut)
+ gamedescription = GetGameName("DOOM 2: Plutonia Experiment");
+ else if (gamemission == pack_tnt)
+ gamedescription = GetGameName("DOOM 2: TNT - Evilution");
+ }
+}
+
+// Clever hack: Setup can invoke Doom to determine which IWADs are installed.
+// Doom searches install paths and exits with the return code being a
+// bitmask of the installed IWAD files.
+
+void D_FindInstalledIWADs(void)
+{
+ unsigned int i;
+ int result;
+
+ BuildIWADDirList();
+
+ result = 0;
+
+ for (i=0; i<arrlen(iwads); ++i)
+ {
+ if (D_FindWADByName(iwads[i].name) != NULL)
+ {
+ result |= 1 << i;
+ }
+ }
+
+ exit(result);
+}
+
--- /dev/null
+++ b/src/doom/d_iwad.h
@@ -1,0 +1,39 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 2006 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION:
+// Find IWAD and initialise according to IWAD type.
+//
+//-----------------------------------------------------------------------------
+
+
+#ifndef __D_IWAD__
+#define __D_IWAD__
+
+char *D_FindWADByName(char *filename);
+char *D_TryFindWADByName(char *filename);
+char *D_FindIWAD(void);
+void D_SetSaveGameDir(void);
+void D_IdentifyVersion(void);
+void D_SetGameDescription(void);
+void D_FindInstalledIWADs(void);
+
+#endif
+
--- /dev/null
+++ b/src/doom/d_main.c
@@ -1,0 +1,1525 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION:
+// DOOM main program (D_DoomMain) and game loop (D_DoomLoop),
+// plus functions to determine game mode (shareware, registered),
+// parse command line parameters, configure game parameters (turbo),
+// and call the startup functions.
+//
+//-----------------------------------------------------------------------------
+
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "config.h"
+#include "deh_main.h"
+#include "doomdef.h"
+#include "doomstat.h"
+
+#include "dstrings.h"
+#include "doomfeatures.h"
+#include "sounds.h"
+
+#include "d_iwad.h"
+
+#include "z_zone.h"
+#include "w_wad.h"
+#include "w_merge.h"
+#include "s_sound.h"
+#include "v_video.h"
+
+#include "f_finale.h"
+#include "f_wipe.h"
+
+#include "m_argv.h"
+#include "m_config.h"
+#include "m_misc.h"
+#include "m_menu.h"
+#include "p_saveg.h"
+
+#include "i_system.h"
+#include "i_timer.h"
+#include "i_video.h"
+
+#include "g_game.h"
+
+#include "hu_stuff.h"
+#include "wi_stuff.h"
+#include "st_stuff.h"
+#include "am_map.h"
+#include "net_client.h"
+#include "net_dedicated.h"
+#include "net_query.h"
+
+#include "p_setup.h"
+#include "r_local.h"
+
+
+#include "d_main.h"
+
+//
+// D-DoomLoop()
+// 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,
+// calls I_GetTime, I_StartFrame, and I_StartTic
+//
+void D_DoomLoop (void);
+
+// Location where savegames are stored
+
+char * savegamedir;
+
+// location of IWAD and WAD files
+
+char * iwadfile;
+
+
+boolean devparm; // started game with -devparm
+boolean nomonsters; // checkparm of -nomonsters
+boolean respawnparm; // checkparm of -respawn
+boolean fastparm; // checkparm of -fast
+
+boolean singletics = false; // debug flag to cancel adaptiveness
+
+
+// If true, game is running as a screensaver
+
+boolean screensaver_mode = false;
+
+
+//extern int soundVolume;
+//extern int sfxVolume;
+//extern int musicVolume;
+
+extern boolean inhelpscreens;
+
+skill_t startskill;
+int startepisode;
+int startmap;
+boolean autostart;
+int startloadgame;
+
+FILE* debugfile;
+
+boolean advancedemo;
+
+// Store demo, do not accept any inputs
+
+boolean storedemo;
+
+
+char wadfile[1024]; // primary wad file
+char mapdir[1024]; // directory of development maps
+
+
+void D_CheckNetGame (void);
+void D_ProcessEvents (void);
+void G_BuildTiccmd (ticcmd_t* cmd);
+void D_DoAdvanceDemo (void);
+
+
+//
+// EVENT HANDLING
+//
+// Events are asynchronous inputs generally generated by the game user.
+// Events can be discarded if no responder claims them
+//
+
+#define MAXEVENTS 64
+
+static event_t events[MAXEVENTS];
+static int eventhead;
+static int eventtail;
+
+
+//
+// D_PostEvent
+// Called by the I/O functions when input is detected
+//
+void D_PostEvent (event_t* ev)
+{
+ events[eventhead] = *ev;
+ eventhead = (eventhead + 1) % MAXEVENTS;
+}
+
+// Read an event from the queue.
+
+event_t *D_PopEvent(void)
+{
+ event_t *result;
+
+ // No more events waiting.
+
+ if (eventtail == eventhead)
+ {
+ return NULL;
+ }
+
+ result = &events[eventtail];
+
+ // Advance to the next event in the queue.
+
+ eventtail = (eventtail + 1) % MAXEVENTS;
+
+ return result;
+}
+
+
+//
+// D_ProcessEvents
+// Send all the events of the given timestamp down the responder chain
+//
+void D_ProcessEvents (void)
+{
+ event_t* ev;
+
+ // IF STORE DEMO, DO NOT ACCEPT INPUT
+ if (storedemo)
+ return;
+
+ while ((ev = D_PopEvent()) != NULL)
+ {
+ if (M_Responder (ev))
+ continue; // menu ate the event
+ G_Responder (ev);
+ }
+}
+
+
+
+
+//
+// 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;
+ int tics;
+ int wipestart;
+ int y;
+ boolean done;
+ boolean wipe;
+ boolean 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 (DEH_String("PLAYPAL"),PU_CACHE));
+
+ // see if the border needs to be initially drawn
+ if (gamestate == GS_LEVEL && oldgamestate != GS_LEVEL)
+ {
+ viewactivestate = false; // view was not 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--;
+ }
+
+ }
+
+ if (testcontrols)
+ {
+ // Box showing current mouse speed
+
+ G_DrawMouseSpeedBox();
+ }
+
+ 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 (DEH_String("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;
+ I_Sleep(1);
+ } while (tics <= 0);
+
+ 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");
+ }
+
+ TryRunTics();
+
+ I_InitGraphics ();
+
+ R_ExecuteSetViewSize();
+
+ D_StartGameLoop();
+
+ if (testcontrols)
+ {
+ wipegamestate = gamestate;
+ }
+
+ while (1)
+ {
+ // frame syncronous IO operations
+ I_StartFrame ();
+
+ // 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
+
+ // Update display, next frame, with current state.
+ if (screenvisible)
+ 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;
+}
+
+
+//
+// This cycles through the demo sequences.
+// FIXME - version dependend demo numbers?
+//
+void D_DoAdvanceDemo (void)
+{
+ players[consoleplayer].playerstate = PST_LIVE; // not reborn
+ advancedemo = false;
+ usergame = false; // no save / end game here
+ paused = false;
+ gameaction = ga_nothing;
+
+ if ( gamemode == retail )
+ demosequence = (demosequence+1)%7;
+ else
+ demosequence = (demosequence+1)%6;
+
+ switch (demosequence)
+ {
+ case 0:
+ if ( gamemode == commercial )
+ pagetic = TICRATE * 11;
+ else
+ pagetic = 170;
+ gamestate = GS_DEMOSCREEN;
+ pagename = DEH_String("TITLEPIC");
+ if ( gamemode == commercial )
+ S_StartMusic(mus_dm2ttl);
+ else
+ S_StartMusic (mus_intro);
+ break;
+ case 1:
+ G_DeferedPlayDemo(DEH_String("demo1"));
+ break;
+ case 2:
+ pagetic = 200;
+ gamestate = GS_DEMOSCREEN;
+ pagename = DEH_String("CREDIT");
+ break;
+ case 3:
+ G_DeferedPlayDemo(DEH_String("demo2"));
+ break;
+ case 4:
+ gamestate = GS_DEMOSCREEN;
+ if ( gamemode == commercial)
+ {
+ pagetic = TICRATE * 11;
+ pagename = DEH_String("TITLEPIC");
+ S_StartMusic(mus_dm2ttl);
+ }
+ else
+ {
+ pagetic = 200;
+
+ if ( gamemode == retail )
+ pagename = DEH_String("CREDIT");
+ else
+ pagename = DEH_String("HELP2");
+ }
+ break;
+ case 5:
+ G_DeferedPlayDemo(DEH_String("demo3"));
+ break;
+ // THE DEFINITIVE DOOM Special Edition demo
+ case 6:
+ G_DeferedPlayDemo(DEH_String("demo4"));
+ break;
+ }
+}
+
+
+
+//
+// D_StartTitle
+//
+void D_StartTitle (void)
+{
+ gameaction = ga_nothing;
+ demosequence = -1;
+ D_AdvanceDemo ();
+}
+
+
+
+
+// print title for every printed line
+char title[128];
+
+
+static boolean D_AddFile(char *filename)
+{
+ wad_file_t *handle;
+
+ printf(" adding %s\n", filename);
+ handle = W_AddFile(filename);
+
+ return handle != NULL;
+}
+// Startup banner
+
+void PrintBanner(char *msg)
+{
+ int i;
+ int spaces = 35 - (strlen(msg) / 2);
+
+ for (i=0; i<spaces; ++i)
+ putchar(' ');
+
+ puts(msg);
+}
+
+// Copyright message banners
+// Some dehacked mods replace these. These are only displayed if they are
+// replaced by dehacked.
+
+static char *copyright_banners[] =
+{
+ "===========================================================================\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",
+
+ "===========================================================================\n"
+ " Commercial product - do not distribute!\n"
+ " Please report software piracy to the SPA: 1-800-388-PIR8\n"
+ "===========================================================================\n",
+
+ "===========================================================================\n"
+ " Shareware!\n"
+ "===========================================================================\n"
+};
+
+// Prints a message only if it has been modified by dehacked.
+
+void PrintDehackedBanners(void)
+{
+ size_t i;
+
+ for (i=0; i<arrlen(copyright_banners); ++i)
+ {
+ char *deh_s;
+
+ deh_s = DEH_String(copyright_banners[i]);
+
+ if (deh_s != copyright_banners[i])
+ {
+ printf("%s", deh_s);
+
+ // Make sure the modified banner always ends in a newline character.
+ // If it doesn't, add a newline. This fixes av.wad.
+
+ if (deh_s[strlen(deh_s) - 1] != '\n')
+ {
+ printf("\n");
+ }
+ }
+ }
+}
+
+static struct
+{
+ char *description;
+ char *cmdline;
+ GameVersion_t version;
+} gameversions[] = {
+ {"Doom 1.9", "1.9", exe_doom_1_9},
+ {"Ultimate Doom", "ultimate", exe_ultimate},
+ {"Final Doom", "final", exe_final},
+ {"Chex Quest", "chex", exe_chex},
+ { NULL, NULL, 0},
+};
+
+// Initialise the game version
+
+static void InitGameVersion(void)
+{
+ int p;
+ int i;
+
+ //!
+ // @arg <version>
+ // @category compat
+ //
+ // Emulate a specific version of Doom. Valid values are "1.9",
+ // "ultimate" and "final".
+ //
+
+ p = M_CheckParm("-gameversion");
+
+ if (p > 0)
+ {
+ for (i=0; gameversions[i].description != NULL; ++i)
+ {
+ if (!strcmp(myargv[p+1], gameversions[i].cmdline))
+ {
+ gameversion = gameversions[i].version;
+ break;
+ }
+ }
+
+ if (gameversions[i].description == NULL)
+ {
+ printf("Supported game versions:\n");
+
+ for (i=0; gameversions[i].description != NULL; ++i)
+ {
+ printf("\t%s (%s)\n", gameversions[i].cmdline,
+ gameversions[i].description);
+ }
+
+ I_Error("Unknown game version '%s'", myargv[p+1]);
+ }
+ }
+ else
+ {
+ // Determine automatically
+
+ if (gameversion == exe_chex)
+ {
+ // Already determined
+ }
+ else if (gamemode == shareware || gamemode == registered)
+ {
+ // original
+
+ gameversion = exe_doom_1_9;
+ }
+ else if (gamemode == retail)
+ {
+ gameversion = exe_ultimate;
+ }
+ else if (gamemode == commercial)
+ {
+ if (gamemission == doom2)
+ {
+ gameversion = exe_doom_1_9;
+ }
+ else
+ {
+ // Final Doom: tnt or plutonia
+
+ gameversion = exe_final;
+ }
+ }
+ }
+
+ // The original exe does not support retail - 4th episode not supported
+
+ if (gameversion < exe_ultimate && gamemode == retail)
+ {
+ gamemode = registered;
+ }
+
+ // EXEs prior to the Final Doom exes do not support Final Doom.
+
+ if (gameversion < exe_final && gamemode == commercial)
+ {
+ gamemission = doom2;
+ }
+}
+
+void PrintGameVersion(void)
+{
+ int i;
+
+ for (i=0; gameversions[i].description != NULL; ++i)
+ {
+ if (gameversions[i].version == gameversion)
+ {
+ printf("Emulating the behavior of the "
+ "'%s' executable.\n", gameversions[i].description);
+ break;
+ }
+ }
+}
+
+// Load the Chex Quest dehacked file, if we are in Chex mode.
+
+static void LoadChexDeh(void)
+{
+ char *chex_deh;
+
+ if (gameversion == exe_chex)
+ {
+ chex_deh = D_FindWADByName("chex.deh");
+
+ if (chex_deh == NULL)
+ {
+ I_Error("Unable to find Chex Quest dehacked file (chex.deh).\n"
+ "The dehacked file is required in order to emulate\n"
+ "chex.exe correctly. It can be found in your nearest\n"
+ "/idgames repository mirror at:\n\n"
+ " utils/exe_edit/patches/chexdeh.zip");
+ }
+
+ if (!DEH_LoadFile(chex_deh))
+ {
+ I_Error("Failed to load chex.deh needed for emulating chex.exe.");
+ }
+ }
+}
+
+//
+// D_DoomMain
+//
+void D_DoomMain (void)
+{
+ int p;
+ char file[256];
+ char demolumpname[9];
+
+ M_FindResponseFile ();
+
+ // Undocumented "search for IWADs" parameter used by the setup
+ // tool.
+
+ if (M_CheckParm("-findiwads") > 0)
+ {
+ D_FindInstalledIWADs();
+ }
+
+ // print banner
+
+ PrintBanner(PACKAGE_STRING);
+
+ printf (DEH_String("Z_Init: Init zone memory allocation daemon. \n"));
+ Z_Init ();
+
+#ifdef FEATURE_MULTIPLAYER
+ //!
+ // @category net
+ //
+ // Start a dedicated server, routing packets but not participating
+ // in the game itself.
+ //
+
+ if (M_CheckParm("-dedicated") > 0)
+ {
+ printf("Dedicated server mode.\n");
+ NET_DedicatedServer();
+
+ // Never returns
+ }
+
+ //!
+ // @arg <address>
+ // @category net
+ //
+ // Query the status of the server running on the given IP
+ // address.
+ //
+
+ p = M_CheckParm("-query");
+
+ if (p > 0)
+ {
+ NET_QueryAddress(myargv[p+1]);
+ }
+
+ //!
+ // @category net
+ //
+ // Search the local LAN for running servers.
+ //
+
+ if (M_CheckParm("-search"))
+ NET_LANQuery();
+
+#endif
+
+#ifdef FEATURE_DEHACKED
+ printf("DEH_Init: Init Dehacked support.\n");
+ DEH_Init();
+#endif
+
+ iwadfile = D_FindIWAD();
+
+ // None found?
+
+ if (iwadfile == NULL)
+ {
+ I_Error("Game mode indeterminate. No IWAD file was found. Try\n"
+ "specifying one with the '-iwad' command line parameter.\n");
+ }
+
+ setbuf (stdout, NULL);
+ modifiedgame = false;
+
+ //!
+ // @vanilla
+ //
+ // Disable monsters.
+ //
+
+ nomonsters = M_CheckParm ("-nomonsters");
+
+ //!
+ // @vanilla
+ //
+ // Monsters respawn after being killed.
+ //
+
+ respawnparm = M_CheckParm ("-respawn");
+
+ //!
+ // @vanilla
+ //
+ // Monsters move faster.
+ //
+
+ fastparm = M_CheckParm ("-fast");
+
+ //!
+ // @vanilla
+ //
+ // Developer mode. F1 saves a screenshot in the current working
+ // directory.
+ //
+
+ devparm = M_CheckParm ("-devparm");
+
+ //!
+ // @category net
+ // @vanilla
+ //
+ // Start a deathmatch game.
+ //
+
+ if (M_CheckParm ("-deathmatch"))
+ deathmatch = 1;
+
+ //!
+ // @category net
+ // @vanilla
+ //
+ // Start a deathmatch 2.0 game. Weapons do not stay in place and
+ // all items respawn after 30 seconds.
+ //
+
+ if (M_CheckParm ("-altdeath"))
+ deathmatch = 2;
+
+ if (devparm)
+ printf(DEH_String(D_DEVSTR));
+
+ // find which dir to use for config files
+
+ M_SetConfigDir();
+
+ //!
+ // @arg <x>
+ // @vanilla
+ //
+ // Turbo mode. The player's speed is multiplied by x%. If unspecified,
+ // x defaults to 200. Values are rounded up to 10 and down to 400.
+ //
+
+ if ( (p=M_CheckParm ("-turbo")) )
+ {
+ int scale = 200;
+ extern int forwardmove[2];
+ extern int sidemove[2];
+
+ if (p<myargc-1)
+ scale = atoi (myargv[p+1]);
+ if (scale < 10)
+ scale = 10;
+ if (scale > 400)
+ scale = 400;
+ printf (DEH_String("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;
+ }
+
+ // init subsystems
+ printf (DEH_String("V_Init: allocate screens.\n"));
+ V_Init ();
+
+ printf (DEH_String("M_LoadDefaults: Load system defaults.\n"));
+ M_LoadDefaults (); // load before initing other systems
+
+ printf (DEH_String("W_Init: Init WADfiles.\n"));
+ D_AddFile(iwadfile);
+
+#ifdef FEATURE_WAD_MERGE
+
+ // Merged PWADs are loaded first, because they are supposed to be
+ // modified IWADs.
+
+ //!
+ // @arg <files>
+ // @category mod
+ //
+ // Simulates the behavior of deutex's -merge option, merging a PWAD
+ // into the main IWAD. Multiple files may be specified.
+ //
+
+ p = M_CheckParm("-merge");
+
+ if (p > 0)
+ {
+ for (p = p + 1; p<myargc && myargv[p][0] != '-'; ++p)
+ {
+ char *filename;
+
+ filename = D_TryFindWADByName(myargv[p]);
+
+ printf(" merging %s\n", filename);
+ W_MergeFile(filename);
+ }
+ }
+
+ // NWT-style merging:
+
+ // NWT's -merge option:
+
+ //!
+ // @arg <files>
+ // @category mod
+ //
+ // Simulates the behavior of NWT's -merge option. Multiple files
+ // may be specified.
+
+ p = M_CheckParm("-nwtmerge");
+
+ if (p > 0)
+ {
+ for (p = p + 1; p<myargc && myargv[p][0] != '-'; ++p)
+ {
+ char *filename;
+
+ filename = D_TryFindWADByName(myargv[p]);
+
+ printf(" performing NWT-style merge of %s\n", filename);
+ W_NWTDashMerge(filename);
+ }
+ }
+
+ // Add flats
+
+ //!
+ // @arg <files>
+ // @category mod
+ //
+ // Simulates the behavior of NWT's -af option, merging flats into
+ // the main IWAD directory. Multiple files may be specified.
+ //
+
+ p = M_CheckParm("-af");
+
+ if (p > 0)
+ {
+ for (p = p + 1; p<myargc && myargv[p][0] != '-'; ++p)
+ {
+ char *filename;
+
+ filename = D_TryFindWADByName(myargv[p]);
+
+ printf(" merging flats from %s\n", filename);
+ W_NWTMergeFile(filename, W_NWT_MERGE_FLATS);
+ }
+ }
+
+ //!
+ // @arg <files>
+ // @category mod
+ //
+ // Simulates the behavior of NWT's -as option, merging sprites
+ // into the main IWAD directory. Multiple files may be specified.
+ //
+
+ p = M_CheckParm("-as");
+
+ if (p > 0)
+ {
+ for (p = p + 1; p<myargc && myargv[p][0] != '-'; ++p)
+ {
+ char *filename;
+
+ filename = D_TryFindWADByName(myargv[p]);
+
+ printf(" merging sprites from %s\n", filename);
+ W_NWTMergeFile(filename, W_NWT_MERGE_SPRITES);
+ }
+ }
+
+ //!
+ // @arg <files>
+ // @category mod
+ //
+ // Equivalent to "-af <files> -as <files>".
+ //
+
+ p = M_CheckParm("-aa");
+
+ if (p > 0)
+ {
+ for (p = p + 1; p<myargc && myargv[p][0] != '-'; ++p)
+ {
+ char *filename;
+
+ filename = D_TryFindWADByName(myargv[p]);
+
+ printf(" merging sprites and flats from %s\n", filename);
+ W_NWTMergeFile(filename, W_NWT_MERGE_SPRITES | W_NWT_MERGE_FLATS);
+ }
+ }
+
+#endif
+
+ //!
+ // @arg <files>
+ // @vanilla
+ //
+ // Load the specified PWAD files.
+ //
+
+ 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] != '-')
+ {
+ char *filename;
+
+ filename = D_TryFindWADByName(myargv[p]);
+
+ D_AddFile(filename);
+ }
+ }
+
+ // Debug:
+// W_PrintDirectory();
+
+ // 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
+
+ // Map name handling.
+ switch (gamemode )
+ {
+ case shareware:
+ case retail:
+ case registered:
+ 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]);
+ break;
+
+ case commercial:
+ default:
+ 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);
+ break;
+ }
+ D_AddFile (file);
+ }
+
+ //!
+ // @arg <demo>
+ // @category demo
+ // @vanilla
+ //
+ // Play back the demo named demo.lmp.
+ //
+
+ p = M_CheckParm ("-playdemo");
+
+ if (!p)
+ {
+ //!
+ // @arg <demo>
+ // @category demo
+ // @vanilla
+ //
+ // Play back the demo named demo.lmp, determining the framerate
+ // of the screen.
+ //
+ p = M_CheckParm ("-timedemo");
+
+ }
+
+ if (p && p < myargc-1)
+ {
+ if (!strcasecmp(myargv[p+1] + strlen(myargv[p+1]) - 4, ".lmp"))
+ {
+ strcpy(file, myargv[p + 1]);
+ }
+ else
+ {
+ sprintf (file,"%s.lmp", myargv[p+1]);
+ }
+
+ if (D_AddFile (file))
+ {
+ strncpy(demolumpname, lumpinfo[numlumps - 1].name, 8);
+ demolumpname[8] = '\0';
+
+ printf("Playing demo %s.\n", file);
+ }
+ else
+ {
+ // If file failed to load, still continue trying to play
+ // the demo in the same way as Vanilla Doom. This makes
+ // tricks like "-playdemo demo1" possible.
+
+ strncpy(demolumpname, myargv[p + 1], 8);
+ demolumpname[8] = '\0';
+ }
+
+ }
+
+ // Generate the WAD hash table. Speed things up a bit.
+
+ W_GenerateHashTable();
+
+ D_IdentifyVersion();
+ InitGameVersion();
+ LoadChexDeh();
+ D_SetGameDescription();
+ D_SetSaveGameDir();
+
+ // Check for -file in shareware
+ if (modifiedgame)
+ {
+ // These are the lumps that will be checked in IWAD,
+ // if any one is not present, execution will be aborted.
+ 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 ( gamemode == shareware)
+ I_Error(DEH_String("\nYou cannot -file with the shareware "
+ "version. Register!"));
+
+ // Check for fake IWAD with right name,
+ // but w/o all the lumps of the registered version.
+ if (gamemode == registered)
+ for (i = 0;i < 23; i++)
+ if (W_CheckNumForName(name[i])<0)
+ I_Error(DEH_String("\nThis is not the registered version."));
+ }
+
+ // get skill / episode / map from parms
+ startskill = sk_medium;
+ startepisode = 1;
+ startmap = 1;
+ autostart = false;
+
+ //!
+ // @arg <skill>
+ // @vanilla
+ //
+ // Set the game skill, 1-5 (1: easiest, 5: hardest). A skill of
+ // 0 disables all monsters.
+ //
+
+ p = M_CheckParm ("-skill");
+
+ if (p && p < myargc-1)
+ {
+ startskill = myargv[p+1][0]-'1';
+ autostart = true;
+ }
+
+ //!
+ // @arg <n>
+ // @vanilla
+ //
+ // Start playing on episode n (1-4)
+ //
+
+ p = M_CheckParm ("-episode");
+
+ if (p && p < myargc-1)
+ {
+ startepisode = myargv[p+1][0]-'0';
+ startmap = 1;
+ autostart = true;
+ }
+
+ timelimit = 0;
+
+ //!
+ // @arg <n>
+ // @category net
+ // @vanilla
+ //
+ // For multiplayer games: exit each level after n minutes.
+ //
+
+ p = M_CheckParm ("-timer");
+
+ if (p && p < myargc-1 && deathmatch)
+ {
+ timelimit = atoi(myargv[p+1]);
+ printf("timer: %i\n", timelimit);
+ }
+
+ //!
+ // @category net
+ // @vanilla
+ //
+ // Austin Virtual Gaming: end levels after 20 minutes.
+ //
+
+ p = M_CheckParm ("-avg");
+
+ if (p && p < myargc-1 && deathmatch)
+ {
+ printf(DEH_String("Austin Virtual Gaming: Levels will end "
+ "after 20 minutes\n"));
+ timelimit = 20;
+ }
+
+ //!
+ // @arg [<x> <y> | <xy>]
+ // @vanilla
+ //
+ // Start a game immediately, warping to ExMy (Doom 1) or MAPxy
+ // (Doom 2)
+ //
+
+ p = M_CheckParm ("-warp");
+
+ if (p && p < myargc-1)
+ {
+ if (gamemode == commercial)
+ startmap = atoi (myargv[p+1]);
+ else
+ {
+ startepisode = myargv[p+1][0]-'0';
+
+ if (p + 2 < myargc)
+ {
+ startmap = myargv[p+2][0]-'0';
+ }
+ else
+ {
+ startmap = 1;
+ }
+ }
+ autostart = true;
+ }
+
+ // Undocumented:
+ // Invoked by setup to test the controls.
+
+ p = M_CheckParm("-testcontrols");
+
+ if (p > 0)
+ {
+ startepisode = 1;
+ startmap = 1;
+ autostart = true;
+ testcontrols = true;
+ }
+
+ // Check for load game parameter
+ // We do this here and save the slot number, so that the network code
+ // can override it or send the load slot to other players.
+
+ //!
+ // @arg <s>
+ // @vanilla
+ //
+ // Load the game in slot s.
+ //
+
+ p = M_CheckParm ("-loadgame");
+
+ if (p && p < myargc-1)
+ {
+ startloadgame = atoi(myargv[p+1]);
+ }
+ else
+ {
+ // Not loading a game
+ startloadgame = -1;
+ }
+
+ //!
+ // @category video
+ //
+ // Disable vertical mouse movement.
+ //
+
+ if (M_CheckParm("-novert"))
+ novert = true;
+
+ //!
+ // @category video
+ //
+ // Enable vertical mouse movement.
+ //
+
+ if (M_CheckParm("-nonovert"))
+ novert = false;
+
+ if (W_CheckNumForName("SS_START") >= 0
+ || W_CheckNumForName("FF_END") >= 0)
+ {
+ printf ("===========================================================================\n");
+ printf(" WARNING: The loaded WAD file contains modified sprites or\n"
+ " floor textures. You may want to use the '-merge' command\n"
+ " line option instead of '-file'.\n");
+ }
+
+ printf ("===========================================================================\n");
+
+ PrintBanner(gamedescription);
+
+
+ printf (
+ "===========================================================================\n"
+ " " PACKAGE_NAME " is free software, covered by the GNU General Public\n"
+ " License. There is NO warranty; not even for MERCHANTABILITY or FITNESS\n"
+ " FOR A PARTICULAR PURPOSE. You are welcome to change and distribute\n"
+ " copies under certain conditions. See the source for more information.\n"
+
+ "===========================================================================\n"
+ );
+
+ PrintDehackedBanners();
+
+ printf (DEH_String("M_Init: Init miscellaneous info.\n"));
+ M_Init ();
+
+ printf (DEH_String("R_Init: Init DOOM refresh daemon - "));
+ R_Init ();
+
+ printf (DEH_String("\nP_Init: Init Playloop state.\n"));
+ P_Init ();
+
+ printf (DEH_String("I_Init: Setting up machine state.\n"));
+ I_Init ();
+
+#ifdef FEATURE_MULTIPLAYER
+ printf ("NET_Init: Initialise network subsystem.\n");
+ NET_Init ();
+#endif
+
+ printf (DEH_String("S_Init: Setting up sound.\n"));
+ S_Init (sfxVolume * 8, musicVolume * 8);
+
+ printf (DEH_String("D_CheckNetGame: Checking network game status.\n"));
+ D_CheckNetGame ();
+
+ PrintGameVersion();
+
+ printf (DEH_String("HU_Init: Setting up heads up display.\n"));
+ HU_Init ();
+
+ printf (DEH_String("ST_Init: Init status bar.\n"));
+ ST_Init ();
+
+ // If Doom II without a MAP01 lump, this is a store demo.
+ // Moved this here so that MAP01 isn't constantly looked up
+ // in the main loop.
+
+ if (gamemode == commercial && W_CheckNumForName("map01") < 0)
+ storedemo = true;
+
+ //!
+ // @arg <x>
+ // @category demo
+ // @vanilla
+ //
+ // Record a demo named x.lmp.
+ //
+
+ p = M_CheckParm ("-record");
+
+ if (p && p < myargc-1)
+ {
+ G_RecordDemo (myargv[p+1]);
+ autostart = true;
+ }
+
+ p = M_CheckParm ("-playdemo");
+ if (p && p < myargc-1)
+ {
+ singledemo = true; // quit after one demo
+ G_DeferedPlayDemo (demolumpname);
+ D_DoomLoop (); // never returns
+ }
+
+ p = M_CheckParm ("-timedemo");
+ if (p && p < myargc-1)
+ {
+ G_TimeDemo (demolumpname);
+ D_DoomLoop (); // never returns
+ }
+
+ if (startloadgame >= 0)
+ {
+ strcpy(file, P_SaveGameFile(startloadgame));
+ G_LoadGame (file);
+ }
+
+ if (gameaction != ga_loadgame )
+ {
+ if (autostart || netgame)
+ G_InitNew (startskill, startepisode, startmap);
+ else
+ D_StartTitle (); // start up intro loop
+ }
+
+ D_DoomLoop (); // never returns
+}
+
--- /dev/null
+++ b/src/doom/d_main.h
@@ -1,0 +1,66 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION:
+// System specific interface stuff.
+//
+//-----------------------------------------------------------------------------
+
+
+#ifndef __D_MAIN__
+#define __D_MAIN__
+
+#include "d_event.h"
+
+
+
+
+//
+// D_DoomMain()
+// Not a globally visible function, just included for source reference,
+// calls all startup code, parses command line options.
+// If not overrided by user input, calls N_AdvanceDemo.
+//
+void D_DoomMain (void);
+
+// Called by IO functions when input is detected.
+void D_PostEvent (event_t *ev);
+
+// Read an event from the event queue
+
+event_t *D_PopEvent(void);
+
+// Read events from all input devices
+
+void D_ProcessEvents (void);
+
+
+//
+// BASE LEVEL
+//
+void D_PageTicker (void);
+void D_PageDrawer (void);
+void D_AdvanceDemo (void);
+void D_DoAdvanceDemo (void);
+void D_StartTitle (void);
+
+
+#endif
--- /dev/null
+++ b/src/doom/d_net.c
@@ -1,0 +1,620 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION:
+// DOOM Network game communication and protocol,
+// all OS independend parts.
+//
+//-----------------------------------------------------------------------------
+
+
+
+#include "doomfeatures.h"
+
+#include "d_main.h"
+#include "m_argv.h"
+#include "m_menu.h"
+#include "i_system.h"
+#include "i_timer.h"
+#include "i_video.h"
+#include "g_game.h"
+#include "doomdef.h"
+#include "doomstat.h"
+
+#include "deh_main.h"
+
+#include "net_client.h"
+#include "net_gui.h"
+#include "net_io.h"
+#include "net_query.h"
+#include "net_server.h"
+#include "net_sdl.h"
+#include "net_loop.h"
+
+
+//
+// NETWORKING
+//
+// gametic is the tic about to (or currently being) run
+// maketic is the tick that hasn't had control made for it yet
+// nettics[] has the maketics for all players
+//
+// a gametic cannot be run until nettics[] > gametic for all players
+//
+
+ticcmd_t netcmds[MAXPLAYERS][BACKUPTICS];
+int nettics[MAXPLAYERS];
+
+int maketic;
+
+// Used for original sync code.
+
+int lastnettic;
+int skiptics = 0;
+
+// Reduce the bandwidth needed by sampling game input less and transmitting
+// less. If ticdup is 2, sample half normal, 3 = one third normal, etc.
+
+int ticdup;
+
+// Send this many extra (backup) tics in each packet.
+
+int extratics;
+
+// Amount to offset the timer for game sync.
+
+fixed_t offsetms;
+
+// Use new client syncronisation code
+
+boolean net_cl_new_sync = true;
+
+// Connected but not participating in the game (observer)
+
+boolean drone = false;
+
+// 35 fps clock adjusted by offsetms milliseconds
+
+static int GetAdjustedTime(void)
+{
+ int time_ms;
+
+ time_ms = I_GetTimeMS();
+
+ if (net_cl_new_sync)
+ {
+ // Use the adjustments from net_client.c only if we are
+ // using the new sync mode.
+
+ time_ms += (offsetms / FRACUNIT);
+ }
+
+ return (time_ms * TICRATE) / 1000;
+}
+
+//
+// NetUpdate
+// Builds ticcmds for console player,
+// sends out a packet
+//
+int lasttime;
+
+void NetUpdate (void)
+{
+ int nowtime;
+ int newtics;
+ int i;
+ int gameticdiv;
+
+ // If we are running with singletics (timing a demo), this
+ // is all done separately.
+
+ if (singletics)
+ return;
+
+#ifdef FEATURE_MULTIPLAYER
+
+ // Run network subsystems
+
+ NET_CL_Run();
+ NET_SV_Run();
+
+#endif
+
+ // check time
+ nowtime = GetAdjustedTime() / ticdup;
+ newtics = nowtime - lasttime;
+
+ lasttime = nowtime;
+
+ if (skiptics <= newtics)
+ {
+ newtics -= skiptics;
+ skiptics = 0;
+ }
+ else
+ {
+ skiptics -= newtics;
+ newtics = 0;
+ }
+
+ // build new ticcmds for console player
+ gameticdiv = gametic/ticdup;
+
+ for (i=0 ; i<newtics ; i++)
+ {
+ ticcmd_t cmd;
+
+ I_StartTic ();
+ D_ProcessEvents ();
+
+ // Always run the menu
+
+ M_Ticker ();
+
+ if (drone)
+ {
+ // In drone mode, do not generate any ticcmds.
+
+ continue;
+ }
+
+ if (net_cl_new_sync)
+ {
+ // If playing single player, do not allow tics to buffer
+ // up very far
+
+ if ((!netgame || demoplayback) && maketic - gameticdiv > 2)
+ break;
+
+ // Never go more than ~200ms ahead
+
+ if (maketic - gameticdiv > 8)
+ break;
+ }
+ else
+ {
+ if (maketic - gameticdiv >= 5)
+ break;
+ }
+
+ //printf ("mk:%i ",maketic);
+ G_BuildTiccmd(&cmd);
+
+#ifdef FEATURE_MULTIPLAYER
+
+ if (netgame && !demoplayback)
+ {
+ NET_CL_SendTiccmd(&cmd, maketic);
+ }
+
+#endif
+ netcmds[consoleplayer][maketic % BACKUPTICS] = cmd;
+
+ ++maketic;
+ nettics[consoleplayer] = maketic;
+ }
+}
+
+//
+// Start game loop
+//
+// Called after the screen is set but before the game starts running.
+//
+
+void D_StartGameLoop(void)
+{
+ lasttime = GetAdjustedTime() / ticdup;
+}
+
+
+//
+// D_CheckNetGame
+// Works out player numbers among the net participants
+//
+extern int viewangleoffset;
+
+void D_CheckNetGame (void)
+{
+ int i;
+ int num_players;
+
+ // default values for single player
+
+ consoleplayer = 0;
+ netgame = false;
+ ticdup = 1;
+ extratics = 1;
+ lowres_turn = false;
+ offsetms = 0;
+
+ for (i=0; i<MAXPLAYERS; i++)
+ {
+ playeringame[i] = false;
+ nettics[i] = 0;
+ }
+
+ playeringame[0] = true;
+
+#ifdef FEATURE_MULTIPLAYER
+
+ {
+ net_addr_t *addr = NULL;
+
+ //!
+ // @category net
+ //
+ // Start a multiplayer server, listening for connections.
+ //
+
+ if (M_CheckParm("-server") > 0)
+ {
+ NET_SV_Init();
+ NET_SV_AddModule(&net_loop_server_module);
+ NET_SV_AddModule(&net_sdl_module);
+
+ net_loop_client_module.InitClient();
+ addr = net_loop_client_module.ResolveAddress(NULL);
+ }
+ else
+ {
+ //!
+ // @category net
+ //
+ // Automatically search the local LAN for a multiplayer
+ // server and join it.
+ //
+
+ i = M_CheckParm("-autojoin");
+
+ if (i > 0)
+ {
+ addr = NET_FindLANServer();
+
+ if (addr == NULL)
+ {
+ I_Error("No server found on local LAN");
+ }
+ }
+
+ //!
+ // @arg <address>
+ // @category net
+ //
+ // Connect to a multiplayer server running on the given
+ // address.
+ //
+
+ i = M_CheckParm("-connect");
+
+ if (i > 0)
+ {
+ net_sdl_module.InitClient();
+ addr = net_sdl_module.ResolveAddress(myargv[i+1]);
+
+ if (addr == NULL)
+ {
+ I_Error("Unable to resolve '%s'\n", myargv[i+1]);
+ }
+ }
+ }
+
+ if (addr != NULL)
+ {
+ if (M_CheckParm("-drone") > 0)
+ {
+ drone = true;
+ }
+
+ //!
+ // @category net
+ //
+ // Run as the left screen in three screen mode.
+ //
+
+ if (M_CheckParm("-left") > 0)
+ {
+ viewangleoffset = ANG90;
+ drone = true;
+ }
+
+ //!
+ // @category net
+ //
+ // Run as the right screen in three screen mode.
+ //
+
+ if (M_CheckParm("-right") > 0)
+ {
+ viewangleoffset = ANG270;
+ drone = true;
+ }
+
+ if (!NET_CL_Connect(addr))
+ {
+ I_Error("D_CheckNetGame: Failed to connect to %s\n",
+ NET_AddrToString(addr));
+ }
+
+ printf("D_CheckNetGame: Connected to %s\n", NET_AddrToString(addr));
+
+ NET_WaitForStart();
+ }
+ }
+
+#endif
+
+ num_players = 0;
+
+ for (i=0; i<MAXPLAYERS; ++i)
+ {
+ if (playeringame[i])
+ ++num_players;
+ }
+
+ printf (DEH_String("startskill %i deathmatch: %i startmap: %i startepisode: %i\n"),
+ startskill, deathmatch, startmap, startepisode);
+
+ printf(DEH_String("player %i of %i (%i nodes)\n"),
+ consoleplayer+1, num_players, num_players);
+
+ // Show players here; the server might have specified a time limit
+
+ if (timelimit > 0)
+ {
+ printf(DEH_String("Levels will end after %d minute"),timelimit);
+ if (timelimit > 1)
+ printf("s");
+ printf(".\n");
+ }
+}
+
+
+//
+// D_QuitNetGame
+// Called before quitting to leave a net game
+// without hanging the other players
+//
+void D_QuitNetGame (void)
+{
+ if (debugfile)
+ fclose (debugfile);
+
+#ifdef FEATURE_MULTIPLAYER
+
+ NET_SV_Shutdown();
+ NET_CL_Disconnect();
+
+#endif
+
+}
+
+// Returns true if there are currently any players in the game.
+
+static boolean PlayersInGame(void)
+{
+ int i;
+
+ for (i=0; i<MAXPLAYERS; ++i)
+ {
+ if (playeringame[i])
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+static int GetLowTic(void)
+{
+ int i;
+ int lowtic;
+
+ if (net_client_connected)
+ {
+ lowtic = INT_MAX;
+
+ for (i=0; i<MAXPLAYERS; ++i)
+ {
+ if (playeringame[i])
+ {
+ if (nettics[i] < lowtic)
+ lowtic = nettics[i];
+ }
+ }
+ }
+ else
+ {
+ lowtic = maketic;
+ }
+
+ return lowtic;
+}
+
+//
+// TryRunTics
+//
+int oldnettics;
+int frametics[4];
+int frameon;
+int frameskip[4];
+int oldnettics;
+
+extern boolean advancedemo;
+
+void TryRunTics (void)
+{
+ int i;
+ int lowtic;
+ int entertic;
+ static int oldentertics;
+ int realtics;
+ int availabletics;
+ int counts;
+
+ // get real tics
+ entertic = I_GetTime() / ticdup;
+ realtics = entertic - oldentertics;
+ oldentertics = entertic;
+
+ // get available tics
+ NetUpdate ();
+
+ lowtic = GetLowTic();
+
+ availabletics = lowtic - gametic/ticdup;
+
+ // decide how many tics to run
+
+ if (net_cl_new_sync)
+ {
+ counts = availabletics;
+ }
+ else
+ {
+ // 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 (!demoplayback)
+ {
+ int keyplayer = -1;
+
+ // ideally maketic should be 1 - 3 tics above lowtic
+ // if we are consistantly slower, speed up time
+
+ for (i=0 ; i<MAXPLAYERS ; i++)
+ {
+ if (playeringame[i])
+ {
+ keyplayer = i;
+ break;
+ }
+ }
+
+ if (keyplayer < 0)
+ {
+ // If there are no players, we can never advance anyway
+
+ return;
+ }
+
+ if (consoleplayer == keyplayer)
+ {
+ // the key player does not adapt
+ }
+ else
+ {
+ if (maketic <= nettics[keyplayer])
+ {
+ lasttime--;
+ // printf ("-");
+ }
+
+ frameskip[frameon & 3] = (oldnettics > nettics[keyplayer]);
+ oldnettics = maketic;
+
+ if (frameskip[0] && frameskip[1] && frameskip[2] && frameskip[3])
+ {
+ skiptics = 1;
+ // printf ("+");
+ }
+ }
+ }
+ }
+
+ if (counts < 1)
+ counts = 1;
+
+ // wait for new tics if needed
+
+ while (!PlayersInGame() || lowtic < gametic/ticdup + counts)
+ {
+ NetUpdate ();
+
+ lowtic = GetLowTic();
+
+ if (lowtic < gametic/ticdup)
+ I_Error ("TryRunTics: lowtic < gametic");
+
+ // Don't stay in this loop forever. The menu is still running,
+ // so return to update the screen
+
+ if (I_GetTime() / ticdup - entertic > 0)
+ {
+ return;
+ }
+
+ I_Sleep(1);
+ }
+
+ // run the count * ticdup dics
+ while (counts--)
+ {
+ for (i=0 ; i<ticdup ; i++)
+ {
+ // check that there are players in the game. if not, we cannot
+ // run a tic.
+
+ if (!PlayersInGame())
+ {
+ return;
+ }
+
+ if (gametic/ticdup > lowtic)
+ I_Error ("gametic>lowtic");
+ if (advancedemo)
+ D_DoAdvanceDemo ();
+
+ 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 ; j<MAXPLAYERS ; j++)
+ {
+ cmd = &netcmds[j][buf];
+ cmd->chatchar = 0;
+ if (cmd->buttons & BT_SPECIAL)
+ cmd->buttons = 0;
+ }
+ }
+ }
+ NetUpdate (); // check for new console commands
+ }
+}
+
--- /dev/null
+++ b/src/doom/d_net.h
@@ -1,0 +1,57 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION:
+// Networking stuff.
+//
+//-----------------------------------------------------------------------------
+
+
+#ifndef __D_NET__
+#define __D_NET__
+
+#include "d_player.h"
+
+#define MAXNETNODES 8
+
+// Networking and tick handling related.
+#define BACKUPTICS 128
+
+extern int extratics;
+
+// Create any new ticcmds and broadcast to other players.
+void NetUpdate (void);
+
+// Broadcasts special packets to other players
+// to notify of game exit
+void D_QuitNetGame (void);
+
+//? how many ticks to run?
+void TryRunTics (void);
+
+// Called at start of game loop to initialise timers
+void D_StartGameLoop(void);
+
+extern boolean drone;
+extern boolean net_cl_new_sync;
+
+#endif
+
--- /dev/null
+++ b/src/doom/d_player.h
@@ -1,0 +1,216 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION:
+//
+//
+//-----------------------------------------------------------------------------
+
+
+#ifndef __D_PLAYER__
+#define __D_PLAYER__
+
+
+// The player data structure depends on a number
+// of other structs: items (internal inventory),
+// animation states (closely tied to the sprites
+// used to represent them, unfortunately).
+#include "d_items.h"
+#include "p_pspr.h"
+
+// In addition, the player is just a special
+// case of the generic moving object/actor.
+#include "p_mobj.h"
+
+// Finally, for odd reasons, the player input
+// is buffered within the player data struct,
+// as commands per game tick.
+#include "d_ticcmd.h"
+
+
+
+
+
+//
+// Player states.
+//
+typedef enum
+{
+ // Playing or camping.
+ PST_LIVE,
+ // Dead on the ground, view follows killer.
+ PST_DEAD,
+ // Ready to restart/respawn???
+ PST_REBORN
+
+} playerstate_t;
+
+
+//
+// Player internal flags, for cheats and debug.
+//
+typedef enum
+{
+ // No clipping, walk through barriers.
+ CF_NOCLIP = 1,
+ // No damage, no health loss.
+ CF_GODMODE = 2,
+ // Not really a cheat, just a debug aid.
+ CF_NOMOMENTUM = 4
+
+} cheat_t;
+
+
+//
+// Extended player object info: player_t
+//
+typedef struct player_s
+{
+ mobj_t* mo;
+ playerstate_t playerstate;
+ ticcmd_t cmd;
+
+ // Determine POV,
+ // including viewpoint bobbing during movement.
+ // Focal origin above r.z
+ fixed_t viewz;
+ // Base height above floor for viewz.
+ fixed_t viewheight;
+ // Bob/squat speed.
+ fixed_t deltaviewheight;
+ // bounded/scaled total momentum.
+ fixed_t bob;
+
+ // This is only used between levels,
+ // mo->health is used during levels.
+ int health;
+ int armorpoints;
+ // Armor type is 0-2.
+ int armortype;
+
+ // Power ups. invinc and invis are tic counters.
+ int powers[NUMPOWERS];
+ boolean cards[NUMCARDS];
+ boolean backpack;
+
+ // Frags, kills of other players.
+ int frags[MAXPLAYERS];
+ weapontype_t readyweapon;
+
+ // Is wp_nochange if not changing.
+ weapontype_t pendingweapon;
+
+ boolean weaponowned[NUMWEAPONS];
+ int ammo[NUMAMMO];
+ int maxammo[NUMAMMO];
+
+ // True if button down last tic.
+ int attackdown;
+ int usedown;
+
+ // Bit flags, for cheats and debug.
+ // See cheat_t, above.
+ int cheats;
+
+ // Refired shots are less accurate.
+ int refire;
+
+ // For intermission stats.
+ int killcount;
+ int itemcount;
+ int secretcount;
+
+ // Hint messages.
+ char* message;
+
+ // For screen flashing (red or bright).
+ int damagecount;
+ int bonuscount;
+
+ // Who did damage (NULL for floors/ceilings).
+ mobj_t* attacker;
+
+ // So gun flashes light up areas.
+ int extralight;
+
+ // Current PLAYPAL, ???
+ // can be set to REDCOLORMAP for pain, etc.
+ int fixedcolormap;
+
+ // Player skin colorshift,
+ // 0-3 for which color to draw player.
+ int colormap;
+
+ // Overlay view sprites (gun, etc).
+ pspdef_t psprites[NUMPSPRITES];
+
+ // True if secret level has been done.
+ boolean didsecret;
+
+} player_t;
+
+
+//
+// INTERMISSION
+// Structure passed e.g. to WI_Start(wb)
+//
+typedef struct
+{
+ boolean in; // whether the player is in game
+
+ // Player stats, kills, collected items etc.
+ int skills;
+ int sitems;
+ int ssecret;
+ int stime;
+ int frags[4];
+ int score; // current score on entry, modified on return
+
+} wbplayerstruct_t;
+
+typedef struct
+{
+ int epsd; // episode # (0-2)
+
+ // if true, splash the secret level
+ boolean didsecret;
+
+ // previous and next levels, origin 0
+ int last;
+ int next;
+
+ int maxkills;
+ int maxitems;
+ int maxsecret;
+ int maxfrags;
+
+ // the par time
+ int partime;
+
+ // index of this player in game
+ int pnum;
+
+ wbplayerstruct_t plyr[MAXPLAYERS];
+
+} wbstartstruct_t;
+
+
+#endif
--- /dev/null
+++ b/src/doom/d_textur.h
@@ -1,0 +1,51 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION:
+// Typedefs related to to textures etc.,
+// isolated here to make it easier separating modules.
+//
+//-----------------------------------------------------------------------------
+
+
+#ifndef __D_TEXTUR__
+#define __D_TEXTUR__
+
+#include "doomtype.h"
+
+
+
+
+//
+// Flats?
+//
+// a pic is an unmasked block of pixels
+typedef struct
+{
+ byte width;
+ byte height;
+ byte data;
+} pic_t;
+
+
+
+
+#endif
--- /dev/null
+++ b/src/doom/d_think.h
@@ -1,0 +1,76 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION:
+// MapObj data. Map Objects or mobjs are actors, entities,
+// thinker, take-your-pick... anything that moves, acts, or
+// suffers state changes of more or less violent nature.
+//
+//-----------------------------------------------------------------------------
+
+
+#ifndef __D_THINK__
+#define __D_THINK__
+
+
+
+
+
+//
+// Experimental stuff.
+// To compile this as "ANSI C with classes"
+// we will need to handle the various
+// action functions cleanly.
+//
+typedef void (*actionf_v)();
+typedef void (*actionf_p1)( void* );
+typedef void (*actionf_p2)( void*, void* );
+
+typedef union
+{
+ actionf_v acv;
+ actionf_p1 acp1;
+ actionf_p2 acp2;
+
+} actionf_t;
+
+
+
+
+
+// Historically, "think_t" is yet another
+// function pointer to a routine to handle
+// an actor.
+typedef actionf_t think_t;
+
+
+// Doubly linked list of actors.
+typedef struct thinker_s
+{
+ struct thinker_s* prev;
+ struct thinker_s* next;
+ think_t function;
+
+} thinker_t;
+
+
+
+#endif
--- /dev/null
+++ b/src/doom/doomdata.h
@@ -1,0 +1,221 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION:
+// all external data is defined here
+// most of the data is loaded into different structures at run time
+// some internal structures shared by many modules are here
+//
+//-----------------------------------------------------------------------------
+
+#ifndef __DOOMDATA__
+#define __DOOMDATA__
+
+// The most basic types we use, portability.
+#include "doomtype.h"
+
+// Some global defines, that configure the game.
+#include "doomdef.h"
+
+
+
+//
+// Map level types.
+// The following data structures define the persistent format
+// used in the lumps of the WAD files.
+//
+
+// Lump order in a map WAD: each map needs a couple of lumps
+// to provide a complete scene geometry description.
+enum
+{
+ ML_LABEL, // A separator, name, ExMx or MAPxx
+ ML_THINGS, // Monsters, items..
+ ML_LINEDEFS, // LineDefs, from editing
+ ML_SIDEDEFS, // SideDefs, from editing
+ ML_VERTEXES, // Vertices, edited and BSP splits generated
+ ML_SEGS, // LineSegs, from LineDefs split by BSP
+ ML_SSECTORS, // SubSectors, list of LineSegs
+ ML_NODES, // BSP nodes
+ ML_SECTORS, // Sectors, from editing
+ ML_REJECT, // LUT, sector-sector visibility
+ ML_BLOCKMAP // LUT, motion clipping, walls/grid element
+};
+
+
+// A single Vertex.
+typedef struct
+{
+ short x;
+ short y;
+} PACKEDATTR mapvertex_t;
+
+
+// A SideDef, defining the visual appearance of a wall,
+// by setting textures and offsets.
+typedef struct
+{
+ short textureoffset;
+ short rowoffset;
+ char toptexture[8];
+ char bottomtexture[8];
+ char midtexture[8];
+ // Front sector, towards viewer.
+ short sector;
+} PACKEDATTR mapsidedef_t;
+
+
+
+// A LineDef, as used for editing, and as input
+// to the BSP builder.
+typedef struct
+{
+ short v1;
+ short v2;
+ short flags;
+ short special;
+ short tag;
+ // sidenum[1] will be -1 if one sided
+ short sidenum[2];
+} PACKEDATTR maplinedef_t;
+
+
+//
+// LineDef attributes.
+//
+
+// Solid, is an obstacle.
+#define ML_BLOCKING 1
+
+// Blocks monsters only.
+#define ML_BLOCKMONSTERS 2
+
+// Backside will not be present at all
+// if not two sided.
+#define ML_TWOSIDED 4
+
+// If a texture is pegged, the texture will have
+// the end exposed to air held constant at the
+// top or bottom of the texture (stairs or pulled
+// down things) and will move with a height change
+// of one of the neighbor sectors.
+// Unpegged textures allways have the first row of
+// the texture at the top pixel of the line for both
+// top and bottom textures (use next to windows).
+
+// upper texture unpegged
+#define ML_DONTPEGTOP 8
+
+// lower texture unpegged
+#define ML_DONTPEGBOTTOM 16
+
+// In AutoMap: don't map as two sided: IT'S A SECRET!
+#define ML_SECRET 32
+
+// Sound rendering: don't let sound cross two of these.
+#define ML_SOUNDBLOCK 64
+
+// Don't draw on the automap at all.
+#define ML_DONTDRAW 128
+
+// Set if already seen, thus drawn in automap.
+#define ML_MAPPED 256
+
+
+
+
+// Sector definition, from editing.
+typedef struct
+{
+ short floorheight;
+ short ceilingheight;
+ char floorpic[8];
+ char ceilingpic[8];
+ short lightlevel;
+ short special;
+ short tag;
+} PACKEDATTR mapsector_t;
+
+// SubSector, as generated by BSP.
+typedef struct
+{
+ short numsegs;
+ // Index of first one, segs are stored sequentially.
+ short firstseg;
+} PACKEDATTR mapsubsector_t;
+
+
+// LineSeg, generated by splitting LineDefs
+// using partition lines selected by BSP builder.
+typedef struct
+{
+ short v1;
+ short v2;
+ short angle;
+ short linedef;
+ short side;
+ short offset;
+} PACKEDATTR mapseg_t;
+
+
+
+// BSP node structure.
+
+// Indicate a leaf.
+#define NF_SUBSECTOR 0x8000
+
+typedef struct
+{
+ // Partition line from (x,y) to x+dx,y+dy)
+ short x;
+ short y;
+ short dx;
+ short dy;
+
+ // Bounding box for each child,
+ // clip against view frustum.
+ short bbox[2][4];
+
+ // If NF_SUBSECTOR its a subsector,
+ // else it's a node of another subtree.
+ unsigned short children[2];
+
+} PACKEDATTR mapnode_t;
+
+
+
+
+// Thing definition, position, orientation and type,
+// plus skill/visibility flags and attributes.
+typedef struct
+{
+ short x;
+ short y;
+ short angle;
+ short type;
+ short options;
+} PACKEDATTR mapthing_t;
+
+
+
+
+
+#endif // __DOOMDATA__
--- /dev/null
+++ b/src/doom/doomdef.c
@@ -1,0 +1,36 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION:
+// DoomDef - basic defines for DOOM, e.g. Version, game mode
+// and skill level, and display parameters.
+//
+//-----------------------------------------------------------------------------
+
+
+
+#include "doomdef.h"
+
+// Location for any defines turned variables.
+
+// None.
+
+
--- /dev/null
+++ b/src/doom/doomdef.h
@@ -1,0 +1,312 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION:
+// Internally used data structures for virtually everything,
+// lots of other stuff.
+//
+//-----------------------------------------------------------------------------
+
+#ifndef __DOOMDEF__
+#define __DOOMDEF__
+
+#include <stdio.h>
+#include <string.h>
+
+// #define macros to provide functions missing in Windows.
+// Outside Windows, we use strings.h for str[n]casecmp.
+
+
+#ifdef _WIN32
+
+#define snprintf _snprintf
+#define vsnprintf _vsnprintf
+#define strcasecmp stricmp
+#define strncasecmp strnicmp
+
+#else
+
+#include <strings.h>
+
+#endif
+
+
+//
+// The packed attribute forces structures to be packed into the minimum
+// space necessary. If this is not done, the compiler may align structure
+// fields differently to optimise memory access, inflating the overall
+// structure size. It is important to use the packed attribute on certain
+// structures where alignment is important, particularly data read/written
+// to disk.
+//
+
+#ifdef __GNUC__
+#define PACKEDATTR __attribute__((packed))
+#else
+#define PACKEDATTR
+#endif
+
+//
+// Global parameters/defines.
+//
+// DOOM version
+#define DOOM_VERSION 109
+
+// Version code for cph's longtics hack ("v1.91")
+#define DOOM_191_VERSION 111
+
+
+// Game mode handling - identify IWAD version
+// to handle IWAD dependend animations etc.
+typedef enum
+{
+ shareware, // DOOM 1 shareware, E1, M9
+ registered, // DOOM 1 registered, E3, M27
+ commercial, // DOOM 2 retail, E1 M34
+ // DOOM 2 german edition not handled
+ retail, // DOOM 1 retail, E4, M36
+ indetermined // Well, no IWAD found.
+
+} GameMode_t;
+
+
+// Mission packs - might be useful for TC stuff?
+typedef enum
+{
+ doom, // DOOM 1
+ doom2, // DOOM 2
+ pack_tnt, // TNT mission pack
+ pack_plut, // Plutonia pack
+ none
+
+} GameMission_t;
+
+// What version are we emulating?
+
+typedef enum
+{
+ exe_doom_1_9, // Doom 1.9: used for shareware, registered and commercial
+ exe_ultimate, // Ultimate Doom (retail)
+ exe_final, // Final Doom
+ exe_chex, // Chex Quest executable (based on Final Doom)
+} GameVersion_t;
+
+
+// If rangecheck is undefined,
+// most parameter validation debugging code will not be compiled
+#define RANGECHECK
+
+
+
+// Screen width and height.
+
+#define SCREENWIDTH 320
+#define SCREENHEIGHT 200
+
+// Screen width used for "squash" scale functions
+
+#define SCREENWIDTH_4_3 256
+
+// Screen height used for "stretch" scale functions.
+
+#define SCREENHEIGHT_4_3 240
+
+// The maximum number of players, multiplayer/networking.
+#define MAXPLAYERS 4
+
+// State updates, number of tics / second.
+#define TICRATE 35
+
+// The current state of the game: whether we are
+// playing, gazing at the intermission screen,
+// the game final animation, or a demo.
+typedef enum
+{
+ GS_LEVEL,
+ GS_INTERMISSION,
+ GS_FINALE,
+ GS_DEMOSCREEN,
+} gamestate_t;
+
+//
+// Difficulty/skill settings/filters.
+//
+
+// Skill flags.
+#define MTF_EASY 1
+#define MTF_NORMAL 2
+#define MTF_HARD 4
+
+// Deaf monsters/do not react to sound.
+#define MTF_AMBUSH 8
+
+typedef enum
+{
+ sk_noitems = -1, // the "-skill 0" hack
+ sk_baby = 0,
+ sk_easy,
+ sk_medium,
+ sk_hard,
+ sk_nightmare
+} skill_t;
+
+
+
+
+//
+// Key cards.
+//
+typedef enum
+{
+ it_bluecard,
+ it_yellowcard,
+ it_redcard,
+ it_blueskull,
+ it_yellowskull,
+ it_redskull,
+
+ NUMCARDS
+
+} card_t;
+
+
+
+// The defined weapons,
+// including a marker indicating
+// user has not changed weapon.
+typedef enum
+{
+ wp_fist,
+ wp_pistol,
+ wp_shotgun,
+ wp_chaingun,
+ wp_missile,
+ wp_plasma,
+ wp_bfg,
+ wp_chainsaw,
+ wp_supershotgun,
+
+ NUMWEAPONS,
+
+ // No pending weapon change.
+ wp_nochange
+
+} weapontype_t;
+
+
+// Ammunition types defined.
+typedef enum
+{
+ am_clip, // Pistol / chaingun ammo.
+ am_shell, // Shotgun / double barreled shotgun.
+ am_cell, // Plasma rifle, BFG.
+ am_misl, // Missile launcher.
+ NUMAMMO,
+ am_noammo // Unlimited for chainsaw / fist.
+
+} ammotype_t;
+
+
+// Power up artifacts.
+typedef enum
+{
+ pw_invulnerability,
+ pw_strength,
+ pw_invisibility,
+ pw_ironfeet,
+ pw_allmap,
+ pw_infrared,
+ NUMPOWERS
+
+} powertype_t;
+
+
+
+//
+// Power up durations,
+// how many seconds till expiration,
+// assuming TICRATE is 35 ticks/second.
+//
+typedef enum
+{
+ INVULNTICS = (30*TICRATE),
+ INVISTICS = (60*TICRATE),
+ INFRATICS = (120*TICRATE),
+ IRONTICS = (60*TICRATE)
+
+} powerduration_t;
+
+
+// fraggle: moved key definitions to a separate file
+
+#include "doomkeys.h"
+
+
+// DOOM basic types (boolean),
+// and max/min values.
+//#include "doomtype.h"
+
+// Fixed point.
+//#include "m_fixed.h"
+
+// Endianess handling.
+//#include "m_swap.h"
+
+
+// Binary Angles, sine/cosine/atan lookups.
+//#include "tables.h"
+
+// Event type.
+//#include "d_event.h"
+
+// Game function, skills.
+//#include "g_game.h"
+
+// All external data is defined here.
+//#include "doomdata.h"
+
+// All important printed strings.
+// Language selection (message strings).
+//#include "dstrings.h"
+
+// Player is a special actor.
+//struct player_s;
+
+
+//#include "d_items.h"
+//#include "d_player.h"
+//#include "p_mobj.h"
+//#include "d_net.h"
+
+// PLAY
+//#include "p_tick.h"
+
+
+
+
+// Header, generated by sound utility.
+// The utility was written by Dave Taylor.
+//#include "sounds.h"
+
+
+
+
+#endif // __DOOMDEF__
--- /dev/null
+++ b/src/doom/doomstat.c
@@ -1,0 +1,43 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION:
+// Put all global tate variables here.
+//
+//-----------------------------------------------------------------------------
+
+
+
+#include "doomstat.h"
+
+
+// Game Mode - identify IWAD as shareware, retail etc.
+GameMode_t gamemode = indetermined;
+GameMission_t gamemission = doom;
+GameVersion_t gameversion = exe_final;
+char *gamedescription;
+
+// Set if homebrew PWAD stuff has been added.
+boolean modifiedgame;
+
+
+
+
--- /dev/null
+++ b/src/doom/doomstat.h
@@ -1,0 +1,300 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION:
+// All the global variables that store the internal state.
+// Theoretically speaking, the internal state of the engine
+// should be found by looking at the variables collected
+// here, and every relevant module will have to include
+// this header file.
+// In practice, things are a bit messy.
+//
+//-----------------------------------------------------------------------------
+
+
+#ifndef __D_STATE__
+#define __D_STATE__
+
+// We need globally shared data structures,
+// for defining the global state variables.
+#include "doomdata.h"
+#include "d_net.h"
+
+// We need the playr data structure as well.
+#include "d_player.h"
+
+
+
+
+
+// ------------------------
+// Command line parameters.
+//
+extern boolean nomonsters; // checkparm of -nomonsters
+extern boolean respawnparm; // checkparm of -respawn
+extern boolean fastparm; // checkparm of -fast
+
+extern boolean devparm; // DEBUG: launched with -devparm
+
+
+extern boolean screensaver_mode; // game running as a screensaver?
+
+// -----------------------------------------------------
+// Game Mode - identify IWAD as shareware, retail etc.
+//
+extern GameMode_t gamemode;
+extern GameMission_t gamemission;
+extern GameVersion_t gameversion;
+extern char *gamedescription;
+
+// Set if homebrew PWAD stuff has been added.
+extern boolean modifiedgame;
+
+
+// -------------------------------------------
+// Selected skill type, map etc.
+//
+
+// Defaults for menu, methinks.
+extern skill_t startskill;
+extern int startepisode;
+extern int startmap;
+
+// Savegame slot to load on startup. This is the value provided to
+// the -loadgame option. If this has not been provided, this is -1.
+
+extern int startloadgame;
+
+extern boolean autostart;
+
+// Selected by user.
+extern skill_t gameskill;
+extern int gameepisode;
+extern int gamemap;
+
+// If non-zero, exit the level after this number of minutes
+extern int timelimit;
+
+// vertical movement from mouse/joystick disabled
+extern int novert;
+
+// Nightmare mode flag, single player.
+extern boolean respawnmonsters;
+
+// Netgame? Only true if >1 player.
+extern boolean netgame;
+
+// Flag: true only if started as net deathmatch.
+// An enum might handle altdeath/cooperative better.
+extern boolean deathmatch;
+
+// -------------------------
+// Internal parameters for sound rendering.
+// These have been taken from the DOS version,
+// but are not (yet) supported with Linux
+// (e.g. no sound volume adjustment with menu.
+
+// From m_menu.c:
+// Sound FX volume has default, 0 - 15
+// Music volume has default, 0 - 15
+// These are multiplied by 8.
+extern int sfxVolume;
+extern int musicVolume;
+
+// Current music/sfx card - index useless
+// w/o a reference LUT in a sound module.
+// Ideally, this would use indices found
+// in: /usr/include/linux/soundcard.h
+extern int snd_MusicDevice;
+extern int snd_SfxDevice;
+// Config file? Same disclaimer as above.
+extern int snd_DesiredMusicDevice;
+extern int snd_DesiredSfxDevice;
+
+
+// -------------------------
+// Status flags for refresh.
+//
+
+// Depending on view size - no status bar?
+// Note that there is no way to disable the
+// status bar explicitely.
+extern boolean statusbaractive;
+
+extern boolean automapactive; // In AutoMap mode?
+extern boolean menuactive; // Menu overlayed?
+extern boolean paused; // Game Pause?
+
+
+extern boolean viewactive;
+
+extern boolean nodrawers;
+extern boolean noblit;
+
+extern int viewwindowx;
+extern int viewwindowy;
+extern int viewheight;
+extern int viewwidth;
+extern int scaledviewwidth;
+
+extern boolean testcontrols;
+
+
+
+
+// This one is related to the 3-screen display mode.
+// ANG90 = left side, ANG270 = right
+extern int viewangleoffset;
+
+// Player taking events, and displaying.
+extern int consoleplayer;
+extern int displayplayer;
+
+
+// -------------------------------------
+// Scores, rating.
+// Statistics on a given map, for intermission.
+//
+extern int totalkills;
+extern int totalitems;
+extern int totalsecret;
+
+// Timer, for scores.
+extern int levelstarttic; // gametic at level start
+extern int leveltime; // tics in game play for par
+
+
+
+// --------------------------------------
+// DEMO playback/recording related stuff.
+// No demo, there is a human player in charge?
+// Disable save/end game?
+extern boolean usergame;
+
+//?
+extern boolean demoplayback;
+extern boolean demorecording;
+
+// Round angleturn in ticcmds to the nearest 256. This is used when
+// recording Vanilla demos in netgames.
+
+extern boolean lowres_turn;
+
+// Quit after playing a demo from cmdline.
+extern boolean singledemo;
+
+
+
+
+//?
+extern gamestate_t gamestate;
+
+
+
+
+
+
+//-----------------------------
+// Internal parameters, fixed.
+// These are set by the engine, and not changed
+// according to user inputs. Partly load from
+// WAD, partly set at startup time.
+
+
+
+extern int gametic;
+
+
+// Bookkeeping on players - state.
+extern player_t players[MAXPLAYERS];
+
+// Alive? Disconnected?
+extern boolean playeringame[MAXPLAYERS];
+
+
+// Player spawn spots for deathmatch.
+#define MAX_DM_STARTS 10
+extern mapthing_t deathmatchstarts[MAX_DM_STARTS];
+extern mapthing_t* deathmatch_p;
+
+// Player spawn spots.
+extern mapthing_t playerstarts[MAXPLAYERS];
+
+// Intermission stats.
+// Parameters for world map / intermission.
+extern wbstartstruct_t wminfo;
+
+
+// LUT of ammunition limits for each kind.
+// This doubles with BackPack powerup item.
+extern int maxammo[NUMAMMO];
+
+
+
+
+
+//-----------------------------------------
+// Internal parameters, used for engine.
+//
+
+// File handling stuff.
+extern char * savegamedir;
+extern char basedefault[1024];
+extern FILE* debugfile;
+
+// if true, load all graphics at level load
+extern boolean precache;
+
+
+// wipegamestate can be set to -1
+// to force a wipe on the next draw
+extern gamestate_t wipegamestate;
+
+extern int mouseSensitivity;
+//?
+// debug flag to cancel adaptiveness
+extern boolean singletics;
+
+extern int bodyqueslot;
+
+
+
+// Needed to store the number of the dummy sky flat.
+// Used for rendering,
+// as well as tracking projectiles etc.
+extern int skyflatnum;
+
+
+
+// Netgame stuff (buffers and pointers, i.e. indices).
+
+
+extern int rndindex;
+
+extern int maketic;
+extern int nettics[MAXPLAYERS];
+
+extern ticcmd_t netcmds[MAXPLAYERS][BACKUPTICS];
+extern int ticdup;
+
+
+
+#endif
--- /dev/null
+++ b/src/doom/dstrings.c
@@ -1,0 +1,81 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION:
+// Globally defined strings.
+//
+//-----------------------------------------------------------------------------
+
+
+
+#include "dstrings.h"
+
+char *doom1_endmsg[] =
+{
+ "are you sure you want to\nquit this great game?",
+ "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.",
+};
+
+char *doom2_endmsg[] =
+{
+ // QuitDOOM II messages
+ "are you sure you want to\nquit this great game?",
+ "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.",
+};
+
+#if 0
+
+// UNUSED messages included in the source release
+
+char* endmsg[] =
+{
+ // DOOM1
+ QUITMSG,
+ // FinalDOOM?
+ "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!",
+
+ // Internal debug. Different style, too.
+ "THIS IS NO MESSAGE!\nPage intentionally left blank."
+};
+
+#endif
+
+
+
+
--- /dev/null
+++ b/src/doom/dstrings.h
@@ -1,0 +1,58 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+//
+// DESCRIPTION:
+// DOOM strings, by language.
+//
+//-----------------------------------------------------------------------------
+
+
+#ifndef __DSTRINGS__
+#define __DSTRINGS__
+
+
+// All important printed strings.
+
+#include "d_englsh.h"
+
+// Misc. other strings.
+#define SAVEGAMENAME "doomsav"
+
+
+//
+// File locations,
+// relative to current position.
+// Path names are OS-sensitive.
+//
+#define DEVMAPS "devmaps"
+#define DEVDATA "devdata"
+
+
+// QuitDOOM messages
+// 8 per each game type
+#define NUM_QUITMESSAGES 8
+
+extern char *doom1_endmsg[];
+extern char *doom2_endmsg[];
+
+
+#endif
--- /dev/null
+++ b/src/doom/f_finale.c
@@ -1,0 +1,728 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION:
+// Game completion, final screen animation.
+//
+//-----------------------------------------------------------------------------
+
+
+
+#include <ctype.h>
+
+// Functions.
+#include "deh_main.h"
+#include "i_system.h"
+#include "i_swap.h"
+#include "z_zone.h"
+#include "v_video.h"
+#include "w_wad.h"
+#include "s_sound.h"
+
+// Data.
+#include "dstrings.h"
+#include "sounds.h"
+
+#include "doomstat.h"
+#include "r_state.h"
+
+typedef enum
+{
+ F_STAGE_TEXT,
+ F_STAGE_ARTSCREEN,
+ F_STAGE_CAST,
+} finalestage_t;
+
+// ?
+//#include "doomstat.h"
+//#include "r_local.h"
+//#include "f_finale.h"
+
+// Stage of animation:
+finalestage_t finalestage;
+
+unsigned int finalecount;
+
+#define TEXTSPEED 3
+#define TEXTWAIT 250
+
+typedef struct
+{
+ GameMission_t mission;
+ int episode, level;
+ char *background;
+ char *text;
+} textscreen_t;
+
+static textscreen_t textscreens[] =
+{
+ { doom, 1, 8, "FLOOR4_8", E1TEXT},
+ { doom, 2, 8, "SFLR6_1", E2TEXT},
+ { doom, 3, 8, "MFLR8_4", E3TEXT},
+ { doom, 4, 8, "MFLR8_3", E4TEXT},
+
+ { doom2, 1, 6, "SLIME16", C1TEXT},
+ { doom2, 1, 11, "RROCK14", C2TEXT},
+ { doom2, 1, 20, "RROCK07", C3TEXT},
+ { doom2, 1, 30, "RROCK17", C4TEXT},
+ { doom2, 1, 15, "RROCK13", C5TEXT},
+ { doom2, 1, 31, "RROCK19", C6TEXT},
+
+ { pack_tnt, 1, 6, "SLIME16", T1TEXT},
+ { pack_tnt, 1, 11, "RROCK14", T2TEXT},
+ { pack_tnt, 1, 20, "RROCK07", T3TEXT},
+ { pack_tnt, 1, 30, "RROCK17", T4TEXT},
+ { pack_tnt, 1, 15, "RROCK13", T5TEXT},
+ { pack_tnt, 1, 31, "RROCK19", T6TEXT},
+
+ { pack_plut, 1, 6, "SLIME16", P1TEXT},
+ { pack_plut, 1, 11, "RROCK14", P2TEXT},
+ { pack_plut, 1, 20, "RROCK07", P3TEXT},
+ { pack_plut, 1, 30, "RROCK17", P4TEXT},
+ { pack_plut, 1, 15, "RROCK13", P5TEXT},
+ { pack_plut, 1, 31, "RROCK19", P6TEXT},
+};
+
+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)
+{
+ size_t i;
+
+ gameaction = ga_nothing;
+ gamestate = GS_FINALE;
+ viewactive = false;
+ automapactive = false;
+
+ if (gamemission == doom)
+ {
+ S_ChangeMusic(mus_victor, true);
+ }
+ else
+ {
+ S_ChangeMusic(mus_read_m, true);
+ }
+
+ // Find the right screen and set the text and background
+
+ for (i=0; i<arrlen(textscreens); ++i)
+ {
+ textscreen_t *screen = &textscreens[i];
+
+ // Hack for Chex Quest
+
+ if (gameversion == exe_chex && screen->mission == doom)
+ {
+ screen->level = 5;
+ }
+
+ if (gamemission == screen->mission
+ && (gamemission != doom || gameepisode == screen->episode)
+ && gamemap == screen->level)
+ {
+ finaletext = screen->text;
+ finaleflat = screen->background;
+ }
+ }
+
+ // Do dehacked substitutions of strings
+
+ finaletext = DEH_String(finaletext);
+ finaleflat = DEH_String(finaleflat);
+
+ finalestage = F_STAGE_TEXT;
+ finalecount = 0;
+
+}
+
+
+
+boolean F_Responder (event_t *event)
+{
+ if (finalestage == F_STAGE_CAST)
+ return F_CastResponder (event);
+
+ return false;
+}
+
+
+//
+// F_Ticker
+//
+void F_Ticker (void)
+{
+ size_t i;
+
+ // check for skipping
+ if ( (gamemode == commercial)
+ && ( finalecount > 50) )
+ {
+ // go on to the next level
+ for (i=0 ; i<MAXPLAYERS ; i++)
+ if (players[i].cmd.buttons)
+ break;
+
+ if (i < MAXPLAYERS)
+ {
+ if (gamemap == 30)
+ F_StartCast ();
+ else
+ gameaction = ga_worlddone;
+ }
+ }
+
+ // advance animation
+ finalecount++;
+
+ if (finalestage == F_STAGE_CAST)
+ {
+ F_CastTicker ();
+ return;
+ }
+
+ if ( gamemode == commercial)
+ return;
+
+ if (finalestage == F_STAGE_TEXT
+ && finalecount>strlen (finaletext)*TEXTSPEED + TEXTWAIT)
+ {
+ finalecount = 0;
+ finalestage = F_STAGE_ARTSCREEN;
+ 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;
+ byte* dest;
+
+ int x,y,w;
+ signed int count;
+ char* ch;
+ int c;
+ int cx;
+ int cy;
+
+ // erase the entire screen to a tiled background
+ src = W_CacheLumpName ( finaleflat , PU_CACHE);
+ dest = screens[0];
+
+ for (y=0 ; y<SCREENHEIGHT ; y++)
+ {
+ for (x=0 ; x<SCREENWIDTH/64 ; x++)
+ {
+ memcpy (dest, src+((y&63)<<6), 64);
+ dest += 64;
+ }
+ if (SCREENWIDTH&63)
+ {
+ memcpy (dest, src+((y&63)<<6), SCREENWIDTH&63);
+ dest += (SCREENWIDTH&63);
+ }
+ }
+
+ V_MarkRect (0, 0, SCREENWIDTH, SCREENHEIGHT);
+
+ // draw some of the text onto the screen
+ cx = 10;
+ cy = 10;
+ ch = finaletext;
+
+ count = ((signed int) finalecount - 10) / TEXTSPEED;
+ if (count < 0)
+ count = 0;
+ for ( ; count ; count-- )
+ {
+ c = *ch++;
+ if (!c)
+ break;
+ if (c == '\n')
+ {
+ cx = 10;
+ cy += 11;
+ 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_DrawPatch(cx, cy, 0, hu_font[c]);
+ cx+=w;
+ }
+
+}
+
+//
+// Final DOOM 2 animation
+// Casting by id Software.
+// in order of appearance
+//
+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 = F_STAGE_CAST;
+ 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;
+ int 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 (DEH_String("BOSSBACK"), PU_CACHE));
+
+ F_CastPrint (DEH_String(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;
+ byte* dest;
+ byte* 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)
+{
+ signed int scrolled;
+ int x;
+ patch_t* p1;
+ patch_t* p2;
+ char name[10];
+ int stage;
+ static int laststage;
+
+ p1 = W_CacheLumpName (DEH_String("PFUB2"), PU_LEVEL);
+ p2 = W_CacheLumpName (DEH_String("PFUB1"), PU_LEVEL);
+
+ V_MarkRect (0, 0, SCREENWIDTH, SCREENHEIGHT);
+
+ scrolled = (320 - ((signed int) finalecount-230)/2);
+ if (scrolled > 320)
+ scrolled = 320;
+ if (scrolled < 0)
+ scrolled = 0;
+
+ for ( x=0 ; x<SCREENWIDTH ; x++)
+ {
+ if (x+scrolled < 320)
+ F_DrawPatchCol (x, p1, x+scrolled);
+ else
+ F_DrawPatchCol (x, p2, x+scrolled - 320);
+ }
+
+ if (finalecount < 1130)
+ return;
+ if (finalecount < 1180)
+ {
+ V_DrawPatch ((SCREENWIDTH-13*8)/2,
+ (SCREENHEIGHT-8*8)/2,0,
+ W_CacheLumpName (DEH_String("END0"),PU_CACHE));
+ laststage = 0;
+ return;
+ }
+
+ stage = (finalecount-1180) / 5;
+ if (stage > 6)
+ stage = 6;
+ if (stage > laststage)
+ {
+ S_StartSound (NULL, sfx_pistol);
+ laststage = stage;
+ }
+
+ sprintf (name, DEH_String("END%i"), stage);
+ V_DrawPatch ((SCREENWIDTH-13*8)/2, (SCREENHEIGHT-8*8)/2,0,
+ W_CacheLumpName (name,PU_CACHE));
+}
+
+static void F_ArtScreenDrawer(void)
+{
+ char *lumpname;
+
+ if (gameepisode == 3)
+ {
+ F_BunnyScroll();
+ }
+ else
+ {
+ switch (gameepisode)
+ {
+ case 1:
+ if (gamemode == retail)
+ {
+ lumpname = "CREDIT";
+ }
+ else
+ {
+ lumpname = "HELP2";
+ }
+ break;
+ case 2:
+ lumpname = "VICTORY2";
+ break;
+ case 4:
+ lumpname = "ENDPIC";
+ break;
+ default:
+ return;
+ }
+
+ lumpname = DEH_String(lumpname);
+
+ V_DrawPatch (0, 0, 0, W_CacheLumpName(lumpname, PU_CACHE));
+ }
+}
+
+//
+// F_Drawer
+//
+void F_Drawer (void)
+{
+ switch (finalestage)
+ {
+ case F_STAGE_CAST:
+ F_CastDrawer();
+ break;
+ case F_STAGE_TEXT:
+ F_TextWrite();
+ break;
+ case F_STAGE_ARTSCREEN:
+ F_ArtScreenDrawer();
+ break;
+ }
+}
+
+
--- /dev/null
+++ b/src/doom/f_finale.h
@@ -1,0 +1,53 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION:
+//
+//
+//-----------------------------------------------------------------------------
+
+
+#ifndef __F_FINALE__
+#define __F_FINALE__
+
+
+#include "doomtype.h"
+#include "d_event.h"
+//
+// FINALE
+//
+
+// Called by main loop.
+boolean F_Responder (event_t* ev);
+
+// Called by main loop.
+void F_Ticker (void);
+
+// Called by main loop.
+void F_Drawer (void);
+
+
+void F_StartFinale (void);
+
+
+
+
+#endif
--- /dev/null
+++ b/src/doom/g_game.c
@@ -1,0 +1,2138 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION: none
+//
+//-----------------------------------------------------------------------------
+
+
+
+#include <string.h>
+#include <stdlib.h>
+#include <math.h>
+
+#include "doomdef.h"
+#include "doomstat.h"
+
+#include "deh_main.h"
+#include "deh_misc.h"
+
+#include "z_zone.h"
+#include "f_finale.h"
+#include "m_argv.h"
+#include "m_misc.h"
+#include "m_menu.h"
+#include "m_random.h"
+#include "i_system.h"
+#include "i_timer.h"
+#include "i_video.h"
+
+#include "p_setup.h"
+#include "p_saveg.h"
+#include "p_tick.h"
+
+#include "d_main.h"
+
+#include "wi_stuff.h"
+#include "hu_stuff.h"
+#include "st_stuff.h"
+#include "am_map.h"
+
+// Needs access to LFB.
+#include "v_video.h"
+
+#include "w_wad.h"
+
+#include "p_local.h"
+
+#include "s_sound.h"
+
+// Data.
+#include "dstrings.h"
+#include "sounds.h"
+
+// SKY handling - still the wrong place.
+#include "r_data.h"
+#include "r_sky.h"
+
+
+
+#include "g_game.h"
+
+
+#define SAVEGAMESIZE 0x2c000
+
+
+
+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);
+
+// Gamestate the last time G_Ticker was called.
+
+gamestate_t oldgamestate;
+
+gameaction_t gameaction;
+gamestate_t gamestate;
+skill_t gameskill;
+boolean respawnmonsters;
+int gameepisode;
+int gamemap;
+
+// If non-zero, exit the level after this number of minutes.
+
+int timelimit;
+
+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];
+
+boolean turbodetected[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 longtics; // cph's doom 1.91 longtics hack
+boolean lowres_turn; // low resolution turning for longtics
+boolean demoplayback;
+boolean netdemo;
+byte* demobuffer;
+byte* demo_p;
+byte* demoend;
+boolean singledemo; // quit after playing a demo from cmdline
+
+boolean precache = true; // if true, load all graphics at start
+
+boolean testcontrols = false; // Invoked by setup to test controls
+
+wbstartstruct_t wminfo; // parms for world map / intermission
+
+byte consistancy[MAXPLAYERS][BACKUPTICS];
+
+
+//
+// Controls
+//
+int key_right = KEY_RIGHTARROW;
+int key_left = KEY_LEFTARROW;
+
+int key_up = KEY_UPARROW;
+int key_down = KEY_DOWNARROW;
+int key_strafeleft = ',';
+int key_straferight = '.';
+int key_fire = KEY_RCTRL;
+int key_use = ' ';
+int key_strafe = KEY_RALT;
+int key_speed = KEY_RSHIFT;
+
+int mousebfire = 0;
+int mousebstrafe = 1;
+int mousebforward = 2;
+
+int mousebstrafeleft = -1;
+int mousebstraferight = -1;
+int mousebbackward = -1;
+int mousebuse = -1;
+
+// Control whether if a mouse button is double clicked, it acts like
+// "use" has been pressed
+
+int dclick_use = 1;
+
+int joybfire = 0;
+int joybstrafe = 1;
+int joybuse = 3;
+int joybspeed = 2;
+int joybstrafeleft = -1;
+int joybstraferight = -1;
+
+// fraggle: Disallow mouse and joystick movement to cause forward/backward
+// motion. Specified with the '-novert' command line parameter.
+// This is an int to allow saving to config file
+
+int novert = 0;
+
+
+
+#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
+
+static boolean gamekeydown[NUMKEYS];
+static int turnheld; // for accelerative turning
+
+static boolean mousearray[4];
+static boolean *mousebuttons = &mousearray[1]; // allow [-1]
+
+// mouse values are used once
+int mousex;
+int mousey;
+
+static int dclicktime;
+static boolean dclickstate;
+static int dclicks;
+static int dclicktime2;
+static boolean dclickstate2;
+static int dclicks2;
+
+#define MAX_JOY_BUTTONS 20
+
+// joystick values are repeated
+static int joyxmove;
+static int joyymove;
+static boolean joyarray[MAX_JOY_BUTTONS + 1];
+static boolean *joybuttons = &joyarray[1]; // allow [-1]
+
+static int savegameslot;
+static char savedescription[32];
+
+static int testcontrols_mousespeed;
+
+#define BODYQUESIZE 32
+
+mobj_t* bodyque[BODYQUESIZE];
+int bodyqueslot;
+
+int vanilla_savegame_limit = 1;
+int vanilla_demo_limit = 1;
+
+
+#define MOUSE_SPEED_BOX_WIDTH 16
+#define COLOR_RED 0xb0
+#define COLOR_BLACK 0x00
+#define COLOR_WHITE 0x04
+#define COLOR_YELLOW 0xe7
+
+void G_DrawMouseSpeedBox(void)
+{
+ extern int usemouse;
+ int i;
+ int box_x, box_y;
+ int original_speed;
+ int x, y;
+ int redline_x;
+ int linelen;
+ char *lumpname;
+ int color;
+
+ // If the mouse is turned off or acceleration is turned off, don't
+ // draw the box at all.
+
+ if (!usemouse || fabs(mouse_acceleration - 1) < 0.01)
+ {
+ return;
+ }
+
+ // Calculate box position
+
+ box_x = SCREENWIDTH - MOUSE_SPEED_BOX_WIDTH * 8;
+ box_y = SCREENHEIGHT - 9;
+
+ // Draw the box.
+
+ x = box_x;
+
+ for (i=0; i<MOUSE_SPEED_BOX_WIDTH; ++i)
+ {
+ if (i == 0)
+ {
+ lumpname = "M_LSLEFT";
+ }
+ else if (i == MOUSE_SPEED_BOX_WIDTH - 1)
+ {
+ lumpname = "M_LSRGHT";
+ }
+ else
+ {
+ lumpname = "M_LSCNTR";
+ }
+
+ V_DrawPatchDirect(x, box_y, 0, W_CacheLumpName(DEH_String(lumpname),
+ PU_CACHE));
+ x += 8;
+ }
+
+ // Calculate the position of the red line. This is 1/3 of the way
+ // along the box.
+
+ redline_x = (MOUSE_SPEED_BOX_WIDTH / 3) * 8;
+
+ // Undo acceleration and get back the original mouse speed
+
+ if (testcontrols_mousespeed < mouse_threshold)
+ {
+ original_speed = testcontrols_mousespeed;
+ }
+ else
+ {
+ original_speed = testcontrols_mousespeed - mouse_threshold;
+ original_speed = (int) (original_speed / mouse_acceleration);
+ original_speed += mouse_threshold;
+ }
+
+ // Calculate line length
+
+ linelen = (original_speed * redline_x) / mouse_threshold;
+
+ // Draw horizontal "thermometer"
+
+ for (x=0; x<(MOUSE_SPEED_BOX_WIDTH - 1) * 8; ++x)
+ {
+ if (x < linelen)
+ {
+ if (x < redline_x)
+ {
+ color = COLOR_WHITE;
+ }
+ else
+ {
+ color = COLOR_YELLOW;
+ }
+ }
+ else
+ {
+ color = COLOR_BLACK;
+ }
+
+ screens[0][(box_y - 4) * SCREENWIDTH + box_x + x + 1] = color;
+ }
+
+ // Draw red line
+
+ for (y=box_y - 8; y<box_y; ++y)
+ {
+ screens[0][y * SCREENWIDTH + box_x + redline_x] = COLOR_RED;
+ }
+}
+
+int G_CmdChecksum (ticcmd_t* cmd)
+{
+ size_t i;
+ int 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
+//
+void G_BuildTiccmd (ticcmd_t* cmd)
+{
+ int i;
+ boolean strafe;
+ boolean bstrafe;
+ int speed;
+ int tspeed;
+ int forward;
+ int side;
+
+ memset(cmd, 0, sizeof(ticcmd_t));
+
+ cmd->consistancy =
+ consistancy[consoleplayer][maketic%BACKUPTICS];
+
+ strafe = gamekeydown[key_strafe] || mousebuttons[mousebstrafe]
+ || joybuttons[joybstrafe];
+
+ // fraggle: support the old "joyb_speed = 31" hack which
+ // allowed an autorun effect
+
+ speed = key_speed >= NUMKEYS
+ || joybspeed >= MAX_JOY_BUTTONS
+ || 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_strafeleft]
+ || joybuttons[joybstrafeleft]
+ || mousebuttons[mousebstrafeleft])
+ {
+ side -= sidemove[speed];
+ }
+
+ if (gamekeydown[key_straferight]
+ || joybuttons[joybstraferight]
+ || mousebuttons[mousebstraferight])
+ {
+ 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]
+ || mousebuttons[mousebuse])
+ {
+ cmd->buttons |= BT_USE;
+ // clear double clicks if hit use button
+ dclicks = 0;
+ }
+
+ // chainsaw overrides
+ for (i=0 ; i<NUMWEAPONS-1 ; i++)
+ if (gamekeydown['1'+i])
+ {
+ cmd->buttons |= BT_CHANGE;
+ cmd->buttons |= i<<BT_WEAPONSHIFT;
+ break;
+ }
+
+ // mouse
+ if (mousebuttons[mousebforward])
+ {
+ forward += forwardmove[speed];
+ }
+ if (mousebuttons[mousebbackward])
+ {
+ forward -= forwardmove[speed];
+ }
+
+ if (dclick_use)
+ {
+ // forward double click
+ if (mousebuttons[mousebforward] != dclickstate && dclicktime > 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;
+ }
+ }
+ }
+
+ // fraggle: allow disabling mouse y movement
+
+ if (!novert)
+ {
+ forward += mousey;
+ }
+
+ if (strafe)
+ side += mousex*2;
+ else
+ cmd->angleturn -= mousex*0x8;
+
+ if (mousex == 0)
+ {
+ // No movement in the previous frame
+
+ testcontrols_mousespeed = 0;
+ }
+
+ 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<<BTS_SAVESHIFT);
+ }
+
+ // low-res turning
+
+ if (lowres_turn)
+ {
+ // round angleturn to the nearest 256 boundary
+ // for recording demos with single byte values for turn
+
+ cmd->angleturn = (cmd->angleturn + 128) & 0xff00;
+ }
+}
+
+
+//
+// G_DoLoadLevel
+//
+extern gamestate_t wipegamestate;
+
+void G_DoLoadLevel (void)
+{
+ int i;
+
+ // Set the sky map.
+ // First thing, we have a dummy sky texture name,
+ // a flat. The data is in the WAD only because
+ // we look for an actual index, instead of simply
+ // setting one.
+
+ skyflatnum = R_FlatNumForName(DEH_String(SKYFLATNAME));
+
+ levelstarttic = gametic; // for time calculation
+
+ if (wipegamestate == GS_LEVEL)
+ wipegamestate = -1; // force a wipe
+
+ gamestate = GS_LEVEL;
+
+ for (i=0 ; i<MAXPLAYERS ; i++)
+ {
+ turbodetected[i] = false;
+ if (playeringame[i] && players[i].playerstate == PST_DEAD)
+ players[i].playerstate = PST_REBORN;
+ memset (players[i].frags,0,sizeof(players[i].frags));
+ }
+
+ P_SetupLevel (gameepisode, gamemap, 0, gameskill);
+ displayplayer = consoleplayer; // view the guy you are playing
+ gameaction = ga_nothing;
+ Z_CheckHeap ();
+
+ // clear cmd building stuff
+
+ memset (gamekeydown, 0, sizeof(gamekeydown));
+ joyxmove = joyymove = 0;
+ mousex = mousey = 0;
+ sendpause = sendsave = paused = false;
+ memset (mousebuttons, 0, sizeof(mousebuttons));
+ memset (joybuttons, 0, sizeof(joybuttons));
+
+ if (testcontrols)
+ {
+ players[consoleplayer].message = "Press escape to quit.";
+ }
+}
+
+
+static void SetJoyButtons(unsigned int buttons_mask)
+{
+ int i;
+
+ for (i=0; i<MAX_JOY_BUTTONS; ++i)
+ {
+ joybuttons[i] = (buttons_mask & (1 << i)) != 0;
+ }
+}
+
+//
+// G_Responder
+// Get info needed to make ticcmd_ts for the players.
+//
+boolean G_Responder (event_t* ev)
+{
+ // allow spy mode changes even during the demo
+ if (gamestate == GS_LEVEL && ev->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
+ }
+
+ if (testcontrols && ev->type == ev_mouse)
+ {
+ // If we are invoked by setup to test the controls, save the
+ // mouse speed so that we can display it on-screen.
+ // Perform a low pass filter on this so that the thermometer
+ // appears to move smoothly.
+
+ testcontrols_mousespeed = abs(ev->data2);
+ }
+
+ switch (ev->type)
+ {
+ case ev_keydown:
+ if (ev->data1 == KEY_PAUSE)
+ {
+ sendpause = true;
+ return true;
+ }
+ if (ev->data1 <NUMKEYS)
+ gamekeydown[ev->data1] = true;
+ return true; // eat key down events
+
+ case ev_keyup:
+ if (ev->data1 <NUMKEYS)
+ gamekeydown[ev->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:
+ SetJoyButtons(ev->data1);
+ 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;
+ int buf;
+ ticcmd_t* cmd;
+
+ // do player reborns if needed
+ for (i=0 ; i<MAXPLAYERS ; i++)
+ if (playeringame[i] && players[i].playerstate == PST_REBORN)
+ G_DoReborn (i);
+
+ // do things to change the game state
+ while (gameaction != ga_nothing)
+ {
+ switch (gameaction)
+ {
+ case ga_loadlevel:
+ G_DoLoadLevel ();
+ break;
+ case ga_newgame:
+ G_DoNewGame ();
+ break;
+ case ga_loadgame:
+ G_DoLoadGame ();
+ break;
+ case ga_savegame:
+ G_DoSaveGame ();
+ break;
+ case ga_playdemo:
+ G_DoPlayDemo ();
+ break;
+ case ga_completed:
+ G_DoCompleted ();
+ break;
+ case ga_victory:
+ F_StartFinale ();
+ break;
+ case ga_worlddone:
+ G_DoWorldDone ();
+ break;
+ case ga_screenshot:
+ V_ScreenShot ();
+ players[consoleplayer].message = DEH_String("screen shot");
+ gameaction = ga_nothing;
+ break;
+ case ga_nothing:
+ break;
+ }
+ }
+
+ // get commands, check consistancy,
+ // and build new consistancy check
+ buf = (gametic/ticdup)%BACKUPTICS;
+
+ for (i=0 ; i<MAXPLAYERS ; i++)
+ {
+ if (playeringame[i])
+ {
+ cmd = &players[i].cmd;
+
+ memcpy (cmd, &netcmds[i][buf], sizeof(ticcmd_t));
+
+ if (demoplayback)
+ G_ReadDemoTiccmd (cmd);
+ if (demorecording)
+ G_WriteDemoTiccmd (cmd);
+
+ // check for turbo cheats
+
+ // check ~ 4 seconds whether to display the turbo message.
+ // store if the turbo threshold was exceeded in any tics
+ // over the past 4 seconds. offset the checking period
+ // for each player so messages are not displayed at the
+ // same time.
+
+ if (cmd->forwardmove > TURBOTHRESHOLD)
+ {
+ turbodetected[i] = true;
+ }
+
+ if ((gametic & 31) == 0
+ && ((gametic >> 5) % MAXPLAYERS) == i
+ && turbodetected[i])
+ {
+ static char turbomessage[80];
+ extern char *player_names[4];
+ sprintf (turbomessage, "%s is turbo!",player_names[i]);
+ players[consoleplayer].message = turbomessage;
+ turbodetected[i] = false;
+ }
+
+ 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<MAXPLAYERS ; i++)
+ {
+ if (playeringame[i])
+ {
+ if (players[i].cmd.buttons & BT_SPECIAL)
+ {
+ switch (players[i].cmd.buttons & BT_SPECIALMASK)
+ {
+ case BTS_PAUSE:
+ paused ^= 1;
+ if (paused)
+ S_PauseSound ();
+ else
+ S_ResumeSound ();
+ break;
+
+ case BTS_SAVEGAME:
+ if (!savedescription[0])
+ strcpy (savedescription, "NET GAME");
+ savegameslot =
+ (players[i].cmd.buttons & BTS_SAVEMASK)>>BTS_SAVESHIFT;
+ gameaction = ga_savegame;
+ break;
+ }
+ }
+ }
+ }
+
+ // Have we just finished displaying an intermission screen?
+
+ if (oldgamestate == GS_INTERMISSION && gamestate != GS_INTERMISSION)
+ {
+ WI_End();
+ }
+
+ oldgamestate = gamestate;
+
+ // 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;
+ int itemcount;
+ int 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 = deh_initial_health; // Use dehacked value
+ p->readyweapon = p->pendingweapon = wp_pistol;
+ p->weaponowned[wp_fist] = true;
+ p->weaponowned[wp_pistol] = true;
+ p->ammo[am_clip] = deh_initial_bullets;
+
+ for (i=0 ; i<NUMAMMO ; i++)
+ p->maxammo[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;
+ fixed_t y;
+ subsector_t* ss;
+ unsigned an;
+ mobj_t* mo;
+ int i;
+
+ if (!players[playernum].mo)
+ {
+ // first spawn of level, before corpses
+ for (i=0 ; i<playernum ; i++)
+ if (players[i].mo->x == 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 * (((unsigned int) 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)
+ {
+ // reload the level from scratch
+ gameaction = ga_loadlevel;
+ }
+ else
+ {
+ // respawn at the start
+
+ // first dissasociate the corpse
+ players[playernum].mo->player = NULL;
+
+ // 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<MAXPLAYERS ; i++)
+ {
+ if (G_CheckSpot (playernum, &playerstarts[i]) )
+ {
+ playerstarts[i].type = playernum+1; // fake as other player
+ P_SpawnPlayer (&playerstarts[i]);
+ playerstarts[i].type = i+1; // restore
+ return;
+ }
+ // he's going to be inside something. Too bad.
+ }
+ P_SpawnPlayer (&playerstarts[playernum]);
+ }
+}
+
+
+void G_ScreenShot (void)
+{
+ gameaction = ga_screenshot;
+}
+
+
+
+// DOOM Par Times
+int pars[4][10] =
+{
+ {0},
+ {0,30,75,120,90,165,180,180,30,165},
+ {0,90,90,90,120,90,360,240,30,170},
+ {0,90,45,90,150,90,90,165,30,135}
+};
+
+// DOOM II Par Times
+int cpars[32] =
+{
+ 30,90,120,120,90,150,120,120,270,90, // 1-10
+ 210,150,150,150,210,150,420,150,210,150, // 11-20
+ 240,150,180,150,150,300,330,420,300,180, // 21-30
+ 120,30 // 31-32
+};
+
+
+//
+// G_DoCompleted
+//
+boolean secretexit;
+extern char* pagename;
+
+void G_ExitLevel (void)
+{
+ secretexit = false;
+ gameaction = ga_completed;
+}
+
+// Here's for the german edition.
+void G_SecretExitLevel (void)
+{
+ // IF NO WOLF3D LEVELS, NO SECRET EXIT!
+ if ( (gamemode == commercial)
+ && (W_CheckNumForName("map31")<0))
+ secretexit = false;
+ else
+ secretexit = true;
+ gameaction = ga_completed;
+}
+
+void G_DoCompleted (void)
+{
+ int i;
+
+ gameaction = ga_nothing;
+
+ for (i=0 ; i<MAXPLAYERS ; i++)
+ if (playeringame[i])
+ G_PlayerFinishLevel (i); // take away cards and stuff
+
+ if (automapactive)
+ AM_Stop ();
+
+ if (gamemode != commercial)
+ {
+ // Chex Quest ends after 5 levels, rather than 8.
+
+ if (gameversion == exe_chex)
+ {
+ if (gamemap == 5)
+ {
+ gameaction = ga_victory;
+ return;
+ }
+ }
+ else
+ {
+ switch(gamemap)
+ {
+ case 8:
+ gameaction = ga_victory;
+ return;
+ case 9:
+ for (i=0 ; i<MAXPLAYERS ; i++)
+ players[i].didsecret = true;
+ break;
+ }
+ }
+ }
+
+//#if 0 Hmmm - why?
+ if ( (gamemap == 8)
+ && (gamemode != commercial) )
+ {
+ // victory
+ gameaction = ga_victory;
+ return;
+ }
+
+ if ( (gamemap == 9)
+ && (gamemode != commercial) )
+ {
+ // exit secret level
+ for (i=0 ; i<MAXPLAYERS ; i++)
+ players[i].didsecret = true;
+ }
+//#endif
+
+
+ wminfo.didsecret = players[consoleplayer].didsecret;
+ wminfo.epsd = gameepisode -1;
+ wminfo.last = gamemap -1;
+
+ // wminfo.next is 0 biased, unlike gamemap
+ if ( gamemode == commercial)
+ {
+ if (secretexit)
+ switch(gamemap)
+ {
+ case 15: wminfo.next = 30; break;
+ case 31: wminfo.next = 31; break;
+ }
+ else
+ switch(gamemap)
+ {
+ case 31:
+ case 32: wminfo.next = 15; break;
+ default: wminfo.next = gamemap;
+ }
+ }
+ else
+ {
+ if (secretexit)
+ wminfo.next = 8; // go to secret level
+ else if (gamemap == 9)
+ {
+ // returning from secret level
+ switch (gameepisode)
+ {
+ case 1:
+ wminfo.next = 3;
+ break;
+ case 2:
+ wminfo.next = 5;
+ break;
+ case 3:
+ wminfo.next = 6;
+ break;
+ case 4:
+ wminfo.next = 2;
+ break;
+ }
+ }
+ else
+ wminfo.next = gamemap; // go to next level
+ }
+
+ wminfo.maxkills = totalkills;
+ wminfo.maxitems = totalitems;
+ wminfo.maxsecret = totalsecret;
+ wminfo.maxfrags = 0;
+ if ( gamemode == commercial )
+ wminfo.partime = TICRATE*cpars[gamemap-1];
+ else
+ wminfo.partime = TICRATE*pars[gameepisode][gamemap];
+ wminfo.pnum = consoleplayer;
+
+ for (i=0 ; i<MAXPLAYERS ; i++)
+ {
+ wminfo.plyr[i].in = playeringame[i];
+ wminfo.plyr[i].skills = players[i].killcount;
+ wminfo.plyr[i].sitems = players[i].itemcount;
+ wminfo.plyr[i].ssecret = players[i].secretcount;
+ wminfo.plyr[i].stime = leveltime;
+ memcpy (wminfo.plyr[i].frags, players[i].frags
+ , sizeof(wminfo.plyr[i].frags));
+ }
+
+ gamestate = GS_INTERMISSION;
+ viewactive = false;
+ automapactive = false;
+
+ WI_Start (&wminfo);
+}
+
+
+//
+// G_WorldDone
+//
+void G_WorldDone (void)
+{
+ gameaction = ga_worlddone;
+
+ if (secretexit)
+ players[consoleplayer].didsecret = true;
+
+ if ( gamemode == commercial )
+ {
+ switch (gamemap)
+ {
+ case 15:
+ case 31:
+ if (!secretexit)
+ break;
+ case 6:
+ case 11:
+ case 20:
+ case 30:
+ F_StartFinale ();
+ break;
+ }
+ }
+}
+
+void G_DoWorldDone (void)
+{
+ gamestate = GS_LEVEL;
+ gamemap = wminfo.next+1;
+ G_DoLoadLevel ();
+ gameaction = ga_nothing;
+ viewactive = true;
+}
+
+
+
+//
+// G_InitFromSavegame
+// Can be called by the startup code or the menu task.
+//
+extern boolean setsizeneeded;
+void R_ExecuteSetViewSize (void);
+
+char savename[256];
+
+void G_LoadGame (char* name)
+{
+ strcpy (savename, name);
+ gameaction = ga_loadgame;
+}
+
+#define VERSIONSIZE 16
+
+
+void G_DoLoadGame (void)
+{
+ int savedleveltime;
+
+ gameaction = ga_nothing;
+
+ save_stream = fopen(savename, "rb");
+
+ if (save_stream == NULL)
+ {
+ return;
+ }
+
+ if (!P_ReadSaveGameHeader())
+ {
+ fclose(save_stream);
+ return;
+ }
+
+ savedleveltime = leveltime;
+
+ // load a base level
+ G_InitNew (gameskill, gameepisode, gamemap);
+
+ leveltime = savedleveltime;
+
+ // dearchive all the modifications
+ P_UnArchivePlayers ();
+ P_UnArchiveWorld ();
+ P_UnArchiveThinkers ();
+ P_UnArchiveSpecials ();
+
+ if (!P_ReadSaveGameEOF())
+ I_Error ("Bad savegame");
+
+ fclose(save_stream);
+
+ if (setsizeneeded)
+ R_ExecuteSetViewSize ();
+
+ // draw the pattern into the back screen
+ R_FillBackScreen ();
+}
+
+
+//
+// G_SaveGame
+// Called by the menu task.
+// Description is a 24 byte text string
+//
+void
+G_SaveGame
+( int slot,
+ char* description )
+{
+ savegameslot = slot;
+ strcpy (savedescription, description);
+ sendsave = true;
+}
+
+void G_DoSaveGame (void)
+{
+ char *savegame_file;
+ char *temp_savegame_file;
+
+ temp_savegame_file = P_TempSaveGameFile();
+ savegame_file = P_SaveGameFile(savegameslot);
+
+ // Open the savegame file for writing. We write to a temporary file
+ // and then rename it at the end if it was successfully written.
+ // This prevents an existing savegame from being overwritten by
+ // a corrupted one, or if a savegame buffer overrun occurs.
+
+ save_stream = fopen(temp_savegame_file, "wb");
+
+ if (save_stream == NULL)
+ {
+ return;
+ }
+
+ P_WriteSaveGameHeader(savedescription);
+
+ P_ArchivePlayers ();
+ P_ArchiveWorld ();
+ P_ArchiveThinkers ();
+ P_ArchiveSpecials ();
+
+ P_WriteSaveGameEOF();
+
+ // Enforce the same savegame size limit as in Vanilla Doom,
+ // except if the vanilla_savegame_limit setting is turned off.
+
+ if (vanilla_savegame_limit && ftell(save_stream) > SAVEGAMESIZE)
+ {
+ I_Error ("Savegame buffer overrun");
+ }
+
+ // Finish up, close the savegame file.
+
+ fclose(save_stream);
+
+ // Now rename the temporary savegame file to the actual savegame
+ // file, overwriting the old savegame if there was one there.
+
+ remove(savegame_file);
+ rename(temp_savegame_file, savegame_file);
+
+ gameaction = ga_nothing;
+ strcpy(savedescription, "");
+
+ players[consoleplayer].message = DEH_String(GGSAVED);
+
+ // draw the pattern into the back screen
+ R_FillBackScreen ();
+}
+
+
+//
+// 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;
+}
+
+// The sky texture to be used instead of the F_SKY1 dummy.
+extern int skytexture;
+
+
+void
+G_InitNew
+( skill_t skill,
+ int episode,
+ int map )
+{
+ char *skytexturename;
+ int i;
+
+ if (paused)
+ {
+ paused = false;
+ S_ResumeSound ();
+ }
+
+
+ if (skill > sk_nightmare)
+ skill = sk_nightmare;
+
+
+ // This was quite messy with SPECIAL and commented parts.
+ // Supposedly hacks to make the latest edition work.
+ // It might not work properly.
+ if (episode < 1)
+ episode = 1;
+
+ if ( gamemode == retail )
+ {
+ if (episode > 4)
+ episode = 4;
+ }
+ else if ( gamemode == shareware )
+ {
+ if (episode > 1)
+ episode = 1; // only start episode 1 on shareware
+ }
+ else
+ {
+ if (episode > 3)
+ episode = 3;
+ }
+
+
+
+ if (map < 1)
+ map = 1;
+
+ if ( (map > 9)
+ && ( gamemode != 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 ; i<MAXPLAYERS ; i++)
+ players[i].playerstate = PST_REBORN;
+
+ usergame = true; // will be set false if a demo
+ paused = false;
+ demoplayback = false;
+ automapactive = false;
+ viewactive = true;
+ gameepisode = episode;
+ gamemap = map;
+ gameskill = skill;
+
+ viewactive = true;
+
+ // Set the sky to use.
+ //
+ // Note: This IS broken, but it is how Vanilla Doom behaves.
+ // See http://doom.wikia.com/wiki/Sky_never_changes_in_Doom_II.
+ //
+ // Because we set the sky here at the start of a game, not at the
+ // start of a level, the sky texture never changes unless we
+ // restore from a saved game. This was fixed before the Doom
+ // source release, but this IS the way Vanilla DOS Doom behaves.
+
+ if (gamemode == commercial)
+ {
+ if (gamemap < 12)
+ skytexturename = "SKY1";
+ else if (gamemap < 21)
+ skytexturename = "SKY2";
+ else
+ skytexturename = "SKY3";
+ }
+ else
+ {
+ switch (gameepisode)
+ {
+ default:
+ case 1:
+ skytexturename = "SKY1";
+ break;
+ case 2:
+ skytexturename = "SKY2";
+ break;
+ case 3:
+ skytexturename = "SKY3";
+ break;
+ case 4: // Special Edition sky
+ skytexturename = "SKY4";
+ break;
+ }
+ }
+
+ skytexturename = DEH_String(skytexturename);
+
+ skytexture = R_TextureNumForName(skytexturename);
+
+
+ G_DoLoadLevel ();
+}
+
+
+//
+// DEMO RECORDING
+//
+#define DEMOMARKER 0x80
+
+
+void G_ReadDemoTiccmd (ticcmd_t* cmd)
+{
+ if (*demo_p == DEMOMARKER)
+ {
+ // end of demo data stream
+ G_CheckDemoStatus ();
+ return;
+ }
+ cmd->forwardmove = ((signed char)*demo_p++);
+ cmd->sidemove = ((signed char)*demo_p++);
+
+ // If this is a longtics demo, read back in higher resolution
+
+ if (longtics)
+ {
+ cmd->angleturn = *demo_p++;
+ cmd->angleturn |= (*demo_p++) << 8;
+ }
+ else
+ {
+ cmd->angleturn = ((unsigned char) *demo_p++)<<8;
+ }
+
+ cmd->buttons = (unsigned char)*demo_p++;
+}
+
+// Increase the size of the demo buffer to allow unlimited demos
+
+static void IncreaseDemoBuffer(void)
+{
+ int current_length;
+ byte *new_demobuffer;
+ byte *new_demop;
+ int new_length;
+
+ // Find the current size
+
+ current_length = demoend - demobuffer;
+
+ // Generate a new buffer twice the size
+ new_length = current_length * 2;
+
+ new_demobuffer = Z_Malloc(new_length, PU_STATIC, 0);
+ new_demop = new_demobuffer + (demo_p - demobuffer);
+
+ // Copy over the old data
+
+ memcpy(new_demobuffer, demobuffer, current_length);
+
+ // Free the old buffer and point the demo pointers at the new buffer.
+
+ Z_Free(demobuffer);
+
+ demobuffer = new_demobuffer;
+ demo_p = new_demop;
+ demoend = demobuffer + new_length;
+}
+
+void G_WriteDemoTiccmd (ticcmd_t* cmd)
+{
+ byte *demo_start;
+
+ if (gamekeydown['q']) // press q to end demo recording
+ G_CheckDemoStatus ();
+
+ demo_start = demo_p;
+
+ *demo_p++ = cmd->forwardmove;
+ *demo_p++ = cmd->sidemove;
+
+ // If this is a longtics demo, record in higher resolution
+
+ if (longtics)
+ {
+ *demo_p++ = (cmd->angleturn & 0xff);
+ *demo_p++ = (cmd->angleturn >> 8) & 0xff;
+ }
+ else
+ {
+ *demo_p++ = cmd->angleturn >> 8;
+ }
+
+ *demo_p++ = cmd->buttons;
+
+ // reset demo pointer back
+ demo_p = demo_start;
+
+ if (demo_p > demoend - 16)
+ {
+ if (vanilla_demo_limit)
+ {
+ // no more space
+ G_CheckDemoStatus ();
+ return;
+ }
+ else
+ {
+ // Vanilla demo limit disabled: unlimited
+ // demo lengths!
+
+ IncreaseDemoBuffer();
+ }
+ }
+
+ 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;
+
+ //!
+ // @arg <size>
+ // @category demo
+ // @vanilla
+ //
+ // Specify the demo buffer size (KiB)
+ //
+
+ i = M_CheckParm ("-maxdemo");
+ if (i && i<myargc-1)
+ maxsize = atoi(myargv[i+1])*1024;
+ demobuffer = Z_Malloc (maxsize,PU_STATIC,NULL);
+ demoend = demobuffer + maxsize;
+
+ demorecording = true;
+}
+
+
+void G_BeginRecording (void)
+{
+ int i;
+
+ //!
+ // @category demo
+ //
+ // Record a high resolution "Doom 1.91" demo.
+ //
+
+ longtics = M_CheckParm("-longtics") != 0;
+
+ // If not recording a longtics demo, record in low res
+
+ lowres_turn = !longtics;
+
+ demo_p = demobuffer;
+
+ // Save the right version code for this demo
+
+ if (longtics)
+ {
+ *demo_p++ = DOOM_191_VERSION;
+ }
+ else
+ {
+ *demo_p++ = DOOM_VERSION;
+ }
+
+ *demo_p++ = gameskill;
+ *demo_p++ = gameepisode;
+ *demo_p++ = gamemap;
+ *demo_p++ = deathmatch;
+ *demo_p++ = respawnparm;
+ *demo_p++ = fastparm;
+ *demo_p++ = nomonsters;
+ *demo_p++ = consoleplayer;
+
+ for (i=0 ; i<MAXPLAYERS ; i++)
+ *demo_p++ = playeringame[i];
+}
+
+
+//
+// G_PlayDemo
+//
+
+char* defdemoname;
+
+void G_DeferedPlayDemo (char* name)
+{
+ defdemoname = name;
+ gameaction = ga_playdemo;
+}
+
+// Generate a string describing a demo version
+
+static char *DemoVersionDescription(int version)
+{
+ static char resultbuf[16];
+
+ switch (version)
+ {
+ case 104:
+ return "v1.4";
+ case 105:
+ return "v1.5";
+ case 106:
+ return "v1.6/v1.666";
+ case 107:
+ return "v1.7/v1.7a";
+ case 108:
+ return "v1.8";
+ case 109:
+ return "v1.9";
+ default:
+ break;
+ }
+
+ // Unknown version. Perhaps this is a pre-v1.4 IWAD? If the version
+ // byte is in the range 0-4 then it can be a v1.0-v1.2 demo.
+
+ if (version >= 0 && version <= 4)
+ {
+ return "v1.0/v1.1/v1.2";
+ }
+ else
+ {
+ sprintf(resultbuf, "%i.%i (unknown)", version / 100, version % 100);
+ return resultbuf;
+ }
+}
+
+void G_DoPlayDemo (void)
+{
+ skill_t skill;
+ int i, episode, map;
+ int demoversion;
+
+ gameaction = ga_nothing;
+ demobuffer = demo_p = W_CacheLumpName (defdemoname, PU_STATIC);
+
+ demoversion = *demo_p++;
+
+ if (demoversion == DOOM_VERSION)
+ {
+ longtics = false;
+ }
+ else if (demoversion == DOOM_191_VERSION)
+ {
+ // demo recorded with cph's modified "v1.91" doom exe
+ longtics = true;
+ }
+ else
+ {
+ char *message = "Demo is from a different game version!\n"
+ "(read %i, should be %i)\n"
+ "\n"
+ "*** You may need to upgrade your version "
+ "of Doom to v1.9. ***\n"
+ " See: http://doomworld.com/files/patches.shtml\n"
+ " This appears to be %s.";
+
+ I_Error(message, demoversion, DOOM_VERSION,
+ DemoVersionDescription(demoversion));
+ }
+
+ skill = *demo_p++;
+ episode = *demo_p++;
+ map = *demo_p++;
+ deathmatch = *demo_p++;
+ respawnparm = *demo_p++;
+ fastparm = *demo_p++;
+ nomonsters = *demo_p++;
+ consoleplayer = *demo_p++;
+
+ for (i=0 ; i<MAXPLAYERS ; i++)
+ playeringame[i] = *demo_p++;
+
+ //!
+ // @category demo
+ //
+ // Play back a demo recorded in a netgame with a single player.
+ //
+
+ if (playeringame[1] || M_CheckParm("-netdemo") > 0)
+ {
+ netgame = true;
+ netdemo = true;
+ }
+
+ // don't spend a lot of time in loadlevel
+ precache = false;
+ G_InitNew (skill, episode, map);
+ precache = true;
+ starttime = I_GetTime ();
+
+ usergame = false;
+ demoplayback = true;
+}
+
+//
+// G_TimeDemo
+//
+void G_TimeDemo (char* name)
+{
+ //!
+ // @vanilla
+ //
+ // Disable rendering the screen entirely.
+ //
+
+ nodrawers = M_CheckParm ("-nodraw");
+
+ //!
+ // @vanilla
+ //
+ // Disable blitting the screen.
+ //
+
+ noblit = M_CheckParm ("-noblit");
+ timingdemo = true;
+ singletics = true;
+
+ defdemoname = name;
+ gameaction = ga_playdemo;
+}
+
+
+/*
+===================
+=
+= G_CheckDemoStatus
+=
+= Called after a death or level completion to allow demos to be cleaned up
+= Returns true if a new demo loop action will take place
+===================
+*/
+
+boolean G_CheckDemoStatus (void)
+{
+ int endtime;
+
+ if (timingdemo)
+ {
+ float fps;
+ int realtics;
+
+ endtime = I_GetTime ();
+ realtics = endtime - starttime;
+ fps = ((float) gametic * TICRATE) / realtics;
+
+ // Prevent recursive calls
+ timingdemo = false;
+ demoplayback = false;
+
+ I_Error ("timed %i gametics in %i realtics (%f fps)",
+ gametic, realtics, fps);
+ }
+
+ if (demoplayback)
+ {
+ W_ReleaseLumpName(defdemoname);
+ demoplayback = false;
+ netdemo = false;
+ netgame = false;
+ deathmatch = false;
+ playeringame[1] = playeringame[2] = playeringame[3] = 0;
+ respawnparm = false;
+ fastparm = false;
+ nomonsters = false;
+ consoleplayer = 0;
+
+ if (singledemo)
+ I_Quit ();
+ else
+ D_AdvanceDemo ();
+
+ return true;
+ }
+
+ if (demorecording)
+ {
+ *demo_p++ = DEMOMARKER;
+ M_WriteFile (demoname, demobuffer, demo_p - demobuffer);
+ Z_Free (demobuffer);
+ demorecording = false;
+ I_Error ("Demo %s recorded",demoname);
+ }
+
+ return false;
+}
+
+
+
--- /dev/null
+++ b/src/doom/g_game.h
@@ -1,0 +1,84 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION:
+// Duh.
+//
+//-----------------------------------------------------------------------------
+
+
+#ifndef __G_GAME__
+#define __G_GAME__
+
+#include "doomdef.h"
+#include "d_event.h"
+#include "d_ticcmd.h"
+
+
+//
+// GAME
+//
+void G_DeathMatchSpawnPlayer (int playernum);
+
+void G_InitNew (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_DeferedInitNew (skill_t skill, int episode, int map);
+
+void G_DeferedPlayDemo (char* demo);
+
+// Can be called by the startup code or M_Responder,
+// calls P_SetupLevel or W_EnterWorld.
+void G_LoadGame (char* name);
+
+void G_DoLoadGame (void);
+
+// Called by M_Responder.
+void G_SaveGame (int slot, char* description);
+
+// Only called by startup code.
+void G_RecordDemo (char* name);
+
+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);
+
+// Read current data from inputs and build a player movement command.
+
+void G_BuildTiccmd (ticcmd_t *cmd);
+
+void G_Ticker (void);
+boolean G_Responder (event_t* ev);
+
+void G_ScreenShot (void);
+
+void G_DrawMouseSpeedBox(void);
+
+#endif
--- /dev/null
+++ b/src/doom/hu_lib.c
@@ -1,0 +1,356 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION: heads-up text and input code
+//
+//-----------------------------------------------------------------------------
+
+
+#include <ctype.h>
+
+#include "doomdef.h"
+
+#include "v_video.h"
+#include "i_swap.h"
+
+#include "hu_lib.h"
+#include "r_local.h"
+#include "r_draw.h"
+
+// boolean : whether the screen is always erased
+#define noterased viewwindowx
+
+extern boolean automapactive; // in AM_map.c
+
+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;
+ int w;
+ int x;
+ unsigned char c;
+
+ // draw the new stuff
+ x = l->x;
+ for (i=0;i<l->len;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;
+ int y;
+ int 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 ; y<l->y+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;i<h;i++)
+ HUlib_initTextLine(&s->l[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 ; i<s->h ; 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 ; i<s->h ; 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 ; i<s->h ; 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 )
+{
+ ch = toupper(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;
+}
+
--- /dev/null
+++ b/src/doom/hu_lib.h
@@ -1,0 +1,196 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION: none
+//
+//-----------------------------------------------------------------------------
+
+#ifndef __HULIB__
+#define __HULIB__
+
+// We are referring to patches.
+#include "r_defs.h"
+
+
+// background and foreground screen numbers
+// different from other modules.
+#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
+{
+ // left-justified position of scrolling text window
+ int x;
+ int y;
+
+ patch_t** f; // font
+ int sc; // start character
+ char l[HU_MAXLINELENGTH+1]; // line of text
+ int len; // current line length
+
+ // whether this line needs to be udpated
+ int needsupdate;
+
+} 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
+
+ // pointer to boolean stating whether to update window
+ boolean* on;
+ 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
+
+ // left margin past which I am not to delete characters
+ int lm;
+
+ // pointer to boolean stating whether to update window
+ boolean* on;
+ 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
+//
+
+// clear a line of text
+void HUlib_clearTextLine(hu_textline_t *t);
+
+void HUlib_initTextLine(hu_textline_t *t, int x, int y, patch_t **f, int sc);
+
+// returns success
+boolean HUlib_addCharToTextLine(hu_textline_t *t, char ch);
+
+// returns success
+boolean HUlib_delCharFromTextLine(hu_textline_t *t);
+
+// draws tline
+void HUlib_drawTextLine(hu_textline_t *l, boolean drawcursor);
+
+// erases text line
+void HUlib_eraseTextLine(hu_textline_t *l);
+
+
+//
+// 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 );
+
+// add a new line
+void HUlib_addLineToSText(hu_stext_t* s);
+
+// ?
+void
+HUlib_addMessageToSText
+( hu_stext_t* s,
+ char* prefix,
+ char* msg );
+
+// draws stext
+void HUlib_drawSText(hu_stext_t* s);
+
+// erases all stext lines
+void HUlib_eraseSText(hu_stext_t* s);
+
+// Input Text Line widget routines
+void
+HUlib_initIText
+( hu_itext_t* it,
+ int x,
+ int y,
+ patch_t** font,
+ int startchar,
+ boolean* on );
+
+// enforces left margin
+void HUlib_delCharFromIText(hu_itext_t* it);
+
+// enforces left margin
+void HUlib_eraseLineFromIText(hu_itext_t* it);
+
+// resets line and left margin
+void HUlib_resetIText(hu_itext_t* it);
+
+// left of left-margin
+void
+HUlib_addPrefixToIText
+( hu_itext_t* it,
+ char* str );
+
+// whether eaten
+boolean
+HUlib_keyInIText
+( hu_itext_t* it,
+ unsigned char ch );
+
+void HUlib_drawIText(hu_itext_t* it);
+
+// erases all itext lines
+void HUlib_eraseIText(hu_itext_t* it);
+
+#endif
--- /dev/null
+++ b/src/doom/hu_stuff.c
@@ -1,0 +1,704 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION: Heads-up displays
+//
+//-----------------------------------------------------------------------------
+
+
+#include <ctype.h>
+
+#include "doomdef.h"
+
+#include "z_zone.h"
+
+#include "deh_main.h"
+#include "i_swap.h"
+#include "i_video.h"
+
+#include "hu_stuff.h"
+#include "hu_lib.h"
+#include "w_wad.h"
+
+#include "s_sound.h"
+
+#include "doomstat.h"
+
+// Data.
+#include "dstrings.h"
+#include "sounds.h"
+
+//
+// Locally used constants, shortcuts.
+//
+#define HU_TITLE (mapnames[(gameepisode-1)*9+gamemap-1])
+#define HU_TITLE2 (mapnames2[gamemap-1])
+#define HU_TITLEP (mapnamesp[gamemap-1])
+#define HU_TITLET (mapnamest[gamemap-1])
+#define HU_TITLE_CHEX (mapnames[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
+
+
+
+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;
+
+//
+// Builtin map names.
+// The actual names can be found in DStrings.h.
+//
+
+char* mapnames[] = // DOOM shareware/registered/retail (Ultimate) names.
+{
+
+ 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,
+
+ HUSTR_E4M1,
+ HUSTR_E4M2,
+ HUSTR_E4M3,
+ HUSTR_E4M4,
+ HUSTR_E4M5,
+ HUSTR_E4M6,
+ HUSTR_E4M7,
+ HUSTR_E4M8,
+ HUSTR_E4M9,
+
+ "NEWLEVEL",
+ "NEWLEVEL",
+ "NEWLEVEL",
+ "NEWLEVEL",
+ "NEWLEVEL",
+ "NEWLEVEL",
+ "NEWLEVEL",
+ "NEWLEVEL",
+ "NEWLEVEL"
+};
+
+char* mapnames2[] = // DOOM 2 map names.
+{
+ 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* mapnamesp[] = // Plutonia WAD map names.
+{
+ PHUSTR_1,
+ PHUSTR_2,
+ PHUSTR_3,
+ PHUSTR_4,
+ PHUSTR_5,
+ PHUSTR_6,
+ PHUSTR_7,
+ PHUSTR_8,
+ PHUSTR_9,
+ PHUSTR_10,
+ PHUSTR_11,
+
+ PHUSTR_12,
+ PHUSTR_13,
+ PHUSTR_14,
+ PHUSTR_15,
+ PHUSTR_16,
+ PHUSTR_17,
+ PHUSTR_18,
+ PHUSTR_19,
+ PHUSTR_20,
+
+ PHUSTR_21,
+ PHUSTR_22,
+ PHUSTR_23,
+ PHUSTR_24,
+ PHUSTR_25,
+ PHUSTR_26,
+ PHUSTR_27,
+ PHUSTR_28,
+ PHUSTR_29,
+ PHUSTR_30,
+ PHUSTR_31,
+ PHUSTR_32
+};
+
+
+char *mapnamest[] = // TNT WAD map names.
+{
+ THUSTR_1,
+ THUSTR_2,
+ THUSTR_3,
+ THUSTR_4,
+ THUSTR_5,
+ THUSTR_6,
+ THUSTR_7,
+ THUSTR_8,
+ THUSTR_9,
+ THUSTR_10,
+ THUSTR_11,
+
+ THUSTR_12,
+ THUSTR_13,
+ THUSTR_14,
+ THUSTR_15,
+ THUSTR_16,
+ THUSTR_17,
+ THUSTR_18,
+ THUSTR_19,
+ THUSTR_20,
+
+ THUSTR_21,
+ THUSTR_22,
+ THUSTR_23,
+ THUSTR_24,
+ THUSTR_25,
+ THUSTR_26,
+ THUSTR_27,
+ THUSTR_28,
+ THUSTR_29,
+ THUSTR_30,
+ THUSTR_31,
+ THUSTR_32
+};
+
+static const char 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
+};
+
+
+void HU_Init(void)
+{
+
+ int i;
+ int j;
+ char buffer[9];
+
+ // load the heads-up font
+ j = HU_FONTSTART;
+ for (i=0;i<HU_FONTSIZE;i++)
+ {
+ sprintf(buffer, DEH_String("STCFN%.3d"), j++);
+ hu_font[i] = (patch_t *) W_CacheLumpName(buffer, PU_STATIC);
+ }
+
+}
+
+void HU_Stop(void)
+{
+ headsupactive = false;
+}
+
+void HU_Start(void)
+{
+
+ int i;
+ char* s;
+
+ if (headsupactive)
+ HU_Stop();
+
+ plr = &players[consoleplayer];
+ message_on = false;
+ message_dontfuckwithme = false;
+ message_nottobefuckedwith = false;
+ chat_on = false;
+
+ // create the message widget
+ HUlib_initSText(&w_message,
+ HU_MSGX, HU_MSGY, HU_MSGHEIGHT,
+ hu_font,
+ HU_FONTSTART, &message_on);
+
+ // create the map title widget
+ HUlib_initTextLine(&w_title,
+ HU_TITLEX, HU_TITLEY,
+ hu_font,
+ HU_FONTSTART);
+
+ switch ( gamemission )
+ {
+ case doom:
+ s = HU_TITLE;
+ break;
+ case doom2:
+ s = HU_TITLE2;
+ break;
+ case pack_plut:
+ s = HU_TITLEP;
+ break;
+ case pack_tnt:
+ s = HU_TITLET;
+ break;
+ default:
+ s = "Unknown level";
+ break;
+ }
+
+ // Chex.exe always uses the episode 1 level title
+ // eg. E2M1 gives the title for E1M1
+
+ if (gameversion == exe_chex)
+ {
+ s = HU_TITLE_CHEX;
+ }
+
+ // dehacked substitution to get modified level name
+
+ s = DEH_String(s);
+
+ while (*s)
+ HUlib_addCharToTextLine(&w_title, *(s++));
+
+ // create the chat widget
+ HUlib_initIText(&w_chat,
+ HU_INPUTX, HU_INPUTY,
+ hu_font,
+ HU_FONTSTART, &chat_on);
+
+ // create the inputbuffer widgets
+ for (i=0 ; i<MAXPLAYERS ; i++)
+ HUlib_initIText(&w_inputbuffer[i], 0, 0, 0, 0, &always_off);
+
+ headsupactive = true;
+
+}
+
+void HU_Drawer(void)
+{
+
+ HUlib_drawSText(&w_message);
+ HUlib_drawIText(&w_chat);
+ if (automapactive)
+ HUlib_drawTextLine(&w_title, false);
+
+}
+
+void HU_Erase(void)
+{
+
+ HUlib_eraseSText(&w_message);
+ HUlib_eraseIText(&w_chat);
+ HUlib_eraseTextLine(&w_title);
+
+}
+
+void HU_Ticker(void)
+{
+
+ int i, rc;
+ char c;
+
+ // tick down message counter if message is up
+ if (message_counter && !--message_counter)
+ {
+ message_on = false;
+ message_nottobefuckedwith = false;
+ }
+
+ if (showMessages || message_dontfuckwithme)
+ {
+
+ // display message if necessary
+ if ((plr->message && !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<MAXPLAYERS; i++)
+ {
+ if (!playeringame[i])
+ continue;
+ if (i != consoleplayer
+ && (c = players[i].cmd.chatchar))
+ {
+ if (c <= HU_BROADCAST)
+ chat_dest[i] = c;
+ else
+ {
+ 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,
+ DEH_String(player_names[i]),
+ w_inputbuffer[i].l.l);
+
+ message_nottobefuckedwith = true;
+ message_on = true;
+ message_counter = HU_MSGTIMEOUT;
+ if ( gamemode == commercial )
+ S_StartSound(0, sfx_radio);
+ else
+ 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;
+static int tail = 0;
+
+
+void HU_queueChatChar(char c)
+{
+ if (((head + 1) & (QUEUESIZE-1)) == tail)
+ {
+ plr->message = DEH_String(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;
+ int numplayers;
+
+ static char destination_keys[MAXPLAYERS] =
+ {
+ HUSTR_KEYGREEN,
+ HUSTR_KEYINDIGO,
+ HUSTR_KEYBROWN,
+ HUSTR_KEYRED
+ };
+
+ static int num_nobrainers = 0;
+
+ numplayers = 0;
+ for (i=0 ; i<MAXPLAYERS ; i++)
+ numplayers += playeringame[i];
+
+ if (ev->data1 == 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->data2 == HU_INPUTTOGGLE)
+ {
+ eatkey = chat_on = true;
+ HUlib_resetIText(&w_chat);
+ HU_queueChatChar(HU_BROADCAST);
+ }
+ else if (netgame && numplayers > 2)
+ {
+ for (i=0; i<MAXPLAYERS ; i++)
+ {
+ if (ev->data2 == 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 = DEH_String(HUSTR_TALKTOSELF1);
+ else if (num_nobrainers < 6)
+ plr->message = DEH_String(HUSTR_TALKTOSELF2);
+ else if (num_nobrainers < 9)
+ plr->message = DEH_String(HUSTR_TALKTOSELF3);
+ else if (num_nobrainers < 32)
+ plr->message = DEH_String(HUSTR_TALKTOSELF4);
+ else
+ plr->message = DEH_String(HUSTR_TALKTOSELF5);
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ c = ev->data2;
+ // 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 (vanilla_keyboard_mapping)
+ {
+ 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;
+
+}
--- /dev/null
+++ b/src/doom/hu_stuff.h
@@ -1,0 +1,66 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION: Head up display
+//
+//-----------------------------------------------------------------------------
+
+#ifndef __HU_STUFF_H__
+#define __HU_STUFF_H__
+
+#include "d_event.h"
+
+
+//
+// Globally visible constants.
+//
+#define HU_FONTSTART '!' // the first font characters
+#define HU_FONTEND '_' // the last font characters
+
+// Calculate # of glyphs in font.
+#define HU_FONTSIZE (HU_FONTEND - HU_FONTSTART + 1)
+
+#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)
+
+//
+// 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);
+
+
+#endif
--- /dev/null
+++ b/src/doom/info.c
@@ -1,0 +1,4670 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION:
+// Thing frame/state LUT,
+// generated by multigen utilitiy.
+// This one is the original DOOM version, preserved.
+//
+//-----------------------------------------------------------------------------
+
+
+#include <stdlib.h>
+
+// Data.
+#include "sounds.h"
+#include "m_fixed.h"
+
+#include "info.h"
+
+#include "p_mobj.h"
+
+char *sprnames[] = {
+ "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", NULL
+};
+
+
+// Doesn't work with g++, needs actionf_p1
+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
+ }
+};
+
--- /dev/null
+++ b/src/doom/info.h
@@ -1,0 +1,1339 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION:
+// Thing frame/state LUT,
+// generated by multigen utilitiy.
+// This one is the original DOOM version, preserved.
+//
+//-----------------------------------------------------------------------------
+
+#ifndef __INFO__
+#define __INFO__
+
+// Needed for action function pointer handling.
+#include "d_think.h"
+
+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;
+ int frame;
+ int tics;
+ // void (*action) ();
+ actionf_t action;
+ statenum_t nextstate;
+ int misc1;
+ int misc2;
+} state_t;
+
+extern state_t states[NUMSTATES];
+extern char *sprnames[];
+
+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];
+
+#endif
--- /dev/null
+++ b/src/doom/m_menu.c
@@ -1,0 +1,1975 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION:
+// DOOM selection menu, options, episode etc.
+// Sliders and icons. Kinda widget stuff.
+//
+//-----------------------------------------------------------------------------
+
+
+#include <stdlib.h>
+#include <ctype.h>
+
+
+#include "doomdef.h"
+#include "dstrings.h"
+
+#include "d_main.h"
+#include "deh_main.h"
+
+#include "i_swap.h"
+#include "i_system.h"
+#include "i_timer.h"
+#include "i_video.h"
+#include "z_zone.h"
+#include "v_video.h"
+#include "w_wad.h"
+
+#include "r_local.h"
+
+
+#include "hu_stuff.h"
+
+#include "g_game.h"
+
+#include "m_argv.h"
+#include "p_saveg.h"
+
+#include "s_sound.h"
+
+#include "doomstat.h"
+
+// Data.
+#include "sounds.h"
+
+#include "m_menu.h"
+
+
+extern void M_QuitDOOM(int);
+
+extern patch_t* hu_font[HU_FONTSIZE];
+extern boolean message_dontfuckwithme;
+
+extern boolean chat_on; // in heads-up code
+
+//
+// defaulted values
+//
+int mouseSensitivity = 5;
+
+// Show messages has default, 0 = off, 1 = on
+int showMessages = 1;
+
+
+// Blocky mode, has default, 0 = high, 1 = normal
+int detailLevel = 0;
+int screenblocks = 9;
+
+// temp for screenblocks (0-9)
+int screenSize;
+
+// -1 = no quicksave slot picked!
+int quickSaveSlot;
+
+ // 1 = message to be printed
+int messageToPrint;
+// ...and here is the message string!
+char* messageString;
+
+// message x & y
+int messx;
+int messy;
+int messageLastMenuActive;
+
+// timed message = no input from user
+boolean messageNeedsInput;
+
+void (*messageRoutine)(int response);
+
+char gammamsg[5][26] =
+{
+ GAMMALVL0,
+ GAMMALVL1,
+ GAMMALVL2,
+ GAMMALVL3,
+ GAMMALVL4
+};
+
+// we are going to be entering a savegame string
+int saveStringEnter;
+int saveSlot; // which slot to save in
+int saveCharIndex; // which char we're editing
+// old save description before edit
+char saveOldString[SAVESTRINGSIZE];
+
+boolean inhelpscreens;
+boolean menuactive;
+
+#define SKULLXOFF -32
+#define LINEHEIGHT 16
+
+extern boolean sendpause;
+char savegamestrings[10][SAVESTRINGSIZE];
+
+char endstring[160];
+
+
+//
+// MENU TYPEDEFS
+//
+typedef struct
+{
+ // 0 = no cursor here, 1 = ok, 2 = arrows ok
+ short status;
+
+ char name[10];
+
+ // choice = menu item #.
+ // if status = 2,
+ // choice=0:leftarrow,1:rightarrow
+ void (*routine)(int choice);
+
+ // hotkey in menu
+ char alphaKey;
+} 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;
+ short 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
+
+// graphic name of skulls
+// warning: initializer-string for array of chars is too long
+char *skullName[2] = {"M_SKULL1","M_SKULL2"};
+
+// current menudef
+menu_t* currentMenu;
+
+//
+// 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_ReadThis2(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_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'},
+ // Another hickup with Special edition.
+ {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,
+ ep4,
+ 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'},
+ {1,"M_EPI4", M_Episode,'t'}
+};
+
+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,'\0'},
+ {2,"M_MSENS", M_ChangeSensitivity,'m'},
+ {-1,"",0,'\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,'\0'},
+ {2,"M_MUSVOL",M_MusicVol,'m'},
+ {-1,"",0,'\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)
+{
+ FILE *handle;
+ int count;
+ int i;
+ char name[256];
+
+ for (i = 0;i < load_end;i++)
+ {
+ strcpy(name, P_SaveGameFile(i));
+
+ handle = fopen(name, "rb");
+ if (handle == NULL)
+ {
+ strcpy(&savegamestrings[i][0], EMPTYSTRING);
+ LoadMenu[i].status = 0;
+ continue;
+ }
+ count = fread(&savegamestrings[i], 1, SAVESTRINGSIZE, handle);
+ fclose(handle);
+ LoadMenu[i].status = 1;
+ }
+}
+
+
+//
+// M_LoadGame & Cie.
+//
+void M_DrawLoad(void)
+{
+ int i;
+
+ V_DrawPatchDirect (72,28,0,W_CacheLumpName(DEH_String("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(DEH_String("M_LSLEFT"),PU_CACHE));
+
+ for (i = 0;i < 24;i++)
+ {
+ V_DrawPatchDirect (x,y+7,0,W_CacheLumpName(DEH_String("M_LSCNTR"),PU_CACHE));
+ x += 8;
+ }
+
+ V_DrawPatchDirect (x,y+7,0,W_CacheLumpName(DEH_String("M_LSRGHT"),PU_CACHE));
+}
+
+
+
+//
+// User wants to load this game
+//
+void M_LoadSelect(int choice)
+{
+ char name[256];
+
+ strcpy(name, P_SaveGameFile(choice));
+
+ G_LoadGame (name);
+ M_ClearMenus ();
+}
+
+//
+// Selected from DOOM menu
+//
+void M_LoadGame (int choice)
+{
+ if (netgame)
+ {
+ M_StartMessage(DEH_String(LOADNET),NULL,false);
+ return;
+ }
+
+ M_SetupNextMenu(&LoadDef);
+ M_ReadSaveStrings();
+}
+
+
+//
+// M_SaveGame & Cie.
+//
+void M_DrawSave(void)
+{
+ int i;
+
+ V_DrawPatchDirect (72,28,0,W_CacheLumpName(DEH_String("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)
+{
+ // we are going to be intercepting all chars
+ saveStringEnter = 1;
+
+ 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(DEH_String(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,DEH_String(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(DEH_String(QLOADNET),NULL,false);
+ return;
+ }
+
+ if (quickSaveSlot < 0)
+ {
+ M_StartMessage(DEH_String(QSAVESPOT),NULL,false);
+ return;
+ }
+ sprintf(tempstring,DEH_String(QLPROMPT),savegamestrings[quickSaveSlot]);
+ M_StartMessage(tempstring,M_QuickLoadResponse,true);
+}
+
+
+
+
+//
+// Read This Menus
+// Had a "quick hack to fix romero bug"
+//
+void M_DrawReadThis1(void)
+{
+ char *lumpname = "CREDIT";
+ int skullx = 330, skully = 175;
+
+ inhelpscreens = true;
+
+ // Different versions of Doom 1.9 work differently
+
+ switch (gameversion)
+ {
+ case exe_doom_1_9:
+ if (gamemode == commercial)
+ {
+ // Doom 2
+
+ lumpname = "HELP";
+
+ skullx = 330;
+ skully = 165;
+ }
+ else
+ {
+ // Doom 1
+ // HELP2 is the first screen shown in Doom 1
+
+ lumpname = "HELP2";
+
+ skullx = 280;
+ skully = 185;
+ }
+ break;
+
+ case exe_ultimate:
+ case exe_chex:
+
+ // Ultimate Doom always displays "HELP1".
+
+ // Chex Quest version also uses "HELP1", even though it is based
+ // on Final Doom.
+
+ lumpname = "HELP1";
+
+ break;
+
+ case exe_final:
+
+ // Final Doom always displays "HELP".
+
+ lumpname = "HELP";
+
+ break;
+ }
+
+ lumpname = DEH_String(lumpname);
+
+ V_DrawPatchDirect (0, 0, 0, W_CacheLumpName(lumpname, PU_CACHE));
+
+ ReadDef1.x = skullx;
+ ReadDef1.y = skully;
+}
+
+
+
+//
+// Read This Menus - optional second page.
+//
+void M_DrawReadThis2(void)
+{
+ inhelpscreens = true;
+
+ // We only ever draw the second page if this is
+ // gameversion == exe_doom_1_9 and gamemode == registered
+
+ V_DrawPatchDirect(0, 0, 0, W_CacheLumpName(DEH_String("HELP1"), PU_CACHE));
+}
+
+
+//
+// Change Sfx & Music volumes
+//
+void M_DrawSound(void)
+{
+ V_DrawPatchDirect (60,38,0,W_CacheLumpName(DEH_String("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(DEH_String("M_DOOM"),PU_CACHE));
+}
+
+
+
+
+//
+// M_NewGame
+//
+void M_DrawNewGame(void)
+{
+ V_DrawPatchDirect (96,14,0,W_CacheLumpName(DEH_String("M_NEWG"),PU_CACHE));
+ V_DrawPatchDirect (54,38,0,W_CacheLumpName(DEH_String("M_SKILL"),PU_CACHE));
+}
+
+void M_NewGame(int choice)
+{
+ if (netgame && !demoplayback)
+ {
+ M_StartMessage(DEH_String(NEWGAME),NULL,false);
+ return;
+ }
+
+ // Chex Quest disabled the episode select screen, as did Doom II.
+
+ if (gamemode == commercial || gameversion == exe_chex)
+ M_SetupNextMenu(&NewDef);
+ else
+ M_SetupNextMenu(&EpiDef);
+}
+
+
+//
+// M_Episode
+//
+int epi;
+
+void M_DrawEpisode(void)
+{
+ V_DrawPatchDirect (54,38,0,W_CacheLumpName(DEH_String("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(DEH_String(NIGHTMARE),M_VerifyNightmare,true);
+ return;
+ }
+
+ G_DeferedInitNew(choice,epi+1,1);
+ M_ClearMenus ();
+}
+
+void M_Episode(int choice)
+{
+ if ( (gamemode == shareware)
+ && choice)
+ {
+ M_StartMessage(DEH_String(SWSTRING),NULL,false);
+ M_SetupNextMenu(&ReadDef1);
+ return;
+ }
+
+ // Yet another hack...
+ if ( (gamemode == registered)
+ && (choice > 2))
+ {
+ fprintf( stderr,
+ "M_Episode: 4th episode requires UltimateDOOM\n");
+ choice = 0;
+ }
+
+ 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(DEH_String("M_OPTTTL"),PU_CACHE));
+
+ V_DrawPatchDirect (OptionsDef.x + 175,OptionsDef.y+LINEHEIGHT*detail,0,
+ W_CacheLumpName(DEH_String(detailNames[detailLevel]),
+ PU_CACHE));
+
+ V_DrawPatchDirect (OptionsDef.x + 120,OptionsDef.y+LINEHEIGHT*messages,0,
+ W_CacheLumpName(DEH_String(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)
+{
+ // warning: unused parameter `int choice'
+ choice = 0;
+ showMessages = 1 - showMessages;
+
+ if (!showMessages)
+ players[consoleplayer].message = DEH_String(MSGOFF);
+ else
+ players[consoleplayer].message = DEH_String(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)
+{
+ choice = 0;
+ if (!usergame)
+ {
+ S_StartSound(NULL,sfx_oof);
+ return;
+ }
+
+ if (netgame)
+ {
+ M_StartMessage(DEH_String(NETEND),NULL,false);
+ return;
+ }
+
+ M_StartMessage(DEH_String(ENDGAME),M_EndGameResponse,true);
+}
+
+
+
+
+//
+// M_ReadThis
+//
+void M_ReadThis(int choice)
+{
+ choice = 0;
+ M_SetupNextMenu(&ReadDef1);
+}
+
+void M_ReadThis2(int choice)
+{
+ // Doom 1.9 had two menus when playing Doom 1
+ // All others had only one
+
+ if (gameversion == exe_doom_1_9 && gamemode != commercial)
+ {
+ choice = 0;
+ M_SetupNextMenu(&ReadDef2);
+ }
+ else
+ {
+ // Close the menu
+
+ M_FinishReadThis(0);
+ }
+}
+
+void M_FinishReadThis(int choice)
+{
+ choice = 0;
+ 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 (gamemode == commercial)
+ S_StartSound(NULL,quitsounds2[(gametic>>2)&7]);
+ else
+ S_StartSound(NULL,quitsounds[(gametic>>2)&7]);
+ I_WaitVBL(105);
+ }
+ I_Quit ();
+}
+
+
+static char *M_SelectEndMessage(void)
+{
+ char **endmsg;
+
+ if (gamemission == doom)
+ {
+ // Doom 1
+
+ endmsg = doom1_endmsg;
+ }
+ else
+ {
+ // Doom 2
+
+ endmsg = doom2_endmsg;
+ }
+
+ return endmsg[gametic % NUM_QUITMESSAGES];
+}
+
+
+void M_QuitDOOM(int choice)
+{
+ sprintf(endstring,
+ DEH_String("%s\n\n" DOSY),
+ DEH_String(M_SelectEndMessage()));
+
+ 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)
+{
+ choice = 0;
+ detailLevel = 1 - detailLevel;
+
+ R_SetViewSize (screenblocks, detailLevel);
+
+ if (!detailLevel)
+ players[consoleplayer].message = DEH_String(DETAILHI);
+ else
+ players[consoleplayer].message = DEH_String(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;
+ int i;
+
+ xx = x;
+ V_DrawPatchDirect (xx,y,0,W_CacheLumpName(DEH_String("M_THERML"),PU_CACHE));
+ xx += 8;
+ for (i=0;i<thermWidth;i++)
+ {
+ V_DrawPatchDirect (xx,y,0,W_CacheLumpName(DEH_String("M_THERMM"),PU_CACHE));
+ xx += 8;
+ }
+ V_DrawPatchDirect (xx,y,0,W_CacheLumpName(DEH_String("M_THERMR"),PU_CACHE));
+
+ V_DrawPatchDirect ((x+8) + thermDot*8,y,
+ 0,W_CacheLumpName(DEH_String("M_THERMO"),PU_CACHE));
+}
+
+
+
+void
+M_DrawEmptyCell
+( menu_t* menu,
+ int item )
+{
+ V_DrawPatchDirect (menu->x - 10, menu->y+item*LINEHEIGHT - 1, 0,
+ W_CacheLumpName(DEH_String("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(DEH_String("M_CELL2"),PU_CACHE));
+}
+
+
+void
+M_StartMessage
+( char* string,
+ void* routine,
+ boolean input )
+{
+ messageLastMenuActive = menuactive;
+ 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)
+{
+ size_t 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)
+{
+ size_t 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 key;
+ 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;
+
+ // key is the key pressed, ch is the actual character typed
+
+ ch = 0;
+ key = -1;
+
+ if (ev->type == ev_joystick && joywait < I_GetTime())
+ {
+ if (ev->data3 == -1)
+ {
+ key = KEY_UPARROW;
+ joywait = I_GetTime() + 5;
+ }
+ else if (ev->data3 == 1)
+ {
+ key = KEY_DOWNARROW;
+ joywait = I_GetTime() + 5;
+ }
+
+ if (ev->data2 == -1)
+ {
+ key = KEY_LEFTARROW;
+ joywait = I_GetTime() + 2;
+ }
+ else if (ev->data2 == 1)
+ {
+ key = KEY_RIGHTARROW;
+ joywait = I_GetTime() + 2;
+ }
+
+ if (ev->data1&1)
+ {
+ key = KEY_ENTER;
+ joywait = I_GetTime() + 5;
+ }
+ if (ev->data1&2)
+ {
+ key = KEY_BACKSPACE;
+ joywait = I_GetTime() + 5;
+ }
+ }
+ else
+ {
+ if (ev->type == ev_mouse && mousewait < I_GetTime())
+ {
+ mousey += ev->data3;
+ if (mousey < lasty-30)
+ {
+ key = KEY_DOWNARROW;
+ mousewait = I_GetTime() + 5;
+ mousey = lasty -= 30;
+ }
+ else if (mousey > lasty+30)
+ {
+ key = KEY_UPARROW;
+ mousewait = I_GetTime() + 5;
+ mousey = lasty += 30;
+ }
+
+ mousex += ev->data2;
+ if (mousex < lastx-30)
+ {
+ key = KEY_LEFTARROW;
+ mousewait = I_GetTime() + 5;
+ mousex = lastx -= 30;
+ }
+ else if (mousex > lastx+30)
+ {
+ key = KEY_RIGHTARROW;
+ mousewait = I_GetTime() + 5;
+ mousex = lastx += 30;
+ }
+
+ if (ev->data1&1)
+ {
+ key = KEY_ENTER;
+ mousewait = I_GetTime() + 15;
+ }
+
+ if (ev->data1&2)
+ {
+ key = KEY_BACKSPACE;
+ mousewait = I_GetTime() + 15;
+ }
+ }
+ else
+ {
+ if (ev->type == ev_keydown)
+ {
+ key = ev->data1;
+ ch = ev->data2;
+ }
+ }
+ }
+
+ if (key == -1)
+ return false;
+
+ // In testcontrols mode, none of the function keys should do anything
+ // - the only key is escape to quit.
+
+ if (testcontrols)
+ {
+ if (key == KEY_ESCAPE || key == KEY_F10)
+ {
+ I_Quit();
+ return true;
+ }
+
+ return false;
+ }
+
+ // Save Game string input
+ if (saveStringEnter)
+ {
+ switch(key)
+ {
+ 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:
+ // Entering a character - use the 'ch' value, not the key
+
+ ch = toupper(ch);
+
+ if (ch != ' '
+ && (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' || key == KEY_ESCAPE))
+ return false;
+
+ menuactive = messageLastMenuActive;
+ messageToPrint = 0;
+ if (messageRoutine)
+ messageRoutine(ch);
+
+ menuactive = false;
+ S_StartSound(NULL,sfx_swtchx);
+ return true;
+ }
+
+ if (devparm && key == KEY_F1)
+ {
+ G_ScreenShot ();
+ return true;
+ }
+
+
+ // F-Keys
+ if (!menuactive)
+ switch(key)
+ {
+ 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 ();
+
+ if ( gamemode == retail )
+ currentMenu = &ReadDef2;
+ else
+ 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 = DEH_String(gammamsg[usegamma]);
+ I_SetPalette (W_CacheLumpName (DEH_String("PLAYPAL"),PU_CACHE));
+ return true;
+
+ }
+
+
+ // Pop-up menu?
+ if (!menuactive)
+ {
+ if (key == KEY_ESCAPE)
+ {
+ M_StartControlPanel ();
+ S_StartSound(NULL,sfx_swtchn);
+ return true;
+ }
+ return false;
+ }
+
+
+ // Keys usable within menu
+ switch (key)
+ {
+ 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)
+{
+ // intro might call this repeatedly
+ if (menuactive)
+ return;
+
+ 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;
+ static short y;
+ unsigned int i;
+ unsigned int max;
+ char string[80];
+ char *name;
+ int start;
+
+ inhelpscreens = false;
+
+ // Horiz. & Vertically center string and print it.
+ if (messageToPrint)
+ {
+ start = 0;
+ y = 100 - M_StringHeight(messageString) / 2;
+ while (messageString[start] != '\0')
+ {
+ int foundnewline = 0;
+
+ for (i = 0; i < strlen(messageString + start); i++)
+ if (messageString[start + i] == '\n')
+ {
+ memset(string, 0, sizeof(string));
+ strncpy(string, messageString + start, i);
+ foundnewline = 1;
+ start += i + 1;
+ break;
+ }
+
+ if (!foundnewline)
+ {
+ strcpy(string, messageString + start);
+ start += strlen(string);
+ }
+
+ 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;i<max;i++)
+ {
+ name = DEH_String(currentMenu->menuitems[i].name);
+
+ if (name[0])
+ {
+ V_DrawPatchDirect (x,y,0, W_CacheLumpName(name, PU_CACHE));
+ }
+ y += LINEHEIGHT;
+ }
+
+
+ // DRAW SKULL
+ V_DrawPatchDirect(x + SKULLXOFF,currentMenu->y - 5 + itemOn*LINEHEIGHT, 0,
+ W_CacheLumpName(DEH_String(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;
+
+ // Here we could catch other version dependencies,
+ // like HELP1/2, and four episodes.
+
+
+ switch ( gamemode )
+ {
+ case commercial:
+ // Commercial has no "read this" entry.
+ MainMenu[readthis] = MainMenu[quitdoom];
+ MainDef.numitems--;
+ MainDef.y += 8;
+ NewDef.prevMenu = &MainDef;
+ break;
+ case shareware:
+ // Episode 2 and 3 are handled,
+ // branching to an ad screen.
+ case registered:
+ // We need to remove the fourth episode.
+ EpiDef.numitems--;
+ break;
+ case retail:
+ // We are fine.
+ default:
+ break;
+ }
+
+}
+
--- /dev/null
+++ b/src/doom/m_menu.h
@@ -1,0 +1,69 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION:
+// Menu widget stuff, episode selection and such.
+//
+//-----------------------------------------------------------------------------
+
+
+#ifndef __M_MENU__
+#define __M_MENU__
+
+
+
+#include "d_event.h"
+
+//
+// MENUS
+//
+// 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.
+boolean M_Responder (event_t *ev);
+
+
+// Called by main loop,
+// only used for menu (skull cursor) animation.
+void M_Ticker (void);
+
+// Called by main loop,
+// draws the menus directly into the screen buffer.
+void M_Drawer (void);
+
+// Called by D_DoomMain,
+// loads the config file.
+void M_Init (void);
+
+// Called by intro code to force menu up upon a keypress,
+// does nothing if menu is already up.
+void M_StartControlPanel (void);
+
+
+
+extern int detailLevel;
+extern int screenblocks;
+
+
+
+#endif
--- /dev/null
+++ b/src/doom/p_ceilng.c
@@ -1,0 +1,332 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION: Ceiling aninmation (lowering, crushing, raising)
+//
+//-----------------------------------------------------------------------------
+
+
+
+#include "z_zone.h"
+#include "doomdef.h"
+#include "p_local.h"
+
+#include "s_sound.h"
+
+// State.
+#include "doomstat.h"
+#include "r_state.h"
+
+// Data.
+#include "sounds.h"
+
+//
+// CEILINGS
+//
+
+
+ceiling_t* activeceilings[MAXCEILINGS];
+
+
+//
+// T_MoveCeiling
+//
+
+void T_MoveCeiling (ceiling_t* ceiling)
+{
+ result_e res;
+
+ switch(ceiling->direction)
+ {
+ 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(&ceiling->sector->soundorg, sfx_stnmov);
+ // ?
+ break;
+ }
+ }
+
+ if (res == pastdest)
+ {
+ switch(ceiling->type)
+ {
+ case raiseToHighest:
+ P_RemoveActiveCeiling(ceiling);
+ break;
+
+ case silentCrushAndRaise:
+ S_StartSound(&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(&ceiling->sector->soundorg, sfx_stnmov);
+ }
+ }
+
+ if (res == pastdest)
+ {
+ switch(ceiling->type)
+ {
+ case silentCrushAndRaise:
+ S_StartSound(&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 // ( res != pastdest )
+ {
+ 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;
+ int 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.acp1 = (actionf_p1)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.acp1
+ = (actionf_p1)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.acv = (actionf_v)NULL;
+ activeceilings[i]->direction = 0; // in-stasis
+ rtn = 1;
+ }
+ }
+
+
+ return rtn;
+}
--- /dev/null
+++ b/src/doom/p_doors.c
@@ -1,0 +1,755 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION: Door animation code (opening/closing)
+//
+//-----------------------------------------------------------------------------
+
+
+
+#include "z_zone.h"
+#include "doomdef.h"
+#include "deh_main.h"
+#include "p_local.h"
+
+#include "s_sound.h"
+
+
+// State.
+#include "doomstat.h"
+#include "r_state.h"
+
+// Data.
+#include "dstrings.h"
+#include "sounds.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(&door->sector->soundorg, sfx_bdcls);
+ break;
+
+ case normal:
+ door->direction = -1; // time to go back down
+ S_StartSound(&door->sector->soundorg, sfx_dorcls);
+ break;
+
+ case close30ThenOpen:
+ door->direction = 1;
+ S_StartSound(&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(&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(&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 = TICRATE*30;
+ break;
+
+ default:
+ break;
+ }
+ }
+ else if (res == crushed)
+ {
+ switch(door->type)
+ {
+ case blazeClose:
+ case close: // DO NOT GO BACK UP!
+ break;
+
+ default:
+ door->direction = 1;
+ S_StartSound(&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 = DEH_String(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 = DEH_String(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 = DEH_String(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.acp1 = (actionf_p1) 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(&door->sector->soundorg, sfx_bdcls);
+ break;
+
+ case close:
+ door->topheight = P_FindLowestCeilingSurrounding(sec);
+ door->topheight -= 4*FRACUNIT;
+ door->direction = -1;
+ S_StartSound(&door->sector->soundorg, sfx_dorcls);
+ break;
+
+ case close30ThenOpen:
+ door->topheight = sec->ceilingheight;
+ door->direction = -1;
+ S_StartSound(&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(&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(&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 = DEH_String(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 = DEH_String(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 = DEH_String(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(&sec->soundorg,sfx_bdopn);
+ break;
+
+ case 1: // NORMAL DOOR SOUND
+ case 31:
+ S_StartSound(&sec->soundorg,sfx_doropn);
+ break;
+
+ default: // LOCKED DOOR SOUND
+ S_StartSound(&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.acp1 = (actionf_p1) 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.acp1 = (actionf_p1)T_VerticalDoor;
+ door->sector = sec;
+ door->direction = 0;
+ door->type = normal;
+ door->speed = VDOORSPEED;
+ door->topcountdown = 30 * TICRATE;
+}
+
+//
+// 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.acp1 = (actionf_p1)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 * TICRATE;
+}
+
+
+
+// UNUSED
+// Separate into p_slidoor.c?
+
+#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 ( gamemode != 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->frame == SNUMFRAMES)
+ {
+ // IF DOOR IS DONE OPENING...
+ 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->frame < 0)
+ {
+ // IF DOOR IS DONE CLOSING...
+ 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 (gamemode != 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
--- /dev/null
+++ b/src/doom/p_enemy.c
@@ -1,0 +1,2034 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION:
+// Enemy thinking, AI.
+// Action Pointer Functions
+// that are associated with states/frames.
+//
+//-----------------------------------------------------------------------------
+
+
+#include <stdlib.h>
+
+#include "m_random.h"
+#include "i_system.h"
+
+#include "doomdef.h"
+#include "p_local.h"
+
+#include "s_sound.h"
+
+#include "g_game.h"
+
+// State.
+#include "doomstat.h"
+#include "r_state.h"
+
+// Data.
+#include "sounds.h"
+
+
+
+
+typedef enum
+{
+ DI_EAST,
+ DI_NORTHEAST,
+ DI_NORTH,
+ DI_NORTHWEST,
+ DI_WEST,
+ DI_SOUTHWEST,
+ DI_SOUTH,
+ DI_SOUTHEAST,
+ DI_NODIR,
+ NUMDIRS
+
+} dirtype_t;
+
+
+//
+// P_NewChaseDir related LUT.
+//
+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 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
+//
+
+
+//
+// Called by P_NoiseAlert.
+// Recursively traverse adjacent sectors,
+// sound blocking lines cut off traversal.
+//
+
+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 ;i<sec->linecount ; 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; // do not 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;
+ fixed_t tryy;
+
+ line_t* ld;
+
+ // warning: 'catch', 'throw', and 'try'
+ // are all C++ reserved words
+ boolean try_ok;
+ boolean 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_ok = P_TryMove (actor, tryx, tryy);
+
+ if (!try_ok)
+ {
+ // 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 is not 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 actor on
+// 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;
+}
+
+
+
+
+void P_NewChaseDir (mobj_t* actor)
+{
+ fixed_t deltax;
+ fixed_t deltay;
+
+ dirtype_t d[3];
+
+ int tdir;
+ dirtype_t olddir;
+
+ dirtype_t 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 != (int) 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))
+ {
+ // either moved forward or attacked
+ return;
+ }
+ }
+
+ 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;
+ }
+
+ // randomly determine direction of search
+ if (P_Random()&1)
+ {
+ for ( tdir=DI_EAST;
+ tdir<=DI_SOUTHEAST;
+ tdir++ )
+ {
+ if (tdir != (int) turnaround)
+ {
+ actor->movedir =tdir;
+
+ if ( P_TryWalk(actor) )
+ return;
+ }
+ }
+ }
+ else
+ {
+ for ( tdir=DI_SOUTHEAST;
+ tdir != (DI_EAST-1);
+ tdir-- )
+ {
+ if (tdir != (int) 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 not 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;
+ int 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)
+ {
+ // done looking
+ return false;
+ }
+
+ 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
+// DOOM II special, map 32.
+// Uses special tag 666.
+//
+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.acp1 != (actionf_p1)P_MobjThinker)
+ continue;
+
+ mo2 = (mobj_t *)th;
+ if (mo2 != mo
+ && mo2->type == mo->type
+ && mo2->health > 0)
+ {
+ // other Keen not dead
+ return;
+ }
+ }
+
+ 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)
+ {
+ // full volume
+ S_StartSound (NULL, sound);
+ }
+ 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;
+ }
+
+ // do not 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;
+ int damage;
+ int 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;
+ int bangle;
+ int damage;
+ int 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;
+ int bangle;
+ int damage;
+ int 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;
+ fixed_t 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
+// Detect a corpse that could be raised.
+//
+mobj_t* corpsehit;
+mobj_t* vileobj;
+fixed_t viletryx;
+fixed_t 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;
+ int xh;
+ int yl;
+ int yh;
+
+ int bx;
+ int 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++)
+ {
+ // Call PIT_VileCheck to check
+ // whether object is a corpse
+ // that canbe raised.
+ 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;
+ }
+ }
+ }
+ }
+
+ // Return to normal attack.
+ 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;
+ mobj_t* target;
+ unsigned an;
+
+ dest = actor->tracer;
+ if (!dest)
+ return;
+
+ target = P_SubstNullMobj(actor->target);
+
+ // don't move it if the vile lost sight
+ if (!P_CheckSight (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 );
+}
+
+
+
+
+//
+// Mancubus attack,
+// firing three missiles (bruisers)
+// in three different directions?
+// Doesn't look like it.
+//
+#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;
+ mobj_t* target;
+ int an;
+
+ A_FaceTarget (actor);
+
+ // Change direction to ...
+ actor->angle += FATSPREAD;
+ target = P_SubstNullMobj(actor->target);
+ P_SpawnMissile (actor, target, MT_FATSHOT);
+
+ mo = P_SpawnMissile (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;
+ mobj_t* target;
+ int an;
+
+ A_FaceTarget (actor);
+ // Now here choose opposite deviation.
+ actor->angle -= FATSPREAD;
+ target = P_SubstNullMobj(actor->target);
+ P_SpawnMissile (actor, target, MT_FATSHOT);
+
+ mo = P_SpawnMissile (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;
+ mobj_t* target;
+ int an;
+
+ A_FaceTarget (actor);
+
+ target = P_SubstNullMobj(actor->target);
+
+ mo = P_SpawnMissile (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, 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;
+ fixed_t y;
+ fixed_t z;
+
+ mobj_t* newmobj;
+ angle_t an;
+ int prestep;
+ int count;
+ thinker_t* currentthinker;
+
+ // count total number of skull currently on the level
+ count = 0;
+
+ currentthinker = thinkercap.next;
+ while (currentthinker != &thinkercap)
+ {
+ if ( (currentthinker->function.acp1 == (actionf_p1)P_MobjThinker)
+ && ((mobj_t *)currentthinker)->type == MT_SKULL)
+ count++;
+ currentthinker = currentthinker->next;
+ }
+
+ // if there are allready 20 skulls on the level,
+ // don't spit another one
+ if (count > 20)
+ return;
+
+
+ // okay, there's playe for another one
+ 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);
+
+ // Check for movements.
+ if (!P_TryMove (newmobj, newmobj->x, newmobj->y))
+ {
+ // kill it immediately
+ P_DamageMobj (newmobj,actor,actor,10000);
+ 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;
+ }
+
+ // Check for bosses.
+ if (actor->type==MT_SPIDER
+ || actor->type == MT_CYBORG)
+ {
+ // full volume
+ S_StartSound (NULL, sound);
+ }
+ 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;
+
+ // So change this if corpse objects
+ // are meant to be obstacles.
+}
+
+
+//
+// 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 ( gamemode == commercial)
+ {
+ if (gamemap != 7)
+ return;
+
+ if ((mo->type != MT_FATSO)
+ && (mo->type != MT_BABY))
+ return;
+ }
+ else
+ {
+ switch(gameepisode)
+ {
+ case 1:
+ if (gamemap != 8)
+ return;
+
+ // fraggle: disable this as it breaks uac_dead.wad.
+ // There is at least one version of Doom 1.9 which it is
+ // possible to play uac_dead through on. I think this was
+ // added here for Ultimate Doom.
+ //
+ // See lmps/doom/ultimate/uac_dead.zip in idgames for
+ // an example of a demo which goes out of sync if this
+ // is left in here.
+ //
+ // For the time being, I'm making the assumption that
+ // doing this is not going to break anything else.
+ //
+ // 2005/10/24: Modify this to test the gameversion setting
+
+ if (gameversion >= exe_ultimate && mo->type != MT_BRUISER)
+ return;
+ break;
+
+ case 2:
+ if (gamemap != 8)
+ return;
+
+ if (mo->type != MT_CYBORG)
+ return;
+ break;
+
+ case 3:
+ if (gamemap != 8)
+ return;
+
+ if (mo->type != MT_SPIDER)
+ return;
+
+ break;
+
+ case 4:
+ switch(gamemap)
+ {
+ case 6:
+ if (mo->type != MT_CYBORG)
+ return;
+ break;
+
+ case 8:
+ if (mo->type != MT_SPIDER)
+ return;
+ break;
+
+ default:
+ return;
+ break;
+ }
+ break;
+
+ default:
+ if (gamemap != 8)
+ return;
+ break;
+ }
+
+ }
+
+
+ // make sure there is a player alive for victory
+ for (i=0 ; i<MAXPLAYERS ; i++)
+ if (playeringame[i] && players[i].health > 0)
+ break;
+
+ if (i==MAXPLAYERS)
+ return; // no one left alive, so do not 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.acp1 != (actionf_p1)P_MobjThinker)
+ continue;
+
+ mo2 = (mobj_t *)th;
+ if (mo2 != mo
+ && mo2->type == mo->type
+ && mo2->health > 0)
+ {
+ // other boss not dead
+ return;
+ }
+ }
+
+ // victory!
+ if ( gamemode == 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
+ {
+ switch(gameepisode)
+ {
+ case 1:
+ junk.tag = 666;
+ EV_DoFloor (&junk, lowerFloorToLowest);
+ return;
+ break;
+
+ case 4:
+ switch(gamemap)
+ {
+ case 6:
+ junk.tag = 666;
+ EV_DoDoor (&junk, blazeOpen);
+ return;
+ break;
+
+ case 8:
+ junk.tag = 666;
+ EV_DoFloor (&junk, lowerFloorToLowest);
+ return;
+ break;
+ }
+ }
+ }
+
+ 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 = 0;
+
+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.acp1 != (actionf_p1)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;
+ int y;
+ int 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;
+ int y;
+ int 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);
+
+// travelling cube sound
+void A_SpawnSound (mobj_t* mo)
+{
+ 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 = P_SubstNullMobj(mo->target);
+
+ // First spawn teleport fog.
+ fog = P_SpawnMobj (targ->x, targ->y, targ->z, MT_SPAWNFIRE);
+ S_StartSound (fog, sfx_telept);
+
+ // Randomly select monster to spawn.
+ r = P_Random ();
+
+ // Probability distribution (kind of :),
+ // decreasing likelihood.
+ 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 (i.e., cube).
+ P_RemoveMobj (mo);
+}
+
+
+
+void A_PlayerScream (mobj_t* mo)
+{
+ // Default death sound.
+ int sound = sfx_pldeth;
+
+ if ( (gamemode == commercial)
+ && (mo->health < -50))
+ {
+ // IF THE PLAYER DIES
+ // LESS THAN -50% WITHOUT GIBBING
+ sound = sfx_pdiehi;
+ }
+
+ S_StartSound (mo, sound);
+}
--- /dev/null
+++ b/src/doom/p_floor.c
@@ -1,0 +1,554 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION:
+// Floor animation: raising stairs.
+//
+//-----------------------------------------------------------------------------
+
+
+
+#include "z_zone.h"
+#include "doomdef.h"
+#include "p_local.h"
+
+#include "s_sound.h"
+
+// State.
+#include "doomstat.h"
+#include "r_state.h"
+// Data.
+#include "sounds.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);
+// UNUSED
+#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(&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(&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.acp1 = (actionf_p1) 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 = INT_MAX;
+ 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;
+ sector_t* tsec;
+
+ floormove_t* floor;
+
+ fixed_t stairsize = 0;
+ fixed_t speed = 0;
+
+ 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.acp1 = (actionf_p1) 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.acp1 = (actionf_p1) T_MoveFloor;
+ floor->direction = 1;
+ floor->sector = sec;
+ floor->speed = speed;
+ floor->floordestheight = height;
+ ok = 1;
+ break;
+ }
+ } while(ok);
+ }
+ return rtn;
+}
+
--- /dev/null
+++ b/src/doom/p_inter.c
@@ -1,0 +1,928 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION:
+// Handling interactions (i.e., collisions).
+//
+//-----------------------------------------------------------------------------
+
+
+
+
+// Data.
+#include "doomdef.h"
+#include "dstrings.h"
+#include "sounds.h"
+
+#include "deh_main.h"
+#include "deh_misc.h"
+#include "doomstat.h"
+
+#include "m_random.h"
+#include "i_system.h"
+
+#include "am_map.h"
+
+#include "p_local.h"
+
+#include "s_sound.h"
+
+#include "p_inter.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 > 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)
+ {
+ // give double ammo in trainer mode,
+ // you'll need in nightmare
+ num <<= 1;
+ }
+
+
+ oldammo = player->ammo[ammo];
+ player->ammo[ammo] += num;
+
+ if (player->ammo[ammo] > player->maxammo[ammo])
+ player->ammo[ammo] = player->maxammo[ammo];
+
+ // If non zero ammo,
+ // don't change up weapons,
+ // player was lower on purpose.
+ if (oldammo)
+ return true;
+
+ // We were down to zero,
+ // so select a new weapon.
+ // Preferences are not user selectable.
+ 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;
+ boolean 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,
+ int /*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)
+ {
+ // out of reach
+ return;
+ }
+
+
+ sound = sfx_itemup;
+ player = toucher->player;
+
+ // Dead thing touching.
+ // Can happen with a sliding player corpse.
+ if (toucher->health <= 0)
+ return;
+
+ // Identify by sprite.
+ switch (special->sprite)
+ {
+ // armor
+ case SPR_ARM1:
+ if (!P_GiveArmor (player, deh_green_armor_class))
+ return;
+ player->message = DEH_String(GOTARMOR);
+ break;
+
+ case SPR_ARM2:
+ if (!P_GiveArmor (player, deh_blue_armor_class))
+ return;
+ player->message = DEH_String(GOTMEGA);
+ break;
+
+ // bonus items
+ case SPR_BON1:
+ player->health++; // can go over 100%
+ if (player->health > deh_max_health)
+ player->health = deh_max_health;
+ player->mo->health = player->health;
+ player->message = DEH_String(GOTHTHBONUS);
+ break;
+
+ case SPR_BON2:
+ player->armorpoints++; // can go over 100%
+ if (player->armorpoints > deh_max_armor)
+ player->armorpoints = deh_max_armor;
+ // deh_green_armor_class only applies to the green armor shirt;
+ // for the armor helmets, armortype 1 is always used.
+ if (!player->armortype)
+ player->armortype = 1;
+ player->message = DEH_String(GOTARMBONUS);
+ break;
+
+ case SPR_SOUL:
+ player->health += deh_soulsphere_health;
+ if (player->health > deh_max_soulsphere)
+ player->health = deh_max_soulsphere;
+ player->mo->health = player->health;
+ player->message = DEH_String(GOTSUPER);
+ sound = sfx_getpow;
+ break;
+
+ case SPR_MEGA:
+ if (gamemode != commercial)
+ return;
+ player->health = deh_megasphere_health;
+ player->mo->health = player->health;
+ // We always give armor type 2 for the megasphere; dehacked only
+ // affects the MegaArmor.
+ P_GiveArmor (player, 2);
+ player->message = DEH_String(GOTMSPHERE);
+ sound = sfx_getpow;
+ break;
+
+ // cards
+ // leave cards for everyone
+ case SPR_BKEY:
+ if (!player->cards[it_bluecard])
+ player->message = DEH_String(GOTBLUECARD);
+ P_GiveCard (player, it_bluecard);
+ if (!netgame)
+ break;
+ return;
+
+ case SPR_YKEY:
+ if (!player->cards[it_yellowcard])
+ player->message = DEH_String(GOTYELWCARD);
+ P_GiveCard (player, it_yellowcard);
+ if (!netgame)
+ break;
+ return;
+
+ case SPR_RKEY:
+ if (!player->cards[it_redcard])
+ player->message = DEH_String(GOTREDCARD);
+ P_GiveCard (player, it_redcard);
+ if (!netgame)
+ break;
+ return;
+
+ case SPR_BSKU:
+ if (!player->cards[it_blueskull])
+ player->message = DEH_String(GOTBLUESKUL);
+ P_GiveCard (player, it_blueskull);
+ if (!netgame)
+ break;
+ return;
+
+ case SPR_YSKU:
+ if (!player->cards[it_yellowskull])
+ player->message = DEH_String(GOTYELWSKUL);
+ P_GiveCard (player, it_yellowskull);
+ if (!netgame)
+ break;
+ return;
+
+ case SPR_RSKU:
+ if (!player->cards[it_redskull])
+ player->message = DEH_String(GOTREDSKULL);
+ P_GiveCard (player, it_redskull);
+ if (!netgame)
+ break;
+ return;
+
+ // medikits, heals
+ case SPR_STIM:
+ if (!P_GiveBody (player, 10))
+ return;
+ player->message = DEH_String(GOTSTIM);
+ break;
+
+ case SPR_MEDI:
+ if (!P_GiveBody (player, 25))
+ return;
+
+ if (player->health < 25)
+ player->message = DEH_String(GOTMEDINEED);
+ else
+ player->message = DEH_String(GOTMEDIKIT);
+ break;
+
+
+ // power ups
+ case SPR_PINV:
+ if (!P_GivePower (player, pw_invulnerability))
+ return;
+ player->message = DEH_String(GOTINVUL);
+ sound = sfx_getpow;
+ break;
+
+ case SPR_PSTR:
+ if (!P_GivePower (player, pw_strength))
+ return;
+ player->message = DEH_String(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 = DEH_String(GOTINVIS);
+ sound = sfx_getpow;
+ break;
+
+ case SPR_SUIT:
+ if (!P_GivePower (player, pw_ironfeet))
+ return;
+ player->message = DEH_String(GOTSUIT);
+ sound = sfx_getpow;
+ break;
+
+ case SPR_PMAP:
+ if (!P_GivePower (player, pw_allmap))
+ return;
+ player->message = DEH_String(GOTMAP);
+ sound = sfx_getpow;
+ break;
+
+ case SPR_PVIS:
+ if (!P_GivePower (player, pw_infrared))
+ return;
+ player->message = DEH_String(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 = DEH_String(GOTCLIP);
+ break;
+
+ case SPR_AMMO:
+ if (!P_GiveAmmo (player, am_clip,5))
+ return;
+ player->message = DEH_String(GOTCLIPBOX);
+ break;
+
+ case SPR_ROCK:
+ if (!P_GiveAmmo (player, am_misl,1))
+ return;
+ player->message = DEH_String(GOTROCKET);
+ break;
+
+ case SPR_BROK:
+ if (!P_GiveAmmo (player, am_misl,5))
+ return;
+ player->message = DEH_String(GOTROCKBOX);
+ break;
+
+ case SPR_CELL:
+ if (!P_GiveAmmo (player, am_cell,1))
+ return;
+ player->message = DEH_String(GOTCELL);
+ break;
+
+ case SPR_CELP:
+ if (!P_GiveAmmo (player, am_cell,5))
+ return;
+ player->message = DEH_String(GOTCELLBOX);
+ break;
+
+ case SPR_SHEL:
+ if (!P_GiveAmmo (player, am_shell,1))
+ return;
+ player->message = DEH_String(GOTSHELLS);
+ break;
+
+ case SPR_SBOX:
+ if (!P_GiveAmmo (player, am_shell,5))
+ return;
+ player->message = DEH_String(GOTSHELLBOX);
+ break;
+
+ case SPR_BPAK:
+ if (!player->backpack)
+ {
+ for (i=0 ; i<NUMAMMO ; i++)
+ player->maxammo[i] *= 2;
+ player->backpack = true;
+ }
+ for (i=0 ; i<NUMAMMO ; i++)
+ P_GiveAmmo (player, i, 1);
+ player->message = DEH_String(GOTBACKPACK);
+ break;
+
+ // weapons
+ case SPR_BFUG:
+ if (!P_GiveWeapon (player, wp_bfg, false) )
+ return;
+ player->message = DEH_String(GOTBFG9000);
+ sound = sfx_wpnup;
+ break;
+
+ case SPR_MGUN:
+ if (!P_GiveWeapon (player, wp_chaingun, special->flags&MF_DROPPED) )
+ return;
+ player->message = DEH_String(GOTCHAINGUN);
+ sound = sfx_wpnup;
+ break;
+
+ case SPR_CSAW:
+ if (!P_GiveWeapon (player, wp_chainsaw, false) )
+ return;
+ player->message = DEH_String(GOTCHAINSAW);
+ sound = sfx_wpnup;
+ break;
+
+ case SPR_LAUN:
+ if (!P_GiveWeapon (player, wp_missile, false) )
+ return;
+ player->message = DEH_String(GOTLAUNCHER);
+ sound = sfx_wpnup;
+ break;
+
+ case SPR_PLAS:
+ if (!P_GiveWeapon (player, wp_plasma, false) )
+ return;
+ player->message = DEH_String(GOTPLASMA);
+ sound = sfx_wpnup;
+ break;
+
+ case SPR_SHOT:
+ if (!P_GiveWeapon (player, wp_shotgun, special->flags&MF_DROPPED ) )
+ return;
+ player->message = DEH_String(GOTSHOTGUN);
+ sound = sfx_wpnup;
+ break;
+
+ case SPR_SGN2:
+ if (!P_GiveWeapon (player, wp_supershotgun, special->flags&MF_DROPPED ) )
+ return;
+ player->message = DEH_String(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)
+ {
+ // count for intermission
+ if (target->flags & MF_COUNTKILL)
+ source->player->killcount++;
+
+ if (target->player)
+ source->player->frags[target->player-players]++;
+ }
+ else if (!netgame && (target->flags & MF_COUNTKILL) )
+ {
+ // count all monster deaths,
+ // even those caused by other monsters
+ players[0].killcount++;
+ }
+
+ if (target->player)
+ {
+ // count environment kills against you
+ if (!source)
+ 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)
+ {
+ // don't die in auto map,
+ // switch view prior to dying
+ AM_Stop ();
+ }
+
+ }
+
+ 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);
+
+ // In Chex Quest, monsters don't drop items.
+
+ if (gameversion == exe_chex)
+ {
+ return;
+ }
+
+ // Drop stuff.
+ // This determines the kind of object spawned
+ // during the death frame of a thing.
+ 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 slime, 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
+
+
+ // Some close combat weapons should not
+ // inflict thrust and push the victim out of reach,
+ // thus 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;
+ }
+
+
+ // Below certain threshold,
+ // ignore damage in GOD mode, or with INVUL power.
+ 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);
+ }
+
+}
+
--- /dev/null
+++ b/src/doom/p_inter.h
@@ -1,0 +1,38 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION:
+//
+//
+//-----------------------------------------------------------------------------
+
+
+#ifndef __P_INTER__
+#define __P_INTER__
+
+
+
+
+boolean P_GivePower(player_t*, int);
+
+
+
+#endif
--- /dev/null
+++ b/src/doom/p_lights.c
@@ -1,0 +1,358 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION:
+// Handle Sector base lighting effects.
+// Muzzle flash?
+//
+//-----------------------------------------------------------------------------
+
+
+
+#include "z_zone.h"
+#include "m_random.h"
+
+#include "doomdef.h"
+#include "p_local.h"
+
+
+// State.
+#include "r_state.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;
+
+ // Note that we are resetting sector attributes.
+ // Nothing special about it during gameplay.
+ sector->special = 0;
+
+ flick = Z_Malloc ( sizeof(*flick), PU_LEVSPEC, 0);
+
+ P_AddThinker (&flick->thinker);
+
+ flick->thinker.function.acp1 = (actionf_p1) 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
+// Do flashing lights.
+//
+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;
+
+ // nothing special about it during gameplay
+ sector->special = 0;
+
+ flash = Z_Malloc ( sizeof(*flash), PU_LEVSPEC, 0);
+
+ P_AddThinker (&flash->thinker);
+
+ flash->thinker.function.acp1 = (actionf_p1) 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
+//
+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_SpawnStrobeFlash
+// 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.acp1 = (actionf_p1) T_StrobeFlash;
+ flash->maxlight = sector->lightlevel;
+ flash->minlight = P_FindMinSurroundingLight(sector, sector->lightlevel);
+
+ if (flash->minlight == flash->maxlight)
+ flash->minlight = 0;
+
+ // nothing special about it during gameplay
+ sector->special = 0;
+
+ 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;i<numsectors;i++, sector++)
+ {
+ if (sector->tag == 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.acp1 = (actionf_p1) T_Glow;
+ g->direction = -1;
+
+ sector->special = 0;
+}
+
--- /dev/null
+++ b/src/doom/p_local.h
@@ -1,0 +1,291 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION:
+// Play functions, animation, global header.
+//
+//-----------------------------------------------------------------------------
+
+
+#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 do not 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)
+
+// follow a player exlusively for 3 seconds
+#define BASETHRESHOLD 100
+
+
+
+//
+// P_TICK
+//
+
+// both the head and tail of the thinker list
+extern thinker_t thinkercap;
+
+
+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 INT_MIN
+#define ONCEILINGZ INT_MAX
+
+// Time interval for item respawning.
+#define ITEMQUESIZE 128
+
+extern mapthing_t itemrespawnque[ITEMQUESIZE];
+extern int itemrespawntime[ITEMQUESIZE];
+extern int iquehead;
+extern int 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);
+mobj_t* P_SubstNullMobj (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;
+ fixed_t y;
+ fixed_t dx;
+ fixed_t dy;
+
+} divline_t;
+
+typedef struct
+{
+ fixed_t frac; // along trace line
+ boolean isaline;
+ union {
+ mobj_t* thing;
+ line_t* line;
+ } d;
+} intercept_t;
+
+// Extended MAXINTERCEPTS, to allow for intercepts overrun emulation.
+
+#define MAXINTERCEPTS_ORIGINAL 128
+#define MAXINTERCEPTS (MAXINTERCEPTS_ORIGINAL + 61)
+
+extern intercept_t intercepts[MAXINTERCEPTS];
+extern intercept_t* 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;
+extern fixed_t openbottom;
+extern fixed_t 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
+//
+
+// If "floatok" true, move would be ok
+// if within "tmfloorz - tmceilingz".
+extern boolean floatok;
+extern fixed_t tmfloorz;
+extern fixed_t 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;
+extern int bmapheight; // in mapblocks
+extern fixed_t bmaporgx;
+extern fixed_t 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 );
+
+
+//
+// P_SPEC
+//
+#include "p_spec.h"
+
+
+#endif // __P_LOCAL__
--- /dev/null
+++ b/src/doom/p_map.c
@@ -1,0 +1,1448 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard, Andrey Budko
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION:
+// Movement, collision handling.
+// Shooting and aiming.
+//
+//-----------------------------------------------------------------------------
+
+
+#include <stdlib.h>
+
+#include "deh_misc.h"
+
+#include "m_bbox.h"
+#include "m_random.h"
+#include "i_system.h"
+
+#include "doomdef.h"
+#include "m_argv.h"
+#include "p_local.h"
+
+#include "s_sound.h"
+
+// State.
+#include "doomstat.h"
+#include "r_state.h"
+// Data.
+#include "sounds.h"
+
+// Spechit overrun magic value.
+//
+// This is the value used by PrBoom-plus. I think the value below is
+// actually better and works with more demos. However, I think
+// it's better for the spechits emulation to be compatible with
+// PrBoom-plus, at least so that the big spechits emulation list
+// on Doomworld can also be used with Chocolate Doom.
+
+#define DEFAULT_SPECHIT_MAGIC 0x01C09C98
+
+// This is from a post by myk on the Doomworld forums,
+// outputted from entryway's spechit_magic generator for
+// s205n546.lmp. The _exact_ value of this isn't too
+// important; as long as it is in the right general
+// range, it will usually work. Otherwise, we can use
+// the generator (hacked doom2.exe) and provide it
+// with -spechit.
+
+//#define DEFAULT_SPECHIT_MAGIC 0x84f968e8
+
+
+fixed_t tmbbox[4];
+mobj_t* tmthing;
+int tmflags;
+fixed_t tmx;
+fixed_t tmy;
+
+
+// If "floatok" true, move would be ok
+// if within "tmfloorz - tmceilingz".
+boolean floatok;
+
+fixed_t tmfloorz;
+fixed_t tmceilingz;
+fixed_t 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
+
+// fraggle: I have increased the size of this buffer. In the original Doom,
+// overrunning past this limit caused other bits of memory to be overwritten,
+// affecting demo playback. However, in doing so, the limit was still
+// exceeded. So we have to support more than 8 specials.
+//
+// We keep the original limit, to detect what variables in memory were
+// overwritten (see SpechitOverrun())
+
+#define MAXSPECIALCROSS 20
+#define MAXSPECIALCROSS_ORIGINAL 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 )
+ {
+ // didn't hit it
+ return true;
+ }
+
+ // don't clip against self
+ if (thing == tmthing)
+ return true;
+
+ // monsters don't stomp things except on boss level
+ if ( !tmthing->player && gamemap != 30)
+ return false;
+
+ P_DamageMobj (thing, tmthing, tmthing, 10000);
+
+ return true;
+}
+
+
+//
+// P_TeleportMove
+//
+boolean
+P_TeleportMove
+( mobj_t* thing,
+ fixed_t x,
+ fixed_t y )
+{
+ int xl;
+ int xh;
+ int yl;
+ int yh;
+ int bx;
+ int 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
+//
+
+static void SpechitOverrun(line_t *ld);
+
+//
+// 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
+ }
+
+ // set openrange, opentop, openbottom
+ P_LineOpening (ld);
+
+ // 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++;
+
+ // fraggle: spechits overrun emulation code from prboom-plus
+ if (numspechit > MAXSPECIALCROSS_ORIGINAL)
+ {
+ SpechitOverrun(ld);
+ }
+ }
+
+ 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 )
+ {
+ // didn't hit it
+ return true;
+ }
+
+ // don't clip against self
+ if (thing == tmthing)
+ return true;
+
+ // 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;
+
+ // sdh: Add deh_species_infighting here. We can override the
+ // "monsters of the same species cant hurt each other" behavior
+ // through dehacked patches
+
+ if (thing->type != MT_PLAYER && !deh_species_infighting)
+ {
+ // Explode, but do no damage.
+ // Let players missile other players.
+ return false;
+ }
+ }
+
+ if (! (thing->flags & MF_SHOOTABLE) )
+ {
+ // didn't do any damage
+ return !(thing->flags & MF_SOLID);
+ }
+
+ // damage / explode
+ damage = ((P_Random()%8)+1)*tmthing->info->damage;
+ P_DamageMobj (thing, tmthing, tmthing->target, damage);
+
+ // don't traverse any more
+ return false;
+ }
+
+ // check for special pickup
+ if (thing->flags & MF_SPECIAL)
+ {
+ solid = thing->flags&MF_SOLID;
+ if (tmflags&MF_PICKUP)
+ {
+ // can remove thing
+ P_TouchSpecialThing (thing, tmthing);
+ }
+ 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;
+ int xh;
+ int yl;
+ int yh;
+ int bx;
+ int 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;
+ fixed_t oldy;
+ int side;
+ int 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, and 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;
+fixed_t secondslidefrac;
+
+line_t* bestslideline;
+line_t* secondslideline;
+
+mobj_t* slidemo;
+
+fixed_t tmxmove;
+fixed_t 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;
+ angle_t moveangle;
+ angle_t deltaangle;
+
+ fixed_t movelen;
+ fixed_t 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))
+ {
+ // don't hit the back side
+ return true;
+ }
+ goto isblocking;
+ }
+
+ // set openrange, opentop, openbottom
+ P_LineOpening (li);
+
+ 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
+
+ // this line doesn't block movement
+ return true;
+
+ // 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;
+ fixed_t leady;
+ fixed_t trailx;
+ fixed_t traily;
+ fixed_t newx;
+ fixed_t 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;
+ }
+
+ // fudge a bit to make sure it doesn't hit
+ bestslidefrac -= 0x800;
+ 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.
+ // First calculate remainder.
+ bestslidefrac = FRACUNIT-(bestslidefrac+0x800);
+
+ 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;
+
+// Height if not aiming up or down
+// ???: use slope for monsters?
+fixed_t shootz;
+
+int la_damage;
+fixed_t attackrange;
+
+fixed_t aimslope;
+
+// slopes to top and bottom of target
+extern fixed_t topslope;
+extern fixed_t bottomslope;
+
+
+//
+// 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;
+ fixed_t thingtopslope;
+ fixed_t 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;
+ fixed_t y;
+ fixed_t z;
+ fixed_t frac;
+
+ line_t* li;
+
+ mobj_t* th;
+
+ fixed_t slope;
+ fixed_t dist;
+ fixed_t thingtopslope;
+ fixed_t 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;
+ }
+
+ // shot continues
+ return true;
+
+
+ // 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)
+ {
+ // don't shoot the sky!
+ if (z > li->frontsector->ceilingheight)
+ return false;
+
+ // it's a sky hack wall
+ if (li->backsector && li->backsector->ceilingpic == skyflatnum)
+ return false;
+ }
+
+ // Spawn bullet puffs.
+ P_SpawnPuff (x,y,z);
+
+ // don't go any farther
+ return false;
+ }
+
+ // 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));
+
+ // Spawn bullet puffs or blod spots,
+ // depending on target type.
+ 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);
+
+ // don't go any farther
+ return false;
+
+}
+
+
+//
+// P_AimLineAttack
+//
+fixed_t
+P_AimLineAttack
+( mobj_t* t1,
+ angle_t angle,
+ fixed_t distance )
+{
+ fixed_t x2;
+ fixed_t y2;
+
+ t1 = P_SubstNullMobj(t1);
+
+ 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;
+
+ // can't shoot outside view angles
+ topslope = 100*FRACUNIT/160;
+ 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;
+ fixed_t 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);
+
+ // can't use through a wall
+ return false;
+ }
+ // not a special line, but keep checking
+ return true ;
+ }
+
+ 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);
+
+ // can't use for than one special line in a row
+ return false;
+}
+
+
+//
+// P_UseLines
+// Looks for special lines in front of the player to activate.
+//
+void P_UseLines (player_t* player)
+{
+ int angle;
+ fixed_t x1;
+ fixed_t y1;
+ fixed_t x2;
+ fixed_t 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
+// "bombsource" is the creature
+// that caused the explosion at "bombspot".
+//
+boolean PIT_RadiusAttack (mobj_t* thing)
+{
+ fixed_t dx;
+ fixed_t dy;
+ fixed_t dist;
+
+ if (!(thing->flags & MF_SHOOTABLE) )
+ return true;
+
+ // Boss spider and cyborg
+ // take no damage from concussion.
+ if (thing->type == MT_CYBORG
+ || thing->type == MT_SPIDER)
+ return true;
+
+ 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 caused the explosion at spot.
+//
+void
+P_RadiusAttack
+( mobj_t* spot,
+ mobj_t* source,
+ int damage )
+{
+ int x;
+ int y;
+
+ int xl;
+ int xh;
+ int yl;
+ int yh;
+
+ fixed_t dist;
+
+ dist = (damage+MAXRADIUS)<<FRACBITS;
+ yh = (spot->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))
+ {
+ // keep checking
+ return true;
+ }
+
+
+ // crunch bodies to giblets
+ if (thing->health <= 0)
+ {
+ P_SetMobjState (thing, S_GIBS);
+
+ thing->flags &= ~MF_SOLID;
+ thing->height = 0;
+ thing->radius = 0;
+
+ // keep checking
+ return true;
+ }
+
+ // crunch dropped items
+ if (thing->flags & MF_DROPPED)
+ {
+ P_RemoveMobj (thing);
+
+ // keep checking
+ return true;
+ }
+
+ if (! (thing->flags & MF_SHOOTABLE) )
+ {
+ // assume it is bloody gibs or something
+ return true;
+ }
+
+ 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;
+ }
+
+ // keep checking (crush other things)
+ return true;
+}
+
+
+
+//
+// P_ChangeSector
+//
+boolean
+P_ChangeSector
+( sector_t* sector,
+ boolean crunch )
+{
+ int x;
+ int y;
+
+ nofit = false;
+ crushchange = crunch;
+
+ // re-check 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;
+}
+
+// Code to emulate the behavior of Vanilla Doom when encountering an overrun
+// of the spechit array. This is by Andrey Budko (e6y) and comes from his
+// PrBoom plus port. A big thanks to Andrey for this.
+
+static void SpechitOverrun(line_t *ld)
+{
+ static unsigned int baseaddr = 0;
+ unsigned int addr;
+
+ if (baseaddr == 0)
+ {
+ int p;
+
+ // This is the first time we have had an overrun. Work out
+ // what base address we are going to use.
+ // Allow a spechit value to be specified on the command line.
+
+ //!
+ // @category compat
+ // @arg <n>
+ //
+ // Use the specified magic value when emulating spechit overruns.
+ //
+
+ p = M_CheckParm("-spechit");
+
+ if (p > 0)
+ {
+ baseaddr = atoi(myargv[p+1]);
+ }
+ else
+ {
+ baseaddr = DEFAULT_SPECHIT_MAGIC;
+ }
+ }
+
+ // Calculate address used in doom2.exe
+
+ addr = baseaddr + (ld - lines) * 0x3E;
+
+ switch(numspechit)
+ {
+ case 9:
+ case 10:
+ case 11:
+ case 12:
+ tmbbox[numspechit-9] = addr;
+ break;
+ case 13:
+ crushchange = addr;
+ break;
+ case 14:
+ nofit = addr;
+ break;
+ default:
+ fprintf(stderr, "SpechitOverrun: Warning: unable to emulate"
+ "an overrun where numspechit=%i\n",
+ numspechit);
+ break;
+ }
+}
+
--- /dev/null
+++ b/src/doom/p_maputl.c
@@ -1,0 +1,1009 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+// Copyright(C) 2005, 2006 Andrey Budko
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION:
+// Movement/collision utility functions,
+// as used by function in p_map.c.
+// BLOCKMAP Iterator functions,
+// and some PIT_* functions to use for iteration.
+//
+//-----------------------------------------------------------------------------
+
+
+
+#include <stdlib.h>
+
+
+#include "m_bbox.h"
+
+#include "doomdef.h"
+#include "doomstat.h"
+#include "p_local.h"
+
+
+// State.
+#include "r_state.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;
+ fixed_t dy;
+ fixed_t left;
+ fixed_t 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 = 0;
+ int p2 = 0;
+
+ 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;
+ fixed_t dy;
+ fixed_t left;
+ fixed_t 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;
+ fixed_t num;
+ fixed_t 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 // UNUSED, float debug.
+ float frac;
+ float num;
+ float den;
+ float v1x;
+ float v1y;
+ float v1dx;
+ float v1dy;
+ float v2x;
+ float v2y;
+ float v2dx;
+ float 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;
+fixed_t openbottom;
+fixed_t openrange;
+fixed_t lowfloor;
+
+
+void P_LineOpening (line_t* linedef)
+{
+ sector_t* front;
+ sector_t* 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.
+// On each position change, BLOCKMAP and other
+// lookups maintaining lists ot things inside
+// these structures need to be updated.
+//
+void P_UnsetThingPosition (mobj_t* thing)
+{
+ int blockx;
+ int 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 <bmapheight)
+ {
+ blocklinks[blocky*bmapwidth+blockx] = thing->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;
+ int 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 < bmapheight)
+ {
+ link = &blocklinks[blocky*bmapwidth+blockx];
+ thing->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 PIT_* 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_t* intercept_p;
+
+divline_t trace;
+boolean earlyout;
+int ptflags;
+
+static void InterceptsOverrun(int num_intercepts, intercept_t *intercept);
+
+//
+// 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;
+ int 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;
+ InterceptsOverrun(intercept_p - intercepts, intercept_p);
+ intercept_p++;
+
+ return true; // continue
+}
+
+
+
+//
+// PIT_AddThingIntercepts
+//
+boolean PIT_AddThingIntercepts (mobj_t* thing)
+{
+ fixed_t x1;
+ fixed_t y1;
+ fixed_t x2;
+ fixed_t y2;
+
+ int s1;
+ int 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;
+ InterceptsOverrun(intercept_p - intercepts, intercept_p);
+ 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;
+ intercept_t* in;
+
+ count = intercept_p - intercepts;
+
+ in = 0; // shut up compiler warning
+
+ while (count--)
+ {
+ dist = INT_MAX;
+ for (scan = intercepts ; scan<intercept_p ; scan++)
+ {
+ if (scan->frac < dist)
+ {
+ dist = scan->frac;
+ in = scan;
+ }
+ }
+
+ if (dist > maxfrac)
+ return true; // checked everything in range
+
+#if 0 // UNUSED
+ {
+ // don't check these yet, there may be others inserted
+ in = scan = intercepts;
+ for ( scan = intercepts ; scan<intercept_p ; scan++)
+ if (scan->frac > maxfrac)
+ *in++ = *scan;
+ intercept_p = in;
+ return false;
+ }
+#endif
+
+ if ( !func (in) )
+ return false; // don't bother going farther
+
+ in->frac = INT_MAX;
+ }
+
+ return true; // everything was traversed
+}
+
+extern fixed_t bulletslope;
+
+// Intercepts Overrun emulation, from PrBoom-plus.
+// Thanks to Andrey Budko (entryway) for researching this and his
+// implementation of Intercepts Overrun emulation in PrBoom-plus
+// which this is based on.
+
+typedef struct
+{
+ int len;
+ void *addr;
+ boolean int16_array;
+} intercepts_overrun_t;
+
+// Intercepts memory table. This is where various variables are located
+// in memory in Vanilla Doom. When the intercepts table overflows, we
+// need to write to them.
+//
+// Almost all of the values to overwrite are 32-bit integers, except for
+// playerstarts, which is effectively an array of 16-bit integers and
+// must be treated differently.
+
+static intercepts_overrun_t intercepts_overrun[] =
+{
+ {4, NULL, false},
+ {4, NULL, /* &earlyout, */ false},
+ {4, NULL, /* &intercept_p, */ false},
+ {4, &lowfloor, false},
+ {4, &openbottom, false},
+ {4, &opentop, false},
+ {4, &openrange, false},
+ {4, NULL, false},
+ {120, NULL, /* &activeplats, */ false},
+ {8, NULL, false},
+ {4, &bulletslope, false},
+ {4, NULL, /* &swingx, */ false},
+ {4, NULL, /* &swingy, */ false},
+ {4, NULL, false},
+ {40, &playerstarts, true},
+ {4, NULL, /* &blocklinks, */ false},
+ {4, &bmapwidth, false},
+ {4, NULL, /* &blockmap, */ false},
+ {4, &bmaporgx, false},
+ {4, &bmaporgy, false},
+ {4, NULL, /* &blockmaplump, */ false},
+ {4, &bmapheight, false},
+ {0, NULL, false},
+};
+
+// Overwrite a specific memory location with a value.
+
+static void InterceptsMemoryOverrun(int location, int value)
+{
+ int i, offset;
+ int index;
+ void *addr;
+
+ i = 0;
+ offset = 0;
+
+ // Search down the array until we find the right entry
+
+ while (intercepts_overrun[i].len != 0)
+ {
+ if (offset + intercepts_overrun[i].len > location)
+ {
+ addr = intercepts_overrun[i].addr;
+
+ // Write the value to the memory location.
+ // 16-bit and 32-bit values are written differently.
+
+ if (addr != NULL)
+ {
+ if (intercepts_overrun[i].int16_array)
+ {
+ index = (location - offset) / 2;
+ ((short *) addr)[index] = value & 0xffff;
+ ((short *) addr)[index + 1] = (value >> 16) & 0xffff;
+ }
+ else
+ {
+ index = (location - offset) / 4;
+ ((int *) addr)[index] = value;
+ }
+ }
+
+ break;
+ }
+
+ offset += intercepts_overrun[i].len;
+ ++i;
+ }
+}
+
+// Emulate overruns of the intercepts[] array.
+
+static void InterceptsOverrun(int num_intercepts, intercept_t *intercept)
+{
+ int location;
+
+ if (num_intercepts <= MAXINTERCEPTS_ORIGINAL)
+ {
+ // No overrun
+
+ return;
+ }
+
+ location = (num_intercepts - MAXINTERCEPTS_ORIGINAL - 1) * 12;
+
+ // Overwrite memory that is overwritten in Vanilla Doom, using
+ // the values from the intercept structure.
+ //
+ // Note: the ->d.{thing,line} member should really have its
+ // address translated into the correct address value for
+ // Vanilla Doom.
+
+ InterceptsMemoryOverrun(location, intercept->frac);
+ InterceptsMemoryOverrun(location + 4, intercept->isaline);
+ InterceptsMemoryOverrun(location + 8, (int) intercept->d.thing);
+}
+
+
+//
+// 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;
+ fixed_t yt1;
+ fixed_t xt2;
+ fixed_t yt2;
+
+ fixed_t xstep;
+ fixed_t ystep;
+
+ fixed_t partial;
+
+ fixed_t xintercept;
+ fixed_t yintercept;
+
+ int mapx;
+ int mapy;
+
+ int mapxstep;
+ int 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 );
+}
+
+
+
--- /dev/null
+++ b/src/doom/p_mobj.c
@@ -1,0 +1,1056 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION:
+// Moving object handling. Spawn functions.
+//
+//-----------------------------------------------------------------------------
+
+
+#include "i_system.h"
+#include "z_zone.h"
+#include "m_random.h"
+
+#include "doomdef.h"
+#include "p_local.h"
+#include "sounds.h"
+
+#include "st_stuff.h"
+#include "hu_stuff.h"
+
+#include "s_sound.h"
+
+#include "doomstat.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;
+
+ // Modified handling.
+ // Call action functions when the state is set
+ if (st->action.acp1)
+ st->action.acp1(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;
+ fixed_t ptryy;
+ player_t* player;
+ fixed_t xmove;
+ fixed_t 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.
+ // Does not handle sky floors.
+ 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)
+ {
+ // do not 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;
+ fixed_t 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
+
+ // Note (id):
+ // somebody left this after the setting momz to 0,
+ // kinda useless there.
+ //
+ // cph - This was the a bug in the linuxdoom-1.10 source which
+ // caused it not to sync Doom 2 v1.9 demos. Someone
+ // added the above comment and moved up the following code. So
+ // demos would desync in close lost soul fights.
+ // Note that this only applies to original Doom 1 or Doom2 demos - not
+ // Final Doom and Ultimate Doom. So we test demo_compatibility *and*
+ // gamemission. (Note we assume that Doom1 is always Ult Doom, which
+ // seems to hold for most published demos.)
+ //
+ // fraggle - cph got the logic here slightly wrong. There are three
+ // versions of Doom 1.9:
+ //
+ // * The version used in registered doom 1.9 + doom2 - no bounce
+ // * The version used in ultimate doom - has bounce
+ // * The version used in final doom - has bounce
+ //
+ // So we need to check that this is either retail or commercial
+ // (but not doom2)
+
+ int correct_lost_soul_bounce = gameversion >= exe_ultimate;
+
+ if (correct_lost_soul_bounce && mo->flags & MF_SKULLFLY)
+ {
+ // the skull slammed into something
+ mo->momz = -mo->momz;
+ }
+
+ if (mo->momz < 0)
+ {
+ if (mo->player
+ && mo->momz < -GRAVITY*8)
+ {
+ // Squat down.
+ // Decrease viewheight for a moment
+ // after hitting the ground (hard),
+ // and utter appropriate sound.
+ mo->player->deltaviewheight = mo->momz>>3;
+ S_StartSound (mo, sfx_oof);
+ }
+ mo->momz = 0;
+ }
+ mo->z = mo->floorz;
+
+
+ // cph 2001/05/26 -
+ // See lost soul bouncing comment above. We need this here for bug
+ // compatibility with original Doom2 v1.9 - if a soul is charging and
+ // hit by a raising floor this incorrectly reverses its Y momentum.
+ //
+
+ if (!correct_lost_soul_bounce && mo->flags & MF_SKULLFLY)
+ 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;
+ fixed_t y;
+ fixed_t z;
+ subsector_t* ss;
+ mobj_t* mo;
+ mapthing_t* mthing;
+
+ x = mobj->spawnpoint.x << FRACBITS;
+ y = mobj->spawnpoint.y << FRACBITS;
+
+ // somthing is occupying it's position?
+ if (!P_CheckPosition (mobj, x, y) )
+ return; // no respwan
+
+ // spawn a teleport fog at old spot
+ // because of removal of the body?
+ mo = P_SpawnMobj (mobj->x,
+ mobj->y,
+ mobj->subsector->sector->floorheight , MT_TFOG);
+ // initiate teleport sound
+ 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;
+
+ // inherit attributes from deceased one
+ 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);
+
+ // FIXME: decent NOP/NULL/Nil function pointer please.
+ if (mobj->thinker.function.acv == (actionf_v) (-1))
+ return; // mobj was removed
+ }
+ if ( (mobj->z != mobj->floorz)
+ || mobj->momz )
+ {
+ P_ZMovement (mobj);
+
+ // FIXME: decent NOP/NULL/Nil function pointer please.
+ if (mobj->thinker.function.acv == (actionf_v) (-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*TICRATE)
+ 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 not 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.acp1 = (actionf_p1)P_MobjThinker;
+
+ P_AddThinker (&mobj->thinker);
+
+ return mobj;
+}
+
+
+//
+// P_RemoveMobj
+//
+mapthing_t itemrespawnque[ITEMQUESIZE];
+int itemrespawntime[ITEMQUESIZE];
+int iquehead;
+int 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);
+
+ // lose one off the end?
+ if (iquehead == iquetail)
+ 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;
+ fixed_t y;
+ fixed_t z;
+
+ subsector_t* ss;
+ mobj_t* mo;
+ mapthing_t* mthing;
+
+ int i;
+
+ // only respawn items in deathmatch
+ if (deathmatch != 2)
+ return; //
+
+ // nothing left to respawn?
+ if (iquehead == iquetail)
+ return;
+
+ // wait at least 30 seconds
+ if (leveltime - itemrespawntime[iquetail] < 30*TICRATE)
+ return;
+
+ 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;
+ fixed_t y;
+ fixed_t z;
+
+ mobj_t* mobj;
+
+ int i;
+
+ if (mthing->type == 0)
+ {
+ return;
+ }
+
+ // not playing?
+ if (!playeringame[mthing->type-1])
+ return;
+
+ 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);
+
+ // set color translations for player sprites
+ if (mthing->type > 1)
+ mobj->flags |= (mthing->type-1)<<MF_TRANSSHIFT;
+
+ mobj->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;
+
+ // setup gun psprite
+ P_SetupPsprites (p);
+
+ // give all cards in death match mode
+ if (deathmatch)
+ for (i=0 ; i<NUMCARDS ; i++)
+ p->cards[i] = true;
+
+ if (mthing->type-1 == consoleplayer)
+ {
+ // wake up the status bar
+ ST_Start ();
+ // wake up the heads up text
+ HU_Start ();
+ }
+}
+
+
+//
+// P_SpawnMapThing
+// The fields of the mapthing should
+// already be in host byte order.
+//
+void P_SpawnMapThing (mapthing_t* mthing)
+{
+ int i;
+ int bit;
+ mobj_t* mobj;
+ fixed_t x;
+ fixed_t y;
+ fixed_t z;
+
+ // count deathmatch start positions
+ if (mthing->type == 11)
+ {
+ if (deathmatch_p < &deathmatchstarts[10])
+ {
+ memcpy (deathmatch_p, mthing, sizeof(*mthing));
+ deathmatch_p++;
+ }
+ return;
+ }
+
+ if (mthing->type <= 0)
+ {
+ // Thing type 0 is actually "player -1 start".
+ // For some reason, Vanilla Doom accepts/ignores this.
+
+ 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;
+
+ // move a little forward so an angle can
+ // be computed if it immediately explodes
+ th->x += (th->momx>>1);
+ th->y += (th->momy>>1);
+ th->z += (th->momz>>1);
+
+ if (!P_TryMove (th, th->x, th->y))
+ P_ExplodeMissile (th);
+}
+
+// Certain functions assume that a mobj_t pointer is non-NULL,
+// causing a crash in some situations where it is NULL. Vanilla
+// Doom did not crash because of the lack of proper memory
+// protection. This function substitutes NULL pointers for
+// pointers to a dummy mobj, to avoid a crash.
+
+mobj_t *P_SubstNullMobj(mobj_t *mobj)
+{
+ if (mobj == NULL)
+ {
+ static mobj_t dummy_mobj;
+
+ dummy_mobj.x = 0;
+ dummy_mobj.y = 0;
+ dummy_mobj.z = 0;
+ dummy_mobj.flags = 0;
+
+ mobj = &dummy_mobj;
+ }
+
+ return mobj;
+}
+
+//
+// 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);
+
+ // fuzzy player
+ if (dest->flags & MF_SHADOW)
+ an += (P_Random()-P_Random())<<20;
+
+ 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;
+ fixed_t y;
+ fixed_t z;
+ fixed_t 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);
+}
+
--- /dev/null
+++ b/src/doom/p_mobj.h
@@ -1,0 +1,292 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION:
+// Map Objects, MObj, definition and handling.
+//
+//-----------------------------------------------------------------------------
+
+
+#ifndef __P_MOBJ__
+#define __P_MOBJ__
+
+// Basics.
+#include "tables.h"
+#include "m_fixed.h"
+
+// We need the thinker_t stuff.
+#include "d_think.h"
+
+// We need the WAD data structure for Map things,
+// from the THINGS lump.
+#include "doomdata.h"
+
+// States are tied to finite states are
+// tied to animation frames.
+// Needs precompiled tables/data structures.
+#include "info.h"
+
+
+
+
+
+
+//
+// NOTES: mobj_t
+//
+// 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 its 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 by 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 its origin contained.
+//
+// A valid mobj_t is a mobj_t that has the proper subsector_t
+// filled in for its xy coordinates and is linked into the
+// sector from which the subsector was made, 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.
+//
+// Any questions?
+//
+
+//
+// Misc. mobj flags
+//
+typedef enum
+{
+ // Call P_SpecialThing when touched.
+ MF_SPECIAL = 1,
+ // Blocks.
+ MF_SOLID = 2,
+ // Can be hit.
+ MF_SHOOTABLE = 4,
+ // Don't use the sector links (invisible but touchable).
+ MF_NOSECTOR = 8,
+ // Don't use the blocklinks (inert but displayable)
+ MF_NOBLOCKMAP = 16,
+
+ // Not to be activated by sound, deaf monster.
+ MF_AMBUSH = 32,
+ // Will try to attack right back.
+ MF_JUSTHIT = 64,
+ // Will take at least one step before attacking.
+ MF_JUSTATTACKED = 128,
+ // On level spawning (initial position),
+ // hang from ceiling instead of stand on floor.
+ MF_SPAWNCEILING = 256,
+ // Don't apply gravity (every tic),
+ // that is, object will float, keeping current height
+ // or changing it actively.
+ MF_NOGRAVITY = 512,
+
+ // Movement flags.
+ // This allows jumps from high places.
+ MF_DROPOFF = 0x400,
+ // For players, will pick up items.
+ MF_PICKUP = 0x800,
+ // Player cheat. ???
+ MF_NOCLIP = 0x1000,
+ // Player: keep info about sliding along walls.
+ MF_SLIDE = 0x2000,
+ // Allow moves to any height, no gravity.
+ // For active floaters, e.g. cacodemons, pain elementals.
+ MF_FLOAT = 0x4000,
+ // Don't cross lines
+ // ??? or look at heights on teleport.
+ MF_TELEPORT = 0x8000,
+ // Don't hit same species, explode on block.
+ // Player missiles as well as fireballs of various kinds.
+ MF_MISSILE = 0x10000,
+ // Dropped by a demon, not level spawned.
+ // E.g. ammo clips dropped by dying former humans.
+ MF_DROPPED = 0x20000,
+ // Use fuzzy draw (shadow demons or spectres),
+ // temporary player invisibility powerup.
+ MF_SHADOW = 0x40000,
+ // Flag: don't bleed when shot (use puff),
+ // barrels and shootable furniture shall not bleed.
+ MF_NOBLOOD = 0x80000,
+ // Don't stop moving halfway off a step,
+ // that is, have dead bodies slide down all the way.
+ MF_CORPSE = 0x100000,
+ // Floating to a height for a move, ???
+ // don't auto float to target's height.
+ MF_INFLOAT = 0x200000,
+
+ // On kill, count this enemy object
+ // towards intermission kill total.
+ // Happy gathering.
+ MF_COUNTKILL = 0x400000,
+
+ // On picking up, count this item object
+ // towards intermission item total.
+ MF_COUNTITEM = 0x800000,
+
+ // Special handling: skull in flight.
+ // Neither a cacodemon nor a missile.
+ MF_SKULLFLY = 0x1000000,
+
+ // Don't spawn this object
+ // in death match mode (e.g. key cards).
+ MF_NOTDMATCH = 0x2000000,
+
+ // Player sprites in multiplayer modes are modified
+ // using an internal color lookup table for re-indexing.
+ // If 0x4 0x8 or 0xc,
+ // use a translation table for player colormaps
+ MF_TRANSLATION = 0xc000000,
+ // Hmm ???.
+ MF_TRANSSHIFT = 26
+
+} mobjflag_t;
+
+
+// Map Object definition.
+typedef struct mobj_s
+{
+ // List: thinker links.
+ thinker_t thinker;
+
+ // Info for drawing: position.
+ fixed_t x;
+ fixed_t y;
+ fixed_t z;
+
+ // More list: links in sector (if needed)
+ struct mobj_s* snext;
+ struct mobj_s* sprev;
+
+ //More drawing info: to determine current sprite.
+ angle_t angle; // orientation
+ spritenum_t sprite; // used to find patch_t and flip value
+ int frame; // might be ORed with FF_FULLBRIGHT
+
+ // Interaction info, by BLOCKMAP.
+ // Links in blocks (if needed).
+ struct mobj_s* bnext;
+ struct mobj_s* bprev;
+
+ struct subsector_s* subsector;
+
+ // The closest interval over all contacted Sectors.
+ fixed_t floorz;
+ fixed_t ceilingz;
+
+ // For movement checking.
+ fixed_t radius;
+ fixed_t height;
+
+ // Momentums, used to update position.
+ fixed_t momx;
+ fixed_t momy;
+ fixed_t momz;
+
+ // If == validcount, already checked.
+ int validcount;
+
+ mobjtype_t type;
+ mobjinfo_t* info; // &mobjinfo[mobj->type]
+
+ int tics; // state tic counter
+ state_t* state;
+ int flags;
+ int health;
+
+ // Movement direction, movement generation (zig-zagging).
+ int movedir; // 0-7
+ int movecount; // when 0, select a new dir
+
+ // Thing being chased/attacked (or NULL),
+ // also the originator for missiles.
+ struct mobj_s* target;
+
+ // Reaction time: if non 0, don't attack yet.
+ // Used by player to freeze a bit after teleporting.
+ int reactiontime;
+
+ // If >0, the target will be chased
+ // no matter what (even if shot)
+ int threshold;
+
+ // Additional info record for player avatars only.
+ // Only valid if type == MT_PLAYER
+ struct player_s* player;
+
+ // Player number last looked for.
+ int lastlook;
+
+ // For nightmare respawn.
+ mapthing_t spawnpoint;
+
+ // Thing being chased/attacked for tracers.
+ struct mobj_s* tracer;
+
+} mobj_t;
+
+
+
+#endif
--- /dev/null
+++ b/src/doom/p_plats.c
@@ -1,0 +1,312 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION:
+// Plats (i.e. elevator platforms) code, raising/lowering.
+//
+//-----------------------------------------------------------------------------
+
+
+
+#include "i_system.h"
+#include "z_zone.h"
+#include "m_random.h"
+
+#include "doomdef.h"
+#include "p_local.h"
+
+#include "s_sound.h"
+
+// State.
+#include "doomstat.h"
+#include "r_state.h"
+
+// Data.
+#include "sounds.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(&plat->sector->soundorg, sfx_stnmov);
+ }
+
+
+ if (res == crushed && (!plat->crush))
+ {
+ plat->count = plat->wait;
+ plat->status = down;
+ S_StartSound(&plat->sector->soundorg, sfx_pstart);
+ }
+ else
+ {
+ if (res == pastdest)
+ {
+ plat->count = plat->wait;
+ plat->status = waiting;
+ S_StartSound(&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(&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(&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 <type> 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.acp1 = (actionf_p1) 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;
+ // NO MORE DAMAGE, IF APPLICABLE
+ sec->special = 0;
+
+ S_StartSound(&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(&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 = TICRATE*PLATWAIT;
+ plat->status = down;
+ S_StartSound(&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 = TICRATE*PLATWAIT;
+ plat->status = down;
+ S_StartSound(&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 = TICRATE*PLATWAIT;
+ plat->status = P_Random()&1;
+
+ S_StartSound(&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.acp1
+ = (actionf_p1) 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.acv = (actionf_v)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!");
+}
--- /dev/null
+++ b/src/doom/p_pspr.c
@@ -1,0 +1,896 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION:
+// Weapon sprite animation, weapon objects.
+// Action functions for weapons.
+//
+//-----------------------------------------------------------------------------
+
+
+#include "doomdef.h"
+#include "d_event.h"
+
+#include "deh_misc.h"
+
+#include "m_random.h"
+#include "p_local.h"
+#include "s_sound.h"
+
+// State.
+#include "doomstat.h"
+
+// Data.
+#include "sounds.h"
+
+#include "p_pspr.h"
+
+#define LOWERSPEED FRACUNIT*6
+#define RAISESPEED FRACUNIT*6
+
+#define WEAPONBOTTOM 128*FRACUNIT
+#define WEAPONTOP 32*FRACUNIT
+
+
+
+//
+// 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)
+ {
+ // object removed itself
+ psp->state = NULL;
+ break;
+ }
+
+ 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.
+ // Modified handling.
+ if (state->action.acp2)
+ {
+ state->action.acp2(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;
+fixed_t swingy;
+
+void P_CalcSwing (player_t* player)
+{
+ fixed_t swing;
+ int angle;
+
+ // OPTIMIZE: tablify this.
+ // A LUT would allow for different modes,
+ // and add flexibility.
+
+ 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]);
+}
+
+
+
+//
+// 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;
+
+ // Minimal amount for one shot varies.
+ if (player->readyweapon == wp_bfg)
+ count = deh_bfg_cells_per_shot;
+ else if (player->readyweapon == wp_supershotgun)
+ count = 2; // Double barrel.
+ else
+ count = 1; // Regular.
+
+ // Some do not need ammunition anyway.
+ // Return if current ammunition sufficient.
+ if (ammo == am_noammo || player->ammo[ammo] >= count)
+ return true;
+
+ // Out of ammo, pick a weapon to change to.
+ // Preferences are set here.
+ do
+ {
+ if (player->weaponowned[wp_plasma]
+ && player->ammo[am_cell]
+ && (gamemode != shareware) )
+ {
+ player->pendingweapon = wp_plasma;
+ }
+ else if (player->weaponowned[wp_supershotgun]
+ && player->ammo[am_shell]>2
+ && (gamemode == 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
+ && (gamemode != shareware) )
+ {
+ player->pendingweapon = wp_bfg;
+ }
+ else
+ {
+ // If everything fails.
+ player->pendingweapon = wp_fist;
+ }
+
+ } while (player->pendingweapon == wp_nochange);
+
+ // Now set appropriate weapon overlay.
+ 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.
+// Follows after getting weapon up,
+// or after previous attack/fire sequence.
+//
+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
+// Lowers current weapon,
+// and changes weapon at bottom.
+//
+void
+A_Lower
+( player_t* player,
+ pspdef_t* psp )
+{
+ psp->sy += LOWERSPEED;
+
+ // Is already down.
+ if (psp->sy < WEAPONBOTTOM )
+ return;
+
+ // Player is dead.
+ if (player->playerstate == PST_DEAD)
+ {
+ psp->sy = WEAPONBOTTOM;
+
+ // don't bring weapon back up
+ return;
+ }
+
+ // 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 ((signed int) (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;
+}
+
+// Doom does not check the bounds of the ammo array. As a result,
+// it is possible to use an ammo type > 4 that overflows into the
+// maxammo array and affects that instead. Through dehacked, for
+// example, it is possible to make a weapon that decreases the max
+// number of ammo for another weapon. Emulate this.
+
+static void DecreaseAmmo(player_t *player, int ammonum, int amount)
+{
+ if (ammonum < NUMAMMO)
+ {
+ player->ammo[ammonum] -= amount;
+ }
+ else
+ {
+ player->maxammo[ammonum - NUMAMMO] -= amount;
+ }
+}
+
+
+//
+// A_FireMissile
+//
+void
+A_FireMissile
+( player_t* player,
+ pspdef_t* psp )
+{
+ DecreaseAmmo(player, weaponinfo[player->readyweapon].ammo, 1);
+ P_SpawnPlayerMissile (player->mo, MT_ROCKET);
+}
+
+
+//
+// A_FireBFG
+//
+void
+A_FireBFG
+( player_t* player,
+ pspdef_t* psp )
+{
+ DecreaseAmmo(player, weaponinfo[player->readyweapon].ammo,
+ deh_bfg_cells_per_shot);
+ P_SpawnPlayerMissile (player->mo, MT_BFG);
+}
+
+
+
+//
+// A_FirePlasma
+//
+void
+A_FirePlasma
+( player_t* player,
+ pspdef_t* psp )
+{
+ DecreaseAmmo(player, weaponinfo[player->readyweapon].ammo, 1);
+
+ 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);
+ DecreaseAmmo(player, weaponinfo[player->readyweapon].ammo, 1);
+
+ 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);
+
+ DecreaseAmmo(player, weaponinfo[player->readyweapon].ammo, 1);
+
+ 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);
+
+ DecreaseAmmo(player, 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);
+ DecreaseAmmo(player, weaponinfo[player->readyweapon].ammo, 1);
+
+ 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;
+ int j;
+ int 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 ; i<NUMPSPRITES ; i++)
+ player->psprites[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 ; i<NUMPSPRITES ; i++, psp++)
+ {
+ // a null state means not active
+ if ( (state = psp->state) )
+ {
+ // drop tic count and possibly change state
+
+ // a -1 tic count never changes
+ if (psp->tics != -1)
+ {
+ 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;
+}
+
+
--- /dev/null
+++ b/src/doom/p_pspr.h
@@ -1,0 +1,79 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION:
+// Sprite animation.
+//
+//-----------------------------------------------------------------------------
+
+
+#ifndef __P_PSPR__
+#define __P_PSPR__
+
+// Basic data types.
+// Needs fixed point, and BAM angles.
+#include "m_fixed.h"
+#include "tables.h"
+
+
+//
+// Needs to include the precompiled
+// sprite animation tables.
+// Header generated by multigen utility.
+// This includes all the data for thing animation,
+// i.e. the Thing Atrributes table
+// and the Frame Sequence table.
+#include "info.h"
+
+
+
+//
+// Frame flags:
+// handles maximum brightness (torches, muzzle flare, light sources)
+//
+#define FF_FULLBRIGHT 0x8000 // flag in thing->frame
+#define FF_FRAMEMASK 0x7fff
+
+
+
+//
+// Overlay psprites are scaled shapes
+// drawn 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;
+ fixed_t sy;
+
+} pspdef_t;
+
+#endif
--- /dev/null
+++ b/src/doom/p_saveg.c
@@ -1,0 +1,1880 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION:
+// Archiving: SaveGame I/O.
+//
+//-----------------------------------------------------------------------------
+
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "dstrings.h"
+#include "deh_main.h"
+#include "i_system.h"
+#include "z_zone.h"
+#include "p_local.h"
+#include "p_saveg.h"
+
+// State.
+#include "doomstat.h"
+#include "r_state.h"
+
+#define SAVEGAME_EOF 0x1d
+#define VERSIONSIZE 16
+
+FILE *save_stream;
+int savegamelength;
+
+// Get the filename of a temporary file to write the savegame to. After
+// the file has been successfully saved, it will be renamed to the
+// real file.
+
+char *P_TempSaveGameFile(void)
+{
+ static char *filename = NULL;
+
+ if (filename == NULL)
+ {
+ filename = malloc(strlen(savegamedir) + 32);
+ }
+
+ sprintf(filename, "%stemp.dsg", savegamedir);
+
+ return filename;
+}
+
+// Get the filename of the save game file to use for the specified slot.
+
+char *P_SaveGameFile(int slot)
+{
+ static char *filename = NULL;
+ char basename[32];
+
+ if (filename == NULL)
+ {
+ filename = malloc(strlen(savegamedir) + 32);
+ }
+
+ sprintf(basename, DEH_String(SAVEGAMENAME "%d.dsg"), slot);
+
+ sprintf(filename, "%s%s", savegamedir, basename);
+
+ return filename;
+}
+
+// Endian-safe integer read/write functions
+
+static byte saveg_read8(void)
+{
+ byte result;
+
+ fread(&result, 1, 1, save_stream);
+
+ return result;
+}
+
+static void saveg_write8(byte value)
+{
+ fwrite(&value, 1, 1, save_stream);
+}
+
+static short saveg_read16(void)
+{
+ int result;
+
+ result = saveg_read8();
+ result |= saveg_read8() << 8;
+
+ return result;
+}
+
+static void saveg_write16(short value)
+{
+ saveg_write8(value & 0xff);
+ saveg_write8((value >> 8) & 0xff);
+}
+
+static int saveg_read32(void)
+{
+ int result;
+
+ result = saveg_read8();
+ result |= saveg_read8() << 8;
+ result |= saveg_read8() << 16;
+ result |= saveg_read8() << 24;
+
+ return result;
+}
+
+static void saveg_write32(int value)
+{
+ saveg_write8(value & 0xff);
+ saveg_write8((value >> 8) & 0xff);
+ saveg_write8((value >> 16) & 0xff);
+ saveg_write8((value >> 24) & 0xff);
+}
+
+// Pad to 4-byte boundaries
+
+static void saveg_read_pad(void)
+{
+ unsigned long pos;
+ int padding;
+ int i;
+
+ pos = ftell(save_stream);
+
+ padding = (4 - (pos & 3)) & 3;
+
+ for (i=0; i<padding; ++i)
+ {
+ saveg_read8();
+ }
+}
+
+static void saveg_write_pad(void)
+{
+ unsigned long pos;
+ int padding;
+ int i;
+
+ pos = ftell(save_stream);
+
+ padding = (4 - (pos & 3)) & 3;
+
+ for (i=0; i<padding; ++i)
+ {
+ saveg_write8(0);
+ }
+}
+
+
+// Pointers
+
+static void *saveg_readp(void)
+{
+ return (void *) saveg_read32();
+}
+
+static void saveg_writep(void *p)
+{
+ saveg_write32((int) p);
+}
+
+// Enum values are 32-bit integers.
+
+#define saveg_read_enum saveg_read32
+#define saveg_write_enum saveg_write32
+
+//
+// Structure read/write functions
+//
+
+//
+// mapthing_t
+//
+
+static void saveg_read_mapthing_t(mapthing_t *str)
+{
+ // short x;
+ str->x = saveg_read16();
+
+ // short y;
+ str->y = saveg_read16();
+
+ // short angle;
+ str->angle = saveg_read16();
+
+ // short type;
+ str->type = saveg_read16();
+
+ // short options;
+ str->options = saveg_read16();
+}
+
+static void saveg_write_mapthing_t(mapthing_t *str)
+{
+ // short x;
+ saveg_write16(str->x);
+
+ // short y;
+ saveg_write16(str->y);
+
+ // short angle;
+ saveg_write16(str->angle);
+
+ // short type;
+ saveg_write16(str->type);
+
+ // short options;
+ saveg_write16(str->options);
+}
+
+//
+// actionf_t
+//
+
+static void saveg_read_actionf_t(actionf_t *str)
+{
+ // actionf_p1 acp1;
+ str->acp1 = saveg_readp();
+}
+
+static void saveg_write_actionf_t(actionf_t *str)
+{
+ // actionf_p1 acp1;
+ saveg_writep(str->acp1);
+}
+
+//
+// think_t
+//
+// This is just an actionf_t.
+//
+
+#define saveg_read_think_t saveg_read_actionf_t
+#define saveg_write_think_t saveg_write_actionf_t
+
+//
+// thinker_t
+//
+
+static void saveg_read_thinker_t(thinker_t *str)
+{
+ // struct thinker_s* prev;
+ str->prev = saveg_readp();
+
+ // struct thinker_s* next;
+ str->next = saveg_readp();
+
+ // think_t function;
+ saveg_read_think_t(&str->function);
+}
+
+static void saveg_write_thinker_t(thinker_t *str)
+{
+ // struct thinker_s* prev;
+ saveg_writep(str->prev);
+
+ // struct thinker_s* next;
+ saveg_writep(str->next);
+
+ // think_t function;
+ saveg_write_think_t(&str->function);
+}
+
+//
+// mobj_t
+//
+
+static void saveg_read_mobj_t(mobj_t *str)
+{
+ int pl;
+
+ // thinker_t thinker;
+ saveg_read_thinker_t(&str->thinker);
+
+ // fixed_t x;
+ str->x = saveg_read32();
+
+ // fixed_t y;
+ str->y = saveg_read32();
+
+ // fixed_t z;
+ str->z = saveg_read32();
+
+ // struct mobj_s* snext;
+ str->snext = saveg_readp();
+
+ // struct mobj_s* sprev;
+ str->sprev = saveg_readp();
+
+ // angle_t angle;
+ str->angle = saveg_read32();
+
+ // spritenum_t sprite;
+ str->sprite = saveg_read_enum();
+
+ // int frame;
+ str->frame = saveg_read32();
+
+ // struct mobj_s* bnext;
+ str->bnext = saveg_readp();
+
+ // struct mobj_s* bprev;
+ str->bprev = saveg_readp();
+
+ // struct subsector_s* subsector;
+ str->subsector = saveg_readp();
+
+ // fixed_t floorz;
+ str->floorz = saveg_read32();
+
+ // fixed_t ceilingz;
+ str->ceilingz = saveg_read32();
+
+ // fixed_t radius;
+ str->radius = saveg_read32();
+
+ // fixed_t height;
+ str->height = saveg_read32();
+
+ // fixed_t momx;
+ str->momx = saveg_read32();
+
+ // fixed_t momy;
+ str->momy = saveg_read32();
+
+ // fixed_t momz;
+ str->momz = saveg_read32();
+
+ // int validcount;
+ str->validcount = saveg_read32();
+
+ // mobjtype_t type;
+ str->type = saveg_read_enum();
+
+ // mobjinfo_t* info;
+ str->info = saveg_readp();
+
+ // int tics;
+ str->tics = saveg_read32();
+
+ // state_t* state;
+ str->state = &states[saveg_read32()];
+
+ // int flags;
+ str->flags = saveg_read32();
+
+ // int health;
+ str->health = saveg_read32();
+
+ // int movedir;
+ str->movedir = saveg_read32();
+
+ // int movecount;
+ str->movecount = saveg_read32();
+
+ // struct mobj_s* target;
+ str->target = saveg_readp();
+
+ // int reactiontime;
+ str->reactiontime = saveg_read32();
+
+ // int threshold;
+ str->threshold = saveg_read32();
+
+ // struct player_s* player;
+ pl = saveg_read32();
+
+ if (pl > 0)
+ {
+ str->player = &players[pl - 1];
+ str->player->mo = str;
+ }
+ else
+ {
+ str->player = NULL;
+ }
+
+ // int lastlook;
+ str->lastlook = saveg_read32();
+
+ // mapthing_t spawnpoint;
+ saveg_read_mapthing_t(&str->spawnpoint);
+
+ // struct mobj_s* tracer;
+ str->tracer = saveg_readp();
+}
+
+static void saveg_write_mobj_t(mobj_t *str)
+{
+ // thinker_t thinker;
+ saveg_write_thinker_t(&str->thinker);
+
+ // fixed_t x;
+ saveg_write32(str->x);
+
+ // fixed_t y;
+ saveg_write32(str->y);
+
+ // fixed_t z;
+ saveg_write32(str->z);
+
+ // struct mobj_s* snext;
+ saveg_writep(str->snext);
+
+ // struct mobj_s* sprev;
+ saveg_writep(str->sprev);
+
+ // angle_t angle;
+ saveg_write32(str->angle);
+
+ // spritenum_t sprite;
+ saveg_write_enum(str->sprite);
+
+ // int frame;
+ saveg_write32(str->frame);
+
+ // struct mobj_s* bnext;
+ saveg_writep(str->bnext);
+
+ // struct mobj_s* bprev;
+ saveg_writep(str->bprev);
+
+ // struct subsector_s* subsector;
+ saveg_writep(str->subsector);
+
+ // fixed_t floorz;
+ saveg_write32(str->floorz);
+
+ // fixed_t ceilingz;
+ saveg_write32(str->ceilingz);
+
+ // fixed_t radius;
+ saveg_write32(str->radius);
+
+ // fixed_t height;
+ saveg_write32(str->height);
+
+ // fixed_t momx;
+ saveg_write32(str->momx);
+
+ // fixed_t momy;
+ saveg_write32(str->momy);
+
+ // fixed_t momz;
+ saveg_write32(str->momz);
+
+ // int validcount;
+ saveg_write32(str->validcount);
+
+ // mobjtype_t type;
+ saveg_write_enum(str->type);
+
+ // mobjinfo_t* info;
+ saveg_writep(str->info);
+
+ // int tics;
+ saveg_write32(str->tics);
+
+ // state_t* state;
+ saveg_write32(str->state - states);
+
+ // int flags;
+ saveg_write32(str->flags);
+
+ // int health;
+ saveg_write32(str->health);
+
+ // int movedir;
+ saveg_write32(str->movedir);
+
+ // int movecount;
+ saveg_write32(str->movecount);
+
+ // struct mobj_s* target;
+ saveg_writep(str->target);
+
+ // int reactiontime;
+ saveg_write32(str->reactiontime);
+
+ // int threshold;
+ saveg_write32(str->threshold);
+
+ // struct player_s* player;
+ if (str->player)
+ {
+ saveg_write32(str->player - players + 1);
+ }
+ else
+ {
+ saveg_write32(0);
+ }
+
+ // int lastlook;
+ saveg_write32(str->lastlook);
+
+ // mapthing_t spawnpoint;
+ saveg_write_mapthing_t(&str->spawnpoint);
+
+ // struct mobj_s* tracer;
+ saveg_writep(str->tracer);
+}
+
+
+//
+// ticcmd_t
+//
+
+static void saveg_read_ticcmd_t(ticcmd_t *str)
+{
+
+ // signed char forwardmove;
+ str->forwardmove = saveg_read8();
+
+ // signed char sidemove;
+ str->sidemove = saveg_read8();
+
+ // short angleturn;
+ str->angleturn = saveg_read16();
+
+ // short consistancy;
+ str->consistancy = saveg_read16();
+
+ // byte chatchar;
+ str->chatchar = saveg_read8();
+
+ // byte buttons;
+ str->buttons = saveg_read8();
+}
+
+static void saveg_write_ticcmd_t(ticcmd_t *str)
+{
+
+ // signed char forwardmove;
+ saveg_write8(str->forwardmove);
+
+ // signed char sidemove;
+ saveg_write8(str->sidemove);
+
+ // short angleturn;
+ saveg_write16(str->angleturn);
+
+ // short consistancy;
+ saveg_write16(str->consistancy);
+
+ // byte chatchar;
+ saveg_write8(str->chatchar);
+
+ // byte buttons;
+ saveg_write8(str->buttons);
+}
+
+//
+// pspdef_t
+//
+
+static void saveg_read_pspdef_t(pspdef_t *str)
+{
+ int state;
+
+ // state_t* state;
+ state = saveg_read32();
+
+ if (state > 0)
+ {
+ str->state = &states[state];
+ }
+ else
+ {
+ str->state = NULL;
+ }
+
+ // int tics;
+ str->tics = saveg_read32();
+
+ // fixed_t sx;
+ str->sx = saveg_read32();
+
+ // fixed_t sy;
+ str->sy = saveg_read32();
+}
+
+static void saveg_write_pspdef_t(pspdef_t *str)
+{
+ // state_t* state;
+ if (str->state)
+ {
+ saveg_write32(str->state - states);
+ }
+ else
+ {
+ saveg_write32(0);
+ }
+
+ // int tics;
+ saveg_write32(str->tics);
+
+ // fixed_t sx;
+ saveg_write32(str->sx);
+
+ // fixed_t sy;
+ saveg_write32(str->sy);
+}
+
+//
+// player_t
+//
+
+static void saveg_read_player_t(player_t *str)
+{
+ int i;
+
+ // mobj_t* mo;
+ str->mo = saveg_readp();
+
+ // playerstate_t playerstate;
+ str->playerstate = saveg_read_enum();
+
+ // ticcmd_t cmd;
+ saveg_read_ticcmd_t(&str->cmd);
+
+ // fixed_t viewz;
+ str->viewz = saveg_read32();
+
+ // fixed_t viewheight;
+ str->viewheight = saveg_read32();
+
+ // fixed_t deltaviewheight;
+ str->deltaviewheight = saveg_read32();
+
+ // fixed_t bob;
+ str->bob = saveg_read32();
+
+ // int health;
+ str->health = saveg_read32();
+
+ // int armorpoints;
+ str->armorpoints = saveg_read32();
+
+ // int armortype;
+ str->armortype = saveg_read32();
+
+ // int powers[NUMPOWERS];
+ for (i=0; i<NUMPOWERS; ++i)
+ {
+ str->powers[i] = saveg_read32();
+ }
+
+ // boolean cards[NUMCARDS];
+ for (i=0; i<NUMCARDS; ++i)
+ {
+ str->cards[i] = saveg_read32();
+ }
+
+ // boolean backpack;
+ str->backpack = saveg_read32();
+
+ // int frags[MAXPLAYERS];
+ for (i=0; i<MAXPLAYERS; ++i)
+ {
+ str->frags[i] = saveg_read32();
+ }
+
+ // weapontype_t readyweapon;
+ str->readyweapon = saveg_read_enum();
+
+ // weapontype_t pendingweapon;
+ str->pendingweapon = saveg_read_enum();
+
+ // boolean weaponowned[NUMWEAPONS];
+ for (i=0; i<NUMWEAPONS; ++i)
+ {
+ str->weaponowned[i] = saveg_read32();
+ }
+
+ // int ammo[NUMAMMO];
+ for (i=0; i<NUMAMMO; ++i)
+ {
+ str->ammo[i] = saveg_read32();
+ }
+
+ // int maxammo[NUMAMMO];
+ for (i=0; i<NUMAMMO; ++i)
+ {
+ str->maxammo[i] = saveg_read32();
+ }
+
+ // int attackdown;
+ str->attackdown = saveg_read32();
+
+ // int usedown;
+ str->usedown = saveg_read32();
+
+ // int cheats;
+ str->cheats = saveg_read32();
+
+ // int refire;
+ str->refire = saveg_read32();
+
+ // int killcount;
+ str->killcount = saveg_read32();
+
+ // int itemcount;
+ str->itemcount = saveg_read32();
+
+ // int secretcount;
+ str->secretcount = saveg_read32();
+
+ // char* message;
+ str->message = saveg_readp();
+
+ // int damagecount;
+ str->damagecount = saveg_read32();
+
+ // int bonuscount;
+ str->bonuscount = saveg_read32();
+
+ // mobj_t* attacker;
+ str->attacker = saveg_readp();
+
+ // int extralight;
+ str->extralight = saveg_read32();
+
+ // int fixedcolormap;
+ str->fixedcolormap = saveg_read32();
+
+ // int colormap;
+ str->colormap = saveg_read32();
+
+ // pspdef_t psprites[NUMPSPRITES];
+ for (i=0; i<NUMPSPRITES; ++i)
+ {
+ saveg_read_pspdef_t(&str->psprites[i]);
+ }
+
+ // boolean didsecret;
+ str->didsecret = saveg_read32();
+}
+
+static void saveg_write_player_t(player_t *str)
+{
+ int i;
+
+ // mobj_t* mo;
+ saveg_writep(str->mo);
+
+ // playerstate_t playerstate;
+ saveg_write_enum(str->playerstate);
+
+ // ticcmd_t cmd;
+ saveg_write_ticcmd_t(&str->cmd);
+
+ // fixed_t viewz;
+ saveg_write32(str->viewz);
+
+ // fixed_t viewheight;
+ saveg_write32(str->viewheight);
+
+ // fixed_t deltaviewheight;
+ saveg_write32(str->deltaviewheight);
+
+ // fixed_t bob;
+ saveg_write32(str->bob);
+
+ // int health;
+ saveg_write32(str->health);
+
+ // int armorpoints;
+ saveg_write32(str->armorpoints);
+
+ // int armortype;
+ saveg_write32(str->armortype);
+
+ // int powers[NUMPOWERS];
+ for (i=0; i<NUMPOWERS; ++i)
+ {
+ saveg_write32(str->powers[i]);
+ }
+
+ // boolean cards[NUMCARDS];
+ for (i=0; i<NUMCARDS; ++i)
+ {
+ saveg_write32(str->cards[i]);
+ }
+
+ // boolean backpack;
+ saveg_write32(str->backpack);
+
+ // int frags[MAXPLAYERS];
+ for (i=0; i<MAXPLAYERS; ++i)
+ {
+ saveg_write32(str->frags[i]);
+ }
+
+ // weapontype_t readyweapon;
+ saveg_write_enum(str->readyweapon);
+
+ // weapontype_t pendingweapon;
+ saveg_write_enum(str->pendingweapon);
+
+ // boolean weaponowned[NUMWEAPONS];
+ for (i=0; i<NUMWEAPONS; ++i)
+ {
+ saveg_write32(str->weaponowned[i]);
+ }
+
+ // int ammo[NUMAMMO];
+ for (i=0; i<NUMAMMO; ++i)
+ {
+ saveg_write32(str->ammo[i]);
+ }
+
+ // int maxammo[NUMAMMO];
+ for (i=0; i<NUMAMMO; ++i)
+ {
+ saveg_write32(str->maxammo[i]);
+ }
+
+ // int attackdown;
+ saveg_write32(str->attackdown);
+
+ // int usedown;
+ saveg_write32(str->usedown);
+
+ // int cheats;
+ saveg_write32(str->cheats);
+
+ // int refire;
+ saveg_write32(str->refire);
+
+ // int killcount;
+ saveg_write32(str->killcount);
+
+ // int itemcount;
+ saveg_write32(str->itemcount);
+
+ // int secretcount;
+ saveg_write32(str->secretcount);
+
+ // char* message;
+ saveg_writep(str->message);
+
+ // int damagecount;
+ saveg_write32(str->damagecount);
+
+ // int bonuscount;
+ saveg_write32(str->bonuscount);
+
+ // mobj_t* attacker;
+ saveg_writep(str->attacker);
+
+ // int extralight;
+ saveg_write32(str->extralight);
+
+ // int fixedcolormap;
+ saveg_write32(str->fixedcolormap);
+
+ // int colormap;
+ saveg_write32(str->colormap);
+
+ // pspdef_t psprites[NUMPSPRITES];
+ for (i=0; i<NUMPSPRITES; ++i)
+ {
+ saveg_write_pspdef_t(&str->psprites[i]);
+ }
+
+ // boolean didsecret;
+ saveg_write32(str->didsecret);
+}
+
+
+//
+// ceiling_t
+//
+
+static void saveg_read_ceiling_t(ceiling_t *str)
+{
+ int sector;
+
+ // thinker_t thinker;
+ saveg_read_thinker_t(&str->thinker);
+
+ // ceiling_e type;
+ str->type = saveg_read_enum();
+
+ // sector_t* sector;
+ sector = saveg_read32();
+ str->sector = §ors[sector];
+
+ // fixed_t bottomheight;
+ str->bottomheight = saveg_read32();
+
+ // fixed_t topheight;
+ str->topheight = saveg_read32();
+
+ // fixed_t speed;
+ str->speed = saveg_read32();
+
+ // boolean crush;
+ str->crush = saveg_read32();
+
+ // int direction;
+ str->direction = saveg_read32();
+
+ // int tag;
+ str->tag = saveg_read32();
+
+ // int olddirection;
+ str->olddirection = saveg_read32();
+}
+
+static void saveg_write_ceiling_t(ceiling_t *str)
+{
+ // thinker_t thinker;
+ saveg_write_thinker_t(&str->thinker);
+
+ // ceiling_e type;
+ saveg_write_enum(str->type);
+
+ // sector_t* sector;
+ saveg_write32(str->sector - sectors);
+
+ // fixed_t bottomheight;
+ saveg_write32(str->bottomheight);
+
+ // fixed_t topheight;
+ saveg_write32(str->topheight);
+
+ // fixed_t speed;
+ saveg_write32(str->speed);
+
+ // boolean crush;
+ saveg_write32(str->crush);
+
+ // int direction;
+ saveg_write32(str->direction);
+
+ // int tag;
+ saveg_write32(str->tag);
+
+ // int olddirection;
+ saveg_write32(str->olddirection);
+}
+
+//
+// vldoor_t
+//
+
+static void saveg_read_vldoor_t(vldoor_t *str)
+{
+ int sector;
+
+ // thinker_t thinker;
+ saveg_read_thinker_t(&str->thinker);
+
+ // vldoor_e type;
+ str->type = saveg_read_enum();
+
+ // sector_t* sector;
+ sector = saveg_read32();
+ str->sector = §ors[sector];
+
+ // fixed_t topheight;
+ str->topheight = saveg_read32();
+
+ // fixed_t speed;
+ str->speed = saveg_read32();
+
+ // int direction;
+ str->direction = saveg_read32();
+
+ // int topwait;
+ str->topwait = saveg_read32();
+
+ // int topcountdown;
+ str->topcountdown = saveg_read32();
+}
+
+static void saveg_write_vldoor_t(vldoor_t *str)
+{
+ // thinker_t thinker;
+ saveg_write_thinker_t(&str->thinker);
+
+ // vldoor_e type;
+ saveg_write_enum(str->type);
+
+ // sector_t* sector;
+ saveg_write32(str->sector - sectors);
+
+ // fixed_t topheight;
+ saveg_write32(str->topheight);
+
+ // fixed_t speed;
+ saveg_write32(str->speed);
+
+ // int direction;
+ saveg_write32(str->direction);
+
+ // int topwait;
+ saveg_write32(str->topwait);
+
+ // int topcountdown;
+ saveg_write32(str->topcountdown);
+}
+
+//
+// floormove_t
+//
+
+static void saveg_read_floormove_t(floormove_t *str)
+{
+ int sector;
+
+ // thinker_t thinker;
+ saveg_read_thinker_t(&str->thinker);
+
+ // floor_e type;
+ str->type = saveg_read_enum();
+
+ // boolean crush;
+ str->crush = saveg_read32();
+
+ // sector_t* sector;
+ sector = saveg_read32();
+ str->sector = §ors[sector];
+
+ // int direction;
+ str->direction = saveg_read32();
+
+ // int newspecial;
+ str->newspecial = saveg_read32();
+
+ // short texture;
+ str->texture = saveg_read16();
+
+ // fixed_t floordestheight;
+ str->floordestheight = saveg_read32();
+
+ // fixed_t speed;
+ str->speed = saveg_read32();
+}
+
+static void saveg_write_floormove_t(floormove_t *str)
+{
+ // thinker_t thinker;
+ saveg_write_thinker_t(&str->thinker);
+
+ // floor_e type;
+ saveg_write_enum(str->type);
+
+ // boolean crush;
+ saveg_write32(str->crush);
+
+ // sector_t* sector;
+ saveg_write32(str->sector - sectors);
+
+ // int direction;
+ saveg_write32(str->direction);
+
+ // int newspecial;
+ saveg_write32(str->newspecial);
+
+ // short texture;
+ saveg_write16(str->texture);
+
+ // fixed_t floordestheight;
+ saveg_write32(str->floordestheight);
+
+ // fixed_t speed;
+ saveg_write32(str->speed);
+}
+
+//
+// plat_t
+//
+
+static void saveg_read_plat_t(plat_t *str)
+{
+ int sector;
+
+ // thinker_t thinker;
+ saveg_read_thinker_t(&str->thinker);
+
+ // sector_t* sector;
+ sector = saveg_read32();
+ str->sector = §ors[sector];
+
+ // fixed_t speed;
+ str->speed = saveg_read32();
+
+ // fixed_t low;
+ str->low = saveg_read32();
+
+ // fixed_t high;
+ str->high = saveg_read32();
+
+ // int wait;
+ str->wait = saveg_read32();
+
+ // int count;
+ str->count = saveg_read32();
+
+ // plat_e status;
+ str->status = saveg_read_enum();
+
+ // plat_e oldstatus;
+ str->oldstatus = saveg_read_enum();
+
+ // boolean crush;
+ str->crush = saveg_read32();
+
+ // int tag;
+ str->tag = saveg_read32();
+
+ // plattype_e type;
+ str->type = saveg_read_enum();
+}
+
+static void saveg_write_plat_t(plat_t *str)
+{
+ // thinker_t thinker;
+ saveg_write_thinker_t(&str->thinker);
+
+ // sector_t* sector;
+ saveg_write32(str->sector - sectors);
+
+ // fixed_t speed;
+ saveg_write32(str->speed);
+
+ // fixed_t low;
+ saveg_write32(str->low);
+
+ // fixed_t high;
+ saveg_write32(str->high);
+
+ // int wait;
+ saveg_write32(str->wait);
+
+ // int count;
+ saveg_write32(str->count);
+
+ // plat_e status;
+ saveg_write_enum(str->status);
+
+ // plat_e oldstatus;
+ saveg_write_enum(str->oldstatus);
+
+ // boolean crush;
+ saveg_write32(str->crush);
+
+ // int tag;
+ saveg_write32(str->tag);
+
+ // plattype_e type;
+ saveg_write_enum(str->type);
+}
+
+//
+// lightflash_t
+//
+
+static void saveg_read_lightflash_t(lightflash_t *str)
+{
+ int sector;
+
+ // thinker_t thinker;
+ saveg_read_thinker_t(&str->thinker);
+
+ // sector_t* sector;
+ sector = saveg_read32();
+ str->sector = §ors[sector];
+
+ // int count;
+ str->count = saveg_read32();
+
+ // int maxlight;
+ str->maxlight = saveg_read32();
+
+ // int minlight;
+ str->minlight = saveg_read32();
+
+ // int maxtime;
+ str->maxtime = saveg_read32();
+
+ // int mintime;
+ str->mintime = saveg_read32();
+}
+
+static void saveg_write_lightflash_t(lightflash_t *str)
+{
+ // thinker_t thinker;
+ saveg_write_thinker_t(&str->thinker);
+
+ // sector_t* sector;
+ saveg_write32(str->sector - sectors);
+
+ // int count;
+ saveg_write32(str->count);
+
+ // int maxlight;
+ saveg_write32(str->maxlight);
+
+ // int minlight;
+ saveg_write32(str->minlight);
+
+ // int maxtime;
+ saveg_write32(str->maxtime);
+
+ // int mintime;
+ saveg_write32(str->mintime);
+}
+
+//
+// strobe_t
+//
+
+static void saveg_read_strobe_t(strobe_t *str)
+{
+ int sector;
+
+ // thinker_t thinker;
+ saveg_read_thinker_t(&str->thinker);
+
+ // sector_t* sector;
+ sector = saveg_read32();
+ str->sector = §ors[sector];
+
+ // int count;
+ str->count = saveg_read32();
+
+ // int minlight;
+ str->minlight = saveg_read32();
+
+ // int maxlight;
+ str->maxlight = saveg_read32();
+
+ // int darktime;
+ str->darktime = saveg_read32();
+
+ // int brighttime;
+ str->brighttime = saveg_read32();
+}
+
+static void saveg_write_strobe_t(strobe_t *str)
+{
+ // thinker_t thinker;
+ saveg_write_thinker_t(&str->thinker);
+
+ // sector_t* sector;
+ saveg_write32(str->sector - sectors);
+
+ // int count;
+ saveg_write32(str->count);
+
+ // int minlight;
+ saveg_write32(str->minlight);
+
+ // int maxlight;
+ saveg_write32(str->maxlight);
+
+ // int darktime;
+ saveg_write32(str->darktime);
+
+ // int brighttime;
+ saveg_write32(str->brighttime);
+}
+
+//
+// glow_t
+//
+
+static void saveg_read_glow_t(glow_t *str)
+{
+ int sector;
+
+ // thinker_t thinker;
+ saveg_read_thinker_t(&str->thinker);
+
+ // sector_t* sector;
+ sector = saveg_read32();
+ str->sector = §ors[sector];
+
+ // int minlight;
+ str->minlight = saveg_read32();
+
+ // int maxlight;
+ str->maxlight = saveg_read32();
+
+ // int direction;
+ str->direction = saveg_read32();
+}
+
+static void saveg_write_glow_t(glow_t *str)
+{
+ // thinker_t thinker;
+ saveg_write_thinker_t(&str->thinker);
+
+ // sector_t* sector;
+ saveg_write32(str->sector - sectors);
+
+ // int minlight;
+ saveg_write32(str->minlight);
+
+ // int maxlight;
+ saveg_write32(str->maxlight);
+
+ // int direction;
+ saveg_write32(str->direction);
+}
+
+//
+// Write the header for a savegame
+//
+
+void P_WriteSaveGameHeader(char *description)
+{
+ char name[VERSIONSIZE];
+ int i;
+
+ for (i=0; description[i] != '\0'; ++i)
+ saveg_write8(description[i]);
+ for (; i<SAVESTRINGSIZE; ++i)
+ saveg_write8(0);
+
+ memset (name,0,sizeof(name));
+ sprintf (name,"version %i",DOOM_VERSION);
+
+ for (i=0; i<VERSIONSIZE; ++i)
+ saveg_write8(name[i]);
+
+ saveg_write8(gameskill);
+ saveg_write8(gameepisode);
+ saveg_write8(gamemap);
+
+ for (i=0 ; i<MAXPLAYERS ; i++)
+ saveg_write8(playeringame[i]);
+
+ saveg_write8((leveltime >> 16) & 0xff);
+ saveg_write8((leveltime >> 8) & 0xff);
+ saveg_write8(leveltime & 0xff);
+}
+
+//
+// Read the header for a savegame
+//
+
+boolean P_ReadSaveGameHeader(void)
+{
+ int i;
+ byte a, b, c;
+ char vcheck[VERSIONSIZE];
+ char read_vcheck[VERSIONSIZE];
+
+ // skip the description field
+
+ for (i=0; i<SAVESTRINGSIZE; ++i)
+ saveg_read8();
+
+ for (i=0; i<VERSIONSIZE; ++i)
+ read_vcheck[i] = saveg_read8();
+
+ memset (vcheck,0,sizeof(vcheck));
+ sprintf (vcheck,"version %i",DOOM_VERSION);
+ if (strcmp(read_vcheck, vcheck) != 0)
+ return false; // bad version
+
+ gameskill = saveg_read8();
+ gameepisode = saveg_read8();
+ gamemap = saveg_read8();
+
+ for (i=0 ; i<MAXPLAYERS ; i++)
+ playeringame[i] = saveg_read8();
+
+ // get the times
+ a = saveg_read8();
+ b = saveg_read8();
+ c = saveg_read8();
+ leveltime = (a<<16) + (b<<8) + c;
+
+ return true;
+}
+
+//
+// Read the end of file marker. Returns true if read successfully.
+//
+
+boolean P_ReadSaveGameEOF(void)
+{
+ int value;
+
+ value = saveg_read8();
+
+ return value == SAVEGAME_EOF;
+}
+
+//
+// Write the end of file marker
+//
+
+void P_WriteSaveGameEOF(void)
+{
+ saveg_write8(SAVEGAME_EOF);
+}
+
+//
+// P_ArchivePlayers
+//
+void P_ArchivePlayers (void)
+{
+ int i;
+
+ for (i=0 ; i<MAXPLAYERS ; i++)
+ {
+ if (!playeringame[i])
+ continue;
+
+ saveg_write_pad();
+
+ saveg_write_player_t(&players[i]);
+ }
+}
+
+
+
+//
+// P_UnArchivePlayers
+//
+void P_UnArchivePlayers (void)
+{
+ int i;
+
+ for (i=0 ; i<MAXPLAYERS ; i++)
+ {
+ if (!playeringame[i])
+ continue;
+
+ saveg_read_pad();
+
+ saveg_read_player_t(&players[i]);
+
+ // will be set when unarc thinker
+ players[i].mo = NULL;
+ players[i].message = NULL;
+ players[i].attacker = NULL;
+ }
+}
+
+
+//
+// P_ArchiveWorld
+//
+void P_ArchiveWorld (void)
+{
+ int i;
+ int j;
+ sector_t* sec;
+ line_t* li;
+ side_t* si;
+
+ // do sectors
+ for (i=0, sec = sectors ; i<numsectors ; i++,sec++)
+ {
+ saveg_write16(sec->floorheight >> FRACBITS);
+ saveg_write16(sec->ceilingheight >> FRACBITS);
+ saveg_write16(sec->floorpic);
+ saveg_write16(sec->ceilingpic);
+ saveg_write16(sec->lightlevel);
+ saveg_write16(sec->special); // needed?
+ saveg_write16(sec->tag); // needed?
+ }
+
+
+ // do lines
+ for (i=0, li = lines ; i<numlines ; i++,li++)
+ {
+ saveg_write16(li->flags);
+ saveg_write16(li->special);
+ saveg_write16(li->tag);
+ for (j=0 ; j<2 ; j++)
+ {
+ if (li->sidenum[j] == -1)
+ continue;
+
+ si = &sides[li->sidenum[j]];
+
+ saveg_write16(si->textureoffset >> FRACBITS);
+ saveg_write16(si->rowoffset >> FRACBITS);
+ saveg_write16(si->toptexture);
+ saveg_write16(si->bottomtexture);
+ saveg_write16(si->midtexture);
+ }
+ }
+}
+
+
+
+//
+// P_UnArchiveWorld
+//
+void P_UnArchiveWorld (void)
+{
+ int i;
+ int j;
+ sector_t* sec;
+ line_t* li;
+ side_t* si;
+
+ // do sectors
+ for (i=0, sec = sectors ; i<numsectors ; i++,sec++)
+ {
+ sec->floorheight = saveg_read16() << FRACBITS;
+ sec->ceilingheight = saveg_read16() << FRACBITS;
+ sec->floorpic = saveg_read16();
+ sec->ceilingpic = saveg_read16();
+ sec->lightlevel = saveg_read16();
+ sec->special = saveg_read16(); // needed?
+ sec->tag = saveg_read16(); // needed?
+ sec->specialdata = 0;
+ sec->soundtarget = 0;
+ }
+
+ // do lines
+ for (i=0, li = lines ; i<numlines ; i++,li++)
+ {
+ li->flags = saveg_read16();
+ li->special = saveg_read16();
+ li->tag = saveg_read16();
+ for (j=0 ; j<2 ; j++)
+ {
+ if (li->sidenum[j] == -1)
+ continue;
+ si = &sides[li->sidenum[j]];
+ si->textureoffset = saveg_read16() << FRACBITS;
+ si->rowoffset = saveg_read16() << FRACBITS;
+ si->toptexture = saveg_read16();
+ si->bottomtexture = saveg_read16();
+ si->midtexture = saveg_read16();
+ }
+ }
+}
+
+
+
+
+
+//
+// Thinkers
+//
+typedef enum
+{
+ tc_end,
+ tc_mobj
+
+} thinkerclass_t;
+
+
+//
+// P_ArchiveThinkers
+//
+void P_ArchiveThinkers (void)
+{
+ thinker_t* th;
+
+ // save off the current thinkers
+ for (th = thinkercap.next ; th != &thinkercap ; th=th->next)
+ {
+ if (th->function.acp1 == (actionf_p1)P_MobjThinker)
+ {
+ saveg_write8(tc_mobj);
+ saveg_write_pad();
+ saveg_write_mobj_t((mobj_t *) th);
+
+ continue;
+ }
+
+ // I_Error ("P_ArchiveThinkers: Unknown thinker function");
+ }
+
+ // add a terminating marker
+ saveg_write8(tc_end);
+}
+
+
+
+//
+// P_UnArchiveThinkers
+//
+void P_UnArchiveThinkers (void)
+{
+ byte tclass;
+ thinker_t* currentthinker;
+ thinker_t* next;
+ mobj_t* mobj;
+
+ // remove all the current thinkers
+ currentthinker = thinkercap.next;
+ while (currentthinker != &thinkercap)
+ {
+ next = currentthinker->next;
+
+ if (currentthinker->function.acp1 == (actionf_p1)P_MobjThinker)
+ P_RemoveMobj ((mobj_t *)currentthinker);
+ else
+ Z_Free (currentthinker);
+
+ currentthinker = next;
+ }
+ P_InitThinkers ();
+
+ // read in saved thinkers
+ while (1)
+ {
+ tclass = saveg_read8();
+ switch (tclass)
+ {
+ case tc_end:
+ return; // end of list
+
+ case tc_mobj:
+ saveg_read_pad();
+ mobj = Z_Malloc (sizeof(*mobj), PU_LEVEL, NULL);
+ saveg_read_mobj_t(mobj);
+
+ mobj->target = NULL;
+ mobj->tracer = NULL;
+ P_SetThingPosition (mobj);
+ mobj->info = &mobjinfo[mobj->type];
+ mobj->floorz = mobj->subsector->sector->floorheight;
+ mobj->ceilingz = mobj->subsector->sector->ceilingheight;
+ mobj->thinker.function.acp1 = (actionf_p1)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;
+
+
+
+//
+// Things to handle:
+//
+// 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
+//
+void P_ArchiveSpecials (void)
+{
+ thinker_t* th;
+ int i;
+
+ // save off the current thinkers
+ for (th = thinkercap.next ; th != &thinkercap ; th=th->next)
+ {
+ if (th->function.acv == (actionf_v)NULL)
+ {
+ for (i = 0; i < MAXCEILINGS;i++)
+ if (activeceilings[i] == (ceiling_t *)th)
+ break;
+
+ if (i<MAXCEILINGS)
+ {
+ saveg_write8(tc_ceiling);
+ saveg_write_pad();
+ saveg_write_ceiling_t((ceiling_t *) th);
+ }
+ continue;
+ }
+
+ if (th->function.acp1 == (actionf_p1)T_MoveCeiling)
+ {
+ saveg_write8(tc_ceiling);
+ saveg_write_pad();
+ saveg_write_ceiling_t((ceiling_t *) th);
+ continue;
+ }
+
+ if (th->function.acp1 == (actionf_p1)T_VerticalDoor)
+ {
+ saveg_write8(tc_door);
+ saveg_write_pad();
+ saveg_write_vldoor_t((vldoor_t *) th);
+ continue;
+ }
+
+ if (th->function.acp1 == (actionf_p1)T_MoveFloor)
+ {
+ saveg_write8(tc_floor);
+ saveg_write_pad();
+ saveg_write_floormove_t((floormove_t *) th);
+ continue;
+ }
+
+ if (th->function.acp1 == (actionf_p1)T_PlatRaise)
+ {
+ saveg_write8(tc_plat);
+ saveg_write_pad();
+ saveg_write_plat_t((plat_t *) th);
+ continue;
+ }
+
+ if (th->function.acp1 == (actionf_p1)T_LightFlash)
+ {
+ saveg_write8(tc_flash);
+ saveg_write_pad();
+ saveg_write_lightflash_t((lightflash_t *) th);
+ continue;
+ }
+
+ if (th->function.acp1 == (actionf_p1)T_StrobeFlash)
+ {
+ saveg_write8(tc_strobe);
+ saveg_write_pad();
+ saveg_write_strobe_t((strobe_t *) th);
+ continue;
+ }
+
+ if (th->function.acp1 == (actionf_p1)T_Glow)
+ {
+ saveg_write8(tc_glow);
+ saveg_write_pad();
+ saveg_write_glow_t((glow_t *) th);
+ continue;
+ }
+ }
+
+ // add a terminating marker
+ saveg_write8(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 = saveg_read8();
+
+ switch (tclass)
+ {
+ case tc_endspecials:
+ return; // end of list
+
+ case tc_ceiling:
+ saveg_read_pad();
+ ceiling = Z_Malloc (sizeof(*ceiling), PU_LEVEL, NULL);
+ saveg_read_ceiling_t(ceiling);
+ ceiling->sector->specialdata = ceiling;
+
+ if (ceiling->thinker.function.acp1)
+ ceiling->thinker.function.acp1 = (actionf_p1)T_MoveCeiling;
+
+ P_AddThinker (&ceiling->thinker);
+ P_AddActiveCeiling(ceiling);
+ break;
+
+ case tc_door:
+ saveg_read_pad();
+ door = Z_Malloc (sizeof(*door), PU_LEVEL, NULL);
+ saveg_read_vldoor_t(door);
+ door->sector->specialdata = door;
+ door->thinker.function.acp1 = (actionf_p1)T_VerticalDoor;
+ P_AddThinker (&door->thinker);
+ break;
+
+ case tc_floor:
+ saveg_read_pad();
+ floor = Z_Malloc (sizeof(*floor), PU_LEVEL, NULL);
+ saveg_read_floormove_t(floor);
+ floor->sector->specialdata = floor;
+ floor->thinker.function.acp1 = (actionf_p1)T_MoveFloor;
+ P_AddThinker (&floor->thinker);
+ break;
+
+ case tc_plat:
+ saveg_read_pad();
+ plat = Z_Malloc (sizeof(*plat), PU_LEVEL, NULL);
+ saveg_read_plat_t(plat);
+ plat->sector->specialdata = plat;
+
+ if (plat->thinker.function.acp1)
+ plat->thinker.function.acp1 = (actionf_p1)T_PlatRaise;
+
+ P_AddThinker (&plat->thinker);
+ P_AddActivePlat(plat);
+ break;
+
+ case tc_flash:
+ saveg_read_pad();
+ flash = Z_Malloc (sizeof(*flash), PU_LEVEL, NULL);
+ saveg_read_lightflash_t(flash);
+ flash->thinker.function.acp1 = (actionf_p1)T_LightFlash;
+ P_AddThinker (&flash->thinker);
+ break;
+
+ case tc_strobe:
+ saveg_read_pad();
+ strobe = Z_Malloc (sizeof(*strobe), PU_LEVEL, NULL);
+ saveg_read_strobe_t(strobe);
+ strobe->thinker.function.acp1 = (actionf_p1)T_StrobeFlash;
+ P_AddThinker (&strobe->thinker);
+ break;
+
+ case tc_glow:
+ saveg_read_pad();
+ glow = Z_Malloc (sizeof(*glow), PU_LEVEL, NULL);
+ saveg_read_glow_t(glow);
+ glow->thinker.function.acp1 = (actionf_p1)T_Glow;
+ P_AddThinker (&glow->thinker);
+ break;
+
+ default:
+ I_Error ("P_UnarchiveSpecials:Unknown tclass %i "
+ "in savegame",tclass);
+ }
+
+ }
+
+}
+
--- /dev/null
+++ b/src/doom/p_saveg.h
@@ -1,0 +1,69 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION:
+// Savegame I/O, archiving, persistence.
+//
+//-----------------------------------------------------------------------------
+
+
+#ifndef __P_SAVEG__
+#define __P_SAVEG__
+
+#include <stdio.h>
+
+// maximum size of a savegame description
+
+#define SAVESTRINGSIZE 24
+
+// temporary filename to use while saving.
+
+char *P_TempSaveGameFile(void);
+
+// filename to use for a savegame slot
+
+char *P_SaveGameFile(int slot);
+
+// Savegame file header read/write functions
+
+boolean P_ReadSaveGameHeader(void);
+void P_WriteSaveGameHeader(char *description);
+
+// Savegame end-of-file read/write functions
+
+boolean P_ReadSaveGameEOF(void);
+void P_WriteSaveGameEOF(void);
+
+// Persistent storage/archiving.
+// These are the load / save game routines.
+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);
+
+extern FILE *save_stream;
+
+
+#endif
--- /dev/null
+++ b/src/doom/p_setup.c
@@ -1,0 +1,753 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION:
+// Do all the WAD I/O, get map description,
+// set up initial state and misc. LUTs.
+//
+//-----------------------------------------------------------------------------
+
+
+
+#include <math.h>
+
+#include "z_zone.h"
+
+#include "deh_main.h"
+#include "i_swap.h"
+#include "m_bbox.h"
+
+#include "g_game.h"
+
+#include "i_system.h"
+#include "w_wad.h"
+
+#include "doomdef.h"
+#include "p_local.h"
+
+#include "s_sound.h"
+
+#include "doomstat.h"
+
+
+void P_SpawnMapThing (mapthing_t* mthing);
+
+
+//
+// MAP related Lookup tables.
+// Store VERTEXES, LINEDEFS, SIDEDEFS, etc.
+//
+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;
+
+
+// BLOCKMAP
+// Created from axis aligned bounding box
+// of the map, a rectangular array of
+// blocks of size ...
+// Used to speed up collision detection
+// by spatial subdivision in 2D.
+//
+// Blockmap size.
+int bmapwidth;
+int bmapheight; // size in mapblocks
+short* blockmap; // int for larger maps
+// offsets in blockmap are from here
+short* blockmaplump;
+// origin of block map
+fixed_t bmaporgx;
+fixed_t bmaporgy;
+// for thing chains
+mobj_t** blocklinks;
+
+
+// REJECT
+// For fast sight rejection.
+// Speeds up enemy AI by skipping detailed
+// LineOf Sight calculation.
+// Without special effect, this could be
+// used as a PVS lookup as well.
+//
+byte* rejectmatrix;
+
+
+// Maintain single and multi player starting spots.
+#define MAX_DEATHMATCH_STARTS 10
+
+mapthing_t deathmatchstarts[MAX_DEATHMATCH_STARTS];
+mapthing_t* deathmatch_p;
+mapthing_t playerstarts[MAXPLAYERS];
+
+
+
+
+
+//
+// P_LoadVertexes
+//
+void P_LoadVertexes (int lump)
+{
+ byte* data;
+ int i;
+ mapvertex_t* ml;
+ vertex_t* li;
+
+ // Determine number of lumps:
+ // total lump length / vertex record length.
+ numvertexes = W_LumpLength (lump) / sizeof(mapvertex_t);
+
+ // Allocate zone memory for buffer.
+ vertexes = Z_Malloc (numvertexes*sizeof(vertex_t),PU_LEVEL,0);
+
+ // Load data into cache.
+ data = W_CacheLumpNum (lump, PU_STATIC);
+
+ ml = (mapvertex_t *)data;
+ li = vertexes;
+
+ // Copy and convert vertex coordinates,
+ // internal representation as fixed.
+ for (i=0 ; i<numvertexes ; i++, li++, ml++)
+ {
+ li->x = SHORT(ml->x)<<FRACBITS;
+ li->y = SHORT(ml->y)<<FRACBITS;
+ }
+
+ // Free buffer memory.
+ W_ReleaseLumpNum(lump);
+}
+
+
+
+//
+// P_LoadSegs
+//
+void P_LoadSegs (int lump)
+{
+ byte* data;
+ int i;
+ mapseg_t* ml;
+ seg_t* li;
+ line_t* ldef;
+ int linedef;
+ int side;
+
+ numsegs = W_LumpLength (lump) / sizeof(mapseg_t);
+ segs = Z_Malloc (numsegs*sizeof(seg_t),PU_LEVEL,0);
+ memset (segs, 0, numsegs*sizeof(seg_t));
+ data = W_CacheLumpNum (lump,PU_STATIC);
+
+ ml = (mapseg_t *)data;
+ li = segs;
+ for (i=0 ; i<numsegs ; i++, li++, ml++)
+ {
+ li->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;
+ }
+
+ W_ReleaseLumpNum(lump);
+}
+
+
+//
+// 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 ; i<numsubsectors ; i++, ss++, ms++)
+ {
+ ss->numlines = SHORT(ms->numsegs);
+ ss->firstline = SHORT(ms->firstseg);
+ }
+
+ W_ReleaseLumpNum(lump);
+}
+
+
+
+//
+// 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 ; i<numsectors ; i++, ss++, ms++)
+ {
+ ss->floorheight = SHORT(ms->floorheight)<<FRACBITS;
+ ss->ceilingheight = SHORT(ms->ceilingheight)<<FRACBITS;
+ ss->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;
+ }
+
+ W_ReleaseLumpNum(lump);
+}
+
+
+//
+// P_LoadNodes
+//
+void P_LoadNodes (int lump)
+{
+ byte* data;
+ int i;
+ int j;
+ int 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 ; i<numnodes ; i++, no++, mn++)
+ {
+ no->x = SHORT(mn->x)<<FRACBITS;
+ no->y = SHORT(mn->y)<<FRACBITS;
+ no->dx = SHORT(mn->dx)<<FRACBITS;
+ no->dy = SHORT(mn->dy)<<FRACBITS;
+ for (j=0 ; j<2 ; j++)
+ {
+ no->children[j] = SHORT(mn->children[j]);
+ for (k=0 ; k<4 ; k++)
+ no->bbox[j][k] = SHORT(mn->bbox[j][k])<<FRACBITS;
+ }
+ }
+
+ W_ReleaseLumpNum(lump);
+}
+
+
+//
+// P_LoadThings
+//
+void P_LoadThings (int lump)
+{
+ byte *data;
+ int i;
+ mapthing_t *mt;
+ mapthing_t spawnthing;
+ int numthings;
+ boolean spawn;
+
+ data = W_CacheLumpNum (lump,PU_STATIC);
+ numthings = W_LumpLength (lump) / sizeof(mapthing_t);
+
+ mt = (mapthing_t *)data;
+ for (i=0 ; i<numthings ; i++, mt++)
+ {
+ spawn = true;
+
+ // Do not spawn cool, new monsters if !commercial
+ if (gamemode != commercial)
+ {
+ switch (SHORT(mt->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;
+ break;
+ }
+ }
+ if (spawn == false)
+ break;
+
+ // Do spawn all other stuff.
+ spawnthing.x = SHORT(mt->x);
+ spawnthing.y = SHORT(mt->y);
+ spawnthing.angle = SHORT(mt->angle);
+ spawnthing.type = SHORT(mt->type);
+ spawnthing.options = SHORT(mt->options);
+
+ P_SpawnMapThing(&spawnthing);
+ }
+
+ W_ReleaseLumpNum(lump);
+}
+
+
+//
+// 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;
+ vertex_t* 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 ; i<numlines ; i++, mld++, ld++)
+ {
+ ld->flags = 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;
+ }
+
+ W_ReleaseLumpNum(lump);
+}
+
+
+//
+// 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 ; i<numsides ; i++, msd++, sd++)
+ {
+ sd->textureoffset = SHORT(msd->textureoffset)<<FRACBITS;
+ sd->rowoffset = SHORT(msd->rowoffset)<<FRACBITS;
+ sd->toptexture = R_TextureNumForName(msd->toptexture);
+ sd->bottomtexture = R_TextureNumForName(msd->bottomtexture);
+ sd->midtexture = R_TextureNumForName(msd->midtexture);
+ sd->sector = §ors[SHORT(msd->sector)];
+ }
+
+ W_ReleaseLumpNum(lump);
+}
+
+
+//
+// P_LoadBlockMap
+//
+void P_LoadBlockMap (int lump)
+{
+ int i;
+ int count;
+ int lumplen;
+
+ lumplen = W_LumpLength(lump);
+ count = lumplen / 2;
+
+ blockmaplump = Z_Malloc(lumplen, PU_LEVEL, NULL);
+ W_ReadLump(lump, blockmaplump);
+ blockmap = blockmaplump + 4;
+
+ // Swap all short integers to native byte ordering.
+
+ for (i=0; i<count; i++)
+ {
+ blockmaplump[i] = SHORT(blockmaplump[i]);
+ }
+
+ // Read the header
+
+ bmaporgx = blockmaplump[0]<<FRACBITS;
+ bmaporgy = blockmaplump[1]<<FRACBITS;
+ bmapwidth = blockmaplump[2];
+ bmapheight = blockmaplump[3];
+
+ // Clear out mobj chains
+
+ count = sizeof(*blocklinks) * bmapwidth * bmapheight;
+ blocklinks = Z_Malloc(count, PU_LEVEL, 0);
+ memset(blocklinks, 0, count);
+}
+
+
+
+//
+// P_GroupLines
+// Builds sector line lists and subsector sector numbers.
+// Finds block bounding boxes for sectors.
+//
+void P_GroupLines (void)
+{
+ line_t** linebuffer;
+ int i;
+ int j;
+ int total;
+ line_t* li;
+ sector_t* sector;
+ subsector_t* ss;
+ seg_t* seg;
+ fixed_t bbox[4];
+ int block;
+
+ // look up sector number for each subsector
+ ss = subsectors;
+ for (i=0 ; i<numsubsectors ; i++, ss++)
+ {
+ seg = &segs[ss->firstline];
+ ss->sector = seg->sidedef->sector;
+ }
+
+ // count number of lines in each sector
+ li = lines;
+ total = 0;
+ for (i=0 ; i<numlines ; i++, li++)
+ {
+ total++;
+ li->frontsector->linecount++;
+
+ if (li->backsector && li->backsector != li->frontsector)
+ {
+ li->backsector->linecount++;
+ total++;
+ }
+ }
+
+ // build line tables for each sector
+ linebuffer = Z_Malloc (total*sizeof(line_t *), PU_LEVEL, 0);
+
+ for (i=0; i<numsectors; ++i)
+ {
+ // Assign the line buffer for this sector
+
+ sectors[i].lines = linebuffer;
+ linebuffer += sectors[i].linecount;
+
+ // Reset linecount to zero so in the next stage we can count
+ // lines into the list.
+
+ sectors[i].linecount = 0;
+ }
+
+ // Assign lines to sectors
+
+ for (i=0; i<numlines; ++i)
+ {
+ li = &lines[i];
+
+ if (li->frontsector != NULL)
+ {
+ sector = li->frontsector;
+
+ sector->lines[sector->linecount] = li;
+ ++sector->linecount;
+ }
+
+ if (li->backsector != NULL && li->frontsector != li->backsector)
+ {
+ sector = li->backsector;
+
+ sector->lines[sector->linecount] = li;
+ ++sector->linecount;
+ }
+ }
+
+ // Generate bounding boxes for sectors
+
+ sector = sectors;
+ for (i=0 ; i<numsectors ; i++, sector++)
+ {
+ M_ClearBox (bbox);
+
+ for (j=0 ; j<sector->linecount; j++)
+ {
+ li = sector->lines[j];
+
+ M_AddToBox (bbox, li->v1->x, li->v1->y);
+ M_AddToBox (bbox, li->v2->x, li->v2->y);
+ }
+
+ // 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 ; i<MAXPLAYERS ; i++)
+ {
+ players[i].killcount = players[i].secretcount
+ = players[i].itemcount = 0;
+ }
+
+ // Initial height of PointOfView
+ // will be set by player think.
+ players[consoleplayer].viewz = 1;
+
+ // Make sure all sounds are stopped before Z_FreeTags.
+ S_Start ();
+
+
+#if 0 // UNUSED
+ if (debugfile)
+ {
+ Z_FreeTags (PU_LEVEL, INT_MAX);
+ Z_FileDumpHeap (debugfile);
+ }
+ else
+#endif
+ Z_FreeTags (PU_LEVEL, PU_PURGELEVEL-1);
+
+
+ // UNUSED W_Profile ();
+ P_InitThinkers ();
+
+ // find map name
+ if ( gamemode == commercial)
+ {
+ if (map<10)
+ sprintf (lumpname, DEH_String("map0%i"), map);
+ else
+ sprintf (lumpname, DEH_String("map%i"), map);
+ }
+ else
+ {
+ lumpname[0] = 'E';
+ lumpname[1] = '0' + episode;
+ lumpname[2] = 'M';
+ lumpname[3] = '0' + map;
+ lumpname[4] = 0;
+ }
+
+ lumpnum = W_GetNumForName (lumpname);
+
+ leveltime = 0;
+
+ // note: most of this ordering is important
+ P_LoadBlockMap (lumpnum+ML_BLOCKMAP);
+ P_LoadVertexes (lumpnum+ML_VERTEXES);
+ P_LoadSectors (lumpnum+ML_SECTORS);
+ P_LoadSideDefs (lumpnum+ML_SIDEDEFS);
+
+ P_LoadLineDefs (lumpnum+ML_LINEDEFS);
+ P_LoadSubsectors (lumpnum+ML_SSECTORS);
+ P_LoadNodes (lumpnum+ML_NODES);
+ P_LoadSegs (lumpnum+ML_SEGS);
+
+ rejectmatrix = W_CacheLumpNum (lumpnum+ML_REJECT,PU_LEVEL);
+ P_GroupLines ();
+
+ bodyqueslot = 0;
+ deathmatch_p = deathmatchstarts;
+ P_LoadThings (lumpnum+ML_THINGS);
+
+ // if deathmatch, randomly spawn the active players
+ if (deathmatch)
+ {
+ for (i=0 ; i<MAXPLAYERS ; i++)
+ if (playeringame[i])
+ {
+ players[i].mo = NULL;
+ G_DeathMatchSpawnPlayer (i);
+ }
+
+ }
+
+ // clear special respawning que
+ iquehead = iquetail = 0;
+
+ // set up world state
+ P_SpawnSpecials ();
+
+ // build subsector connect matrix
+ // UNUSED P_ConnectSubsectors ();
+
+ // preload graphics
+ if (precache)
+ R_PrecacheLevel ();
+
+ //printf ("free memory: 0x%x\n", Z_FreeMemory());
+
+}
+
+
+
+//
+// P_Init
+//
+void P_Init (void)
+{
+ P_InitSwitchList ();
+ P_InitPicAnims ();
+ R_InitSprites (sprnames);
+}
+
+
+
--- /dev/null
+++ b/src/doom/p_setup.h
@@ -1,0 +1,45 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION:
+// Setup a game, startup stuff.
+//
+//-----------------------------------------------------------------------------
+
+
+#ifndef __P_SETUP__
+#define __P_SETUP__
+
+
+
+
+// NOT called by W_Ticker. Fixme.
+void
+P_SetupLevel
+( int episode,
+ int map,
+ int playermask,
+ skill_t skill);
+
+// Called by startup code.
+void P_Init (void);
+
+#endif
--- /dev/null
+++ b/src/doom/p_sight.c
@@ -1,0 +1,350 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION:
+// LineOfSight/Visibility checks, uses REJECT Lookup Table.
+//
+//-----------------------------------------------------------------------------
+
+
+
+#include "doomdef.h"
+
+#include "i_system.h"
+#include "p_local.h"
+
+// State.
+#include "r_state.h"
+
+//
+// P_CheckSight
+//
+fixed_t sightzstart; // eye z of looker
+fixed_t topslope;
+fixed_t bottomslope; // slopes to top and bottom of target
+
+divline_t strace; // from t1 to t2
+fixed_t t2x;
+fixed_t t2y;
+
+int sightcounts[2];
+
+
+//
+// P_DivlineSide
+// Returns side 0 (front), 1 (back), or 2 (on).
+//
+int
+P_DivlineSide
+( fixed_t x,
+ fixed_t y,
+ divline_t* node )
+{
+ fixed_t dx;
+ fixed_t dy;
+ fixed_t left;
+ fixed_t right;
+
+ if (!node->dx)
+ {
+ 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;
+ fixed_t num;
+ fixed_t 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 successfully.
+//
+boolean P_CrossSubsector (int num)
+{
+ seg_t* seg;
+ line_t* line;
+ int s1;
+ int s2;
+ int count;
+ subsector_t* sub;
+ sector_t* front;
+ sector_t* back;
+ fixed_t opentop;
+ fixed_t openbottom;
+ divline_t divl;
+ vertex_t* v1;
+ vertex_t* v2;
+ fixed_t frac;
+ fixed_t 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;
+
+ // allready checked other side?
+ if (line->validcount == validcount)
+ continue;
+
+ 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);
+
+ // line isn't crossed?
+ if (s1 == s2)
+ continue;
+
+ 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);
+
+ // line isn't crossed?
+ if (s1 == s2)
+ continue;
+
+ // stop because it is not two sided anyway
+ // might do this after updating validcount?
+ if ( !(line->flags & ML_TWOSIDED) )
+ return false;
+
+ // crosses a two sided line
+ front = seg->frontsector;
+ back = seg->backsector;
+
+ // no wall to block sight with?
+ if (front->floorheight == back->floorheight
+ && front->ceilingheight == back->ceilingheight)
+ continue;
+
+ // possible occluder
+ // because of ceiling height differences
+ if (front->ceilingheight < back->ceilingheight)
+ opentop = front->ceilingheight;
+ else
+ opentop = back->ceilingheight;
+
+ // because of ceiling height differences
+ if (front->floorheight > back->floorheight)
+ openbottom = front->floorheight;
+ else
+ openbottom = back->floorheight;
+
+ // quick test for totally closed doors
+ if (openbottom >= opentop)
+ 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
+ }
+ // passed the subsector ok
+ return true;
+}
+
+
+
+//
+// P_CrossBSPNode
+// Returns true
+// if strace crosses the given node successfully.
+//
+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))
+ {
+ // the line doesn't touch the other side
+ return true;
+ }
+
+ // 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.
+// Uses REJECT.
+//
+boolean
+P_CheckSight
+( mobj_t* t1,
+ mobj_t* t2 )
+{
+ int s1;
+ int s2;
+ int pnum;
+ int bytenum;
+ int bitnum;
+
+ // First check for trivial rejection.
+
+ // Determine subsector entries in REJECT table.
+ s1 = (t1->subsector->sector - sectors);
+ s2 = (t2->subsector->sector - sectors);
+ pnum = s1*numsectors + s2;
+ bytenum = pnum>>3;
+ bitnum = 1 << (pnum&7);
+
+ // Check in REJECT table.
+ if (rejectmatrix[bytenum]&bitnum)
+ {
+ sightcounts[0]++;
+
+ // can't possibly be connected
+ return false;
+ }
+
+ // An unobstructed LOS is possible.
+ // Now 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;
+
+ // the head node is the last node output
+ return P_CrossBSPNode (numnodes-1);
+}
+
+
--- /dev/null
+++ b/src/doom/p_spec.c
@@ -1,0 +1,1372 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION:
+// Implements special effects:
+// Texture animation, height or lighting changes
+// according to adjacent sectors, respective
+// utility functions, etc.
+// Line Tag handling. Line and Sector triggers.
+//
+//-----------------------------------------------------------------------------
+
+
+#include <stdlib.h>
+
+#include "doomdef.h"
+#include "doomstat.h"
+
+#include "deh_main.h"
+#include "i_system.h"
+#include "z_zone.h"
+#include "m_argv.h"
+#include "m_random.h"
+#include "w_wad.h"
+
+#include "r_local.h"
+#include "p_local.h"
+
+#include "g_game.h"
+
+#include "s_sound.h"
+
+// State.
+#include "r_state.h"
+
+// Data.
+#include "sounds.h"
+
+
+//
+// Animating textures and planes
+// There is another anim_t used in wi_stuff, unrelated.
+//
+typedef struct
+{
+ boolean istexture;
+ int picnum;
+ int basepic;
+ int numpics;
+ int speed;
+
+} anim_t;
+
+//
+// source animation definition
+//
+typedef struct
+{
+ int istexture; // if false, it is a flat
+ char endname[9];
+ char startname[9];
+ int speed;
+} animdef_t;
+
+
+
+#define MAXANIMS 32
+
+extern anim_t anims[MAXANIMS];
+extern anim_t* lastanim;
+
+//
+// P_InitPicAnims
+//
+
+// Floor/ceiling animation sequences,
+// defined by first and last frame,
+// i.e. the flat (64x64 tile) name to
+// be used.
+// The full animation sequence is given
+// using all the flats between the start
+// and end entry, in the order found in
+// the WAD file.
+//
+animdef_t animdefs[] =
+{
+ {false, "NUKAGE3", "NUKAGE1", 8},
+ {false, "FWATER4", "FWATER1", 8},
+ {false, "SWATER4", "SWATER1", 8},
+ {false, "LAVA4", "LAVA1", 8},
+ {false, "BLOOD3", "BLOOD1", 8},
+
+ // DOOM II flat animations.
+ {false, "RROCK08", "RROCK05", 8},
+ {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, "", "", 0},
+};
+
+anim_t anims[MAXANIMS];
+anim_t* lastanim;
+
+
+//
+// Animating line specials
+//
+#define MAXLINEANIMS 64
+
+extern short numlinespecials;
+extern line_t* linespeciallist[MAXLINEANIMS];
+
+
+
+void P_InitPicAnims (void)
+{
+ int i;
+
+
+ // Init animation
+ lastanim = anims;
+ for (i=0 ; animdefs[i].istexture != -1 ; i++)
+ {
+ char *startname, *endname;
+
+ startname = DEH_String(animdefs[i].startname);
+ endname = DEH_String(animdefs[i].endname);
+
+ if (animdefs[i].istexture)
+ {
+ // different episode ?
+ if (R_CheckTextureNumForName(startname) == -1)
+ continue;
+
+ lastanim->picnum = R_TextureNumForName(endname);
+ lastanim->basepic = R_TextureNumForName(startname);
+ }
+ else
+ {
+ if (W_CheckNumForName(startname) == -1)
+ continue;
+
+ lastanim->picnum = R_FlatNumForName(endname);
+ lastanim->basepic = R_FlatNumForName(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",
+ startname, endname);
+
+ lastanim->speed = animdefs[i].speed;
+ lastanim++;
+ }
+
+}
+
+
+
+//
+// UTILITIES
+//
+
+
+
+//
+// getSide()
+// 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] ];
+}
+
+
+//
+// getSector()
+// 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;
+}
+
+
+//
+// twoSided()
+// Given the sector number and the line number,
+// it 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;
+}
+
+
+
+
+//
+// getNextSector()
+// 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;
+}
+
+
+
+//
+// P_FindLowestFloorSurrounding()
+// 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;
+}
+
+
+
+//
+// P_FindHighestFloorSurrounding()
+// 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;
+}
+
+
+
+//
+// P_FindNextHighestFloor
+// FIND NEXT HIGHEST FLOOR IN SURROUNDING SECTORS
+// Note: this should be doable w/o a fixed array.
+
+// Thanks to entryway for the Vanilla overflow emulation.
+
+// 20 adjoining sectors max!
+#define MAX_ADJOINING_SECTORS 20
+
+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[MAX_ADJOINING_SECTORS + 2];
+
+ for (i=0, h=0; i < sec->linecount; i++)
+ {
+ check = sec->lines[i];
+ other = getNextSector(check,sec);
+
+ if (!other)
+ continue;
+
+ if (other->floorheight > height)
+ {
+ // Emulation of memory (stack) overflow
+ if (h == MAX_ADJOINING_SECTORS + 1)
+ {
+ height = other->floorheight;
+ }
+ else if (h == MAX_ADJOINING_SECTORS + 2)
+ {
+ // Fatal overflow: game crashes at 22 textures
+ I_Error("Sector with more than 22 adjoining sectors. "
+ "Vanilla will crash here");
+ }
+
+ heightlist[h++] = other->floorheight;
+ }
+ }
+
+ // Find lowest height in list
+ if (!h)
+ {
+ return currentheight;
+ }
+
+ min = heightlist[0];
+
+ // Range checking?
+ 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 = INT_MAX;
+
+ 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;i<numsectors;i++)
+ if (sectors[i].tag == line->tag)
+ 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;
+ break;
+
+ 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;
+ }
+
+
+ // Note: could use some const's here.
+ switch (line->special)
+ {
+ // TRIGGERS.
+ // All from here to RETRIGGERS.
+ 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. All from here till end.
+ 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;
+
+ // Falling, not all the way down yet?
+ if (player->mo->z != sector->floorheight)
+ return;
+
+ // Has hitten ground.
+ 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);
+ break;
+ };
+}
+
+
+
+
+//
+// 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 GLOBALLY
+ for (anim = anims ; anim < lastanim ; anim++)
+ {
+ for (i=anim->basepic ; i<anim->basepic+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(&buttonlist[i].soundorg,sfx_swtchn);
+ memset(&buttonlist[i],0,sizeof(button_t));
+ }
+ }
+
+}
+
+
+
+//
+// Special Stuff that can not 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.acp1 = (actionf_p1) 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.acp1 = (actionf_p1) 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];
+
+
+// Parses command line parameters.
+void P_SpawnSpecials (void)
+{
+ sector_t* sector;
+ int i;
+ int episode;
+
+ episode = 1;
+ if (W_CheckNumForName(DEH_String("texture2")) >= 0)
+ episode = 2;
+
+
+ // See if -TIMER was specified.
+
+ if (timelimit > 0)
+ {
+ levelTimer = true;
+ levelTimeCount = timelimit * 60 * TICRATE;
+ }
+ else
+ {
+ levelTimer = false;
+ }
+
+ // Init special SECTORs.
+ sector = sectors;
+ for (i=0 ; i<numsectors ; i++, sector++)
+ {
+ if (!sector->special)
+ 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));
+
+ // UNUSED: no horizonal sliders.
+ // P_InitSlidingDoorFrames();
+}
--- /dev/null
+++ b/src/doom/p_spec.h
@@ -1,0 +1,645 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION: none
+// Implements special effects:
+// Texture animation, height or lighting changes
+// according to adjacent sectors, respective
+// utility functions, etc.
+//
+//-----------------------------------------------------------------------------
+
+
+#ifndef __P_SPEC__
+#define __P_SPEC__
+
+
+//
+// End-level timer (-TIMER option)
+//
+extern boolean levelTimer;
+extern int levelTimeCount;
+
+
+// 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;
+ degenmobj_t *soundorg;
+
+} button_t;
+
+
+
+
+ // max # of wall switches in a level
+#define MAXSWITCHES 50
+
+ // 4 players, 4 buttons each at once, max.
+#define MAXBUTTONS 16
+
+ // 1 second, in ticks.
+#define BUTTONTIME 35
+
+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;
+
+ // 1 = up, 0 = waiting at top, -1 = down
+ int direction;
+
+ // tics to wait at the top
+ int topwait;
+ // (keep in case a door going down is reset)
+ // when it reaches 0, start going down
+ int topcountdown;
+
+} 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 // UNUSED
+//
+// 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;
+
+
+
+// how many frames of animation
+#define SNUMFRAMES 4
+
+#define SDOORWAIT 35*3
+#define SWAITTICS 4
+
+// how many diff. types of anims
+#define MAXSLIDEDOORS 5
+
+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;
+ fixed_t topheight;
+ fixed_t speed;
+ boolean crush;
+
+ // 1 = up, 0 = waiting, -1 = down
+ int direction;
+
+ // ID
+ int tag;
+ 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
+{
+ // lower floor to highest surrounding floor
+ lowerFloor,
+
+ // lower floor to lowest surrounding floor
+ lowerFloorToLowest,
+
+ // lower floor to highest surrounding floor VERY FAST
+ turboLower,
+
+ // raise floor to lowest surrounding CEILING
+ raiseFloor,
+
+ // raise floor to next highest surrounding floor
+ raiseFloorToNearest,
+
+ // raise floor to shortest height texture around it
+ raiseToTexture,
+
+ // lower floor to lowest surrounding floor
+ // and change floorpic
+ lowerAndChange,
+
+ raiseFloor24,
+ raiseFloor24AndChange,
+ raiseFloorCrush,
+
+ // raise to next highest floor, turbo-speed
+ raiseFloorTurbo,
+ 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 );
+
+#endif
--- /dev/null
+++ b/src/doom/p_switch.c
@@ -1,0 +1,656 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+//
+// DESCRIPTION:
+// Switches, buttons. Two-state animation. Exits.
+//
+//-----------------------------------------------------------------------------
+
+
+
+#include "i_system.h"
+#include "deh_main.h"
+#include "doomdef.h"
+#include "p_local.h"
+
+#include "g_game.h"
+
+#include "s_sound.h"
+
+// Data.
+#include "sounds.h"
+
+// State.
+#include "doomstat.h"
+#include "r_state.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 (gamemode == registered || gamemode == retail)
+ episode = 2;
+ else
+ if ( gamemode == 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 // UNUSED - debug?
+ 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(DEH_String(alphSwitchList[i].name1));
+ switchlist[index++] = R_TextureNumForName(DEH_String(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 = &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;
+
+ // EXIT SWITCH?
+ if (line->special == 11)
+ 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 )
+{
+
+ // Err...
+ // Use the back sides of VERY SPECIAL lines...
+ if (side)
+ {
+ switch(line->special)
+ {
+ case 124:
+ // Sliding door open&close
+ // UNUSED?
+ break;
+
+ default:
+ return false;
+ break;
+ }
+ }
+
+
+ // Switches that other things can activate.
+ if (!thing->player)
+ {
+ // never open secret doors
+ if (line->flags & ML_SECRET)
+ return false;
+
+ switch(line->special)
+ {
+ case 1: // MANUAL DOOR RAISE
+ case 32: // MANUAL BLUE
+ case 33: // MANUAL RED
+ case 34: // MANUAL YELLOW
+ break;
+
+ default:
+ return false;
+ break;
+ }
+ }
+
+
+ // 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;
+
+ //UNUSED - Door Slide Open&Close
+ // case 124:
+ // 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;
+}
+
--- /dev/null
+++ b/src/doom/p_telept.c
@@ -1,0 +1,142 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION:
+// Teleportation.
+//
+//-----------------------------------------------------------------------------
+
+
+
+
+#include "doomdef.h"
+#include "doomstat.h"
+
+#include "s_sound.h"
+
+#include "p_local.h"
+
+
+// Data.
+#include "sounds.h"
+
+// State.
+#include "r_state.h"
+
+
+
+//
+// TELEPORTATION
+//
+int
+EV_Teleport
+( line_t* line,
+ int side,
+ mobj_t* thing )
+{
+ int i;
+ int tag;
+ mobj_t* m;
+ mobj_t* fog;
+ unsigned an;
+ thinker_t* thinker;
+ sector_t* sector;
+ fixed_t oldx;
+ fixed_t oldy;
+ fixed_t oldz;
+
+ // don't teleport missiles
+ if (thing->flags & MF_MISSILE)
+ return 0;
+
+ // Don't teleport if hit back of line,
+ // so you can get out of teleporter.
+ if (side == 1)
+ return 0;
+
+
+ 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)
+ {
+ // not a mobj
+ if (thinker->function.acp1 != (actionf_p1)P_MobjThinker)
+ continue;
+
+ m = (mobj_t *)thinker;
+
+ // not a teleportman
+ if (m->type != MT_TELEPORTMAN )
+ continue;
+
+ sector = m->subsector->sector;
+ // wrong sector
+ if (sector-sectors != i )
+ continue;
+
+ oldx = thing->x;
+ oldy = thing->y;
+ oldz = thing->z;
+
+ if (!P_TeleportMove (thing, m->x, m->y))
+ return 0;
+
+ // fraggle: this was changed in final doom,
+ // problem between normal doom2 1.9 and final doom
+ //
+ // Note that although chex.exe is based on Final Doom,
+ // it does not have this quirk.
+
+ if (gameversion < exe_final || gameversion == exe_chex)
+ 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);
+
+ // emit sound, where?
+ S_StartSound (fog, sfx_telept);
+
+ // don't move for a bit
+ if (thing->player)
+ thing->reactiontime = 18;
+
+ thing->angle = m->angle;
+ thing->momx = thing->momy = thing->momz = 0;
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+
--- /dev/null
+++ b/src/doom/p_tick.c
@@ -1,0 +1,159 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION:
+// Archiving: SaveGame I/O.
+// Thinker, Ticker.
+//
+//-----------------------------------------------------------------------------
+
+
+#include "z_zone.h"
+#include "p_local.h"
+
+#include "doomstat.h"
+
+
+int leveltime;
+
+//
+// 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.
+//
+
+
+
+// Both the head and tail of the thinker list.
+thinker_t thinkercap;
+
+
+//
+// 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)
+{
+ // FIXME: NOP.
+ thinker->function.acv = (actionf_v)(-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.acv == (actionf_v)(-1) )
+ {
+ // time to remove it
+ currentthinker->next->prev = currentthinker->prev;
+ currentthinker->prev->next = currentthinker->next;
+ Z_Free (currentthinker);
+ }
+ else
+ {
+ if (currentthinker->function.acp1)
+ currentthinker->function.acp1 (currentthinker);
+ }
+ currentthinker = currentthinker->next;
+ }
+}
+
+
+
+//
+// P_Ticker
+//
+
+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<MAXPLAYERS ; i++)
+ if (playeringame[i])
+ P_PlayerThink (&players[i]);
+
+ P_RunThinkers ();
+ P_UpdateSpecials ();
+ P_RespawnSpecials ();
+
+ // for par times
+ leveltime++;
+}
--- /dev/null
+++ b/src/doom/p_tick.h
@@ -1,0 +1,41 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION:
+// ?
+//
+//-----------------------------------------------------------------------------
+
+
+#ifndef __P_TICK__
+#define __P_TICK__
+
+
+
+
+// Called by C_Ticker,
+// can call G_PlayerExited.
+// Carries out all thinking of monsters and players.
+void P_Ticker (void);
+
+
+
+#endif
--- /dev/null
+++ b/src/doom/p_user.c
@@ -1,0 +1,387 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION:
+// Player related stuff.
+// Bobbing POV/weapon, movement.
+// Pending weapon.
+//
+//-----------------------------------------------------------------------------
+
+
+
+
+#include "doomdef.h"
+#include "d_event.h"
+
+#include "p_local.h"
+
+#include "doomstat.h"
+
+
+
+// Index of the special effects (INVUL inverse) map.
+#define INVERSECOLORMAP 32
+
+
+//
+// Movement.
+//
+
+// 16 pixels of bob
+#define MAXBOB 0x100000
+
+boolean onground;
+
+
+//
+// P_Thrust
+// Moves the given origin along a given angle.
+//
+void
+P_Thrust
+( player_t* player,
+ angle_t angle,
+ fixed_t move )
+{
+ angle >>= 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
+ // Note: a LUT allows for effects
+ // like a ramp with low health.
+ 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);
+
+ // Do not 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
+// Fall on your face when dying.
+// Decrease POV height to floor height.
+//
+#define ANG5 (ANG90/18)
+
+void P_DeathThink (player_t* player)
+{
+ angle_t angle;
+ angle_t 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.
+
+ // A special event has no other buttons.
+ if (cmd->buttons & BT_SPECIAL)
+ cmd->buttons = 0;
+
+ if (cmd->buttons & BT_CHANGE)
+ {
+ // The actual changing of the weapon is done
+ // when the weapon psprite can do it
+ // (read: 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 ( (gamemode == commercial)
+ && newweapon == wp_shotgun
+ && player->weaponowned[wp_supershotgun]
+ && player->readyweapon != wp_supershotgun)
+ {
+ newweapon = wp_supershotgun;
+ }
+
+
+ if (player->weaponowned[newweapon]
+ && newweapon != player->readyweapon)
+ {
+ // Do not go to plasma or BFG in shareware,
+ // even if cheated.
+ if ((newweapon != wp_plasma
+ && newweapon != wp_bfg)
+ || (gamemode != 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, time dependend power ups.
+
+ // Strength counts up to diminish fade.
+ if (player->powers[pw_strength])
+ player->powers[pw_strength]++;
+
+ 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--;
+
+
+ // Handling 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) )
+ {
+ // almost full bright
+ player->fixedcolormap = 1;
+ }
+ else
+ player->fixedcolormap = 0;
+ }
+ else
+ player->fixedcolormap = 0;
+}
+
+
--- /dev/null
+++ b/src/doom/r_bsp.c
@@ -1,0 +1,581 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION:
+// BSP traversal, handling of LineSegs for rendering.
+//
+//-----------------------------------------------------------------------------
+
+
+
+
+#include "doomdef.h"
+
+#include "m_bbox.h"
+
+#include "i_system.h"
+
+#include "r_main.h"
+#include "r_plane.h"
+#include "r_things.h"
+
+// State.
+#include "doomstat.h"
+#include "r_state.h"
+
+//#include "r_local.h"
+
+
+
+seg_t* curline;
+side_t* sidedef;
+line_t* linedef;
+sector_t* frontsector;
+sector_t* backsector;
+
+drawseg_t drawsegs[MAXDRAWSEGS];
+drawseg_t* 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;
+ int last;
+
+} cliprange_t;
+
+
+#define MAXSEGS 32
+
+// newend is one past the last valid seg
+cliprange_t* newend;
+cliprange_t solidsegs[MAXSEGS];
+
+
+
+
+//
+// R_ClipSolidWallSegment
+// Does handle solid walls,
+// e.g. single sided LineDefs (middle texture)
+// that entirely block the view.
+//
+void
+R_ClipSolidWallSegment
+( int first,
+ int last )
+{
+ cliprange_t* next;
+ 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),
+ // 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);
+ // Now adjust the clip size.
+ start->first = first;
+ }
+
+ // Bottom contained in start?
+ if (last <= start->last)
+ return;
+
+ 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.
+ // Adjust the clip size.
+ start->last = next->last;
+ goto crunch;
+ }
+ }
+
+ // There is a fragment after *next.
+ R_StoreWallRange (next->last + 1, last);
+ // Adjust the clip size.
+ start->last = last;
+
+ // Remove start+1 to next from the clip list,
+ // because start now covers their area.
+ crunch:
+ if (next == start)
+ {
+ // Post just extended past the bottom of one post.
+ return;
+ }
+
+
+ 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.
+// Does handle windows,
+// e.g. LineDefs with upper and lower texture.
+//
+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);
+ }
+
+ // Bottom contained in start?
+ if (last <= start->last)
+ return;
+
+ 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;
+ int x2;
+ angle_t angle1;
+ angle_t angle2;
+ angle_t span;
+ angle_t tspan;
+
+ 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;
+
+ // Back side? I.e. backface culling?
+ if (span >= ANG180)
+ return;
+
+ // Global angle needed by segcalc.
+ rw_angle1 = angle1;
+ angle1 -= viewangle;
+ angle2 -= viewangle;
+
+ tspan = angle1 + clipangle;
+ if (tspan > 2*clipangle)
+ {
+ tspan -= 2*clipangle;
+
+ // Totally off the left edge?
+ if (tspan >= span)
+ return;
+
+ angle1 = clipangle;
+ }
+ tspan = clipangle - angle2;
+ if (tspan > 2*clipangle)
+ {
+ tspan -= 2*clipangle;
+
+ // Totally off the left edge?
+ if (tspan >= span)
+ return;
+ 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];
+
+ // Does not cross a pixel?
+ if (x1 == x2)
+ return;
+
+ backsector = line->backsector;
+
+ // Single sided line?
+ if (!backsector)
+ goto clipsolid;
+
+ // Closed door.
+ if (backsector->ceilingheight <= frontsector->floorheight
+ || backsector->floorheight >= frontsector->ceilingheight)
+ goto clipsolid;
+
+ // Window.
+ if (backsector->ceilingheight != frontsector->ceilingheight
+ || backsector->floorheight != frontsector->floorheight)
+ goto clippass;
+
+ // Reject empty lines used for triggers
+ // and special events.
+ // Identical floor and ceiling on both sides,
+ // identical light levels on both sides,
+ // and no middle texture.
+ 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
+// Checks BSP node/subtree bounding box.
+// 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;
+ int boxy;
+ int boxpos;
+
+ fixed_t x1;
+ fixed_t y1;
+ fixed_t x2;
+ fixed_t y2;
+
+ angle_t angle1;
+ angle_t angle2;
+ angle_t span;
+ angle_t tspan;
+
+ cliprange_t* start;
+
+ int sx1;
+ int sx2;
+
+ // 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]];
+
+ // check clip list for an open space
+ angle1 = R_PointToAngle (x1, y1) - viewangle;
+ angle2 = R_PointToAngle (x2, y2) - viewangle;
+
+ span = angle1 - angle2;
+
+ // Sitting on a line?
+ if (span >= ANG180)
+ return true;
+
+ tspan = angle1 + clipangle;
+
+ if (tspan > 2*clipangle)
+ {
+ tspan -= 2*clipangle;
+
+ // Totally off the left edge?
+ if (tspan >= span)
+ return false;
+
+ angle1 = clipangle;
+ }
+ tspan = clipangle - angle2;
+ if (tspan > 2*clipangle)
+ {
+ tspan -= 2*clipangle;
+
+ // Totally off the left edge?
+ if (tspan >= span)
+ return false;
+
+ 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];
+
+ // Does not cross a pixel.
+ if (sx1 == sx2)
+ return false;
+ sx2--;
+
+ start = solidsegs;
+ while (start->last < sx2)
+ start++;
+
+ if (sx1 >= start->first
+ && sx2 <= start->last)
+ {
+ // The clippost contains the new span.
+ return false;
+ }
+
+ return true;
+}
+
+
+
+//
+// R_Subsector
+// Determine floor/ceiling planes.
+// Add sprites of things in sector.
+// Draw one or more line 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
+// Renders all subsectors below a given node,
+// traversing subtree recursively.
+// Just call with BSP root.
+void R_RenderBSPNode (int bspnum)
+{
+ node_t* bsp;
+ int side;
+
+ // Found a subsector?
+ if (bspnum & NF_SUBSECTOR)
+ {
+ if (bspnum == -1)
+ R_Subsector (0);
+ else
+ R_Subsector (bspnum&(~NF_SUBSECTOR));
+ return;
+ }
+
+ bsp = &nodes[bspnum];
+
+ // Decide which side the view point is on.
+ side = R_PointOnSide (viewx, viewy, bsp);
+
+ // Recursively divide front space.
+ R_RenderBSPNode (bsp->children[side]);
+
+ // Possibly divide back space.
+ if (R_CheckBBox (bsp->bbox[side^1]))
+ R_RenderBSPNode (bsp->children[side^1]);
+}
+
+
--- /dev/null
+++ b/src/doom/r_bsp.h
@@ -1,0 +1,69 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION:
+// Refresh module, BSP traversal and handling.
+//
+//-----------------------------------------------------------------------------
+
+
+#ifndef __R_BSP__
+#define __R_BSP__
+
+
+
+extern seg_t* curline;
+extern side_t* sidedef;
+extern line_t* linedef;
+extern sector_t* frontsector;
+extern sector_t* backsector;
+
+extern int rw_x;
+extern int rw_stopx;
+
+extern boolean segtextured;
+
+// false if the back side is the same plane
+extern boolean markfloor;
+extern boolean markceiling;
+
+extern boolean skymap;
+
+extern drawseg_t drawsegs[MAXDRAWSEGS];
+extern drawseg_t* ds_p;
+
+extern lighttable_t** hscalelight;
+extern lighttable_t** vscalelight;
+extern lighttable_t** dscalelight;
+
+
+typedef void (*drawfunc_t) (int start, int stop);
+
+
+// BSP?
+void R_ClearClipSegs (void);
+void R_ClearDrawSegs (void);
+
+
+void R_RenderBSPNode (int bspnum);
+
+
+#endif
--- /dev/null
+++ b/src/doom/r_data.c
@@ -1,0 +1,909 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION:
+// Preparation of data for rendering,
+// generation of lookups, caching, retrieval by name.
+//
+//-----------------------------------------------------------------------------
+
+
+
+#include "deh_main.h"
+#include "i_swap.h"
+#include "i_system.h"
+#include "z_zone.h"
+
+
+#include "w_wad.h"
+
+#include "doomdef.h"
+#include "r_local.h"
+#include "p_local.h"
+
+#include "doomstat.h"
+#include "r_sky.h"
+
+
+#include "r_data.h"
+
+//
+// Graphics.
+// DOOM graphics for walls and sprites
+// is stored in vertical runs of opaque pixels (posts).
+// A column is composed of zero or more posts,
+// a patch or sprite is composed of zero or more columns.
+//
+
+
+
+//
+// Texture definition.
+// Each texture is composed of one or more patches,
+// with patches being lumps stored in the WAD.
+// The lumps are referenced by number, and patched
+// into the rectangular texture space using origin
+// and possibly other attributes.
+//
+typedef struct
+{
+ short originx;
+ short originy;
+ short patch;
+ short stepdir;
+ short colormap;
+} PACKEDATTR mappatch_t;
+
+
+//
+// Texture definition.
+// A DOOM wall texture is a list of patches
+// which are to be combined in a predefined order.
+//
+typedef struct
+{
+ char name[8];
+ int masked;
+ short width;
+ short height;
+ int obsolete;
+ short patchcount;
+ mappatch_t patches[1];
+} PACKEDATTR maptexture_t;
+
+
+// A single patch from a texture definition,
+// basically a rectangular area within
+// the texture rectangle.
+typedef struct
+{
+ // Block origin (allways UL),
+ // which has allready accounted
+ // for the internal origin of the patch.
+ short originx;
+ short originy;
+ 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 texture_s texture_t;
+
+struct texture_s
+{
+ // Keep name for switch changing, etc.
+ char name[8];
+ short width;
+ short height;
+
+ // Index in textures list
+
+ int index;
+
+ // Next in hash table chain
+
+ texture_t *next;
+
+ // All the patches[patchcount]
+ // are drawn back to front into the cached texture.
+ short patchcount;
+ texpatch_t patches[1];
+};
+
+
+
+int firstflat;
+int lastflat;
+int numflats;
+
+int firstpatch;
+int lastpatch;
+int numpatches;
+
+int firstspritelump;
+int lastspritelump;
+int numspritelumps;
+
+int numtextures;
+texture_t** textures;
+texture_t** textures_hashtable;
+
+
+int* texturewidthmask;
+// needed for texture pegging
+fixed_t* textureheight;
+int* texturecompositesize;
+short** texturecolumnlump;
+unsigned short** texturecolumnofs;
+byte** texturecomposite;
+
+// for global animation
+int* flattranslation;
+int* texturetranslation;
+
+// needed for pre rendering
+fixed_t* spritewidth;
+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;
+ int position;
+ byte* source;
+ byte* 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
+// Using the texture definition,
+// the composite texture is created from the patches,
+// and each column is cached.
+//
+void R_GenerateComposite (int texnum)
+{
+ byte* block;
+ texture_t* texture;
+ texpatch_t* patch;
+ patch_t* realpatch;
+ int x;
+ int x1;
+ int 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;
+ i<texture->patchcount;
+ 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<x2 ; x++)
+ {
+ // Column does not have multiple patches?
+ if (collump[x] >= 0)
+ continue;
+
+ 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 in column cache,
+ // it is purgable from zone memory.
+ Z_ChangeTag (block, PU_CACHE);
+}
+
+
+
+//
+// R_GenerateLookup
+//
+void R_GenerateLookup (int texnum)
+{
+ texture_t* texture;
+ byte* patchcount; // patchcount[texture->width]
+ texpatch_t* patch;
+ patch_t* realpatch;
+ int x;
+ int x1;
+ int x2;
+ int i;
+ short* collump;
+ unsigned short* colofs;
+
+ texture = textures[texnum];
+
+ // Composited texture not created yet.
+ texturecomposite[texnum] = 0;
+
+ texturecompositesize[texnum] = 0;
+ collump = texturecolumnlump[texnum];
+ colofs = texturecolumnofs[texnum];
+
+ // Now 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 *) Z_Malloc(texture->width, PU_STATIC, &patchcount);
+ memset (patchcount, 0, texture->width);
+ patch = texture->patches;
+
+ for (i=0 , patch = texture->patches;
+ i<texture->patchcount;
+ 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<x2 ; x++)
+ {
+ patchcount[x]++;
+ collump[x] = patch->patch;
+ colofs[x] = LONG(realpatch->columnofs[x-x1])+3;
+ }
+ }
+
+ for (x=0 ; x<texture->width ; 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)
+ {
+ // Use the cached block.
+ collump[x] = -1;
+ colofs[x] = texturecompositesize[texnum];
+
+ if (texturecompositesize[texnum] > 0x10000-texture->height)
+ {
+ I_Error ("R_GenerateLookup: texture %i is >64k",
+ texnum);
+ }
+
+ texturecompositesize[texnum] += texture->height;
+ }
+ }
+
+ Z_Free(patchcount);
+}
+
+
+
+
+//
+// R_GetColumn
+//
+byte*
+R_GetColumn
+( int tex,
+ int col )
+{
+ int lump;
+ int 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;
+}
+
+
+static void GenerateTextureHashTable(void)
+{
+ int i;
+ int key;
+
+ textures_hashtable
+ = Z_Malloc(sizeof(texture_t *) * numtextures, PU_STATIC, 0);
+
+ memset(textures_hashtable, 0, sizeof(texture_t *) * numtextures);
+
+ // Add all textures to hash table
+
+ for (i=0; i<numtextures; ++i)
+ {
+ // Store index
+
+ textures[i]->index = i;
+
+ // Hook into hash table
+
+ key = W_LumpNameHash(textures[i]->name) % numtextures;
+
+ textures[i]->next = textures_hashtable[key];
+ textures_hashtable[key] = textures[i];
+ }
+}
+
+
+//
+// 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;
+ int j;
+
+ int* maptex;
+ int* maptex2;
+ int* maptex1;
+
+ char name[9];
+ char* names;
+ char* name_p;
+
+ int* patchlookup;
+
+ int totalwidth;
+ int nummappatches;
+ int offset;
+ int maxoff;
+ int maxoff2;
+ int numtextures1;
+ int numtextures2;
+
+ int* directory;
+
+ int temp1;
+ int temp2;
+ int temp3;
+
+
+ // Load the patch names from pnames.lmp.
+ name[8] = 0;
+ names = W_CacheLumpName (DEH_String("PNAMES"), PU_STATIC);
+ nummappatches = LONG ( *((int *)names) );
+ name_p = names+4;
+ patchlookup = Z_Malloc(nummappatches*sizeof(*patchlookup), PU_STATIC, NULL);
+
+ for (i=0 ; i<nummappatches ; i++)
+ {
+ strncpy (name,name_p+i*8, 8);
+ patchlookup[i] = W_CheckNumForName (name);
+ }
+ W_ReleaseLumpName(DEH_String("PNAMES"));
+
+ // Load the map texture definitions from textures.lmp.
+ // The data is contained in one or two lumps,
+ // TEXTURE1 for shareware, plus TEXTURE2 for commercial.
+ maptex = maptex1 = W_CacheLumpName (DEH_String("TEXTURE1"), PU_STATIC);
+ numtextures1 = LONG(*maptex);
+ maxoff = W_LumpLength (W_GetNumForName (DEH_String("TEXTURE1")));
+ directory = maptex+1;
+
+ if (W_CheckNumForName (DEH_String("TEXTURE2")) != -1)
+ {
+ maptex2 = W_CacheLumpName (DEH_String("TEXTURE2"), PU_STATIC);
+ numtextures2 = LONG(*maptex2);
+ maxoff2 = W_LumpLength (W_GetNumForName (DEH_String("TEXTURE2")));
+ }
+ else
+ {
+ maptex2 = NULL;
+ numtextures2 = 0;
+ maxoff2 = 0;
+ }
+ numtextures = numtextures1 + numtextures2;
+
+ textures = Z_Malloc (numtextures * sizeof(*textures), PU_STATIC, 0);
+ texturecolumnlump = Z_Malloc (numtextures * sizeof(*texturecolumnlump), PU_STATIC, 0);
+ texturecolumnofs = Z_Malloc (numtextures * sizeof(*texturecolumnofs), PU_STATIC, 0);
+ texturecomposite = Z_Malloc (numtextures * sizeof(*texturecomposite), PU_STATIC, 0);
+ texturecompositesize = Z_Malloc (numtextures * sizeof(*texturecompositesize), PU_STATIC, 0);
+ texturewidthmask = Z_Malloc (numtextures * sizeof(*texturewidthmask), PU_STATIC, 0);
+ textureheight = Z_Malloc (numtextures * sizeof(*textureheight), PU_STATIC, 0);
+
+ totalwidth = 0;
+
+ // Really complex printing shit...
+ temp1 = W_GetNumForName (DEH_String("S_START")); // P_???????
+ temp2 = W_GetNumForName (DEH_String("S_END")) - 1;
+ temp3 = ((temp2-temp1+63)/64) + ((numtextures+63)/64);
+
+ // If stdout is a real console, use the classic vanilla "filling
+ // up the box" effect, which uses backspace to "step back" inside
+ // the box. If stdout is a file, don't draw the box.
+
+ if (I_ConsoleStdout())
+ {
+ printf("[");
+ for (i = 0; i < temp3 + 9; i++)
+ printf(" ");
+ printf("]");
+ for (i = 0; i < temp3 + 10; i++)
+ printf("\b");
+ }
+
+ for (i=0 ; i<numtextures ; i++, directory++)
+ {
+ if (!(i&63))
+ printf (".");
+
+ if (i == numtextures1)
+ {
+ // Start looking in second texture file.
+ maptex = maptex2;
+ maxoff = maxoff2;
+ directory = maptex+1;
+ }
+
+ offset = LONG(*directory);
+
+ if (offset > 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 ; j<texture->patchcount ; 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*sizeof(**texturecolumnlump), PU_STATIC,0);
+ texturecolumnofs[i] = Z_Malloc (texture->width*sizeof(**texturecolumnofs), PU_STATIC,0);
+
+ j = 1;
+ while (j*2 <= texture->width)
+ j<<=1;
+
+ texturewidthmask[i] = j-1;
+ textureheight[i] = texture->height<<FRACBITS;
+
+ totalwidth += texture->width;
+ }
+
+ Z_Free(patchlookup);
+
+ W_ReleaseLumpName(DEH_String("TEXTURE1"));
+ if (maptex2)
+ W_ReleaseLumpName(DEH_String("TEXTURE2"));
+
+ // Precalculate whatever possible.
+
+ for (i=0 ; i<numtextures ; i++)
+ R_GenerateLookup (i);
+
+ // Create translation table for global animation.
+ texturetranslation = Z_Malloc ((numtextures+1)*sizeof(*texturetranslation), PU_STATIC, 0);
+
+ for (i=0 ; i<numtextures ; i++)
+ texturetranslation[i] = i;
+
+ GenerateTextureHashTable();
+}
+
+
+
+//
+// R_InitFlats
+//
+void R_InitFlats (void)
+{
+ int i;
+
+ firstflat = W_GetNumForName (DEH_String("F_START")) + 1;
+ lastflat = W_GetNumForName (DEH_String("F_END")) - 1;
+ numflats = lastflat - firstflat + 1;
+
+ // Create translation table for global animation.
+ flattranslation = Z_Malloc ((numflats+1)*sizeof(*flattranslation), PU_STATIC, 0);
+
+ for (i=0 ; i<numflats ; i++)
+ flattranslation[i] = i;
+}
+
+
+//
+// R_InitSpriteLumps
+// Finds the width and hoffset of all sprites in the wad,
+// so the sprite does not need to be cached completely
+// just for having the header info ready during rendering.
+//
+void R_InitSpriteLumps (void)
+{
+ int i;
+ patch_t *patch;
+
+ firstspritelump = W_GetNumForName (DEH_String("S_START")) + 1;
+ lastspritelump = W_GetNumForName (DEH_String("S_END")) - 1;
+
+ numspritelumps = lastspritelump - firstspritelump + 1;
+ spritewidth = Z_Malloc (numspritelumps*sizeof(*spritewidth), PU_STATIC, 0);
+ spriteoffset = Z_Malloc (numspritelumps*sizeof(*spriteoffset), PU_STATIC, 0);
+ spritetopoffset = Z_Malloc (numspritelumps*sizeof(*spritetopoffset), PU_STATIC, 0);
+
+ for (i=0 ; i< numspritelumps ; i++)
+ {
+ if (!(i&63))
+ printf (".");
+
+ patch = W_CacheLumpNum (firstspritelump+i, PU_CACHE);
+ spritewidth[i] = SHORT(patch->width)<<FRACBITS;
+ spriteoffset[i] = SHORT(patch->leftoffset)<<FRACBITS;
+ spritetopoffset[i] = SHORT(patch->topoffset)<<FRACBITS;
+ }
+}
+
+
+
+//
+// R_InitColormaps
+//
+void R_InitColormaps (void)
+{
+ int lump, length;
+
+ // Load in the light tables,
+ // 256 byte align tables.
+ lump = W_GetNumForName(DEH_String("COLORMAP"));
+ length = W_LumpLength (lump);
+ colormaps = W_CacheLumpNum(lump, PU_STATIC);
+}
+
+
+
+//
+// R_InitData
+// Locates all the lumps
+// that will be used by all views
+// Must be called after W_Init.
+//
+void R_InitData (void)
+{
+ R_InitTextures ();
+ printf (".");
+ R_InitFlats ();
+ printf (".");
+ R_InitSpriteLumps ();
+ printf (".");
+ R_InitColormaps ();
+}
+
+
+
+//
+// R_FlatNumForName
+// Retrieval, get a flat number for a flat name.
+//
+int R_FlatNumForName (char* name)
+{
+ int i;
+ char namet[9];
+
+ i = W_CheckNumForName (name);
+
+ if (i == -1)
+ {
+ namet[8] = 0;
+ memcpy (namet, name,8);
+ I_Error ("R_FlatNumForName: %s not found",namet);
+ }
+ return i - firstflat;
+}
+
+
+
+
+//
+// R_CheckTextureNumForName
+// Check whether texture is available.
+// Filter out NoTexture indicator.
+//
+int R_CheckTextureNumForName (char *name)
+{
+ texture_t *texture;
+ int key;
+
+ // "NoTexture" marker.
+ if (name[0] == '-')
+ return 0;
+
+ key = W_LumpNameHash(name) % numtextures;
+
+ texture=textures_hashtable[key];
+
+ while (texture != NULL)
+ {
+ if (!strncasecmp (texture->name, name, 8) )
+ return texture->index;
+
+ texture = texture->next;
+ }
+
+ return -1;
+}
+
+
+
+//
+// R_TextureNumForName
+// Calls R_CheckTextureNumForName,
+// aborts with error message.
+//
+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 relevant graphics for the level.
+//
+int flatmemory;
+int texturememory;
+int spritememory;
+
+void R_PrecacheLevel (void)
+{
+ char* flatpresent;
+ char* texturepresent;
+ char* spritepresent;
+
+ int i;
+ int j;
+ int k;
+ int lump;
+
+ texture_t* texture;
+ thinker_t* th;
+ spriteframe_t* sf;
+
+ if (demoplayback)
+ return;
+
+ // Precache flats.
+ flatpresent = Z_Malloc(numflats, PU_STATIC, NULL);
+ memset (flatpresent,0,numflats);
+
+ for (i=0 ; i<numsectors ; i++)
+ {
+ flatpresent[sectors[i].floorpic] = 1;
+ flatpresent[sectors[i].ceilingpic] = 1;
+ }
+
+ flatmemory = 0;
+
+ for (i=0 ; i<numflats ; i++)
+ {
+ if (flatpresent[i])
+ {
+ lump = firstflat + i;
+ flatmemory += lumpinfo[lump].size;
+ W_CacheLumpNum(lump, PU_CACHE);
+ }
+ }
+
+ Z_Free(flatpresent);
+
+ // Precache textures.
+ texturepresent = Z_Malloc(numtextures, PU_STATIC, NULL);
+ memset (texturepresent,0, numtextures);
+
+ for (i=0 ; i<numsides ; i++)
+ {
+ texturepresent[sides[i].toptexture] = 1;
+ texturepresent[sides[i].midtexture] = 1;
+ texturepresent[sides[i].bottomtexture] = 1;
+ }
+
+ // Sky texture is always present.
+ // Note that F_SKY1 is the name used to
+ // indicate a sky floor/ceiling as a flat,
+ // while the sky texture is stored like
+ // a wall texture, with an episode dependend
+ // name.
+ texturepresent[skytexture] = 1;
+
+ texturememory = 0;
+ for (i=0 ; i<numtextures ; i++)
+ {
+ if (!texturepresent[i])
+ continue;
+
+ texture = textures[i];
+
+ for (j=0 ; j<texture->patchcount ; j++)
+ {
+ lump = texture->patches[j].patch;
+ texturememory += lumpinfo[lump].size;
+ W_CacheLumpNum(lump , PU_CACHE);
+ }
+ }
+
+ Z_Free(texturepresent);
+
+ // Precache sprites.
+ spritepresent = Z_Malloc(numsprites, PU_STATIC, NULL);
+ memset (spritepresent,0, numsprites);
+
+ for (th = thinkercap.next ; th != &thinkercap ; th=th->next)
+ {
+ if (th->function.acp1 == (actionf_p1)P_MobjThinker)
+ spritepresent[((mobj_t *)th)->sprite] = 1;
+ }
+
+ spritememory = 0;
+ for (i=0 ; i<numsprites ; i++)
+ {
+ if (!spritepresent[i])
+ continue;
+
+ for (j=0 ; j<sprites[i].numframes ; j++)
+ {
+ sf = &sprites[i].spriteframes[j];
+ for (k=0 ; k<8 ; k++)
+ {
+ lump = firstspritelump + sf->lump[k];
+ spritememory += lumpinfo[lump].size;
+ W_CacheLumpNum(lump , PU_CACHE);
+ }
+ }
+ }
+
+ Z_Free(spritepresent);
+}
+
+
+
+
--- /dev/null
+++ b/src/doom/r_data.h
@@ -1,0 +1,59 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION:
+// Refresh module, data I/O, caching, retrieval of graphics
+// by name.
+//
+//-----------------------------------------------------------------------------
+
+
+#ifndef __R_DATA__
+#define __R_DATA__
+
+#include "r_defs.h"
+#include "r_state.h"
+
+
+// Retrieve column data for span blitting.
+byte*
+R_GetColumn
+( int tex,
+ int col );
+
+
+// I/O, setting up the stuff.
+void R_InitData (void);
+void R_PrecacheLevel (void);
+
+
+// Retrieval.
+// Floor/ceiling opaque texture tiles,
+// lookup by name. For animation?
+int R_FlatNumForName (char* name);
+
+
+// Called by P_Ticker for switches and animations,
+// returns the texture number for the texture name.
+int R_TextureNumForName (char *name);
+int R_CheckTextureNumForName (char *name);
+
+#endif
--- /dev/null
+++ b/src/doom/r_defs.h
@@ -1,0 +1,487 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION:
+// Refresh/rendering module, shared data struct definitions.
+//
+//-----------------------------------------------------------------------------
+
+
+#ifndef __R_DEFS__
+#define __R_DEFS__
+
+
+// Screenwidth.
+#include "doomdef.h"
+
+// Some more or less basic data types
+// we depend on.
+#include "m_fixed.h"
+
+// We rely on the thinker data struct
+// to handle sound origins in sectors.
+#include "d_think.h"
+// SECTORS do store MObjs anyway.
+#include "p_mobj.h"
+
+
+
+
+
+
+// Silhouette, needed for clipping Segs (mainly)
+// and sprites representing things.
+#define SIL_NONE 0
+#define SIL_BOTTOM 1
+#define SIL_TOP 2
+#define SIL_BOTH 3
+
+#define MAXDRAWSEGS 256
+
+
+
+
+
+//
+// INTERNAL MAP TYPES
+// used by play and refresh
+//
+
+//
+// Your plain vanilla vertex.
+// Note: transformed values not buffered locally,
+// like some DOOM-alikes ("wt", "WebView") did.
+//
+typedef struct
+{
+ fixed_t x;
+ fixed_t y;
+
+} vertex_t;
+
+
+// Forward of LineDefs, for Sectors.
+struct line_s;
+
+// Each sector has a degenmobj_t in its center
+// for sound origin purposes.
+// I suppose this does not handle sound from
+// moving objects (doppler), because
+// position is prolly just buffered, not
+// updated.
+typedef struct
+{
+ thinker_t thinker; // not used for anything
+ fixed_t x;
+ fixed_t y;
+ fixed_t z;
+
+} degenmobj_t;
+
+//
+// The SECTORS record, at runtime.
+// Stores things/mobjs.
+//
+typedef struct
+{
+ fixed_t floorheight;
+ fixed_t ceilingheight;
+ short floorpic;
+ short ceilingpic;
+ short lightlevel;
+ short special;
+ short tag;
+
+ // 0 = untraversed, 1,2 = sndlines -1
+ int soundtraversed;
+
+ // thing that made a sound (or null)
+ mobj_t* soundtarget;
+
+ // mapblock bounding box for height changes
+ int blockbox[4];
+
+ // origin for any sounds played by the sector
+ degenmobj_t soundorg;
+
+ // if == validcount, already checked
+ int validcount;
+
+ // list of mobjs in sector
+ mobj_t* thinglist;
+
+ // thinker_t for reversable actions
+ void* specialdata;
+
+ int linecount;
+ struct line_s** lines; // [linecount] size
+
+} sector_t;
+
+
+
+
+//
+// The SideDef.
+//
+
+typedef struct
+{
+ // add this to the calculated texture column
+ fixed_t textureoffset;
+
+ // add this to the calculated texture top
+ fixed_t rowoffset;
+
+ // Texture indices.
+ // We do not maintain names here.
+ short toptexture;
+ short bottomtexture;
+ short midtexture;
+
+ // Sector the SideDef is facing.
+ sector_t* sector;
+
+} side_t;
+
+
+
+//
+// Move clipping aid for LineDefs.
+//
+typedef enum
+{
+ ST_HORIZONTAL,
+ ST_VERTICAL,
+ ST_POSITIVE,
+ ST_NEGATIVE
+
+} slopetype_t;
+
+
+
+typedef struct line_s
+{
+ // Vertices, from v1 to v2.
+ vertex_t* v1;
+ vertex_t* v2;
+
+ // Precalculated v2 - v1 for side checking.
+ fixed_t dx;
+ fixed_t dy;
+
+ // Animation related.
+ short flags;
+ short special;
+ short tag;
+
+ // Visual appearance: SideDefs.
+ // sidenum[1] will be -1 if one sided
+ short sidenum[2];
+
+ // Neat. Another bounding box, for the extent
+ // of the LineDef.
+ fixed_t bbox[4];
+
+ // To aid move clipping.
+ slopetype_t slopetype;
+
+ // Front and back sector.
+ // Note: redundant? Can be retrieved from SideDefs.
+ sector_t* frontsector;
+ sector_t* backsector;
+
+ // if == validcount, already checked
+ int validcount;
+
+ // thinker_t for reversable actions
+ void* specialdata;
+} line_t;
+
+
+
+
+//
+// A SubSector.
+// References a Sector.
+// Basically, this is a list of LineSegs,
+// indicating the visible walls that define
+// (all or some) sides of a convex BSP leaf.
+//
+typedef struct subsector_s
+{
+ sector_t* sector;
+ short numlines;
+ short firstline;
+
+} subsector_t;
+
+
+
+//
+// The LineSeg.
+//
+typedef struct
+{
+ vertex_t* v1;
+ vertex_t* v2;
+
+ fixed_t offset;
+
+ angle_t angle;
+
+ side_t* sidedef;
+ line_t* linedef;
+
+ // Sector references.
+ // Could be retrieved from linedef, too.
+ // backsector is NULL for one sided lines
+ sector_t* frontsector;
+ sector_t* backsector;
+
+} seg_t;
+
+
+
+//
+// BSP node.
+//
+typedef struct
+{
+ // Partition line.
+ fixed_t x;
+ fixed_t y;
+ fixed_t dx;
+ fixed_t dy;
+
+ // Bounding box for each child.
+ fixed_t bbox[2][4];
+
+ // If NF_SUBSECTOR its a subsector.
+ unsigned short children[2];
+
+} node_t;
+
+
+
+
+// posts are runs of non masked source pixels
+typedef struct
+{
+ byte topdelta; // -1 is the last post in a column
+ byte length; // length data bytes follows
+} PACKEDATTR post_t;
+
+// column_t is a list of 0 or more post_t, (byte)-1 terminated
+typedef post_t column_t;
+
+
+
+// PC direct to screen pointers
+//B UNUSED - keep till detailshift in r_draw.c resolved
+//extern byte* destview;
+//extern byte* destscreen;
+
+
+
+
+
+//
+// OTHER TYPES
+//
+
+// This could be wider for >8 bit display.
+// Indeed, true color support is posibble
+// precalculating 24bpp lightmap/colormap LUT.
+// from darkening PLAYPAL to all black.
+// Could even us emore than 32 levels.
+typedef byte lighttable_t;
+
+
+
+
+//
+// ?
+//
+typedef struct drawseg_s
+{
+ seg_t* curline;
+ int x1;
+ int x2;
+
+ fixed_t scale1;
+ fixed_t scale2;
+ fixed_t scalestep;
+
+ // 0=none, 1=bottom, 2=top, 3=both
+ int silhouette;
+
+ // do not clip sprites above this
+ fixed_t bsilheight;
+
+ // do not clip sprites below this
+ fixed_t tsilheight;
+
+ // Pointers to lists for sprite clipping,
+ // all three adjusted so [x1] is first value.
+ short* sprtopclip;
+ short* sprbottomclip;
+ short* maskedtexturecol;
+
+} drawseg_t;
+
+
+
+// Patches.
+// A patch holds one or more columns.
+// Patches are used for sprites and all masked pictures,
+// and we compose textures from the TEXTURE1/2 lists
+// of patches.
+typedef struct
+{
+ short width; // bounding box size
+ short height;
+ short leftoffset; // pixels to the left of origin
+ short topoffset; // pixels below the origin
+ int columnofs[8]; // only [width] used
+ // the [0] is &columnofs[width]
+} PACKEDATTR patch_t;
+
+
+
+
+
+
+
+// A vissprite_t is a thing
+// that will be drawn during a refresh.
+// I.e. a sprite object that is partly visible.
+typedef struct vissprite_s
+{
+ // Doubly linked list.
+ struct vissprite_s* prev;
+ struct vissprite_s* next;
+
+ int x1;
+ int x2;
+
+ // for line side calculation
+ fixed_t gx;
+ fixed_t gy;
+
+ // global bottom / top for silhouette clipping
+ fixed_t gz;
+ fixed_t gzt;
+
+ // horizontal position of x1
+ fixed_t startfrac;
+
+ fixed_t scale;
+
+ // negative if flipped
+ fixed_t xiscale;
+
+ fixed_t texturemid;
+ int patch;
+
+ // for color translation and shadow draw,
+ // maxbright frames as well
+ lighttable_t* colormap;
+
+ int mobjflags;
+
+} vissprite_t;
+
+
+//
+// Sprites are patches with a special naming convention
+// so they can be recognized by R_InitSprites.
+// The base name is NNNNFx or NNNNFxFx, with
+// x indicating the rotation, x = 0, 1-7.
+// 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,
+// thus NNNNF2F5 defines a mirrored patch.
+// Some sprites will only have one picture used
+// for all views: NNNNF0
+//
+typedef struct
+{
+ // If false use 0 for any position.
+ // Note: as eight entries are available,
+ // we might as well insert the same name eight times.
+ boolean rotate;
+
+ // Lump to use for view angles 0-7.
+ short lump[8];
+
+ // Flip bit (1 = flip) to use for view angles 0-7.
+ byte flip[8];
+
+} spriteframe_t;
+
+
+
+//
+// A sprite definition:
+// a number of animation frames.
+//
+typedef struct
+{
+ int numframes;
+ spriteframe_t* spriteframes;
+
+} spritedef_t;
+
+
+
+//
+// Now what is a visplane, anyway?
+//
+typedef struct
+{
+ fixed_t height;
+ int picnum;
+ int lightlevel;
+ int minx;
+ int maxx;
+
+ // leave pads for [minx-1]/[maxx+1]
+
+ byte pad1;
+ // Here lies the rub for all
+ // dynamic resize/change of resolution.
+ byte top[SCREENWIDTH];
+ byte pad2;
+ byte pad3;
+ // See above.
+ byte bottom[SCREENWIDTH];
+ byte pad4;
+
+} visplane_t;
+
+
+
+
+#endif
--- /dev/null
+++ b/src/doom/r_draw.c
@@ -1,0 +1,952 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION:
+// The actual span/column drawing functions.
+// Here find the main potential for optimization,
+// e.g. inline assembly, different algorithms.
+//
+//-----------------------------------------------------------------------------
+
+
+
+
+#include "doomdef.h"
+#include "deh_main.h"
+
+#include "i_system.h"
+#include "z_zone.h"
+#include "w_wad.h"
+
+#include "r_local.h"
+
+// Needs access to LFB (guess what).
+#include "v_video.h"
+
+// State.
+#include "doomstat.h"
+
+
+// ?
+#define MAXWIDTH 1120
+#define MAXHEIGHT 832
+
+// status bar height at bottom of screen
+#define SBARHEIGHT 32
+
+//
+// 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.
+// Conveniently, the frame buffer is a linear one,
+// and we need only the base address,
+// and the total size == width*height*depth/8.,
+//
+
+
+byte* viewimage;
+int viewwidth;
+int scaledviewwidth;
+int viewheight;
+int viewwindowx;
+int viewwindowy;
+byte* ylookup[MAXHEIGHT];
+int columnofs[MAXWIDTH];
+
+// Color tables for different players,
+// translate a limited part to another
+// (color ramps used for suit colors).
+//
+byte translations[3][256];
+
+
+
+
+//
+// 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;
+
+// first pixel in a column (possibly virtual)
+byte* dc_source;
+
+// just for profiling
+int dccount;
+
+//
+// A column is a vertical slice/span from a wall texture that,
+// given the DOOM style restrictions on the view orientation,
+// will always have constant z depth.
+// Thus a special case loop for very fast rendering can
+// be used. It has also been used with Wolfenstein 3D.
+//
+void R_DrawColumn (void)
+{
+ int count;
+ byte* dest;
+ fixed_t frac;
+ fixed_t fracstep;
+
+ count = dc_yh - dc_yl;
+
+ // Zero length, column does not exceed a pixel.
+ 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
+
+ // Framebuffer destination address.
+ // Use ylookup LUT to avoid multiply with ScreenWidth.
+ // Use columnofs LUT for subwindows?
+ dest = ylookup[dc_yl] + columnofs[dc_x];
+
+ // Determine scaling,
+ // which is the only mapping to be done.
+ fracstep = dc_iscale;
+ frac = dc_texturemid + (dc_yl-centery)*fracstep;
+
+ // Inner loop that does the actual texture mapping,
+ // e.g. a DDA-lile scaling.
+ // This is as fast as it gets.
+ do
+ {
+ // Re-map color indices from wall texture column
+ // using a lighting/special effects LUT.
+ *dest = dc_colormap[dc_source[(frac>>FRACBITS)&127]];
+
+ dest += SCREENWIDTH;
+ frac += fracstep;
+
+ } while (count--);
+}
+
+
+
+// UNUSED.
+// Loop unrolled.
+#if 0
+void R_DrawColumn (void)
+{
+ int count;
+ byte* source;
+ byte* dest;
+ byte* colormap;
+
+ unsigned frac;
+ unsigned fracstep;
+ unsigned fracstep2;
+ unsigned fracstep3;
+ unsigned 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
+
+
+void R_DrawColumnLow (void)
+{
+ int count;
+ byte* dest;
+ byte* dest2;
+ fixed_t frac;
+ fixed_t fracstep;
+ int x;
+
+ count = dc_yh - dc_yl;
+
+ // Zero length.
+ 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
+ // Blocky mode, need to multiply by 2.
+ x = dc_x << 1;
+
+ dest = ylookup[dc_yl] + columnofs[x];
+ dest2 = ylookup[dc_yl] + columnofs[x+1];
+
+ fracstep = dc_iscale;
+ frac = dc_texturemid + (dc_yl-centery)*fracstep;
+
+ do
+ {
+ // Hack. Does not work corretly.
+ *dest2 = *dest = dc_colormap[dc_source[(frac>>FRACBITS)&127]];
+ dest += SCREENWIDTH;
+ dest2 += SCREENWIDTH;
+ frac += fracstep;
+
+ } while (count--);
+}
+
+
+//
+// Spectre/Invisibility.
+//
+#define FUZZTABLE 50
+#define FUZZOFF (SCREENWIDTH)
+
+
+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;
+
+
+//
+// Framebuffer postprocessing.
+// Creates a fuzzy image by copying pixels
+// from adjacent ones to left and right.
+// Used with an all black colormap, this
+// could create the SHADOW effect,
+// i.e. spectres and invisible players.
+//
+void R_DrawFuzzColumn (void)
+{
+ int count;
+ byte* dest;
+ fixed_t frac;
+ fixed_t fracstep;
+
+ // Adjust borders. Low...
+ if (!dc_yl)
+ dc_yl = 1;
+
+ // .. and high.
+ if (dc_yh == viewheight-1)
+ dc_yh = viewheight - 2;
+
+ count = dc_yh - dc_yl;
+
+ // Zero length.
+ 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
+
+ dest = ylookup[dc_yl] + columnofs[dc_x];
+
+ // Looks familiar.
+ fracstep = dc_iscale;
+ frac = dc_texturemid + (dc_yl-centery)*fracstep;
+
+ // Looks like an attempt at dithering,
+ // using the colormap #6 (of 0-31, a bit
+ // brighter than average).
+ do
+ {
+ // Lookup framebuffer, and retrieve
+ // a pixel that is either one column
+ // left or right of the current one.
+ // Add index from colormap to index.
+ *dest = colormaps[6*256+dest[fuzzoffset[fuzzpos]]];
+
+ // Clamp table lookup index.
+ if (++fuzzpos == FUZZTABLE)
+ fuzzpos = 0;
+
+ dest += SCREENWIDTH;
+
+ frac += fracstep;
+ } while (count--);
+}
+
+// low detail mode version
+
+void R_DrawFuzzColumnLow (void)
+{
+ int count;
+ byte* dest;
+ byte* dest2;
+ fixed_t frac;
+ fixed_t fracstep;
+ int x;
+
+ // Adjust borders. Low...
+ if (!dc_yl)
+ dc_yl = 1;
+
+ // .. and high.
+ if (dc_yh == viewheight-1)
+ dc_yh = viewheight - 2;
+
+ count = dc_yh - dc_yl;
+
+ // Zero length.
+ if (count < 0)
+ return;
+
+ // low detail mode, need to multiply by 2
+
+ x = dc_x << 1;
+
+#ifdef RANGECHECK
+ if ((unsigned)x >= SCREENWIDTH
+ || dc_yl < 0 || dc_yh >= SCREENHEIGHT)
+ {
+ I_Error ("R_DrawFuzzColumn: %i to %i at %i",
+ dc_yl, dc_yh, dc_x);
+ }
+#endif
+
+ dest = ylookup[dc_yl] + columnofs[x];
+ dest2 = ylookup[dc_yl] + columnofs[x+1];
+
+ // Looks familiar.
+ fracstep = dc_iscale;
+ frac = dc_texturemid + (dc_yl-centery)*fracstep;
+
+ // Looks like an attempt at dithering,
+ // using the colormap #6 (of 0-31, a bit
+ // brighter than average).
+ do
+ {
+ // Lookup framebuffer, and retrieve
+ // a pixel that is either one column
+ // left or right of the current one.
+ // Add index from colormap to index.
+ *dest = colormaps[6*256+dest[fuzzoffset[fuzzpos]]];
+ *dest2 = colormaps[6*256+dest2[fuzzoffset[fuzzpos]]];
+
+ // Clamp table lookup index.
+ if (++fuzzpos == FUZZTABLE)
+ fuzzpos = 0;
+
+ dest += SCREENWIDTH;
+ dest2 += SCREENWIDTH;
+
+ frac += fracstep;
+ } while (count--);
+}
+
+
+
+
+
+//
+// R_DrawTranslatedColumn
+// Used to draw player sprites
+// with the green colorramp mapped to others.
+// Could be used with different translation
+// tables, e.g. the lighter colored version
+// of the BaronOfHell, the HellKnight, uses
+// identical sprites, kinda brightened up.
+//
+byte* dc_translation;
+byte* translationtables;
+
+void R_DrawTranslatedColumn (void)
+{
+ int count;
+ byte* dest;
+ fixed_t frac;
+ fixed_t 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];
+
+ // Looks familiar.
+ fracstep = dc_iscale;
+ frac = dc_texturemid + (dc_yl-centery)*fracstep;
+
+ // Here we do an additional index re-mapping.
+ do
+ {
+ // Translation tables are used
+ // to map certain colorramps to other ones,
+ // used with PLAY sprites.
+ // Thus the "green" ramp of the player 0 sprite
+ // is mapped to gray, red, black/indigo.
+ *dest = dc_colormap[dc_translation[dc_source[frac>>FRACBITS]]];
+ dest += SCREENWIDTH;
+
+ frac += fracstep;
+ } while (count--);
+}
+
+void R_DrawTranslatedColumnLow (void)
+{
+ int count;
+ byte* dest;
+ byte* dest2;
+ fixed_t frac;
+ fixed_t fracstep;
+ int x;
+
+ count = dc_yh - dc_yl;
+ if (count < 0)
+ return;
+
+ // low detail, need to scale by 2
+ x = dc_x << 1;
+
+#ifdef RANGECHECK
+ if ((unsigned)x >= SCREENWIDTH
+ || dc_yl < 0
+ || dc_yh >= SCREENHEIGHT)
+ {
+ I_Error ( "R_DrawColumn: %i to %i at %i",
+ dc_yl, dc_yh, x);
+ }
+
+#endif
+
+
+ dest = ylookup[dc_yl] + columnofs[x];
+ dest2 = ylookup[dc_yl] + columnofs[x+1];
+
+ // Looks familiar.
+ fracstep = dc_iscale;
+ frac = dc_texturemid + (dc_yl-centery)*fracstep;
+
+ // Here we do an additional index re-mapping.
+ do
+ {
+ // Translation tables are used
+ // to map certain colorramps to other ones,
+ // used with PLAY sprites.
+ // Thus the "green" ramp of the player 0 sprite
+ // is mapped to gray, red, black/indigo.
+ *dest = dc_colormap[dc_translation[dc_source[frac>>FRACBITS]]];
+ *dest2 = dc_colormap[dc_translation[dc_source[frac>>FRACBITS]]];
+ dest += SCREENWIDTH;
+ dest2 += SCREENWIDTH;
+
+ frac += fracstep;
+ } while (count--);
+}
+
+
+
+
+//
+// R_InitTranslationTables
+// Creates the translation tables to map
+// the green color ramp to gray, brown, red.
+// Assumes a given structure of the PLAYPAL.
+// Could be read from a lump instead.
+//
+void R_InitTranslationTables (void)
+{
+ int i;
+
+ translationtables = Z_Malloc (256*3, PU_STATIC, 0);
+
+ // translate just the 16 green colors
+ for (i=0 ; i<256 ; i++)
+ {
+ if (i >= 0x70 && i<= 0x7f)
+ {
+ // map green ramp to gray, brown, red
+ translationtables[i] = 0x60 + (i&0xf);
+ translationtables [i+256] = 0x40 + (i&0xf);
+ translationtables [i+512] = 0x20 + (i&0xf);
+ }
+ else
+ {
+ // Keep all other colors as is.
+ translationtables[i] = translationtables[i+256]
+ = translationtables[i+512] = i;
+ }
+ }
+}
+
+
+
+
+//
+// R_DrawSpan
+// With DOOM style restrictions on view orientation,
+// the floors and ceilings consist of horizontal slices
+// or spans with constant z depth.
+// However, rotation around the world z axis is possible,
+// thus this mapping, while simpler and faster than
+// perspective correct texture mapping, has to traverse
+// the texture at an angle in all but a few cases.
+// In consequence, flats are not stored by column (like walls),
+// and the inner loop has to step in texture space u and v.
+//
+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;
+
+// start of a 64*64 tile image
+byte* ds_source;
+
+// just for profiling
+int dscount;
+
+
+//
+// Draws the actual span.
+void R_DrawSpan (void)
+{
+ fixed_t xfrac;
+ fixed_t yfrac;
+ byte* dest;
+ int count;
+ int 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];
+
+ // We do not check for zero spans here?
+ count = ds_x2 - ds_x1;
+
+ do
+ {
+ // Current texture index in u,v.
+ spot = ((yfrac>>(16-6))&(63*64)) + ((xfrac>>16)&63);
+
+ // Lookup pixel from flat texture tile,
+ // re-index using light/colormap.
+ *dest++ = ds_colormap[ds_source[spot]];
+
+ // Next step in u,v.
+ xfrac += ds_xstep;
+ yfrac += ds_ystep;
+
+ } while (count--);
+}
+
+
+
+// UNUSED.
+// Loop unrolled by 4.
+#if 0
+void R_DrawSpan (void)
+{
+ unsigned position, step;
+
+ byte* source;
+ byte* colormap;
+ byte* dest;
+
+ unsigned count;
+ usingned spot;
+ unsigned value;
+ unsigned temp;
+ unsigned xtemp;
+ unsigned 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
+
+
+//
+// Again..
+//
+void R_DrawSpanLow (void)
+{
+ fixed_t xfrac;
+ fixed_t yfrac;
+ byte* dest;
+ int count;
+ int 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;
+
+ count = (ds_x2 - ds_x1);
+
+ // Blocky mode, need to multiply by 2.
+ ds_x1 <<= 1;
+ ds_x2 <<= 1;
+
+ dest = ylookup[ds_y] + columnofs[ds_x1];
+
+ do
+ {
+ spot = ((yfrac>>(16-6))&(63*64)) + ((xfrac>>16)&63);
+ // Lowres/blocky mode does it twice,
+ // while scale is adjusted appropriately.
+ *dest++ = ds_colormap[ds_source[spot]];
+ *dest++ = ds_colormap[ds_source[spot]];
+
+ xfrac += ds_xstep;
+ yfrac += ds_ystep;
+
+ } while (count--);
+}
+
+//
+// R_InitBuffer
+// Creats lookup tables that avoid
+// multiplies and other hazzles
+// for getting the framebuffer address
+// of a pixel to draw.
+//
+void
+R_InitBuffer
+( int width,
+ int height )
+{
+ int i;
+
+ // Handle resize,
+ // e.g. smaller view windows
+ // with border and/or status bar.
+ viewwindowx = (SCREENWIDTH-width) >> 1;
+
+ // Column offset. For windows.
+ for (i=0 ; i<width ; i++)
+ columnofs[i] = viewwindowx + i;
+
+ // Samw with base row offset.
+ if (width == SCREENWIDTH)
+ viewwindowy = 0;
+ else
+ viewwindowy = (SCREENHEIGHT-SBARHEIGHT-height) >> 1;
+
+ // Preclaculate all row offsets.
+ for (i=0 ; i<height ; i++)
+ ylookup[i] = screens[0] + (i+viewwindowy)*SCREENWIDTH;
+}
+
+
+
+
+//
+// R_FillBackScreen
+// Fills the back screen with a pattern
+// for variable screen sizes
+// Also draws a beveled edge.
+//
+void R_FillBackScreen (void)
+{
+ byte* src;
+ byte* dest;
+ int x;
+ int y;
+ patch_t* patch;
+
+ // DOOM border patch.
+ char *name1 = DEH_String("FLOOR7_2");
+
+ // DOOM II border patch.
+ char *name2 = DEH_String("GRNROCK");
+
+ char* name;
+
+ if (scaledviewwidth == 320)
+ return;
+
+ if ( gamemode == commercial)
+ name = name2;
+ else
+ name = name1;
+
+ src = W_CacheLumpName (name, PU_CACHE);
+ dest = screens[1];
+
+ for (y=0 ; y<SCREENHEIGHT-SBARHEIGHT ; y++)
+ {
+ for (x=0 ; x<SCREENWIDTH/64 ; x++)
+ {
+ memcpy (dest, src+((y&63)<<6), 64);
+ dest += 64;
+ }
+
+ if (SCREENWIDTH&63)
+ {
+ memcpy (dest, src+((y&63)<<6), SCREENWIDTH&63);
+ dest += (SCREENWIDTH&63);
+ }
+ }
+
+ patch = W_CacheLumpName (DEH_String("brdr_t"),PU_CACHE);
+
+ for (x=0 ; x<scaledviewwidth ; x+=8)
+ V_DrawPatch (viewwindowx+x,viewwindowy-8,1,patch);
+ patch = W_CacheLumpName (DEH_String("brdr_b"),PU_CACHE);
+
+ for (x=0 ; x<scaledviewwidth ; x+=8)
+ V_DrawPatch (viewwindowx+x,viewwindowy+viewheight,1,patch);
+ patch = W_CacheLumpName (DEH_String("brdr_l"),PU_CACHE);
+
+ for (y=0 ; y<viewheight ; y+=8)
+ V_DrawPatch (viewwindowx-8,viewwindowy+y,1,patch);
+ patch = W_CacheLumpName (DEH_String("brdr_r"),PU_CACHE);
+
+ for (y=0 ; y<viewheight ; y+=8)
+ V_DrawPatch (viewwindowx+scaledviewwidth,viewwindowy+y,1,patch);
+
+
+ // Draw beveled edge.
+ V_DrawPatch (viewwindowx-8,
+ viewwindowy-8,
+ 1,
+ W_CacheLumpName (DEH_String("brdr_tl"),PU_CACHE));
+
+ V_DrawPatch (viewwindowx+scaledviewwidth,
+ viewwindowy-8,
+ 1,
+ W_CacheLumpName (DEH_String("brdr_tr"),PU_CACHE));
+
+ V_DrawPatch (viewwindowx-8,
+ viewwindowy+viewheight,
+ 1,
+ W_CacheLumpName (DEH_String("brdr_bl"),PU_CACHE));
+
+ V_DrawPatch (viewwindowx+scaledviewwidth,
+ viewwindowy+viewheight,
+ 1,
+ W_CacheLumpName (DEH_String("brdr_br"),PU_CACHE));
+}
+
+
+//
+// Copy a screen buffer.
+//
+void
+R_VideoErase
+( unsigned ofs,
+ int count )
+{
+ // LFB copy.
+ // This might not be a good idea if memcpy
+ // is not optiomal, e.g. byte by byte on
+ // a 32bit CPU, as GNU GCC/Linux libc did
+ // at one point.
+ memcpy (screens[0]+ofs, screens[1]+ofs, count);
+}
+
+
+//
+// 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;
+ int side;
+ int ofs;
+ int 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 ; i<viewheight ; i++)
+ {
+ R_VideoErase (ofs, side);
+ ofs += SCREENWIDTH;
+ }
+
+ // ?
+ V_MarkRect (0,0,SCREENWIDTH, SCREENHEIGHT-SBARHEIGHT);
+}
+
+
--- /dev/null
+++ b/src/doom/r_draw.h
@@ -1,0 +1,112 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION:
+// System specific interface stuff.
+//
+//-----------------------------------------------------------------------------
+
+
+#ifndef __R_DRAW__
+#define __R_DRAW__
+
+
+
+
+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;
+
+// first pixel in a column
+extern byte* dc_source;
+
+
+// The span blitting interface.
+// Hook in assembler or system specific BLT
+// here.
+void R_DrawColumn (void);
+void R_DrawColumnLow (void);
+
+// The Spectre/Invisibility effect.
+void R_DrawFuzzColumn (void);
+void R_DrawFuzzColumnLow (void);
+
+// Draw with color translation tables,
+// for player sprite rendering,
+// Green/Red/Blue/Indigo shirts.
+void R_DrawTranslatedColumn (void);
+void R_DrawTranslatedColumnLow (void);
+
+void
+R_VideoErase
+( unsigned ofs,
+ int count );
+
+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;
+
+// start of a 64*64 tile image
+extern byte* ds_source;
+
+extern byte* translationtables;
+extern byte* dc_translation;
+
+
+// Span blitting for rows, floor/ceiling.
+// No Sepctre effect needed.
+void R_DrawSpan (void);
+
+// Low resolution mode, 160x200?
+void R_DrawSpanLow (void);
+
+
+void
+R_InitBuffer
+( int width,
+ int height );
+
+
+// Initialize color translation tables,
+// for player rendering etc.
+void R_InitTranslationTables (void);
+
+
+
+// Rendering function.
+void R_FillBackScreen (void);
+
+// If the view size is not full screen, draws a border around it.
+void R_DrawViewBorder (void);
+
+
+
+#endif
--- /dev/null
+++ b/src/doom/r_local.h
@@ -1,0 +1,53 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION:
+// Refresh (R_*) module, global header.
+// All the rendering/drawing stuff is here.
+//
+//-----------------------------------------------------------------------------
+
+#ifndef __R_LOCAL__
+#define __R_LOCAL__
+
+// Binary Angles, sine/cosine/atan lookups.
+#include "tables.h"
+
+// Screen size related parameters.
+#include "doomdef.h"
+
+// Include the refresh/render data structs.
+#include "r_data.h"
+
+
+
+//
+// Separate header file for each module.
+//
+#include "r_main.h"
+#include "r_bsp.h"
+#include "r_segs.h"
+#include "r_plane.h"
+#include "r_data.h"
+#include "r_things.h"
+#include "r_draw.h"
+
+#endif // __R_LOCAL__
--- /dev/null
+++ b/src/doom/r_main.c
@@ -1,0 +1,910 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION:
+// Rendering main loop and setup functions,
+// utility functions (BSP, geometry, trigonometry).
+// See tables.c, too.
+//
+//-----------------------------------------------------------------------------
+
+
+
+
+
+#include <stdlib.h>
+#include <math.h>
+
+
+#include "doomdef.h"
+#include "d_net.h"
+
+#include "m_bbox.h"
+#include "m_menu.h"
+
+#include "r_local.h"
+#include "r_sky.h"
+
+
+
+
+
+// Fineangles in the SCREENWIDTH wide window.
+#define FIELDOFVIEW 2048
+
+
+
+int viewangleoffset;
+
+// increment every time a check is made
+int validcount = 1;
+
+
+lighttable_t* fixedcolormap;
+extern lighttable_t** walllights;
+
+int centerx;
+int centery;
+
+fixed_t centerxfrac;
+fixed_t centeryfrac;
+fixed_t projection;
+
+// just for profiling purposes
+int framecount;
+
+int sscount;
+int linecount;
+int loopcount;
+
+fixed_t viewx;
+fixed_t viewy;
+fixed_t viewz;
+
+angle_t viewangle;
+
+fixed_t viewcos;
+fixed_t viewsin;
+
+player_t* viewplayer;
+
+// 0 = high, 1 = low
+int detailshift;
+
+//
+// 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];
+
+
+// UNUSED.
+// The finetangentgent[angle+FINEANGLES/4] table
+// holds the fixed_t tangent values for view angles,
+// ranging from INT_MIN to 0 to INT_MAX.
+// fixed_t finetangent[FINEANGLES/2];
+
+// fixed_t finesine[5*FINEANGLES/4];
+const fixed_t* finecosine = &finesine[FINEANGLES/4];
+
+
+lighttable_t* scalelight[LIGHTLEVELS][MAXLIGHTSCALE];
+lighttable_t* scalelightfixed[MAXLIGHTSCALE];
+lighttable_t* zlight[LIGHTLEVELS][MAXLIGHTZ];
+
+// bumped light from gun blasts
+int extralight;
+
+
+
+void (*colfunc) (void);
+void (*basecolfunc) (void);
+void (*fuzzcolfunc) (void);
+void (*transcolfunc) (void);
+void (*spanfunc) (void);
+
+
+
+//
+// R_AddPointToBox
+// Expand a given bbox
+// so that it encloses a given point.
+//
+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
+// Traverse BSP (sub) tree,
+// check point against partition plane.
+// Returns side 0 (front) or 1 (back).
+//
+int
+R_PointOnSide
+( fixed_t x,
+ fixed_t y,
+ node_t* node )
+{
+ fixed_t dx;
+ fixed_t dy;
+ fixed_t left;
+ fixed_t 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 )
+ {
+ // (left is negative)
+ return 1;
+ }
+ return 0;
+ }
+
+ left = FixedMul ( node->dy>>FRACBITS , dx );
+ right = FixedMul ( dy , node->dx>>FRACBITS );
+
+ if (right < left)
+ {
+ // front side
+ return 0;
+ }
+ // back side
+ return 1;
+}
+
+
+int
+R_PointOnSegSide
+( fixed_t x,
+ fixed_t y,
+ seg_t* line )
+{
+ fixed_t lx;
+ fixed_t ly;
+ fixed_t ldx;
+ fixed_t ldy;
+ fixed_t dx;
+ fixed_t dy;
+ fixed_t left;
+ fixed_t 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 )
+ {
+ // (left is negative)
+ return 1;
+ }
+ return 0;
+ }
+
+ left = FixedMul ( ldy>>FRACBITS , dx );
+ right = FixedMul ( dy , ldx>>FRACBITS );
+
+ if (right < left)
+ {
+ // front side
+ return 0;
+ }
+ // back side
+ return 1;
+}
+
+
+//
+// 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.
+
+//
+
+
+
+
+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)
+ {
+ // octant 0
+ return tantoangle[ SlopeDiv(y,x)];
+ }
+ else
+ {
+ // octant 1
+ return ANG90-1-tantoangle[ SlopeDiv(x,y)];
+ }
+ }
+ else
+ {
+ // y<0
+ y = -y;
+
+ if (x>y)
+ {
+ // octant 8
+ return -tantoangle[SlopeDiv(y,x)];
+ }
+ else
+ {
+ // octant 7
+ return ANG270+tantoangle[ SlopeDiv(x,y)];
+ }
+ }
+ }
+ else
+ {
+ // x<0
+ x = -x;
+
+ if (y>= 0)
+ {
+ // y>= 0
+ if (x>y)
+ {
+ // octant 3
+ return ANG180-1-tantoangle[ SlopeDiv(y,x)];
+ }
+ else
+ {
+ // octant 2
+ return ANG90+ tantoangle[ SlopeDiv(x,y)];
+ }
+ }
+ else
+ {
+ // y<0
+ y = -y;
+
+ if (x>y)
+ {
+ // octant 4
+ return ANG180+tantoangle[ SlopeDiv(y,x)];
+ }
+ else
+ {
+ // octant 5
+ return ANG270-1-tantoangle[ SlopeDiv(x,y)];
+ }
+ }
+ }
+ 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;
+ fixed_t dy;
+ fixed_t temp;
+ fixed_t dist;
+ fixed_t frac;
+
+ dx = abs(x - viewx);
+ dy = abs(y - viewy);
+
+ if (dy>dx)
+ {
+ temp = dx;
+ dx = dy;
+ dy = temp;
+ }
+
+ // Fix crashes in udm1.wad
+
+ if (dx != 0)
+ {
+ frac = FixedDiv(dy, dx);
+ }
+ else
+ {
+ frac = 0;
+ }
+
+ angle = (tantoangle[frac>>DBITS]+ANG90) >> ANGLETOFINESHIFT;
+
+ // use as cosine
+ dist = FixedDiv (dx, finesine[angle] );
+
+ return dist;
+}
+
+
+
+
+//
+// R_InitPointToAngle
+//
+void R_InitPointToAngle (void)
+{
+ // UNUSED - 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 (horizontal span)
+// at the given angle.
+// rw_distance must be calculated first.
+//
+fixed_t R_ScaleFromGlobalAngle (angle_t visangle)
+{
+ fixed_t scale;
+ angle_t anglea;
+ angle_t angleb;
+ int sinea;
+ int sineb;
+ fixed_t num;
+ int den;
+
+ // UNUSED
+#if 0
+{
+ fixed_t dist;
+ fixed_t z;
+ fixed_t sinv;
+ fixed_t 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);
+
+ // both sines are allways positive
+ sinea = finesine[anglea>>ANGLETOFINESHIFT];
+ sineb = finesine[angleb>>ANGLETOFINESHIFT];
+ num = FixedMul(projection,sineb)<<detailshift;
+ den = FixedMul(rw_distance,sinea);
+
+ if (den > 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)
+{
+ // UNUSED: now getting from tables.c
+#if 0
+ int i;
+ float a;
+ float fv;
+ int t;
+
+ // viewangle tangent table
+ for (i=0 ; i<FINEANGLES/2 ; i++)
+ {
+ a = (i-FINEANGLES/4+0.5)*PI*2/FINEANGLES;
+ fv = FRACUNIT*tan (a);
+ t = fv;
+ finetangent[i] = t;
+ }
+
+ // finesine table
+ for (i=0 ; i<5*FINEANGLES/4 ; i++)
+ {
+ // OPTIMIZE: mirror...
+ a = (i+0.5)*PI*2/FINEANGLES;
+ t = FRACUNIT*sin (a);
+ finesine[i] = t;
+ }
+#endif
+
+}
+
+
+
+//
+// R_InitTextureMapping
+//
+void R_InitTextureMapping (void)
+{
+ int i;
+ int x;
+ int t;
+ fixed_t focallength;
+
+ // Use tangent table to generate viewangletox:
+ // viewangletox will give the next greatest x
+ // after the view angle.
+ //
+ // Calc focallength
+ // so FIELDOFVIEW angles covers SCREENWIDTH.
+ focallength = FixedDiv (centerxfrac,
+ finetangent[FINEANGLES/4+FIELDOFVIEW/2] );
+
+ for (i=0 ; i<FINEANGLES/2 ; i++)
+ {
+ if (finetangent[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 xtoviewangle[]:
+ // 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<<ANGLETOFINESHIFT)-ANG90;
+ }
+
+ // Take out the fencepost cases from viewangletox.
+ for (i=0 ; i<FINEANGLES/2 ; i++)
+ {
+ t = FixedMul (finetangent[i], focallength);
+ t = centerx - t;
+
+ if (viewangletox[i] == -1)
+ viewangletox[i] = 0;
+ else if (viewangletox[i] == viewwidth+1)
+ viewangletox[i] = viewwidth;
+ }
+
+ clipangle = xtoviewangle[0];
+}
+
+
+
+//
+// R_InitLightTables
+// Only inits the zlight table,
+// because the scalelight table changes with view size.
+//
+#define DISTMAP 2
+
+void R_InitLightTables (void)
+{
+ int i;
+ int j;
+ int level;
+ int startmap;
+ int scale;
+
+ // Calculate the light levels to use
+ // for each level / distance combination.
+ for (i=0 ; i< LIGHTLEVELS ; i++)
+ {
+ startmap = ((LIGHTLEVELS-1-i)*2)*NUMCOLORMAPS/LIGHTLEVELS;
+ for (j=0 ; j<MAXLIGHTZ ; j++)
+ {
+ scale = FixedDiv ((SCREENWIDTH/2*FRACUNIT), (j+1)<<LIGHTZSHIFT);
+ scale >>= LIGHTSCALESHIFT;
+ level = startmap - scale/DISTMAP;
+
+ if (level < 0)
+ level = 0;
+
+ if (level >= NUMCOLORMAPS)
+ level = NUMCOLORMAPS-1;
+
+ zlight[i][j] = colormaps + level*256;
+ }
+ }
+}
+
+
+
+//
+// R_SetViewSize
+// Do not really change anything here,
+// because it might be in the middle of a refresh.
+// The change will take effect next refresh.
+//
+boolean setsizeneeded;
+int setblocks;
+int setdetail;
+
+
+void
+R_SetViewSize
+( int blocks,
+ int detail )
+{
+ setsizeneeded = true;
+ setblocks = blocks;
+ setdetail = detail;
+}
+
+
+//
+// R_ExecuteSetViewSize
+//
+void R_ExecuteSetViewSize (void)
+{
+ fixed_t cosadj;
+ fixed_t dy;
+ int i;
+ int j;
+ int level;
+ int 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<<FRACBITS;
+ centeryfrac = centery<<FRACBITS;
+ projection = centerxfrac;
+
+ if (!detailshift)
+ {
+ colfunc = basecolfunc = R_DrawColumn;
+ fuzzcolfunc = R_DrawFuzzColumn;
+ transcolfunc = R_DrawTranslatedColumn;
+ spanfunc = R_DrawSpan;
+ }
+ else
+ {
+ colfunc = basecolfunc = R_DrawColumnLow;
+ fuzzcolfunc = R_DrawFuzzColumnLow;
+ transcolfunc = R_DrawTranslatedColumnLow;
+ spanfunc = R_DrawSpanLow;
+ }
+
+ R_InitBuffer (scaledviewwidth, viewheight);
+
+ R_InitTextureMapping ();
+
+ // psprite scales
+ pspritescale = FRACUNIT*viewwidth/SCREENWIDTH;
+ pspriteiscale = FRACUNIT*SCREENWIDTH/viewwidth;
+
+ // thing clipping
+ for (i=0 ; i<viewwidth ; i++)
+ screenheightarray[i] = viewheight;
+
+ // planes
+ for (i=0 ; i<viewheight ; i++)
+ {
+ dy = ((i-viewheight/2)<<FRACBITS)+FRACUNIT/2;
+ dy = abs(dy);
+ yslope[i] = FixedDiv ( (viewwidth<<detailshift)/2*FRACUNIT, dy);
+ }
+
+ for (i=0 ; i<viewwidth ; i++)
+ {
+ cosadj = abs(finecosine[xtoviewangle[i]>>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<MAXLIGHTSCALE ; j++)
+ {
+ level = startmap - j*SCREENWIDTH/(viewwidth<<detailshift)/DISTMAP;
+
+ if (level < 0)
+ level = 0;
+
+ if (level >= NUMCOLORMAPS)
+ level = NUMCOLORMAPS-1;
+
+ scalelight[i][j] = colormaps + level*256;
+ }
+ }
+}
+
+
+
+//
+// R_Init
+//
+
+
+
+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 ();
+ R_InitTranslationTables ();
+ printf (".");
+
+ framecount = 0;
+}
+
+
+//
+// R_PointInSubsector
+//
+subsector_t*
+R_PointInSubsector
+( fixed_t x,
+ fixed_t y )
+{
+ node_t* node;
+ int side;
+ int nodenum;
+
+ // single subsector is a special case
+ if (!numnodes)
+ 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;
+
+ viewplayer = player;
+ viewx = player->mo->x;
+ viewy = player->mo->y;
+ viewangle = player->mo->angle + viewangleoffset;
+ extralight = player->extralight;
+
+ viewz = player->viewz;
+
+ 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<MAXLIGHTSCALE ; i++)
+ scalelightfixed[i] = fixedcolormap;
+ }
+ else
+ fixedcolormap = 0;
+
+ framecount++;
+ validcount++;
+}
+
+
+
+//
+// R_RenderView
+//
+void R_RenderPlayerView (player_t* player)
+{
+ R_SetupFrame (player);
+
+ // Clear buffers.
+ R_ClearClipSegs ();
+ R_ClearDrawSegs ();
+ R_ClearPlanes ();
+ R_ClearSprites ();
+
+ // check for new console commands.
+ NetUpdate ();
+
+ // The head node is the last node output.
+ R_RenderBSPNode (numnodes-1);
+
+ // Check for new console commands.
+ NetUpdate ();
+
+ R_DrawPlanes ();
+
+ // Check for new console commands.
+ NetUpdate ();
+
+ R_DrawMasked ();
+
+ // Check for new console commands.
+ NetUpdate ();
+}
--- /dev/null
+++ b/src/doom/r_main.h
@@ -1,0 +1,170 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION:
+// System specific interface stuff.
+//
+//-----------------------------------------------------------------------------
+
+
+#ifndef __R_MAIN__
+#define __R_MAIN__
+
+#include "d_player.h"
+#include "r_data.h"
+
+
+
+
+//
+// POV related.
+//
+extern fixed_t viewcos;
+extern fixed_t viewsin;
+
+extern int viewwidth;
+extern int viewheight;
+extern int viewwindowx;
+extern int viewwindowy;
+
+
+
+extern int centerx;
+extern int centery;
+
+extern fixed_t centerxfrac;
+extern fixed_t centeryfrac;
+extern fixed_t projection;
+
+extern int validcount;
+
+extern int linecount;
+extern int loopcount;
+
+
+//
+// Lighting LUT.
+// Used for z-depth cuing per column/row,
+// and other lighting effects (sector ambient, flash).
+//
+
+// Lighting constants.
+// Now why not 32 levels here?
+#define LIGHTLEVELS 16
+#define LIGHTSEGSHIFT 4
+
+#define MAXLIGHTSCALE 48
+#define LIGHTSCALESHIFT 12
+#define MAXLIGHTZ 128
+#define LIGHTZSHIFT 20
+
+extern lighttable_t* scalelight[LIGHTLEVELS][MAXLIGHTSCALE];
+extern lighttable_t* scalelightfixed[MAXLIGHTSCALE];
+extern lighttable_t* zlight[LIGHTLEVELS][MAXLIGHTZ];
+
+extern int extralight;
+extern lighttable_t* fixedcolormap;
+
+
+// Number of diminishing brightness levels.
+// There a 0-31, i.e. 32 LUT in the COLORMAP lump.
+#define NUMCOLORMAPS 32
+
+
+// Blocky/low detail mode.
+//B remove this?
+// 0 = high, 1 = low
+extern int detailshift;
+
+
+//
+// Function pointers to switch refresh/drawing functions.
+// Used to select shadow mode etc.
+//
+extern void (*colfunc) (void);
+extern void (*transcolfunc) (void);
+extern void (*basecolfunc) (void);
+extern void (*fuzzcolfunc) (void);
+// No shadow effects on floors.
+extern void (*spanfunc) (void);
+
+
+//
+// Utility functions.
+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 );
+
+
+
+//
+// REFRESH - the actual rendering functions.
+//
+
+// Called by G_Drawer.
+void R_RenderPlayerView (player_t *player);
+
+// Called by startup code.
+void R_Init (void);
+
+// Called by M_Responder.
+void R_SetViewSize (int blocks, int detail);
+
+#endif
--- /dev/null
+++ b/src/doom/r_plane.c
@@ -1,0 +1,454 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION:
+// Here is a core component: drawing the floors and ceilings,
+// while maintaining a per column clipping list only.
+// Moreover, the sky areas have to be determined.
+//
+//-----------------------------------------------------------------------------
+
+
+
+#include <stdlib.h>
+
+#include "i_system.h"
+#include "z_zone.h"
+#include "w_wad.h"
+
+#include "doomdef.h"
+#include "doomstat.h"
+
+#include "r_local.h"
+#include "r_sky.h"
+
+
+
+planefunction_t floorfunc;
+planefunction_t ceilingfunc;
+
+//
+// opening
+//
+
+// Here comes the obnoxious "visplane".
+#define MAXVISPLANES 128
+visplane_t visplanes[MAXVISPLANES];
+visplane_t* lastvisplane;
+visplane_t* floorplane;
+visplane_t* ceilingplane;
+
+// ?
+#define MAXOPENINGS SCREENWIDTH*64
+short openings[MAXOPENINGS];
+short* 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;
+fixed_t baseyscale;
+
+fixed_t cachedheight[SCREENHEIGHT];
+fixed_t cacheddistance[SCREENHEIGHT];
+fixed_t cachedxstep[SCREENHEIGHT];
+fixed_t cachedystep[SCREENHEIGHT];
+
+
+
+//
+// R_InitPlanes
+// Only at game startup.
+//
+void R_InitPlanes (void)
+{
+ // Doh!
+}
+
+
+//
+// R_MapPlane
+//
+// Uses 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;
+ fixed_t length;
+ unsigned index;
+
+#ifdef RANGECHECK
+ if (x2 < x1
+ || x1 < 0
+ || x2 >= viewwidth
+ || 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;
+
+ // high or low detail
+ spanfunc ();
+}
+
+
+//
+// R_ClearPlanes
+// At begining of frame.
+//
+void R_ClearPlanes (void)
+{
+ int i;
+ angle_t angle;
+
+ // opening / clipping determination
+ for (i=0 ; i<viewwidth ; i++)
+ {
+ floorclip[i] = viewheight;
+ ceilingclip[i] = -1;
+ }
+
+ lastvisplane = visplanes;
+ lastopening = openings;
+
+ // texture calculation
+ memset (cachedheight, 0, sizeof(cachedheight));
+
+ // left to right mapping
+ angle = (viewangle-ANG90)>>ANGLETOFINESHIFT;
+
+ // 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; check<lastvisplane; check++)
+ {
+ if (height == check->height
+ && 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;
+ int intrh;
+ int unionl;
+ int 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;
+
+ // use the same one
+ return pl;
+ }
+
+ // 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;
+ int stop;
+ int angle;
+ int lumpnum;
+
+#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;
+
+ // Sky is allways drawn full bright,
+ // i.e. colormaps[0] is used.
+ // Because of this hack, sky is not affected
+ // by INVUL inverse mapping.
+ dc_colormap = colormaps;
+ 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
+ lumpnum = firstflat + flattranslation[pl->picnum];
+ ds_source = W_CacheLumpNum(lumpnum, 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]);
+ }
+
+ W_ReleaseLumpNum(lumpnum);
+ }
+}
--- /dev/null
+++ b/src/doom/r_plane.h
@@ -1,0 +1,84 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION:
+// Refresh, visplane stuff (floor, ceilings).
+//
+//-----------------------------------------------------------------------------
+
+
+#ifndef __R_PLANE__
+#define __R_PLANE__
+
+
+#include "r_data.h"
+
+
+
+// Visplane related.
+extern short* lastopening;
+
+
+typedef void (*planefunction_t) (int top, int bottom);
+
+extern planefunction_t floorfunc;
+extern planefunction_t ceilingfunc_t;
+
+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 );
+
+
+
+#endif
--- /dev/null
+++ b/src/doom/r_segs.c
@@ -1,0 +1,751 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION:
+// All the clipping: columns, horizontal spans, sky columns.
+//
+//-----------------------------------------------------------------------------
+
+
+
+
+
+
+
+#include <stdlib.h>
+
+#include "i_system.h"
+
+#include "doomdef.h"
+#include "doomstat.h"
+
+#include "r_local.h"
+#include "r_sky.h"
+
+
+// OPTIMIZE: closed two sided lines as single sided
+
+// True if any of the segs textures might be visible.
+boolean segtextured;
+
+// False if the back side is the same plane.
+boolean markfloor;
+boolean markceiling;
+
+boolean maskedtexture;
+int toptexture;
+int bottomtexture;
+int midtexture;
+
+
+angle_t rw_normalangle;
+// angle to line origin
+int rw_angle1;
+
+//
+// regular 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;
+int worldbottom;
+int worldhigh;
+int worldlow;
+
+fixed_t pixhigh;
+fixed_t pixlow;
+fixed_t pixhighstep;
+fixed_t pixlowstep;
+
+fixed_t topfrac;
+fixed_t topstep;
+
+fixed_t bottomfrac;
+fixed_t 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. 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->ceilingheight<backsector->ceilingheight
+ ? 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] != SHRT_MAX)
+ {
+ 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] = SHRT_MAX;
+ }
+ 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)
+
+void R_RenderSegLoop (void)
+{
+ angle_t angle;
+ unsigned index;
+ int yl;
+ int yh;
+ int mid;
+ fixed_t texturecolumn;
+ int top;
+ int bottom;
+
+ for ( ; rw_x < rw_stopx ; rw_x++)
+ {
+ // mark floor / ceiling areas
+ yl = (topfrac+HEIGHTUNIT-1)>>HEIGHTBITS;
+
+ // no space above wall?
+ if (yl < ceilingclip[rw_x]+1)
+ yl = ceilingclip[rw_x]+1;
+
+ 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;
+ }
+ else
+ {
+ // purely to shut up the compiler
+
+ texturecolumn = 0;
+ }
+
+ // 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;
+
+ // no space above wall?
+ if (mid <= ceilingclip[rw_x])
+ mid = ceilingclip[rw_x]+1;
+
+ 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;
+
+ // don't overflow and crash
+ if (ds_p == &drawsegs[MAXDRAWSEGS])
+ return;
+
+#ifdef RANGECHECK
+ if (start >=viewwidth || start > stop)
+ I_Error ("Bad R_RenderWallRange: %i to %i", start , stop);
+#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
+ {
+ // UNUSED: 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)<<detailshift;
+ }
+#endif
+ ds_p->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];
+ // bottom of texture at bottom
+ rw_midtexturemid = vtop - viewz;
+ }
+ else
+ {
+ // top of texture at top
+ rw_midtexturemid = worldtop;
+ }
+ rw_midtexturemid += sidedef->rowoffset;
+
+ ds_p->silhouette = SIL_BOTH;
+ ds_p->sprtopclip = screenheightarray;
+ ds_p->sprbottomclip = negonearray;
+ ds_p->bsilheight = INT_MAX;
+ ds_p->tsilheight = INT_MIN;
+ }
+ 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 = INT_MAX;
+ // 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 = INT_MIN;
+ // ds_p->sprtopclip = screenheightarray;
+ }
+
+ if (backsector->ceilingheight <= frontsector->floorheight)
+ {
+ ds_p->sprbottomclip = negonearray;
+ ds_p->bsilheight = INT_MAX;
+ ds_p->silhouette |= SIL_BOTTOM;
+ }
+
+ if (backsector->floorheight >= frontsector->ceilingheight)
+ {
+ ds_p->sprtopclip = screenheightarray;
+ ds_p->tsilheight = INT_MIN;
+ 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
+ {
+ // same plane on both sides
+ markfloor = false;
+ }
+
+
+ if (worldhigh != worldtop
+ || backsector->ceilingpic != frontsector->ceilingpic
+ || backsector->lightlevel != frontsector->lightlevel)
+ {
+ markceiling = true;
+ }
+ else
+ {
+ // same plane on both sides
+ markceiling = false;
+ }
+
+ if (backsector->ceilingheight <= frontsector->floorheight
+ || backsector->floorheight >= frontsector->ceilingheight)
+ {
+ // closed door
+ markceiling = markfloor = true;
+ }
+
+
+ if (worldhigh < worldtop)
+ {
+ // top texture
+ toptexture = texturetranslation[sidedef->toptexture];
+ if (linedef->flags & ML_DONTPEGTOP)
+ {
+ // top of texture at top
+ rw_toptexturemid = worldtop;
+ }
+ else
+ {
+ vtop =
+ backsector->ceilingheight
+ + textureheight[sidedef->toptexture];
+
+ // bottom of texture
+ rw_toptexturemid = vtop - viewz;
+ }
+ }
+ if (worldlow > worldbottom)
+ {
+ // bottom texture
+ bottomtexture = texturetranslation[sidedef->bottomtexture];
+
+ if (linedef->flags & ML_DONTPEGBOTTOM )
+ {
+ // bottom of texture at bottom
+ // top of texture at top
+ rw_bottomtexturemid = worldtop;
+ }
+ 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 definitely invisible
+ // and doesn't need to be marked.
+
+
+ if (frontsector->floorheight >= viewz)
+ {
+ // above view plane
+ markfloor = false;
+ }
+
+ if (frontsector->ceilingheight <= viewz
+ && frontsector->ceilingpic != skyflatnum)
+ {
+ // below view plane
+ markceiling = false;
+ }
+
+
+ // 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 = INT_MIN;
+ }
+ if (maskedtexture && !(ds_p->silhouette&SIL_BOTTOM))
+ {
+ ds_p->silhouette |= SIL_BOTTOM;
+ ds_p->bsilheight = INT_MAX;
+ }
+ ds_p++;
+}
+
--- /dev/null
+++ b/src/doom/r_segs.h
@@ -1,0 +1,41 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION:
+// Refresh module, drawing LineSegs from BSP.
+//
+//-----------------------------------------------------------------------------
+
+
+#ifndef __R_SEGS__
+#define __R_SEGS__
+
+
+
+
+void
+R_RenderMaskedSegRange
+( drawseg_t* ds,
+ int x1,
+ int x2 );
+
+
+#endif
--- /dev/null
+++ b/src/doom/r_sky.c
@@ -1,0 +1,60 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION:
+// Sky rendering. The DOOM sky is a texture map like any
+// wall, wrapping around. A 1024 columns equal 360 degrees.
+// The default sky map is 256 columns and repeats 4 times
+// on a 320 screen?
+//
+//
+//-----------------------------------------------------------------------------
+
+
+
+// Needed for FRACUNIT.
+#include "m_fixed.h"
+
+// Needed for Flat retrieval.
+#include "r_data.h"
+
+
+#include "r_sky.h"
+
+//
+// sky mapping
+//
+int skyflatnum;
+int skytexture;
+int skytexturemid;
+
+
+
+//
+// R_InitSkyMap
+// Called whenever the view size changes.
+//
+void R_InitSkyMap (void)
+{
+ // skyflatnum = R_FlatNumForName ( SKYFLATNAME );
+ skytexturemid = 100*FRACUNIT;
+}
+
--- /dev/null
+++ b/src/doom/r_sky.h
@@ -1,0 +1,45 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION:
+// Sky rendering.
+//
+//-----------------------------------------------------------------------------
+
+
+#ifndef __R_SKY__
+#define __R_SKY__
+
+
+
+// SKY, store the number for name.
+#define SKYFLATNAME "F_SKY1"
+
+// The sky map is 256*128*4 maps.
+#define ANGLETOSKYSHIFT 22
+
+extern int skytexture;
+extern int skytexturemid;
+
+// Called whenever the view size changes.
+void R_InitSkyMap (void);
+
+#endif
--- /dev/null
+++ b/src/doom/r_state.h
@@ -1,0 +1,135 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION:
+// Refresh/render internal state variables (global).
+//
+//-----------------------------------------------------------------------------
+
+
+#ifndef __R_STATE__
+#define __R_STATE__
+
+// Need data structure definitions.
+#include "d_player.h"
+#include "r_data.h"
+
+
+
+
+
+
+//
+// Refresh internal data structures,
+// for rendering.
+//
+
+// needed for texture pegging
+extern fixed_t* textureheight;
+
+// needed for pre rendering (fracs)
+extern fixed_t* spritewidth;
+
+extern fixed_t* spriteoffset;
+extern fixed_t* spritetopoffset;
+
+extern lighttable_t* colormaps;
+
+extern int viewwidth;
+extern int scaledviewwidth;
+extern int viewheight;
+
+extern int firstflat;
+
+// for global animation
+extern int* flattranslation;
+extern int* texturetranslation;
+
+
+// Sprite....
+extern int firstspritelump;
+extern int lastspritelump;
+extern int numspritelumps;
+
+
+
+//
+// Lookup tables for map data.
+//
+extern int numsprites;
+extern spritedef_t* sprites;
+
+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;
+
+
+//
+// POV data.
+//
+extern fixed_t viewx;
+extern fixed_t viewy;
+extern fixed_t 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;
+
+
+
+// angle to line origin
+extern int rw_angle1;
+
+// Segs count?
+extern int sscount;
+
+extern visplane_t* floorplane;
+extern visplane_t* ceilingplane;
+
+
+#endif
--- /dev/null
+++ b/src/doom/r_things.c
@@ -1,0 +1,990 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION:
+// Refresh of things, i.e. objects represented by sprites.
+//
+//-----------------------------------------------------------------------------
+
+
+
+
+#include <stdio.h>
+#include <stdlib.h>
+
+
+#include "deh_main.h"
+#include "doomdef.h"
+
+#include "i_swap.h"
+#include "i_system.h"
+#include "z_zone.h"
+#include "w_wad.h"
+
+#include "r_local.h"
+
+#include "doomstat.h"
+
+
+
+#define MINZ (FRACUNIT*4)
+#define BASEYCENTER 100
+
+//void R_DrawColumn (void);
+//void R_DrawFuzzColumn (void);
+
+
+
+typedef struct
+{
+ int x1;
+ int 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;
+fixed_t 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;
+
+ // make 0 based
+ rotation--;
+ 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;
+ int l;
+ int frame;
+ int rotation;
+ int start;
+ int 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 ; i<numsprites ; i++)
+ {
+ spritename = DEH_String(namelist[i]);
+ memset (sprtemp,-1, sizeof(sprtemp));
+
+ maxframe = -1;
+
+ // scan the lumps,
+ // filling in the frames for whatever is found
+ for (l=start+1 ; l<end ; l++)
+ {
+ if (!strncasecmp(lumpinfo[l].name, spritename, 4))
+ {
+ frame = lumpinfo[l].name[4] - 'A';
+ rotation = lumpinfo[l].name[5] - '0';
+
+ if (modifiedgame)
+ patched = W_GetNumForName (lumpinfo[l].name);
+ else
+ patched = l;
+
+ R_InstallSpriteLump (patched, frame, rotation, false);
+
+ if (lumpinfo[l].name[6])
+ {
+ frame = lumpinfo[l].name[6] - 'A';
+ rotation = lumpinfo[l].name[7] - '0';
+ R_InstallSpriteLump (l, frame, rotation, true);
+ }
+ }
+ }
+
+ // check the frames that were found for completeness
+ if (maxframe == -1)
+ {
+ sprites[i].numframes = 0;
+ continue;
+ }
+
+ maxframe++;
+
+ for (frame = 0 ; frame < maxframe ; frame++)
+ {
+ switch ((int)sprtemp[frame].rotate)
+ {
+ case -1:
+ // no rotations were found for that frame at all
+ I_Error ("R_InitSprites: No patches found "
+ "for %s frame %c", spritename, frame+'A');
+ break;
+
+ case 0:
+ // only the first rotation is needed
+ break;
+
+ case 1:
+ // must have all 8 frames
+ for (rotation=0 ; rotation<8 ; rotation++)
+ if (sprtemp[frame].lump[rotation] == -1)
+ I_Error ("R_InitSprites: Sprite %s frame %c "
+ "is missing rotations",
+ spritename, frame+'A');
+ break;
+ }
+ }
+
+ // allocate space for the frames present and copy sprtemp to it
+ sprites[i].numframes = maxframe;
+ sprites[i].spriteframes =
+ Z_Malloc (maxframe * sizeof(spriteframe_t), PU_STATIC, NULL);
+ memcpy (sprites[i].spriteframes, sprtemp, maxframe*sizeof(spriteframe_t));
+ }
+
+}
+
+
+
+
+//
+// GAME FUNCTIONS
+//
+vissprite_t vissprites[MAXVISSPRITES];
+vissprite_t* vissprite_p;
+int newvissprite;
+
+
+
+//
+// R_InitSprites
+// Called at program start.
+//
+void R_InitSprites (char** namelist)
+{
+ int i;
+
+ for (i=0 ; i<SCREENWIDTH ; i++)
+ {
+ negonearray[i] = -1;
+ }
+
+ R_InitSpriteDefs (namelist);
+}
+
+
+
+//
+// R_ClearSprites
+// Called at frame start.
+//
+void R_ClearSprites (void)
+{
+ vissprite_p = vissprites;
+}
+
+
+//
+// R_NewVisSprite
+//
+vissprite_t overflowsprite;
+
+vissprite_t* R_NewVisSprite (void)
+{
+ if (vissprite_p == &vissprites[MAXVISSPRITES])
+ return &overflowsprite;
+
+ vissprite_p++;
+ return vissprite_p-1;
+}
+
+
+
+//
+// R_DrawMaskedColumn
+// Used for sprites and masked mid textures.
+// Masked means: partly transparent, i.e. stored
+// in posts/runs of opaque pixels.
+//
+short* mfloorclip;
+short* mceilingclip;
+
+fixed_t spryscale;
+fixed_t sprtopscreen;
+
+void R_DrawMaskedColumn (column_t* column)
+{
+ int topscreen;
+ int bottomscreen;
+ fixed_t basetexturemid;
+
+ basetexturemid = dc_texturemid;
+
+ for ( ; column->topdelta != 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<<FRACBITS);
+ // dc_source = (byte *)column + 3 - column->topdelta;
+
+ // Drawn by either R_DrawColumn
+ // or (SHADOW) R_DrawFuzzColumn.
+ colfunc ();
+ }
+ 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)
+ {
+ // NULL colormap = shadow draw
+ colfunc = fuzzcolfunc;
+ }
+ else if (vis->mobjflags & MF_TRANSLATION)
+ {
+ colfunc = transcolfunc;
+ 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 tr_x;
+ fixed_t tr_y;
+
+ fixed_t gxt;
+ fixed_t gyt;
+
+ fixed_t tx;
+ fixed_t tz;
+
+ fixed_t xscale;
+
+ int x1;
+ int 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
+ tr_x = thing->x - viewx;
+ tr_y = thing->y - viewy;
+
+ gxt = FixedMul(tr_x,viewcos);
+ gyt = -FixedMul(tr_y,viewsin);
+
+ tz = gxt-gyt;
+
+ // thing is behind view plane?
+ if (tz < MINZ)
+ return;
+
+ xscale = FixedDiv(projection, tz);
+
+ gxt = -FixedMul(tr_x,viewsin);
+ gyt = FixedMul(tr_y,viewcos);
+ tx = -(gyt+gxt);
+
+ // too far off the side?
+ if (abs(tx)>(tz<<2))
+ return;
+
+ // decide which patch to use for sprite relative to player
+#ifdef RANGECHECK
+ if ((unsigned int) thing->sprite >= (unsigned int) 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;
+
+ // off the right side?
+ if (x1 > viewwidth)
+ return;
+
+ tx += spritewidth[lump];
+ x2 = ((centerxfrac + FixedMul (tx,xscale) ) >>FRACBITS) - 1;
+
+ // off the left side
+ if (x2 < 0)
+ return;
+
+ // store information in a vissprite
+ vis = R_NewVisSprite ();
+ vis->mobjflags = thing->flags;
+ vis->scale = xscale<<detailshift;
+ vis->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)
+ {
+ // shadow draw
+ vis->colormap = NULL;
+ }
+ else if (fixedcolormap)
+ {
+ // fixed map
+ vis->colormap = fixedcolormap;
+ }
+ else if (thing->frame & FF_FULLBRIGHT)
+ {
+ // full bright
+ vis->colormap = colormaps;
+ }
+
+ else
+ {
+ // diminished light
+ index = xscale>>(LIGHTSCALESHIFT-detailshift);
+
+ if (index >= MAXLIGHTSCALE)
+ index = MAXLIGHTSCALE-1;
+
+ vis->colormap = spritelights[index];
+ }
+}
+
+
+
+
+//
+// R_AddSprites
+// During BSP traversal, this adds sprites by sector.
+//
+void R_AddSprites (sector_t* sec)
+{
+ mobj_t* thing;
+ int lightnum;
+
+ // BSP is traversed by subsector.
+ // A sector might have been split into several
+ // subsectors during BSP building.
+ // Thus we check whether its already added.
+ if (sec->validcount == validcount)
+ return;
+
+ // Well, now it will be done.
+ 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];
+
+ // Handle all things in sector.
+ for (thing = sec->thinglist ; thing ; thing = thing->snext)
+ R_ProjectSprite (thing);
+}
+
+
+//
+// R_DrawPSprite
+//
+void R_DrawPSprite (pspdef_t* psp)
+{
+ fixed_t tx;
+ int x1;
+ int x2;
+ spritedef_t* sprdef;
+ spriteframe_t* sprframe;
+ int lump;
+ boolean flip;
+ vissprite_t* vis;
+ vissprite_t avis;
+
+ // decide which patch to use
+#ifdef RANGECHECK
+ if ( (unsigned)psp->state->sprite >= (unsigned int) 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;
+
+ // off the right side
+ if (x1 > viewwidth)
+ return;
+
+ tx += spritewidth[lump];
+ x2 = ((centerxfrac + FixedMul (tx, pspritescale) ) >>FRACBITS) - 1;
+
+ // off the left side
+ if (x2 < 0)
+ return;
+
+ // store information in a vissprite
+ vis = &avis;
+ vis->mobjflags = 0;
+ vis->texturemid = (BASEYCENTER<<FRACBITS)+FRACUNIT/2-(psp->sy-spritetopoffset[lump]);
+ vis->x1 = x1 < 0 ? 0 : x1;
+ vis->x2 = x2 >= viewwidth ? viewwidth-1 : x2;
+ vis->scale = pspritescale<<detailshift;
+
+ if (flip)
+ {
+ vis->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)
+ {
+ // shadow draw
+ vis->colormap = NULL;
+ }
+ else if (fixedcolormap)
+ {
+ // fixed color
+ vis->colormap = fixedcolormap;
+ }
+ else if (psp->state->frame & FF_FULLBRIGHT)
+ {
+ // full bright
+ vis->colormap = colormaps;
+ }
+ else
+ {
+ // local light
+ vis->colormap = spritelights[MAXLIGHTSCALE-1];
+ }
+
+ R_DrawVisSprite (vis, vis->x1, vis->x2);
+}
+
+
+
+//
+// R_DrawPlayerSprites
+//
+void R_DrawPlayerSprites (void)
+{
+ int i;
+ int 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;
+ i<NUMPSPRITES;
+ i++,psp++)
+ {
+ if (psp->state)
+ R_DrawPSprite (psp);
+ }
+}
+
+
+
+
+//
+// R_SortVisSprites
+//
+vissprite_t vsprsortedhead;
+
+
+void R_SortVisSprites (void)
+{
+ int i;
+ int count;
+ vissprite_t* ds;
+ vissprite_t* best;
+ vissprite_t unsorted;
+ fixed_t bestscale;
+
+ count = vissprite_p - vissprites;
+
+ unsorted.next = unsorted.prev = &unsorted;
+
+ if (!count)
+ return;
+
+ for (ds=vissprites ; ds<vissprite_p ; ds++)
+ {
+ ds->next = 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
+
+ vsprsortedhead.next = vsprsortedhead.prev = &vsprsortedhead;
+ for (i=0 ; i<count ; i++)
+ {
+ bestscale = INT_MAX;
+ best = unsorted.next;
+ for (ds=unsorted.next ; ds!= &unsorted ; ds=ds->next)
+ {
+ 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];
+ short cliptop[SCREENWIDTH];
+ int x;
+ int r1;
+ int r2;
+ fixed_t scale;
+ fixed_t 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) )
+ {
+ // does not cover sprite
+ continue;
+ }
+
+ 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) ) )
+ {
+ // masked mid texture?
+ if (ds->maskedtexturecol)
+ R_RenderMaskedSegRange (ds, r1, r2);
+ // seg is behind sprite
+ continue;
+ }
+
+
+ // 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
+ // but does not draw on side views
+ if (!viewangleoffset)
+ R_DrawPlayerSprites ();
+}
+
+
+
--- /dev/null
+++ b/src/doom/r_things.h
@@ -1,0 +1,73 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION:
+// Rendering of moving objects, sprites.
+//
+//-----------------------------------------------------------------------------
+
+
+#ifndef __R_THINGS__
+#define __R_THINGS__
+
+
+
+#define MAXVISSPRITES 128
+
+extern vissprite_t vissprites[MAXVISSPRITES];
+extern vissprite_t* 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;
+extern fixed_t 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 );
+
+
+#endif
--- /dev/null
+++ b/src/doom/sounds.c
@@ -1,0 +1,230 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION:
+// Created by a sound utility.
+// Kept as a sample, DOOM2 sounds.
+//
+//-----------------------------------------------------------------------------
+
+
+#include <stdlib.h>
+
+
+#include "doomtype.h"
+#include "sounds.h"
+
+//
+// Information about all the music
+//
+
+musicinfo_t S_music[] =
+{
+ { NULL, 0, 0, 0 },
+ { "e1m1", 0, 0, 0 },
+ { "e1m2", 0, 0, 0 },
+ { "e1m3", 0, 0, 0 },
+ { "e1m4", 0, 0, 0 },
+ { "e1m5", 0, 0, 0 },
+ { "e1m6", 0, 0, 0 },
+ { "e1m7", 0, 0, 0 },
+ { "e1m8", 0, 0, 0 },
+ { "e1m9", 0, 0, 0 },
+ { "e2m1", 0, 0, 0 },
+ { "e2m2", 0, 0, 0 },
+ { "e2m3", 0, 0, 0 },
+ { "e2m4", 0, 0, 0 },
+ { "e2m5", 0, 0, 0 },
+ { "e2m6", 0, 0, 0 },
+ { "e2m7", 0, 0, 0 },
+ { "e2m8", 0, 0, 0 },
+ { "e2m9", 0, 0, 0 },
+ { "e3m1", 0, 0, 0 },
+ { "e3m2", 0, 0, 0 },
+ { "e3m3", 0, 0, 0 },
+ { "e3m4", 0, 0, 0 },
+ { "e3m5", 0, 0, 0 },
+ { "e3m6", 0, 0, 0 },
+ { "e3m7", 0, 0, 0 },
+ { "e3m8", 0, 0, 0 },
+ { "e3m9", 0, 0, 0 },
+ { "inter", 0, 0, 0 },
+ { "intro", 0, 0, 0 },
+ { "bunny", 0, 0, 0 },
+ { "victor", 0, 0, 0 },
+ { "introa", 0, 0, 0 },
+ { "runnin", 0, 0, 0 },
+ { "stalks", 0, 0, 0 },
+ { "countd", 0, 0, 0 },
+ { "betwee", 0, 0, 0 },
+ { "doom", 0, 0, 0 },
+ { "the_da", 0, 0, 0 },
+ { "shawn", 0, 0, 0 },
+ { "ddtblu", 0, 0, 0 },
+ { "in_cit", 0, 0, 0 },
+ { "dead", 0, 0, 0 },
+ { "stlks2", 0, 0, 0 },
+ { "theda2", 0, 0, 0 },
+ { "doom2", 0, 0, 0 },
+ { "ddtbl2", 0, 0, 0 },
+ { "runni2", 0, 0, 0 },
+ { "dead2", 0, 0, 0 },
+ { "stlks3", 0, 0, 0 },
+ { "romero", 0, 0, 0 },
+ { "shawn2", 0, 0, 0 },
+ { "messag", 0, 0, 0 },
+ { "count2", 0, 0, 0 },
+ { "ddtbl3", 0, 0, 0 },
+ { "ampie", 0, 0, 0 },
+ { "theda3", 0, 0, 0 },
+ { "adrian", 0, 0, 0 },
+ { "messg2", 0, 0, 0 },
+ { "romer2", 0, 0, 0 },
+ { "tense", 0, 0, 0 },
+ { "shawn3", 0, 0, 0 },
+ { "openin", 0, 0, 0 },
+ { "evil", 0, 0, 0 },
+ { "ultima", 0, 0, 0 },
+ { "read_m", 0, 0, 0 },
+ { "dm2ttl", 0, 0, 0 },
+ { "dm2int", 0, 0, 0 }
+};
+
+
+//
+// Information about all the sfx
+//
+
+sfxinfo_t S_sfx[] =
+{
+ // S_sfx[0] needs to be a dummy for odd reasons.
+ { "none", false, 0, 0, -1, -1, 0, 0, 0 },
+
+ { "pistol", false, 64, 0, -1, -1, 0, 0, 0 },
+ { "shotgn", false, 64, 0, -1, -1, 0, 0, 0 },
+ { "sgcock", false, 64, 0, -1, -1, 0, 0, 0 },
+ { "dshtgn", false, 64, 0, -1, -1, 0, 0, 0 },
+ { "dbopn", false, 64, 0, -1, -1, 0, 0, 0 },
+ { "dbcls", false, 64, 0, -1, -1, 0, 0, 0 },
+ { "dbload", false, 64, 0, -1, -1, 0, 0, 0 },
+ { "plasma", false, 64, 0, -1, -1, 0, 0, 0 },
+ { "bfg", false, 64, 0, -1, -1, 0, 0, 0 },
+ { "sawup", false, 64, 0, -1, -1, 0, 0, 0 },
+ { "sawidl", false, 118, 0, -1, -1, 0, 0, 0 },
+ { "sawful", false, 64, 0, -1, -1, 0, 0, 0 },
+ { "sawhit", false, 64, 0, -1, -1, 0, 0, 0 },
+ { "rlaunc", false, 64, 0, -1, -1, 0, 0, 0 },
+ { "rxplod", false, 70, 0, -1, -1, 0, 0, 0 },
+ { "firsht", false, 70, 0, -1, -1, 0, 0, 0 },
+ { "firxpl", false, 70, 0, -1, -1, 0, 0, 0 },
+ { "pstart", false, 100, 0, -1, -1, 0, 0, 0 },
+ { "pstop", false, 100, 0, -1, -1, 0, 0, 0 },
+ { "doropn", false, 100, 0, -1, -1, 0, 0, 0 },
+ { "dorcls", false, 100, 0, -1, -1, 0, 0, 0 },
+ { "stnmov", false, 119, 0, -1, -1, 0, 0, 0 },
+ { "swtchn", false, 78, 0, -1, -1, 0, 0, 0 },
+ { "swtchx", false, 78, 0, -1, -1, 0, 0, 0 },
+ { "plpain", false, 96, 0, -1, -1, 0, 0, 0 },
+ { "dmpain", false, 96, 0, -1, -1, 0, 0, 0 },
+ { "popain", false, 96, 0, -1, -1, 0, 0, 0 },
+ { "vipain", false, 96, 0, -1, -1, 0, 0, 0 },
+ { "mnpain", false, 96, 0, -1, -1, 0, 0, 0 },
+ { "pepain", false, 96, 0, -1, -1, 0, 0, 0 },
+ { "slop", false, 78, 0, -1, -1, 0, 0, 0 },
+ { "itemup", true, 78, 0, -1, -1, 0, 0, 0 },
+ { "wpnup", true, 78, 0, -1, -1, 0, 0, 0 },
+ { "oof", false, 96, 0, -1, -1, 0, 0, 0 },
+ { "telept", false, 32, 0, -1, -1, 0, 0, 0 },
+ { "posit1", true, 98, 0, -1, -1, 0, 0, 0 },
+ { "posit2", true, 98, 0, -1, -1, 0, 0, 0 },
+ { "posit3", true, 98, 0, -1, -1, 0, 0, 0 },
+ { "bgsit1", true, 98, 0, -1, -1, 0, 0, 0 },
+ { "bgsit2", true, 98, 0, -1, -1, 0, 0, 0 },
+ { "sgtsit", true, 98, 0, -1, -1, 0, 0, 0 },
+ { "cacsit", true, 98, 0, -1, -1, 0, 0, 0 },
+ { "brssit", true, 94, 0, -1, -1, 0, 0, 0 },
+ { "cybsit", true, 92, 0, -1, -1, 0, 0, 0 },
+ { "spisit", true, 90, 0, -1, -1, 0, 0, 0 },
+ { "bspsit", true, 90, 0, -1, -1, 0, 0, 0 },
+ { "kntsit", true, 90, 0, -1, -1, 0, 0, 0 },
+ { "vilsit", true, 90, 0, -1, -1, 0, 0, 0 },
+ { "mansit", true, 90, 0, -1, -1, 0, 0, 0 },
+ { "pesit", true, 90, 0, -1, -1, 0, 0, 0 },
+ { "sklatk", false, 70, 0, -1, -1, 0, 0, 0 },
+ { "sgtatk", false, 70, 0, -1, -1, 0, 0, 0 },
+ { "skepch", false, 70, 0, -1, -1, 0, 0, 0 },
+ { "vilatk", false, 70, 0, -1, -1, 0, 0, 0 },
+ { "claw", false, 70, 0, -1, -1, 0, 0, 0 },
+ { "skeswg", false, 70, 0, -1, -1, 0, 0, 0 },
+ { "pldeth", false, 32, 0, -1, -1, 0, 0, 0 },
+ { "pdiehi", false, 32, 0, -1, -1, 0, 0, 0 },
+ { "podth1", false, 70, 0, -1, -1, 0, 0, 0 },
+ { "podth2", false, 70, 0, -1, -1, 0, 0, 0 },
+ { "podth3", false, 70, 0, -1, -1, 0, 0, 0 },
+ { "bgdth1", false, 70, 0, -1, -1, 0, 0, 0 },
+ { "bgdth2", false, 70, 0, -1, -1, 0, 0, 0 },
+ { "sgtdth", false, 70, 0, -1, -1, 0, 0, 0 },
+ { "cacdth", false, 70, 0, -1, -1, 0, 0, 0 },
+ { "skldth", false, 70, 0, -1, -1, 0, 0, 0 },
+ { "brsdth", false, 32, 0, -1, -1, 0, 0, 0 },
+ { "cybdth", false, 32, 0, -1, -1, 0, 0, 0 },
+ { "spidth", false, 32, 0, -1, -1, 0, 0, 0 },
+ { "bspdth", false, 32, 0, -1, -1, 0, 0, 0 },
+ { "vildth", false, 32, 0, -1, -1, 0, 0, 0 },
+ { "kntdth", false, 32, 0, -1, -1, 0, 0, 0 },
+ { "pedth", false, 32, 0, -1, -1, 0, 0, 0 },
+ { "skedth", false, 32, 0, -1, -1, 0, 0, 0 },
+ { "posact", true, 120, 0, -1, -1, 0, 0, 0 },
+ { "bgact", true, 120, 0, -1, -1, 0, 0, 0 },
+ { "dmact", true, 120, 0, -1, -1, 0, 0, 0 },
+ { "bspact", true, 100, 0, -1, -1, 0, 0, 0 },
+ { "bspwlk", true, 100, 0, -1, -1, 0, 0, 0 },
+ { "vilact", true, 100, 0, -1, -1, 0, 0, 0 },
+ { "noway", false, 78, 0, -1, -1, 0, 0, 0 },
+ { "barexp", false, 60, 0, -1, -1, 0, 0, 0 },
+ { "punch", false, 64, 0, -1, -1, 0, 0, 0 },
+ { "hoof", false, 70, 0, -1, -1, 0, 0, 0 },
+ { "metal", false, 70, 0, -1, -1, 0, 0, 0 },
+ { "chgun", false, 64, &S_sfx[sfx_pistol], 150, 0, 0, 0, 0 },
+ { "tink", false, 60, 0, -1, -1, 0, 0, 0 },
+ { "bdopn", false, 100, 0, -1, -1, 0, 0, 0 },
+ { "bdcls", false, 100, 0, -1, -1, 0, 0, 0 },
+ { "itmbk", false, 100, 0, -1, -1, 0, 0, 0 },
+ { "flame", false, 32, 0, -1, -1, 0, 0, 0 },
+ { "flamst", false, 32, 0, -1, -1, 0, 0, 0 },
+ { "getpow", false, 60, 0, -1, -1, 0, 0, 0 },
+ { "bospit", false, 70, 0, -1, -1, 0, 0, 0 },
+ { "boscub", false, 70, 0, -1, -1, 0, 0, 0 },
+ { "bossit", false, 70, 0, -1, -1, 0, 0, 0 },
+ { "bospn", false, 70, 0, -1, -1, 0, 0, 0 },
+ { "bosdth", false, 70, 0, -1, -1, 0, 0, 0 },
+ { "manatk", false, 70, 0, -1, -1, 0, 0, 0 },
+ { "mandth", false, 70, 0, -1, -1, 0, 0, 0 },
+ { "sssit", false, 70, 0, -1, -1, 0, 0, 0 },
+ { "ssdth", false, 70, 0, -1, -1, 0, 0, 0 },
+ { "keenpn", false, 70, 0, -1, -1, 0, 0, 0 },
+ { "keendt", false, 70, 0, -1, -1, 0, 0, 0 },
+ { "skeact", false, 70, 0, -1, -1, 0, 0, 0 },
+ { "skesit", false, 70, 0, -1, -1, 0, 0, 0 },
+ { "skeatk", false, 70, 0, -1, -1, 0, 0, 0 },
+ { "radio", false, 60, 0, -1, -1, 0, 0, 0 }
+};
+
--- /dev/null
+++ b/src/doom/sounds.h
@@ -1,0 +1,296 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION:
+// Created by the sound utility written by Dave Taylor.
+// Kept as a sample, DOOM2 sounds. Frozen.
+//
+//-----------------------------------------------------------------------------
+
+#ifndef __SOUNDS__
+#define __SOUNDS__
+
+
+//
+// SoundFX struct.
+//
+typedef struct sfxinfo_struct sfxinfo_t;
+
+struct sfxinfo_struct
+{
+ // up to 6-character name
+ char* name;
+
+ // Sfx singularity (only one at a time)
+ int singularity;
+
+ // Sfx priority
+ int priority;
+
+ // referenced sound if a link
+ sfxinfo_t* link;
+
+ // pitch if a link
+ int pitch;
+
+ // volume if a link
+ int volume;
+
+ // sound data
+ void* data;
+
+ // 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 is in use)
+ int usefulness;
+
+ // lump number of sfx
+ int lumpnum;
+};
+
+
+
+
+//
+// MusicInfo struct.
+//
+typedef struct
+{
+ // up to 6-character name
+ char* name;
+
+ // lump number of music
+ int lumpnum;
+
+ // music data
+ void* data;
+
+ // music handle once registered
+ void *handle;
+
+} musicinfo_t;
+
+
+
+
+// the complete set of sound effects
+extern sfxinfo_t S_sfx[];
+
+// the complete set of music
+extern musicinfo_t S_music[];
+
+//
+// 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;
+
+#endif
--- /dev/null
+++ b/src/doom/st_lib.c
@@ -1,0 +1,294 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION:
+// The status bar widget code.
+//
+//-----------------------------------------------------------------------------
+
+
+
+#include <ctype.h>
+
+#include "deh_main.h"
+#include "doomdef.h"
+
+#include "z_zone.h"
+#include "v_video.h"
+
+#include "i_swap.h"
+#include "i_system.h"
+
+#include "w_wad.h"
+
+#include "st_stuff.h"
+#include "st_lib.h"
+#include "r_local.h"
+
+
+// in AM_map.c
+extern boolean automapactive;
+
+
+
+
+//
+// Hack display negative frags.
+// Loads and store the stminus lump.
+//
+patch_t* sttminus;
+
+void STlib_init(void)
+{
+ sttminus = (patch_t *) W_CacheLumpName(DEH_String("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.
+// Note: worth the trouble?
+//
+void
+STlib_drawNum
+( st_number_t* n,
+ boolean refresh )
+{
+
+ int numdigits = n->width;
+ int num = *n->num;
+
+ int w = SHORT(n->p[0]->width);
+ int 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, do not 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;
+ int h;
+ int x;
+ int 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 = false;
+ b->val = val;
+ b->on = on;
+ b->p = i;
+}
+
+
+
+void
+STlib_updateBinIcon
+( st_binicon_t* bi,
+ boolean refresh )
+{
+ int x;
+ int y;
+ int w;
+ int 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;
+ }
+
+}
+
--- /dev/null
+++ b/src/doom/st_lib.h
@@ -1,0 +1,226 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION:
+// The status bar widget code.
+//
+//-----------------------------------------------------------------------------
+
+#ifndef __STLIB__
+#define __STLIB__
+
+
+// We are referring to patches.
+#include "r_defs.h"
+
+
+//
+// Background and foreground screen numbers
+//
+#define BG 4
+#define FG 0
+
+
+
+//
+// Typedefs of widgets
+//
+
+// Number widget
+
+typedef struct
+{
+ // upper right-hand corner
+ // of the number (right-justified)
+ int x;
+ int y;
+
+ // max # of digits in number
+ int width;
+
+ // last number value
+ int oldnum;
+
+ // pointer to current value
+ int* num;
+
+ // pointer to boolean stating
+ // whether to update number
+ boolean* on;
+
+ // list of patches for 0-9
+ patch_t** p;
+
+ // user data
+ int data;
+
+} st_number_t;
+
+
+
+// Percent widget ("child" of number widget,
+// or, more precisely, contains a number widget.)
+typedef struct
+{
+ // number information
+ st_number_t n;
+
+ // percent sign graphic
+ patch_t* p;
+
+} st_percent_t;
+
+
+
+// Multiple Icon widget
+typedef struct
+{
+ // center-justified location of icons
+ int x;
+ int y;
+
+ // last icon number
+ int oldinum;
+
+ // pointer to current icon
+ int* inum;
+
+ // pointer to boolean stating
+ // whether to update icon
+ boolean* on;
+
+ // list of icons
+ patch_t** p;
+
+ // user data
+ int data;
+
+} st_multicon_t;
+
+
+
+
+// Binary Icon widget
+
+typedef struct
+{
+ // center-justified location of icon
+ int x;
+ int y;
+
+ // last icon value
+ boolean oldval;
+
+ // pointer to current icon status
+ boolean* val;
+
+ // pointer to boolean
+ // stating whether to update icon
+ boolean* on;
+
+
+ patch_t* p; // icon
+ int data; // user data
+
+} st_binicon_t;
+
+
+
+//
+// Widget creation, access, and update routines
+//
+
+// Initializes widget library.
+// More precisely, initialize STMINUS,
+// everything else is done somewhere else.
+//
+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
--- /dev/null
+++ b/src/doom/st_stuff.c
@@ -1,0 +1,1408 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION:
+// Status bar code.
+// Does the face/direction indicator animatin.
+// Does palette indicators as well (red pain/berserk, bright pickup)
+//
+//-----------------------------------------------------------------------------
+
+
+
+#include <stdio.h>
+
+#include "i_system.h"
+#include "i_video.h"
+#include "z_zone.h"
+#include "m_random.h"
+#include "w_wad.h"
+
+#include "deh_main.h"
+#include "deh_misc.h"
+#include "doomdef.h"
+
+#include "g_game.h"
+
+#include "st_stuff.h"
+#include "st_lib.h"
+#include "r_local.h"
+
+#include "p_local.h"
+#include "p_inter.h"
+
+#include "am_map.h"
+#include "m_cheat.h"
+
+#include "s_sound.h"
+
+// Needs access to LFB.
+#include "v_video.h"
+
+// State.
+#include "doomstat.h"
+
+// Data.
+#include "dstrings.h"
+#include "sounds.h"
+
+//
+// STATUS BAR DATA
+//
+
+
+// Palette indices.
+// For damage/bonus red-/gold-shifts
+#define STARTREDPALS 1
+#define STARTBONUSPALS 9
+#define NUMREDPALS 8
+#define NUMBONUSPALS 4
+// Radiation suit, green shift.
+#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 of status bar
+#define ST_X 0
+#define ST_X2 104
+
+#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.
+// Problem is, within which space? STbar? Screen?
+// Note: this could be read in by a lump.
+// Problem is, is the stuff rendered
+// into a buffer,
+// or into the frame buffer?
+
+// AMMO number pos.
+#define ST_AMMOWIDTH 3
+#define ST_AMMOX 44
+#define ST_AMMOY 171
+
+// HEALTH number pos.
+#define ST_HEALTHWIDTH 3
+#define ST_HEALTHX 90
+#define ST_HEALTHY 171
+
+// Weapon pos.
+#define ST_ARMSX 111
+#define ST_ARMSY 172
+#define ST_ARMSBGX 104
+#define ST_ARMSBGY 168
+#define ST_ARMSXSPACE 12
+#define ST_ARMSYSPACE 10
+
+// Frags pos.
+#define ST_FRAGSX 138
+#define ST_FRAGSY 171
+#define ST_FRAGSWIDTH 2
+
+// ARMOR number pos.
+#define ST_ARMORWIDTH 3
+#define ST_ARMORX 221
+#define ST_ARMORY 171
+
+// Key icon positions.
+#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
+
+// Ammunition counter.
+#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
+
+// Indicate maximum ammunition.
+// Only needed because backpack exists.
+#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
+
+// pistol
+#define ST_WEAPON0X 110
+#define ST_WEAPON0Y 172
+
+// shotgun
+#define ST_WEAPON1X 122
+#define ST_WEAPON1Y 172
+
+// chain gun
+#define ST_WEAPON2X 134
+#define ST_WEAPON2Y 172
+
+// missile launcher
+#define ST_WEAPON3X 110
+#define ST_WEAPON3Y 181
+
+// plasma gun
+#define ST_WEAPON4X 122
+#define ST_WEAPON4Y 181
+
+ // bfg
+#define ST_WEAPON5X 134
+#define ST_WEAPON5Y 181
+
+// WPNS title
+#define ST_WPNSX 109
+#define ST_WPNSY 191
+
+ // DETH title
+#define ST_DETHX 109
+#define ST_DETHY 191
+
+//Incoming messages window location
+//UNUSED
+// #define ST_MSGTEXTX (viewwindowx)
+// #define ST_MSGTEXTY (viewwindowy+viewheight-18)
+#define ST_MSGTEXTX 0
+#define ST_MSGTEXTY 0
+// Dimensions given in characters.
+#define ST_MSGWIDTH 52
+// Or shall I say, in lines?
+#define ST_MSGHEIGHT 1
+
+#define ST_OUTTEXTX 0
+#define ST_OUTTEXTY 6
+
+// Width, in characters again.
+#define ST_OUTWIDTH 52
+ // Height, in lines.
+#define ST_OUTHEIGHT 1
+
+#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
+
+
+// main player in game
+static player_t* plyr;
+
+// ST_Start() has just been called
+static boolean st_firsttime;
+
+// used to execute ST_Init() only once
+static int veryfirsttime = 1;
+
+// lump number for PLAYPAL
+static int lu_palette;
+
+// used for timing
+static unsigned int st_clock;
+
+// used for making messages go away
+static int st_msgcounter=0;
+
+// used when in chat
+static st_chatstateenum_t st_chatstate;
+
+// whether in automap or first-person
+static st_stateenum_t st_gamestate;
+
+// whether left-side main status bar is active
+static boolean st_statusbaron;
+
+// whether status bar chat is active
+static boolean st_chat;
+
+// value of st_chat before message popped up
+static boolean st_oldchat;
+
+// whether chat window has the cursor on
+static boolean st_cursoron;
+
+// !deathmatch
+static boolean st_notdeathmatch;
+
+// !deathmatch && st_statusbaron
+static boolean st_armson;
+
+// !deathmatch
+static boolean st_fragson;
+
+// main bar left
+static patch_t* sbar;
+
+// 0-9, tall numbers
+static patch_t* tallnum[10];
+
+// tall % sign
+static patch_t* tallpercent;
+
+// 0-9, short, yellow (,different!) numbers
+static patch_t* shortnum[10];
+
+// 3 key-cards, 3 skulls
+static patch_t* keys[NUMCARDS];
+
+// face status patches
+static patch_t* faces[ST_NUMFACES];
+
+// face background
+static patch_t* faceback;
+
+ // main bar right
+static patch_t* armsbg;
+
+// weapon ownership patches
+static patch_t* arms[6][2];
+
+// ready-weapon widget
+static st_number_t w_ready;
+
+ // in deathmatch only, summary of frags stats
+static st_number_t w_frags;
+
+// health widget
+static st_percent_t w_health;
+
+// arms background
+static st_binicon_t w_armsbg;
+
+
+// weapon ownership widgets
+static st_multicon_t w_arms[6];
+
+// face status widget
+static st_multicon_t w_faces;
+
+// keycard widgets
+static st_multicon_t w_keyboxes[3];
+
+// armor widget
+static st_percent_t w_armor;
+
+// ammo widgets
+static st_number_t w_ammo[4];
+
+// max ammo widgets
+static st_number_t w_maxammo[4];
+
+
+
+ // number of frags so far in deathmatch
+static int st_fragscount;
+
+// used to use appopriately pained face
+static int st_oldhealth = -1;
+
+// used for evil grin
+static boolean oldweaponsowned[NUMWEAPONS];
+
+ // count until face changes
+static int st_facecount = 0;
+
+// current face index, used by w_faces
+static int st_faceindex = 0;
+
+// holds key-type for each key box on bar
+static int keyboxes[3];
+
+// a random number per tick
+static int st_randomnumber;
+
+cheatseq_t cheat_mus = CHEAT("idmus", 2);
+cheatseq_t cheat_god = CHEAT("iddqd", 0);
+cheatseq_t cheat_ammo = CHEAT("idkfa", 0);
+cheatseq_t cheat_ammonokey = CHEAT("idfa", 0);
+cheatseq_t cheat_noclip = CHEAT("idspispopd", 0);
+cheatseq_t cheat_commercial_noclip = CHEAT("idclip", 0);
+
+cheatseq_t cheat_powerup[7] =
+{
+ CHEAT("idbeholdv", 0),
+ CHEAT("idbeholds", 0),
+ CHEAT("idbeholdi", 0),
+ CHEAT("idbeholdr", 0),
+ CHEAT("idbeholda", 0),
+ CHEAT("idbeholdl", 0),
+ CHEAT("idbehold", 0),
+};
+
+cheatseq_t cheat_choppers = CHEAT("idchoppers", 0);
+cheatseq_t cheat_clev = CHEAT("idclev", 2);
+cheatseq_t cheat_mypos = CHEAT("idmypos", 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);
+ }
+
+}
+
+
+// Respond to keyboard input events,
+// intercept cheats.
+boolean
+ST_Responder (event_t* ev)
+{
+ int i;
+
+ // Filter automap on/off.
+ 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 && gameskill != sk_nightmare)
+ {
+ // 'dqd' cheat for toggleable god mode
+ if (cht_CheckCheat(&cheat_god, ev->data2))
+ {
+ plyr->cheats ^= CF_GODMODE;
+ if (plyr->cheats & CF_GODMODE)
+ {
+ if (plyr->mo)
+ plyr->mo->health = 100;
+
+ plyr->health = deh_god_mode_health;
+ plyr->message = DEH_String(STSTR_DQDON);
+ }
+ else
+ plyr->message = DEH_String(STSTR_DQDOFF);
+ }
+ // 'fa' cheat for killer fucking arsenal
+ else if (cht_CheckCheat(&cheat_ammonokey, ev->data2))
+ {
+ plyr->armorpoints = deh_idfa_armor;
+ plyr->armortype = deh_idfa_armor_class;
+
+ for (i=0;i<NUMWEAPONS;i++)
+ plyr->weaponowned[i] = true;
+
+ for (i=0;i<NUMAMMO;i++)
+ plyr->ammo[i] = plyr->maxammo[i];
+
+ plyr->message = DEH_String(STSTR_FAADDED);
+ }
+ // 'kfa' cheat for key full ammo
+ else if (cht_CheckCheat(&cheat_ammo, ev->data2))
+ {
+ plyr->armorpoints = deh_idkfa_armor;
+ plyr->armortype = deh_idkfa_armor_class;
+
+ for (i=0;i<NUMWEAPONS;i++)
+ plyr->weaponowned[i] = true;
+
+ for (i=0;i<NUMAMMO;i++)
+ plyr->ammo[i] = plyr->maxammo[i];
+
+ for (i=0;i<NUMCARDS;i++)
+ plyr->cards[i] = true;
+
+ plyr->message = DEH_String(STSTR_KFAADDED);
+ }
+ // 'mus' cheat for changing music
+ else if (cht_CheckCheat(&cheat_mus, ev->data2))
+ {
+
+ char buf[3];
+ int musnum;
+
+ plyr->message = DEH_String(STSTR_MUS);
+ cht_GetParam(&cheat_mus, buf);
+
+ if (gamemode == commercial)
+ {
+ musnum = mus_runnin + (buf[0]-'0')*10 + buf[1]-'0' - 1;
+
+ if (((buf[0]-'0')*10 + buf[1]-'0') > 35)
+ plyr->message = DEH_String(STSTR_NOMUS);
+ else
+ S_ChangeMusic(musnum, 1);
+ }
+ else
+ {
+ musnum = mus_e1m1 + (buf[0]-'1')*9 + (buf[1]-'1');
+
+ if (((buf[0]-'1')*9 + buf[1]-'1') > 31)
+ plyr->message = DEH_String(STSTR_NOMUS);
+ else
+ S_ChangeMusic(musnum, 1);
+ }
+ }
+ else if ( (gamemission == doom
+ && cht_CheckCheat(&cheat_noclip, ev->data2))
+ || (gamemission != doom
+ && cht_CheckCheat(&cheat_commercial_noclip,ev->data2)))
+ {
+ // Noclip cheat.
+ // For Doom 1, use the idspipsopd cheat; for all others, use
+ // idclip
+
+ plyr->cheats ^= CF_NOCLIP;
+
+ if (plyr->cheats & CF_NOCLIP)
+ plyr->message = DEH_String(STSTR_NCON);
+ else
+ plyr->message = DEH_String(STSTR_NCOFF);
+ }
+ // 'behold?' power-up cheats
+ for (i=0;i<6;i++)
+ {
+ if (cht_CheckCheat(&cheat_powerup[i], ev->data2))
+ {
+ if (!plyr->powers[i])
+ P_GivePower( plyr, i);
+ else if (i!=pw_strength)
+ plyr->powers[i] = 1;
+ else
+ plyr->powers[i] = 0;
+
+ plyr->message = DEH_String(STSTR_BEHOLDX);
+ }
+ }
+
+ // 'behold' power-up menu
+ if (cht_CheckCheat(&cheat_powerup[6], ev->data2))
+ {
+ plyr->message = DEH_String(STSTR_BEHOLD);
+ }
+ // 'choppers' invulnerability & chainsaw
+ else if (cht_CheckCheat(&cheat_choppers, ev->data2))
+ {
+ plyr->weaponowned[wp_chainsaw] = true;
+ plyr->powers[pw_invulnerability] = true;
+ plyr->message = DEH_String(STSTR_CHOPPERS);
+ }
+ // 'mypos' for player position
+ else if (cht_CheckCheat(&cheat_mypos, ev->data2))
+ {
+ 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 (!netgame && cht_CheckCheat(&cheat_clev, ev->data2))
+ {
+ char buf[3];
+ int epsd;
+ int map;
+
+ cht_GetParam(&cheat_clev, buf);
+
+ if (gamemode == commercial)
+ {
+ epsd = 1;
+ map = (buf[0] - '0')*10 + buf[1] - '0';
+ }
+ else
+ {
+ epsd = buf[0] - '0';
+ map = buf[1] - '0';
+ }
+
+ // Chex.exe always warps to episode 1.
+
+ if (gameversion == exe_chex)
+ {
+ epsd = 1;
+ }
+
+ // Catch invalid maps.
+ if (epsd < 1)
+ return false;
+
+ if (map < 1)
+ return false;
+
+ // Ohmygod - this is not going to work.
+ if ((gamemode == retail)
+ && ((epsd > 4) || (map > 9)))
+ return false;
+
+ if ((gamemode == registered)
+ && ((epsd > 3) || (map > 9)))
+ return false;
+
+ if ((gamemode == shareware)
+ && ((epsd > 1) || (map > 9)))
+ return false;
+
+ if ((gamemode == commercial)
+ && (( epsd > 1) || (map > 34)))
+ return false;
+
+ // So be it.
+ plyr->message = DEH_String(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;
+ angle_t 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)
+ {
+ if (plyr->bonuscount)
+ {
+ // picking up bonus
+ doevilgrin = false;
+
+ for (i=0;i<NUMWEAPONS;i++)
+ {
+ if (oldweaponsowned[i] != plyr->weaponowned[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)
+ {
+ if (plyr->damagecount
+ && plyr->attacker
+ && plyr->attacker != plyr->mo)
+ {
+ // being attacked
+ 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)
+ {
+ // whether right or left
+ diffang = badguyangle - plyr->mo->angle;
+ i = diffang > ANG180;
+ }
+ else
+ {
+ // whether left or right
+ diffang = plyr->mo->angle - badguyangle;
+ i = diffang <= ANG180;
+ } // confusing, aint it?
+
+
+ st_facecount = ST_TURNCOUNT;
+ st_faceindex = ST_calcPainOffset();
+
+ if (diffang < ANG45)
+ {
+ // head-on
+ st_faceindex += ST_RAMPAGEOFFSET;
+ }
+ else if (i)
+ {
+ // turn face right
+ st_faceindex += ST_TURNOFFSET;
+ }
+ else
+ {
+ // turn face left
+ st_faceindex += ST_TURNOFFSET+1;
+ }
+ }
+ }
+ }
+
+ 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();
+
+ // used by the w_armsbg widget
+ st_notdeathmatch = !deathmatch;
+
+ // used by w_arms[] widgets
+ st_armson = st_statusbaron && !deathmatch;
+
+ // used by w_frags widget
+ st_fragson = deathmatch && st_statusbaron;
+ st_fragscount = 0;
+
+ for (i=0 ; i<MAXPLAYERS ; i++)
+ {
+ if (i != consoleplayer)
+ st_fragscount += plyr->frags[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;
+ int 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;
+
+ // used by w_arms[] widgets
+ st_armson = st_statusbaron && !deathmatch;
+
+ // used by w_frags widget
+ st_fragson = deathmatch && st_statusbaron;
+
+ 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();
+
+}
+
+typedef void (*load_callback_t)(char *lumpname, patch_t **variable);
+
+// Iterates through all graphics to be loaded or unloaded, along with
+// the variable they use, invoking the specified callback function.
+
+static void ST_loadUnloadGraphics(load_callback_t callback)
+{
+
+ int i;
+ int j;
+ int facenum;
+
+ char namebuf[9];
+
+ // Load the numbers, tall and short
+ for (i=0;i<10;i++)
+ {
+ sprintf(namebuf, DEH_String("STTNUM%d"), i);
+ callback(namebuf, &tallnum[i]);
+
+ sprintf(namebuf, DEH_String("STYSNUM%d"), i);
+ callback(namebuf, &shortnum[i]);
+ }
+
+ // Load percent key.
+ //Note: why not load STMINUS here, too?
+
+ callback(DEH_String("STTPRCNT"), &tallpercent);
+
+ // key cards
+ for (i=0;i<NUMCARDS;i++)
+ {
+ sprintf(namebuf, DEH_String("STKEYS%d"), i);
+ callback(namebuf, &keys[i]);
+ }
+
+ // arms background
+ callback(DEH_String("STARMS"), &armsbg);
+
+ // arms ownership widgets
+ for (i=0; i<6; i++)
+ {
+ sprintf(namebuf, DEH_String("STGNUM%d"), i+2);
+
+ // gray #
+ callback(namebuf, &arms[i][0]);
+
+ // yellow #
+ arms[i][1] = shortnum[i+2];
+ }
+
+ // face backgrounds for different color players
+ sprintf(namebuf, DEH_String("STFB%d"), consoleplayer);
+ callback(namebuf, &faceback);
+
+ // status bar background bits
+ callback(DEH_String("STBAR"), &sbar);
+
+ // face states
+ facenum = 0;
+ for (i=0; i<ST_NUMPAINFACES; i++)
+ {
+ for (j=0; j<ST_NUMSTRAIGHTFACES; j++)
+ {
+ sprintf(namebuf, DEH_String("STFST%d%d"), i, j);
+ callback(namebuf, &faces[facenum]);
+ ++facenum;
+ }
+ sprintf(namebuf, DEH_String("STFTR%d0"), i); // turn right
+ callback(namebuf, &faces[facenum]);
+ ++facenum;
+ sprintf(namebuf, DEH_String("STFTL%d0"), i); // turn left
+ callback(namebuf, &faces[facenum]);
+ ++facenum;
+ sprintf(namebuf, DEH_String("STFOUCH%d"), i); // ouch!
+ callback(namebuf, &faces[facenum]);
+ ++facenum;
+ sprintf(namebuf, DEH_String("STFEVL%d"), i); // evil grin ;)
+ callback(namebuf, &faces[facenum]);
+ ++facenum;
+ sprintf(namebuf, DEH_String("STFKILL%d"), i); // pissed off
+ callback(namebuf, &faces[facenum]);
+ ++facenum;
+ }
+
+ callback(DEH_String("STFGOD0"), &faces[facenum]);
+ ++facenum;
+ callback(DEH_String("STFDEAD0"), &faces[facenum]);
+ ++facenum;
+}
+
+static void ST_loadCallback(char *lumpname, patch_t **variable)
+{
+ *variable = W_CacheLumpName(lumpname, PU_STATIC);
+}
+
+void ST_loadGraphics(void)
+{
+ ST_loadUnloadGraphics(ST_loadCallback);
+}
+
+void ST_loadData(void)
+{
+ lu_palette = W_GetNumForName (DEH_String("PLAYPAL"));
+ ST_loadGraphics();
+}
+
+static void ST_unloadCallback(char *lumpname, patch_t **variable)
+{
+ W_ReleaseLumpName(lumpname);
+ *variable = NULL;
+}
+
+void ST_unloadGraphics(void)
+{
+ ST_loadUnloadGraphics(ST_unloadCallback);
+}
+
+void ST_unloadData(void)
+{
+ ST_unloadGraphics();
+}
+
+void ST_initData(void)
+{
+
+ int i;
+
+ st_firsttime = true;
+ plyr = &players[consoleplayer];
+
+ st_clock = 0;
+ st_chatstate = StartChatState;
+ st_gamestate = FirstPersonState;
+
+ st_statusbaron = true;
+ st_oldchat = st_chat = false;
+ st_cursoron = false;
+
+ st_faceindex = 0;
+ st_palette = -1;
+
+ st_oldhealth = -1;
+
+ for (i=0;i<NUMWEAPONS;i++)
+ oldweaponsowned[i] = plyr->weaponowned[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 );
+
+ // the last weapon type
+ w_ready.data = plyr->readyweapon;
+
+ // 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);
+}
--- /dev/null
+++ b/src/doom/st_stuff.h
@@ -1,0 +1,97 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION:
+// Status bar code.
+// Does the face/direction indicator animatin.
+// Does palette indicators as well (red pain/berserk, bright pickup)
+//
+//-----------------------------------------------------------------------------
+
+#ifndef __STSTUFF_H__
+#define __STSTUFF_H__
+
+#include "doomtype.h"
+#include "d_event.h"
+#include "m_cheat.h"
+
+// Size of statusbar.
+// Now sensitive for scaling.
+#define ST_HEIGHT 32
+#define ST_WIDTH SCREENWIDTH
+#define ST_Y (SCREENHEIGHT - ST_HEIGHT)
+
+
+//
+// STATUS BAR
+//
+
+// Called by main loop.
+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 when the console player is spawned on each level.
+void ST_Start (void);
+
+// Called by startup code.
+void ST_Init (void);
+
+
+
+// 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;
+
+
+boolean ST_Responder(event_t* ev);
+
+extern cheatseq_t cheat_mus;
+extern cheatseq_t cheat_god;
+extern cheatseq_t cheat_ammo;
+extern cheatseq_t cheat_ammonokey;
+extern cheatseq_t cheat_noclip;
+extern cheatseq_t cheat_commercial_noclip;
+extern cheatseq_t cheat_powerup[7];
+extern cheatseq_t cheat_choppers;
+extern cheatseq_t cheat_clev;
+extern cheatseq_t cheat_mypos;
+
+
+#endif
--- /dev/null
+++ b/src/doom/wi_stuff.c
@@ -1,0 +1,1843 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION:
+// Intermission screens.
+//
+//-----------------------------------------------------------------------------
+
+
+#include <stdio.h>
+
+#include "z_zone.h"
+
+#include "m_random.h"
+
+#include "deh_main.h"
+#include "i_swap.h"
+#include "i_system.h"
+
+#include "w_wad.h"
+
+#include "g_game.h"
+
+#include "r_local.h"
+#include "s_sound.h"
+
+#include "doomstat.h"
+
+// Data.
+#include "sounds.h"
+
+// Needs access to LFB.
+#include "v_video.h"
+
+#include "wi_stuff.h"
+
+//
+// Data needed to add patches to full screen intermission pics.
+// Patches are statistics messages, and animations.
+// Loads of by-pixel layout and placement, offsets etc.
+//
+
+
+//
+// Different vetween registered DOOM (1994) and
+// Ultimate DOOM - Final edition (retail, 1995?).
+// This is supposedly ignored for commercial
+// release (aka DOOM II), which had 34 maps
+// in one episode. So there.
+#define NUMEPISODES 4
+#define NUMMAPS 9
+
+
+// in tics
+//U #define PAUSELEN (TICRATE*2)
+//U #define SCORESTEP 100
+//U #define ANIMPERIOD 32
+// pixel distance from "(YOU)" to "PLAYER N"
+//U #define STARDIST 10
+//U #define WK 1
+
+
+// GLOBAL LOCATIONS
+#define WI_TITLEY 2
+#define WI_SPACINGY 33
+
+// SINGPLE-PLAYER STUFF
+#define SP_STATSX 50
+#define SP_STATSY 50
+
+#define SP_TIMEX 16
+#define SP_TIMEY (SCREENHEIGHT-32)
+
+
+// NET GAME STUFF
+#define NG_STATSY 50
+#define NG_STATSX (32 + SHORT(star->width)/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
+
+
+
+
+typedef enum
+{
+ ANIM_ALWAYS,
+ ANIM_RANDOM,
+ ANIM_LEVEL
+
+} animenum_t;
+
+typedef struct
+{
+ int x;
+ int y;
+
+} point_t;
+
+
+//
+// Animation.
+// There is another anim_t used in p_spec.
+//
+typedef struct
+{
+ animenum_t type;
+
+ // period in tics between animations
+ int period;
+
+ // number of animation frames
+ int nanims;
+
+ // location of animation
+ point_t loc;
+
+ // ALWAYS: n/a,
+ // RANDOM: period deviation (<256),
+ // LEVEL: level
+ int data1;
+
+ // ALWAYS: n/a,
+ // RANDOM: random base period,
+ // LEVEL: n/a
+ int data2;
+
+ // actual graphics for frames of animations
+ patch_t* p[3];
+
+ // following must be initialized to zero before use!
+
+ // next value of bcnt (used in conjunction with period)
+ int nexttic;
+
+ // last drawn animation frame
+ int lastdrawn;
+
+ // next frame number to animate
+ int ctr;
+
+ // used by RANDOM and LEVEL when animating
+ int state;
+
+} anim_t;
+
+
+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).
+// Using patches saves a lot of space,
+// as they replace 320x200 full screen frames.
+//
+
+#define ANIM(type, period, nanims, x, y, nexttic) \
+ { (type), (period), (nanims), { (x), (y) }, (nexttic), \
+ 0, { NULL, NULL, NULL }, 0, 0, 0, 0 }
+
+
+static anim_t epsd0animinfo[] =
+{
+ ANIM(ANIM_ALWAYS, TICRATE/3, 3, 224, 104, 0),
+ ANIM(ANIM_ALWAYS, TICRATE/3, 3, 184, 160, 0),
+ ANIM(ANIM_ALWAYS, TICRATE/3, 3, 112, 136, 0),
+ ANIM(ANIM_ALWAYS, TICRATE/3, 3, 72, 112, 0),
+ ANIM(ANIM_ALWAYS, TICRATE/3, 3, 88, 96, 0),
+ ANIM(ANIM_ALWAYS, TICRATE/3, 3, 64, 48, 0),
+ ANIM(ANIM_ALWAYS, TICRATE/3, 3, 192, 40, 0),
+ ANIM(ANIM_ALWAYS, TICRATE/3, 3, 136, 16, 0),
+ ANIM(ANIM_ALWAYS, TICRATE/3, 3, 80, 16, 0),
+ ANIM(ANIM_ALWAYS, TICRATE/3, 3, 64, 24, 0),
+};
+
+static anim_t epsd1animinfo[] =
+{
+ ANIM(ANIM_LEVEL, TICRATE/3, 1, 128, 136, 1),
+ ANIM(ANIM_LEVEL, TICRATE/3, 1, 128, 136, 2),
+ ANIM(ANIM_LEVEL, TICRATE/3, 1, 128, 136, 3),
+ ANIM(ANIM_LEVEL, TICRATE/3, 1, 128, 136, 4),
+ ANIM(ANIM_LEVEL, TICRATE/3, 1, 128, 136, 5),
+ ANIM(ANIM_LEVEL, TICRATE/3, 1, 128, 136, 6),
+ ANIM(ANIM_LEVEL, TICRATE/3, 1, 128, 136, 7),
+ ANIM(ANIM_LEVEL, TICRATE/3, 3, 192, 144, 8),
+ ANIM(ANIM_LEVEL, TICRATE/3, 1, 128, 136, 8),
+};
+
+static anim_t epsd2animinfo[] =
+{
+ ANIM(ANIM_ALWAYS, TICRATE/3, 3, 104, 168, 0),
+ ANIM(ANIM_ALWAYS, TICRATE/3, 3, 40, 136, 0),
+ ANIM(ANIM_ALWAYS, TICRATE/3, 3, 160, 96, 0),
+ ANIM(ANIM_ALWAYS, TICRATE/3, 3, 104, 80, 0),
+ ANIM(ANIM_ALWAYS, TICRATE/3, 3, 120, 32, 0),
+ ANIM(ANIM_ALWAYS, TICRATE/4, 3, 40, 0, 0),
+};
+
+static int NUMANIMS[NUMEPISODES] =
+{
+ arrlen(epsd0animinfo),
+ arrlen(epsd1animinfo),
+ arrlen(epsd2animinfo),
+};
+
+static anim_t *anims[NUMEPISODES] =
+{
+ epsd0animinfo,
+ epsd1animinfo,
+ epsd2animinfo
+};
+
+
+//
+// GENERAL DATA
+//
+
+//
+// Locally used stuff.
+//
+#define FB 0
+
+
+// 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
+
+// in seconds
+#define SHOWNEXTLOCDELAY 4
+//#define SHOWLASTLOCDELAY SHOWNEXTLOCDELAY
+
+
+// used to accelerate or skip a stage
+static int acceleratestage;
+
+// wbs->pnum
+static int me;
+
+ // specifies current state
+static stateenum_t state;
+
+// contains information passed into intermission
+static wbstartstruct_t* wbs;
+
+static wbplayerstruct_t* plrs; // wbs->plyr[]
+
+// used for general timing
+static int cnt;
+
+// used for timing of background animation
+static int bcnt;
+
+// signals to refresh everything for one frame
+static int firstrefresh;
+
+static int cnt_kills[MAXPLAYERS];
+static int cnt_items[MAXPLAYERS];
+static int cnt_secret[MAXPLAYERS];
+static int cnt_time;
+static int cnt_par;
+static int cnt_pause;
+
+// # of commercial levels
+static int NUMCMAPS;
+
+
+//
+// GRAPHICS
+//
+
+// You Are Here graphic
+static patch_t* yah[3] = { NULL, NULL, NULL };
+
+// splat
+static patch_t* splat[2] = { NULL, NULL };
+
+// %, : graphics
+static patch_t* percent;
+static patch_t* colon;
+
+// 0-9 graphic
+static patch_t* num[10];
+
+// minus sign
+static patch_t* wiminus;
+
+// "Finished!" graphics
+static patch_t* finished;
+
+// "Entering" graphic
+static patch_t* entering;
+
+// "secret"
+static patch_t* sp_secret;
+
+ // "Kills", "Scrt", "Items", "Frags"
+static patch_t* kills;
+static patch_t* secret;
+static patch_t* items;
+static patch_t* frags;
+
+// Time sucks.
+static patch_t* timepatch;
+static patch_t* par;
+static patch_t* sucks;
+
+// "killers", "victims"
+static patch_t* killers;
+static patch_t* victims;
+
+// "Total", your face, your dead face
+static patch_t* total;
+static patch_t* star;
+static patch_t* bstar;
+
+// "red P[1..MAXPLAYERS]"
+static patch_t* p[MAXPLAYERS];
+
+// "gray P[1..MAXPLAYERS]"
+static patch_t* bp[MAXPLAYERS];
+
+ // Name graphics of each level (centered)
+static patch_t** lnames;
+
+//
+// CODE
+//
+
+// slam background
+// UNUSED 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 "<Levelname> Finished!"
+void WI_drawLF(void)
+{
+ int y = WI_TITLEY;
+
+ // draw <LevelName>
+ 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 <LevelName>"
+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;
+ int left;
+ int top;
+ int right;
+ int 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 && c[i] != NULL);
+
+ if (fits && i<2)
+ {
+ V_DrawPatch(lnodes[wbs->epsd][n].x, lnodes[wbs->epsd][n].y,
+ FB, c[i]);
+ }
+ else
+ {
+ // DEBUG
+ printf("Could not place patch on level %d", n+1);
+ }
+}
+
+
+
+void WI_initAnimatedBack(void)
+{
+ int i;
+ anim_t* a;
+
+ if (gamemode == commercial)
+ return;
+
+ if (wbs->epsd > 2)
+ return;
+
+ for (i=0;i<NUMANIMS[wbs->epsd];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 (gamemode == commercial)
+ return;
+
+ if (wbs->epsd > 2)
+ return;
+
+ for (i=0;i<NUMANIMS[wbs->epsd];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 (gamemode == commercial)
+ return;
+
+ if (wbs->epsd > 2)
+ return;
+
+ for (i=0 ; i<NUMANIMS[wbs->epsd] ; 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)
+ {
+ // make variable-length zeros 1 digit long
+ digits = 1;
+ }
+ 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, do not 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);
+}
+
+
+
+//
+// Display level completion time and par,
+// or "sucks" message if overflow.
+//
+void
+WI_drawTime
+( int x,
+ int y,
+ int t )
+{
+
+ int div;
+ int 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;
+
+ // draw
+ if (div==60 || t / div)
+ V_DrawPatch(x, y, FB, colon);
+
+ } while (t / div);
+ }
+ else
+ {
+ // "sucks"
+ V_DrawPatch(x - SHORT(sucks->width), y, FB, 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)
+ {
+ // Don't call WI_End yet. G_WorldDone doesnt immediately
+ // change gamestate, so WI_Drawer is still going to get
+ // run until that happens. If we do that after WI_End
+ // (which unloads all the graphics), we're in trouble.
+ //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;
+ int last;
+
+ WI_slamBackground();
+
+ // draw animated background
+ WI_drawAnimatedBack();
+
+ if ( gamemode != commercial)
+ {
+ if (wbs->epsd > 2)
+ {
+ WI_drawEL();
+ return;
+ }
+
+ last = (wbs->last == 8) ? wbs->next - 1 : wbs->last;
+
+ // draw a splat on taken cities.
+ for (i=0 ; i<=last ; i++)
+ WI_drawOnLnode(i, splat);
+
+ // splat the secret level?
+ if (wbs->didsecret)
+ WI_drawOnLnode(8, splat);
+
+ // draw flashing ptr
+ if (snl_pointeron)
+ WI_drawOnLnode(wbs->next, yah);
+ }
+
+ // draws which level you are entering..
+ if ( (gamemode != commercial)
+ || wbs->next != 30)
+ WI_drawEL();
+
+}
+
+void WI_drawNoState(void)
+{
+ snl_pointeron = true;
+ WI_drawShowNextLoc();
+}
+
+int WI_fragSum(int playernum)
+{
+ int i;
+ int frags = 0;
+
+ for (i=0 ; i<MAXPLAYERS ; i++)
+ {
+ if (playeringame[i]
+ && i!=playernum)
+ {
+ frags += plrs[playernum].frags[i];
+ }
+ }
+
+
+ // JDC hack - negative frags.
+ frags -= plrs[playernum].frags[playernum];
+ // UNUSED if (frags < 0)
+ // frags = 0;
+
+ return frags;
+}
+
+
+
+static int dm_state;
+static int dm_frags[MAXPLAYERS][MAXPLAYERS];
+static int dm_totals[MAXPLAYERS];
+
+
+
+void WI_initDeathmatchStats(void)
+{
+
+ int i;
+ int j;
+
+ state = StatCount;
+ acceleratestage = 0;
+ dm_state = 1;
+
+ cnt_pause = TICRATE;
+
+ for (i=0 ; i<MAXPLAYERS ; i++)
+ {
+ if (playeringame[i])
+ {
+ for (j=0 ; j<MAXPLAYERS ; j++)
+ if (playeringame[j])
+ dm_frags[i][j] = 0;
+
+ dm_totals[i] = 0;
+ }
+ }
+
+ WI_initAnimatedBack();
+}
+
+
+
+void WI_updateDeathmatchStats(void)
+{
+
+ int i;
+ int j;
+
+ boolean stillticking;
+
+ WI_updateAnimatedBack();
+
+ if (acceleratestage && dm_state != 4)
+ {
+ acceleratestage = 0;
+
+ for (i=0 ; i<MAXPLAYERS ; i++)
+ {
+ if (playeringame[i])
+ {
+ for (j=0 ; j<MAXPLAYERS ; j++)
+ if (playeringame[j])
+ dm_frags[i][j] = plrs[i].frags[j];
+
+ dm_totals[i] = WI_fragSum(i);
+ }
+ }
+
+
+ S_StartSound(0, sfx_barexp);
+ dm_state = 4;
+ }
+
+
+ if (dm_state == 2)
+ {
+ if (!(bcnt&3))
+ S_StartSound(0, sfx_pistol);
+
+ stillticking = false;
+
+ for (i=0 ; i<MAXPLAYERS ; i++)
+ {
+ if (playeringame[i])
+ {
+ for (j=0 ; j<MAXPLAYERS ; j++)
+ {
+ if (playeringame[j]
+ && dm_frags[i][j] != plrs[i].frags[j])
+ {
+ if (plrs[i].frags[j] < 0)
+ dm_frags[i][j]--;
+ else
+ dm_frags[i][j]++;
+
+ if (dm_frags[i][j] > 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 ( gamemode == 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;
+ int j;
+ int x;
+ int y;
+ int w;
+
+ int lh; // line height
+
+ lh = WI_SPACINGY;
+
+ WI_slamBackground();
+
+ // draw animated background
+ WI_drawAnimatedBack();
+ 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?
+ x = DM_MATRIXX + DM_SPACINGX;
+ y = DM_MATRIXY;
+
+ for (i=0 ; i<MAXPLAYERS ; i++)
+ {
+ if (playeringame[i])
+ {
+ V_DrawPatch(x-SHORT(p[i]->width)/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 ; i<MAXPLAYERS ; i++)
+ {
+ x = DM_MATRIXX + DM_SPACINGX;
+
+ if (playeringame[i])
+ {
+ for (j=0 ; j<MAXPLAYERS ; j++)
+ {
+ if (playeringame[j])
+ WI_drawNum(x+w, y, dm_frags[i][j], 2);
+
+ x += DM_SPACINGX;
+ }
+ WI_drawNum(DM_TOTALSX+w, y, dm_totals[i], 2);
+ }
+ y += WI_SPACINGY;
+ }
+}
+
+static int cnt_frags[MAXPLAYERS];
+static int dofrags;
+static int ng_state;
+
+void WI_initNetgameStats(void)
+{
+
+ int i;
+
+ state = StatCount;
+ acceleratestage = 0;
+ ng_state = 1;
+
+ cnt_pause = TICRATE;
+
+ for (i=0 ; i<MAXPLAYERS ; i++)
+ {
+ if (!playeringame[i])
+ continue;
+
+ cnt_kills[i] = cnt_items[i] = cnt_secret[i] = cnt_frags[i] = 0;
+
+ dofrags += WI_fragSum(i);
+ }
+
+ dofrags = !!dofrags;
+
+ WI_initAnimatedBack();
+}
+
+
+
+void WI_updateNetgameStats(void)
+{
+
+ int i;
+ int fsum;
+
+ boolean stillticking;
+
+ WI_updateAnimatedBack();
+
+ if (acceleratestage && ng_state != 10)
+ {
+ acceleratestage = 0;
+
+ for (i=0 ; i<MAXPLAYERS ; i++)
+ {
+ if (!playeringame[i])
+ continue;
+
+ cnt_kills[i] = (plrs[i].skills * 100) / wbs->maxkills;
+ 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<MAXPLAYERS ; i++)
+ {
+ if (!playeringame[i])
+ continue;
+
+ cnt_kills[i] += 2;
+
+ if (cnt_kills[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<MAXPLAYERS ; i++)
+ {
+ if (!playeringame[i])
+ continue;
+
+ cnt_items[i] += 2;
+ if (cnt_items[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<MAXPLAYERS ; i++)
+ {
+ if (!playeringame[i])
+ continue;
+
+ cnt_secret[i] += 2;
+
+ if (cnt_secret[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<MAXPLAYERS ; i++)
+ {
+ if (!playeringame[i])
+ continue;
+
+ cnt_frags[i] += 1;
+
+ if (cnt_frags[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 ( gamemode == 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;
+ int x;
+ int y;
+ int pwidth = SHORT(percent->width);
+
+ WI_slamBackground();
+
+ // draw animated background
+ WI_drawAnimatedBack();
+
+ 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 ; i<MAXPLAYERS ; i++)
+ {
+ if (!playeringame[i])
+ continue;
+
+ x = NG_STATSX;
+ V_DrawPatch(x-SHORT(p[i]->width), 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 (gamemode == commercial)
+ WI_initNoState();
+ else
+ WI_initShowNextLoc();
+ }
+ }
+ else if (sp_state & 1)
+ {
+ if (!--cnt_pause)
+ {
+ sp_state++;
+ cnt_pause = TICRATE;
+ }
+ }
+
+}
+
+void WI_drawStats(void)
+{
+ // line height
+ int lh;
+
+ lh = (3*SHORT(num[0]->height))/2;
+
+ WI_slamBackground();
+
+ // draw animated background
+ WI_drawAnimatedBack();
+
+ 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, timepatch);
+ WI_drawTime(SCREENWIDTH/2 - SP_TIMEX, SP_TIMEY, cnt_time);
+
+ if (wbs->epsd < 3)
+ {
+ 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 ; i<MAXPLAYERS ; i++, player++)
+ {
+ if (playeringame[i])
+ {
+ if (player->cmd.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)
+{
+ // counter for general background animation
+ bcnt++;
+
+ if (bcnt == 1)
+ {
+ // intermission music
+ if ( gamemode == commercial )
+ S_ChangeMusic(mus_dm2int, true);
+ else
+ S_ChangeMusic(mus_inter, true);
+ }
+
+ 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;
+ }
+
+}
+
+typedef void (*load_callback_t)(char *lumpname, patch_t **variable);
+
+// Common load/unload function. Iterates over all the graphics
+// lumps to be loaded/unloaded into memory.
+
+static void WI_loadUnloadData(load_callback_t callback)
+{
+ int i;
+ int j;
+ char name[9];
+ anim_t* a;
+
+ // UNUSED unsigned char *pic = screens[1];
+ // if (gamemode == commercial)
+ // {
+ // darken the background image
+ // while (pic != screens[1] + SCREENHEIGHT*SCREENWIDTH)
+ // {
+ // *pic = colormaps[256*25 + *pic];
+ // pic++;
+ // }
+ //}
+
+ if (gamemode == commercial)
+ {
+ for (i=0 ; i<NUMCMAPS ; i++)
+ {
+ sprintf(name, DEH_String("CWILV%2.2d"), i);
+ callback(name, &lnames[i]);
+ }
+ }
+ else
+ {
+ for (i=0 ; i<NUMMAPS ; i++)
+ {
+ sprintf(name, DEH_String("WILV%d%d"), wbs->epsd, i);
+ callback(name, &lnames[i]);
+ }
+
+ // you are here
+ callback(DEH_String("WIURH0"), &yah[0]);
+
+ // you are here (alt.)
+ callback(DEH_String("WIURH1"), &yah[1]);
+
+ // splat
+ callback(DEH_String("WISPLAT"), &splat[0]);
+
+ if (wbs->epsd < 3)
+ {
+ for (j=0;j<NUMANIMS[wbs->epsd];j++)
+ {
+ a = &anims[wbs->epsd][j];
+ for (i=0;i<a->nanims;i++)
+ {
+ // MONDO HACK!
+ if (wbs->epsd != 1 || j != 8)
+ {
+ // animations
+ sprintf(name, DEH_String("WIA%d%.2d%.2d"),
+ wbs->epsd, j, i);
+ callback(name, &a->p[i]);
+ }
+ else
+ {
+ // HACK ALERT!
+ a->p[i] = anims[1][4].p[i];
+ }
+ }
+ }
+ }
+ }
+
+ // More hacks on minus sign.
+ callback(DEH_String("WIMINUS"), &wiminus);
+
+ for (i=0;i<10;i++)
+ {
+ // numbers 0-9
+ sprintf(name, DEH_String("WINUM%d"), i);
+ callback(name, &num[i]);
+ }
+
+ // percent sign
+ callback(DEH_String("WIPCNT"), &percent);
+
+ // "finished"
+ callback(DEH_String("WIF"), &finished);
+
+ // "entering"
+ callback(DEH_String("WIENTER"), &entering);
+
+ // "kills"
+ callback(DEH_String("WIOSTK"), &kills);
+
+ // "scrt"
+ callback(DEH_String("WIOSTS"), &secret);
+
+ // "secret"
+ callback(DEH_String("WISCRT2"), &sp_secret);
+
+ // french wad uses WIOBJ (?)
+ if (W_CheckNumForName(DEH_String("WIOBJ")) >= 0)
+ {
+ // "items"
+ if (netgame && !deathmatch)
+ callback(DEH_String("WIOBJ"), &items);
+ else
+ callback(DEH_String("WIOSTI"), &items);
+ } else {
+ callback(DEH_String("WIOSTI"), &items);
+ }
+
+ // "frgs"
+ callback(DEH_String("WIFRGS"), &frags);
+
+ // ":"
+ callback(DEH_String("WICOLON"), &colon);
+
+ // "time"
+ callback(DEH_String("WITIME"), &timepatch);
+
+ // "sucks"
+ callback(DEH_String("WISUCKS"), &sucks);
+
+ // "par"
+ callback(DEH_String("WIPAR"), &par);
+
+ // "killers" (vertical)
+ callback(DEH_String("WIKILRS"), &killers);
+
+ // "victims" (horiz)
+ callback(DEH_String("WIVCTMS"), &victims);
+
+ // "total"
+ callback(DEH_String("WIMSTT"), &total);
+
+ for (i=0 ; i<MAXPLAYERS ; i++)
+ {
+ // "1,2,3,4"
+ sprintf(name, DEH_String("STPB%d"), i);
+ callback(name, &p[i]);
+
+ // "1,2,3,4"
+ sprintf(name, DEH_String("WIBP%d"), i+1);
+ callback(name, &bp[i]);
+ }
+
+}
+
+static void WI_loadCallback(char *name, patch_t **variable)
+{
+ *variable = W_CacheLumpName(name, PU_STATIC);
+}
+
+void WI_loadData(void)
+{
+ char bg_lumpname[9];
+ patch_t *bg;
+
+ if (gamemode == commercial)
+ {
+ NUMCMAPS = 32;
+ lnames = (patch_t **) Z_Malloc(sizeof(patch_t*) * NUMCMAPS,
+ PU_STATIC, NULL);
+ }
+ else
+ {
+ lnames = (patch_t **) Z_Malloc(sizeof(patch_t*) * NUMMAPS,
+ PU_STATIC, NULL);
+ }
+
+ WI_loadUnloadData(WI_loadCallback);
+
+ // These two graphics are special cased because we're sharing
+ // them with the status bar code
+
+ // your face
+ star = W_CacheLumpName(DEH_String("STFST01"), PU_STATIC);
+
+ // dead face
+ bstar = W_CacheLumpName(DEH_String("STFDEAD0"), PU_STATIC);
+
+ // Background image
+
+ if (gamemode == commercial)
+ {
+ strcpy(bg_lumpname, DEH_String("INTERPIC"));
+ }
+ else if (gamemode == retail && wbs->epsd == 3)
+ {
+ strcpy(bg_lumpname, DEH_String("INTERPIC"));
+ }
+ else
+ {
+ sprintf(bg_lumpname, DEH_String("WIMAP%d"), wbs->epsd);
+ }
+
+ bg = W_CacheLumpName(bg_lumpname, PU_CACHE);
+ V_DrawPatch(0, 0, 1, bg);
+}
+
+static void WI_unloadCallback(char *name, patch_t **variable)
+{
+ W_ReleaseLumpName(name);
+ *variable = NULL;
+}
+
+void WI_unloadData(void)
+{
+ WI_loadUnloadData(WI_unloadCallback);
+
+ // We do not free these lumps as they are shared with the status
+ // bar code.
+
+ // W_ReleaseLumpName("STFST01");
+ // W_ReleaseLumpName("STFDEAD0");
+}
+
+void WI_Drawer (void)
+{
+ switch (state)
+ {
+ case StatCount:
+ if (deathmatch)
+ WI_drawDeathmatchStats();
+ else if (netgame)
+ WI_drawNetgameStats();
+ else
+ WI_drawStats();
+ break;
+
+ case ShowNextLoc:
+ WI_drawShowNextLoc();
+ break;
+
+ case NoState:
+ WI_drawNoState();
+ break;
+ }
+}
+
+
+void WI_initVariables(wbstartstruct_t* wbstartstruct)
+{
+
+ wbs = wbstartstruct;
+
+#ifdef RANGECHECKING
+ if (gamemode != commercial)
+ {
+ if ( gamemode == retail )
+ RNGCHECK(wbs->epsd, 0, 3);
+ else
+ RNGCHECK(wbs->epsd, 0, 2);
+ }
+ else
+ {
+ 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 ( gamemode != retail )
+ 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();
+}
--- /dev/null
+++ b/src/doom/wi_stuff.h
@@ -1,0 +1,56 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION:
+// Intermission.
+//
+//-----------------------------------------------------------------------------
+
+#ifndef __WI_STUFF__
+#define __WI_STUFF__
+
+//#include "v_video.h"
+
+#include "doomdef.h"
+
+// States for the intermission
+
+typedef enum
+{
+ NoState = -1,
+ StatCount,
+ ShowNextLoc,
+} stateenum_t;
+
+// Called by main loop, animate the intermission.
+void WI_Ticker (void);
+
+// Called by main loop,
+// draws the intermission directly into the screen buffer.
+void WI_Drawer (void);
+
+// Setup for an intermission screen.
+void WI_Start(wbstartstruct_t* wbstartstruct);
+
+// Shut down the intermission screen
+void WI_End(void);
+
+#endif
--- a/src/doomdata.h
+++ /dev/null
@@ -1,221 +1,0 @@
-// Emacs style mode select -*- C++ -*-
-//-----------------------------------------------------------------------------
-//
-// Copyright(C) 1993-1996 Id Software, Inc.
-// Copyright(C) 2005 Simon Howard
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-// 02111-1307, USA.
-//
-// DESCRIPTION:
-// all external data is defined here
-// most of the data is loaded into different structures at run time
-// some internal structures shared by many modules are here
-//
-//-----------------------------------------------------------------------------
-
-#ifndef __DOOMDATA__
-#define __DOOMDATA__
-
-// The most basic types we use, portability.
-#include "doomtype.h"
-
-// Some global defines, that configure the game.
-#include "doomdef.h"
-
-
-
-//
-// Map level types.
-// The following data structures define the persistent format
-// used in the lumps of the WAD files.
-//
-
-// Lump order in a map WAD: each map needs a couple of lumps
-// to provide a complete scene geometry description.
-enum
-{
- ML_LABEL, // A separator, name, ExMx or MAPxx
- ML_THINGS, // Monsters, items..
- ML_LINEDEFS, // LineDefs, from editing
- ML_SIDEDEFS, // SideDefs, from editing
- ML_VERTEXES, // Vertices, edited and BSP splits generated
- ML_SEGS, // LineSegs, from LineDefs split by BSP
- ML_SSECTORS, // SubSectors, list of LineSegs
- ML_NODES, // BSP nodes
- ML_SECTORS, // Sectors, from editing
- ML_REJECT, // LUT, sector-sector visibility
- ML_BLOCKMAP // LUT, motion clipping, walls/grid element
-};
-
-
-// A single Vertex.
-typedef struct
-{
- short x;
- short y;
-} PACKEDATTR mapvertex_t;
-
-
-// A SideDef, defining the visual appearance of a wall,
-// by setting textures and offsets.
-typedef struct
-{
- short textureoffset;
- short rowoffset;
- char toptexture[8];
- char bottomtexture[8];
- char midtexture[8];
- // Front sector, towards viewer.
- short sector;
-} PACKEDATTR mapsidedef_t;
-
-
-
-// A LineDef, as used for editing, and as input
-// to the BSP builder.
-typedef struct
-{
- short v1;
- short v2;
- short flags;
- short special;
- short tag;
- // sidenum[1] will be -1 if one sided
- short sidenum[2];
-} PACKEDATTR maplinedef_t;
-
-
-//
-// LineDef attributes.
-//
-
-// Solid, is an obstacle.
-#define ML_BLOCKING 1
-
-// Blocks monsters only.
-#define ML_BLOCKMONSTERS 2
-
-// Backside will not be present at all
-// if not two sided.
-#define ML_TWOSIDED 4
-
-// If a texture is pegged, the texture will have
-// the end exposed to air held constant at the
-// top or bottom of the texture (stairs or pulled
-// down things) and will move with a height change
-// of one of the neighbor sectors.
-// Unpegged textures allways have the first row of
-// the texture at the top pixel of the line for both
-// top and bottom textures (use next to windows).
-
-// upper texture unpegged
-#define ML_DONTPEGTOP 8
-
-// lower texture unpegged
-#define ML_DONTPEGBOTTOM 16
-
-// In AutoMap: don't map as two sided: IT'S A SECRET!
-#define ML_SECRET 32
-
-// Sound rendering: don't let sound cross two of these.
-#define ML_SOUNDBLOCK 64
-
-// Don't draw on the automap at all.
-#define ML_DONTDRAW 128
-
-// Set if already seen, thus drawn in automap.
-#define ML_MAPPED 256
-
-
-
-
-// Sector definition, from editing.
-typedef struct
-{
- short floorheight;
- short ceilingheight;
- char floorpic[8];
- char ceilingpic[8];
- short lightlevel;
- short special;
- short tag;
-} PACKEDATTR mapsector_t;
-
-// SubSector, as generated by BSP.
-typedef struct
-{
- short numsegs;
- // Index of first one, segs are stored sequentially.
- short firstseg;
-} PACKEDATTR mapsubsector_t;
-
-
-// LineSeg, generated by splitting LineDefs
-// using partition lines selected by BSP builder.
-typedef struct
-{
- short v1;
- short v2;
- short angle;
- short linedef;
- short side;
- short offset;
-} PACKEDATTR mapseg_t;
-
-
-
-// BSP node structure.
-
-// Indicate a leaf.
-#define NF_SUBSECTOR 0x8000
-
-typedef struct
-{
- // Partition line from (x,y) to x+dx,y+dy)
- short x;
- short y;
- short dx;
- short dy;
-
- // Bounding box for each child,
- // clip against view frustum.
- short bbox[2][4];
-
- // If NF_SUBSECTOR its a subsector,
- // else it's a node of another subtree.
- unsigned short children[2];
-
-} PACKEDATTR mapnode_t;
-
-
-
-
-// Thing definition, position, orientation and type,
-// plus skill/visibility flags and attributes.
-typedef struct
-{
- short x;
- short y;
- short angle;
- short type;
- short options;
-} PACKEDATTR mapthing_t;
-
-
-
-
-
-#endif // __DOOMDATA__
--- a/src/doomdef.c
+++ /dev/null
@@ -1,36 +1,0 @@
-// Emacs style mode select -*- C++ -*-
-//-----------------------------------------------------------------------------
-//
-// Copyright(C) 1993-1996 Id Software, Inc.
-// Copyright(C) 2005 Simon Howard
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-// 02111-1307, USA.
-//
-// DESCRIPTION:
-// DoomDef - basic defines for DOOM, e.g. Version, game mode
-// and skill level, and display parameters.
-//
-//-----------------------------------------------------------------------------
-
-
-
-#include "doomdef.h"
-
-// Location for any defines turned variables.
-
-// None.
-
-
--- a/src/doomdef.h
+++ /dev/null
@@ -1,312 +1,0 @@
-// Emacs style mode select -*- C++ -*-
-//-----------------------------------------------------------------------------
-//
-// Copyright(C) 1993-1996 Id Software, Inc.
-// Copyright(C) 2005 Simon Howard
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-// 02111-1307, USA.
-//
-// DESCRIPTION:
-// Internally used data structures for virtually everything,
-// lots of other stuff.
-//
-//-----------------------------------------------------------------------------
-
-#ifndef __DOOMDEF__
-#define __DOOMDEF__
-
-#include <stdio.h>
-#include <string.h>
-
-// #define macros to provide functions missing in Windows.
-// Outside Windows, we use strings.h for str[n]casecmp.
-
-
-#ifdef _WIN32
-
-#define snprintf _snprintf
-#define vsnprintf _vsnprintf
-#define strcasecmp stricmp
-#define strncasecmp strnicmp
-
-#else
-
-#include <strings.h>
-
-#endif
-
-
-//
-// The packed attribute forces structures to be packed into the minimum
-// space necessary. If this is not done, the compiler may align structure
-// fields differently to optimise memory access, inflating the overall
-// structure size. It is important to use the packed attribute on certain
-// structures where alignment is important, particularly data read/written
-// to disk.
-//
-
-#ifdef __GNUC__
-#define PACKEDATTR __attribute__((packed))
-#else
-#define PACKEDATTR
-#endif
-
-//
-// Global parameters/defines.
-//
-// DOOM version
-#define DOOM_VERSION 109
-
-// Version code for cph's longtics hack ("v1.91")
-#define DOOM_191_VERSION 111
-
-
-// Game mode handling - identify IWAD version
-// to handle IWAD dependend animations etc.
-typedef enum
-{
- shareware, // DOOM 1 shareware, E1, M9
- registered, // DOOM 1 registered, E3, M27
- commercial, // DOOM 2 retail, E1 M34
- // DOOM 2 german edition not handled
- retail, // DOOM 1 retail, E4, M36
- indetermined // Well, no IWAD found.
-
-} GameMode_t;
-
-
-// Mission packs - might be useful for TC stuff?
-typedef enum
-{
- doom, // DOOM 1
- doom2, // DOOM 2
- pack_tnt, // TNT mission pack
- pack_plut, // Plutonia pack
- none
-
-} GameMission_t;
-
-// What version are we emulating?
-
-typedef enum
-{
- exe_doom_1_9, // Doom 1.9: used for shareware, registered and commercial
- exe_ultimate, // Ultimate Doom (retail)
- exe_final, // Final Doom
- exe_chex, // Chex Quest executable (based on Final Doom)
-} GameVersion_t;
-
-
-// If rangecheck is undefined,
-// most parameter validation debugging code will not be compiled
-#define RANGECHECK
-
-
-
-// Screen width and height.
-
-#define SCREENWIDTH 320
-#define SCREENHEIGHT 200
-
-// Screen width used for "squash" scale functions
-
-#define SCREENWIDTH_4_3 256
-
-// Screen height used for "stretch" scale functions.
-
-#define SCREENHEIGHT_4_3 240
-
-// The maximum number of players, multiplayer/networking.
-#define MAXPLAYERS 4
-
-// State updates, number of tics / second.
-#define TICRATE 35
-
-// The current state of the game: whether we are
-// playing, gazing at the intermission screen,
-// the game final animation, or a demo.
-typedef enum
-{
- GS_LEVEL,
- GS_INTERMISSION,
- GS_FINALE,
- GS_DEMOSCREEN,
-} gamestate_t;
-
-//
-// Difficulty/skill settings/filters.
-//
-
-// Skill flags.
-#define MTF_EASY 1
-#define MTF_NORMAL 2
-#define MTF_HARD 4
-
-// Deaf monsters/do not react to sound.
-#define MTF_AMBUSH 8
-
-typedef enum
-{
- sk_noitems = -1, // the "-skill 0" hack
- sk_baby = 0,
- sk_easy,
- sk_medium,
- sk_hard,
- sk_nightmare
-} skill_t;
-
-
-
-
-//
-// Key cards.
-//
-typedef enum
-{
- it_bluecard,
- it_yellowcard,
- it_redcard,
- it_blueskull,
- it_yellowskull,
- it_redskull,
-
- NUMCARDS
-
-} card_t;
-
-
-
-// The defined weapons,
-// including a marker indicating
-// user has not changed weapon.
-typedef enum
-{
- wp_fist,
- wp_pistol,
- wp_shotgun,
- wp_chaingun,
- wp_missile,
- wp_plasma,
- wp_bfg,
- wp_chainsaw,
- wp_supershotgun,
-
- NUMWEAPONS,
-
- // No pending weapon change.
- wp_nochange
-
-} weapontype_t;
-
-
-// Ammunition types defined.
-typedef enum
-{
- am_clip, // Pistol / chaingun ammo.
- am_shell, // Shotgun / double barreled shotgun.
- am_cell, // Plasma rifle, BFG.
- am_misl, // Missile launcher.
- NUMAMMO,
- am_noammo // Unlimited for chainsaw / fist.
-
-} ammotype_t;
-
-
-// Power up artifacts.
-typedef enum
-{
- pw_invulnerability,
- pw_strength,
- pw_invisibility,
- pw_ironfeet,
- pw_allmap,
- pw_infrared,
- NUMPOWERS
-
-} powertype_t;
-
-
-
-//
-// Power up durations,
-// how many seconds till expiration,
-// assuming TICRATE is 35 ticks/second.
-//
-typedef enum
-{
- INVULNTICS = (30*TICRATE),
- INVISTICS = (60*TICRATE),
- INFRATICS = (120*TICRATE),
- IRONTICS = (60*TICRATE)
-
-} powerduration_t;
-
-
-// fraggle: moved key definitions to a separate file
-
-#include "doomkeys.h"
-
-
-// DOOM basic types (boolean),
-// and max/min values.
-//#include "doomtype.h"
-
-// Fixed point.
-//#include "m_fixed.h"
-
-// Endianess handling.
-//#include "m_swap.h"
-
-
-// Binary Angles, sine/cosine/atan lookups.
-//#include "tables.h"
-
-// Event type.
-//#include "d_event.h"
-
-// Game function, skills.
-//#include "g_game.h"
-
-// All external data is defined here.
-//#include "doomdata.h"
-
-// All important printed strings.
-// Language selection (message strings).
-//#include "dstrings.h"
-
-// Player is a special actor.
-//struct player_s;
-
-
-//#include "d_items.h"
-//#include "d_player.h"
-//#include "p_mobj.h"
-//#include "d_net.h"
-
-// PLAY
-//#include "p_tick.h"
-
-
-
-
-// Header, generated by sound utility.
-// The utility was written by Dave Taylor.
-//#include "sounds.h"
-
-
-
-
-#endif // __DOOMDEF__
--- a/src/doomstat.c
+++ /dev/null
@@ -1,43 +1,0 @@
-// Emacs style mode select -*- C++ -*-
-//-----------------------------------------------------------------------------
-//
-// Copyright(C) 1993-1996 Id Software, Inc.
-// Copyright(C) 2005 Simon Howard
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-// 02111-1307, USA.
-//
-// DESCRIPTION:
-// Put all global tate variables here.
-//
-//-----------------------------------------------------------------------------
-
-
-
-#include "doomstat.h"
-
-
-// Game Mode - identify IWAD as shareware, retail etc.
-GameMode_t gamemode = indetermined;
-GameMission_t gamemission = doom;
-GameVersion_t gameversion = exe_final;
-char *gamedescription;
-
-// Set if homebrew PWAD stuff has been added.
-boolean modifiedgame;
-
-
-
-
--- a/src/doomstat.h
+++ /dev/null
@@ -1,300 +1,0 @@
-// Emacs style mode select -*- C++ -*-
-//-----------------------------------------------------------------------------
-//
-// Copyright(C) 1993-1996 Id Software, Inc.
-// Copyright(C) 2005 Simon Howard
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-// 02111-1307, USA.
-//
-// DESCRIPTION:
-// All the global variables that store the internal state.
-// Theoretically speaking, the internal state of the engine
-// should be found by looking at the variables collected
-// here, and every relevant module will have to include
-// this header file.
-// In practice, things are a bit messy.
-//
-//-----------------------------------------------------------------------------
-
-
-#ifndef __D_STATE__
-#define __D_STATE__
-
-// We need globally shared data structures,
-// for defining the global state variables.
-#include "doomdata.h"
-#include "d_net.h"
-
-// We need the playr data structure as well.
-#include "d_player.h"
-
-
-
-
-
-// ------------------------
-// Command line parameters.
-//
-extern boolean nomonsters; // checkparm of -nomonsters
-extern boolean respawnparm; // checkparm of -respawn
-extern boolean fastparm; // checkparm of -fast
-
-extern boolean devparm; // DEBUG: launched with -devparm
-
-
-extern boolean screensaver_mode; // game running as a screensaver?
-
-// -----------------------------------------------------
-// Game Mode - identify IWAD as shareware, retail etc.
-//
-extern GameMode_t gamemode;
-extern GameMission_t gamemission;
-extern GameVersion_t gameversion;
-extern char *gamedescription;
-
-// Set if homebrew PWAD stuff has been added.
-extern boolean modifiedgame;
-
-
-// -------------------------------------------
-// Selected skill type, map etc.
-//
-
-// Defaults for menu, methinks.
-extern skill_t startskill;
-extern int startepisode;
-extern int startmap;
-
-// Savegame slot to load on startup. This is the value provided to
-// the -loadgame option. If this has not been provided, this is -1.
-
-extern int startloadgame;
-
-extern boolean autostart;
-
-// Selected by user.
-extern skill_t gameskill;
-extern int gameepisode;
-extern int gamemap;
-
-// If non-zero, exit the level after this number of minutes
-extern int timelimit;
-
-// vertical movement from mouse/joystick disabled
-extern int novert;
-
-// Nightmare mode flag, single player.
-extern boolean respawnmonsters;
-
-// Netgame? Only true if >1 player.
-extern boolean netgame;
-
-// Flag: true only if started as net deathmatch.
-// An enum might handle altdeath/cooperative better.
-extern boolean deathmatch;
-
-// -------------------------
-// Internal parameters for sound rendering.
-// These have been taken from the DOS version,
-// but are not (yet) supported with Linux
-// (e.g. no sound volume adjustment with menu.
-
-// From m_menu.c:
-// Sound FX volume has default, 0 - 15
-// Music volume has default, 0 - 15
-// These are multiplied by 8.
-extern int sfxVolume;
-extern int musicVolume;
-
-// Current music/sfx card - index useless
-// w/o a reference LUT in a sound module.
-// Ideally, this would use indices found
-// in: /usr/include/linux/soundcard.h
-extern int snd_MusicDevice;
-extern int snd_SfxDevice;
-// Config file? Same disclaimer as above.
-extern int snd_DesiredMusicDevice;
-extern int snd_DesiredSfxDevice;
-
-
-// -------------------------
-// Status flags for refresh.
-//
-
-// Depending on view size - no status bar?
-// Note that there is no way to disable the
-// status bar explicitely.
-extern boolean statusbaractive;
-
-extern boolean automapactive; // In AutoMap mode?
-extern boolean menuactive; // Menu overlayed?
-extern boolean paused; // Game Pause?
-
-
-extern boolean viewactive;
-
-extern boolean nodrawers;
-extern boolean noblit;
-
-extern int viewwindowx;
-extern int viewwindowy;
-extern int viewheight;
-extern int viewwidth;
-extern int scaledviewwidth;
-
-extern boolean testcontrols;
-
-
-
-
-// This one is related to the 3-screen display mode.
-// ANG90 = left side, ANG270 = right
-extern int viewangleoffset;
-
-// Player taking events, and displaying.
-extern int consoleplayer;
-extern int displayplayer;
-
-
-// -------------------------------------
-// Scores, rating.
-// Statistics on a given map, for intermission.
-//
-extern int totalkills;
-extern int totalitems;
-extern int totalsecret;
-
-// Timer, for scores.
-extern int levelstarttic; // gametic at level start
-extern int leveltime; // tics in game play for par
-
-
-
-// --------------------------------------
-// DEMO playback/recording related stuff.
-// No demo, there is a human player in charge?
-// Disable save/end game?
-extern boolean usergame;
-
-//?
-extern boolean demoplayback;
-extern boolean demorecording;
-
-// Round angleturn in ticcmds to the nearest 256. This is used when
-// recording Vanilla demos in netgames.
-
-extern boolean lowres_turn;
-
-// Quit after playing a demo from cmdline.
-extern boolean singledemo;
-
-
-
-
-//?
-extern gamestate_t gamestate;
-
-
-
-
-
-
-//-----------------------------
-// Internal parameters, fixed.
-// These are set by the engine, and not changed
-// according to user inputs. Partly load from
-// WAD, partly set at startup time.
-
-
-
-extern int gametic;
-
-
-// Bookkeeping on players - state.
-extern player_t players[MAXPLAYERS];
-
-// Alive? Disconnected?
-extern boolean playeringame[MAXPLAYERS];
-
-
-// Player spawn spots for deathmatch.
-#define MAX_DM_STARTS 10
-extern mapthing_t deathmatchstarts[MAX_DM_STARTS];
-extern mapthing_t* deathmatch_p;
-
-// Player spawn spots.
-extern mapthing_t playerstarts[MAXPLAYERS];
-
-// Intermission stats.
-// Parameters for world map / intermission.
-extern wbstartstruct_t wminfo;
-
-
-// LUT of ammunition limits for each kind.
-// This doubles with BackPack powerup item.
-extern int maxammo[NUMAMMO];
-
-
-
-
-
-//-----------------------------------------
-// Internal parameters, used for engine.
-//
-
-// File handling stuff.
-extern char * savegamedir;
-extern char basedefault[1024];
-extern FILE* debugfile;
-
-// if true, load all graphics at level load
-extern boolean precache;
-
-
-// wipegamestate can be set to -1
-// to force a wipe on the next draw
-extern gamestate_t wipegamestate;
-
-extern int mouseSensitivity;
-//?
-// debug flag to cancel adaptiveness
-extern boolean singletics;
-
-extern int bodyqueslot;
-
-
-
-// Needed to store the number of the dummy sky flat.
-// Used for rendering,
-// as well as tracking projectiles etc.
-extern int skyflatnum;
-
-
-
-// Netgame stuff (buffers and pointers, i.e. indices).
-
-
-extern int rndindex;
-
-extern int maketic;
-extern int nettics[MAXPLAYERS];
-
-extern ticcmd_t netcmds[MAXPLAYERS][BACKUPTICS];
-extern int ticdup;
-
-
-
-#endif
--- a/src/dstrings.c
+++ /dev/null
@@ -1,81 +1,0 @@
-// Emacs style mode select -*- C++ -*-
-//-----------------------------------------------------------------------------
-//
-// Copyright(C) 1993-1996 Id Software, Inc.
-// Copyright(C) 2005 Simon Howard
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-// 02111-1307, USA.
-//
-// DESCRIPTION:
-// Globally defined strings.
-//
-//-----------------------------------------------------------------------------
-
-
-
-#include "dstrings.h"
-
-char *doom1_endmsg[] =
-{
- "are you sure you want to\nquit this great game?",
- "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.",
-};
-
-char *doom2_endmsg[] =
-{
- // QuitDOOM II messages
- "are you sure you want to\nquit this great game?",
- "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.",
-};
-
-#if 0
-
-// UNUSED messages included in the source release
-
-char* endmsg[] =
-{
- // DOOM1
- QUITMSG,
- // FinalDOOM?
- "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!",
-
- // Internal debug. Different style, too.
- "THIS IS NO MESSAGE!\nPage intentionally left blank."
-};
-
-#endif
-
-
-
-
--- a/src/dstrings.h
+++ /dev/null
@@ -1,58 +1,0 @@
-// Emacs style mode select -*- C++ -*-
-//-----------------------------------------------------------------------------
-//
-// Copyright(C) 1993-1996 Id Software, Inc.
-// Copyright(C) 2005 Simon Howard
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-// 02111-1307, USA.
-//
-//
-// DESCRIPTION:
-// DOOM strings, by language.
-//
-//-----------------------------------------------------------------------------
-
-
-#ifndef __DSTRINGS__
-#define __DSTRINGS__
-
-
-// All important printed strings.
-
-#include "d_englsh.h"
-
-// Misc. other strings.
-#define SAVEGAMENAME "doomsav"
-
-
-//
-// File locations,
-// relative to current position.
-// Path names are OS-sensitive.
-//
-#define DEVMAPS "devmaps"
-#define DEVDATA "devdata"
-
-
-// QuitDOOM messages
-// 8 per each game type
-#define NUM_QUITMESSAGES 8
-
-extern char *doom1_endmsg[];
-extern char *doom2_endmsg[];
-
-
-#endif
--- a/src/f_finale.c
+++ /dev/null
@@ -1,728 +1,0 @@
-// Emacs style mode select -*- C++ -*-
-//-----------------------------------------------------------------------------
-//
-// Copyright(C) 1993-1996 Id Software, Inc.
-// Copyright(C) 2005 Simon Howard
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-// 02111-1307, USA.
-//
-// DESCRIPTION:
-// Game completion, final screen animation.
-//
-//-----------------------------------------------------------------------------
-
-
-
-#include <ctype.h>
-
-// Functions.
-#include "deh_main.h"
-#include "i_system.h"
-#include "i_swap.h"
-#include "z_zone.h"
-#include "v_video.h"
-#include "w_wad.h"
-#include "s_sound.h"
-
-// Data.
-#include "dstrings.h"
-#include "sounds.h"
-
-#include "doomstat.h"
-#include "r_state.h"
-
-typedef enum
-{
- F_STAGE_TEXT,
- F_STAGE_ARTSCREEN,
- F_STAGE_CAST,
-} finalestage_t;
-
-// ?
-//#include "doomstat.h"
-//#include "r_local.h"
-//#include "f_finale.h"
-
-// Stage of animation:
-finalestage_t finalestage;
-
-unsigned int finalecount;
-
-#define TEXTSPEED 3
-#define TEXTWAIT 250
-
-typedef struct
-{
- GameMission_t mission;
- int episode, level;
- char *background;
- char *text;
-} textscreen_t;
-
-static textscreen_t textscreens[] =
-{
- { doom, 1, 8, "FLOOR4_8", E1TEXT},
- { doom, 2, 8, "SFLR6_1", E2TEXT},
- { doom, 3, 8, "MFLR8_4", E3TEXT},
- { doom, 4, 8, "MFLR8_3", E4TEXT},
-
- { doom2, 1, 6, "SLIME16", C1TEXT},
- { doom2, 1, 11, "RROCK14", C2TEXT},
- { doom2, 1, 20, "RROCK07", C3TEXT},
- { doom2, 1, 30, "RROCK17", C4TEXT},
- { doom2, 1, 15, "RROCK13", C5TEXT},
- { doom2, 1, 31, "RROCK19", C6TEXT},
-
- { pack_tnt, 1, 6, "SLIME16", T1TEXT},
- { pack_tnt, 1, 11, "RROCK14", T2TEXT},
- { pack_tnt, 1, 20, "RROCK07", T3TEXT},
- { pack_tnt, 1, 30, "RROCK17", T4TEXT},
- { pack_tnt, 1, 15, "RROCK13", T5TEXT},
- { pack_tnt, 1, 31, "RROCK19", T6TEXT},
-
- { pack_plut, 1, 6, "SLIME16", P1TEXT},
- { pack_plut, 1, 11, "RROCK14", P2TEXT},
- { pack_plut, 1, 20, "RROCK07", P3TEXT},
- { pack_plut, 1, 30, "RROCK17", P4TEXT},
- { pack_plut, 1, 15, "RROCK13", P5TEXT},
- { pack_plut, 1, 31, "RROCK19", P6TEXT},
-};
-
-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)
-{
- size_t i;
-
- gameaction = ga_nothing;
- gamestate = GS_FINALE;
- viewactive = false;
- automapactive = false;
-
- if (gamemission == doom)
- {
- S_ChangeMusic(mus_victor, true);
- }
- else
- {
- S_ChangeMusic(mus_read_m, true);
- }
-
- // Find the right screen and set the text and background
-
- for (i=0; i<arrlen(textscreens); ++i)
- {
- textscreen_t *screen = &textscreens[i];
-
- // Hack for Chex Quest
-
- if (gameversion == exe_chex && screen->mission == doom)
- {
- screen->level = 5;
- }
-
- if (gamemission == screen->mission
- && (gamemission != doom || gameepisode == screen->episode)
- && gamemap == screen->level)
- {
- finaletext = screen->text;
- finaleflat = screen->background;
- }
- }
-
- // Do dehacked substitutions of strings
-
- finaletext = DEH_String(finaletext);
- finaleflat = DEH_String(finaleflat);
-
- finalestage = F_STAGE_TEXT;
- finalecount = 0;
-
-}
-
-
-
-boolean F_Responder (event_t *event)
-{
- if (finalestage == F_STAGE_CAST)
- return F_CastResponder (event);
-
- return false;
-}
-
-
-//
-// F_Ticker
-//
-void F_Ticker (void)
-{
- size_t i;
-
- // check for skipping
- if ( (gamemode == commercial)
- && ( finalecount > 50) )
- {
- // go on to the next level
- for (i=0 ; i<MAXPLAYERS ; i++)
- if (players[i].cmd.buttons)
- break;
-
- if (i < MAXPLAYERS)
- {
- if (gamemap == 30)
- F_StartCast ();
- else
- gameaction = ga_worlddone;
- }
- }
-
- // advance animation
- finalecount++;
-
- if (finalestage == F_STAGE_CAST)
- {
- F_CastTicker ();
- return;
- }
-
- if ( gamemode == commercial)
- return;
-
- if (finalestage == F_STAGE_TEXT
- && finalecount>strlen (finaletext)*TEXTSPEED + TEXTWAIT)
- {
- finalecount = 0;
- finalestage = F_STAGE_ARTSCREEN;
- 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;
- byte* dest;
-
- int x,y,w;
- signed int count;
- char* ch;
- int c;
- int cx;
- int cy;
-
- // erase the entire screen to a tiled background
- src = W_CacheLumpName ( finaleflat , PU_CACHE);
- dest = screens[0];
-
- for (y=0 ; y<SCREENHEIGHT ; y++)
- {
- for (x=0 ; x<SCREENWIDTH/64 ; x++)
- {
- memcpy (dest, src+((y&63)<<6), 64);
- dest += 64;
- }
- if (SCREENWIDTH&63)
- {
- memcpy (dest, src+((y&63)<<6), SCREENWIDTH&63);
- dest += (SCREENWIDTH&63);
- }
- }
-
- V_MarkRect (0, 0, SCREENWIDTH, SCREENHEIGHT);
-
- // draw some of the text onto the screen
- cx = 10;
- cy = 10;
- ch = finaletext;
-
- count = ((signed int) finalecount - 10) / TEXTSPEED;
- if (count < 0)
- count = 0;
- for ( ; count ; count-- )
- {
- c = *ch++;
- if (!c)
- break;
- if (c == '\n')
- {
- cx = 10;
- cy += 11;
- 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_DrawPatch(cx, cy, 0, hu_font[c]);
- cx+=w;
- }
-
-}
-
-//
-// Final DOOM 2 animation
-// Casting by id Software.
-// in order of appearance
-//
-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 = F_STAGE_CAST;
- 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;
- int 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 (DEH_String("BOSSBACK"), PU_CACHE));
-
- F_CastPrint (DEH_String(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;
- byte* dest;
- byte* 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)
-{
- signed int scrolled;
- int x;
- patch_t* p1;
- patch_t* p2;
- char name[10];
- int stage;
- static int laststage;
-
- p1 = W_CacheLumpName (DEH_String("PFUB2"), PU_LEVEL);
- p2 = W_CacheLumpName (DEH_String("PFUB1"), PU_LEVEL);
-
- V_MarkRect (0, 0, SCREENWIDTH, SCREENHEIGHT);
-
- scrolled = (320 - ((signed int) finalecount-230)/2);
- if (scrolled > 320)
- scrolled = 320;
- if (scrolled < 0)
- scrolled = 0;
-
- for ( x=0 ; x<SCREENWIDTH ; x++)
- {
- if (x+scrolled < 320)
- F_DrawPatchCol (x, p1, x+scrolled);
- else
- F_DrawPatchCol (x, p2, x+scrolled - 320);
- }
-
- if (finalecount < 1130)
- return;
- if (finalecount < 1180)
- {
- V_DrawPatch ((SCREENWIDTH-13*8)/2,
- (SCREENHEIGHT-8*8)/2,0,
- W_CacheLumpName (DEH_String("END0"),PU_CACHE));
- laststage = 0;
- return;
- }
-
- stage = (finalecount-1180) / 5;
- if (stage > 6)
- stage = 6;
- if (stage > laststage)
- {
- S_StartSound (NULL, sfx_pistol);
- laststage = stage;
- }
-
- sprintf (name, DEH_String("END%i"), stage);
- V_DrawPatch ((SCREENWIDTH-13*8)/2, (SCREENHEIGHT-8*8)/2,0,
- W_CacheLumpName (name,PU_CACHE));
-}
-
-static void F_ArtScreenDrawer(void)
-{
- char *lumpname;
-
- if (gameepisode == 3)
- {
- F_BunnyScroll();
- }
- else
- {
- switch (gameepisode)
- {
- case 1:
- if (gamemode == retail)
- {
- lumpname = "CREDIT";
- }
- else
- {
- lumpname = "HELP2";
- }
- break;
- case 2:
- lumpname = "VICTORY2";
- break;
- case 4:
- lumpname = "ENDPIC";
- break;
- default:
- return;
- }
-
- lumpname = DEH_String(lumpname);
-
- V_DrawPatch (0, 0, 0, W_CacheLumpName(lumpname, PU_CACHE));
- }
-}
-
-//
-// F_Drawer
-//
-void F_Drawer (void)
-{
- switch (finalestage)
- {
- case F_STAGE_CAST:
- F_CastDrawer();
- break;
- case F_STAGE_TEXT:
- F_TextWrite();
- break;
- case F_STAGE_ARTSCREEN:
- F_ArtScreenDrawer();
- break;
- }
-}
-
-
--- a/src/f_finale.h
+++ /dev/null
@@ -1,53 +1,0 @@
-// Emacs style mode select -*- C++ -*-
-//-----------------------------------------------------------------------------
-//
-// Copyright(C) 1993-1996 Id Software, Inc.
-// Copyright(C) 2005 Simon Howard
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-// 02111-1307, USA.
-//
-// DESCRIPTION:
-//
-//
-//-----------------------------------------------------------------------------
-
-
-#ifndef __F_FINALE__
-#define __F_FINALE__
-
-
-#include "doomtype.h"
-#include "d_event.h"
-//
-// FINALE
-//
-
-// Called by main loop.
-boolean F_Responder (event_t* ev);
-
-// Called by main loop.
-void F_Ticker (void);
-
-// Called by main loop.
-void F_Drawer (void);
-
-
-void F_StartFinale (void);
-
-
-
-
-#endif
--- a/src/g_game.c
+++ /dev/null
@@ -1,2138 +1,0 @@
-// Emacs style mode select -*- C++ -*-
-//-----------------------------------------------------------------------------
-//
-// Copyright(C) 1993-1996 Id Software, Inc.
-// Copyright(C) 2005 Simon Howard
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-// 02111-1307, USA.
-//
-// DESCRIPTION: none
-//
-//-----------------------------------------------------------------------------
-
-
-
-#include <string.h>
-#include <stdlib.h>
-#include <math.h>
-
-#include "doomdef.h"
-#include "doomstat.h"
-
-#include "deh_main.h"
-#include "deh_misc.h"
-
-#include "z_zone.h"
-#include "f_finale.h"
-#include "m_argv.h"
-#include "m_misc.h"
-#include "m_menu.h"
-#include "m_random.h"
-#include "i_system.h"
-#include "i_timer.h"
-#include "i_video.h"
-
-#include "p_setup.h"
-#include "p_saveg.h"
-#include "p_tick.h"
-
-#include "d_main.h"
-
-#include "wi_stuff.h"
-#include "hu_stuff.h"
-#include "st_stuff.h"
-#include "am_map.h"
-
-// Needs access to LFB.
-#include "v_video.h"
-
-#include "w_wad.h"
-
-#include "p_local.h"
-
-#include "s_sound.h"
-
-// Data.
-#include "dstrings.h"
-#include "sounds.h"
-
-// SKY handling - still the wrong place.
-#include "r_data.h"
-#include "r_sky.h"
-
-
-
-#include "g_game.h"
-
-
-#define SAVEGAMESIZE 0x2c000
-
-
-
-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);
-
-// Gamestate the last time G_Ticker was called.
-
-gamestate_t oldgamestate;
-
-gameaction_t gameaction;
-gamestate_t gamestate;
-skill_t gameskill;
-boolean respawnmonsters;
-int gameepisode;
-int gamemap;
-
-// If non-zero, exit the level after this number of minutes.
-
-int timelimit;
-
-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];
-
-boolean turbodetected[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 longtics; // cph's doom 1.91 longtics hack
-boolean lowres_turn; // low resolution turning for longtics
-boolean demoplayback;
-boolean netdemo;
-byte* demobuffer;
-byte* demo_p;
-byte* demoend;
-boolean singledemo; // quit after playing a demo from cmdline
-
-boolean precache = true; // if true, load all graphics at start
-
-boolean testcontrols = false; // Invoked by setup to test controls
-
-wbstartstruct_t wminfo; // parms for world map / intermission
-
-byte consistancy[MAXPLAYERS][BACKUPTICS];
-
-
-//
-// Controls
-//
-int key_right = KEY_RIGHTARROW;
-int key_left = KEY_LEFTARROW;
-
-int key_up = KEY_UPARROW;
-int key_down = KEY_DOWNARROW;
-int key_strafeleft = ',';
-int key_straferight = '.';
-int key_fire = KEY_RCTRL;
-int key_use = ' ';
-int key_strafe = KEY_RALT;
-int key_speed = KEY_RSHIFT;
-
-int mousebfire = 0;
-int mousebstrafe = 1;
-int mousebforward = 2;
-
-int mousebstrafeleft = -1;
-int mousebstraferight = -1;
-int mousebbackward = -1;
-int mousebuse = -1;
-
-// Control whether if a mouse button is double clicked, it acts like
-// "use" has been pressed
-
-int dclick_use = 1;
-
-int joybfire = 0;
-int joybstrafe = 1;
-int joybuse = 3;
-int joybspeed = 2;
-int joybstrafeleft = -1;
-int joybstraferight = -1;
-
-// fraggle: Disallow mouse and joystick movement to cause forward/backward
-// motion. Specified with the '-novert' command line parameter.
-// This is an int to allow saving to config file
-
-int novert = 0;
-
-
-
-#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
-
-static boolean gamekeydown[NUMKEYS];
-static int turnheld; // for accelerative turning
-
-static boolean mousearray[4];
-static boolean *mousebuttons = &mousearray[1]; // allow [-1]
-
-// mouse values are used once
-int mousex;
-int mousey;
-
-static int dclicktime;
-static boolean dclickstate;
-static int dclicks;
-static int dclicktime2;
-static boolean dclickstate2;
-static int dclicks2;
-
-#define MAX_JOY_BUTTONS 20
-
-// joystick values are repeated
-static int joyxmove;
-static int joyymove;
-static boolean joyarray[MAX_JOY_BUTTONS + 1];
-static boolean *joybuttons = &joyarray[1]; // allow [-1]
-
-static int savegameslot;
-static char savedescription[32];
-
-static int testcontrols_mousespeed;
-
-#define BODYQUESIZE 32
-
-mobj_t* bodyque[BODYQUESIZE];
-int bodyqueslot;
-
-int vanilla_savegame_limit = 1;
-int vanilla_demo_limit = 1;
-
-
-#define MOUSE_SPEED_BOX_WIDTH 16
-#define COLOR_RED 0xb0
-#define COLOR_BLACK 0x00
-#define COLOR_WHITE 0x04
-#define COLOR_YELLOW 0xe7
-
-void G_DrawMouseSpeedBox(void)
-{
- extern int usemouse;
- int i;
- int box_x, box_y;
- int original_speed;
- int x, y;
- int redline_x;
- int linelen;
- char *lumpname;
- int color;
-
- // If the mouse is turned off or acceleration is turned off, don't
- // draw the box at all.
-
- if (!usemouse || fabs(mouse_acceleration - 1) < 0.01)
- {
- return;
- }
-
- // Calculate box position
-
- box_x = SCREENWIDTH - MOUSE_SPEED_BOX_WIDTH * 8;
- box_y = SCREENHEIGHT - 9;
-
- // Draw the box.
-
- x = box_x;
-
- for (i=0; i<MOUSE_SPEED_BOX_WIDTH; ++i)
- {
- if (i == 0)
- {
- lumpname = "M_LSLEFT";
- }
- else if (i == MOUSE_SPEED_BOX_WIDTH - 1)
- {
- lumpname = "M_LSRGHT";
- }
- else
- {
- lumpname = "M_LSCNTR";
- }
-
- V_DrawPatchDirect(x, box_y, 0, W_CacheLumpName(DEH_String(lumpname),
- PU_CACHE));
- x += 8;
- }
-
- // Calculate the position of the red line. This is 1/3 of the way
- // along the box.
-
- redline_x = (MOUSE_SPEED_BOX_WIDTH / 3) * 8;
-
- // Undo acceleration and get back the original mouse speed
-
- if (testcontrols_mousespeed < mouse_threshold)
- {
- original_speed = testcontrols_mousespeed;
- }
- else
- {
- original_speed = testcontrols_mousespeed - mouse_threshold;
- original_speed = (int) (original_speed / mouse_acceleration);
- original_speed += mouse_threshold;
- }
-
- // Calculate line length
-
- linelen = (original_speed * redline_x) / mouse_threshold;
-
- // Draw horizontal "thermometer"
-
- for (x=0; x<(MOUSE_SPEED_BOX_WIDTH - 1) * 8; ++x)
- {
- if (x < linelen)
- {
- if (x < redline_x)
- {
- color = COLOR_WHITE;
- }
- else
- {
- color = COLOR_YELLOW;
- }
- }
- else
- {
- color = COLOR_BLACK;
- }
-
- screens[0][(box_y - 4) * SCREENWIDTH + box_x + x + 1] = color;
- }
-
- // Draw red line
-
- for (y=box_y - 8; y<box_y; ++y)
- {
- screens[0][y * SCREENWIDTH + box_x + redline_x] = COLOR_RED;
- }
-}
-
-int G_CmdChecksum (ticcmd_t* cmd)
-{
- size_t i;
- int 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
-//
-void G_BuildTiccmd (ticcmd_t* cmd)
-{
- int i;
- boolean strafe;
- boolean bstrafe;
- int speed;
- int tspeed;
- int forward;
- int side;
-
- memset(cmd, 0, sizeof(ticcmd_t));
-
- cmd->consistancy =
- consistancy[consoleplayer][maketic%BACKUPTICS];
-
- strafe = gamekeydown[key_strafe] || mousebuttons[mousebstrafe]
- || joybuttons[joybstrafe];
-
- // fraggle: support the old "joyb_speed = 31" hack which
- // allowed an autorun effect
-
- speed = key_speed >= NUMKEYS
- || joybspeed >= MAX_JOY_BUTTONS
- || 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_strafeleft]
- || joybuttons[joybstrafeleft]
- || mousebuttons[mousebstrafeleft])
- {
- side -= sidemove[speed];
- }
-
- if (gamekeydown[key_straferight]
- || joybuttons[joybstraferight]
- || mousebuttons[mousebstraferight])
- {
- 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]
- || mousebuttons[mousebuse])
- {
- cmd->buttons |= BT_USE;
- // clear double clicks if hit use button
- dclicks = 0;
- }
-
- // chainsaw overrides
- for (i=0 ; i<NUMWEAPONS-1 ; i++)
- if (gamekeydown['1'+i])
- {
- cmd->buttons |= BT_CHANGE;
- cmd->buttons |= i<<BT_WEAPONSHIFT;
- break;
- }
-
- // mouse
- if (mousebuttons[mousebforward])
- {
- forward += forwardmove[speed];
- }
- if (mousebuttons[mousebbackward])
- {
- forward -= forwardmove[speed];
- }
-
- if (dclick_use)
- {
- // forward double click
- if (mousebuttons[mousebforward] != dclickstate && dclicktime > 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;
- }
- }
- }
-
- // fraggle: allow disabling mouse y movement
-
- if (!novert)
- {
- forward += mousey;
- }
-
- if (strafe)
- side += mousex*2;
- else
- cmd->angleturn -= mousex*0x8;
-
- if (mousex == 0)
- {
- // No movement in the previous frame
-
- testcontrols_mousespeed = 0;
- }
-
- 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<<BTS_SAVESHIFT);
- }
-
- // low-res turning
-
- if (lowres_turn)
- {
- // round angleturn to the nearest 256 boundary
- // for recording demos with single byte values for turn
-
- cmd->angleturn = (cmd->angleturn + 128) & 0xff00;
- }
-}
-
-
-//
-// G_DoLoadLevel
-//
-extern gamestate_t wipegamestate;
-
-void G_DoLoadLevel (void)
-{
- int i;
-
- // Set the sky map.
- // First thing, we have a dummy sky texture name,
- // a flat. The data is in the WAD only because
- // we look for an actual index, instead of simply
- // setting one.
-
- skyflatnum = R_FlatNumForName(DEH_String(SKYFLATNAME));
-
- levelstarttic = gametic; // for time calculation
-
- if (wipegamestate == GS_LEVEL)
- wipegamestate = -1; // force a wipe
-
- gamestate = GS_LEVEL;
-
- for (i=0 ; i<MAXPLAYERS ; i++)
- {
- turbodetected[i] = false;
- if (playeringame[i] && players[i].playerstate == PST_DEAD)
- players[i].playerstate = PST_REBORN;
- memset (players[i].frags,0,sizeof(players[i].frags));
- }
-
- P_SetupLevel (gameepisode, gamemap, 0, gameskill);
- displayplayer = consoleplayer; // view the guy you are playing
- gameaction = ga_nothing;
- Z_CheckHeap ();
-
- // clear cmd building stuff
-
- memset (gamekeydown, 0, sizeof(gamekeydown));
- joyxmove = joyymove = 0;
- mousex = mousey = 0;
- sendpause = sendsave = paused = false;
- memset (mousebuttons, 0, sizeof(mousebuttons));
- memset (joybuttons, 0, sizeof(joybuttons));
-
- if (testcontrols)
- {
- players[consoleplayer].message = "Press escape to quit.";
- }
-}
-
-
-static void SetJoyButtons(unsigned int buttons_mask)
-{
- int i;
-
- for (i=0; i<MAX_JOY_BUTTONS; ++i)
- {
- joybuttons[i] = (buttons_mask & (1 << i)) != 0;
- }
-}
-
-//
-// G_Responder
-// Get info needed to make ticcmd_ts for the players.
-//
-boolean G_Responder (event_t* ev)
-{
- // allow spy mode changes even during the demo
- if (gamestate == GS_LEVEL && ev->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
- }
-
- if (testcontrols && ev->type == ev_mouse)
- {
- // If we are invoked by setup to test the controls, save the
- // mouse speed so that we can display it on-screen.
- // Perform a low pass filter on this so that the thermometer
- // appears to move smoothly.
-
- testcontrols_mousespeed = abs(ev->data2);
- }
-
- switch (ev->type)
- {
- case ev_keydown:
- if (ev->data1 == KEY_PAUSE)
- {
- sendpause = true;
- return true;
- }
- if (ev->data1 <NUMKEYS)
- gamekeydown[ev->data1] = true;
- return true; // eat key down events
-
- case ev_keyup:
- if (ev->data1 <NUMKEYS)
- gamekeydown[ev->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:
- SetJoyButtons(ev->data1);
- 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;
- int buf;
- ticcmd_t* cmd;
-
- // do player reborns if needed
- for (i=0 ; i<MAXPLAYERS ; i++)
- if (playeringame[i] && players[i].playerstate == PST_REBORN)
- G_DoReborn (i);
-
- // do things to change the game state
- while (gameaction != ga_nothing)
- {
- switch (gameaction)
- {
- case ga_loadlevel:
- G_DoLoadLevel ();
- break;
- case ga_newgame:
- G_DoNewGame ();
- break;
- case ga_loadgame:
- G_DoLoadGame ();
- break;
- case ga_savegame:
- G_DoSaveGame ();
- break;
- case ga_playdemo:
- G_DoPlayDemo ();
- break;
- case ga_completed:
- G_DoCompleted ();
- break;
- case ga_victory:
- F_StartFinale ();
- break;
- case ga_worlddone:
- G_DoWorldDone ();
- break;
- case ga_screenshot:
- V_ScreenShot ();
- players[consoleplayer].message = DEH_String("screen shot");
- gameaction = ga_nothing;
- break;
- case ga_nothing:
- break;
- }
- }
-
- // get commands, check consistancy,
- // and build new consistancy check
- buf = (gametic/ticdup)%BACKUPTICS;
-
- for (i=0 ; i<MAXPLAYERS ; i++)
- {
- if (playeringame[i])
- {
- cmd = &players[i].cmd;
-
- memcpy (cmd, &netcmds[i][buf], sizeof(ticcmd_t));
-
- if (demoplayback)
- G_ReadDemoTiccmd (cmd);
- if (demorecording)
- G_WriteDemoTiccmd (cmd);
-
- // check for turbo cheats
-
- // check ~ 4 seconds whether to display the turbo message.
- // store if the turbo threshold was exceeded in any tics
- // over the past 4 seconds. offset the checking period
- // for each player so messages are not displayed at the
- // same time.
-
- if (cmd->forwardmove > TURBOTHRESHOLD)
- {
- turbodetected[i] = true;
- }
-
- if ((gametic & 31) == 0
- && ((gametic >> 5) % MAXPLAYERS) == i
- && turbodetected[i])
- {
- static char turbomessage[80];
- extern char *player_names[4];
- sprintf (turbomessage, "%s is turbo!",player_names[i]);
- players[consoleplayer].message = turbomessage;
- turbodetected[i] = false;
- }
-
- 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<MAXPLAYERS ; i++)
- {
- if (playeringame[i])
- {
- if (players[i].cmd.buttons & BT_SPECIAL)
- {
- switch (players[i].cmd.buttons & BT_SPECIALMASK)
- {
- case BTS_PAUSE:
- paused ^= 1;
- if (paused)
- S_PauseSound ();
- else
- S_ResumeSound ();
- break;
-
- case BTS_SAVEGAME:
- if (!savedescription[0])
- strcpy (savedescription, "NET GAME");
- savegameslot =
- (players[i].cmd.buttons & BTS_SAVEMASK)>>BTS_SAVESHIFT;
- gameaction = ga_savegame;
- break;
- }
- }
- }
- }
-
- // Have we just finished displaying an intermission screen?
-
- if (oldgamestate == GS_INTERMISSION && gamestate != GS_INTERMISSION)
- {
- WI_End();
- }
-
- oldgamestate = gamestate;
-
- // 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;
- int itemcount;
- int 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 = deh_initial_health; // Use dehacked value
- p->readyweapon = p->pendingweapon = wp_pistol;
- p->weaponowned[wp_fist] = true;
- p->weaponowned[wp_pistol] = true;
- p->ammo[am_clip] = deh_initial_bullets;
-
- for (i=0 ; i<NUMAMMO ; i++)
- p->maxammo[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;
- fixed_t y;
- subsector_t* ss;
- unsigned an;
- mobj_t* mo;
- int i;
-
- if (!players[playernum].mo)
- {
- // first spawn of level, before corpses
- for (i=0 ; i<playernum ; i++)
- if (players[i].mo->x == 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 * (((unsigned int) 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)
- {
- // reload the level from scratch
- gameaction = ga_loadlevel;
- }
- else
- {
- // respawn at the start
-
- // first dissasociate the corpse
- players[playernum].mo->player = NULL;
-
- // 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<MAXPLAYERS ; i++)
- {
- if (G_CheckSpot (playernum, &playerstarts[i]) )
- {
- playerstarts[i].type = playernum+1; // fake as other player
- P_SpawnPlayer (&playerstarts[i]);
- playerstarts[i].type = i+1; // restore
- return;
- }
- // he's going to be inside something. Too bad.
- }
- P_SpawnPlayer (&playerstarts[playernum]);
- }
-}
-
-
-void G_ScreenShot (void)
-{
- gameaction = ga_screenshot;
-}
-
-
-
-// DOOM Par Times
-int pars[4][10] =
-{
- {0},
- {0,30,75,120,90,165,180,180,30,165},
- {0,90,90,90,120,90,360,240,30,170},
- {0,90,45,90,150,90,90,165,30,135}
-};
-
-// DOOM II Par Times
-int cpars[32] =
-{
- 30,90,120,120,90,150,120,120,270,90, // 1-10
- 210,150,150,150,210,150,420,150,210,150, // 11-20
- 240,150,180,150,150,300,330,420,300,180, // 21-30
- 120,30 // 31-32
-};
-
-
-//
-// G_DoCompleted
-//
-boolean secretexit;
-extern char* pagename;
-
-void G_ExitLevel (void)
-{
- secretexit = false;
- gameaction = ga_completed;
-}
-
-// Here's for the german edition.
-void G_SecretExitLevel (void)
-{
- // IF NO WOLF3D LEVELS, NO SECRET EXIT!
- if ( (gamemode == commercial)
- && (W_CheckNumForName("map31")<0))
- secretexit = false;
- else
- secretexit = true;
- gameaction = ga_completed;
-}
-
-void G_DoCompleted (void)
-{
- int i;
-
- gameaction = ga_nothing;
-
- for (i=0 ; i<MAXPLAYERS ; i++)
- if (playeringame[i])
- G_PlayerFinishLevel (i); // take away cards and stuff
-
- if (automapactive)
- AM_Stop ();
-
- if (gamemode != commercial)
- {
- // Chex Quest ends after 5 levels, rather than 8.
-
- if (gameversion == exe_chex)
- {
- if (gamemap == 5)
- {
- gameaction = ga_victory;
- return;
- }
- }
- else
- {
- switch(gamemap)
- {
- case 8:
- gameaction = ga_victory;
- return;
- case 9:
- for (i=0 ; i<MAXPLAYERS ; i++)
- players[i].didsecret = true;
- break;
- }
- }
- }
-
-//#if 0 Hmmm - why?
- if ( (gamemap == 8)
- && (gamemode != commercial) )
- {
- // victory
- gameaction = ga_victory;
- return;
- }
-
- if ( (gamemap == 9)
- && (gamemode != commercial) )
- {
- // exit secret level
- for (i=0 ; i<MAXPLAYERS ; i++)
- players[i].didsecret = true;
- }
-//#endif
-
-
- wminfo.didsecret = players[consoleplayer].didsecret;
- wminfo.epsd = gameepisode -1;
- wminfo.last = gamemap -1;
-
- // wminfo.next is 0 biased, unlike gamemap
- if ( gamemode == commercial)
- {
- if (secretexit)
- switch(gamemap)
- {
- case 15: wminfo.next = 30; break;
- case 31: wminfo.next = 31; break;
- }
- else
- switch(gamemap)
- {
- case 31:
- case 32: wminfo.next = 15; break;
- default: wminfo.next = gamemap;
- }
- }
- else
- {
- if (secretexit)
- wminfo.next = 8; // go to secret level
- else if (gamemap == 9)
- {
- // returning from secret level
- switch (gameepisode)
- {
- case 1:
- wminfo.next = 3;
- break;
- case 2:
- wminfo.next = 5;
- break;
- case 3:
- wminfo.next = 6;
- break;
- case 4:
- wminfo.next = 2;
- break;
- }
- }
- else
- wminfo.next = gamemap; // go to next level
- }
-
- wminfo.maxkills = totalkills;
- wminfo.maxitems = totalitems;
- wminfo.maxsecret = totalsecret;
- wminfo.maxfrags = 0;
- if ( gamemode == commercial )
- wminfo.partime = TICRATE*cpars[gamemap-1];
- else
- wminfo.partime = TICRATE*pars[gameepisode][gamemap];
- wminfo.pnum = consoleplayer;
-
- for (i=0 ; i<MAXPLAYERS ; i++)
- {
- wminfo.plyr[i].in = playeringame[i];
- wminfo.plyr[i].skills = players[i].killcount;
- wminfo.plyr[i].sitems = players[i].itemcount;
- wminfo.plyr[i].ssecret = players[i].secretcount;
- wminfo.plyr[i].stime = leveltime;
- memcpy (wminfo.plyr[i].frags, players[i].frags
- , sizeof(wminfo.plyr[i].frags));
- }
-
- gamestate = GS_INTERMISSION;
- viewactive = false;
- automapactive = false;
-
- WI_Start (&wminfo);
-}
-
-
-//
-// G_WorldDone
-//
-void G_WorldDone (void)
-{
- gameaction = ga_worlddone;
-
- if (secretexit)
- players[consoleplayer].didsecret = true;
-
- if ( gamemode == commercial )
- {
- switch (gamemap)
- {
- case 15:
- case 31:
- if (!secretexit)
- break;
- case 6:
- case 11:
- case 20:
- case 30:
- F_StartFinale ();
- break;
- }
- }
-}
-
-void G_DoWorldDone (void)
-{
- gamestate = GS_LEVEL;
- gamemap = wminfo.next+1;
- G_DoLoadLevel ();
- gameaction = ga_nothing;
- viewactive = true;
-}
-
-
-
-//
-// G_InitFromSavegame
-// Can be called by the startup code or the menu task.
-//
-extern boolean setsizeneeded;
-void R_ExecuteSetViewSize (void);
-
-char savename[256];
-
-void G_LoadGame (char* name)
-{
- strcpy (savename, name);
- gameaction = ga_loadgame;
-}
-
-#define VERSIONSIZE 16
-
-
-void G_DoLoadGame (void)
-{
- int savedleveltime;
-
- gameaction = ga_nothing;
-
- save_stream = fopen(savename, "rb");
-
- if (save_stream == NULL)
- {
- return;
- }
-
- if (!P_ReadSaveGameHeader())
- {
- fclose(save_stream);
- return;
- }
-
- savedleveltime = leveltime;
-
- // load a base level
- G_InitNew (gameskill, gameepisode, gamemap);
-
- leveltime = savedleveltime;
-
- // dearchive all the modifications
- P_UnArchivePlayers ();
- P_UnArchiveWorld ();
- P_UnArchiveThinkers ();
- P_UnArchiveSpecials ();
-
- if (!P_ReadSaveGameEOF())
- I_Error ("Bad savegame");
-
- fclose(save_stream);
-
- if (setsizeneeded)
- R_ExecuteSetViewSize ();
-
- // draw the pattern into the back screen
- R_FillBackScreen ();
-}
-
-
-//
-// G_SaveGame
-// Called by the menu task.
-// Description is a 24 byte text string
-//
-void
-G_SaveGame
-( int slot,
- char* description )
-{
- savegameslot = slot;
- strcpy (savedescription, description);
- sendsave = true;
-}
-
-void G_DoSaveGame (void)
-{
- char *savegame_file;
- char *temp_savegame_file;
-
- temp_savegame_file = P_TempSaveGameFile();
- savegame_file = P_SaveGameFile(savegameslot);
-
- // Open the savegame file for writing. We write to a temporary file
- // and then rename it at the end if it was successfully written.
- // This prevents an existing savegame from being overwritten by
- // a corrupted one, or if a savegame buffer overrun occurs.
-
- save_stream = fopen(temp_savegame_file, "wb");
-
- if (save_stream == NULL)
- {
- return;
- }
-
- P_WriteSaveGameHeader(savedescription);
-
- P_ArchivePlayers ();
- P_ArchiveWorld ();
- P_ArchiveThinkers ();
- P_ArchiveSpecials ();
-
- P_WriteSaveGameEOF();
-
- // Enforce the same savegame size limit as in Vanilla Doom,
- // except if the vanilla_savegame_limit setting is turned off.
-
- if (vanilla_savegame_limit && ftell(save_stream) > SAVEGAMESIZE)
- {
- I_Error ("Savegame buffer overrun");
- }
-
- // Finish up, close the savegame file.
-
- fclose(save_stream);
-
- // Now rename the temporary savegame file to the actual savegame
- // file, overwriting the old savegame if there was one there.
-
- remove(savegame_file);
- rename(temp_savegame_file, savegame_file);
-
- gameaction = ga_nothing;
- strcpy(savedescription, "");
-
- players[consoleplayer].message = DEH_String(GGSAVED);
-
- // draw the pattern into the back screen
- R_FillBackScreen ();
-}
-
-
-//
-// 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;
-}
-
-// The sky texture to be used instead of the F_SKY1 dummy.
-extern int skytexture;
-
-
-void
-G_InitNew
-( skill_t skill,
- int episode,
- int map )
-{
- char *skytexturename;
- int i;
-
- if (paused)
- {
- paused = false;
- S_ResumeSound ();
- }
-
-
- if (skill > sk_nightmare)
- skill = sk_nightmare;
-
-
- // This was quite messy with SPECIAL and commented parts.
- // Supposedly hacks to make the latest edition work.
- // It might not work properly.
- if (episode < 1)
- episode = 1;
-
- if ( gamemode == retail )
- {
- if (episode > 4)
- episode = 4;
- }
- else if ( gamemode == shareware )
- {
- if (episode > 1)
- episode = 1; // only start episode 1 on shareware
- }
- else
- {
- if (episode > 3)
- episode = 3;
- }
-
-
-
- if (map < 1)
- map = 1;
-
- if ( (map > 9)
- && ( gamemode != 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 ; i<MAXPLAYERS ; i++)
- players[i].playerstate = PST_REBORN;
-
- usergame = true; // will be set false if a demo
- paused = false;
- demoplayback = false;
- automapactive = false;
- viewactive = true;
- gameepisode = episode;
- gamemap = map;
- gameskill = skill;
-
- viewactive = true;
-
- // Set the sky to use.
- //
- // Note: This IS broken, but it is how Vanilla Doom behaves.
- // See http://doom.wikia.com/wiki/Sky_never_changes_in_Doom_II.
- //
- // Because we set the sky here at the start of a game, not at the
- // start of a level, the sky texture never changes unless we
- // restore from a saved game. This was fixed before the Doom
- // source release, but this IS the way Vanilla DOS Doom behaves.
-
- if (gamemode == commercial)
- {
- if (gamemap < 12)
- skytexturename = "SKY1";
- else if (gamemap < 21)
- skytexturename = "SKY2";
- else
- skytexturename = "SKY3";
- }
- else
- {
- switch (gameepisode)
- {
- default:
- case 1:
- skytexturename = "SKY1";
- break;
- case 2:
- skytexturename = "SKY2";
- break;
- case 3:
- skytexturename = "SKY3";
- break;
- case 4: // Special Edition sky
- skytexturename = "SKY4";
- break;
- }
- }
-
- skytexturename = DEH_String(skytexturename);
-
- skytexture = R_TextureNumForName(skytexturename);
-
-
- G_DoLoadLevel ();
-}
-
-
-//
-// DEMO RECORDING
-//
-#define DEMOMARKER 0x80
-
-
-void G_ReadDemoTiccmd (ticcmd_t* cmd)
-{
- if (*demo_p == DEMOMARKER)
- {
- // end of demo data stream
- G_CheckDemoStatus ();
- return;
- }
- cmd->forwardmove = ((signed char)*demo_p++);
- cmd->sidemove = ((signed char)*demo_p++);
-
- // If this is a longtics demo, read back in higher resolution
-
- if (longtics)
- {
- cmd->angleturn = *demo_p++;
- cmd->angleturn |= (*demo_p++) << 8;
- }
- else
- {
- cmd->angleturn = ((unsigned char) *demo_p++)<<8;
- }
-
- cmd->buttons = (unsigned char)*demo_p++;
-}
-
-// Increase the size of the demo buffer to allow unlimited demos
-
-static void IncreaseDemoBuffer(void)
-{
- int current_length;
- byte *new_demobuffer;
- byte *new_demop;
- int new_length;
-
- // Find the current size
-
- current_length = demoend - demobuffer;
-
- // Generate a new buffer twice the size
- new_length = current_length * 2;
-
- new_demobuffer = Z_Malloc(new_length, PU_STATIC, 0);
- new_demop = new_demobuffer + (demo_p - demobuffer);
-
- // Copy over the old data
-
- memcpy(new_demobuffer, demobuffer, current_length);
-
- // Free the old buffer and point the demo pointers at the new buffer.
-
- Z_Free(demobuffer);
-
- demobuffer = new_demobuffer;
- demo_p = new_demop;
- demoend = demobuffer + new_length;
-}
-
-void G_WriteDemoTiccmd (ticcmd_t* cmd)
-{
- byte *demo_start;
-
- if (gamekeydown['q']) // press q to end demo recording
- G_CheckDemoStatus ();
-
- demo_start = demo_p;
-
- *demo_p++ = cmd->forwardmove;
- *demo_p++ = cmd->sidemove;
-
- // If this is a longtics demo, record in higher resolution
-
- if (longtics)
- {
- *demo_p++ = (cmd->angleturn & 0xff);
- *demo_p++ = (cmd->angleturn >> 8) & 0xff;
- }
- else
- {
- *demo_p++ = cmd->angleturn >> 8;
- }
-
- *demo_p++ = cmd->buttons;
-
- // reset demo pointer back
- demo_p = demo_start;
-
- if (demo_p > demoend - 16)
- {
- if (vanilla_demo_limit)
- {
- // no more space
- G_CheckDemoStatus ();
- return;
- }
- else
- {
- // Vanilla demo limit disabled: unlimited
- // demo lengths!
-
- IncreaseDemoBuffer();
- }
- }
-
- 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;
-
- //!
- // @arg <size>
- // @category demo
- // @vanilla
- //
- // Specify the demo buffer size (KiB)
- //
-
- i = M_CheckParm ("-maxdemo");
- if (i && i<myargc-1)
- maxsize = atoi(myargv[i+1])*1024;
- demobuffer = Z_Malloc (maxsize,PU_STATIC,NULL);
- demoend = demobuffer + maxsize;
-
- demorecording = true;
-}
-
-
-void G_BeginRecording (void)
-{
- int i;
-
- //!
- // @category demo
- //
- // Record a high resolution "Doom 1.91" demo.
- //
-
- longtics = M_CheckParm("-longtics") != 0;
-
- // If not recording a longtics demo, record in low res
-
- lowres_turn = !longtics;
-
- demo_p = demobuffer;
-
- // Save the right version code for this demo
-
- if (longtics)
- {
- *demo_p++ = DOOM_191_VERSION;
- }
- else
- {
- *demo_p++ = DOOM_VERSION;
- }
-
- *demo_p++ = gameskill;
- *demo_p++ = gameepisode;
- *demo_p++ = gamemap;
- *demo_p++ = deathmatch;
- *demo_p++ = respawnparm;
- *demo_p++ = fastparm;
- *demo_p++ = nomonsters;
- *demo_p++ = consoleplayer;
-
- for (i=0 ; i<MAXPLAYERS ; i++)
- *demo_p++ = playeringame[i];
-}
-
-
-//
-// G_PlayDemo
-//
-
-char* defdemoname;
-
-void G_DeferedPlayDemo (char* name)
-{
- defdemoname = name;
- gameaction = ga_playdemo;
-}
-
-// Generate a string describing a demo version
-
-static char *DemoVersionDescription(int version)
-{
- static char resultbuf[16];
-
- switch (version)
- {
- case 104:
- return "v1.4";
- case 105:
- return "v1.5";
- case 106:
- return "v1.6/v1.666";
- case 107:
- return "v1.7/v1.7a";
- case 108:
- return "v1.8";
- case 109:
- return "v1.9";
- default:
- break;
- }
-
- // Unknown version. Perhaps this is a pre-v1.4 IWAD? If the version
- // byte is in the range 0-4 then it can be a v1.0-v1.2 demo.
-
- if (version >= 0 && version <= 4)
- {
- return "v1.0/v1.1/v1.2";
- }
- else
- {
- sprintf(resultbuf, "%i.%i (unknown)", version / 100, version % 100);
- return resultbuf;
- }
-}
-
-void G_DoPlayDemo (void)
-{
- skill_t skill;
- int i, episode, map;
- int demoversion;
-
- gameaction = ga_nothing;
- demobuffer = demo_p = W_CacheLumpName (defdemoname, PU_STATIC);
-
- demoversion = *demo_p++;
-
- if (demoversion == DOOM_VERSION)
- {
- longtics = false;
- }
- else if (demoversion == DOOM_191_VERSION)
- {
- // demo recorded with cph's modified "v1.91" doom exe
- longtics = true;
- }
- else
- {
- char *message = "Demo is from a different game version!\n"
- "(read %i, should be %i)\n"
- "\n"
- "*** You may need to upgrade your version "
- "of Doom to v1.9. ***\n"
- " See: http://doomworld.com/files/patches.shtml\n"
- " This appears to be %s.";
-
- I_Error(message, demoversion, DOOM_VERSION,
- DemoVersionDescription(demoversion));
- }
-
- skill = *demo_p++;
- episode = *demo_p++;
- map = *demo_p++;
- deathmatch = *demo_p++;
- respawnparm = *demo_p++;
- fastparm = *demo_p++;
- nomonsters = *demo_p++;
- consoleplayer = *demo_p++;
-
- for (i=0 ; i<MAXPLAYERS ; i++)
- playeringame[i] = *demo_p++;
-
- //!
- // @category demo
- //
- // Play back a demo recorded in a netgame with a single player.
- //
-
- if (playeringame[1] || M_CheckParm("-netdemo") > 0)
- {
- netgame = true;
- netdemo = true;
- }
-
- // don't spend a lot of time in loadlevel
- precache = false;
- G_InitNew (skill, episode, map);
- precache = true;
- starttime = I_GetTime ();
-
- usergame = false;
- demoplayback = true;
-}
-
-//
-// G_TimeDemo
-//
-void G_TimeDemo (char* name)
-{
- //!
- // @vanilla
- //
- // Disable rendering the screen entirely.
- //
-
- nodrawers = M_CheckParm ("-nodraw");
-
- //!
- // @vanilla
- //
- // Disable blitting the screen.
- //
-
- noblit = M_CheckParm ("-noblit");
- timingdemo = true;
- singletics = true;
-
- defdemoname = name;
- gameaction = ga_playdemo;
-}
-
-
-/*
-===================
-=
-= G_CheckDemoStatus
-=
-= Called after a death or level completion to allow demos to be cleaned up
-= Returns true if a new demo loop action will take place
-===================
-*/
-
-boolean G_CheckDemoStatus (void)
-{
- int endtime;
-
- if (timingdemo)
- {
- float fps;
- int realtics;
-
- endtime = I_GetTime ();
- realtics = endtime - starttime;
- fps = ((float) gametic * TICRATE) / realtics;
-
- // Prevent recursive calls
- timingdemo = false;
- demoplayback = false;
-
- I_Error ("timed %i gametics in %i realtics (%f fps)",
- gametic, realtics, fps);
- }
-
- if (demoplayback)
- {
- W_ReleaseLumpName(defdemoname);
- demoplayback = false;
- netdemo = false;
- netgame = false;
- deathmatch = false;
- playeringame[1] = playeringame[2] = playeringame[3] = 0;
- respawnparm = false;
- fastparm = false;
- nomonsters = false;
- consoleplayer = 0;
-
- if (singledemo)
- I_Quit ();
- else
- D_AdvanceDemo ();
-
- return true;
- }
-
- if (demorecording)
- {
- *demo_p++ = DEMOMARKER;
- M_WriteFile (demoname, demobuffer, demo_p - demobuffer);
- Z_Free (demobuffer);
- demorecording = false;
- I_Error ("Demo %s recorded",demoname);
- }
-
- return false;
-}
-
-
-
--- a/src/g_game.h
+++ /dev/null
@@ -1,84 +1,0 @@
-// Emacs style mode select -*- C++ -*-
-//-----------------------------------------------------------------------------
-//
-// Copyright(C) 1993-1996 Id Software, Inc.
-// Copyright(C) 2005 Simon Howard
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-// 02111-1307, USA.
-//
-// DESCRIPTION:
-// Duh.
-//
-//-----------------------------------------------------------------------------
-
-
-#ifndef __G_GAME__
-#define __G_GAME__
-
-#include "doomdef.h"
-#include "d_event.h"
-#include "d_ticcmd.h"
-
-
-//
-// GAME
-//
-void G_DeathMatchSpawnPlayer (int playernum);
-
-void G_InitNew (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_DeferedInitNew (skill_t skill, int episode, int map);
-
-void G_DeferedPlayDemo (char* demo);
-
-// Can be called by the startup code or M_Responder,
-// calls P_SetupLevel or W_EnterWorld.
-void G_LoadGame (char* name);
-
-void G_DoLoadGame (void);
-
-// Called by M_Responder.
-void G_SaveGame (int slot, char* description);
-
-// Only called by startup code.
-void G_RecordDemo (char* name);
-
-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);
-
-// Read current data from inputs and build a player movement command.
-
-void G_BuildTiccmd (ticcmd_t *cmd);
-
-void G_Ticker (void);
-boolean G_Responder (event_t* ev);
-
-void G_ScreenShot (void);
-
-void G_DrawMouseSpeedBox(void);
-
-#endif
--- a/src/hu_lib.c
+++ /dev/null
@@ -1,356 +1,0 @@
-// Emacs style mode select -*- C++ -*-
-//-----------------------------------------------------------------------------
-//
-// Copyright(C) 1993-1996 Id Software, Inc.
-// Copyright(C) 2005 Simon Howard
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-// 02111-1307, USA.
-//
-// DESCRIPTION: heads-up text and input code
-//
-//-----------------------------------------------------------------------------
-
-
-#include <ctype.h>
-
-#include "doomdef.h"
-
-#include "v_video.h"
-#include "i_swap.h"
-
-#include "hu_lib.h"
-#include "r_local.h"
-#include "r_draw.h"
-
-// boolean : whether the screen is always erased
-#define noterased viewwindowx
-
-extern boolean automapactive; // in AM_map.c
-
-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;
- int w;
- int x;
- unsigned char c;
-
- // draw the new stuff
- x = l->x;
- for (i=0;i<l->len;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;
- int y;
- int 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 ; y<l->y+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;i<h;i++)
- HUlib_initTextLine(&s->l[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 ; i<s->h ; 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 ; i<s->h ; 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 ; i<s->h ; 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 )
-{
- ch = toupper(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;
-}
-
--- a/src/hu_lib.h
+++ /dev/null
@@ -1,196 +1,0 @@
-// Emacs style mode select -*- C++ -*-
-//-----------------------------------------------------------------------------
-//
-// Copyright(C) 1993-1996 Id Software, Inc.
-// Copyright(C) 2005 Simon Howard
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-// 02111-1307, USA.
-//
-// DESCRIPTION: none
-//
-//-----------------------------------------------------------------------------
-
-#ifndef __HULIB__
-#define __HULIB__
-
-// We are referring to patches.
-#include "r_defs.h"
-
-
-// background and foreground screen numbers
-// different from other modules.
-#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
-{
- // left-justified position of scrolling text window
- int x;
- int y;
-
- patch_t** f; // font
- int sc; // start character
- char l[HU_MAXLINELENGTH+1]; // line of text
- int len; // current line length
-
- // whether this line needs to be udpated
- int needsupdate;
-
-} 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
-
- // pointer to boolean stating whether to update window
- boolean* on;
- 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
-
- // left margin past which I am not to delete characters
- int lm;
-
- // pointer to boolean stating whether to update window
- boolean* on;
- 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
-//
-
-// clear a line of text
-void HUlib_clearTextLine(hu_textline_t *t);
-
-void HUlib_initTextLine(hu_textline_t *t, int x, int y, patch_t **f, int sc);
-
-// returns success
-boolean HUlib_addCharToTextLine(hu_textline_t *t, char ch);
-
-// returns success
-boolean HUlib_delCharFromTextLine(hu_textline_t *t);
-
-// draws tline
-void HUlib_drawTextLine(hu_textline_t *l, boolean drawcursor);
-
-// erases text line
-void HUlib_eraseTextLine(hu_textline_t *l);
-
-
-//
-// 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 );
-
-// add a new line
-void HUlib_addLineToSText(hu_stext_t* s);
-
-// ?
-void
-HUlib_addMessageToSText
-( hu_stext_t* s,
- char* prefix,
- char* msg );
-
-// draws stext
-void HUlib_drawSText(hu_stext_t* s);
-
-// erases all stext lines
-void HUlib_eraseSText(hu_stext_t* s);
-
-// Input Text Line widget routines
-void
-HUlib_initIText
-( hu_itext_t* it,
- int x,
- int y,
- patch_t** font,
- int startchar,
- boolean* on );
-
-// enforces left margin
-void HUlib_delCharFromIText(hu_itext_t* it);
-
-// enforces left margin
-void HUlib_eraseLineFromIText(hu_itext_t* it);
-
-// resets line and left margin
-void HUlib_resetIText(hu_itext_t* it);
-
-// left of left-margin
-void
-HUlib_addPrefixToIText
-( hu_itext_t* it,
- char* str );
-
-// whether eaten
-boolean
-HUlib_keyInIText
-( hu_itext_t* it,
- unsigned char ch );
-
-void HUlib_drawIText(hu_itext_t* it);
-
-// erases all itext lines
-void HUlib_eraseIText(hu_itext_t* it);
-
-#endif
--- a/src/hu_stuff.c
+++ /dev/null
@@ -1,704 +1,0 @@
-// Emacs style mode select -*- C++ -*-
-//-----------------------------------------------------------------------------
-//
-// Copyright(C) 1993-1996 Id Software, Inc.
-// Copyright(C) 2005 Simon Howard
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-// 02111-1307, USA.
-//
-// DESCRIPTION: Heads-up displays
-//
-//-----------------------------------------------------------------------------
-
-
-#include <ctype.h>
-
-#include "doomdef.h"
-
-#include "z_zone.h"
-
-#include "deh_main.h"
-#include "i_swap.h"
-#include "i_video.h"
-
-#include "hu_stuff.h"
-#include "hu_lib.h"
-#include "w_wad.h"
-
-#include "s_sound.h"
-
-#include "doomstat.h"
-
-// Data.
-#include "dstrings.h"
-#include "sounds.h"
-
-//
-// Locally used constants, shortcuts.
-//
-#define HU_TITLE (mapnames[(gameepisode-1)*9+gamemap-1])
-#define HU_TITLE2 (mapnames2[gamemap-1])
-#define HU_TITLEP (mapnamesp[gamemap-1])
-#define HU_TITLET (mapnamest[gamemap-1])
-#define HU_TITLE_CHEX (mapnames[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
-
-
-
-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;
-
-//
-// Builtin map names.
-// The actual names can be found in DStrings.h.
-//
-
-char* mapnames[] = // DOOM shareware/registered/retail (Ultimate) names.
-{
-
- 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,
-
- HUSTR_E4M1,
- HUSTR_E4M2,
- HUSTR_E4M3,
- HUSTR_E4M4,
- HUSTR_E4M5,
- HUSTR_E4M6,
- HUSTR_E4M7,
- HUSTR_E4M8,
- HUSTR_E4M9,
-
- "NEWLEVEL",
- "NEWLEVEL",
- "NEWLEVEL",
- "NEWLEVEL",
- "NEWLEVEL",
- "NEWLEVEL",
- "NEWLEVEL",
- "NEWLEVEL",
- "NEWLEVEL"
-};
-
-char* mapnames2[] = // DOOM 2 map names.
-{
- 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* mapnamesp[] = // Plutonia WAD map names.
-{
- PHUSTR_1,
- PHUSTR_2,
- PHUSTR_3,
- PHUSTR_4,
- PHUSTR_5,
- PHUSTR_6,
- PHUSTR_7,
- PHUSTR_8,
- PHUSTR_9,
- PHUSTR_10,
- PHUSTR_11,
-
- PHUSTR_12,
- PHUSTR_13,
- PHUSTR_14,
- PHUSTR_15,
- PHUSTR_16,
- PHUSTR_17,
- PHUSTR_18,
- PHUSTR_19,
- PHUSTR_20,
-
- PHUSTR_21,
- PHUSTR_22,
- PHUSTR_23,
- PHUSTR_24,
- PHUSTR_25,
- PHUSTR_26,
- PHUSTR_27,
- PHUSTR_28,
- PHUSTR_29,
- PHUSTR_30,
- PHUSTR_31,
- PHUSTR_32
-};
-
-
-char *mapnamest[] = // TNT WAD map names.
-{
- THUSTR_1,
- THUSTR_2,
- THUSTR_3,
- THUSTR_4,
- THUSTR_5,
- THUSTR_6,
- THUSTR_7,
- THUSTR_8,
- THUSTR_9,
- THUSTR_10,
- THUSTR_11,
-
- THUSTR_12,
- THUSTR_13,
- THUSTR_14,
- THUSTR_15,
- THUSTR_16,
- THUSTR_17,
- THUSTR_18,
- THUSTR_19,
- THUSTR_20,
-
- THUSTR_21,
- THUSTR_22,
- THUSTR_23,
- THUSTR_24,
- THUSTR_25,
- THUSTR_26,
- THUSTR_27,
- THUSTR_28,
- THUSTR_29,
- THUSTR_30,
- THUSTR_31,
- THUSTR_32
-};
-
-static const char 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
-};
-
-
-void HU_Init(void)
-{
-
- int i;
- int j;
- char buffer[9];
-
- // load the heads-up font
- j = HU_FONTSTART;
- for (i=0;i<HU_FONTSIZE;i++)
- {
- sprintf(buffer, DEH_String("STCFN%.3d"), j++);
- hu_font[i] = (patch_t *) W_CacheLumpName(buffer, PU_STATIC);
- }
-
-}
-
-void HU_Stop(void)
-{
- headsupactive = false;
-}
-
-void HU_Start(void)
-{
-
- int i;
- char* s;
-
- if (headsupactive)
- HU_Stop();
-
- plr = &players[consoleplayer];
- message_on = false;
- message_dontfuckwithme = false;
- message_nottobefuckedwith = false;
- chat_on = false;
-
- // create the message widget
- HUlib_initSText(&w_message,
- HU_MSGX, HU_MSGY, HU_MSGHEIGHT,
- hu_font,
- HU_FONTSTART, &message_on);
-
- // create the map title widget
- HUlib_initTextLine(&w_title,
- HU_TITLEX, HU_TITLEY,
- hu_font,
- HU_FONTSTART);
-
- switch ( gamemission )
- {
- case doom:
- s = HU_TITLE;
- break;
- case doom2:
- s = HU_TITLE2;
- break;
- case pack_plut:
- s = HU_TITLEP;
- break;
- case pack_tnt:
- s = HU_TITLET;
- break;
- default:
- s = "Unknown level";
- break;
- }
-
- // Chex.exe always uses the episode 1 level title
- // eg. E2M1 gives the title for E1M1
-
- if (gameversion == exe_chex)
- {
- s = HU_TITLE_CHEX;
- }
-
- // dehacked substitution to get modified level name
-
- s = DEH_String(s);
-
- while (*s)
- HUlib_addCharToTextLine(&w_title, *(s++));
-
- // create the chat widget
- HUlib_initIText(&w_chat,
- HU_INPUTX, HU_INPUTY,
- hu_font,
- HU_FONTSTART, &chat_on);
-
- // create the inputbuffer widgets
- for (i=0 ; i<MAXPLAYERS ; i++)
- HUlib_initIText(&w_inputbuffer[i], 0, 0, 0, 0, &always_off);
-
- headsupactive = true;
-
-}
-
-void HU_Drawer(void)
-{
-
- HUlib_drawSText(&w_message);
- HUlib_drawIText(&w_chat);
- if (automapactive)
- HUlib_drawTextLine(&w_title, false);
-
-}
-
-void HU_Erase(void)
-{
-
- HUlib_eraseSText(&w_message);
- HUlib_eraseIText(&w_chat);
- HUlib_eraseTextLine(&w_title);
-
-}
-
-void HU_Ticker(void)
-{
-
- int i, rc;
- char c;
-
- // tick down message counter if message is up
- if (message_counter && !--message_counter)
- {
- message_on = false;
- message_nottobefuckedwith = false;
- }
-
- if (showMessages || message_dontfuckwithme)
- {
-
- // display message if necessary
- if ((plr->message && !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<MAXPLAYERS; i++)
- {
- if (!playeringame[i])
- continue;
- if (i != consoleplayer
- && (c = players[i].cmd.chatchar))
- {
- if (c <= HU_BROADCAST)
- chat_dest[i] = c;
- else
- {
- 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,
- DEH_String(player_names[i]),
- w_inputbuffer[i].l.l);
-
- message_nottobefuckedwith = true;
- message_on = true;
- message_counter = HU_MSGTIMEOUT;
- if ( gamemode == commercial )
- S_StartSound(0, sfx_radio);
- else
- 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;
-static int tail = 0;
-
-
-void HU_queueChatChar(char c)
-{
- if (((head + 1) & (QUEUESIZE-1)) == tail)
- {
- plr->message = DEH_String(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;
- int numplayers;
-
- static char destination_keys[MAXPLAYERS] =
- {
- HUSTR_KEYGREEN,
- HUSTR_KEYINDIGO,
- HUSTR_KEYBROWN,
- HUSTR_KEYRED
- };
-
- static int num_nobrainers = 0;
-
- numplayers = 0;
- for (i=0 ; i<MAXPLAYERS ; i++)
- numplayers += playeringame[i];
-
- if (ev->data1 == 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->data2 == HU_INPUTTOGGLE)
- {
- eatkey = chat_on = true;
- HUlib_resetIText(&w_chat);
- HU_queueChatChar(HU_BROADCAST);
- }
- else if (netgame && numplayers > 2)
- {
- for (i=0; i<MAXPLAYERS ; i++)
- {
- if (ev->data2 == 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 = DEH_String(HUSTR_TALKTOSELF1);
- else if (num_nobrainers < 6)
- plr->message = DEH_String(HUSTR_TALKTOSELF2);
- else if (num_nobrainers < 9)
- plr->message = DEH_String(HUSTR_TALKTOSELF3);
- else if (num_nobrainers < 32)
- plr->message = DEH_String(HUSTR_TALKTOSELF4);
- else
- plr->message = DEH_String(HUSTR_TALKTOSELF5);
- }
- }
- }
- }
- }
- else
- {
- c = ev->data2;
- // 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 (vanilla_keyboard_mapping)
- {
- 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;
-
-}
--- a/src/hu_stuff.h
+++ /dev/null
@@ -1,66 +1,0 @@
-// Emacs style mode select -*- C++ -*-
-//-----------------------------------------------------------------------------
-//
-// Copyright(C) 1993-1996 Id Software, Inc.
-// Copyright(C) 2005 Simon Howard
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-// 02111-1307, USA.
-//
-// DESCRIPTION: Head up display
-//
-//-----------------------------------------------------------------------------
-
-#ifndef __HU_STUFF_H__
-#define __HU_STUFF_H__
-
-#include "d_event.h"
-
-
-//
-// Globally visible constants.
-//
-#define HU_FONTSTART '!' // the first font characters
-#define HU_FONTEND '_' // the last font characters
-
-// Calculate # of glyphs in font.
-#define HU_FONTSIZE (HU_FONTEND - HU_FONTSTART + 1)
-
-#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)
-
-//
-// 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);
-
-
-#endif
--- a/src/info.c
+++ /dev/null
@@ -1,4670 +1,0 @@
-// Emacs style mode select -*- C++ -*-
-//-----------------------------------------------------------------------------
-//
-// Copyright(C) 1993-1996 Id Software, Inc.
-// Copyright(C) 2005 Simon Howard
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-// 02111-1307, USA.
-//
-// DESCRIPTION:
-// Thing frame/state LUT,
-// generated by multigen utilitiy.
-// This one is the original DOOM version, preserved.
-//
-//-----------------------------------------------------------------------------
-
-
-#include <stdlib.h>
-
-// Data.
-#include "sounds.h"
-#include "m_fixed.h"
-
-#include "info.h"
-
-#include "p_mobj.h"
-
-char *sprnames[] = {
- "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", NULL
-};
-
-
-// Doesn't work with g++, needs actionf_p1
-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
- }
-};
-
--- a/src/info.h
+++ /dev/null
@@ -1,1339 +1,0 @@
-// Emacs style mode select -*- C++ -*-
-//-----------------------------------------------------------------------------
-//
-// Copyright(C) 1993-1996 Id Software, Inc.
-// Copyright(C) 2005 Simon Howard
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-// 02111-1307, USA.
-//
-// DESCRIPTION:
-// Thing frame/state LUT,
-// generated by multigen utilitiy.
-// This one is the original DOOM version, preserved.
-//
-//-----------------------------------------------------------------------------
-
-#ifndef __INFO__
-#define __INFO__
-
-// Needed for action function pointer handling.
-#include "d_think.h"
-
-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;
- int frame;
- int tics;
- // void (*action) ();
- actionf_t action;
- statenum_t nextstate;
- int misc1;
- int misc2;
-} state_t;
-
-extern state_t states[NUMSTATES];
-extern char *sprnames[];
-
-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];
-
-#endif
--- a/src/m_menu.c
+++ /dev/null
@@ -1,1975 +1,0 @@
-// Emacs style mode select -*- C++ -*-
-//-----------------------------------------------------------------------------
-//
-// Copyright(C) 1993-1996 Id Software, Inc.
-// Copyright(C) 2005 Simon Howard
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-// 02111-1307, USA.
-//
-// DESCRIPTION:
-// DOOM selection menu, options, episode etc.
-// Sliders and icons. Kinda widget stuff.
-//
-//-----------------------------------------------------------------------------
-
-
-#include <stdlib.h>
-#include <ctype.h>
-
-
-#include "doomdef.h"
-#include "dstrings.h"
-
-#include "d_main.h"
-#include "deh_main.h"
-
-#include "i_swap.h"
-#include "i_system.h"
-#include "i_timer.h"
-#include "i_video.h"
-#include "z_zone.h"
-#include "v_video.h"
-#include "w_wad.h"
-
-#include "r_local.h"
-
-
-#include "hu_stuff.h"
-
-#include "g_game.h"
-
-#include "m_argv.h"
-#include "p_saveg.h"
-
-#include "s_sound.h"
-
-#include "doomstat.h"
-
-// Data.
-#include "sounds.h"
-
-#include "m_menu.h"
-
-
-extern void M_QuitDOOM(int);
-
-extern patch_t* hu_font[HU_FONTSIZE];
-extern boolean message_dontfuckwithme;
-
-extern boolean chat_on; // in heads-up code
-
-//
-// defaulted values
-//
-int mouseSensitivity = 5;
-
-// Show messages has default, 0 = off, 1 = on
-int showMessages = 1;
-
-
-// Blocky mode, has default, 0 = high, 1 = normal
-int detailLevel = 0;
-int screenblocks = 9;
-
-// temp for screenblocks (0-9)
-int screenSize;
-
-// -1 = no quicksave slot picked!
-int quickSaveSlot;
-
- // 1 = message to be printed
-int messageToPrint;
-// ...and here is the message string!
-char* messageString;
-
-// message x & y
-int messx;
-int messy;
-int messageLastMenuActive;
-
-// timed message = no input from user
-boolean messageNeedsInput;
-
-void (*messageRoutine)(int response);
-
-char gammamsg[5][26] =
-{
- GAMMALVL0,
- GAMMALVL1,
- GAMMALVL2,
- GAMMALVL3,
- GAMMALVL4
-};
-
-// we are going to be entering a savegame string
-int saveStringEnter;
-int saveSlot; // which slot to save in
-int saveCharIndex; // which char we're editing
-// old save description before edit
-char saveOldString[SAVESTRINGSIZE];
-
-boolean inhelpscreens;
-boolean menuactive;
-
-#define SKULLXOFF -32
-#define LINEHEIGHT 16
-
-extern boolean sendpause;
-char savegamestrings[10][SAVESTRINGSIZE];
-
-char endstring[160];
-
-
-//
-// MENU TYPEDEFS
-//
-typedef struct
-{
- // 0 = no cursor here, 1 = ok, 2 = arrows ok
- short status;
-
- char name[10];
-
- // choice = menu item #.
- // if status = 2,
- // choice=0:leftarrow,1:rightarrow
- void (*routine)(int choice);
-
- // hotkey in menu
- char alphaKey;
-} 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;
- short 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
-
-// graphic name of skulls
-// warning: initializer-string for array of chars is too long
-char *skullName[2] = {"M_SKULL1","M_SKULL2"};
-
-// current menudef
-menu_t* currentMenu;
-
-//
-// 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_ReadThis2(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_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'},
- // Another hickup with Special edition.
- {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,
- ep4,
- 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'},
- {1,"M_EPI4", M_Episode,'t'}
-};
-
-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,'\0'},
- {2,"M_MSENS", M_ChangeSensitivity,'m'},
- {-1,"",0,'\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,'\0'},
- {2,"M_MUSVOL",M_MusicVol,'m'},
- {-1,"",0,'\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)
-{
- FILE *handle;
- int count;
- int i;
- char name[256];
-
- for (i = 0;i < load_end;i++)
- {
- strcpy(name, P_SaveGameFile(i));
-
- handle = fopen(name, "rb");
- if (handle == NULL)
- {
- strcpy(&savegamestrings[i][0], EMPTYSTRING);
- LoadMenu[i].status = 0;
- continue;
- }
- count = fread(&savegamestrings[i], 1, SAVESTRINGSIZE, handle);
- fclose(handle);
- LoadMenu[i].status = 1;
- }
-}
-
-
-//
-// M_LoadGame & Cie.
-//
-void M_DrawLoad(void)
-{
- int i;
-
- V_DrawPatchDirect (72,28,0,W_CacheLumpName(DEH_String("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(DEH_String("M_LSLEFT"),PU_CACHE));
-
- for (i = 0;i < 24;i++)
- {
- V_DrawPatchDirect (x,y+7,0,W_CacheLumpName(DEH_String("M_LSCNTR"),PU_CACHE));
- x += 8;
- }
-
- V_DrawPatchDirect (x,y+7,0,W_CacheLumpName(DEH_String("M_LSRGHT"),PU_CACHE));
-}
-
-
-
-//
-// User wants to load this game
-//
-void M_LoadSelect(int choice)
-{
- char name[256];
-
- strcpy(name, P_SaveGameFile(choice));
-
- G_LoadGame (name);
- M_ClearMenus ();
-}
-
-//
-// Selected from DOOM menu
-//
-void M_LoadGame (int choice)
-{
- if (netgame)
- {
- M_StartMessage(DEH_String(LOADNET),NULL,false);
- return;
- }
-
- M_SetupNextMenu(&LoadDef);
- M_ReadSaveStrings();
-}
-
-
-//
-// M_SaveGame & Cie.
-//
-void M_DrawSave(void)
-{
- int i;
-
- V_DrawPatchDirect (72,28,0,W_CacheLumpName(DEH_String("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)
-{
- // we are going to be intercepting all chars
- saveStringEnter = 1;
-
- 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(DEH_String(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,DEH_String(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(DEH_String(QLOADNET),NULL,false);
- return;
- }
-
- if (quickSaveSlot < 0)
- {
- M_StartMessage(DEH_String(QSAVESPOT),NULL,false);
- return;
- }
- sprintf(tempstring,DEH_String(QLPROMPT),savegamestrings[quickSaveSlot]);
- M_StartMessage(tempstring,M_QuickLoadResponse,true);
-}
-
-
-
-
-//
-// Read This Menus
-// Had a "quick hack to fix romero bug"
-//
-void M_DrawReadThis1(void)
-{
- char *lumpname = "CREDIT";
- int skullx = 330, skully = 175;
-
- inhelpscreens = true;
-
- // Different versions of Doom 1.9 work differently
-
- switch (gameversion)
- {
- case exe_doom_1_9:
- if (gamemode == commercial)
- {
- // Doom 2
-
- lumpname = "HELP";
-
- skullx = 330;
- skully = 165;
- }
- else
- {
- // Doom 1
- // HELP2 is the first screen shown in Doom 1
-
- lumpname = "HELP2";
-
- skullx = 280;
- skully = 185;
- }
- break;
-
- case exe_ultimate:
- case exe_chex:
-
- // Ultimate Doom always displays "HELP1".
-
- // Chex Quest version also uses "HELP1", even though it is based
- // on Final Doom.
-
- lumpname = "HELP1";
-
- break;
-
- case exe_final:
-
- // Final Doom always displays "HELP".
-
- lumpname = "HELP";
-
- break;
- }
-
- lumpname = DEH_String(lumpname);
-
- V_DrawPatchDirect (0, 0, 0, W_CacheLumpName(lumpname, PU_CACHE));
-
- ReadDef1.x = skullx;
- ReadDef1.y = skully;
-}
-
-
-
-//
-// Read This Menus - optional second page.
-//
-void M_DrawReadThis2(void)
-{
- inhelpscreens = true;
-
- // We only ever draw the second page if this is
- // gameversion == exe_doom_1_9 and gamemode == registered
-
- V_DrawPatchDirect(0, 0, 0, W_CacheLumpName(DEH_String("HELP1"), PU_CACHE));
-}
-
-
-//
-// Change Sfx & Music volumes
-//
-void M_DrawSound(void)
-{
- V_DrawPatchDirect (60,38,0,W_CacheLumpName(DEH_String("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(DEH_String("M_DOOM"),PU_CACHE));
-}
-
-
-
-
-//
-// M_NewGame
-//
-void M_DrawNewGame(void)
-{
- V_DrawPatchDirect (96,14,0,W_CacheLumpName(DEH_String("M_NEWG"),PU_CACHE));
- V_DrawPatchDirect (54,38,0,W_CacheLumpName(DEH_String("M_SKILL"),PU_CACHE));
-}
-
-void M_NewGame(int choice)
-{
- if (netgame && !demoplayback)
- {
- M_StartMessage(DEH_String(NEWGAME),NULL,false);
- return;
- }
-
- // Chex Quest disabled the episode select screen, as did Doom II.
-
- if (gamemode == commercial || gameversion == exe_chex)
- M_SetupNextMenu(&NewDef);
- else
- M_SetupNextMenu(&EpiDef);
-}
-
-
-//
-// M_Episode
-//
-int epi;
-
-void M_DrawEpisode(void)
-{
- V_DrawPatchDirect (54,38,0,W_CacheLumpName(DEH_String("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(DEH_String(NIGHTMARE),M_VerifyNightmare,true);
- return;
- }
-
- G_DeferedInitNew(choice,epi+1,1);
- M_ClearMenus ();
-}
-
-void M_Episode(int choice)
-{
- if ( (gamemode == shareware)
- && choice)
- {
- M_StartMessage(DEH_String(SWSTRING),NULL,false);
- M_SetupNextMenu(&ReadDef1);
- return;
- }
-
- // Yet another hack...
- if ( (gamemode == registered)
- && (choice > 2))
- {
- fprintf( stderr,
- "M_Episode: 4th episode requires UltimateDOOM\n");
- choice = 0;
- }
-
- 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(DEH_String("M_OPTTTL"),PU_CACHE));
-
- V_DrawPatchDirect (OptionsDef.x + 175,OptionsDef.y+LINEHEIGHT*detail,0,
- W_CacheLumpName(DEH_String(detailNames[detailLevel]),
- PU_CACHE));
-
- V_DrawPatchDirect (OptionsDef.x + 120,OptionsDef.y+LINEHEIGHT*messages,0,
- W_CacheLumpName(DEH_String(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)
-{
- // warning: unused parameter `int choice'
- choice = 0;
- showMessages = 1 - showMessages;
-
- if (!showMessages)
- players[consoleplayer].message = DEH_String(MSGOFF);
- else
- players[consoleplayer].message = DEH_String(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)
-{
- choice = 0;
- if (!usergame)
- {
- S_StartSound(NULL,sfx_oof);
- return;
- }
-
- if (netgame)
- {
- M_StartMessage(DEH_String(NETEND),NULL,false);
- return;
- }
-
- M_StartMessage(DEH_String(ENDGAME),M_EndGameResponse,true);
-}
-
-
-
-
-//
-// M_ReadThis
-//
-void M_ReadThis(int choice)
-{
- choice = 0;
- M_SetupNextMenu(&ReadDef1);
-}
-
-void M_ReadThis2(int choice)
-{
- // Doom 1.9 had two menus when playing Doom 1
- // All others had only one
-
- if (gameversion == exe_doom_1_9 && gamemode != commercial)
- {
- choice = 0;
- M_SetupNextMenu(&ReadDef2);
- }
- else
- {
- // Close the menu
-
- M_FinishReadThis(0);
- }
-}
-
-void M_FinishReadThis(int choice)
-{
- choice = 0;
- 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 (gamemode == commercial)
- S_StartSound(NULL,quitsounds2[(gametic>>2)&7]);
- else
- S_StartSound(NULL,quitsounds[(gametic>>2)&7]);
- I_WaitVBL(105);
- }
- I_Quit ();
-}
-
-
-static char *M_SelectEndMessage(void)
-{
- char **endmsg;
-
- if (gamemission == doom)
- {
- // Doom 1
-
- endmsg = doom1_endmsg;
- }
- else
- {
- // Doom 2
-
- endmsg = doom2_endmsg;
- }
-
- return endmsg[gametic % NUM_QUITMESSAGES];
-}
-
-
-void M_QuitDOOM(int choice)
-{
- sprintf(endstring,
- DEH_String("%s\n\n" DOSY),
- DEH_String(M_SelectEndMessage()));
-
- 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)
-{
- choice = 0;
- detailLevel = 1 - detailLevel;
-
- R_SetViewSize (screenblocks, detailLevel);
-
- if (!detailLevel)
- players[consoleplayer].message = DEH_String(DETAILHI);
- else
- players[consoleplayer].message = DEH_String(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;
- int i;
-
- xx = x;
- V_DrawPatchDirect (xx,y,0,W_CacheLumpName(DEH_String("M_THERML"),PU_CACHE));
- xx += 8;
- for (i=0;i<thermWidth;i++)
- {
- V_DrawPatchDirect (xx,y,0,W_CacheLumpName(DEH_String("M_THERMM"),PU_CACHE));
- xx += 8;
- }
- V_DrawPatchDirect (xx,y,0,W_CacheLumpName(DEH_String("M_THERMR"),PU_CACHE));
-
- V_DrawPatchDirect ((x+8) + thermDot*8,y,
- 0,W_CacheLumpName(DEH_String("M_THERMO"),PU_CACHE));
-}
-
-
-
-void
-M_DrawEmptyCell
-( menu_t* menu,
- int item )
-{
- V_DrawPatchDirect (menu->x - 10, menu->y+item*LINEHEIGHT - 1, 0,
- W_CacheLumpName(DEH_String("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(DEH_String("M_CELL2"),PU_CACHE));
-}
-
-
-void
-M_StartMessage
-( char* string,
- void* routine,
- boolean input )
-{
- messageLastMenuActive = menuactive;
- 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)
-{
- size_t 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)
-{
- size_t 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 key;
- 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;
-
- // key is the key pressed, ch is the actual character typed
-
- ch = 0;
- key = -1;
-
- if (ev->type == ev_joystick && joywait < I_GetTime())
- {
- if (ev->data3 == -1)
- {
- key = KEY_UPARROW;
- joywait = I_GetTime() + 5;
- }
- else if (ev->data3 == 1)
- {
- key = KEY_DOWNARROW;
- joywait = I_GetTime() + 5;
- }
-
- if (ev->data2 == -1)
- {
- key = KEY_LEFTARROW;
- joywait = I_GetTime() + 2;
- }
- else if (ev->data2 == 1)
- {
- key = KEY_RIGHTARROW;
- joywait = I_GetTime() + 2;
- }
-
- if (ev->data1&1)
- {
- key = KEY_ENTER;
- joywait = I_GetTime() + 5;
- }
- if (ev->data1&2)
- {
- key = KEY_BACKSPACE;
- joywait = I_GetTime() + 5;
- }
- }
- else
- {
- if (ev->type == ev_mouse && mousewait < I_GetTime())
- {
- mousey += ev->data3;
- if (mousey < lasty-30)
- {
- key = KEY_DOWNARROW;
- mousewait = I_GetTime() + 5;
- mousey = lasty -= 30;
- }
- else if (mousey > lasty+30)
- {
- key = KEY_UPARROW;
- mousewait = I_GetTime() + 5;
- mousey = lasty += 30;
- }
-
- mousex += ev->data2;
- if (mousex < lastx-30)
- {
- key = KEY_LEFTARROW;
- mousewait = I_GetTime() + 5;
- mousex = lastx -= 30;
- }
- else if (mousex > lastx+30)
- {
- key = KEY_RIGHTARROW;
- mousewait = I_GetTime() + 5;
- mousex = lastx += 30;
- }
-
- if (ev->data1&1)
- {
- key = KEY_ENTER;
- mousewait = I_GetTime() + 15;
- }
-
- if (ev->data1&2)
- {
- key = KEY_BACKSPACE;
- mousewait = I_GetTime() + 15;
- }
- }
- else
- {
- if (ev->type == ev_keydown)
- {
- key = ev->data1;
- ch = ev->data2;
- }
- }
- }
-
- if (key == -1)
- return false;
-
- // In testcontrols mode, none of the function keys should do anything
- // - the only key is escape to quit.
-
- if (testcontrols)
- {
- if (key == KEY_ESCAPE || key == KEY_F10)
- {
- I_Quit();
- return true;
- }
-
- return false;
- }
-
- // Save Game string input
- if (saveStringEnter)
- {
- switch(key)
- {
- 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:
- // Entering a character - use the 'ch' value, not the key
-
- ch = toupper(ch);
-
- if (ch != ' '
- && (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' || key == KEY_ESCAPE))
- return false;
-
- menuactive = messageLastMenuActive;
- messageToPrint = 0;
- if (messageRoutine)
- messageRoutine(ch);
-
- menuactive = false;
- S_StartSound(NULL,sfx_swtchx);
- return true;
- }
-
- if (devparm && key == KEY_F1)
- {
- G_ScreenShot ();
- return true;
- }
-
-
- // F-Keys
- if (!menuactive)
- switch(key)
- {
- 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 ();
-
- if ( gamemode == retail )
- currentMenu = &ReadDef2;
- else
- 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 = DEH_String(gammamsg[usegamma]);
- I_SetPalette (W_CacheLumpName (DEH_String("PLAYPAL"),PU_CACHE));
- return true;
-
- }
-
-
- // Pop-up menu?
- if (!menuactive)
- {
- if (key == KEY_ESCAPE)
- {
- M_StartControlPanel ();
- S_StartSound(NULL,sfx_swtchn);
- return true;
- }
- return false;
- }
-
-
- // Keys usable within menu
- switch (key)
- {
- 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)
-{
- // intro might call this repeatedly
- if (menuactive)
- return;
-
- 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;
- static short y;
- unsigned int i;
- unsigned int max;
- char string[80];
- char *name;
- int start;
-
- inhelpscreens = false;
-
- // Horiz. & Vertically center string and print it.
- if (messageToPrint)
- {
- start = 0;
- y = 100 - M_StringHeight(messageString) / 2;
- while (messageString[start] != '\0')
- {
- int foundnewline = 0;
-
- for (i = 0; i < strlen(messageString + start); i++)
- if (messageString[start + i] == '\n')
- {
- memset(string, 0, sizeof(string));
- strncpy(string, messageString + start, i);
- foundnewline = 1;
- start += i + 1;
- break;
- }
-
- if (!foundnewline)
- {
- strcpy(string, messageString + start);
- start += strlen(string);
- }
-
- 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;i<max;i++)
- {
- name = DEH_String(currentMenu->menuitems[i].name);
-
- if (name[0])
- {
- V_DrawPatchDirect (x,y,0, W_CacheLumpName(name, PU_CACHE));
- }
- y += LINEHEIGHT;
- }
-
-
- // DRAW SKULL
- V_DrawPatchDirect(x + SKULLXOFF,currentMenu->y - 5 + itemOn*LINEHEIGHT, 0,
- W_CacheLumpName(DEH_String(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;
-
- // Here we could catch other version dependencies,
- // like HELP1/2, and four episodes.
-
-
- switch ( gamemode )
- {
- case commercial:
- // Commercial has no "read this" entry.
- MainMenu[readthis] = MainMenu[quitdoom];
- MainDef.numitems--;
- MainDef.y += 8;
- NewDef.prevMenu = &MainDef;
- break;
- case shareware:
- // Episode 2 and 3 are handled,
- // branching to an ad screen.
- case registered:
- // We need to remove the fourth episode.
- EpiDef.numitems--;
- break;
- case retail:
- // We are fine.
- default:
- break;
- }
-
-}
-
--- a/src/m_menu.h
+++ /dev/null
@@ -1,69 +1,0 @@
-// Emacs style mode select -*- C++ -*-
-//-----------------------------------------------------------------------------
-//
-// Copyright(C) 1993-1996 Id Software, Inc.
-// Copyright(C) 2005 Simon Howard
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-// 02111-1307, USA.
-//
-// DESCRIPTION:
-// Menu widget stuff, episode selection and such.
-//
-//-----------------------------------------------------------------------------
-
-
-#ifndef __M_MENU__
-#define __M_MENU__
-
-
-
-#include "d_event.h"
-
-//
-// MENUS
-//
-// 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.
-boolean M_Responder (event_t *ev);
-
-
-// Called by main loop,
-// only used for menu (skull cursor) animation.
-void M_Ticker (void);
-
-// Called by main loop,
-// draws the menus directly into the screen buffer.
-void M_Drawer (void);
-
-// Called by D_DoomMain,
-// loads the config file.
-void M_Init (void);
-
-// Called by intro code to force menu up upon a keypress,
-// does nothing if menu is already up.
-void M_StartControlPanel (void);
-
-
-
-extern int detailLevel;
-extern int screenblocks;
-
-
-
-#endif
--- a/src/p_ceilng.c
+++ /dev/null
@@ -1,332 +1,0 @@
-// Emacs style mode select -*- C++ -*-
-//-----------------------------------------------------------------------------
-//
-// Copyright(C) 1993-1996 Id Software, Inc.
-// Copyright(C) 2005 Simon Howard
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-// 02111-1307, USA.
-//
-// DESCRIPTION: Ceiling aninmation (lowering, crushing, raising)
-//
-//-----------------------------------------------------------------------------
-
-
-
-#include "z_zone.h"
-#include "doomdef.h"
-#include "p_local.h"
-
-#include "s_sound.h"
-
-// State.
-#include "doomstat.h"
-#include "r_state.h"
-
-// Data.
-#include "sounds.h"
-
-//
-// CEILINGS
-//
-
-
-ceiling_t* activeceilings[MAXCEILINGS];
-
-
-//
-// T_MoveCeiling
-//
-
-void T_MoveCeiling (ceiling_t* ceiling)
-{
- result_e res;
-
- switch(ceiling->direction)
- {
- 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(&ceiling->sector->soundorg, sfx_stnmov);
- // ?
- break;
- }
- }
-
- if (res == pastdest)
- {
- switch(ceiling->type)
- {
- case raiseToHighest:
- P_RemoveActiveCeiling(ceiling);
- break;
-
- case silentCrushAndRaise:
- S_StartSound(&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(&ceiling->sector->soundorg, sfx_stnmov);
- }
- }
-
- if (res == pastdest)
- {
- switch(ceiling->type)
- {
- case silentCrushAndRaise:
- S_StartSound(&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 // ( res != pastdest )
- {
- 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;
- int 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.acp1 = (actionf_p1)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.acp1
- = (actionf_p1)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.acv = (actionf_v)NULL;
- activeceilings[i]->direction = 0; // in-stasis
- rtn = 1;
- }
- }
-
-
- return rtn;
-}
--- a/src/p_doors.c
+++ /dev/null
@@ -1,755 +1,0 @@
-// Emacs style mode select -*- C++ -*-
-//-----------------------------------------------------------------------------
-//
-// Copyright(C) 1993-1996 Id Software, Inc.
-// Copyright(C) 2005 Simon Howard
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-// 02111-1307, USA.
-//
-// DESCRIPTION: Door animation code (opening/closing)
-//
-//-----------------------------------------------------------------------------
-
-
-
-#include "z_zone.h"
-#include "doomdef.h"
-#include "deh_main.h"
-#include "p_local.h"
-
-#include "s_sound.h"
-
-
-// State.
-#include "doomstat.h"
-#include "r_state.h"
-
-// Data.
-#include "dstrings.h"
-#include "sounds.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(&door->sector->soundorg, sfx_bdcls);
- break;
-
- case normal:
- door->direction = -1; // time to go back down
- S_StartSound(&door->sector->soundorg, sfx_dorcls);
- break;
-
- case close30ThenOpen:
- door->direction = 1;
- S_StartSound(&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(&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(&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 = TICRATE*30;
- break;
-
- default:
- break;
- }
- }
- else if (res == crushed)
- {
- switch(door->type)
- {
- case blazeClose:
- case close: // DO NOT GO BACK UP!
- break;
-
- default:
- door->direction = 1;
- S_StartSound(&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 = DEH_String(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 = DEH_String(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 = DEH_String(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.acp1 = (actionf_p1) 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(&door->sector->soundorg, sfx_bdcls);
- break;
-
- case close:
- door->topheight = P_FindLowestCeilingSurrounding(sec);
- door->topheight -= 4*FRACUNIT;
- door->direction = -1;
- S_StartSound(&door->sector->soundorg, sfx_dorcls);
- break;
-
- case close30ThenOpen:
- door->topheight = sec->ceilingheight;
- door->direction = -1;
- S_StartSound(&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(&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(&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 = DEH_String(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 = DEH_String(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 = DEH_String(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(&sec->soundorg,sfx_bdopn);
- break;
-
- case 1: // NORMAL DOOR SOUND
- case 31:
- S_StartSound(&sec->soundorg,sfx_doropn);
- break;
-
- default: // LOCKED DOOR SOUND
- S_StartSound(&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.acp1 = (actionf_p1) 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.acp1 = (actionf_p1)T_VerticalDoor;
- door->sector = sec;
- door->direction = 0;
- door->type = normal;
- door->speed = VDOORSPEED;
- door->topcountdown = 30 * TICRATE;
-}
-
-//
-// 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.acp1 = (actionf_p1)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 * TICRATE;
-}
-
-
-
-// UNUSED
-// Separate into p_slidoor.c?
-
-#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 ( gamemode != 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->frame == SNUMFRAMES)
- {
- // IF DOOR IS DONE OPENING...
- 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->frame < 0)
- {
- // IF DOOR IS DONE CLOSING...
- 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 (gamemode != 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
--- a/src/p_enemy.c
+++ /dev/null
@@ -1,2034 +1,0 @@
-// Emacs style mode select -*- C++ -*-
-//-----------------------------------------------------------------------------
-//
-// Copyright(C) 1993-1996 Id Software, Inc.
-// Copyright(C) 2005 Simon Howard
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-// 02111-1307, USA.
-//
-// DESCRIPTION:
-// Enemy thinking, AI.
-// Action Pointer Functions
-// that are associated with states/frames.
-//
-//-----------------------------------------------------------------------------
-
-
-#include <stdlib.h>
-
-#include "m_random.h"
-#include "i_system.h"
-
-#include "doomdef.h"
-#include "p_local.h"
-
-#include "s_sound.h"
-
-#include "g_game.h"
-
-// State.
-#include "doomstat.h"
-#include "r_state.h"
-
-// Data.
-#include "sounds.h"
-
-
-
-
-typedef enum
-{
- DI_EAST,
- DI_NORTHEAST,
- DI_NORTH,
- DI_NORTHWEST,
- DI_WEST,
- DI_SOUTHWEST,
- DI_SOUTH,
- DI_SOUTHEAST,
- DI_NODIR,
- NUMDIRS
-
-} dirtype_t;
-
-
-//
-// P_NewChaseDir related LUT.
-//
-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 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
-//
-
-
-//
-// Called by P_NoiseAlert.
-// Recursively traverse adjacent sectors,
-// sound blocking lines cut off traversal.
-//
-
-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 ;i<sec->linecount ; 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; // do not 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;
- fixed_t tryy;
-
- line_t* ld;
-
- // warning: 'catch', 'throw', and 'try'
- // are all C++ reserved words
- boolean try_ok;
- boolean 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_ok = P_TryMove (actor, tryx, tryy);
-
- if (!try_ok)
- {
- // 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 is not 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 actor on
-// 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;
-}
-
-
-
-
-void P_NewChaseDir (mobj_t* actor)
-{
- fixed_t deltax;
- fixed_t deltay;
-
- dirtype_t d[3];
-
- int tdir;
- dirtype_t olddir;
-
- dirtype_t 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 != (int) 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))
- {
- // either moved forward or attacked
- return;
- }
- }
-
- 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;
- }
-
- // randomly determine direction of search
- if (P_Random()&1)
- {
- for ( tdir=DI_EAST;
- tdir<=DI_SOUTHEAST;
- tdir++ )
- {
- if (tdir != (int) turnaround)
- {
- actor->movedir =tdir;
-
- if ( P_TryWalk(actor) )
- return;
- }
- }
- }
- else
- {
- for ( tdir=DI_SOUTHEAST;
- tdir != (DI_EAST-1);
- tdir-- )
- {
- if (tdir != (int) 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 not 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;
- int 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)
- {
- // done looking
- return false;
- }
-
- 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
-// DOOM II special, map 32.
-// Uses special tag 666.
-//
-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.acp1 != (actionf_p1)P_MobjThinker)
- continue;
-
- mo2 = (mobj_t *)th;
- if (mo2 != mo
- && mo2->type == mo->type
- && mo2->health > 0)
- {
- // other Keen not dead
- return;
- }
- }
-
- 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)
- {
- // full volume
- S_StartSound (NULL, sound);
- }
- 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;
- }
-
- // do not 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;
- int damage;
- int 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;
- int bangle;
- int damage;
- int 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;
- int bangle;
- int damage;
- int 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;
- fixed_t 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
-// Detect a corpse that could be raised.
-//
-mobj_t* corpsehit;
-mobj_t* vileobj;
-fixed_t viletryx;
-fixed_t 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;
- int xh;
- int yl;
- int yh;
-
- int bx;
- int 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++)
- {
- // Call PIT_VileCheck to check
- // whether object is a corpse
- // that canbe raised.
- 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;
- }
- }
- }
- }
-
- // Return to normal attack.
- 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;
- mobj_t* target;
- unsigned an;
-
- dest = actor->tracer;
- if (!dest)
- return;
-
- target = P_SubstNullMobj(actor->target);
-
- // don't move it if the vile lost sight
- if (!P_CheckSight (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 );
-}
-
-
-
-
-//
-// Mancubus attack,
-// firing three missiles (bruisers)
-// in three different directions?
-// Doesn't look like it.
-//
-#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;
- mobj_t* target;
- int an;
-
- A_FaceTarget (actor);
-
- // Change direction to ...
- actor->angle += FATSPREAD;
- target = P_SubstNullMobj(actor->target);
- P_SpawnMissile (actor, target, MT_FATSHOT);
-
- mo = P_SpawnMissile (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;
- mobj_t* target;
- int an;
-
- A_FaceTarget (actor);
- // Now here choose opposite deviation.
- actor->angle -= FATSPREAD;
- target = P_SubstNullMobj(actor->target);
- P_SpawnMissile (actor, target, MT_FATSHOT);
-
- mo = P_SpawnMissile (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;
- mobj_t* target;
- int an;
-
- A_FaceTarget (actor);
-
- target = P_SubstNullMobj(actor->target);
-
- mo = P_SpawnMissile (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, 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;
- fixed_t y;
- fixed_t z;
-
- mobj_t* newmobj;
- angle_t an;
- int prestep;
- int count;
- thinker_t* currentthinker;
-
- // count total number of skull currently on the level
- count = 0;
-
- currentthinker = thinkercap.next;
- while (currentthinker != &thinkercap)
- {
- if ( (currentthinker->function.acp1 == (actionf_p1)P_MobjThinker)
- && ((mobj_t *)currentthinker)->type == MT_SKULL)
- count++;
- currentthinker = currentthinker->next;
- }
-
- // if there are allready 20 skulls on the level,
- // don't spit another one
- if (count > 20)
- return;
-
-
- // okay, there's playe for another one
- 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);
-
- // Check for movements.
- if (!P_TryMove (newmobj, newmobj->x, newmobj->y))
- {
- // kill it immediately
- P_DamageMobj (newmobj,actor,actor,10000);
- 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;
- }
-
- // Check for bosses.
- if (actor->type==MT_SPIDER
- || actor->type == MT_CYBORG)
- {
- // full volume
- S_StartSound (NULL, sound);
- }
- 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;
-
- // So change this if corpse objects
- // are meant to be obstacles.
-}
-
-
-//
-// 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 ( gamemode == commercial)
- {
- if (gamemap != 7)
- return;
-
- if ((mo->type != MT_FATSO)
- && (mo->type != MT_BABY))
- return;
- }
- else
- {
- switch(gameepisode)
- {
- case 1:
- if (gamemap != 8)
- return;
-
- // fraggle: disable this as it breaks uac_dead.wad.
- // There is at least one version of Doom 1.9 which it is
- // possible to play uac_dead through on. I think this was
- // added here for Ultimate Doom.
- //
- // See lmps/doom/ultimate/uac_dead.zip in idgames for
- // an example of a demo which goes out of sync if this
- // is left in here.
- //
- // For the time being, I'm making the assumption that
- // doing this is not going to break anything else.
- //
- // 2005/10/24: Modify this to test the gameversion setting
-
- if (gameversion >= exe_ultimate && mo->type != MT_BRUISER)
- return;
- break;
-
- case 2:
- if (gamemap != 8)
- return;
-
- if (mo->type != MT_CYBORG)
- return;
- break;
-
- case 3:
- if (gamemap != 8)
- return;
-
- if (mo->type != MT_SPIDER)
- return;
-
- break;
-
- case 4:
- switch(gamemap)
- {
- case 6:
- if (mo->type != MT_CYBORG)
- return;
- break;
-
- case 8:
- if (mo->type != MT_SPIDER)
- return;
- break;
-
- default:
- return;
- break;
- }
- break;
-
- default:
- if (gamemap != 8)
- return;
- break;
- }
-
- }
-
-
- // make sure there is a player alive for victory
- for (i=0 ; i<MAXPLAYERS ; i++)
- if (playeringame[i] && players[i].health > 0)
- break;
-
- if (i==MAXPLAYERS)
- return; // no one left alive, so do not 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.acp1 != (actionf_p1)P_MobjThinker)
- continue;
-
- mo2 = (mobj_t *)th;
- if (mo2 != mo
- && mo2->type == mo->type
- && mo2->health > 0)
- {
- // other boss not dead
- return;
- }
- }
-
- // victory!
- if ( gamemode == 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
- {
- switch(gameepisode)
- {
- case 1:
- junk.tag = 666;
- EV_DoFloor (&junk, lowerFloorToLowest);
- return;
- break;
-
- case 4:
- switch(gamemap)
- {
- case 6:
- junk.tag = 666;
- EV_DoDoor (&junk, blazeOpen);
- return;
- break;
-
- case 8:
- junk.tag = 666;
- EV_DoFloor (&junk, lowerFloorToLowest);
- return;
- break;
- }
- }
- }
-
- 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 = 0;
-
-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.acp1 != (actionf_p1)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;
- int y;
- int 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;
- int y;
- int 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);
-
-// travelling cube sound
-void A_SpawnSound (mobj_t* mo)
-{
- 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 = P_SubstNullMobj(mo->target);
-
- // First spawn teleport fog.
- fog = P_SpawnMobj (targ->x, targ->y, targ->z, MT_SPAWNFIRE);
- S_StartSound (fog, sfx_telept);
-
- // Randomly select monster to spawn.
- r = P_Random ();
-
- // Probability distribution (kind of :),
- // decreasing likelihood.
- 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 (i.e., cube).
- P_RemoveMobj (mo);
-}
-
-
-
-void A_PlayerScream (mobj_t* mo)
-{
- // Default death sound.
- int sound = sfx_pldeth;
-
- if ( (gamemode == commercial)
- && (mo->health < -50))
- {
- // IF THE PLAYER DIES
- // LESS THAN -50% WITHOUT GIBBING
- sound = sfx_pdiehi;
- }
-
- S_StartSound (mo, sound);
-}
--- a/src/p_floor.c
+++ /dev/null
@@ -1,554 +1,0 @@
-// Emacs style mode select -*- C++ -*-
-//-----------------------------------------------------------------------------
-//
-// Copyright(C) 1993-1996 Id Software, Inc.
-// Copyright(C) 2005 Simon Howard
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-// 02111-1307, USA.
-//
-// DESCRIPTION:
-// Floor animation: raising stairs.
-//
-//-----------------------------------------------------------------------------
-
-
-
-#include "z_zone.h"
-#include "doomdef.h"
-#include "p_local.h"
-
-#include "s_sound.h"
-
-// State.
-#include "doomstat.h"
-#include "r_state.h"
-// Data.
-#include "sounds.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);
-// UNUSED
-#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(&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(&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.acp1 = (actionf_p1) 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 = INT_MAX;
- 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;
- sector_t* tsec;
-
- floormove_t* floor;
-
- fixed_t stairsize = 0;
- fixed_t speed = 0;
-
- 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.acp1 = (actionf_p1) 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.acp1 = (actionf_p1) T_MoveFloor;
- floor->direction = 1;
- floor->sector = sec;
- floor->speed = speed;
- floor->floordestheight = height;
- ok = 1;
- break;
- }
- } while(ok);
- }
- return rtn;
-}
-
--- a/src/p_inter.c
+++ /dev/null
@@ -1,928 +1,0 @@
-// Emacs style mode select -*- C++ -*-
-//-----------------------------------------------------------------------------
-//
-// Copyright(C) 1993-1996 Id Software, Inc.
-// Copyright(C) 2005 Simon Howard
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-// 02111-1307, USA.
-//
-// DESCRIPTION:
-// Handling interactions (i.e., collisions).
-//
-//-----------------------------------------------------------------------------
-
-
-
-
-// Data.
-#include "doomdef.h"
-#include "dstrings.h"
-#include "sounds.h"
-
-#include "deh_main.h"
-#include "deh_misc.h"
-#include "doomstat.h"
-
-#include "m_random.h"
-#include "i_system.h"
-
-#include "am_map.h"
-
-#include "p_local.h"
-
-#include "s_sound.h"
-
-#include "p_inter.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 > 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)
- {
- // give double ammo in trainer mode,
- // you'll need in nightmare
- num <<= 1;
- }
-
-
- oldammo = player->ammo[ammo];
- player->ammo[ammo] += num;
-
- if (player->ammo[ammo] > player->maxammo[ammo])
- player->ammo[ammo] = player->maxammo[ammo];
-
- // If non zero ammo,
- // don't change up weapons,
- // player was lower on purpose.
- if (oldammo)
- return true;
-
- // We were down to zero,
- // so select a new weapon.
- // Preferences are not user selectable.
- 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;
- boolean 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,
- int /*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)
- {
- // out of reach
- return;
- }
-
-
- sound = sfx_itemup;
- player = toucher->player;
-
- // Dead thing touching.
- // Can happen with a sliding player corpse.
- if (toucher->health <= 0)
- return;
-
- // Identify by sprite.
- switch (special->sprite)
- {
- // armor
- case SPR_ARM1:
- if (!P_GiveArmor (player, deh_green_armor_class))
- return;
- player->message = DEH_String(GOTARMOR);
- break;
-
- case SPR_ARM2:
- if (!P_GiveArmor (player, deh_blue_armor_class))
- return;
- player->message = DEH_String(GOTMEGA);
- break;
-
- // bonus items
- case SPR_BON1:
- player->health++; // can go over 100%
- if (player->health > deh_max_health)
- player->health = deh_max_health;
- player->mo->health = player->health;
- player->message = DEH_String(GOTHTHBONUS);
- break;
-
- case SPR_BON2:
- player->armorpoints++; // can go over 100%
- if (player->armorpoints > deh_max_armor)
- player->armorpoints = deh_max_armor;
- // deh_green_armor_class only applies to the green armor shirt;
- // for the armor helmets, armortype 1 is always used.
- if (!player->armortype)
- player->armortype = 1;
- player->message = DEH_String(GOTARMBONUS);
- break;
-
- case SPR_SOUL:
- player->health += deh_soulsphere_health;
- if (player->health > deh_max_soulsphere)
- player->health = deh_max_soulsphere;
- player->mo->health = player->health;
- player->message = DEH_String(GOTSUPER);
- sound = sfx_getpow;
- break;
-
- case SPR_MEGA:
- if (gamemode != commercial)
- return;
- player->health = deh_megasphere_health;
- player->mo->health = player->health;
- // We always give armor type 2 for the megasphere; dehacked only
- // affects the MegaArmor.
- P_GiveArmor (player, 2);
- player->message = DEH_String(GOTMSPHERE);
- sound = sfx_getpow;
- break;
-
- // cards
- // leave cards for everyone
- case SPR_BKEY:
- if (!player->cards[it_bluecard])
- player->message = DEH_String(GOTBLUECARD);
- P_GiveCard (player, it_bluecard);
- if (!netgame)
- break;
- return;
-
- case SPR_YKEY:
- if (!player->cards[it_yellowcard])
- player->message = DEH_String(GOTYELWCARD);
- P_GiveCard (player, it_yellowcard);
- if (!netgame)
- break;
- return;
-
- case SPR_RKEY:
- if (!player->cards[it_redcard])
- player->message = DEH_String(GOTREDCARD);
- P_GiveCard (player, it_redcard);
- if (!netgame)
- break;
- return;
-
- case SPR_BSKU:
- if (!player->cards[it_blueskull])
- player->message = DEH_String(GOTBLUESKUL);
- P_GiveCard (player, it_blueskull);
- if (!netgame)
- break;
- return;
-
- case SPR_YSKU:
- if (!player->cards[it_yellowskull])
- player->message = DEH_String(GOTYELWSKUL);
- P_GiveCard (player, it_yellowskull);
- if (!netgame)
- break;
- return;
-
- case SPR_RSKU:
- if (!player->cards[it_redskull])
- player->message = DEH_String(GOTREDSKULL);
- P_GiveCard (player, it_redskull);
- if (!netgame)
- break;
- return;
-
- // medikits, heals
- case SPR_STIM:
- if (!P_GiveBody (player, 10))
- return;
- player->message = DEH_String(GOTSTIM);
- break;
-
- case SPR_MEDI:
- if (!P_GiveBody (player, 25))
- return;
-
- if (player->health < 25)
- player->message = DEH_String(GOTMEDINEED);
- else
- player->message = DEH_String(GOTMEDIKIT);
- break;
-
-
- // power ups
- case SPR_PINV:
- if (!P_GivePower (player, pw_invulnerability))
- return;
- player->message = DEH_String(GOTINVUL);
- sound = sfx_getpow;
- break;
-
- case SPR_PSTR:
- if (!P_GivePower (player, pw_strength))
- return;
- player->message = DEH_String(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 = DEH_String(GOTINVIS);
- sound = sfx_getpow;
- break;
-
- case SPR_SUIT:
- if (!P_GivePower (player, pw_ironfeet))
- return;
- player->message = DEH_String(GOTSUIT);
- sound = sfx_getpow;
- break;
-
- case SPR_PMAP:
- if (!P_GivePower (player, pw_allmap))
- return;
- player->message = DEH_String(GOTMAP);
- sound = sfx_getpow;
- break;
-
- case SPR_PVIS:
- if (!P_GivePower (player, pw_infrared))
- return;
- player->message = DEH_String(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 = DEH_String(GOTCLIP);
- break;
-
- case SPR_AMMO:
- if (!P_GiveAmmo (player, am_clip,5))
- return;
- player->message = DEH_String(GOTCLIPBOX);
- break;
-
- case SPR_ROCK:
- if (!P_GiveAmmo (player, am_misl,1))
- return;
- player->message = DEH_String(GOTROCKET);
- break;
-
- case SPR_BROK:
- if (!P_GiveAmmo (player, am_misl,5))
- return;
- player->message = DEH_String(GOTROCKBOX);
- break;
-
- case SPR_CELL:
- if (!P_GiveAmmo (player, am_cell,1))
- return;
- player->message = DEH_String(GOTCELL);
- break;
-
- case SPR_CELP:
- if (!P_GiveAmmo (player, am_cell,5))
- return;
- player->message = DEH_String(GOTCELLBOX);
- break;
-
- case SPR_SHEL:
- if (!P_GiveAmmo (player, am_shell,1))
- return;
- player->message = DEH_String(GOTSHELLS);
- break;
-
- case SPR_SBOX:
- if (!P_GiveAmmo (player, am_shell,5))
- return;
- player->message = DEH_String(GOTSHELLBOX);
- break;
-
- case SPR_BPAK:
- if (!player->backpack)
- {
- for (i=0 ; i<NUMAMMO ; i++)
- player->maxammo[i] *= 2;
- player->backpack = true;
- }
- for (i=0 ; i<NUMAMMO ; i++)
- P_GiveAmmo (player, i, 1);
- player->message = DEH_String(GOTBACKPACK);
- break;
-
- // weapons
- case SPR_BFUG:
- if (!P_GiveWeapon (player, wp_bfg, false) )
- return;
- player->message = DEH_String(GOTBFG9000);
- sound = sfx_wpnup;
- break;
-
- case SPR_MGUN:
- if (!P_GiveWeapon (player, wp_chaingun, special->flags&MF_DROPPED) )
- return;
- player->message = DEH_String(GOTCHAINGUN);
- sound = sfx_wpnup;
- break;
-
- case SPR_CSAW:
- if (!P_GiveWeapon (player, wp_chainsaw, false) )
- return;
- player->message = DEH_String(GOTCHAINSAW);
- sound = sfx_wpnup;
- break;
-
- case SPR_LAUN:
- if (!P_GiveWeapon (player, wp_missile, false) )
- return;
- player->message = DEH_String(GOTLAUNCHER);
- sound = sfx_wpnup;
- break;
-
- case SPR_PLAS:
- if (!P_GiveWeapon (player, wp_plasma, false) )
- return;
- player->message = DEH_String(GOTPLASMA);
- sound = sfx_wpnup;
- break;
-
- case SPR_SHOT:
- if (!P_GiveWeapon (player, wp_shotgun, special->flags&MF_DROPPED ) )
- return;
- player->message = DEH_String(GOTSHOTGUN);
- sound = sfx_wpnup;
- break;
-
- case SPR_SGN2:
- if (!P_GiveWeapon (player, wp_supershotgun, special->flags&MF_DROPPED ) )
- return;
- player->message = DEH_String(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)
- {
- // count for intermission
- if (target->flags & MF_COUNTKILL)
- source->player->killcount++;
-
- if (target->player)
- source->player->frags[target->player-players]++;
- }
- else if (!netgame && (target->flags & MF_COUNTKILL) )
- {
- // count all monster deaths,
- // even those caused by other monsters
- players[0].killcount++;
- }
-
- if (target->player)
- {
- // count environment kills against you
- if (!source)
- 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)
- {
- // don't die in auto map,
- // switch view prior to dying
- AM_Stop ();
- }
-
- }
-
- 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);
-
- // In Chex Quest, monsters don't drop items.
-
- if (gameversion == exe_chex)
- {
- return;
- }
-
- // Drop stuff.
- // This determines the kind of object spawned
- // during the death frame of a thing.
- 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 slime, 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
-
-
- // Some close combat weapons should not
- // inflict thrust and push the victim out of reach,
- // thus 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;
- }
-
-
- // Below certain threshold,
- // ignore damage in GOD mode, or with INVUL power.
- 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);
- }
-
-}
-
--- a/src/p_inter.h
+++ /dev/null
@@ -1,38 +1,0 @@
-// Emacs style mode select -*- C++ -*-
-//-----------------------------------------------------------------------------
-//
-// Copyright(C) 1993-1996 Id Software, Inc.
-// Copyright(C) 2005 Simon Howard
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-// 02111-1307, USA.
-//
-// DESCRIPTION:
-//
-//
-//-----------------------------------------------------------------------------
-
-
-#ifndef __P_INTER__
-#define __P_INTER__
-
-
-
-
-boolean P_GivePower(player_t*, int);
-
-
-
-#endif
--- a/src/p_lights.c
+++ /dev/null
@@ -1,358 +1,0 @@
-// Emacs style mode select -*- C++ -*-
-//-----------------------------------------------------------------------------
-//
-// Copyright(C) 1993-1996 Id Software, Inc.
-// Copyright(C) 2005 Simon Howard
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-// 02111-1307, USA.
-//
-// DESCRIPTION:
-// Handle Sector base lighting effects.
-// Muzzle flash?
-//
-//-----------------------------------------------------------------------------
-
-
-
-#include "z_zone.h"
-#include "m_random.h"
-
-#include "doomdef.h"
-#include "p_local.h"
-
-
-// State.
-#include "r_state.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;
-
- // Note that we are resetting sector attributes.
- // Nothing special about it during gameplay.
- sector->special = 0;
-
- flick = Z_Malloc ( sizeof(*flick), PU_LEVSPEC, 0);
-
- P_AddThinker (&flick->thinker);
-
- flick->thinker.function.acp1 = (actionf_p1) 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
-// Do flashing lights.
-//
-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;
-
- // nothing special about it during gameplay
- sector->special = 0;
-
- flash = Z_Malloc ( sizeof(*flash), PU_LEVSPEC, 0);
-
- P_AddThinker (&flash->thinker);
-
- flash->thinker.function.acp1 = (actionf_p1) 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
-//
-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_SpawnStrobeFlash
-// 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.acp1 = (actionf_p1) T_StrobeFlash;
- flash->maxlight = sector->lightlevel;
- flash->minlight = P_FindMinSurroundingLight(sector, sector->lightlevel);
-
- if (flash->minlight == flash->maxlight)
- flash->minlight = 0;
-
- // nothing special about it during gameplay
- sector->special = 0;
-
- 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;i<numsectors;i++, sector++)
- {
- if (sector->tag == 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.acp1 = (actionf_p1) T_Glow;
- g->direction = -1;
-
- sector->special = 0;
-}
-
--- a/src/p_local.h
+++ /dev/null
@@ -1,291 +1,0 @@
-// Emacs style mode select -*- C++ -*-
-//-----------------------------------------------------------------------------
-//
-// Copyright(C) 1993-1996 Id Software, Inc.
-// Copyright(C) 2005 Simon Howard
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-// 02111-1307, USA.
-//
-// DESCRIPTION:
-// Play functions, animation, global header.
-//
-//-----------------------------------------------------------------------------
-
-
-#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 do not 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)
-
-// follow a player exlusively for 3 seconds
-#define BASETHRESHOLD 100
-
-
-
-//
-// P_TICK
-//
-
-// both the head and tail of the thinker list
-extern thinker_t thinkercap;
-
-
-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 INT_MIN
-#define ONCEILINGZ INT_MAX
-
-// Time interval for item respawning.
-#define ITEMQUESIZE 128
-
-extern mapthing_t itemrespawnque[ITEMQUESIZE];
-extern int itemrespawntime[ITEMQUESIZE];
-extern int iquehead;
-extern int 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);
-mobj_t* P_SubstNullMobj (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;
- fixed_t y;
- fixed_t dx;
- fixed_t dy;
-
-} divline_t;
-
-typedef struct
-{
- fixed_t frac; // along trace line
- boolean isaline;
- union {
- mobj_t* thing;
- line_t* line;
- } d;
-} intercept_t;
-
-// Extended MAXINTERCEPTS, to allow for intercepts overrun emulation.
-
-#define MAXINTERCEPTS_ORIGINAL 128
-#define MAXINTERCEPTS (MAXINTERCEPTS_ORIGINAL + 61)
-
-extern intercept_t intercepts[MAXINTERCEPTS];
-extern intercept_t* 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;
-extern fixed_t openbottom;
-extern fixed_t 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
-//
-
-// If "floatok" true, move would be ok
-// if within "tmfloorz - tmceilingz".
-extern boolean floatok;
-extern fixed_t tmfloorz;
-extern fixed_t 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;
-extern int bmapheight; // in mapblocks
-extern fixed_t bmaporgx;
-extern fixed_t 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 );
-
-
-//
-// P_SPEC
-//
-#include "p_spec.h"
-
-
-#endif // __P_LOCAL__
--- a/src/p_map.c
+++ /dev/null
@@ -1,1448 +1,0 @@
-// Emacs style mode select -*- C++ -*-
-//-----------------------------------------------------------------------------
-//
-// Copyright(C) 1993-1996 Id Software, Inc.
-// Copyright(C) 2005 Simon Howard, Andrey Budko
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-// 02111-1307, USA.
-//
-// DESCRIPTION:
-// Movement, collision handling.
-// Shooting and aiming.
-//
-//-----------------------------------------------------------------------------
-
-
-#include <stdlib.h>
-
-#include "deh_misc.h"
-
-#include "m_bbox.h"
-#include "m_random.h"
-#include "i_system.h"
-
-#include "doomdef.h"
-#include "m_argv.h"
-#include "p_local.h"
-
-#include "s_sound.h"
-
-// State.
-#include "doomstat.h"
-#include "r_state.h"
-// Data.
-#include "sounds.h"
-
-// Spechit overrun magic value.
-//
-// This is the value used by PrBoom-plus. I think the value below is
-// actually better and works with more demos. However, I think
-// it's better for the spechits emulation to be compatible with
-// PrBoom-plus, at least so that the big spechits emulation list
-// on Doomworld can also be used with Chocolate Doom.
-
-#define DEFAULT_SPECHIT_MAGIC 0x01C09C98
-
-// This is from a post by myk on the Doomworld forums,
-// outputted from entryway's spechit_magic generator for
-// s205n546.lmp. The _exact_ value of this isn't too
-// important; as long as it is in the right general
-// range, it will usually work. Otherwise, we can use
-// the generator (hacked doom2.exe) and provide it
-// with -spechit.
-
-//#define DEFAULT_SPECHIT_MAGIC 0x84f968e8
-
-
-fixed_t tmbbox[4];
-mobj_t* tmthing;
-int tmflags;
-fixed_t tmx;
-fixed_t tmy;
-
-
-// If "floatok" true, move would be ok
-// if within "tmfloorz - tmceilingz".
-boolean floatok;
-
-fixed_t tmfloorz;
-fixed_t tmceilingz;
-fixed_t 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
-
-// fraggle: I have increased the size of this buffer. In the original Doom,
-// overrunning past this limit caused other bits of memory to be overwritten,
-// affecting demo playback. However, in doing so, the limit was still
-// exceeded. So we have to support more than 8 specials.
-//
-// We keep the original limit, to detect what variables in memory were
-// overwritten (see SpechitOverrun())
-
-#define MAXSPECIALCROSS 20
-#define MAXSPECIALCROSS_ORIGINAL 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 )
- {
- // didn't hit it
- return true;
- }
-
- // don't clip against self
- if (thing == tmthing)
- return true;
-
- // monsters don't stomp things except on boss level
- if ( !tmthing->player && gamemap != 30)
- return false;
-
- P_DamageMobj (thing, tmthing, tmthing, 10000);
-
- return true;
-}
-
-
-//
-// P_TeleportMove
-//
-boolean
-P_TeleportMove
-( mobj_t* thing,
- fixed_t x,
- fixed_t y )
-{
- int xl;
- int xh;
- int yl;
- int yh;
- int bx;
- int 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
-//
-
-static void SpechitOverrun(line_t *ld);
-
-//
-// 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
- }
-
- // set openrange, opentop, openbottom
- P_LineOpening (ld);
-
- // 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++;
-
- // fraggle: spechits overrun emulation code from prboom-plus
- if (numspechit > MAXSPECIALCROSS_ORIGINAL)
- {
- SpechitOverrun(ld);
- }
- }
-
- 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 )
- {
- // didn't hit it
- return true;
- }
-
- // don't clip against self
- if (thing == tmthing)
- return true;
-
- // 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;
-
- // sdh: Add deh_species_infighting here. We can override the
- // "monsters of the same species cant hurt each other" behavior
- // through dehacked patches
-
- if (thing->type != MT_PLAYER && !deh_species_infighting)
- {
- // Explode, but do no damage.
- // Let players missile other players.
- return false;
- }
- }
-
- if (! (thing->flags & MF_SHOOTABLE) )
- {
- // didn't do any damage
- return !(thing->flags & MF_SOLID);
- }
-
- // damage / explode
- damage = ((P_Random()%8)+1)*tmthing->info->damage;
- P_DamageMobj (thing, tmthing, tmthing->target, damage);
-
- // don't traverse any more
- return false;
- }
-
- // check for special pickup
- if (thing->flags & MF_SPECIAL)
- {
- solid = thing->flags&MF_SOLID;
- if (tmflags&MF_PICKUP)
- {
- // can remove thing
- P_TouchSpecialThing (thing, tmthing);
- }
- 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;
- int xh;
- int yl;
- int yh;
- int bx;
- int 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;
- fixed_t oldy;
- int side;
- int 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, and 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;
-fixed_t secondslidefrac;
-
-line_t* bestslideline;
-line_t* secondslideline;
-
-mobj_t* slidemo;
-
-fixed_t tmxmove;
-fixed_t 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;
- angle_t moveangle;
- angle_t deltaangle;
-
- fixed_t movelen;
- fixed_t 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))
- {
- // don't hit the back side
- return true;
- }
- goto isblocking;
- }
-
- // set openrange, opentop, openbottom
- P_LineOpening (li);
-
- 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
-
- // this line doesn't block movement
- return true;
-
- // 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;
- fixed_t leady;
- fixed_t trailx;
- fixed_t traily;
- fixed_t newx;
- fixed_t 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;
- }
-
- // fudge a bit to make sure it doesn't hit
- bestslidefrac -= 0x800;
- 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.
- // First calculate remainder.
- bestslidefrac = FRACUNIT-(bestslidefrac+0x800);
-
- 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;
-
-// Height if not aiming up or down
-// ???: use slope for monsters?
-fixed_t shootz;
-
-int la_damage;
-fixed_t attackrange;
-
-fixed_t aimslope;
-
-// slopes to top and bottom of target
-extern fixed_t topslope;
-extern fixed_t bottomslope;
-
-
-//
-// 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;
- fixed_t thingtopslope;
- fixed_t 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;
- fixed_t y;
- fixed_t z;
- fixed_t frac;
-
- line_t* li;
-
- mobj_t* th;
-
- fixed_t slope;
- fixed_t dist;
- fixed_t thingtopslope;
- fixed_t 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;
- }
-
- // shot continues
- return true;
-
-
- // 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)
- {
- // don't shoot the sky!
- if (z > li->frontsector->ceilingheight)
- return false;
-
- // it's a sky hack wall
- if (li->backsector && li->backsector->ceilingpic == skyflatnum)
- return false;
- }
-
- // Spawn bullet puffs.
- P_SpawnPuff (x,y,z);
-
- // don't go any farther
- return false;
- }
-
- // 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));
-
- // Spawn bullet puffs or blod spots,
- // depending on target type.
- 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);
-
- // don't go any farther
- return false;
-
-}
-
-
-//
-// P_AimLineAttack
-//
-fixed_t
-P_AimLineAttack
-( mobj_t* t1,
- angle_t angle,
- fixed_t distance )
-{
- fixed_t x2;
- fixed_t y2;
-
- t1 = P_SubstNullMobj(t1);
-
- 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;
-
- // can't shoot outside view angles
- topslope = 100*FRACUNIT/160;
- 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;
- fixed_t 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);
-
- // can't use through a wall
- return false;
- }
- // not a special line, but keep checking
- return true ;
- }
-
- 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);
-
- // can't use for than one special line in a row
- return false;
-}
-
-
-//
-// P_UseLines
-// Looks for special lines in front of the player to activate.
-//
-void P_UseLines (player_t* player)
-{
- int angle;
- fixed_t x1;
- fixed_t y1;
- fixed_t x2;
- fixed_t 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
-// "bombsource" is the creature
-// that caused the explosion at "bombspot".
-//
-boolean PIT_RadiusAttack (mobj_t* thing)
-{
- fixed_t dx;
- fixed_t dy;
- fixed_t dist;
-
- if (!(thing->flags & MF_SHOOTABLE) )
- return true;
-
- // Boss spider and cyborg
- // take no damage from concussion.
- if (thing->type == MT_CYBORG
- || thing->type == MT_SPIDER)
- return true;
-
- 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 caused the explosion at spot.
-//
-void
-P_RadiusAttack
-( mobj_t* spot,
- mobj_t* source,
- int damage )
-{
- int x;
- int y;
-
- int xl;
- int xh;
- int yl;
- int yh;
-
- fixed_t dist;
-
- dist = (damage+MAXRADIUS)<<FRACBITS;
- yh = (spot->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))
- {
- // keep checking
- return true;
- }
-
-
- // crunch bodies to giblets
- if (thing->health <= 0)
- {
- P_SetMobjState (thing, S_GIBS);
-
- thing->flags &= ~MF_SOLID;
- thing->height = 0;
- thing->radius = 0;
-
- // keep checking
- return true;
- }
-
- // crunch dropped items
- if (thing->flags & MF_DROPPED)
- {
- P_RemoveMobj (thing);
-
- // keep checking
- return true;
- }
-
- if (! (thing->flags & MF_SHOOTABLE) )
- {
- // assume it is bloody gibs or something
- return true;
- }
-
- 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;
- }
-
- // keep checking (crush other things)
- return true;
-}
-
-
-
-//
-// P_ChangeSector
-//
-boolean
-P_ChangeSector
-( sector_t* sector,
- boolean crunch )
-{
- int x;
- int y;
-
- nofit = false;
- crushchange = crunch;
-
- // re-check 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;
-}
-
-// Code to emulate the behavior of Vanilla Doom when encountering an overrun
-// of the spechit array. This is by Andrey Budko (e6y) and comes from his
-// PrBoom plus port. A big thanks to Andrey for this.
-
-static void SpechitOverrun(line_t *ld)
-{
- static unsigned int baseaddr = 0;
- unsigned int addr;
-
- if (baseaddr == 0)
- {
- int p;
-
- // This is the first time we have had an overrun. Work out
- // what base address we are going to use.
- // Allow a spechit value to be specified on the command line.
-
- //!
- // @category compat
- // @arg <n>
- //
- // Use the specified magic value when emulating spechit overruns.
- //
-
- p = M_CheckParm("-spechit");
-
- if (p > 0)
- {
- baseaddr = atoi(myargv[p+1]);
- }
- else
- {
- baseaddr = DEFAULT_SPECHIT_MAGIC;
- }
- }
-
- // Calculate address used in doom2.exe
-
- addr = baseaddr + (ld - lines) * 0x3E;
-
- switch(numspechit)
- {
- case 9:
- case 10:
- case 11:
- case 12:
- tmbbox[numspechit-9] = addr;
- break;
- case 13:
- crushchange = addr;
- break;
- case 14:
- nofit = addr;
- break;
- default:
- fprintf(stderr, "SpechitOverrun: Warning: unable to emulate"
- "an overrun where numspechit=%i\n",
- numspechit);
- break;
- }
-}
-
--- a/src/p_maputl.c
+++ /dev/null
@@ -1,1009 +1,0 @@
-// Emacs style mode select -*- C++ -*-
-//-----------------------------------------------------------------------------
-//
-// Copyright(C) 1993-1996 Id Software, Inc.
-// Copyright(C) 2005 Simon Howard
-// Copyright(C) 2005, 2006 Andrey Budko
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-// 02111-1307, USA.
-//
-// DESCRIPTION:
-// Movement/collision utility functions,
-// as used by function in p_map.c.
-// BLOCKMAP Iterator functions,
-// and some PIT_* functions to use for iteration.
-//
-//-----------------------------------------------------------------------------
-
-
-
-#include <stdlib.h>
-
-
-#include "m_bbox.h"
-
-#include "doomdef.h"
-#include "doomstat.h"
-#include "p_local.h"
-
-
-// State.
-#include "r_state.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;
- fixed_t dy;
- fixed_t left;
- fixed_t 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 = 0;
- int p2 = 0;
-
- 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;
- fixed_t dy;
- fixed_t left;
- fixed_t 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;
- fixed_t num;
- fixed_t 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 // UNUSED, float debug.
- float frac;
- float num;
- float den;
- float v1x;
- float v1y;
- float v1dx;
- float v1dy;
- float v2x;
- float v2y;
- float v2dx;
- float 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;
-fixed_t openbottom;
-fixed_t openrange;
-fixed_t lowfloor;
-
-
-void P_LineOpening (line_t* linedef)
-{
- sector_t* front;
- sector_t* 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.
-// On each position change, BLOCKMAP and other
-// lookups maintaining lists ot things inside
-// these structures need to be updated.
-//
-void P_UnsetThingPosition (mobj_t* thing)
-{
- int blockx;
- int 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 <bmapheight)
- {
- blocklinks[blocky*bmapwidth+blockx] = thing->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;
- int 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 < bmapheight)
- {
- link = &blocklinks[blocky*bmapwidth+blockx];
- thing->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 PIT_* 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_t* intercept_p;
-
-divline_t trace;
-boolean earlyout;
-int ptflags;
-
-static void InterceptsOverrun(int num_intercepts, intercept_t *intercept);
-
-//
-// 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;
- int 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;
- InterceptsOverrun(intercept_p - intercepts, intercept_p);
- intercept_p++;
-
- return true; // continue
-}
-
-
-
-//
-// PIT_AddThingIntercepts
-//
-boolean PIT_AddThingIntercepts (mobj_t* thing)
-{
- fixed_t x1;
- fixed_t y1;
- fixed_t x2;
- fixed_t y2;
-
- int s1;
- int 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;
- InterceptsOverrun(intercept_p - intercepts, intercept_p);
- 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;
- intercept_t* in;
-
- count = intercept_p - intercepts;
-
- in = 0; // shut up compiler warning
-
- while (count--)
- {
- dist = INT_MAX;
- for (scan = intercepts ; scan<intercept_p ; scan++)
- {
- if (scan->frac < dist)
- {
- dist = scan->frac;
- in = scan;
- }
- }
-
- if (dist > maxfrac)
- return true; // checked everything in range
-
-#if 0 // UNUSED
- {
- // don't check these yet, there may be others inserted
- in = scan = intercepts;
- for ( scan = intercepts ; scan<intercept_p ; scan++)
- if (scan->frac > maxfrac)
- *in++ = *scan;
- intercept_p = in;
- return false;
- }
-#endif
-
- if ( !func (in) )
- return false; // don't bother going farther
-
- in->frac = INT_MAX;
- }
-
- return true; // everything was traversed
-}
-
-extern fixed_t bulletslope;
-
-// Intercepts Overrun emulation, from PrBoom-plus.
-// Thanks to Andrey Budko (entryway) for researching this and his
-// implementation of Intercepts Overrun emulation in PrBoom-plus
-// which this is based on.
-
-typedef struct
-{
- int len;
- void *addr;
- boolean int16_array;
-} intercepts_overrun_t;
-
-// Intercepts memory table. This is where various variables are located
-// in memory in Vanilla Doom. When the intercepts table overflows, we
-// need to write to them.
-//
-// Almost all of the values to overwrite are 32-bit integers, except for
-// playerstarts, which is effectively an array of 16-bit integers and
-// must be treated differently.
-
-static intercepts_overrun_t intercepts_overrun[] =
-{
- {4, NULL, false},
- {4, NULL, /* &earlyout, */ false},
- {4, NULL, /* &intercept_p, */ false},
- {4, &lowfloor, false},
- {4, &openbottom, false},
- {4, &opentop, false},
- {4, &openrange, false},
- {4, NULL, false},
- {120, NULL, /* &activeplats, */ false},
- {8, NULL, false},
- {4, &bulletslope, false},
- {4, NULL, /* &swingx, */ false},
- {4, NULL, /* &swingy, */ false},
- {4, NULL, false},
- {40, &playerstarts, true},
- {4, NULL, /* &blocklinks, */ false},
- {4, &bmapwidth, false},
- {4, NULL, /* &blockmap, */ false},
- {4, &bmaporgx, false},
- {4, &bmaporgy, false},
- {4, NULL, /* &blockmaplump, */ false},
- {4, &bmapheight, false},
- {0, NULL, false},
-};
-
-// Overwrite a specific memory location with a value.
-
-static void InterceptsMemoryOverrun(int location, int value)
-{
- int i, offset;
- int index;
- void *addr;
-
- i = 0;
- offset = 0;
-
- // Search down the array until we find the right entry
-
- while (intercepts_overrun[i].len != 0)
- {
- if (offset + intercepts_overrun[i].len > location)
- {
- addr = intercepts_overrun[i].addr;
-
- // Write the value to the memory location.
- // 16-bit and 32-bit values are written differently.
-
- if (addr != NULL)
- {
- if (intercepts_overrun[i].int16_array)
- {
- index = (location - offset) / 2;
- ((short *) addr)[index] = value & 0xffff;
- ((short *) addr)[index + 1] = (value >> 16) & 0xffff;
- }
- else
- {
- index = (location - offset) / 4;
- ((int *) addr)[index] = value;
- }
- }
-
- break;
- }
-
- offset += intercepts_overrun[i].len;
- ++i;
- }
-}
-
-// Emulate overruns of the intercepts[] array.
-
-static void InterceptsOverrun(int num_intercepts, intercept_t *intercept)
-{
- int location;
-
- if (num_intercepts <= MAXINTERCEPTS_ORIGINAL)
- {
- // No overrun
-
- return;
- }
-
- location = (num_intercepts - MAXINTERCEPTS_ORIGINAL - 1) * 12;
-
- // Overwrite memory that is overwritten in Vanilla Doom, using
- // the values from the intercept structure.
- //
- // Note: the ->d.{thing,line} member should really have its
- // address translated into the correct address value for
- // Vanilla Doom.
-
- InterceptsMemoryOverrun(location, intercept->frac);
- InterceptsMemoryOverrun(location + 4, intercept->isaline);
- InterceptsMemoryOverrun(location + 8, (int) intercept->d.thing);
-}
-
-
-//
-// 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;
- fixed_t yt1;
- fixed_t xt2;
- fixed_t yt2;
-
- fixed_t xstep;
- fixed_t ystep;
-
- fixed_t partial;
-
- fixed_t xintercept;
- fixed_t yintercept;
-
- int mapx;
- int mapy;
-
- int mapxstep;
- int 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 );
-}
-
-
-
--- a/src/p_mobj.c
+++ /dev/null
@@ -1,1056 +1,0 @@
-// Emacs style mode select -*- C++ -*-
-//-----------------------------------------------------------------------------
-//
-// Copyright(C) 1993-1996 Id Software, Inc.
-// Copyright(C) 2005 Simon Howard
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-// 02111-1307, USA.
-//
-// DESCRIPTION:
-// Moving object handling. Spawn functions.
-//
-//-----------------------------------------------------------------------------
-
-
-#include "i_system.h"
-#include "z_zone.h"
-#include "m_random.h"
-
-#include "doomdef.h"
-#include "p_local.h"
-#include "sounds.h"
-
-#include "st_stuff.h"
-#include "hu_stuff.h"
-
-#include "s_sound.h"
-
-#include "doomstat.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;
-
- // Modified handling.
- // Call action functions when the state is set
- if (st->action.acp1)
- st->action.acp1(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;
- fixed_t ptryy;
- player_t* player;
- fixed_t xmove;
- fixed_t 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.
- // Does not handle sky floors.
- 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)
- {
- // do not 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;
- fixed_t 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
-
- // Note (id):
- // somebody left this after the setting momz to 0,
- // kinda useless there.
- //
- // cph - This was the a bug in the linuxdoom-1.10 source which
- // caused it not to sync Doom 2 v1.9 demos. Someone
- // added the above comment and moved up the following code. So
- // demos would desync in close lost soul fights.
- // Note that this only applies to original Doom 1 or Doom2 demos - not
- // Final Doom and Ultimate Doom. So we test demo_compatibility *and*
- // gamemission. (Note we assume that Doom1 is always Ult Doom, which
- // seems to hold for most published demos.)
- //
- // fraggle - cph got the logic here slightly wrong. There are three
- // versions of Doom 1.9:
- //
- // * The version used in registered doom 1.9 + doom2 - no bounce
- // * The version used in ultimate doom - has bounce
- // * The version used in final doom - has bounce
- //
- // So we need to check that this is either retail or commercial
- // (but not doom2)
-
- int correct_lost_soul_bounce = gameversion >= exe_ultimate;
-
- if (correct_lost_soul_bounce && mo->flags & MF_SKULLFLY)
- {
- // the skull slammed into something
- mo->momz = -mo->momz;
- }
-
- if (mo->momz < 0)
- {
- if (mo->player
- && mo->momz < -GRAVITY*8)
- {
- // Squat down.
- // Decrease viewheight for a moment
- // after hitting the ground (hard),
- // and utter appropriate sound.
- mo->player->deltaviewheight = mo->momz>>3;
- S_StartSound (mo, sfx_oof);
- }
- mo->momz = 0;
- }
- mo->z = mo->floorz;
-
-
- // cph 2001/05/26 -
- // See lost soul bouncing comment above. We need this here for bug
- // compatibility with original Doom2 v1.9 - if a soul is charging and
- // hit by a raising floor this incorrectly reverses its Y momentum.
- //
-
- if (!correct_lost_soul_bounce && mo->flags & MF_SKULLFLY)
- 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;
- fixed_t y;
- fixed_t z;
- subsector_t* ss;
- mobj_t* mo;
- mapthing_t* mthing;
-
- x = mobj->spawnpoint.x << FRACBITS;
- y = mobj->spawnpoint.y << FRACBITS;
-
- // somthing is occupying it's position?
- if (!P_CheckPosition (mobj, x, y) )
- return; // no respwan
-
- // spawn a teleport fog at old spot
- // because of removal of the body?
- mo = P_SpawnMobj (mobj->x,
- mobj->y,
- mobj->subsector->sector->floorheight , MT_TFOG);
- // initiate teleport sound
- 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;
-
- // inherit attributes from deceased one
- 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);
-
- // FIXME: decent NOP/NULL/Nil function pointer please.
- if (mobj->thinker.function.acv == (actionf_v) (-1))
- return; // mobj was removed
- }
- if ( (mobj->z != mobj->floorz)
- || mobj->momz )
- {
- P_ZMovement (mobj);
-
- // FIXME: decent NOP/NULL/Nil function pointer please.
- if (mobj->thinker.function.acv == (actionf_v) (-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*TICRATE)
- 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 not 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.acp1 = (actionf_p1)P_MobjThinker;
-
- P_AddThinker (&mobj->thinker);
-
- return mobj;
-}
-
-
-//
-// P_RemoveMobj
-//
-mapthing_t itemrespawnque[ITEMQUESIZE];
-int itemrespawntime[ITEMQUESIZE];
-int iquehead;
-int 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);
-
- // lose one off the end?
- if (iquehead == iquetail)
- 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;
- fixed_t y;
- fixed_t z;
-
- subsector_t* ss;
- mobj_t* mo;
- mapthing_t* mthing;
-
- int i;
-
- // only respawn items in deathmatch
- if (deathmatch != 2)
- return; //
-
- // nothing left to respawn?
- if (iquehead == iquetail)
- return;
-
- // wait at least 30 seconds
- if (leveltime - itemrespawntime[iquetail] < 30*TICRATE)
- return;
-
- 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;
- fixed_t y;
- fixed_t z;
-
- mobj_t* mobj;
-
- int i;
-
- if (mthing->type == 0)
- {
- return;
- }
-
- // not playing?
- if (!playeringame[mthing->type-1])
- return;
-
- 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);
-
- // set color translations for player sprites
- if (mthing->type > 1)
- mobj->flags |= (mthing->type-1)<<MF_TRANSSHIFT;
-
- mobj->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;
-
- // setup gun psprite
- P_SetupPsprites (p);
-
- // give all cards in death match mode
- if (deathmatch)
- for (i=0 ; i<NUMCARDS ; i++)
- p->cards[i] = true;
-
- if (mthing->type-1 == consoleplayer)
- {
- // wake up the status bar
- ST_Start ();
- // wake up the heads up text
- HU_Start ();
- }
-}
-
-
-//
-// P_SpawnMapThing
-// The fields of the mapthing should
-// already be in host byte order.
-//
-void P_SpawnMapThing (mapthing_t* mthing)
-{
- int i;
- int bit;
- mobj_t* mobj;
- fixed_t x;
- fixed_t y;
- fixed_t z;
-
- // count deathmatch start positions
- if (mthing->type == 11)
- {
- if (deathmatch_p < &deathmatchstarts[10])
- {
- memcpy (deathmatch_p, mthing, sizeof(*mthing));
- deathmatch_p++;
- }
- return;
- }
-
- if (mthing->type <= 0)
- {
- // Thing type 0 is actually "player -1 start".
- // For some reason, Vanilla Doom accepts/ignores this.
-
- 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;
-
- // move a little forward so an angle can
- // be computed if it immediately explodes
- th->x += (th->momx>>1);
- th->y += (th->momy>>1);
- th->z += (th->momz>>1);
-
- if (!P_TryMove (th, th->x, th->y))
- P_ExplodeMissile (th);
-}
-
-// Certain functions assume that a mobj_t pointer is non-NULL,
-// causing a crash in some situations where it is NULL. Vanilla
-// Doom did not crash because of the lack of proper memory
-// protection. This function substitutes NULL pointers for
-// pointers to a dummy mobj, to avoid a crash.
-
-mobj_t *P_SubstNullMobj(mobj_t *mobj)
-{
- if (mobj == NULL)
- {
- static mobj_t dummy_mobj;
-
- dummy_mobj.x = 0;
- dummy_mobj.y = 0;
- dummy_mobj.z = 0;
- dummy_mobj.flags = 0;
-
- mobj = &dummy_mobj;
- }
-
- return mobj;
-}
-
-//
-// 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);
-
- // fuzzy player
- if (dest->flags & MF_SHADOW)
- an += (P_Random()-P_Random())<<20;
-
- 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;
- fixed_t y;
- fixed_t z;
- fixed_t 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);
-}
-
--- a/src/p_mobj.h
+++ /dev/null
@@ -1,292 +1,0 @@
-// Emacs style mode select -*- C++ -*-
-//-----------------------------------------------------------------------------
-//
-// Copyright(C) 1993-1996 Id Software, Inc.
-// Copyright(C) 2005 Simon Howard
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-// 02111-1307, USA.
-//
-// DESCRIPTION:
-// Map Objects, MObj, definition and handling.
-//
-//-----------------------------------------------------------------------------
-
-
-#ifndef __P_MOBJ__
-#define __P_MOBJ__
-
-// Basics.
-#include "tables.h"
-#include "m_fixed.h"
-
-// We need the thinker_t stuff.
-#include "d_think.h"
-
-// We need the WAD data structure for Map things,
-// from the THINGS lump.
-#include "doomdata.h"
-
-// States are tied to finite states are
-// tied to animation frames.
-// Needs precompiled tables/data structures.
-#include "info.h"
-
-
-
-
-
-
-//
-// NOTES: mobj_t
-//
-// 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 its 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 by 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 its origin contained.
-//
-// A valid mobj_t is a mobj_t that has the proper subsector_t
-// filled in for its xy coordinates and is linked into the
-// sector from which the subsector was made, 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.
-//
-// Any questions?
-//
-
-//
-// Misc. mobj flags
-//
-typedef enum
-{
- // Call P_SpecialThing when touched.
- MF_SPECIAL = 1,
- // Blocks.
- MF_SOLID = 2,
- // Can be hit.
- MF_SHOOTABLE = 4,
- // Don't use the sector links (invisible but touchable).
- MF_NOSECTOR = 8,
- // Don't use the blocklinks (inert but displayable)
- MF_NOBLOCKMAP = 16,
-
- // Not to be activated by sound, deaf monster.
- MF_AMBUSH = 32,
- // Will try to attack right back.
- MF_JUSTHIT = 64,
- // Will take at least one step before attacking.
- MF_JUSTATTACKED = 128,
- // On level spawning (initial position),
- // hang from ceiling instead of stand on floor.
- MF_SPAWNCEILING = 256,
- // Don't apply gravity (every tic),
- // that is, object will float, keeping current height
- // or changing it actively.
- MF_NOGRAVITY = 512,
-
- // Movement flags.
- // This allows jumps from high places.
- MF_DROPOFF = 0x400,
- // For players, will pick up items.
- MF_PICKUP = 0x800,
- // Player cheat. ???
- MF_NOCLIP = 0x1000,
- // Player: keep info about sliding along walls.
- MF_SLIDE = 0x2000,
- // Allow moves to any height, no gravity.
- // For active floaters, e.g. cacodemons, pain elementals.
- MF_FLOAT = 0x4000,
- // Don't cross lines
- // ??? or look at heights on teleport.
- MF_TELEPORT = 0x8000,
- // Don't hit same species, explode on block.
- // Player missiles as well as fireballs of various kinds.
- MF_MISSILE = 0x10000,
- // Dropped by a demon, not level spawned.
- // E.g. ammo clips dropped by dying former humans.
- MF_DROPPED = 0x20000,
- // Use fuzzy draw (shadow demons or spectres),
- // temporary player invisibility powerup.
- MF_SHADOW = 0x40000,
- // Flag: don't bleed when shot (use puff),
- // barrels and shootable furniture shall not bleed.
- MF_NOBLOOD = 0x80000,
- // Don't stop moving halfway off a step,
- // that is, have dead bodies slide down all the way.
- MF_CORPSE = 0x100000,
- // Floating to a height for a move, ???
- // don't auto float to target's height.
- MF_INFLOAT = 0x200000,
-
- // On kill, count this enemy object
- // towards intermission kill total.
- // Happy gathering.
- MF_COUNTKILL = 0x400000,
-
- // On picking up, count this item object
- // towards intermission item total.
- MF_COUNTITEM = 0x800000,
-
- // Special handling: skull in flight.
- // Neither a cacodemon nor a missile.
- MF_SKULLFLY = 0x1000000,
-
- // Don't spawn this object
- // in death match mode (e.g. key cards).
- MF_NOTDMATCH = 0x2000000,
-
- // Player sprites in multiplayer modes are modified
- // using an internal color lookup table for re-indexing.
- // If 0x4 0x8 or 0xc,
- // use a translation table for player colormaps
- MF_TRANSLATION = 0xc000000,
- // Hmm ???.
- MF_TRANSSHIFT = 26
-
-} mobjflag_t;
-
-
-// Map Object definition.
-typedef struct mobj_s
-{
- // List: thinker links.
- thinker_t thinker;
-
- // Info for drawing: position.
- fixed_t x;
- fixed_t y;
- fixed_t z;
-
- // More list: links in sector (if needed)
- struct mobj_s* snext;
- struct mobj_s* sprev;
-
- //More drawing info: to determine current sprite.
- angle_t angle; // orientation
- spritenum_t sprite; // used to find patch_t and flip value
- int frame; // might be ORed with FF_FULLBRIGHT
-
- // Interaction info, by BLOCKMAP.
- // Links in blocks (if needed).
- struct mobj_s* bnext;
- struct mobj_s* bprev;
-
- struct subsector_s* subsector;
-
- // The closest interval over all contacted Sectors.
- fixed_t floorz;
- fixed_t ceilingz;
-
- // For movement checking.
- fixed_t radius;
- fixed_t height;
-
- // Momentums, used to update position.
- fixed_t momx;
- fixed_t momy;
- fixed_t momz;
-
- // If == validcount, already checked.
- int validcount;
-
- mobjtype_t type;
- mobjinfo_t* info; // &mobjinfo[mobj->type]
-
- int tics; // state tic counter
- state_t* state;
- int flags;
- int health;
-
- // Movement direction, movement generation (zig-zagging).
- int movedir; // 0-7
- int movecount; // when 0, select a new dir
-
- // Thing being chased/attacked (or NULL),
- // also the originator for missiles.
- struct mobj_s* target;
-
- // Reaction time: if non 0, don't attack yet.
- // Used by player to freeze a bit after teleporting.
- int reactiontime;
-
- // If >0, the target will be chased
- // no matter what (even if shot)
- int threshold;
-
- // Additional info record for player avatars only.
- // Only valid if type == MT_PLAYER
- struct player_s* player;
-
- // Player number last looked for.
- int lastlook;
-
- // For nightmare respawn.
- mapthing_t spawnpoint;
-
- // Thing being chased/attacked for tracers.
- struct mobj_s* tracer;
-
-} mobj_t;
-
-
-
-#endif
--- a/src/p_plats.c
+++ /dev/null
@@ -1,312 +1,0 @@
-// Emacs style mode select -*- C++ -*-
-//-----------------------------------------------------------------------------
-//
-// Copyright(C) 1993-1996 Id Software, Inc.
-// Copyright(C) 2005 Simon Howard
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-// 02111-1307, USA.
-//
-// DESCRIPTION:
-// Plats (i.e. elevator platforms) code, raising/lowering.
-//
-//-----------------------------------------------------------------------------
-
-
-
-#include "i_system.h"
-#include "z_zone.h"
-#include "m_random.h"
-
-#include "doomdef.h"
-#include "p_local.h"
-
-#include "s_sound.h"
-
-// State.
-#include "doomstat.h"
-#include "r_state.h"
-
-// Data.
-#include "sounds.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(&plat->sector->soundorg, sfx_stnmov);
- }
-
-
- if (res == crushed && (!plat->crush))
- {
- plat->count = plat->wait;
- plat->status = down;
- S_StartSound(&plat->sector->soundorg, sfx_pstart);
- }
- else
- {
- if (res == pastdest)
- {
- plat->count = plat->wait;
- plat->status = waiting;
- S_StartSound(&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(&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(&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 <type> 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.acp1 = (actionf_p1) 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;
- // NO MORE DAMAGE, IF APPLICABLE
- sec->special = 0;
-
- S_StartSound(&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(&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 = TICRATE*PLATWAIT;
- plat->status = down;
- S_StartSound(&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 = TICRATE*PLATWAIT;
- plat->status = down;
- S_StartSound(&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 = TICRATE*PLATWAIT;
- plat->status = P_Random()&1;
-
- S_StartSound(&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.acp1
- = (actionf_p1) 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.acv = (actionf_v)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!");
-}
--- a/src/p_pspr.c
+++ /dev/null
@@ -1,896 +1,0 @@
-// Emacs style mode select -*- C++ -*-
-//-----------------------------------------------------------------------------
-//
-// Copyright(C) 1993-1996 Id Software, Inc.
-// Copyright(C) 2005 Simon Howard
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-// 02111-1307, USA.
-//
-// DESCRIPTION:
-// Weapon sprite animation, weapon objects.
-// Action functions for weapons.
-//
-//-----------------------------------------------------------------------------
-
-
-#include "doomdef.h"
-#include "d_event.h"
-
-#include "deh_misc.h"
-
-#include "m_random.h"
-#include "p_local.h"
-#include "s_sound.h"
-
-// State.
-#include "doomstat.h"
-
-// Data.
-#include "sounds.h"
-
-#include "p_pspr.h"
-
-#define LOWERSPEED FRACUNIT*6
-#define RAISESPEED FRACUNIT*6
-
-#define WEAPONBOTTOM 128*FRACUNIT
-#define WEAPONTOP 32*FRACUNIT
-
-
-
-//
-// 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)
- {
- // object removed itself
- psp->state = NULL;
- break;
- }
-
- 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.
- // Modified handling.
- if (state->action.acp2)
- {
- state->action.acp2(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;
-fixed_t swingy;
-
-void P_CalcSwing (player_t* player)
-{
- fixed_t swing;
- int angle;
-
- // OPTIMIZE: tablify this.
- // A LUT would allow for different modes,
- // and add flexibility.
-
- 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]);
-}
-
-
-
-//
-// 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;
-
- // Minimal amount for one shot varies.
- if (player->readyweapon == wp_bfg)
- count = deh_bfg_cells_per_shot;
- else if (player->readyweapon == wp_supershotgun)
- count = 2; // Double barrel.
- else
- count = 1; // Regular.
-
- // Some do not need ammunition anyway.
- // Return if current ammunition sufficient.
- if (ammo == am_noammo || player->ammo[ammo] >= count)
- return true;
-
- // Out of ammo, pick a weapon to change to.
- // Preferences are set here.
- do
- {
- if (player->weaponowned[wp_plasma]
- && player->ammo[am_cell]
- && (gamemode != shareware) )
- {
- player->pendingweapon = wp_plasma;
- }
- else if (player->weaponowned[wp_supershotgun]
- && player->ammo[am_shell]>2
- && (gamemode == 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
- && (gamemode != shareware) )
- {
- player->pendingweapon = wp_bfg;
- }
- else
- {
- // If everything fails.
- player->pendingweapon = wp_fist;
- }
-
- } while (player->pendingweapon == wp_nochange);
-
- // Now set appropriate weapon overlay.
- 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.
-// Follows after getting weapon up,
-// or after previous attack/fire sequence.
-//
-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
-// Lowers current weapon,
-// and changes weapon at bottom.
-//
-void
-A_Lower
-( player_t* player,
- pspdef_t* psp )
-{
- psp->sy += LOWERSPEED;
-
- // Is already down.
- if (psp->sy < WEAPONBOTTOM )
- return;
-
- // Player is dead.
- if (player->playerstate == PST_DEAD)
- {
- psp->sy = WEAPONBOTTOM;
-
- // don't bring weapon back up
- return;
- }
-
- // 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 ((signed int) (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;
-}
-
-// Doom does not check the bounds of the ammo array. As a result,
-// it is possible to use an ammo type > 4 that overflows into the
-// maxammo array and affects that instead. Through dehacked, for
-// example, it is possible to make a weapon that decreases the max
-// number of ammo for another weapon. Emulate this.
-
-static void DecreaseAmmo(player_t *player, int ammonum, int amount)
-{
- if (ammonum < NUMAMMO)
- {
- player->ammo[ammonum] -= amount;
- }
- else
- {
- player->maxammo[ammonum - NUMAMMO] -= amount;
- }
-}
-
-
-//
-// A_FireMissile
-//
-void
-A_FireMissile
-( player_t* player,
- pspdef_t* psp )
-{
- DecreaseAmmo(player, weaponinfo[player->readyweapon].ammo, 1);
- P_SpawnPlayerMissile (player->mo, MT_ROCKET);
-}
-
-
-//
-// A_FireBFG
-//
-void
-A_FireBFG
-( player_t* player,
- pspdef_t* psp )
-{
- DecreaseAmmo(player, weaponinfo[player->readyweapon].ammo,
- deh_bfg_cells_per_shot);
- P_SpawnPlayerMissile (player->mo, MT_BFG);
-}
-
-
-
-//
-// A_FirePlasma
-//
-void
-A_FirePlasma
-( player_t* player,
- pspdef_t* psp )
-{
- DecreaseAmmo(player, weaponinfo[player->readyweapon].ammo, 1);
-
- 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);
- DecreaseAmmo(player, weaponinfo[player->readyweapon].ammo, 1);
-
- 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);
-
- DecreaseAmmo(player, weaponinfo[player->readyweapon].ammo, 1);
-
- 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);
-
- DecreaseAmmo(player, 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);
- DecreaseAmmo(player, weaponinfo[player->readyweapon].ammo, 1);
-
- 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;
- int j;
- int 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 ; i<NUMPSPRITES ; i++)
- player->psprites[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 ; i<NUMPSPRITES ; i++, psp++)
- {
- // a null state means not active
- if ( (state = psp->state) )
- {
- // drop tic count and possibly change state
-
- // a -1 tic count never changes
- if (psp->tics != -1)
- {
- 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;
-}
-
-
--- a/src/p_pspr.h
+++ /dev/null
@@ -1,79 +1,0 @@
-// Emacs style mode select -*- C++ -*-
-//-----------------------------------------------------------------------------
-//
-// Copyright(C) 1993-1996 Id Software, Inc.
-// Copyright(C) 2005 Simon Howard
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-// 02111-1307, USA.
-//
-// DESCRIPTION:
-// Sprite animation.
-//
-//-----------------------------------------------------------------------------
-
-
-#ifndef __P_PSPR__
-#define __P_PSPR__
-
-// Basic data types.
-// Needs fixed point, and BAM angles.
-#include "m_fixed.h"
-#include "tables.h"
-
-
-//
-// Needs to include the precompiled
-// sprite animation tables.
-// Header generated by multigen utility.
-// This includes all the data for thing animation,
-// i.e. the Thing Atrributes table
-// and the Frame Sequence table.
-#include "info.h"
-
-
-
-//
-// Frame flags:
-// handles maximum brightness (torches, muzzle flare, light sources)
-//
-#define FF_FULLBRIGHT 0x8000 // flag in thing->frame
-#define FF_FRAMEMASK 0x7fff
-
-
-
-//
-// Overlay psprites are scaled shapes
-// drawn 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;
- fixed_t sy;
-
-} pspdef_t;
-
-#endif
--- a/src/p_saveg.c
+++ /dev/null
@@ -1,1880 +1,0 @@
-// Emacs style mode select -*- C++ -*-
-//-----------------------------------------------------------------------------
-//
-// Copyright(C) 1993-1996 Id Software, Inc.
-// Copyright(C) 2005 Simon Howard
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-// 02111-1307, USA.
-//
-// DESCRIPTION:
-// Archiving: SaveGame I/O.
-//
-//-----------------------------------------------------------------------------
-
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "dstrings.h"
-#include "deh_main.h"
-#include "i_system.h"
-#include "z_zone.h"
-#include "p_local.h"
-#include "p_saveg.h"
-
-// State.
-#include "doomstat.h"
-#include "r_state.h"
-
-#define SAVEGAME_EOF 0x1d
-#define VERSIONSIZE 16
-
-FILE *save_stream;
-int savegamelength;
-
-// Get the filename of a temporary file to write the savegame to. After
-// the file has been successfully saved, it will be renamed to the
-// real file.
-
-char *P_TempSaveGameFile(void)
-{
- static char *filename = NULL;
-
- if (filename == NULL)
- {
- filename = malloc(strlen(savegamedir) + 32);
- }
-
- sprintf(filename, "%stemp.dsg", savegamedir);
-
- return filename;
-}
-
-// Get the filename of the save game file to use for the specified slot.
-
-char *P_SaveGameFile(int slot)
-{
- static char *filename = NULL;
- char basename[32];
-
- if (filename == NULL)
- {
- filename = malloc(strlen(savegamedir) + 32);
- }
-
- sprintf(basename, DEH_String(SAVEGAMENAME "%d.dsg"), slot);
-
- sprintf(filename, "%s%s", savegamedir, basename);
-
- return filename;
-}
-
-// Endian-safe integer read/write functions
-
-static byte saveg_read8(void)
-{
- byte result;
-
- fread(&result, 1, 1, save_stream);
-
- return result;
-}
-
-static void saveg_write8(byte value)
-{
- fwrite(&value, 1, 1, save_stream);
-}
-
-static short saveg_read16(void)
-{
- int result;
-
- result = saveg_read8();
- result |= saveg_read8() << 8;
-
- return result;
-}
-
-static void saveg_write16(short value)
-{
- saveg_write8(value & 0xff);
- saveg_write8((value >> 8) & 0xff);
-}
-
-static int saveg_read32(void)
-{
- int result;
-
- result = saveg_read8();
- result |= saveg_read8() << 8;
- result |= saveg_read8() << 16;
- result |= saveg_read8() << 24;
-
- return result;
-}
-
-static void saveg_write32(int value)
-{
- saveg_write8(value & 0xff);
- saveg_write8((value >> 8) & 0xff);
- saveg_write8((value >> 16) & 0xff);
- saveg_write8((value >> 24) & 0xff);
-}
-
-// Pad to 4-byte boundaries
-
-static void saveg_read_pad(void)
-{
- unsigned long pos;
- int padding;
- int i;
-
- pos = ftell(save_stream);
-
- padding = (4 - (pos & 3)) & 3;
-
- for (i=0; i<padding; ++i)
- {
- saveg_read8();
- }
-}
-
-static void saveg_write_pad(void)
-{
- unsigned long pos;
- int padding;
- int i;
-
- pos = ftell(save_stream);
-
- padding = (4 - (pos & 3)) & 3;
-
- for (i=0; i<padding; ++i)
- {
- saveg_write8(0);
- }
-}
-
-
-// Pointers
-
-static void *saveg_readp(void)
-{
- return (void *) saveg_read32();
-}
-
-static void saveg_writep(void *p)
-{
- saveg_write32((int) p);
-}
-
-// Enum values are 32-bit integers.
-
-#define saveg_read_enum saveg_read32
-#define saveg_write_enum saveg_write32
-
-//
-// Structure read/write functions
-//
-
-//
-// mapthing_t
-//
-
-static void saveg_read_mapthing_t(mapthing_t *str)
-{
- // short x;
- str->x = saveg_read16();
-
- // short y;
- str->y = saveg_read16();
-
- // short angle;
- str->angle = saveg_read16();
-
- // short type;
- str->type = saveg_read16();
-
- // short options;
- str->options = saveg_read16();
-}
-
-static void saveg_write_mapthing_t(mapthing_t *str)
-{
- // short x;
- saveg_write16(str->x);
-
- // short y;
- saveg_write16(str->y);
-
- // short angle;
- saveg_write16(str->angle);
-
- // short type;
- saveg_write16(str->type);
-
- // short options;
- saveg_write16(str->options);
-}
-
-//
-// actionf_t
-//
-
-static void saveg_read_actionf_t(actionf_t *str)
-{
- // actionf_p1 acp1;
- str->acp1 = saveg_readp();
-}
-
-static void saveg_write_actionf_t(actionf_t *str)
-{
- // actionf_p1 acp1;
- saveg_writep(str->acp1);
-}
-
-//
-// think_t
-//
-// This is just an actionf_t.
-//
-
-#define saveg_read_think_t saveg_read_actionf_t
-#define saveg_write_think_t saveg_write_actionf_t
-
-//
-// thinker_t
-//
-
-static void saveg_read_thinker_t(thinker_t *str)
-{
- // struct thinker_s* prev;
- str->prev = saveg_readp();
-
- // struct thinker_s* next;
- str->next = saveg_readp();
-
- // think_t function;
- saveg_read_think_t(&str->function);
-}
-
-static void saveg_write_thinker_t(thinker_t *str)
-{
- // struct thinker_s* prev;
- saveg_writep(str->prev);
-
- // struct thinker_s* next;
- saveg_writep(str->next);
-
- // think_t function;
- saveg_write_think_t(&str->function);
-}
-
-//
-// mobj_t
-//
-
-static void saveg_read_mobj_t(mobj_t *str)
-{
- int pl;
-
- // thinker_t thinker;
- saveg_read_thinker_t(&str->thinker);
-
- // fixed_t x;
- str->x = saveg_read32();
-
- // fixed_t y;
- str->y = saveg_read32();
-
- // fixed_t z;
- str->z = saveg_read32();
-
- // struct mobj_s* snext;
- str->snext = saveg_readp();
-
- // struct mobj_s* sprev;
- str->sprev = saveg_readp();
-
- // angle_t angle;
- str->angle = saveg_read32();
-
- // spritenum_t sprite;
- str->sprite = saveg_read_enum();
-
- // int frame;
- str->frame = saveg_read32();
-
- // struct mobj_s* bnext;
- str->bnext = saveg_readp();
-
- // struct mobj_s* bprev;
- str->bprev = saveg_readp();
-
- // struct subsector_s* subsector;
- str->subsector = saveg_readp();
-
- // fixed_t floorz;
- str->floorz = saveg_read32();
-
- // fixed_t ceilingz;
- str->ceilingz = saveg_read32();
-
- // fixed_t radius;
- str->radius = saveg_read32();
-
- // fixed_t height;
- str->height = saveg_read32();
-
- // fixed_t momx;
- str->momx = saveg_read32();
-
- // fixed_t momy;
- str->momy = saveg_read32();
-
- // fixed_t momz;
- str->momz = saveg_read32();
-
- // int validcount;
- str->validcount = saveg_read32();
-
- // mobjtype_t type;
- str->type = saveg_read_enum();
-
- // mobjinfo_t* info;
- str->info = saveg_readp();
-
- // int tics;
- str->tics = saveg_read32();
-
- // state_t* state;
- str->state = &states[saveg_read32()];
-
- // int flags;
- str->flags = saveg_read32();
-
- // int health;
- str->health = saveg_read32();
-
- // int movedir;
- str->movedir = saveg_read32();
-
- // int movecount;
- str->movecount = saveg_read32();
-
- // struct mobj_s* target;
- str->target = saveg_readp();
-
- // int reactiontime;
- str->reactiontime = saveg_read32();
-
- // int threshold;
- str->threshold = saveg_read32();
-
- // struct player_s* player;
- pl = saveg_read32();
-
- if (pl > 0)
- {
- str->player = &players[pl - 1];
- str->player->mo = str;
- }
- else
- {
- str->player = NULL;
- }
-
- // int lastlook;
- str->lastlook = saveg_read32();
-
- // mapthing_t spawnpoint;
- saveg_read_mapthing_t(&str->spawnpoint);
-
- // struct mobj_s* tracer;
- str->tracer = saveg_readp();
-}
-
-static void saveg_write_mobj_t(mobj_t *str)
-{
- // thinker_t thinker;
- saveg_write_thinker_t(&str->thinker);
-
- // fixed_t x;
- saveg_write32(str->x);
-
- // fixed_t y;
- saveg_write32(str->y);
-
- // fixed_t z;
- saveg_write32(str->z);
-
- // struct mobj_s* snext;
- saveg_writep(str->snext);
-
- // struct mobj_s* sprev;
- saveg_writep(str->sprev);
-
- // angle_t angle;
- saveg_write32(str->angle);
-
- // spritenum_t sprite;
- saveg_write_enum(str->sprite);
-
- // int frame;
- saveg_write32(str->frame);
-
- // struct mobj_s* bnext;
- saveg_writep(str->bnext);
-
- // struct mobj_s* bprev;
- saveg_writep(str->bprev);
-
- // struct subsector_s* subsector;
- saveg_writep(str->subsector);
-
- // fixed_t floorz;
- saveg_write32(str->floorz);
-
- // fixed_t ceilingz;
- saveg_write32(str->ceilingz);
-
- // fixed_t radius;
- saveg_write32(str->radius);
-
- // fixed_t height;
- saveg_write32(str->height);
-
- // fixed_t momx;
- saveg_write32(str->momx);
-
- // fixed_t momy;
- saveg_write32(str->momy);
-
- // fixed_t momz;
- saveg_write32(str->momz);
-
- // int validcount;
- saveg_write32(str->validcount);
-
- // mobjtype_t type;
- saveg_write_enum(str->type);
-
- // mobjinfo_t* info;
- saveg_writep(str->info);
-
- // int tics;
- saveg_write32(str->tics);
-
- // state_t* state;
- saveg_write32(str->state - states);
-
- // int flags;
- saveg_write32(str->flags);
-
- // int health;
- saveg_write32(str->health);
-
- // int movedir;
- saveg_write32(str->movedir);
-
- // int movecount;
- saveg_write32(str->movecount);
-
- // struct mobj_s* target;
- saveg_writep(str->target);
-
- // int reactiontime;
- saveg_write32(str->reactiontime);
-
- // int threshold;
- saveg_write32(str->threshold);
-
- // struct player_s* player;
- if (str->player)
- {
- saveg_write32(str->player - players + 1);
- }
- else
- {
- saveg_write32(0);
- }
-
- // int lastlook;
- saveg_write32(str->lastlook);
-
- // mapthing_t spawnpoint;
- saveg_write_mapthing_t(&str->spawnpoint);
-
- // struct mobj_s* tracer;
- saveg_writep(str->tracer);
-}
-
-
-//
-// ticcmd_t
-//
-
-static void saveg_read_ticcmd_t(ticcmd_t *str)
-{
-
- // signed char forwardmove;
- str->forwardmove = saveg_read8();
-
- // signed char sidemove;
- str->sidemove = saveg_read8();
-
- // short angleturn;
- str->angleturn = saveg_read16();
-
- // short consistancy;
- str->consistancy = saveg_read16();
-
- // byte chatchar;
- str->chatchar = saveg_read8();
-
- // byte buttons;
- str->buttons = saveg_read8();
-}
-
-static void saveg_write_ticcmd_t(ticcmd_t *str)
-{
-
- // signed char forwardmove;
- saveg_write8(str->forwardmove);
-
- // signed char sidemove;
- saveg_write8(str->sidemove);
-
- // short angleturn;
- saveg_write16(str->angleturn);
-
- // short consistancy;
- saveg_write16(str->consistancy);
-
- // byte chatchar;
- saveg_write8(str->chatchar);
-
- // byte buttons;
- saveg_write8(str->buttons);
-}
-
-//
-// pspdef_t
-//
-
-static void saveg_read_pspdef_t(pspdef_t *str)
-{
- int state;
-
- // state_t* state;
- state = saveg_read32();
-
- if (state > 0)
- {
- str->state = &states[state];
- }
- else
- {
- str->state = NULL;
- }
-
- // int tics;
- str->tics = saveg_read32();
-
- // fixed_t sx;
- str->sx = saveg_read32();
-
- // fixed_t sy;
- str->sy = saveg_read32();
-}
-
-static void saveg_write_pspdef_t(pspdef_t *str)
-{
- // state_t* state;
- if (str->state)
- {
- saveg_write32(str->state - states);
- }
- else
- {
- saveg_write32(0);
- }
-
- // int tics;
- saveg_write32(str->tics);
-
- // fixed_t sx;
- saveg_write32(str->sx);
-
- // fixed_t sy;
- saveg_write32(str->sy);
-}
-
-//
-// player_t
-//
-
-static void saveg_read_player_t(player_t *str)
-{
- int i;
-
- // mobj_t* mo;
- str->mo = saveg_readp();
-
- // playerstate_t playerstate;
- str->playerstate = saveg_read_enum();
-
- // ticcmd_t cmd;
- saveg_read_ticcmd_t(&str->cmd);
-
- // fixed_t viewz;
- str->viewz = saveg_read32();
-
- // fixed_t viewheight;
- str->viewheight = saveg_read32();
-
- // fixed_t deltaviewheight;
- str->deltaviewheight = saveg_read32();
-
- // fixed_t bob;
- str->bob = saveg_read32();
-
- // int health;
- str->health = saveg_read32();
-
- // int armorpoints;
- str->armorpoints = saveg_read32();
-
- // int armortype;
- str->armortype = saveg_read32();
-
- // int powers[NUMPOWERS];
- for (i=0; i<NUMPOWERS; ++i)
- {
- str->powers[i] = saveg_read32();
- }
-
- // boolean cards[NUMCARDS];
- for (i=0; i<NUMCARDS; ++i)
- {
- str->cards[i] = saveg_read32();
- }
-
- // boolean backpack;
- str->backpack = saveg_read32();
-
- // int frags[MAXPLAYERS];
- for (i=0; i<MAXPLAYERS; ++i)
- {
- str->frags[i] = saveg_read32();
- }
-
- // weapontype_t readyweapon;
- str->readyweapon = saveg_read_enum();
-
- // weapontype_t pendingweapon;
- str->pendingweapon = saveg_read_enum();
-
- // boolean weaponowned[NUMWEAPONS];
- for (i=0; i<NUMWEAPONS; ++i)
- {
- str->weaponowned[i] = saveg_read32();
- }
-
- // int ammo[NUMAMMO];
- for (i=0; i<NUMAMMO; ++i)
- {
- str->ammo[i] = saveg_read32();
- }
-
- // int maxammo[NUMAMMO];
- for (i=0; i<NUMAMMO; ++i)
- {
- str->maxammo[i] = saveg_read32();
- }
-
- // int attackdown;
- str->attackdown = saveg_read32();
-
- // int usedown;
- str->usedown = saveg_read32();
-
- // int cheats;
- str->cheats = saveg_read32();
-
- // int refire;
- str->refire = saveg_read32();
-
- // int killcount;
- str->killcount = saveg_read32();
-
- // int itemcount;
- str->itemcount = saveg_read32();
-
- // int secretcount;
- str->secretcount = saveg_read32();
-
- // char* message;
- str->message = saveg_readp();
-
- // int damagecount;
- str->damagecount = saveg_read32();
-
- // int bonuscount;
- str->bonuscount = saveg_read32();
-
- // mobj_t* attacker;
- str->attacker = saveg_readp();
-
- // int extralight;
- str->extralight = saveg_read32();
-
- // int fixedcolormap;
- str->fixedcolormap = saveg_read32();
-
- // int colormap;
- str->colormap = saveg_read32();
-
- // pspdef_t psprites[NUMPSPRITES];
- for (i=0; i<NUMPSPRITES; ++i)
- {
- saveg_read_pspdef_t(&str->psprites[i]);
- }
-
- // boolean didsecret;
- str->didsecret = saveg_read32();
-}
-
-static void saveg_write_player_t(player_t *str)
-{
- int i;
-
- // mobj_t* mo;
- saveg_writep(str->mo);
-
- // playerstate_t playerstate;
- saveg_write_enum(str->playerstate);
-
- // ticcmd_t cmd;
- saveg_write_ticcmd_t(&str->cmd);
-
- // fixed_t viewz;
- saveg_write32(str->viewz);
-
- // fixed_t viewheight;
- saveg_write32(str->viewheight);
-
- // fixed_t deltaviewheight;
- saveg_write32(str->deltaviewheight);
-
- // fixed_t bob;
- saveg_write32(str->bob);
-
- // int health;
- saveg_write32(str->health);
-
- // int armorpoints;
- saveg_write32(str->armorpoints);
-
- // int armortype;
- saveg_write32(str->armortype);
-
- // int powers[NUMPOWERS];
- for (i=0; i<NUMPOWERS; ++i)
- {
- saveg_write32(str->powers[i]);
- }
-
- // boolean cards[NUMCARDS];
- for (i=0; i<NUMCARDS; ++i)
- {
- saveg_write32(str->cards[i]);
- }
-
- // boolean backpack;
- saveg_write32(str->backpack);
-
- // int frags[MAXPLAYERS];
- for (i=0; i<MAXPLAYERS; ++i)
- {
- saveg_write32(str->frags[i]);
- }
-
- // weapontype_t readyweapon;
- saveg_write_enum(str->readyweapon);
-
- // weapontype_t pendingweapon;
- saveg_write_enum(str->pendingweapon);
-
- // boolean weaponowned[NUMWEAPONS];
- for (i=0; i<NUMWEAPONS; ++i)
- {
- saveg_write32(str->weaponowned[i]);
- }
-
- // int ammo[NUMAMMO];
- for (i=0; i<NUMAMMO; ++i)
- {
- saveg_write32(str->ammo[i]);
- }
-
- // int maxammo[NUMAMMO];
- for (i=0; i<NUMAMMO; ++i)
- {
- saveg_write32(str->maxammo[i]);
- }
-
- // int attackdown;
- saveg_write32(str->attackdown);
-
- // int usedown;
- saveg_write32(str->usedown);
-
- // int cheats;
- saveg_write32(str->cheats);
-
- // int refire;
- saveg_write32(str->refire);
-
- // int killcount;
- saveg_write32(str->killcount);
-
- // int itemcount;
- saveg_write32(str->itemcount);
-
- // int secretcount;
- saveg_write32(str->secretcount);
-
- // char* message;
- saveg_writep(str->message);
-
- // int damagecount;
- saveg_write32(str->damagecount);
-
- // int bonuscount;
- saveg_write32(str->bonuscount);
-
- // mobj_t* attacker;
- saveg_writep(str->attacker);
-
- // int extralight;
- saveg_write32(str->extralight);
-
- // int fixedcolormap;
- saveg_write32(str->fixedcolormap);
-
- // int colormap;
- saveg_write32(str->colormap);
-
- // pspdef_t psprites[NUMPSPRITES];
- for (i=0; i<NUMPSPRITES; ++i)
- {
- saveg_write_pspdef_t(&str->psprites[i]);
- }
-
- // boolean didsecret;
- saveg_write32(str->didsecret);
-}
-
-
-//
-// ceiling_t
-//
-
-static void saveg_read_ceiling_t(ceiling_t *str)
-{
- int sector;
-
- // thinker_t thinker;
- saveg_read_thinker_t(&str->thinker);
-
- // ceiling_e type;
- str->type = saveg_read_enum();
-
- // sector_t* sector;
- sector = saveg_read32();
- str->sector = §ors[sector];
-
- // fixed_t bottomheight;
- str->bottomheight = saveg_read32();
-
- // fixed_t topheight;
- str->topheight = saveg_read32();
-
- // fixed_t speed;
- str->speed = saveg_read32();
-
- // boolean crush;
- str->crush = saveg_read32();
-
- // int direction;
- str->direction = saveg_read32();
-
- // int tag;
- str->tag = saveg_read32();
-
- // int olddirection;
- str->olddirection = saveg_read32();
-}
-
-static void saveg_write_ceiling_t(ceiling_t *str)
-{
- // thinker_t thinker;
- saveg_write_thinker_t(&str->thinker);
-
- // ceiling_e type;
- saveg_write_enum(str->type);
-
- // sector_t* sector;
- saveg_write32(str->sector - sectors);
-
- // fixed_t bottomheight;
- saveg_write32(str->bottomheight);
-
- // fixed_t topheight;
- saveg_write32(str->topheight);
-
- // fixed_t speed;
- saveg_write32(str->speed);
-
- // boolean crush;
- saveg_write32(str->crush);
-
- // int direction;
- saveg_write32(str->direction);
-
- // int tag;
- saveg_write32(str->tag);
-
- // int olddirection;
- saveg_write32(str->olddirection);
-}
-
-//
-// vldoor_t
-//
-
-static void saveg_read_vldoor_t(vldoor_t *str)
-{
- int sector;
-
- // thinker_t thinker;
- saveg_read_thinker_t(&str->thinker);
-
- // vldoor_e type;
- str->type = saveg_read_enum();
-
- // sector_t* sector;
- sector = saveg_read32();
- str->sector = §ors[sector];
-
- // fixed_t topheight;
- str->topheight = saveg_read32();
-
- // fixed_t speed;
- str->speed = saveg_read32();
-
- // int direction;
- str->direction = saveg_read32();
-
- // int topwait;
- str->topwait = saveg_read32();
-
- // int topcountdown;
- str->topcountdown = saveg_read32();
-}
-
-static void saveg_write_vldoor_t(vldoor_t *str)
-{
- // thinker_t thinker;
- saveg_write_thinker_t(&str->thinker);
-
- // vldoor_e type;
- saveg_write_enum(str->type);
-
- // sector_t* sector;
- saveg_write32(str->sector - sectors);
-
- // fixed_t topheight;
- saveg_write32(str->topheight);
-
- // fixed_t speed;
- saveg_write32(str->speed);
-
- // int direction;
- saveg_write32(str->direction);
-
- // int topwait;
- saveg_write32(str->topwait);
-
- // int topcountdown;
- saveg_write32(str->topcountdown);
-}
-
-//
-// floormove_t
-//
-
-static void saveg_read_floormove_t(floormove_t *str)
-{
- int sector;
-
- // thinker_t thinker;
- saveg_read_thinker_t(&str->thinker);
-
- // floor_e type;
- str->type = saveg_read_enum();
-
- // boolean crush;
- str->crush = saveg_read32();
-
- // sector_t* sector;
- sector = saveg_read32();
- str->sector = §ors[sector];
-
- // int direction;
- str->direction = saveg_read32();
-
- // int newspecial;
- str->newspecial = saveg_read32();
-
- // short texture;
- str->texture = saveg_read16();
-
- // fixed_t floordestheight;
- str->floordestheight = saveg_read32();
-
- // fixed_t speed;
- str->speed = saveg_read32();
-}
-
-static void saveg_write_floormove_t(floormove_t *str)
-{
- // thinker_t thinker;
- saveg_write_thinker_t(&str->thinker);
-
- // floor_e type;
- saveg_write_enum(str->type);
-
- // boolean crush;
- saveg_write32(str->crush);
-
- // sector_t* sector;
- saveg_write32(str->sector - sectors);
-
- // int direction;
- saveg_write32(str->direction);
-
- // int newspecial;
- saveg_write32(str->newspecial);
-
- // short texture;
- saveg_write16(str->texture);
-
- // fixed_t floordestheight;
- saveg_write32(str->floordestheight);
-
- // fixed_t speed;
- saveg_write32(str->speed);
-}
-
-//
-// plat_t
-//
-
-static void saveg_read_plat_t(plat_t *str)
-{
- int sector;
-
- // thinker_t thinker;
- saveg_read_thinker_t(&str->thinker);
-
- // sector_t* sector;
- sector = saveg_read32();
- str->sector = §ors[sector];
-
- // fixed_t speed;
- str->speed = saveg_read32();
-
- // fixed_t low;
- str->low = saveg_read32();
-
- // fixed_t high;
- str->high = saveg_read32();
-
- // int wait;
- str->wait = saveg_read32();
-
- // int count;
- str->count = saveg_read32();
-
- // plat_e status;
- str->status = saveg_read_enum();
-
- // plat_e oldstatus;
- str->oldstatus = saveg_read_enum();
-
- // boolean crush;
- str->crush = saveg_read32();
-
- // int tag;
- str->tag = saveg_read32();
-
- // plattype_e type;
- str->type = saveg_read_enum();
-}
-
-static void saveg_write_plat_t(plat_t *str)
-{
- // thinker_t thinker;
- saveg_write_thinker_t(&str->thinker);
-
- // sector_t* sector;
- saveg_write32(str->sector - sectors);
-
- // fixed_t speed;
- saveg_write32(str->speed);
-
- // fixed_t low;
- saveg_write32(str->low);
-
- // fixed_t high;
- saveg_write32(str->high);
-
- // int wait;
- saveg_write32(str->wait);
-
- // int count;
- saveg_write32(str->count);
-
- // plat_e status;
- saveg_write_enum(str->status);
-
- // plat_e oldstatus;
- saveg_write_enum(str->oldstatus);
-
- // boolean crush;
- saveg_write32(str->crush);
-
- // int tag;
- saveg_write32(str->tag);
-
- // plattype_e type;
- saveg_write_enum(str->type);
-}
-
-//
-// lightflash_t
-//
-
-static void saveg_read_lightflash_t(lightflash_t *str)
-{
- int sector;
-
- // thinker_t thinker;
- saveg_read_thinker_t(&str->thinker);
-
- // sector_t* sector;
- sector = saveg_read32();
- str->sector = §ors[sector];
-
- // int count;
- str->count = saveg_read32();
-
- // int maxlight;
- str->maxlight = saveg_read32();
-
- // int minlight;
- str->minlight = saveg_read32();
-
- // int maxtime;
- str->maxtime = saveg_read32();
-
- // int mintime;
- str->mintime = saveg_read32();
-}
-
-static void saveg_write_lightflash_t(lightflash_t *str)
-{
- // thinker_t thinker;
- saveg_write_thinker_t(&str->thinker);
-
- // sector_t* sector;
- saveg_write32(str->sector - sectors);
-
- // int count;
- saveg_write32(str->count);
-
- // int maxlight;
- saveg_write32(str->maxlight);
-
- // int minlight;
- saveg_write32(str->minlight);
-
- // int maxtime;
- saveg_write32(str->maxtime);
-
- // int mintime;
- saveg_write32(str->mintime);
-}
-
-//
-// strobe_t
-//
-
-static void saveg_read_strobe_t(strobe_t *str)
-{
- int sector;
-
- // thinker_t thinker;
- saveg_read_thinker_t(&str->thinker);
-
- // sector_t* sector;
- sector = saveg_read32();
- str->sector = §ors[sector];
-
- // int count;
- str->count = saveg_read32();
-
- // int minlight;
- str->minlight = saveg_read32();
-
- // int maxlight;
- str->maxlight = saveg_read32();
-
- // int darktime;
- str->darktime = saveg_read32();
-
- // int brighttime;
- str->brighttime = saveg_read32();
-}
-
-static void saveg_write_strobe_t(strobe_t *str)
-{
- // thinker_t thinker;
- saveg_write_thinker_t(&str->thinker);
-
- // sector_t* sector;
- saveg_write32(str->sector - sectors);
-
- // int count;
- saveg_write32(str->count);
-
- // int minlight;
- saveg_write32(str->minlight);
-
- // int maxlight;
- saveg_write32(str->maxlight);
-
- // int darktime;
- saveg_write32(str->darktime);
-
- // int brighttime;
- saveg_write32(str->brighttime);
-}
-
-//
-// glow_t
-//
-
-static void saveg_read_glow_t(glow_t *str)
-{
- int sector;
-
- // thinker_t thinker;
- saveg_read_thinker_t(&str->thinker);
-
- // sector_t* sector;
- sector = saveg_read32();
- str->sector = §ors[sector];
-
- // int minlight;
- str->minlight = saveg_read32();
-
- // int maxlight;
- str->maxlight = saveg_read32();
-
- // int direction;
- str->direction = saveg_read32();
-}
-
-static void saveg_write_glow_t(glow_t *str)
-{
- // thinker_t thinker;
- saveg_write_thinker_t(&str->thinker);
-
- // sector_t* sector;
- saveg_write32(str->sector - sectors);
-
- // int minlight;
- saveg_write32(str->minlight);
-
- // int maxlight;
- saveg_write32(str->maxlight);
-
- // int direction;
- saveg_write32(str->direction);
-}
-
-//
-// Write the header for a savegame
-//
-
-void P_WriteSaveGameHeader(char *description)
-{
- char name[VERSIONSIZE];
- int i;
-
- for (i=0; description[i] != '\0'; ++i)
- saveg_write8(description[i]);
- for (; i<SAVESTRINGSIZE; ++i)
- saveg_write8(0);
-
- memset (name,0,sizeof(name));
- sprintf (name,"version %i",DOOM_VERSION);
-
- for (i=0; i<VERSIONSIZE; ++i)
- saveg_write8(name[i]);
-
- saveg_write8(gameskill);
- saveg_write8(gameepisode);
- saveg_write8(gamemap);
-
- for (i=0 ; i<MAXPLAYERS ; i++)
- saveg_write8(playeringame[i]);
-
- saveg_write8((leveltime >> 16) & 0xff);
- saveg_write8((leveltime >> 8) & 0xff);
- saveg_write8(leveltime & 0xff);
-}
-
-//
-// Read the header for a savegame
-//
-
-boolean P_ReadSaveGameHeader(void)
-{
- int i;
- byte a, b, c;
- char vcheck[VERSIONSIZE];
- char read_vcheck[VERSIONSIZE];
-
- // skip the description field
-
- for (i=0; i<SAVESTRINGSIZE; ++i)
- saveg_read8();
-
- for (i=0; i<VERSIONSIZE; ++i)
- read_vcheck[i] = saveg_read8();
-
- memset (vcheck,0,sizeof(vcheck));
- sprintf (vcheck,"version %i",DOOM_VERSION);
- if (strcmp(read_vcheck, vcheck) != 0)
- return false; // bad version
-
- gameskill = saveg_read8();
- gameepisode = saveg_read8();
- gamemap = saveg_read8();
-
- for (i=0 ; i<MAXPLAYERS ; i++)
- playeringame[i] = saveg_read8();
-
- // get the times
- a = saveg_read8();
- b = saveg_read8();
- c = saveg_read8();
- leveltime = (a<<16) + (b<<8) + c;
-
- return true;
-}
-
-//
-// Read the end of file marker. Returns true if read successfully.
-//
-
-boolean P_ReadSaveGameEOF(void)
-{
- int value;
-
- value = saveg_read8();
-
- return value == SAVEGAME_EOF;
-}
-
-//
-// Write the end of file marker
-//
-
-void P_WriteSaveGameEOF(void)
-{
- saveg_write8(SAVEGAME_EOF);
-}
-
-//
-// P_ArchivePlayers
-//
-void P_ArchivePlayers (void)
-{
- int i;
-
- for (i=0 ; i<MAXPLAYERS ; i++)
- {
- if (!playeringame[i])
- continue;
-
- saveg_write_pad();
-
- saveg_write_player_t(&players[i]);
- }
-}
-
-
-
-//
-// P_UnArchivePlayers
-//
-void P_UnArchivePlayers (void)
-{
- int i;
-
- for (i=0 ; i<MAXPLAYERS ; i++)
- {
- if (!playeringame[i])
- continue;
-
- saveg_read_pad();
-
- saveg_read_player_t(&players[i]);
-
- // will be set when unarc thinker
- players[i].mo = NULL;
- players[i].message = NULL;
- players[i].attacker = NULL;
- }
-}
-
-
-//
-// P_ArchiveWorld
-//
-void P_ArchiveWorld (void)
-{
- int i;
- int j;
- sector_t* sec;
- line_t* li;
- side_t* si;
-
- // do sectors
- for (i=0, sec = sectors ; i<numsectors ; i++,sec++)
- {
- saveg_write16(sec->floorheight >> FRACBITS);
- saveg_write16(sec->ceilingheight >> FRACBITS);
- saveg_write16(sec->floorpic);
- saveg_write16(sec->ceilingpic);
- saveg_write16(sec->lightlevel);
- saveg_write16(sec->special); // needed?
- saveg_write16(sec->tag); // needed?
- }
-
-
- // do lines
- for (i=0, li = lines ; i<numlines ; i++,li++)
- {
- saveg_write16(li->flags);
- saveg_write16(li->special);
- saveg_write16(li->tag);
- for (j=0 ; j<2 ; j++)
- {
- if (li->sidenum[j] == -1)
- continue;
-
- si = &sides[li->sidenum[j]];
-
- saveg_write16(si->textureoffset >> FRACBITS);
- saveg_write16(si->rowoffset >> FRACBITS);
- saveg_write16(si->toptexture);
- saveg_write16(si->bottomtexture);
- saveg_write16(si->midtexture);
- }
- }
-}
-
-
-
-//
-// P_UnArchiveWorld
-//
-void P_UnArchiveWorld (void)
-{
- int i;
- int j;
- sector_t* sec;
- line_t* li;
- side_t* si;
-
- // do sectors
- for (i=0, sec = sectors ; i<numsectors ; i++,sec++)
- {
- sec->floorheight = saveg_read16() << FRACBITS;
- sec->ceilingheight = saveg_read16() << FRACBITS;
- sec->floorpic = saveg_read16();
- sec->ceilingpic = saveg_read16();
- sec->lightlevel = saveg_read16();
- sec->special = saveg_read16(); // needed?
- sec->tag = saveg_read16(); // needed?
- sec->specialdata = 0;
- sec->soundtarget = 0;
- }
-
- // do lines
- for (i=0, li = lines ; i<numlines ; i++,li++)
- {
- li->flags = saveg_read16();
- li->special = saveg_read16();
- li->tag = saveg_read16();
- for (j=0 ; j<2 ; j++)
- {
- if (li->sidenum[j] == -1)
- continue;
- si = &sides[li->sidenum[j]];
- si->textureoffset = saveg_read16() << FRACBITS;
- si->rowoffset = saveg_read16() << FRACBITS;
- si->toptexture = saveg_read16();
- si->bottomtexture = saveg_read16();
- si->midtexture = saveg_read16();
- }
- }
-}
-
-
-
-
-
-//
-// Thinkers
-//
-typedef enum
-{
- tc_end,
- tc_mobj
-
-} thinkerclass_t;
-
-
-//
-// P_ArchiveThinkers
-//
-void P_ArchiveThinkers (void)
-{
- thinker_t* th;
-
- // save off the current thinkers
- for (th = thinkercap.next ; th != &thinkercap ; th=th->next)
- {
- if (th->function.acp1 == (actionf_p1)P_MobjThinker)
- {
- saveg_write8(tc_mobj);
- saveg_write_pad();
- saveg_write_mobj_t((mobj_t *) th);
-
- continue;
- }
-
- // I_Error ("P_ArchiveThinkers: Unknown thinker function");
- }
-
- // add a terminating marker
- saveg_write8(tc_end);
-}
-
-
-
-//
-// P_UnArchiveThinkers
-//
-void P_UnArchiveThinkers (void)
-{
- byte tclass;
- thinker_t* currentthinker;
- thinker_t* next;
- mobj_t* mobj;
-
- // remove all the current thinkers
- currentthinker = thinkercap.next;
- while (currentthinker != &thinkercap)
- {
- next = currentthinker->next;
-
- if (currentthinker->function.acp1 == (actionf_p1)P_MobjThinker)
- P_RemoveMobj ((mobj_t *)currentthinker);
- else
- Z_Free (currentthinker);
-
- currentthinker = next;
- }
- P_InitThinkers ();
-
- // read in saved thinkers
- while (1)
- {
- tclass = saveg_read8();
- switch (tclass)
- {
- case tc_end:
- return; // end of list
-
- case tc_mobj:
- saveg_read_pad();
- mobj = Z_Malloc (sizeof(*mobj), PU_LEVEL, NULL);
- saveg_read_mobj_t(mobj);
-
- mobj->target = NULL;
- mobj->tracer = NULL;
- P_SetThingPosition (mobj);
- mobj->info = &mobjinfo[mobj->type];
- mobj->floorz = mobj->subsector->sector->floorheight;
- mobj->ceilingz = mobj->subsector->sector->ceilingheight;
- mobj->thinker.function.acp1 = (actionf_p1)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;
-
-
-
-//
-// Things to handle:
-//
-// 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
-//
-void P_ArchiveSpecials (void)
-{
- thinker_t* th;
- int i;
-
- // save off the current thinkers
- for (th = thinkercap.next ; th != &thinkercap ; th=th->next)
- {
- if (th->function.acv == (actionf_v)NULL)
- {
- for (i = 0; i < MAXCEILINGS;i++)
- if (activeceilings[i] == (ceiling_t *)th)
- break;
-
- if (i<MAXCEILINGS)
- {
- saveg_write8(tc_ceiling);
- saveg_write_pad();
- saveg_write_ceiling_t((ceiling_t *) th);
- }
- continue;
- }
-
- if (th->function.acp1 == (actionf_p1)T_MoveCeiling)
- {
- saveg_write8(tc_ceiling);
- saveg_write_pad();
- saveg_write_ceiling_t((ceiling_t *) th);
- continue;
- }
-
- if (th->function.acp1 == (actionf_p1)T_VerticalDoor)
- {
- saveg_write8(tc_door);
- saveg_write_pad();
- saveg_write_vldoor_t((vldoor_t *) th);
- continue;
- }
-
- if (th->function.acp1 == (actionf_p1)T_MoveFloor)
- {
- saveg_write8(tc_floor);
- saveg_write_pad();
- saveg_write_floormove_t((floormove_t *) th);
- continue;
- }
-
- if (th->function.acp1 == (actionf_p1)T_PlatRaise)
- {
- saveg_write8(tc_plat);
- saveg_write_pad();
- saveg_write_plat_t((plat_t *) th);
- continue;
- }
-
- if (th->function.acp1 == (actionf_p1)T_LightFlash)
- {
- saveg_write8(tc_flash);
- saveg_write_pad();
- saveg_write_lightflash_t((lightflash_t *) th);
- continue;
- }
-
- if (th->function.acp1 == (actionf_p1)T_StrobeFlash)
- {
- saveg_write8(tc_strobe);
- saveg_write_pad();
- saveg_write_strobe_t((strobe_t *) th);
- continue;
- }
-
- if (th->function.acp1 == (actionf_p1)T_Glow)
- {
- saveg_write8(tc_glow);
- saveg_write_pad();
- saveg_write_glow_t((glow_t *) th);
- continue;
- }
- }
-
- // add a terminating marker
- saveg_write8(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 = saveg_read8();
-
- switch (tclass)
- {
- case tc_endspecials:
- return; // end of list
-
- case tc_ceiling:
- saveg_read_pad();
- ceiling = Z_Malloc (sizeof(*ceiling), PU_LEVEL, NULL);
- saveg_read_ceiling_t(ceiling);
- ceiling->sector->specialdata = ceiling;
-
- if (ceiling->thinker.function.acp1)
- ceiling->thinker.function.acp1 = (actionf_p1)T_MoveCeiling;
-
- P_AddThinker (&ceiling->thinker);
- P_AddActiveCeiling(ceiling);
- break;
-
- case tc_door:
- saveg_read_pad();
- door = Z_Malloc (sizeof(*door), PU_LEVEL, NULL);
- saveg_read_vldoor_t(door);
- door->sector->specialdata = door;
- door->thinker.function.acp1 = (actionf_p1)T_VerticalDoor;
- P_AddThinker (&door->thinker);
- break;
-
- case tc_floor:
- saveg_read_pad();
- floor = Z_Malloc (sizeof(*floor), PU_LEVEL, NULL);
- saveg_read_floormove_t(floor);
- floor->sector->specialdata = floor;
- floor->thinker.function.acp1 = (actionf_p1)T_MoveFloor;
- P_AddThinker (&floor->thinker);
- break;
-
- case tc_plat:
- saveg_read_pad();
- plat = Z_Malloc (sizeof(*plat), PU_LEVEL, NULL);
- saveg_read_plat_t(plat);
- plat->sector->specialdata = plat;
-
- if (plat->thinker.function.acp1)
- plat->thinker.function.acp1 = (actionf_p1)T_PlatRaise;
-
- P_AddThinker (&plat->thinker);
- P_AddActivePlat(plat);
- break;
-
- case tc_flash:
- saveg_read_pad();
- flash = Z_Malloc (sizeof(*flash), PU_LEVEL, NULL);
- saveg_read_lightflash_t(flash);
- flash->thinker.function.acp1 = (actionf_p1)T_LightFlash;
- P_AddThinker (&flash->thinker);
- break;
-
- case tc_strobe:
- saveg_read_pad();
- strobe = Z_Malloc (sizeof(*strobe), PU_LEVEL, NULL);
- saveg_read_strobe_t(strobe);
- strobe->thinker.function.acp1 = (actionf_p1)T_StrobeFlash;
- P_AddThinker (&strobe->thinker);
- break;
-
- case tc_glow:
- saveg_read_pad();
- glow = Z_Malloc (sizeof(*glow), PU_LEVEL, NULL);
- saveg_read_glow_t(glow);
- glow->thinker.function.acp1 = (actionf_p1)T_Glow;
- P_AddThinker (&glow->thinker);
- break;
-
- default:
- I_Error ("P_UnarchiveSpecials:Unknown tclass %i "
- "in savegame",tclass);
- }
-
- }
-
-}
-
--- a/src/p_saveg.h
+++ /dev/null
@@ -1,69 +1,0 @@
-// Emacs style mode select -*- C++ -*-
-//-----------------------------------------------------------------------------
-//
-// Copyright(C) 1993-1996 Id Software, Inc.
-// Copyright(C) 2005 Simon Howard
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-// 02111-1307, USA.
-//
-// DESCRIPTION:
-// Savegame I/O, archiving, persistence.
-//
-//-----------------------------------------------------------------------------
-
-
-#ifndef __P_SAVEG__
-#define __P_SAVEG__
-
-#include <stdio.h>
-
-// maximum size of a savegame description
-
-#define SAVESTRINGSIZE 24
-
-// temporary filename to use while saving.
-
-char *P_TempSaveGameFile(void);
-
-// filename to use for a savegame slot
-
-char *P_SaveGameFile(int slot);
-
-// Savegame file header read/write functions
-
-boolean P_ReadSaveGameHeader(void);
-void P_WriteSaveGameHeader(char *description);
-
-// Savegame end-of-file read/write functions
-
-boolean P_ReadSaveGameEOF(void);
-void P_WriteSaveGameEOF(void);
-
-// Persistent storage/archiving.
-// These are the load / save game routines.
-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);
-
-extern FILE *save_stream;
-
-
-#endif
--- a/src/p_setup.c
+++ /dev/null
@@ -1,753 +1,0 @@
-// Emacs style mode select -*- C++ -*-
-//-----------------------------------------------------------------------------
-//
-// Copyright(C) 1993-1996 Id Software, Inc.
-// Copyright(C) 2005 Simon Howard
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-// 02111-1307, USA.
-//
-// DESCRIPTION:
-// Do all the WAD I/O, get map description,
-// set up initial state and misc. LUTs.
-//
-//-----------------------------------------------------------------------------
-
-
-
-#include <math.h>
-
-#include "z_zone.h"
-
-#include "deh_main.h"
-#include "i_swap.h"
-#include "m_bbox.h"
-
-#include "g_game.h"
-
-#include "i_system.h"
-#include "w_wad.h"
-
-#include "doomdef.h"
-#include "p_local.h"
-
-#include "s_sound.h"
-
-#include "doomstat.h"
-
-
-void P_SpawnMapThing (mapthing_t* mthing);
-
-
-//
-// MAP related Lookup tables.
-// Store VERTEXES, LINEDEFS, SIDEDEFS, etc.
-//
-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;
-
-
-// BLOCKMAP
-// Created from axis aligned bounding box
-// of the map, a rectangular array of
-// blocks of size ...
-// Used to speed up collision detection
-// by spatial subdivision in 2D.
-//
-// Blockmap size.
-int bmapwidth;
-int bmapheight; // size in mapblocks
-short* blockmap; // int for larger maps
-// offsets in blockmap are from here
-short* blockmaplump;
-// origin of block map
-fixed_t bmaporgx;
-fixed_t bmaporgy;
-// for thing chains
-mobj_t** blocklinks;
-
-
-// REJECT
-// For fast sight rejection.
-// Speeds up enemy AI by skipping detailed
-// LineOf Sight calculation.
-// Without special effect, this could be
-// used as a PVS lookup as well.
-//
-byte* rejectmatrix;
-
-
-// Maintain single and multi player starting spots.
-#define MAX_DEATHMATCH_STARTS 10
-
-mapthing_t deathmatchstarts[MAX_DEATHMATCH_STARTS];
-mapthing_t* deathmatch_p;
-mapthing_t playerstarts[MAXPLAYERS];
-
-
-
-
-
-//
-// P_LoadVertexes
-//
-void P_LoadVertexes (int lump)
-{
- byte* data;
- int i;
- mapvertex_t* ml;
- vertex_t* li;
-
- // Determine number of lumps:
- // total lump length / vertex record length.
- numvertexes = W_LumpLength (lump) / sizeof(mapvertex_t);
-
- // Allocate zone memory for buffer.
- vertexes = Z_Malloc (numvertexes*sizeof(vertex_t),PU_LEVEL,0);
-
- // Load data into cache.
- data = W_CacheLumpNum (lump, PU_STATIC);
-
- ml = (mapvertex_t *)data;
- li = vertexes;
-
- // Copy and convert vertex coordinates,
- // internal representation as fixed.
- for (i=0 ; i<numvertexes ; i++, li++, ml++)
- {
- li->x = SHORT(ml->x)<<FRACBITS;
- li->y = SHORT(ml->y)<<FRACBITS;
- }
-
- // Free buffer memory.
- W_ReleaseLumpNum(lump);
-}
-
-
-
-//
-// P_LoadSegs
-//
-void P_LoadSegs (int lump)
-{
- byte* data;
- int i;
- mapseg_t* ml;
- seg_t* li;
- line_t* ldef;
- int linedef;
- int side;
-
- numsegs = W_LumpLength (lump) / sizeof(mapseg_t);
- segs = Z_Malloc (numsegs*sizeof(seg_t),PU_LEVEL,0);
- memset (segs, 0, numsegs*sizeof(seg_t));
- data = W_CacheLumpNum (lump,PU_STATIC);
-
- ml = (mapseg_t *)data;
- li = segs;
- for (i=0 ; i<numsegs ; i++, li++, ml++)
- {
- li->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;
- }
-
- W_ReleaseLumpNum(lump);
-}
-
-
-//
-// 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 ; i<numsubsectors ; i++, ss++, ms++)
- {
- ss->numlines = SHORT(ms->numsegs);
- ss->firstline = SHORT(ms->firstseg);
- }
-
- W_ReleaseLumpNum(lump);
-}
-
-
-
-//
-// 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 ; i<numsectors ; i++, ss++, ms++)
- {
- ss->floorheight = SHORT(ms->floorheight)<<FRACBITS;
- ss->ceilingheight = SHORT(ms->ceilingheight)<<FRACBITS;
- ss->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;
- }
-
- W_ReleaseLumpNum(lump);
-}
-
-
-//
-// P_LoadNodes
-//
-void P_LoadNodes (int lump)
-{
- byte* data;
- int i;
- int j;
- int 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 ; i<numnodes ; i++, no++, mn++)
- {
- no->x = SHORT(mn->x)<<FRACBITS;
- no->y = SHORT(mn->y)<<FRACBITS;
- no->dx = SHORT(mn->dx)<<FRACBITS;
- no->dy = SHORT(mn->dy)<<FRACBITS;
- for (j=0 ; j<2 ; j++)
- {
- no->children[j] = SHORT(mn->children[j]);
- for (k=0 ; k<4 ; k++)
- no->bbox[j][k] = SHORT(mn->bbox[j][k])<<FRACBITS;
- }
- }
-
- W_ReleaseLumpNum(lump);
-}
-
-
-//
-// P_LoadThings
-//
-void P_LoadThings (int lump)
-{
- byte *data;
- int i;
- mapthing_t *mt;
- mapthing_t spawnthing;
- int numthings;
- boolean spawn;
-
- data = W_CacheLumpNum (lump,PU_STATIC);
- numthings = W_LumpLength (lump) / sizeof(mapthing_t);
-
- mt = (mapthing_t *)data;
- for (i=0 ; i<numthings ; i++, mt++)
- {
- spawn = true;
-
- // Do not spawn cool, new monsters if !commercial
- if (gamemode != commercial)
- {
- switch (SHORT(mt->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;
- break;
- }
- }
- if (spawn == false)
- break;
-
- // Do spawn all other stuff.
- spawnthing.x = SHORT(mt->x);
- spawnthing.y = SHORT(mt->y);
- spawnthing.angle = SHORT(mt->angle);
- spawnthing.type = SHORT(mt->type);
- spawnthing.options = SHORT(mt->options);
-
- P_SpawnMapThing(&spawnthing);
- }
-
- W_ReleaseLumpNum(lump);
-}
-
-
-//
-// 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;
- vertex_t* 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 ; i<numlines ; i++, mld++, ld++)
- {
- ld->flags = 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;
- }
-
- W_ReleaseLumpNum(lump);
-}
-
-
-//
-// 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 ; i<numsides ; i++, msd++, sd++)
- {
- sd->textureoffset = SHORT(msd->textureoffset)<<FRACBITS;
- sd->rowoffset = SHORT(msd->rowoffset)<<FRACBITS;
- sd->toptexture = R_TextureNumForName(msd->toptexture);
- sd->bottomtexture = R_TextureNumForName(msd->bottomtexture);
- sd->midtexture = R_TextureNumForName(msd->midtexture);
- sd->sector = §ors[SHORT(msd->sector)];
- }
-
- W_ReleaseLumpNum(lump);
-}
-
-
-//
-// P_LoadBlockMap
-//
-void P_LoadBlockMap (int lump)
-{
- int i;
- int count;
- int lumplen;
-
- lumplen = W_LumpLength(lump);
- count = lumplen / 2;
-
- blockmaplump = Z_Malloc(lumplen, PU_LEVEL, NULL);
- W_ReadLump(lump, blockmaplump);
- blockmap = blockmaplump + 4;
-
- // Swap all short integers to native byte ordering.
-
- for (i=0; i<count; i++)
- {
- blockmaplump[i] = SHORT(blockmaplump[i]);
- }
-
- // Read the header
-
- bmaporgx = blockmaplump[0]<<FRACBITS;
- bmaporgy = blockmaplump[1]<<FRACBITS;
- bmapwidth = blockmaplump[2];
- bmapheight = blockmaplump[3];
-
- // Clear out mobj chains
-
- count = sizeof(*blocklinks) * bmapwidth * bmapheight;
- blocklinks = Z_Malloc(count, PU_LEVEL, 0);
- memset(blocklinks, 0, count);
-}
-
-
-
-//
-// P_GroupLines
-// Builds sector line lists and subsector sector numbers.
-// Finds block bounding boxes for sectors.
-//
-void P_GroupLines (void)
-{
- line_t** linebuffer;
- int i;
- int j;
- int total;
- line_t* li;
- sector_t* sector;
- subsector_t* ss;
- seg_t* seg;
- fixed_t bbox[4];
- int block;
-
- // look up sector number for each subsector
- ss = subsectors;
- for (i=0 ; i<numsubsectors ; i++, ss++)
- {
- seg = &segs[ss->firstline];
- ss->sector = seg->sidedef->sector;
- }
-
- // count number of lines in each sector
- li = lines;
- total = 0;
- for (i=0 ; i<numlines ; i++, li++)
- {
- total++;
- li->frontsector->linecount++;
-
- if (li->backsector && li->backsector != li->frontsector)
- {
- li->backsector->linecount++;
- total++;
- }
- }
-
- // build line tables for each sector
- linebuffer = Z_Malloc (total*sizeof(line_t *), PU_LEVEL, 0);
-
- for (i=0; i<numsectors; ++i)
- {
- // Assign the line buffer for this sector
-
- sectors[i].lines = linebuffer;
- linebuffer += sectors[i].linecount;
-
- // Reset linecount to zero so in the next stage we can count
- // lines into the list.
-
- sectors[i].linecount = 0;
- }
-
- // Assign lines to sectors
-
- for (i=0; i<numlines; ++i)
- {
- li = &lines[i];
-
- if (li->frontsector != NULL)
- {
- sector = li->frontsector;
-
- sector->lines[sector->linecount] = li;
- ++sector->linecount;
- }
-
- if (li->backsector != NULL && li->frontsector != li->backsector)
- {
- sector = li->backsector;
-
- sector->lines[sector->linecount] = li;
- ++sector->linecount;
- }
- }
-
- // Generate bounding boxes for sectors
-
- sector = sectors;
- for (i=0 ; i<numsectors ; i++, sector++)
- {
- M_ClearBox (bbox);
-
- for (j=0 ; j<sector->linecount; j++)
- {
- li = sector->lines[j];
-
- M_AddToBox (bbox, li->v1->x, li->v1->y);
- M_AddToBox (bbox, li->v2->x, li->v2->y);
- }
-
- // 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 ; i<MAXPLAYERS ; i++)
- {
- players[i].killcount = players[i].secretcount
- = players[i].itemcount = 0;
- }
-
- // Initial height of PointOfView
- // will be set by player think.
- players[consoleplayer].viewz = 1;
-
- // Make sure all sounds are stopped before Z_FreeTags.
- S_Start ();
-
-
-#if 0 // UNUSED
- if (debugfile)
- {
- Z_FreeTags (PU_LEVEL, INT_MAX);
- Z_FileDumpHeap (debugfile);
- }
- else
-#endif
- Z_FreeTags (PU_LEVEL, PU_PURGELEVEL-1);
-
-
- // UNUSED W_Profile ();
- P_InitThinkers ();
-
- // find map name
- if ( gamemode == commercial)
- {
- if (map<10)
- sprintf (lumpname, DEH_String("map0%i"), map);
- else
- sprintf (lumpname, DEH_String("map%i"), map);
- }
- else
- {
- lumpname[0] = 'E';
- lumpname[1] = '0' + episode;
- lumpname[2] = 'M';
- lumpname[3] = '0' + map;
- lumpname[4] = 0;
- }
-
- lumpnum = W_GetNumForName (lumpname);
-
- leveltime = 0;
-
- // note: most of this ordering is important
- P_LoadBlockMap (lumpnum+ML_BLOCKMAP);
- P_LoadVertexes (lumpnum+ML_VERTEXES);
- P_LoadSectors (lumpnum+ML_SECTORS);
- P_LoadSideDefs (lumpnum+ML_SIDEDEFS);
-
- P_LoadLineDefs (lumpnum+ML_LINEDEFS);
- P_LoadSubsectors (lumpnum+ML_SSECTORS);
- P_LoadNodes (lumpnum+ML_NODES);
- P_LoadSegs (lumpnum+ML_SEGS);
-
- rejectmatrix = W_CacheLumpNum (lumpnum+ML_REJECT,PU_LEVEL);
- P_GroupLines ();
-
- bodyqueslot = 0;
- deathmatch_p = deathmatchstarts;
- P_LoadThings (lumpnum+ML_THINGS);
-
- // if deathmatch, randomly spawn the active players
- if (deathmatch)
- {
- for (i=0 ; i<MAXPLAYERS ; i++)
- if (playeringame[i])
- {
- players[i].mo = NULL;
- G_DeathMatchSpawnPlayer (i);
- }
-
- }
-
- // clear special respawning que
- iquehead = iquetail = 0;
-
- // set up world state
- P_SpawnSpecials ();
-
- // build subsector connect matrix
- // UNUSED P_ConnectSubsectors ();
-
- // preload graphics
- if (precache)
- R_PrecacheLevel ();
-
- //printf ("free memory: 0x%x\n", Z_FreeMemory());
-
-}
-
-
-
-//
-// P_Init
-//
-void P_Init (void)
-{
- P_InitSwitchList ();
- P_InitPicAnims ();
- R_InitSprites (sprnames);
-}
-
-
-
--- a/src/p_setup.h
+++ /dev/null
@@ -1,45 +1,0 @@
-// Emacs style mode select -*- C++ -*-
-//-----------------------------------------------------------------------------
-//
-// Copyright(C) 1993-1996 Id Software, Inc.
-// Copyright(C) 2005 Simon Howard
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-// 02111-1307, USA.
-//
-// DESCRIPTION:
-// Setup a game, startup stuff.
-//
-//-----------------------------------------------------------------------------
-
-
-#ifndef __P_SETUP__
-#define __P_SETUP__
-
-
-
-
-// NOT called by W_Ticker. Fixme.
-void
-P_SetupLevel
-( int episode,
- int map,
- int playermask,
- skill_t skill);
-
-// Called by startup code.
-void P_Init (void);
-
-#endif
--- a/src/p_sight.c
+++ /dev/null
@@ -1,350 +1,0 @@
-// Emacs style mode select -*- C++ -*-
-//-----------------------------------------------------------------------------
-//
-// Copyright(C) 1993-1996 Id Software, Inc.
-// Copyright(C) 2005 Simon Howard
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-// 02111-1307, USA.
-//
-// DESCRIPTION:
-// LineOfSight/Visibility checks, uses REJECT Lookup Table.
-//
-//-----------------------------------------------------------------------------
-
-
-
-#include "doomdef.h"
-
-#include "i_system.h"
-#include "p_local.h"
-
-// State.
-#include "r_state.h"
-
-//
-// P_CheckSight
-//
-fixed_t sightzstart; // eye z of looker
-fixed_t topslope;
-fixed_t bottomslope; // slopes to top and bottom of target
-
-divline_t strace; // from t1 to t2
-fixed_t t2x;
-fixed_t t2y;
-
-int sightcounts[2];
-
-
-//
-// P_DivlineSide
-// Returns side 0 (front), 1 (back), or 2 (on).
-//
-int
-P_DivlineSide
-( fixed_t x,
- fixed_t y,
- divline_t* node )
-{
- fixed_t dx;
- fixed_t dy;
- fixed_t left;
- fixed_t right;
-
- if (!node->dx)
- {
- 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;
- fixed_t num;
- fixed_t 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 successfully.
-//
-boolean P_CrossSubsector (int num)
-{
- seg_t* seg;
- line_t* line;
- int s1;
- int s2;
- int count;
- subsector_t* sub;
- sector_t* front;
- sector_t* back;
- fixed_t opentop;
- fixed_t openbottom;
- divline_t divl;
- vertex_t* v1;
- vertex_t* v2;
- fixed_t frac;
- fixed_t 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;
-
- // allready checked other side?
- if (line->validcount == validcount)
- continue;
-
- 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);
-
- // line isn't crossed?
- if (s1 == s2)
- continue;
-
- 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);
-
- // line isn't crossed?
- if (s1 == s2)
- continue;
-
- // stop because it is not two sided anyway
- // might do this after updating validcount?
- if ( !(line->flags & ML_TWOSIDED) )
- return false;
-
- // crosses a two sided line
- front = seg->frontsector;
- back = seg->backsector;
-
- // no wall to block sight with?
- if (front->floorheight == back->floorheight
- && front->ceilingheight == back->ceilingheight)
- continue;
-
- // possible occluder
- // because of ceiling height differences
- if (front->ceilingheight < back->ceilingheight)
- opentop = front->ceilingheight;
- else
- opentop = back->ceilingheight;
-
- // because of ceiling height differences
- if (front->floorheight > back->floorheight)
- openbottom = front->floorheight;
- else
- openbottom = back->floorheight;
-
- // quick test for totally closed doors
- if (openbottom >= opentop)
- 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
- }
- // passed the subsector ok
- return true;
-}
-
-
-
-//
-// P_CrossBSPNode
-// Returns true
-// if strace crosses the given node successfully.
-//
-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))
- {
- // the line doesn't touch the other side
- return true;
- }
-
- // 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.
-// Uses REJECT.
-//
-boolean
-P_CheckSight
-( mobj_t* t1,
- mobj_t* t2 )
-{
- int s1;
- int s2;
- int pnum;
- int bytenum;
- int bitnum;
-
- // First check for trivial rejection.
-
- // Determine subsector entries in REJECT table.
- s1 = (t1->subsector->sector - sectors);
- s2 = (t2->subsector->sector - sectors);
- pnum = s1*numsectors + s2;
- bytenum = pnum>>3;
- bitnum = 1 << (pnum&7);
-
- // Check in REJECT table.
- if (rejectmatrix[bytenum]&bitnum)
- {
- sightcounts[0]++;
-
- // can't possibly be connected
- return false;
- }
-
- // An unobstructed LOS is possible.
- // Now 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;
-
- // the head node is the last node output
- return P_CrossBSPNode (numnodes-1);
-}
-
-
--- a/src/p_spec.c
+++ /dev/null
@@ -1,1372 +1,0 @@
-// Emacs style mode select -*- C++ -*-
-//-----------------------------------------------------------------------------
-//
-// Copyright(C) 1993-1996 Id Software, Inc.
-// Copyright(C) 2005 Simon Howard
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-// 02111-1307, USA.
-//
-// DESCRIPTION:
-// Implements special effects:
-// Texture animation, height or lighting changes
-// according to adjacent sectors, respective
-// utility functions, etc.
-// Line Tag handling. Line and Sector triggers.
-//
-//-----------------------------------------------------------------------------
-
-
-#include <stdlib.h>
-
-#include "doomdef.h"
-#include "doomstat.h"
-
-#include "deh_main.h"
-#include "i_system.h"
-#include "z_zone.h"
-#include "m_argv.h"
-#include "m_random.h"
-#include "w_wad.h"
-
-#include "r_local.h"
-#include "p_local.h"
-
-#include "g_game.h"
-
-#include "s_sound.h"
-
-// State.
-#include "r_state.h"
-
-// Data.
-#include "sounds.h"
-
-
-//
-// Animating textures and planes
-// There is another anim_t used in wi_stuff, unrelated.
-//
-typedef struct
-{
- boolean istexture;
- int picnum;
- int basepic;
- int numpics;
- int speed;
-
-} anim_t;
-
-//
-// source animation definition
-//
-typedef struct
-{
- int istexture; // if false, it is a flat
- char endname[9];
- char startname[9];
- int speed;
-} animdef_t;
-
-
-
-#define MAXANIMS 32
-
-extern anim_t anims[MAXANIMS];
-extern anim_t* lastanim;
-
-//
-// P_InitPicAnims
-//
-
-// Floor/ceiling animation sequences,
-// defined by first and last frame,
-// i.e. the flat (64x64 tile) name to
-// be used.
-// The full animation sequence is given
-// using all the flats between the start
-// and end entry, in the order found in
-// the WAD file.
-//
-animdef_t animdefs[] =
-{
- {false, "NUKAGE3", "NUKAGE1", 8},
- {false, "FWATER4", "FWATER1", 8},
- {false, "SWATER4", "SWATER1", 8},
- {false, "LAVA4", "LAVA1", 8},
- {false, "BLOOD3", "BLOOD1", 8},
-
- // DOOM II flat animations.
- {false, "RROCK08", "RROCK05", 8},
- {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, "", "", 0},
-};
-
-anim_t anims[MAXANIMS];
-anim_t* lastanim;
-
-
-//
-// Animating line specials
-//
-#define MAXLINEANIMS 64
-
-extern short numlinespecials;
-extern line_t* linespeciallist[MAXLINEANIMS];
-
-
-
-void P_InitPicAnims (void)
-{
- int i;
-
-
- // Init animation
- lastanim = anims;
- for (i=0 ; animdefs[i].istexture != -1 ; i++)
- {
- char *startname, *endname;
-
- startname = DEH_String(animdefs[i].startname);
- endname = DEH_String(animdefs[i].endname);
-
- if (animdefs[i].istexture)
- {
- // different episode ?
- if (R_CheckTextureNumForName(startname) == -1)
- continue;
-
- lastanim->picnum = R_TextureNumForName(endname);
- lastanim->basepic = R_TextureNumForName(startname);
- }
- else
- {
- if (W_CheckNumForName(startname) == -1)
- continue;
-
- lastanim->picnum = R_FlatNumForName(endname);
- lastanim->basepic = R_FlatNumForName(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",
- startname, endname);
-
- lastanim->speed = animdefs[i].speed;
- lastanim++;
- }
-
-}
-
-
-
-//
-// UTILITIES
-//
-
-
-
-//
-// getSide()
-// 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] ];
-}
-
-
-//
-// getSector()
-// 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;
-}
-
-
-//
-// twoSided()
-// Given the sector number and the line number,
-// it 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;
-}
-
-
-
-
-//
-// getNextSector()
-// 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;
-}
-
-
-
-//
-// P_FindLowestFloorSurrounding()
-// 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;
-}
-
-
-
-//
-// P_FindHighestFloorSurrounding()
-// 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;
-}
-
-
-
-//
-// P_FindNextHighestFloor
-// FIND NEXT HIGHEST FLOOR IN SURROUNDING SECTORS
-// Note: this should be doable w/o a fixed array.
-
-// Thanks to entryway for the Vanilla overflow emulation.
-
-// 20 adjoining sectors max!
-#define MAX_ADJOINING_SECTORS 20
-
-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[MAX_ADJOINING_SECTORS + 2];
-
- for (i=0, h=0; i < sec->linecount; i++)
- {
- check = sec->lines[i];
- other = getNextSector(check,sec);
-
- if (!other)
- continue;
-
- if (other->floorheight > height)
- {
- // Emulation of memory (stack) overflow
- if (h == MAX_ADJOINING_SECTORS + 1)
- {
- height = other->floorheight;
- }
- else if (h == MAX_ADJOINING_SECTORS + 2)
- {
- // Fatal overflow: game crashes at 22 textures
- I_Error("Sector with more than 22 adjoining sectors. "
- "Vanilla will crash here");
- }
-
- heightlist[h++] = other->floorheight;
- }
- }
-
- // Find lowest height in list
- if (!h)
- {
- return currentheight;
- }
-
- min = heightlist[0];
-
- // Range checking?
- 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 = INT_MAX;
-
- 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;i<numsectors;i++)
- if (sectors[i].tag == line->tag)
- 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;
- break;
-
- 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;
- }
-
-
- // Note: could use some const's here.
- switch (line->special)
- {
- // TRIGGERS.
- // All from here to RETRIGGERS.
- 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. All from here till end.
- 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;
-
- // Falling, not all the way down yet?
- if (player->mo->z != sector->floorheight)
- return;
-
- // Has hitten ground.
- 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);
- break;
- };
-}
-
-
-
-
-//
-// 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 GLOBALLY
- for (anim = anims ; anim < lastanim ; anim++)
- {
- for (i=anim->basepic ; i<anim->basepic+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(&buttonlist[i].soundorg,sfx_swtchn);
- memset(&buttonlist[i],0,sizeof(button_t));
- }
- }
-
-}
-
-
-
-//
-// Special Stuff that can not 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.acp1 = (actionf_p1) 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.acp1 = (actionf_p1) 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];
-
-
-// Parses command line parameters.
-void P_SpawnSpecials (void)
-{
- sector_t* sector;
- int i;
- int episode;
-
- episode = 1;
- if (W_CheckNumForName(DEH_String("texture2")) >= 0)
- episode = 2;
-
-
- // See if -TIMER was specified.
-
- if (timelimit > 0)
- {
- levelTimer = true;
- levelTimeCount = timelimit * 60 * TICRATE;
- }
- else
- {
- levelTimer = false;
- }
-
- // Init special SECTORs.
- sector = sectors;
- for (i=0 ; i<numsectors ; i++, sector++)
- {
- if (!sector->special)
- 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));
-
- // UNUSED: no horizonal sliders.
- // P_InitSlidingDoorFrames();
-}
--- a/src/p_spec.h
+++ /dev/null
@@ -1,645 +1,0 @@
-// Emacs style mode select -*- C++ -*-
-//-----------------------------------------------------------------------------
-//
-// Copyright(C) 1993-1996 Id Software, Inc.
-// Copyright(C) 2005 Simon Howard
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-// 02111-1307, USA.
-//
-// DESCRIPTION: none
-// Implements special effects:
-// Texture animation, height or lighting changes
-// according to adjacent sectors, respective
-// utility functions, etc.
-//
-//-----------------------------------------------------------------------------
-
-
-#ifndef __P_SPEC__
-#define __P_SPEC__
-
-
-//
-// End-level timer (-TIMER option)
-//
-extern boolean levelTimer;
-extern int levelTimeCount;
-
-
-// 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;
- degenmobj_t *soundorg;
-
-} button_t;
-
-
-
-
- // max # of wall switches in a level
-#define MAXSWITCHES 50
-
- // 4 players, 4 buttons each at once, max.
-#define MAXBUTTONS 16
-
- // 1 second, in ticks.
-#define BUTTONTIME 35
-
-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;
-
- // 1 = up, 0 = waiting at top, -1 = down
- int direction;
-
- // tics to wait at the top
- int topwait;
- // (keep in case a door going down is reset)
- // when it reaches 0, start going down
- int topcountdown;
-
-} 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 // UNUSED
-//
-// 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;
-
-
-
-// how many frames of animation
-#define SNUMFRAMES 4
-
-#define SDOORWAIT 35*3
-#define SWAITTICS 4
-
-// how many diff. types of anims
-#define MAXSLIDEDOORS 5
-
-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;
- fixed_t topheight;
- fixed_t speed;
- boolean crush;
-
- // 1 = up, 0 = waiting, -1 = down
- int direction;
-
- // ID
- int tag;
- 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
-{
- // lower floor to highest surrounding floor
- lowerFloor,
-
- // lower floor to lowest surrounding floor
- lowerFloorToLowest,
-
- // lower floor to highest surrounding floor VERY FAST
- turboLower,
-
- // raise floor to lowest surrounding CEILING
- raiseFloor,
-
- // raise floor to next highest surrounding floor
- raiseFloorToNearest,
-
- // raise floor to shortest height texture around it
- raiseToTexture,
-
- // lower floor to lowest surrounding floor
- // and change floorpic
- lowerAndChange,
-
- raiseFloor24,
- raiseFloor24AndChange,
- raiseFloorCrush,
-
- // raise to next highest floor, turbo-speed
- raiseFloorTurbo,
- 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 );
-
-#endif
--- a/src/p_switch.c
+++ /dev/null
@@ -1,656 +1,0 @@
-// Emacs style mode select -*- C++ -*-
-//-----------------------------------------------------------------------------
-//
-// Copyright(C) 1993-1996 Id Software, Inc.
-// Copyright(C) 2005 Simon Howard
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-// 02111-1307, USA.
-//
-//
-// DESCRIPTION:
-// Switches, buttons. Two-state animation. Exits.
-//
-//-----------------------------------------------------------------------------
-
-
-
-#include "i_system.h"
-#include "deh_main.h"
-#include "doomdef.h"
-#include "p_local.h"
-
-#include "g_game.h"
-
-#include "s_sound.h"
-
-// Data.
-#include "sounds.h"
-
-// State.
-#include "doomstat.h"
-#include "r_state.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 (gamemode == registered || gamemode == retail)
- episode = 2;
- else
- if ( gamemode == 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 // UNUSED - debug?
- 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(DEH_String(alphSwitchList[i].name1));
- switchlist[index++] = R_TextureNumForName(DEH_String(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 = &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;
-
- // EXIT SWITCH?
- if (line->special == 11)
- 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 )
-{
-
- // Err...
- // Use the back sides of VERY SPECIAL lines...
- if (side)
- {
- switch(line->special)
- {
- case 124:
- // Sliding door open&close
- // UNUSED?
- break;
-
- default:
- return false;
- break;
- }
- }
-
-
- // Switches that other things can activate.
- if (!thing->player)
- {
- // never open secret doors
- if (line->flags & ML_SECRET)
- return false;
-
- switch(line->special)
- {
- case 1: // MANUAL DOOR RAISE
- case 32: // MANUAL BLUE
- case 33: // MANUAL RED
- case 34: // MANUAL YELLOW
- break;
-
- default:
- return false;
- break;
- }
- }
-
-
- // 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;
-
- //UNUSED - Door Slide Open&Close
- // case 124:
- // 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;
-}
-
--- a/src/p_telept.c
+++ /dev/null
@@ -1,142 +1,0 @@
-// Emacs style mode select -*- C++ -*-
-//-----------------------------------------------------------------------------
-//
-// Copyright(C) 1993-1996 Id Software, Inc.
-// Copyright(C) 2005 Simon Howard
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-// 02111-1307, USA.
-//
-// DESCRIPTION:
-// Teleportation.
-//
-//-----------------------------------------------------------------------------
-
-
-
-
-#include "doomdef.h"
-#include "doomstat.h"
-
-#include "s_sound.h"
-
-#include "p_local.h"
-
-
-// Data.
-#include "sounds.h"
-
-// State.
-#include "r_state.h"
-
-
-
-//
-// TELEPORTATION
-//
-int
-EV_Teleport
-( line_t* line,
- int side,
- mobj_t* thing )
-{
- int i;
- int tag;
- mobj_t* m;
- mobj_t* fog;
- unsigned an;
- thinker_t* thinker;
- sector_t* sector;
- fixed_t oldx;
- fixed_t oldy;
- fixed_t oldz;
-
- // don't teleport missiles
- if (thing->flags & MF_MISSILE)
- return 0;
-
- // Don't teleport if hit back of line,
- // so you can get out of teleporter.
- if (side == 1)
- return 0;
-
-
- 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)
- {
- // not a mobj
- if (thinker->function.acp1 != (actionf_p1)P_MobjThinker)
- continue;
-
- m = (mobj_t *)thinker;
-
- // not a teleportman
- if (m->type != MT_TELEPORTMAN )
- continue;
-
- sector = m->subsector->sector;
- // wrong sector
- if (sector-sectors != i )
- continue;
-
- oldx = thing->x;
- oldy = thing->y;
- oldz = thing->z;
-
- if (!P_TeleportMove (thing, m->x, m->y))
- return 0;
-
- // fraggle: this was changed in final doom,
- // problem between normal doom2 1.9 and final doom
- //
- // Note that although chex.exe is based on Final Doom,
- // it does not have this quirk.
-
- if (gameversion < exe_final || gameversion == exe_chex)
- 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);
-
- // emit sound, where?
- S_StartSound (fog, sfx_telept);
-
- // don't move for a bit
- if (thing->player)
- thing->reactiontime = 18;
-
- thing->angle = m->angle;
- thing->momx = thing->momy = thing->momz = 0;
- return 1;
- }
- }
- }
- return 0;
-}
-
--- a/src/p_tick.c
+++ /dev/null
@@ -1,159 +1,0 @@
-// Emacs style mode select -*- C++ -*-
-//-----------------------------------------------------------------------------
-//
-// Copyright(C) 1993-1996 Id Software, Inc.
-// Copyright(C) 2005 Simon Howard
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-// 02111-1307, USA.
-//
-// DESCRIPTION:
-// Archiving: SaveGame I/O.
-// Thinker, Ticker.
-//
-//-----------------------------------------------------------------------------
-
-
-#include "z_zone.h"
-#include "p_local.h"
-
-#include "doomstat.h"
-
-
-int leveltime;
-
-//
-// 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.
-//
-
-
-
-// Both the head and tail of the thinker list.
-thinker_t thinkercap;
-
-
-//
-// 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)
-{
- // FIXME: NOP.
- thinker->function.acv = (actionf_v)(-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.acv == (actionf_v)(-1) )
- {
- // time to remove it
- currentthinker->next->prev = currentthinker->prev;
- currentthinker->prev->next = currentthinker->next;
- Z_Free (currentthinker);
- }
- else
- {
- if (currentthinker->function.acp1)
- currentthinker->function.acp1 (currentthinker);
- }
- currentthinker = currentthinker->next;
- }
-}
-
-
-
-//
-// P_Ticker
-//
-
-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<MAXPLAYERS ; i++)
- if (playeringame[i])
- P_PlayerThink (&players[i]);
-
- P_RunThinkers ();
- P_UpdateSpecials ();
- P_RespawnSpecials ();
-
- // for par times
- leveltime++;
-}
--- a/src/p_tick.h
+++ /dev/null
@@ -1,41 +1,0 @@
-// Emacs style mode select -*- C++ -*-
-//-----------------------------------------------------------------------------
-//
-// Copyright(C) 1993-1996 Id Software, Inc.
-// Copyright(C) 2005 Simon Howard
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-// 02111-1307, USA.
-//
-// DESCRIPTION:
-// ?
-//
-//-----------------------------------------------------------------------------
-
-
-#ifndef __P_TICK__
-#define __P_TICK__
-
-
-
-
-// Called by C_Ticker,
-// can call G_PlayerExited.
-// Carries out all thinking of monsters and players.
-void P_Ticker (void);
-
-
-
-#endif
--- a/src/p_user.c
+++ /dev/null
@@ -1,387 +1,0 @@
-// Emacs style mode select -*- C++ -*-
-//-----------------------------------------------------------------------------
-//
-// Copyright(C) 1993-1996 Id Software, Inc.
-// Copyright(C) 2005 Simon Howard
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-// 02111-1307, USA.
-//
-// DESCRIPTION:
-// Player related stuff.
-// Bobbing POV/weapon, movement.
-// Pending weapon.
-//
-//-----------------------------------------------------------------------------
-
-
-
-
-#include "doomdef.h"
-#include "d_event.h"
-
-#include "p_local.h"
-
-#include "doomstat.h"
-
-
-
-// Index of the special effects (INVUL inverse) map.
-#define INVERSECOLORMAP 32
-
-
-//
-// Movement.
-//
-
-// 16 pixels of bob
-#define MAXBOB 0x100000
-
-boolean onground;
-
-
-//
-// P_Thrust
-// Moves the given origin along a given angle.
-//
-void
-P_Thrust
-( player_t* player,
- angle_t angle,
- fixed_t move )
-{
- angle >>= 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
- // Note: a LUT allows for effects
- // like a ramp with low health.
- 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);
-
- // Do not 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
-// Fall on your face when dying.
-// Decrease POV height to floor height.
-//
-#define ANG5 (ANG90/18)
-
-void P_DeathThink (player_t* player)
-{
- angle_t angle;
- angle_t 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.
-
- // A special event has no other buttons.
- if (cmd->buttons & BT_SPECIAL)
- cmd->buttons = 0;
-
- if (cmd->buttons & BT_CHANGE)
- {
- // The actual changing of the weapon is done
- // when the weapon psprite can do it
- // (read: 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 ( (gamemode == commercial)
- && newweapon == wp_shotgun
- && player->weaponowned[wp_supershotgun]
- && player->readyweapon != wp_supershotgun)
- {
- newweapon = wp_supershotgun;
- }
-
-
- if (player->weaponowned[newweapon]
- && newweapon != player->readyweapon)
- {
- // Do not go to plasma or BFG in shareware,
- // even if cheated.
- if ((newweapon != wp_plasma
- && newweapon != wp_bfg)
- || (gamemode != 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, time dependend power ups.
-
- // Strength counts up to diminish fade.
- if (player->powers[pw_strength])
- player->powers[pw_strength]++;
-
- 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--;
-
-
- // Handling 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) )
- {
- // almost full bright
- player->fixedcolormap = 1;
- }
- else
- player->fixedcolormap = 0;
- }
- else
- player->fixedcolormap = 0;
-}
-
-
--- a/src/r_bsp.c
+++ /dev/null
@@ -1,581 +1,0 @@
-// Emacs style mode select -*- C++ -*-
-//-----------------------------------------------------------------------------
-//
-// Copyright(C) 1993-1996 Id Software, Inc.
-// Copyright(C) 2005 Simon Howard
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-// 02111-1307, USA.
-//
-// DESCRIPTION:
-// BSP traversal, handling of LineSegs for rendering.
-//
-//-----------------------------------------------------------------------------
-
-
-
-
-#include "doomdef.h"
-
-#include "m_bbox.h"
-
-#include "i_system.h"
-
-#include "r_main.h"
-#include "r_plane.h"
-#include "r_things.h"
-
-// State.
-#include "doomstat.h"
-#include "r_state.h"
-
-//#include "r_local.h"
-
-
-
-seg_t* curline;
-side_t* sidedef;
-line_t* linedef;
-sector_t* frontsector;
-sector_t* backsector;
-
-drawseg_t drawsegs[MAXDRAWSEGS];
-drawseg_t* 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;
- int last;
-
-} cliprange_t;
-
-
-#define MAXSEGS 32
-
-// newend is one past the last valid seg
-cliprange_t* newend;
-cliprange_t solidsegs[MAXSEGS];
-
-
-
-
-//
-// R_ClipSolidWallSegment
-// Does handle solid walls,
-// e.g. single sided LineDefs (middle texture)
-// that entirely block the view.
-//
-void
-R_ClipSolidWallSegment
-( int first,
- int last )
-{
- cliprange_t* next;
- 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),
- // 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);
- // Now adjust the clip size.
- start->first = first;
- }
-
- // Bottom contained in start?
- if (last <= start->last)
- return;
-
- 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.
- // Adjust the clip size.
- start->last = next->last;
- goto crunch;
- }
- }
-
- // There is a fragment after *next.
- R_StoreWallRange (next->last + 1, last);
- // Adjust the clip size.
- start->last = last;
-
- // Remove start+1 to next from the clip list,
- // because start now covers their area.
- crunch:
- if (next == start)
- {
- // Post just extended past the bottom of one post.
- return;
- }
-
-
- 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.
-// Does handle windows,
-// e.g. LineDefs with upper and lower texture.
-//
-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);
- }
-
- // Bottom contained in start?
- if (last <= start->last)
- return;
-
- 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;
- int x2;
- angle_t angle1;
- angle_t angle2;
- angle_t span;
- angle_t tspan;
-
- 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;
-
- // Back side? I.e. backface culling?
- if (span >= ANG180)
- return;
-
- // Global angle needed by segcalc.
- rw_angle1 = angle1;
- angle1 -= viewangle;
- angle2 -= viewangle;
-
- tspan = angle1 + clipangle;
- if (tspan > 2*clipangle)
- {
- tspan -= 2*clipangle;
-
- // Totally off the left edge?
- if (tspan >= span)
- return;
-
- angle1 = clipangle;
- }
- tspan = clipangle - angle2;
- if (tspan > 2*clipangle)
- {
- tspan -= 2*clipangle;
-
- // Totally off the left edge?
- if (tspan >= span)
- return;
- 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];
-
- // Does not cross a pixel?
- if (x1 == x2)
- return;
-
- backsector = line->backsector;
-
- // Single sided line?
- if (!backsector)
- goto clipsolid;
-
- // Closed door.
- if (backsector->ceilingheight <= frontsector->floorheight
- || backsector->floorheight >= frontsector->ceilingheight)
- goto clipsolid;
-
- // Window.
- if (backsector->ceilingheight != frontsector->ceilingheight
- || backsector->floorheight != frontsector->floorheight)
- goto clippass;
-
- // Reject empty lines used for triggers
- // and special events.
- // Identical floor and ceiling on both sides,
- // identical light levels on both sides,
- // and no middle texture.
- 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
-// Checks BSP node/subtree bounding box.
-// 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;
- int boxy;
- int boxpos;
-
- fixed_t x1;
- fixed_t y1;
- fixed_t x2;
- fixed_t y2;
-
- angle_t angle1;
- angle_t angle2;
- angle_t span;
- angle_t tspan;
-
- cliprange_t* start;
-
- int sx1;
- int sx2;
-
- // 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]];
-
- // check clip list for an open space
- angle1 = R_PointToAngle (x1, y1) - viewangle;
- angle2 = R_PointToAngle (x2, y2) - viewangle;
-
- span = angle1 - angle2;
-
- // Sitting on a line?
- if (span >= ANG180)
- return true;
-
- tspan = angle1 + clipangle;
-
- if (tspan > 2*clipangle)
- {
- tspan -= 2*clipangle;
-
- // Totally off the left edge?
- if (tspan >= span)
- return false;
-
- angle1 = clipangle;
- }
- tspan = clipangle - angle2;
- if (tspan > 2*clipangle)
- {
- tspan -= 2*clipangle;
-
- // Totally off the left edge?
- if (tspan >= span)
- return false;
-
- 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];
-
- // Does not cross a pixel.
- if (sx1 == sx2)
- return false;
- sx2--;
-
- start = solidsegs;
- while (start->last < sx2)
- start++;
-
- if (sx1 >= start->first
- && sx2 <= start->last)
- {
- // The clippost contains the new span.
- return false;
- }
-
- return true;
-}
-
-
-
-//
-// R_Subsector
-// Determine floor/ceiling planes.
-// Add sprites of things in sector.
-// Draw one or more line 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
-// Renders all subsectors below a given node,
-// traversing subtree recursively.
-// Just call with BSP root.
-void R_RenderBSPNode (int bspnum)
-{
- node_t* bsp;
- int side;
-
- // Found a subsector?
- if (bspnum & NF_SUBSECTOR)
- {
- if (bspnum == -1)
- R_Subsector (0);
- else
- R_Subsector (bspnum&(~NF_SUBSECTOR));
- return;
- }
-
- bsp = &nodes[bspnum];
-
- // Decide which side the view point is on.
- side = R_PointOnSide (viewx, viewy, bsp);
-
- // Recursively divide front space.
- R_RenderBSPNode (bsp->children[side]);
-
- // Possibly divide back space.
- if (R_CheckBBox (bsp->bbox[side^1]))
- R_RenderBSPNode (bsp->children[side^1]);
-}
-
-
--- a/src/r_bsp.h
+++ /dev/null
@@ -1,69 +1,0 @@
-// Emacs style mode select -*- C++ -*-
-//-----------------------------------------------------------------------------
-//
-// Copyright(C) 1993-1996 Id Software, Inc.
-// Copyright(C) 2005 Simon Howard
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-// 02111-1307, USA.
-//
-// DESCRIPTION:
-// Refresh module, BSP traversal and handling.
-//
-//-----------------------------------------------------------------------------
-
-
-#ifndef __R_BSP__
-#define __R_BSP__
-
-
-
-extern seg_t* curline;
-extern side_t* sidedef;
-extern line_t* linedef;
-extern sector_t* frontsector;
-extern sector_t* backsector;
-
-extern int rw_x;
-extern int rw_stopx;
-
-extern boolean segtextured;
-
-// false if the back side is the same plane
-extern boolean markfloor;
-extern boolean markceiling;
-
-extern boolean skymap;
-
-extern drawseg_t drawsegs[MAXDRAWSEGS];
-extern drawseg_t* ds_p;
-
-extern lighttable_t** hscalelight;
-extern lighttable_t** vscalelight;
-extern lighttable_t** dscalelight;
-
-
-typedef void (*drawfunc_t) (int start, int stop);
-
-
-// BSP?
-void R_ClearClipSegs (void);
-void R_ClearDrawSegs (void);
-
-
-void R_RenderBSPNode (int bspnum);
-
-
-#endif
--- a/src/r_data.c
+++ /dev/null
@@ -1,909 +1,0 @@
-// Emacs style mode select -*- C++ -*-
-//-----------------------------------------------------------------------------
-//
-// Copyright(C) 1993-1996 Id Software, Inc.
-// Copyright(C) 2005 Simon Howard
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-// 02111-1307, USA.
-//
-// DESCRIPTION:
-// Preparation of data for rendering,
-// generation of lookups, caching, retrieval by name.
-//
-//-----------------------------------------------------------------------------
-
-
-
-#include "deh_main.h"
-#include "i_swap.h"
-#include "i_system.h"
-#include "z_zone.h"
-
-
-#include "w_wad.h"
-
-#include "doomdef.h"
-#include "r_local.h"
-#include "p_local.h"
-
-#include "doomstat.h"
-#include "r_sky.h"
-
-
-#include "r_data.h"
-
-//
-// Graphics.
-// DOOM graphics for walls and sprites
-// is stored in vertical runs of opaque pixels (posts).
-// A column is composed of zero or more posts,
-// a patch or sprite is composed of zero or more columns.
-//
-
-
-
-//
-// Texture definition.
-// Each texture is composed of one or more patches,
-// with patches being lumps stored in the WAD.
-// The lumps are referenced by number, and patched
-// into the rectangular texture space using origin
-// and possibly other attributes.
-//
-typedef struct
-{
- short originx;
- short originy;
- short patch;
- short stepdir;
- short colormap;
-} PACKEDATTR mappatch_t;
-
-
-//
-// Texture definition.
-// A DOOM wall texture is a list of patches
-// which are to be combined in a predefined order.
-//
-typedef struct
-{
- char name[8];
- int masked;
- short width;
- short height;
- int obsolete;
- short patchcount;
- mappatch_t patches[1];
-} PACKEDATTR maptexture_t;
-
-
-// A single patch from a texture definition,
-// basically a rectangular area within
-// the texture rectangle.
-typedef struct
-{
- // Block origin (allways UL),
- // which has allready accounted
- // for the internal origin of the patch.
- short originx;
- short originy;
- 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 texture_s texture_t;
-
-struct texture_s
-{
- // Keep name for switch changing, etc.
- char name[8];
- short width;
- short height;
-
- // Index in textures list
-
- int index;
-
- // Next in hash table chain
-
- texture_t *next;
-
- // All the patches[patchcount]
- // are drawn back to front into the cached texture.
- short patchcount;
- texpatch_t patches[1];
-};
-
-
-
-int firstflat;
-int lastflat;
-int numflats;
-
-int firstpatch;
-int lastpatch;
-int numpatches;
-
-int firstspritelump;
-int lastspritelump;
-int numspritelumps;
-
-int numtextures;
-texture_t** textures;
-texture_t** textures_hashtable;
-
-
-int* texturewidthmask;
-// needed for texture pegging
-fixed_t* textureheight;
-int* texturecompositesize;
-short** texturecolumnlump;
-unsigned short** texturecolumnofs;
-byte** texturecomposite;
-
-// for global animation
-int* flattranslation;
-int* texturetranslation;
-
-// needed for pre rendering
-fixed_t* spritewidth;
-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;
- int position;
- byte* source;
- byte* 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
-// Using the texture definition,
-// the composite texture is created from the patches,
-// and each column is cached.
-//
-void R_GenerateComposite (int texnum)
-{
- byte* block;
- texture_t* texture;
- texpatch_t* patch;
- patch_t* realpatch;
- int x;
- int x1;
- int 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;
- i<texture->patchcount;
- 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<x2 ; x++)
- {
- // Column does not have multiple patches?
- if (collump[x] >= 0)
- continue;
-
- 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 in column cache,
- // it is purgable from zone memory.
- Z_ChangeTag (block, PU_CACHE);
-}
-
-
-
-//
-// R_GenerateLookup
-//
-void R_GenerateLookup (int texnum)
-{
- texture_t* texture;
- byte* patchcount; // patchcount[texture->width]
- texpatch_t* patch;
- patch_t* realpatch;
- int x;
- int x1;
- int x2;
- int i;
- short* collump;
- unsigned short* colofs;
-
- texture = textures[texnum];
-
- // Composited texture not created yet.
- texturecomposite[texnum] = 0;
-
- texturecompositesize[texnum] = 0;
- collump = texturecolumnlump[texnum];
- colofs = texturecolumnofs[texnum];
-
- // Now 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 *) Z_Malloc(texture->width, PU_STATIC, &patchcount);
- memset (patchcount, 0, texture->width);
- patch = texture->patches;
-
- for (i=0 , patch = texture->patches;
- i<texture->patchcount;
- 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<x2 ; x++)
- {
- patchcount[x]++;
- collump[x] = patch->patch;
- colofs[x] = LONG(realpatch->columnofs[x-x1])+3;
- }
- }
-
- for (x=0 ; x<texture->width ; 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)
- {
- // Use the cached block.
- collump[x] = -1;
- colofs[x] = texturecompositesize[texnum];
-
- if (texturecompositesize[texnum] > 0x10000-texture->height)
- {
- I_Error ("R_GenerateLookup: texture %i is >64k",
- texnum);
- }
-
- texturecompositesize[texnum] += texture->height;
- }
- }
-
- Z_Free(patchcount);
-}
-
-
-
-
-//
-// R_GetColumn
-//
-byte*
-R_GetColumn
-( int tex,
- int col )
-{
- int lump;
- int 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;
-}
-
-
-static void GenerateTextureHashTable(void)
-{
- int i;
- int key;
-
- textures_hashtable
- = Z_Malloc(sizeof(texture_t *) * numtextures, PU_STATIC, 0);
-
- memset(textures_hashtable, 0, sizeof(texture_t *) * numtextures);
-
- // Add all textures to hash table
-
- for (i=0; i<numtextures; ++i)
- {
- // Store index
-
- textures[i]->index = i;
-
- // Hook into hash table
-
- key = W_LumpNameHash(textures[i]->name) % numtextures;
-
- textures[i]->next = textures_hashtable[key];
- textures_hashtable[key] = textures[i];
- }
-}
-
-
-//
-// 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;
- int j;
-
- int* maptex;
- int* maptex2;
- int* maptex1;
-
- char name[9];
- char* names;
- char* name_p;
-
- int* patchlookup;
-
- int totalwidth;
- int nummappatches;
- int offset;
- int maxoff;
- int maxoff2;
- int numtextures1;
- int numtextures2;
-
- int* directory;
-
- int temp1;
- int temp2;
- int temp3;
-
-
- // Load the patch names from pnames.lmp.
- name[8] = 0;
- names = W_CacheLumpName (DEH_String("PNAMES"), PU_STATIC);
- nummappatches = LONG ( *((int *)names) );
- name_p = names+4;
- patchlookup = Z_Malloc(nummappatches*sizeof(*patchlookup), PU_STATIC, NULL);
-
- for (i=0 ; i<nummappatches ; i++)
- {
- strncpy (name,name_p+i*8, 8);
- patchlookup[i] = W_CheckNumForName (name);
- }
- W_ReleaseLumpName(DEH_String("PNAMES"));
-
- // Load the map texture definitions from textures.lmp.
- // The data is contained in one or two lumps,
- // TEXTURE1 for shareware, plus TEXTURE2 for commercial.
- maptex = maptex1 = W_CacheLumpName (DEH_String("TEXTURE1"), PU_STATIC);
- numtextures1 = LONG(*maptex);
- maxoff = W_LumpLength (W_GetNumForName (DEH_String("TEXTURE1")));
- directory = maptex+1;
-
- if (W_CheckNumForName (DEH_String("TEXTURE2")) != -1)
- {
- maptex2 = W_CacheLumpName (DEH_String("TEXTURE2"), PU_STATIC);
- numtextures2 = LONG(*maptex2);
- maxoff2 = W_LumpLength (W_GetNumForName (DEH_String("TEXTURE2")));
- }
- else
- {
- maptex2 = NULL;
- numtextures2 = 0;
- maxoff2 = 0;
- }
- numtextures = numtextures1 + numtextures2;
-
- textures = Z_Malloc (numtextures * sizeof(*textures), PU_STATIC, 0);
- texturecolumnlump = Z_Malloc (numtextures * sizeof(*texturecolumnlump), PU_STATIC, 0);
- texturecolumnofs = Z_Malloc (numtextures * sizeof(*texturecolumnofs), PU_STATIC, 0);
- texturecomposite = Z_Malloc (numtextures * sizeof(*texturecomposite), PU_STATIC, 0);
- texturecompositesize = Z_Malloc (numtextures * sizeof(*texturecompositesize), PU_STATIC, 0);
- texturewidthmask = Z_Malloc (numtextures * sizeof(*texturewidthmask), PU_STATIC, 0);
- textureheight = Z_Malloc (numtextures * sizeof(*textureheight), PU_STATIC, 0);
-
- totalwidth = 0;
-
- // Really complex printing shit...
- temp1 = W_GetNumForName (DEH_String("S_START")); // P_???????
- temp2 = W_GetNumForName (DEH_String("S_END")) - 1;
- temp3 = ((temp2-temp1+63)/64) + ((numtextures+63)/64);
-
- // If stdout is a real console, use the classic vanilla "filling
- // up the box" effect, which uses backspace to "step back" inside
- // the box. If stdout is a file, don't draw the box.
-
- if (I_ConsoleStdout())
- {
- printf("[");
- for (i = 0; i < temp3 + 9; i++)
- printf(" ");
- printf("]");
- for (i = 0; i < temp3 + 10; i++)
- printf("\b");
- }
-
- for (i=0 ; i<numtextures ; i++, directory++)
- {
- if (!(i&63))
- printf (".");
-
- if (i == numtextures1)
- {
- // Start looking in second texture file.
- maptex = maptex2;
- maxoff = maxoff2;
- directory = maptex+1;
- }
-
- offset = LONG(*directory);
-
- if (offset > 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 ; j<texture->patchcount ; 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*sizeof(**texturecolumnlump), PU_STATIC,0);
- texturecolumnofs[i] = Z_Malloc (texture->width*sizeof(**texturecolumnofs), PU_STATIC,0);
-
- j = 1;
- while (j*2 <= texture->width)
- j<<=1;
-
- texturewidthmask[i] = j-1;
- textureheight[i] = texture->height<<FRACBITS;
-
- totalwidth += texture->width;
- }
-
- Z_Free(patchlookup);
-
- W_ReleaseLumpName(DEH_String("TEXTURE1"));
- if (maptex2)
- W_ReleaseLumpName(DEH_String("TEXTURE2"));
-
- // Precalculate whatever possible.
-
- for (i=0 ; i<numtextures ; i++)
- R_GenerateLookup (i);
-
- // Create translation table for global animation.
- texturetranslation = Z_Malloc ((numtextures+1)*sizeof(*texturetranslation), PU_STATIC, 0);
-
- for (i=0 ; i<numtextures ; i++)
- texturetranslation[i] = i;
-
- GenerateTextureHashTable();
-}
-
-
-
-//
-// R_InitFlats
-//
-void R_InitFlats (void)
-{
- int i;
-
- firstflat = W_GetNumForName (DEH_String("F_START")) + 1;
- lastflat = W_GetNumForName (DEH_String("F_END")) - 1;
- numflats = lastflat - firstflat + 1;
-
- // Create translation table for global animation.
- flattranslation = Z_Malloc ((numflats+1)*sizeof(*flattranslation), PU_STATIC, 0);
-
- for (i=0 ; i<numflats ; i++)
- flattranslation[i] = i;
-}
-
-
-//
-// R_InitSpriteLumps
-// Finds the width and hoffset of all sprites in the wad,
-// so the sprite does not need to be cached completely
-// just for having the header info ready during rendering.
-//
-void R_InitSpriteLumps (void)
-{
- int i;
- patch_t *patch;
-
- firstspritelump = W_GetNumForName (DEH_String("S_START")) + 1;
- lastspritelump = W_GetNumForName (DEH_String("S_END")) - 1;
-
- numspritelumps = lastspritelump - firstspritelump + 1;
- spritewidth = Z_Malloc (numspritelumps*sizeof(*spritewidth), PU_STATIC, 0);
- spriteoffset = Z_Malloc (numspritelumps*sizeof(*spriteoffset), PU_STATIC, 0);
- spritetopoffset = Z_Malloc (numspritelumps*sizeof(*spritetopoffset), PU_STATIC, 0);
-
- for (i=0 ; i< numspritelumps ; i++)
- {
- if (!(i&63))
- printf (".");
-
- patch = W_CacheLumpNum (firstspritelump+i, PU_CACHE);
- spritewidth[i] = SHORT(patch->width)<<FRACBITS;
- spriteoffset[i] = SHORT(patch->leftoffset)<<FRACBITS;
- spritetopoffset[i] = SHORT(patch->topoffset)<<FRACBITS;
- }
-}
-
-
-
-//
-// R_InitColormaps
-//
-void R_InitColormaps (void)
-{
- int lump, length;
-
- // Load in the light tables,
- // 256 byte align tables.
- lump = W_GetNumForName(DEH_String("COLORMAP"));
- length = W_LumpLength (lump);
- colormaps = W_CacheLumpNum(lump, PU_STATIC);
-}
-
-
-
-//
-// R_InitData
-// Locates all the lumps
-// that will be used by all views
-// Must be called after W_Init.
-//
-void R_InitData (void)
-{
- R_InitTextures ();
- printf (".");
- R_InitFlats ();
- printf (".");
- R_InitSpriteLumps ();
- printf (".");
- R_InitColormaps ();
-}
-
-
-
-//
-// R_FlatNumForName
-// Retrieval, get a flat number for a flat name.
-//
-int R_FlatNumForName (char* name)
-{
- int i;
- char namet[9];
-
- i = W_CheckNumForName (name);
-
- if (i == -1)
- {
- namet[8] = 0;
- memcpy (namet, name,8);
- I_Error ("R_FlatNumForName: %s not found",namet);
- }
- return i - firstflat;
-}
-
-
-
-
-//
-// R_CheckTextureNumForName
-// Check whether texture is available.
-// Filter out NoTexture indicator.
-//
-int R_CheckTextureNumForName (char *name)
-{
- texture_t *texture;
- int key;
-
- // "NoTexture" marker.
- if (name[0] == '-')
- return 0;
-
- key = W_LumpNameHash(name) % numtextures;
-
- texture=textures_hashtable[key];
-
- while (texture != NULL)
- {
- if (!strncasecmp (texture->name, name, 8) )
- return texture->index;
-
- texture = texture->next;
- }
-
- return -1;
-}
-
-
-
-//
-// R_TextureNumForName
-// Calls R_CheckTextureNumForName,
-// aborts with error message.
-//
-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 relevant graphics for the level.
-//
-int flatmemory;
-int texturememory;
-int spritememory;
-
-void R_PrecacheLevel (void)
-{
- char* flatpresent;
- char* texturepresent;
- char* spritepresent;
-
- int i;
- int j;
- int k;
- int lump;
-
- texture_t* texture;
- thinker_t* th;
- spriteframe_t* sf;
-
- if (demoplayback)
- return;
-
- // Precache flats.
- flatpresent = Z_Malloc(numflats, PU_STATIC, NULL);
- memset (flatpresent,0,numflats);
-
- for (i=0 ; i<numsectors ; i++)
- {
- flatpresent[sectors[i].floorpic] = 1;
- flatpresent[sectors[i].ceilingpic] = 1;
- }
-
- flatmemory = 0;
-
- for (i=0 ; i<numflats ; i++)
- {
- if (flatpresent[i])
- {
- lump = firstflat + i;
- flatmemory += lumpinfo[lump].size;
- W_CacheLumpNum(lump, PU_CACHE);
- }
- }
-
- Z_Free(flatpresent);
-
- // Precache textures.
- texturepresent = Z_Malloc(numtextures, PU_STATIC, NULL);
- memset (texturepresent,0, numtextures);
-
- for (i=0 ; i<numsides ; i++)
- {
- texturepresent[sides[i].toptexture] = 1;
- texturepresent[sides[i].midtexture] = 1;
- texturepresent[sides[i].bottomtexture] = 1;
- }
-
- // Sky texture is always present.
- // Note that F_SKY1 is the name used to
- // indicate a sky floor/ceiling as a flat,
- // while the sky texture is stored like
- // a wall texture, with an episode dependend
- // name.
- texturepresent[skytexture] = 1;
-
- texturememory = 0;
- for (i=0 ; i<numtextures ; i++)
- {
- if (!texturepresent[i])
- continue;
-
- texture = textures[i];
-
- for (j=0 ; j<texture->patchcount ; j++)
- {
- lump = texture->patches[j].patch;
- texturememory += lumpinfo[lump].size;
- W_CacheLumpNum(lump , PU_CACHE);
- }
- }
-
- Z_Free(texturepresent);
-
- // Precache sprites.
- spritepresent = Z_Malloc(numsprites, PU_STATIC, NULL);
- memset (spritepresent,0, numsprites);
-
- for (th = thinkercap.next ; th != &thinkercap ; th=th->next)
- {
- if (th->function.acp1 == (actionf_p1)P_MobjThinker)
- spritepresent[((mobj_t *)th)->sprite] = 1;
- }
-
- spritememory = 0;
- for (i=0 ; i<numsprites ; i++)
- {
- if (!spritepresent[i])
- continue;
-
- for (j=0 ; j<sprites[i].numframes ; j++)
- {
- sf = &sprites[i].spriteframes[j];
- for (k=0 ; k<8 ; k++)
- {
- lump = firstspritelump + sf->lump[k];
- spritememory += lumpinfo[lump].size;
- W_CacheLumpNum(lump , PU_CACHE);
- }
- }
- }
-
- Z_Free(spritepresent);
-}
-
-
-
-
--- a/src/r_data.h
+++ /dev/null
@@ -1,59 +1,0 @@
-// Emacs style mode select -*- C++ -*-
-//-----------------------------------------------------------------------------
-//
-// Copyright(C) 1993-1996 Id Software, Inc.
-// Copyright(C) 2005 Simon Howard
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-// 02111-1307, USA.
-//
-// DESCRIPTION:
-// Refresh module, data I/O, caching, retrieval of graphics
-// by name.
-//
-//-----------------------------------------------------------------------------
-
-
-#ifndef __R_DATA__
-#define __R_DATA__
-
-#include "r_defs.h"
-#include "r_state.h"
-
-
-// Retrieve column data for span blitting.
-byte*
-R_GetColumn
-( int tex,
- int col );
-
-
-// I/O, setting up the stuff.
-void R_InitData (void);
-void R_PrecacheLevel (void);
-
-
-// Retrieval.
-// Floor/ceiling opaque texture tiles,
-// lookup by name. For animation?
-int R_FlatNumForName (char* name);
-
-
-// Called by P_Ticker for switches and animations,
-// returns the texture number for the texture name.
-int R_TextureNumForName (char *name);
-int R_CheckTextureNumForName (char *name);
-
-#endif
--- a/src/r_defs.h
+++ /dev/null
@@ -1,487 +1,0 @@
-// Emacs style mode select -*- C++ -*-
-//-----------------------------------------------------------------------------
-//
-// Copyright(C) 1993-1996 Id Software, Inc.
-// Copyright(C) 2005 Simon Howard
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-// 02111-1307, USA.
-//
-// DESCRIPTION:
-// Refresh/rendering module, shared data struct definitions.
-//
-//-----------------------------------------------------------------------------
-
-
-#ifndef __R_DEFS__
-#define __R_DEFS__
-
-
-// Screenwidth.
-#include "doomdef.h"
-
-// Some more or less basic data types
-// we depend on.
-#include "m_fixed.h"
-
-// We rely on the thinker data struct
-// to handle sound origins in sectors.
-#include "d_think.h"
-// SECTORS do store MObjs anyway.
-#include "p_mobj.h"
-
-
-
-
-
-
-// Silhouette, needed for clipping Segs (mainly)
-// and sprites representing things.
-#define SIL_NONE 0
-#define SIL_BOTTOM 1
-#define SIL_TOP 2
-#define SIL_BOTH 3
-
-#define MAXDRAWSEGS 256
-
-
-
-
-
-//
-// INTERNAL MAP TYPES
-// used by play and refresh
-//
-
-//
-// Your plain vanilla vertex.
-// Note: transformed values not buffered locally,
-// like some DOOM-alikes ("wt", "WebView") did.
-//
-typedef struct
-{
- fixed_t x;
- fixed_t y;
-
-} vertex_t;
-
-
-// Forward of LineDefs, for Sectors.
-struct line_s;
-
-// Each sector has a degenmobj_t in its center
-// for sound origin purposes.
-// I suppose this does not handle sound from
-// moving objects (doppler), because
-// position is prolly just buffered, not
-// updated.
-typedef struct
-{
- thinker_t thinker; // not used for anything
- fixed_t x;
- fixed_t y;
- fixed_t z;
-
-} degenmobj_t;
-
-//
-// The SECTORS record, at runtime.
-// Stores things/mobjs.
-//
-typedef struct
-{
- fixed_t floorheight;
- fixed_t ceilingheight;
- short floorpic;
- short ceilingpic;
- short lightlevel;
- short special;
- short tag;
-
- // 0 = untraversed, 1,2 = sndlines -1
- int soundtraversed;
-
- // thing that made a sound (or null)
- mobj_t* soundtarget;
-
- // mapblock bounding box for height changes
- int blockbox[4];
-
- // origin for any sounds played by the sector
- degenmobj_t soundorg;
-
- // if == validcount, already checked
- int validcount;
-
- // list of mobjs in sector
- mobj_t* thinglist;
-
- // thinker_t for reversable actions
- void* specialdata;
-
- int linecount;
- struct line_s** lines; // [linecount] size
-
-} sector_t;
-
-
-
-
-//
-// The SideDef.
-//
-
-typedef struct
-{
- // add this to the calculated texture column
- fixed_t textureoffset;
-
- // add this to the calculated texture top
- fixed_t rowoffset;
-
- // Texture indices.
- // We do not maintain names here.
- short toptexture;
- short bottomtexture;
- short midtexture;
-
- // Sector the SideDef is facing.
- sector_t* sector;
-
-} side_t;
-
-
-
-//
-// Move clipping aid for LineDefs.
-//
-typedef enum
-{
- ST_HORIZONTAL,
- ST_VERTICAL,
- ST_POSITIVE,
- ST_NEGATIVE
-
-} slopetype_t;
-
-
-
-typedef struct line_s
-{
- // Vertices, from v1 to v2.
- vertex_t* v1;
- vertex_t* v2;
-
- // Precalculated v2 - v1 for side checking.
- fixed_t dx;
- fixed_t dy;
-
- // Animation related.
- short flags;
- short special;
- short tag;
-
- // Visual appearance: SideDefs.
- // sidenum[1] will be -1 if one sided
- short sidenum[2];
-
- // Neat. Another bounding box, for the extent
- // of the LineDef.
- fixed_t bbox[4];
-
- // To aid move clipping.
- slopetype_t slopetype;
-
- // Front and back sector.
- // Note: redundant? Can be retrieved from SideDefs.
- sector_t* frontsector;
- sector_t* backsector;
-
- // if == validcount, already checked
- int validcount;
-
- // thinker_t for reversable actions
- void* specialdata;
-} line_t;
-
-
-
-
-//
-// A SubSector.
-// References a Sector.
-// Basically, this is a list of LineSegs,
-// indicating the visible walls that define
-// (all or some) sides of a convex BSP leaf.
-//
-typedef struct subsector_s
-{
- sector_t* sector;
- short numlines;
- short firstline;
-
-} subsector_t;
-
-
-
-//
-// The LineSeg.
-//
-typedef struct
-{
- vertex_t* v1;
- vertex_t* v2;
-
- fixed_t offset;
-
- angle_t angle;
-
- side_t* sidedef;
- line_t* linedef;
-
- // Sector references.
- // Could be retrieved from linedef, too.
- // backsector is NULL for one sided lines
- sector_t* frontsector;
- sector_t* backsector;
-
-} seg_t;
-
-
-
-//
-// BSP node.
-//
-typedef struct
-{
- // Partition line.
- fixed_t x;
- fixed_t y;
- fixed_t dx;
- fixed_t dy;
-
- // Bounding box for each child.
- fixed_t bbox[2][4];
-
- // If NF_SUBSECTOR its a subsector.
- unsigned short children[2];
-
-} node_t;
-
-
-
-
-// posts are runs of non masked source pixels
-typedef struct
-{
- byte topdelta; // -1 is the last post in a column
- byte length; // length data bytes follows
-} PACKEDATTR post_t;
-
-// column_t is a list of 0 or more post_t, (byte)-1 terminated
-typedef post_t column_t;
-
-
-
-// PC direct to screen pointers
-//B UNUSED - keep till detailshift in r_draw.c resolved
-//extern byte* destview;
-//extern byte* destscreen;
-
-
-
-
-
-//
-// OTHER TYPES
-//
-
-// This could be wider for >8 bit display.
-// Indeed, true color support is posibble
-// precalculating 24bpp lightmap/colormap LUT.
-// from darkening PLAYPAL to all black.
-// Could even us emore than 32 levels.
-typedef byte lighttable_t;
-
-
-
-
-//
-// ?
-//
-typedef struct drawseg_s
-{
- seg_t* curline;
- int x1;
- int x2;
-
- fixed_t scale1;
- fixed_t scale2;
- fixed_t scalestep;
-
- // 0=none, 1=bottom, 2=top, 3=both
- int silhouette;
-
- // do not clip sprites above this
- fixed_t bsilheight;
-
- // do not clip sprites below this
- fixed_t tsilheight;
-
- // Pointers to lists for sprite clipping,
- // all three adjusted so [x1] is first value.
- short* sprtopclip;
- short* sprbottomclip;
- short* maskedtexturecol;
-
-} drawseg_t;
-
-
-
-// Patches.
-// A patch holds one or more columns.
-// Patches are used for sprites and all masked pictures,
-// and we compose textures from the TEXTURE1/2 lists
-// of patches.
-typedef struct
-{
- short width; // bounding box size
- short height;
- short leftoffset; // pixels to the left of origin
- short topoffset; // pixels below the origin
- int columnofs[8]; // only [width] used
- // the [0] is &columnofs[width]
-} PACKEDATTR patch_t;
-
-
-
-
-
-
-
-// A vissprite_t is a thing
-// that will be drawn during a refresh.
-// I.e. a sprite object that is partly visible.
-typedef struct vissprite_s
-{
- // Doubly linked list.
- struct vissprite_s* prev;
- struct vissprite_s* next;
-
- int x1;
- int x2;
-
- // for line side calculation
- fixed_t gx;
- fixed_t gy;
-
- // global bottom / top for silhouette clipping
- fixed_t gz;
- fixed_t gzt;
-
- // horizontal position of x1
- fixed_t startfrac;
-
- fixed_t scale;
-
- // negative if flipped
- fixed_t xiscale;
-
- fixed_t texturemid;
- int patch;
-
- // for color translation and shadow draw,
- // maxbright frames as well
- lighttable_t* colormap;
-
- int mobjflags;
-
-} vissprite_t;
-
-
-//
-// Sprites are patches with a special naming convention
-// so they can be recognized by R_InitSprites.
-// The base name is NNNNFx or NNNNFxFx, with
-// x indicating the rotation, x = 0, 1-7.
-// 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,
-// thus NNNNF2F5 defines a mirrored patch.
-// Some sprites will only have one picture used
-// for all views: NNNNF0
-//
-typedef struct
-{
- // If false use 0 for any position.
- // Note: as eight entries are available,
- // we might as well insert the same name eight times.
- boolean rotate;
-
- // Lump to use for view angles 0-7.
- short lump[8];
-
- // Flip bit (1 = flip) to use for view angles 0-7.
- byte flip[8];
-
-} spriteframe_t;
-
-
-
-//
-// A sprite definition:
-// a number of animation frames.
-//
-typedef struct
-{
- int numframes;
- spriteframe_t* spriteframes;
-
-} spritedef_t;
-
-
-
-//
-// Now what is a visplane, anyway?
-//
-typedef struct
-{
- fixed_t height;
- int picnum;
- int lightlevel;
- int minx;
- int maxx;
-
- // leave pads for [minx-1]/[maxx+1]
-
- byte pad1;
- // Here lies the rub for all
- // dynamic resize/change of resolution.
- byte top[SCREENWIDTH];
- byte pad2;
- byte pad3;
- // See above.
- byte bottom[SCREENWIDTH];
- byte pad4;
-
-} visplane_t;
-
-
-
-
-#endif
--- a/src/r_draw.c
+++ /dev/null
@@ -1,952 +1,0 @@
-// Emacs style mode select -*- C++ -*-
-//-----------------------------------------------------------------------------
-//
-// Copyright(C) 1993-1996 Id Software, Inc.
-// Copyright(C) 2005 Simon Howard
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-// 02111-1307, USA.
-//
-// DESCRIPTION:
-// The actual span/column drawing functions.
-// Here find the main potential for optimization,
-// e.g. inline assembly, different algorithms.
-//
-//-----------------------------------------------------------------------------
-
-
-
-
-#include "doomdef.h"
-#include "deh_main.h"
-
-#include "i_system.h"
-#include "z_zone.h"
-#include "w_wad.h"
-
-#include "r_local.h"
-
-// Needs access to LFB (guess what).
-#include "v_video.h"
-
-// State.
-#include "doomstat.h"
-
-
-// ?
-#define MAXWIDTH 1120
-#define MAXHEIGHT 832
-
-// status bar height at bottom of screen
-#define SBARHEIGHT 32
-
-//
-// 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.
-// Conveniently, the frame buffer is a linear one,
-// and we need only the base address,
-// and the total size == width*height*depth/8.,
-//
-
-
-byte* viewimage;
-int viewwidth;
-int scaledviewwidth;
-int viewheight;
-int viewwindowx;
-int viewwindowy;
-byte* ylookup[MAXHEIGHT];
-int columnofs[MAXWIDTH];
-
-// Color tables for different players,
-// translate a limited part to another
-// (color ramps used for suit colors).
-//
-byte translations[3][256];
-
-
-
-
-//
-// 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;
-
-// first pixel in a column (possibly virtual)
-byte* dc_source;
-
-// just for profiling
-int dccount;
-
-//
-// A column is a vertical slice/span from a wall texture that,
-// given the DOOM style restrictions on the view orientation,
-// will always have constant z depth.
-// Thus a special case loop for very fast rendering can
-// be used. It has also been used with Wolfenstein 3D.
-//
-void R_DrawColumn (void)
-{
- int count;
- byte* dest;
- fixed_t frac;
- fixed_t fracstep;
-
- count = dc_yh - dc_yl;
-
- // Zero length, column does not exceed a pixel.
- 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
-
- // Framebuffer destination address.
- // Use ylookup LUT to avoid multiply with ScreenWidth.
- // Use columnofs LUT for subwindows?
- dest = ylookup[dc_yl] + columnofs[dc_x];
-
- // Determine scaling,
- // which is the only mapping to be done.
- fracstep = dc_iscale;
- frac = dc_texturemid + (dc_yl-centery)*fracstep;
-
- // Inner loop that does the actual texture mapping,
- // e.g. a DDA-lile scaling.
- // This is as fast as it gets.
- do
- {
- // Re-map color indices from wall texture column
- // using a lighting/special effects LUT.
- *dest = dc_colormap[dc_source[(frac>>FRACBITS)&127]];
-
- dest += SCREENWIDTH;
- frac += fracstep;
-
- } while (count--);
-}
-
-
-
-// UNUSED.
-// Loop unrolled.
-#if 0
-void R_DrawColumn (void)
-{
- int count;
- byte* source;
- byte* dest;
- byte* colormap;
-
- unsigned frac;
- unsigned fracstep;
- unsigned fracstep2;
- unsigned fracstep3;
- unsigned 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
-
-
-void R_DrawColumnLow (void)
-{
- int count;
- byte* dest;
- byte* dest2;
- fixed_t frac;
- fixed_t fracstep;
- int x;
-
- count = dc_yh - dc_yl;
-
- // Zero length.
- 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
- // Blocky mode, need to multiply by 2.
- x = dc_x << 1;
-
- dest = ylookup[dc_yl] + columnofs[x];
- dest2 = ylookup[dc_yl] + columnofs[x+1];
-
- fracstep = dc_iscale;
- frac = dc_texturemid + (dc_yl-centery)*fracstep;
-
- do
- {
- // Hack. Does not work corretly.
- *dest2 = *dest = dc_colormap[dc_source[(frac>>FRACBITS)&127]];
- dest += SCREENWIDTH;
- dest2 += SCREENWIDTH;
- frac += fracstep;
-
- } while (count--);
-}
-
-
-//
-// Spectre/Invisibility.
-//
-#define FUZZTABLE 50
-#define FUZZOFF (SCREENWIDTH)
-
-
-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;
-
-
-//
-// Framebuffer postprocessing.
-// Creates a fuzzy image by copying pixels
-// from adjacent ones to left and right.
-// Used with an all black colormap, this
-// could create the SHADOW effect,
-// i.e. spectres and invisible players.
-//
-void R_DrawFuzzColumn (void)
-{
- int count;
- byte* dest;
- fixed_t frac;
- fixed_t fracstep;
-
- // Adjust borders. Low...
- if (!dc_yl)
- dc_yl = 1;
-
- // .. and high.
- if (dc_yh == viewheight-1)
- dc_yh = viewheight - 2;
-
- count = dc_yh - dc_yl;
-
- // Zero length.
- 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
-
- dest = ylookup[dc_yl] + columnofs[dc_x];
-
- // Looks familiar.
- fracstep = dc_iscale;
- frac = dc_texturemid + (dc_yl-centery)*fracstep;
-
- // Looks like an attempt at dithering,
- // using the colormap #6 (of 0-31, a bit
- // brighter than average).
- do
- {
- // Lookup framebuffer, and retrieve
- // a pixel that is either one column
- // left or right of the current one.
- // Add index from colormap to index.
- *dest = colormaps[6*256+dest[fuzzoffset[fuzzpos]]];
-
- // Clamp table lookup index.
- if (++fuzzpos == FUZZTABLE)
- fuzzpos = 0;
-
- dest += SCREENWIDTH;
-
- frac += fracstep;
- } while (count--);
-}
-
-// low detail mode version
-
-void R_DrawFuzzColumnLow (void)
-{
- int count;
- byte* dest;
- byte* dest2;
- fixed_t frac;
- fixed_t fracstep;
- int x;
-
- // Adjust borders. Low...
- if (!dc_yl)
- dc_yl = 1;
-
- // .. and high.
- if (dc_yh == viewheight-1)
- dc_yh = viewheight - 2;
-
- count = dc_yh - dc_yl;
-
- // Zero length.
- if (count < 0)
- return;
-
- // low detail mode, need to multiply by 2
-
- x = dc_x << 1;
-
-#ifdef RANGECHECK
- if ((unsigned)x >= SCREENWIDTH
- || dc_yl < 0 || dc_yh >= SCREENHEIGHT)
- {
- I_Error ("R_DrawFuzzColumn: %i to %i at %i",
- dc_yl, dc_yh, dc_x);
- }
-#endif
-
- dest = ylookup[dc_yl] + columnofs[x];
- dest2 = ylookup[dc_yl] + columnofs[x+1];
-
- // Looks familiar.
- fracstep = dc_iscale;
- frac = dc_texturemid + (dc_yl-centery)*fracstep;
-
- // Looks like an attempt at dithering,
- // using the colormap #6 (of 0-31, a bit
- // brighter than average).
- do
- {
- // Lookup framebuffer, and retrieve
- // a pixel that is either one column
- // left or right of the current one.
- // Add index from colormap to index.
- *dest = colormaps[6*256+dest[fuzzoffset[fuzzpos]]];
- *dest2 = colormaps[6*256+dest2[fuzzoffset[fuzzpos]]];
-
- // Clamp table lookup index.
- if (++fuzzpos == FUZZTABLE)
- fuzzpos = 0;
-
- dest += SCREENWIDTH;
- dest2 += SCREENWIDTH;
-
- frac += fracstep;
- } while (count--);
-}
-
-
-
-
-
-//
-// R_DrawTranslatedColumn
-// Used to draw player sprites
-// with the green colorramp mapped to others.
-// Could be used with different translation
-// tables, e.g. the lighter colored version
-// of the BaronOfHell, the HellKnight, uses
-// identical sprites, kinda brightened up.
-//
-byte* dc_translation;
-byte* translationtables;
-
-void R_DrawTranslatedColumn (void)
-{
- int count;
- byte* dest;
- fixed_t frac;
- fixed_t 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];
-
- // Looks familiar.
- fracstep = dc_iscale;
- frac = dc_texturemid + (dc_yl-centery)*fracstep;
-
- // Here we do an additional index re-mapping.
- do
- {
- // Translation tables are used
- // to map certain colorramps to other ones,
- // used with PLAY sprites.
- // Thus the "green" ramp of the player 0 sprite
- // is mapped to gray, red, black/indigo.
- *dest = dc_colormap[dc_translation[dc_source[frac>>FRACBITS]]];
- dest += SCREENWIDTH;
-
- frac += fracstep;
- } while (count--);
-}
-
-void R_DrawTranslatedColumnLow (void)
-{
- int count;
- byte* dest;
- byte* dest2;
- fixed_t frac;
- fixed_t fracstep;
- int x;
-
- count = dc_yh - dc_yl;
- if (count < 0)
- return;
-
- // low detail, need to scale by 2
- x = dc_x << 1;
-
-#ifdef RANGECHECK
- if ((unsigned)x >= SCREENWIDTH
- || dc_yl < 0
- || dc_yh >= SCREENHEIGHT)
- {
- I_Error ( "R_DrawColumn: %i to %i at %i",
- dc_yl, dc_yh, x);
- }
-
-#endif
-
-
- dest = ylookup[dc_yl] + columnofs[x];
- dest2 = ylookup[dc_yl] + columnofs[x+1];
-
- // Looks familiar.
- fracstep = dc_iscale;
- frac = dc_texturemid + (dc_yl-centery)*fracstep;
-
- // Here we do an additional index re-mapping.
- do
- {
- // Translation tables are used
- // to map certain colorramps to other ones,
- // used with PLAY sprites.
- // Thus the "green" ramp of the player 0 sprite
- // is mapped to gray, red, black/indigo.
- *dest = dc_colormap[dc_translation[dc_source[frac>>FRACBITS]]];
- *dest2 = dc_colormap[dc_translation[dc_source[frac>>FRACBITS]]];
- dest += SCREENWIDTH;
- dest2 += SCREENWIDTH;
-
- frac += fracstep;
- } while (count--);
-}
-
-
-
-
-//
-// R_InitTranslationTables
-// Creates the translation tables to map
-// the green color ramp to gray, brown, red.
-// Assumes a given structure of the PLAYPAL.
-// Could be read from a lump instead.
-//
-void R_InitTranslationTables (void)
-{
- int i;
-
- translationtables = Z_Malloc (256*3, PU_STATIC, 0);
-
- // translate just the 16 green colors
- for (i=0 ; i<256 ; i++)
- {
- if (i >= 0x70 && i<= 0x7f)
- {
- // map green ramp to gray, brown, red
- translationtables[i] = 0x60 + (i&0xf);
- translationtables [i+256] = 0x40 + (i&0xf);
- translationtables [i+512] = 0x20 + (i&0xf);
- }
- else
- {
- // Keep all other colors as is.
- translationtables[i] = translationtables[i+256]
- = translationtables[i+512] = i;
- }
- }
-}
-
-
-
-
-//
-// R_DrawSpan
-// With DOOM style restrictions on view orientation,
-// the floors and ceilings consist of horizontal slices
-// or spans with constant z depth.
-// However, rotation around the world z axis is possible,
-// thus this mapping, while simpler and faster than
-// perspective correct texture mapping, has to traverse
-// the texture at an angle in all but a few cases.
-// In consequence, flats are not stored by column (like walls),
-// and the inner loop has to step in texture space u and v.
-//
-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;
-
-// start of a 64*64 tile image
-byte* ds_source;
-
-// just for profiling
-int dscount;
-
-
-//
-// Draws the actual span.
-void R_DrawSpan (void)
-{
- fixed_t xfrac;
- fixed_t yfrac;
- byte* dest;
- int count;
- int 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];
-
- // We do not check for zero spans here?
- count = ds_x2 - ds_x1;
-
- do
- {
- // Current texture index in u,v.
- spot = ((yfrac>>(16-6))&(63*64)) + ((xfrac>>16)&63);
-
- // Lookup pixel from flat texture tile,
- // re-index using light/colormap.
- *dest++ = ds_colormap[ds_source[spot]];
-
- // Next step in u,v.
- xfrac += ds_xstep;
- yfrac += ds_ystep;
-
- } while (count--);
-}
-
-
-
-// UNUSED.
-// Loop unrolled by 4.
-#if 0
-void R_DrawSpan (void)
-{
- unsigned position, step;
-
- byte* source;
- byte* colormap;
- byte* dest;
-
- unsigned count;
- usingned spot;
- unsigned value;
- unsigned temp;
- unsigned xtemp;
- unsigned 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
-
-
-//
-// Again..
-//
-void R_DrawSpanLow (void)
-{
- fixed_t xfrac;
- fixed_t yfrac;
- byte* dest;
- int count;
- int 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;
-
- count = (ds_x2 - ds_x1);
-
- // Blocky mode, need to multiply by 2.
- ds_x1 <<= 1;
- ds_x2 <<= 1;
-
- dest = ylookup[ds_y] + columnofs[ds_x1];
-
- do
- {
- spot = ((yfrac>>(16-6))&(63*64)) + ((xfrac>>16)&63);
- // Lowres/blocky mode does it twice,
- // while scale is adjusted appropriately.
- *dest++ = ds_colormap[ds_source[spot]];
- *dest++ = ds_colormap[ds_source[spot]];
-
- xfrac += ds_xstep;
- yfrac += ds_ystep;
-
- } while (count--);
-}
-
-//
-// R_InitBuffer
-// Creats lookup tables that avoid
-// multiplies and other hazzles
-// for getting the framebuffer address
-// of a pixel to draw.
-//
-void
-R_InitBuffer
-( int width,
- int height )
-{
- int i;
-
- // Handle resize,
- // e.g. smaller view windows
- // with border and/or status bar.
- viewwindowx = (SCREENWIDTH-width) >> 1;
-
- // Column offset. For windows.
- for (i=0 ; i<width ; i++)
- columnofs[i] = viewwindowx + i;
-
- // Samw with base row offset.
- if (width == SCREENWIDTH)
- viewwindowy = 0;
- else
- viewwindowy = (SCREENHEIGHT-SBARHEIGHT-height) >> 1;
-
- // Preclaculate all row offsets.
- for (i=0 ; i<height ; i++)
- ylookup[i] = screens[0] + (i+viewwindowy)*SCREENWIDTH;
-}
-
-
-
-
-//
-// R_FillBackScreen
-// Fills the back screen with a pattern
-// for variable screen sizes
-// Also draws a beveled edge.
-//
-void R_FillBackScreen (void)
-{
- byte* src;
- byte* dest;
- int x;
- int y;
- patch_t* patch;
-
- // DOOM border patch.
- char *name1 = DEH_String("FLOOR7_2");
-
- // DOOM II border patch.
- char *name2 = DEH_String("GRNROCK");
-
- char* name;
-
- if (scaledviewwidth == 320)
- return;
-
- if ( gamemode == commercial)
- name = name2;
- else
- name = name1;
-
- src = W_CacheLumpName (name, PU_CACHE);
- dest = screens[1];
-
- for (y=0 ; y<SCREENHEIGHT-SBARHEIGHT ; y++)
- {
- for (x=0 ; x<SCREENWIDTH/64 ; x++)
- {
- memcpy (dest, src+((y&63)<<6), 64);
- dest += 64;
- }
-
- if (SCREENWIDTH&63)
- {
- memcpy (dest, src+((y&63)<<6), SCREENWIDTH&63);
- dest += (SCREENWIDTH&63);
- }
- }
-
- patch = W_CacheLumpName (DEH_String("brdr_t"),PU_CACHE);
-
- for (x=0 ; x<scaledviewwidth ; x+=8)
- V_DrawPatch (viewwindowx+x,viewwindowy-8,1,patch);
- patch = W_CacheLumpName (DEH_String("brdr_b"),PU_CACHE);
-
- for (x=0 ; x<scaledviewwidth ; x+=8)
- V_DrawPatch (viewwindowx+x,viewwindowy+viewheight,1,patch);
- patch = W_CacheLumpName (DEH_String("brdr_l"),PU_CACHE);
-
- for (y=0 ; y<viewheight ; y+=8)
- V_DrawPatch (viewwindowx-8,viewwindowy+y,1,patch);
- patch = W_CacheLumpName (DEH_String("brdr_r"),PU_CACHE);
-
- for (y=0 ; y<viewheight ; y+=8)
- V_DrawPatch (viewwindowx+scaledviewwidth,viewwindowy+y,1,patch);
-
-
- // Draw beveled edge.
- V_DrawPatch (viewwindowx-8,
- viewwindowy-8,
- 1,
- W_CacheLumpName (DEH_String("brdr_tl"),PU_CACHE));
-
- V_DrawPatch (viewwindowx+scaledviewwidth,
- viewwindowy-8,
- 1,
- W_CacheLumpName (DEH_String("brdr_tr"),PU_CACHE));
-
- V_DrawPatch (viewwindowx-8,
- viewwindowy+viewheight,
- 1,
- W_CacheLumpName (DEH_String("brdr_bl"),PU_CACHE));
-
- V_DrawPatch (viewwindowx+scaledviewwidth,
- viewwindowy+viewheight,
- 1,
- W_CacheLumpName (DEH_String("brdr_br"),PU_CACHE));
-}
-
-
-//
-// Copy a screen buffer.
-//
-void
-R_VideoErase
-( unsigned ofs,
- int count )
-{
- // LFB copy.
- // This might not be a good idea if memcpy
- // is not optiomal, e.g. byte by byte on
- // a 32bit CPU, as GNU GCC/Linux libc did
- // at one point.
- memcpy (screens[0]+ofs, screens[1]+ofs, count);
-}
-
-
-//
-// 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;
- int side;
- int ofs;
- int 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 ; i<viewheight ; i++)
- {
- R_VideoErase (ofs, side);
- ofs += SCREENWIDTH;
- }
-
- // ?
- V_MarkRect (0,0,SCREENWIDTH, SCREENHEIGHT-SBARHEIGHT);
-}
-
-
--- a/src/r_draw.h
+++ /dev/null
@@ -1,112 +1,0 @@
-// Emacs style mode select -*- C++ -*-
-//-----------------------------------------------------------------------------
-//
-// Copyright(C) 1993-1996 Id Software, Inc.
-// Copyright(C) 2005 Simon Howard
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-// 02111-1307, USA.
-//
-// DESCRIPTION:
-// System specific interface stuff.
-//
-//-----------------------------------------------------------------------------
-
-
-#ifndef __R_DRAW__
-#define __R_DRAW__
-
-
-
-
-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;
-
-// first pixel in a column
-extern byte* dc_source;
-
-
-// The span blitting interface.
-// Hook in assembler or system specific BLT
-// here.
-void R_DrawColumn (void);
-void R_DrawColumnLow (void);
-
-// The Spectre/Invisibility effect.
-void R_DrawFuzzColumn (void);
-void R_DrawFuzzColumnLow (void);
-
-// Draw with color translation tables,
-// for player sprite rendering,
-// Green/Red/Blue/Indigo shirts.
-void R_DrawTranslatedColumn (void);
-void R_DrawTranslatedColumnLow (void);
-
-void
-R_VideoErase
-( unsigned ofs,
- int count );
-
-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;
-
-// start of a 64*64 tile image
-extern byte* ds_source;
-
-extern byte* translationtables;
-extern byte* dc_translation;
-
-
-// Span blitting for rows, floor/ceiling.
-// No Sepctre effect needed.
-void R_DrawSpan (void);
-
-// Low resolution mode, 160x200?
-void R_DrawSpanLow (void);
-
-
-void
-R_InitBuffer
-( int width,
- int height );
-
-
-// Initialize color translation tables,
-// for player rendering etc.
-void R_InitTranslationTables (void);
-
-
-
-// Rendering function.
-void R_FillBackScreen (void);
-
-// If the view size is not full screen, draws a border around it.
-void R_DrawViewBorder (void);
-
-
-
-#endif
--- a/src/r_local.h
+++ /dev/null
@@ -1,53 +1,0 @@
-// Emacs style mode select -*- C++ -*-
-//-----------------------------------------------------------------------------
-//
-// Copyright(C) 1993-1996 Id Software, Inc.
-// Copyright(C) 2005 Simon Howard
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-// 02111-1307, USA.
-//
-// DESCRIPTION:
-// Refresh (R_*) module, global header.
-// All the rendering/drawing stuff is here.
-//
-//-----------------------------------------------------------------------------
-
-#ifndef __R_LOCAL__
-#define __R_LOCAL__
-
-// Binary Angles, sine/cosine/atan lookups.
-#include "tables.h"
-
-// Screen size related parameters.
-#include "doomdef.h"
-
-// Include the refresh/render data structs.
-#include "r_data.h"
-
-
-
-//
-// Separate header file for each module.
-//
-#include "r_main.h"
-#include "r_bsp.h"
-#include "r_segs.h"
-#include "r_plane.h"
-#include "r_data.h"
-#include "r_things.h"
-#include "r_draw.h"
-
-#endif // __R_LOCAL__
--- a/src/r_main.c
+++ /dev/null
@@ -1,910 +1,0 @@
-// Emacs style mode select -*- C++ -*-
-//-----------------------------------------------------------------------------
-//
-// Copyright(C) 1993-1996 Id Software, Inc.
-// Copyright(C) 2005 Simon Howard
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-// 02111-1307, USA.
-//
-// DESCRIPTION:
-// Rendering main loop and setup functions,
-// utility functions (BSP, geometry, trigonometry).
-// See tables.c, too.
-//
-//-----------------------------------------------------------------------------
-
-
-
-
-
-#include <stdlib.h>
-#include <math.h>
-
-
-#include "doomdef.h"
-#include "d_net.h"
-
-#include "m_bbox.h"
-#include "m_menu.h"
-
-#include "r_local.h"
-#include "r_sky.h"
-
-
-
-
-
-// Fineangles in the SCREENWIDTH wide window.
-#define FIELDOFVIEW 2048
-
-
-
-int viewangleoffset;
-
-// increment every time a check is made
-int validcount = 1;
-
-
-lighttable_t* fixedcolormap;
-extern lighttable_t** walllights;
-
-int centerx;
-int centery;
-
-fixed_t centerxfrac;
-fixed_t centeryfrac;
-fixed_t projection;
-
-// just for profiling purposes
-int framecount;
-
-int sscount;
-int linecount;
-int loopcount;
-
-fixed_t viewx;
-fixed_t viewy;
-fixed_t viewz;
-
-angle_t viewangle;
-
-fixed_t viewcos;
-fixed_t viewsin;
-
-player_t* viewplayer;
-
-// 0 = high, 1 = low
-int detailshift;
-
-//
-// 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];
-
-
-// UNUSED.
-// The finetangentgent[angle+FINEANGLES/4] table
-// holds the fixed_t tangent values for view angles,
-// ranging from INT_MIN to 0 to INT_MAX.
-// fixed_t finetangent[FINEANGLES/2];
-
-// fixed_t finesine[5*FINEANGLES/4];
-const fixed_t* finecosine = &finesine[FINEANGLES/4];
-
-
-lighttable_t* scalelight[LIGHTLEVELS][MAXLIGHTSCALE];
-lighttable_t* scalelightfixed[MAXLIGHTSCALE];
-lighttable_t* zlight[LIGHTLEVELS][MAXLIGHTZ];
-
-// bumped light from gun blasts
-int extralight;
-
-
-
-void (*colfunc) (void);
-void (*basecolfunc) (void);
-void (*fuzzcolfunc) (void);
-void (*transcolfunc) (void);
-void (*spanfunc) (void);
-
-
-
-//
-// R_AddPointToBox
-// Expand a given bbox
-// so that it encloses a given point.
-//
-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
-// Traverse BSP (sub) tree,
-// check point against partition plane.
-// Returns side 0 (front) or 1 (back).
-//
-int
-R_PointOnSide
-( fixed_t x,
- fixed_t y,
- node_t* node )
-{
- fixed_t dx;
- fixed_t dy;
- fixed_t left;
- fixed_t 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 )
- {
- // (left is negative)
- return 1;
- }
- return 0;
- }
-
- left = FixedMul ( node->dy>>FRACBITS , dx );
- right = FixedMul ( dy , node->dx>>FRACBITS );
-
- if (right < left)
- {
- // front side
- return 0;
- }
- // back side
- return 1;
-}
-
-
-int
-R_PointOnSegSide
-( fixed_t x,
- fixed_t y,
- seg_t* line )
-{
- fixed_t lx;
- fixed_t ly;
- fixed_t ldx;
- fixed_t ldy;
- fixed_t dx;
- fixed_t dy;
- fixed_t left;
- fixed_t 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 )
- {
- // (left is negative)
- return 1;
- }
- return 0;
- }
-
- left = FixedMul ( ldy>>FRACBITS , dx );
- right = FixedMul ( dy , ldx>>FRACBITS );
-
- if (right < left)
- {
- // front side
- return 0;
- }
- // back side
- return 1;
-}
-
-
-//
-// 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.
-
-//
-
-
-
-
-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)
- {
- // octant 0
- return tantoangle[ SlopeDiv(y,x)];
- }
- else
- {
- // octant 1
- return ANG90-1-tantoangle[ SlopeDiv(x,y)];
- }
- }
- else
- {
- // y<0
- y = -y;
-
- if (x>y)
- {
- // octant 8
- return -tantoangle[SlopeDiv(y,x)];
- }
- else
- {
- // octant 7
- return ANG270+tantoangle[ SlopeDiv(x,y)];
- }
- }
- }
- else
- {
- // x<0
- x = -x;
-
- if (y>= 0)
- {
- // y>= 0
- if (x>y)
- {
- // octant 3
- return ANG180-1-tantoangle[ SlopeDiv(y,x)];
- }
- else
- {
- // octant 2
- return ANG90+ tantoangle[ SlopeDiv(x,y)];
- }
- }
- else
- {
- // y<0
- y = -y;
-
- if (x>y)
- {
- // octant 4
- return ANG180+tantoangle[ SlopeDiv(y,x)];
- }
- else
- {
- // octant 5
- return ANG270-1-tantoangle[ SlopeDiv(x,y)];
- }
- }
- }
- 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;
- fixed_t dy;
- fixed_t temp;
- fixed_t dist;
- fixed_t frac;
-
- dx = abs(x - viewx);
- dy = abs(y - viewy);
-
- if (dy>dx)
- {
- temp = dx;
- dx = dy;
- dy = temp;
- }
-
- // Fix crashes in udm1.wad
-
- if (dx != 0)
- {
- frac = FixedDiv(dy, dx);
- }
- else
- {
- frac = 0;
- }
-
- angle = (tantoangle[frac>>DBITS]+ANG90) >> ANGLETOFINESHIFT;
-
- // use as cosine
- dist = FixedDiv (dx, finesine[angle] );
-
- return dist;
-}
-
-
-
-
-//
-// R_InitPointToAngle
-//
-void R_InitPointToAngle (void)
-{
- // UNUSED - 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 (horizontal span)
-// at the given angle.
-// rw_distance must be calculated first.
-//
-fixed_t R_ScaleFromGlobalAngle (angle_t visangle)
-{
- fixed_t scale;
- angle_t anglea;
- angle_t angleb;
- int sinea;
- int sineb;
- fixed_t num;
- int den;
-
- // UNUSED
-#if 0
-{
- fixed_t dist;
- fixed_t z;
- fixed_t sinv;
- fixed_t 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);
-
- // both sines are allways positive
- sinea = finesine[anglea>>ANGLETOFINESHIFT];
- sineb = finesine[angleb>>ANGLETOFINESHIFT];
- num = FixedMul(projection,sineb)<<detailshift;
- den = FixedMul(rw_distance,sinea);
-
- if (den > 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)
-{
- // UNUSED: now getting from tables.c
-#if 0
- int i;
- float a;
- float fv;
- int t;
-
- // viewangle tangent table
- for (i=0 ; i<FINEANGLES/2 ; i++)
- {
- a = (i-FINEANGLES/4+0.5)*PI*2/FINEANGLES;
- fv = FRACUNIT*tan (a);
- t = fv;
- finetangent[i] = t;
- }
-
- // finesine table
- for (i=0 ; i<5*FINEANGLES/4 ; i++)
- {
- // OPTIMIZE: mirror...
- a = (i+0.5)*PI*2/FINEANGLES;
- t = FRACUNIT*sin (a);
- finesine[i] = t;
- }
-#endif
-
-}
-
-
-
-//
-// R_InitTextureMapping
-//
-void R_InitTextureMapping (void)
-{
- int i;
- int x;
- int t;
- fixed_t focallength;
-
- // Use tangent table to generate viewangletox:
- // viewangletox will give the next greatest x
- // after the view angle.
- //
- // Calc focallength
- // so FIELDOFVIEW angles covers SCREENWIDTH.
- focallength = FixedDiv (centerxfrac,
- finetangent[FINEANGLES/4+FIELDOFVIEW/2] );
-
- for (i=0 ; i<FINEANGLES/2 ; i++)
- {
- if (finetangent[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 xtoviewangle[]:
- // 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<<ANGLETOFINESHIFT)-ANG90;
- }
-
- // Take out the fencepost cases from viewangletox.
- for (i=0 ; i<FINEANGLES/2 ; i++)
- {
- t = FixedMul (finetangent[i], focallength);
- t = centerx - t;
-
- if (viewangletox[i] == -1)
- viewangletox[i] = 0;
- else if (viewangletox[i] == viewwidth+1)
- viewangletox[i] = viewwidth;
- }
-
- clipangle = xtoviewangle[0];
-}
-
-
-
-//
-// R_InitLightTables
-// Only inits the zlight table,
-// because the scalelight table changes with view size.
-//
-#define DISTMAP 2
-
-void R_InitLightTables (void)
-{
- int i;
- int j;
- int level;
- int startmap;
- int scale;
-
- // Calculate the light levels to use
- // for each level / distance combination.
- for (i=0 ; i< LIGHTLEVELS ; i++)
- {
- startmap = ((LIGHTLEVELS-1-i)*2)*NUMCOLORMAPS/LIGHTLEVELS;
- for (j=0 ; j<MAXLIGHTZ ; j++)
- {
- scale = FixedDiv ((SCREENWIDTH/2*FRACUNIT), (j+1)<<LIGHTZSHIFT);
- scale >>= LIGHTSCALESHIFT;
- level = startmap - scale/DISTMAP;
-
- if (level < 0)
- level = 0;
-
- if (level >= NUMCOLORMAPS)
- level = NUMCOLORMAPS-1;
-
- zlight[i][j] = colormaps + level*256;
- }
- }
-}
-
-
-
-//
-// R_SetViewSize
-// Do not really change anything here,
-// because it might be in the middle of a refresh.
-// The change will take effect next refresh.
-//
-boolean setsizeneeded;
-int setblocks;
-int setdetail;
-
-
-void
-R_SetViewSize
-( int blocks,
- int detail )
-{
- setsizeneeded = true;
- setblocks = blocks;
- setdetail = detail;
-}
-
-
-//
-// R_ExecuteSetViewSize
-//
-void R_ExecuteSetViewSize (void)
-{
- fixed_t cosadj;
- fixed_t dy;
- int i;
- int j;
- int level;
- int 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<<FRACBITS;
- centeryfrac = centery<<FRACBITS;
- projection = centerxfrac;
-
- if (!detailshift)
- {
- colfunc = basecolfunc = R_DrawColumn;
- fuzzcolfunc = R_DrawFuzzColumn;
- transcolfunc = R_DrawTranslatedColumn;
- spanfunc = R_DrawSpan;
- }
- else
- {
- colfunc = basecolfunc = R_DrawColumnLow;
- fuzzcolfunc = R_DrawFuzzColumnLow;
- transcolfunc = R_DrawTranslatedColumnLow;
- spanfunc = R_DrawSpanLow;
- }
-
- R_InitBuffer (scaledviewwidth, viewheight);
-
- R_InitTextureMapping ();
-
- // psprite scales
- pspritescale = FRACUNIT*viewwidth/SCREENWIDTH;
- pspriteiscale = FRACUNIT*SCREENWIDTH/viewwidth;
-
- // thing clipping
- for (i=0 ; i<viewwidth ; i++)
- screenheightarray[i] = viewheight;
-
- // planes
- for (i=0 ; i<viewheight ; i++)
- {
- dy = ((i-viewheight/2)<<FRACBITS)+FRACUNIT/2;
- dy = abs(dy);
- yslope[i] = FixedDiv ( (viewwidth<<detailshift)/2*FRACUNIT, dy);
- }
-
- for (i=0 ; i<viewwidth ; i++)
- {
- cosadj = abs(finecosine[xtoviewangle[i]>>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<MAXLIGHTSCALE ; j++)
- {
- level = startmap - j*SCREENWIDTH/(viewwidth<<detailshift)/DISTMAP;
-
- if (level < 0)
- level = 0;
-
- if (level >= NUMCOLORMAPS)
- level = NUMCOLORMAPS-1;
-
- scalelight[i][j] = colormaps + level*256;
- }
- }
-}
-
-
-
-//
-// R_Init
-//
-
-
-
-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 ();
- R_InitTranslationTables ();
- printf (".");
-
- framecount = 0;
-}
-
-
-//
-// R_PointInSubsector
-//
-subsector_t*
-R_PointInSubsector
-( fixed_t x,
- fixed_t y )
-{
- node_t* node;
- int side;
- int nodenum;
-
- // single subsector is a special case
- if (!numnodes)
- 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;
-
- viewplayer = player;
- viewx = player->mo->x;
- viewy = player->mo->y;
- viewangle = player->mo->angle + viewangleoffset;
- extralight = player->extralight;
-
- viewz = player->viewz;
-
- 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<MAXLIGHTSCALE ; i++)
- scalelightfixed[i] = fixedcolormap;
- }
- else
- fixedcolormap = 0;
-
- framecount++;
- validcount++;
-}
-
-
-
-//
-// R_RenderView
-//
-void R_RenderPlayerView (player_t* player)
-{
- R_SetupFrame (player);
-
- // Clear buffers.
- R_ClearClipSegs ();
- R_ClearDrawSegs ();
- R_ClearPlanes ();
- R_ClearSprites ();
-
- // check for new console commands.
- NetUpdate ();
-
- // The head node is the last node output.
- R_RenderBSPNode (numnodes-1);
-
- // Check for new console commands.
- NetUpdate ();
-
- R_DrawPlanes ();
-
- // Check for new console commands.
- NetUpdate ();
-
- R_DrawMasked ();
-
- // Check for new console commands.
- NetUpdate ();
-}
--- a/src/r_main.h
+++ /dev/null
@@ -1,170 +1,0 @@
-// Emacs style mode select -*- C++ -*-
-//-----------------------------------------------------------------------------
-//
-// Copyright(C) 1993-1996 Id Software, Inc.
-// Copyright(C) 2005 Simon Howard
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-// 02111-1307, USA.
-//
-// DESCRIPTION:
-// System specific interface stuff.
-//
-//-----------------------------------------------------------------------------
-
-
-#ifndef __R_MAIN__
-#define __R_MAIN__
-
-#include "d_player.h"
-#include "r_data.h"
-
-
-
-
-//
-// POV related.
-//
-extern fixed_t viewcos;
-extern fixed_t viewsin;
-
-extern int viewwidth;
-extern int viewheight;
-extern int viewwindowx;
-extern int viewwindowy;
-
-
-
-extern int centerx;
-extern int centery;
-
-extern fixed_t centerxfrac;
-extern fixed_t centeryfrac;
-extern fixed_t projection;
-
-extern int validcount;
-
-extern int linecount;
-extern int loopcount;
-
-
-//
-// Lighting LUT.
-// Used for z-depth cuing per column/row,
-// and other lighting effects (sector ambient, flash).
-//
-
-// Lighting constants.
-// Now why not 32 levels here?
-#define LIGHTLEVELS 16
-#define LIGHTSEGSHIFT 4
-
-#define MAXLIGHTSCALE 48
-#define LIGHTSCALESHIFT 12
-#define MAXLIGHTZ 128
-#define LIGHTZSHIFT 20
-
-extern lighttable_t* scalelight[LIGHTLEVELS][MAXLIGHTSCALE];
-extern lighttable_t* scalelightfixed[MAXLIGHTSCALE];
-extern lighttable_t* zlight[LIGHTLEVELS][MAXLIGHTZ];
-
-extern int extralight;
-extern lighttable_t* fixedcolormap;
-
-
-// Number of diminishing brightness levels.
-// There a 0-31, i.e. 32 LUT in the COLORMAP lump.
-#define NUMCOLORMAPS 32
-
-
-// Blocky/low detail mode.
-//B remove this?
-// 0 = high, 1 = low
-extern int detailshift;
-
-
-//
-// Function pointers to switch refresh/drawing functions.
-// Used to select shadow mode etc.
-//
-extern void (*colfunc) (void);
-extern void (*transcolfunc) (void);
-extern void (*basecolfunc) (void);
-extern void (*fuzzcolfunc) (void);
-// No shadow effects on floors.
-extern void (*spanfunc) (void);
-
-
-//
-// Utility functions.
-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 );
-
-
-
-//
-// REFRESH - the actual rendering functions.
-//
-
-// Called by G_Drawer.
-void R_RenderPlayerView (player_t *player);
-
-// Called by startup code.
-void R_Init (void);
-
-// Called by M_Responder.
-void R_SetViewSize (int blocks, int detail);
-
-#endif
--- a/src/r_plane.c
+++ /dev/null
@@ -1,454 +1,0 @@
-// Emacs style mode select -*- C++ -*-
-//-----------------------------------------------------------------------------
-//
-// Copyright(C) 1993-1996 Id Software, Inc.
-// Copyright(C) 2005 Simon Howard
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-// 02111-1307, USA.
-//
-// DESCRIPTION:
-// Here is a core component: drawing the floors and ceilings,
-// while maintaining a per column clipping list only.
-// Moreover, the sky areas have to be determined.
-//
-//-----------------------------------------------------------------------------
-
-
-
-#include <stdlib.h>
-
-#include "i_system.h"
-#include "z_zone.h"
-#include "w_wad.h"
-
-#include "doomdef.h"
-#include "doomstat.h"
-
-#include "r_local.h"
-#include "r_sky.h"
-
-
-
-planefunction_t floorfunc;
-planefunction_t ceilingfunc;
-
-//
-// opening
-//
-
-// Here comes the obnoxious "visplane".
-#define MAXVISPLANES 128
-visplane_t visplanes[MAXVISPLANES];
-visplane_t* lastvisplane;
-visplane_t* floorplane;
-visplane_t* ceilingplane;
-
-// ?
-#define MAXOPENINGS SCREENWIDTH*64
-short openings[MAXOPENINGS];
-short* 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;
-fixed_t baseyscale;
-
-fixed_t cachedheight[SCREENHEIGHT];
-fixed_t cacheddistance[SCREENHEIGHT];
-fixed_t cachedxstep[SCREENHEIGHT];
-fixed_t cachedystep[SCREENHEIGHT];
-
-
-
-//
-// R_InitPlanes
-// Only at game startup.
-//
-void R_InitPlanes (void)
-{
- // Doh!
-}
-
-
-//
-// R_MapPlane
-//
-// Uses 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;
- fixed_t length;
- unsigned index;
-
-#ifdef RANGECHECK
- if (x2 < x1
- || x1 < 0
- || x2 >= viewwidth
- || 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;
-
- // high or low detail
- spanfunc ();
-}
-
-
-//
-// R_ClearPlanes
-// At begining of frame.
-//
-void R_ClearPlanes (void)
-{
- int i;
- angle_t angle;
-
- // opening / clipping determination
- for (i=0 ; i<viewwidth ; i++)
- {
- floorclip[i] = viewheight;
- ceilingclip[i] = -1;
- }
-
- lastvisplane = visplanes;
- lastopening = openings;
-
- // texture calculation
- memset (cachedheight, 0, sizeof(cachedheight));
-
- // left to right mapping
- angle = (viewangle-ANG90)>>ANGLETOFINESHIFT;
-
- // 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; check<lastvisplane; check++)
- {
- if (height == check->height
- && 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;
- int intrh;
- int unionl;
- int 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;
-
- // use the same one
- return pl;
- }
-
- // 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;
- int stop;
- int angle;
- int lumpnum;
-
-#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;
-
- // Sky is allways drawn full bright,
- // i.e. colormaps[0] is used.
- // Because of this hack, sky is not affected
- // by INVUL inverse mapping.
- dc_colormap = colormaps;
- 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
- lumpnum = firstflat + flattranslation[pl->picnum];
- ds_source = W_CacheLumpNum(lumpnum, 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]);
- }
-
- W_ReleaseLumpNum(lumpnum);
- }
-}
--- a/src/r_plane.h
+++ /dev/null
@@ -1,84 +1,0 @@
-// Emacs style mode select -*- C++ -*-
-//-----------------------------------------------------------------------------
-//
-// Copyright(C) 1993-1996 Id Software, Inc.
-// Copyright(C) 2005 Simon Howard
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-// 02111-1307, USA.
-//
-// DESCRIPTION:
-// Refresh, visplane stuff (floor, ceilings).
-//
-//-----------------------------------------------------------------------------
-
-
-#ifndef __R_PLANE__
-#define __R_PLANE__
-
-
-#include "r_data.h"
-
-
-
-// Visplane related.
-extern short* lastopening;
-
-
-typedef void (*planefunction_t) (int top, int bottom);
-
-extern planefunction_t floorfunc;
-extern planefunction_t ceilingfunc_t;
-
-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 );
-
-
-
-#endif
--- a/src/r_segs.c
+++ /dev/null
@@ -1,751 +1,0 @@
-// Emacs style mode select -*- C++ -*-
-//-----------------------------------------------------------------------------
-//
-// Copyright(C) 1993-1996 Id Software, Inc.
-// Copyright(C) 2005 Simon Howard
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-// 02111-1307, USA.
-//
-// DESCRIPTION:
-// All the clipping: columns, horizontal spans, sky columns.
-//
-//-----------------------------------------------------------------------------
-
-
-
-
-
-
-
-#include <stdlib.h>
-
-#include "i_system.h"
-
-#include "doomdef.h"
-#include "doomstat.h"
-
-#include "r_local.h"
-#include "r_sky.h"
-
-
-// OPTIMIZE: closed two sided lines as single sided
-
-// True if any of the segs textures might be visible.
-boolean segtextured;
-
-// False if the back side is the same plane.
-boolean markfloor;
-boolean markceiling;
-
-boolean maskedtexture;
-int toptexture;
-int bottomtexture;
-int midtexture;
-
-
-angle_t rw_normalangle;
-// angle to line origin
-int rw_angle1;
-
-//
-// regular 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;
-int worldbottom;
-int worldhigh;
-int worldlow;
-
-fixed_t pixhigh;
-fixed_t pixlow;
-fixed_t pixhighstep;
-fixed_t pixlowstep;
-
-fixed_t topfrac;
-fixed_t topstep;
-
-fixed_t bottomfrac;
-fixed_t 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. 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->ceilingheight<backsector->ceilingheight
- ? 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] != SHRT_MAX)
- {
- 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] = SHRT_MAX;
- }
- 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)
-
-void R_RenderSegLoop (void)
-{
- angle_t angle;
- unsigned index;
- int yl;
- int yh;
- int mid;
- fixed_t texturecolumn;
- int top;
- int bottom;
-
- for ( ; rw_x < rw_stopx ; rw_x++)
- {
- // mark floor / ceiling areas
- yl = (topfrac+HEIGHTUNIT-1)>>HEIGHTBITS;
-
- // no space above wall?
- if (yl < ceilingclip[rw_x]+1)
- yl = ceilingclip[rw_x]+1;
-
- 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;
- }
- else
- {
- // purely to shut up the compiler
-
- texturecolumn = 0;
- }
-
- // 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;
-
- // no space above wall?
- if (mid <= ceilingclip[rw_x])
- mid = ceilingclip[rw_x]+1;
-
- 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;
-
- // don't overflow and crash
- if (ds_p == &drawsegs[MAXDRAWSEGS])
- return;
-
-#ifdef RANGECHECK
- if (start >=viewwidth || start > stop)
- I_Error ("Bad R_RenderWallRange: %i to %i", start , stop);
-#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
- {
- // UNUSED: 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)<<detailshift;
- }
-#endif
- ds_p->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];
- // bottom of texture at bottom
- rw_midtexturemid = vtop - viewz;
- }
- else
- {
- // top of texture at top
- rw_midtexturemid = worldtop;
- }
- rw_midtexturemid += sidedef->rowoffset;
-
- ds_p->silhouette = SIL_BOTH;
- ds_p->sprtopclip = screenheightarray;
- ds_p->sprbottomclip = negonearray;
- ds_p->bsilheight = INT_MAX;
- ds_p->tsilheight = INT_MIN;
- }
- 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 = INT_MAX;
- // 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 = INT_MIN;
- // ds_p->sprtopclip = screenheightarray;
- }
-
- if (backsector->ceilingheight <= frontsector->floorheight)
- {
- ds_p->sprbottomclip = negonearray;
- ds_p->bsilheight = INT_MAX;
- ds_p->silhouette |= SIL_BOTTOM;
- }
-
- if (backsector->floorheight >= frontsector->ceilingheight)
- {
- ds_p->sprtopclip = screenheightarray;
- ds_p->tsilheight = INT_MIN;
- 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
- {
- // same plane on both sides
- markfloor = false;
- }
-
-
- if (worldhigh != worldtop
- || backsector->ceilingpic != frontsector->ceilingpic
- || backsector->lightlevel != frontsector->lightlevel)
- {
- markceiling = true;
- }
- else
- {
- // same plane on both sides
- markceiling = false;
- }
-
- if (backsector->ceilingheight <= frontsector->floorheight
- || backsector->floorheight >= frontsector->ceilingheight)
- {
- // closed door
- markceiling = markfloor = true;
- }
-
-
- if (worldhigh < worldtop)
- {
- // top texture
- toptexture = texturetranslation[sidedef->toptexture];
- if (linedef->flags & ML_DONTPEGTOP)
- {
- // top of texture at top
- rw_toptexturemid = worldtop;
- }
- else
- {
- vtop =
- backsector->ceilingheight
- + textureheight[sidedef->toptexture];
-
- // bottom of texture
- rw_toptexturemid = vtop - viewz;
- }
- }
- if (worldlow > worldbottom)
- {
- // bottom texture
- bottomtexture = texturetranslation[sidedef->bottomtexture];
-
- if (linedef->flags & ML_DONTPEGBOTTOM )
- {
- // bottom of texture at bottom
- // top of texture at top
- rw_bottomtexturemid = worldtop;
- }
- 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 definitely invisible
- // and doesn't need to be marked.
-
-
- if (frontsector->floorheight >= viewz)
- {
- // above view plane
- markfloor = false;
- }
-
- if (frontsector->ceilingheight <= viewz
- && frontsector->ceilingpic != skyflatnum)
- {
- // below view plane
- markceiling = false;
- }
-
-
- // 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 = INT_MIN;
- }
- if (maskedtexture && !(ds_p->silhouette&SIL_BOTTOM))
- {
- ds_p->silhouette |= SIL_BOTTOM;
- ds_p->bsilheight = INT_MAX;
- }
- ds_p++;
-}
-
--- a/src/r_segs.h
+++ /dev/null
@@ -1,41 +1,0 @@
-// Emacs style mode select -*- C++ -*-
-//-----------------------------------------------------------------------------
-//
-// Copyright(C) 1993-1996 Id Software, Inc.
-// Copyright(C) 2005 Simon Howard
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-// 02111-1307, USA.
-//
-// DESCRIPTION:
-// Refresh module, drawing LineSegs from BSP.
-//
-//-----------------------------------------------------------------------------
-
-
-#ifndef __R_SEGS__
-#define __R_SEGS__
-
-
-
-
-void
-R_RenderMaskedSegRange
-( drawseg_t* ds,
- int x1,
- int x2 );
-
-
-#endif
--- a/src/r_sky.c
+++ /dev/null
@@ -1,60 +1,0 @@
-// Emacs style mode select -*- C++ -*-
-//-----------------------------------------------------------------------------
-//
-// Copyright(C) 1993-1996 Id Software, Inc.
-// Copyright(C) 2005 Simon Howard
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-// 02111-1307, USA.
-//
-// DESCRIPTION:
-// Sky rendering. The DOOM sky is a texture map like any
-// wall, wrapping around. A 1024 columns equal 360 degrees.
-// The default sky map is 256 columns and repeats 4 times
-// on a 320 screen?
-//
-//
-//-----------------------------------------------------------------------------
-
-
-
-// Needed for FRACUNIT.
-#include "m_fixed.h"
-
-// Needed for Flat retrieval.
-#include "r_data.h"
-
-
-#include "r_sky.h"
-
-//
-// sky mapping
-//
-int skyflatnum;
-int skytexture;
-int skytexturemid;
-
-
-
-//
-// R_InitSkyMap
-// Called whenever the view size changes.
-//
-void R_InitSkyMap (void)
-{
- // skyflatnum = R_FlatNumForName ( SKYFLATNAME );
- skytexturemid = 100*FRACUNIT;
-}
-
--- a/src/r_sky.h
+++ /dev/null
@@ -1,45 +1,0 @@
-// Emacs style mode select -*- C++ -*-
-//-----------------------------------------------------------------------------
-//
-// Copyright(C) 1993-1996 Id Software, Inc.
-// Copyright(C) 2005 Simon Howard
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-// 02111-1307, USA.
-//
-// DESCRIPTION:
-// Sky rendering.
-//
-//-----------------------------------------------------------------------------
-
-
-#ifndef __R_SKY__
-#define __R_SKY__
-
-
-
-// SKY, store the number for name.
-#define SKYFLATNAME "F_SKY1"
-
-// The sky map is 256*128*4 maps.
-#define ANGLETOSKYSHIFT 22
-
-extern int skytexture;
-extern int skytexturemid;
-
-// Called whenever the view size changes.
-void R_InitSkyMap (void);
-
-#endif
--- a/src/r_state.h
+++ /dev/null
@@ -1,135 +1,0 @@
-// Emacs style mode select -*- C++ -*-
-//-----------------------------------------------------------------------------
-//
-// Copyright(C) 1993-1996 Id Software, Inc.
-// Copyright(C) 2005 Simon Howard
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-// 02111-1307, USA.
-//
-// DESCRIPTION:
-// Refresh/render internal state variables (global).
-//
-//-----------------------------------------------------------------------------
-
-
-#ifndef __R_STATE__
-#define __R_STATE__
-
-// Need data structure definitions.
-#include "d_player.h"
-#include "r_data.h"
-
-
-
-
-
-
-//
-// Refresh internal data structures,
-// for rendering.
-//
-
-// needed for texture pegging
-extern fixed_t* textureheight;
-
-// needed for pre rendering (fracs)
-extern fixed_t* spritewidth;
-
-extern fixed_t* spriteoffset;
-extern fixed_t* spritetopoffset;
-
-extern lighttable_t* colormaps;
-
-extern int viewwidth;
-extern int scaledviewwidth;
-extern int viewheight;
-
-extern int firstflat;
-
-// for global animation
-extern int* flattranslation;
-extern int* texturetranslation;
-
-
-// Sprite....
-extern int firstspritelump;
-extern int lastspritelump;
-extern int numspritelumps;
-
-
-
-//
-// Lookup tables for map data.
-//
-extern int numsprites;
-extern spritedef_t* sprites;
-
-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;
-
-
-//
-// POV data.
-//
-extern fixed_t viewx;
-extern fixed_t viewy;
-extern fixed_t 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;
-
-
-
-// angle to line origin
-extern int rw_angle1;
-
-// Segs count?
-extern int sscount;
-
-extern visplane_t* floorplane;
-extern visplane_t* ceilingplane;
-
-
-#endif
--- a/src/r_things.c
+++ /dev/null
@@ -1,990 +1,0 @@
-// Emacs style mode select -*- C++ -*-
-//-----------------------------------------------------------------------------
-//
-// Copyright(C) 1993-1996 Id Software, Inc.
-// Copyright(C) 2005 Simon Howard
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-// 02111-1307, USA.
-//
-// DESCRIPTION:
-// Refresh of things, i.e. objects represented by sprites.
-//
-//-----------------------------------------------------------------------------
-
-
-
-
-#include <stdio.h>
-#include <stdlib.h>
-
-
-#include "deh_main.h"
-#include "doomdef.h"
-
-#include "i_swap.h"
-#include "i_system.h"
-#include "z_zone.h"
-#include "w_wad.h"
-
-#include "r_local.h"
-
-#include "doomstat.h"
-
-
-
-#define MINZ (FRACUNIT*4)
-#define BASEYCENTER 100
-
-//void R_DrawColumn (void);
-//void R_DrawFuzzColumn (void);
-
-
-
-typedef struct
-{
- int x1;
- int 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;
-fixed_t 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;
-
- // make 0 based
- rotation--;
- 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;
- int l;
- int frame;
- int rotation;
- int start;
- int 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 ; i<numsprites ; i++)
- {
- spritename = DEH_String(namelist[i]);
- memset (sprtemp,-1, sizeof(sprtemp));
-
- maxframe = -1;
-
- // scan the lumps,
- // filling in the frames for whatever is found
- for (l=start+1 ; l<end ; l++)
- {
- if (!strncasecmp(lumpinfo[l].name, spritename, 4))
- {
- frame = lumpinfo[l].name[4] - 'A';
- rotation = lumpinfo[l].name[5] - '0';
-
- if (modifiedgame)
- patched = W_GetNumForName (lumpinfo[l].name);
- else
- patched = l;
-
- R_InstallSpriteLump (patched, frame, rotation, false);
-
- if (lumpinfo[l].name[6])
- {
- frame = lumpinfo[l].name[6] - 'A';
- rotation = lumpinfo[l].name[7] - '0';
- R_InstallSpriteLump (l, frame, rotation, true);
- }
- }
- }
-
- // check the frames that were found for completeness
- if (maxframe == -1)
- {
- sprites[i].numframes = 0;
- continue;
- }
-
- maxframe++;
-
- for (frame = 0 ; frame < maxframe ; frame++)
- {
- switch ((int)sprtemp[frame].rotate)
- {
- case -1:
- // no rotations were found for that frame at all
- I_Error ("R_InitSprites: No patches found "
- "for %s frame %c", spritename, frame+'A');
- break;
-
- case 0:
- // only the first rotation is needed
- break;
-
- case 1:
- // must have all 8 frames
- for (rotation=0 ; rotation<8 ; rotation++)
- if (sprtemp[frame].lump[rotation] == -1)
- I_Error ("R_InitSprites: Sprite %s frame %c "
- "is missing rotations",
- spritename, frame+'A');
- break;
- }
- }
-
- // allocate space for the frames present and copy sprtemp to it
- sprites[i].numframes = maxframe;
- sprites[i].spriteframes =
- Z_Malloc (maxframe * sizeof(spriteframe_t), PU_STATIC, NULL);
- memcpy (sprites[i].spriteframes, sprtemp, maxframe*sizeof(spriteframe_t));
- }
-
-}
-
-
-
-
-//
-// GAME FUNCTIONS
-//
-vissprite_t vissprites[MAXVISSPRITES];
-vissprite_t* vissprite_p;
-int newvissprite;
-
-
-
-//
-// R_InitSprites
-// Called at program start.
-//
-void R_InitSprites (char** namelist)
-{
- int i;
-
- for (i=0 ; i<SCREENWIDTH ; i++)
- {
- negonearray[i] = -1;
- }
-
- R_InitSpriteDefs (namelist);
-}
-
-
-
-//
-// R_ClearSprites
-// Called at frame start.
-//
-void R_ClearSprites (void)
-{
- vissprite_p = vissprites;
-}
-
-
-//
-// R_NewVisSprite
-//
-vissprite_t overflowsprite;
-
-vissprite_t* R_NewVisSprite (void)
-{
- if (vissprite_p == &vissprites[MAXVISSPRITES])
- return &overflowsprite;
-
- vissprite_p++;
- return vissprite_p-1;
-}
-
-
-
-//
-// R_DrawMaskedColumn
-// Used for sprites and masked mid textures.
-// Masked means: partly transparent, i.e. stored
-// in posts/runs of opaque pixels.
-//
-short* mfloorclip;
-short* mceilingclip;
-
-fixed_t spryscale;
-fixed_t sprtopscreen;
-
-void R_DrawMaskedColumn (column_t* column)
-{
- int topscreen;
- int bottomscreen;
- fixed_t basetexturemid;
-
- basetexturemid = dc_texturemid;
-
- for ( ; column->topdelta != 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<<FRACBITS);
- // dc_source = (byte *)column + 3 - column->topdelta;
-
- // Drawn by either R_DrawColumn
- // or (SHADOW) R_DrawFuzzColumn.
- colfunc ();
- }
- 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)
- {
- // NULL colormap = shadow draw
- colfunc = fuzzcolfunc;
- }
- else if (vis->mobjflags & MF_TRANSLATION)
- {
- colfunc = transcolfunc;
- 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 tr_x;
- fixed_t tr_y;
-
- fixed_t gxt;
- fixed_t gyt;
-
- fixed_t tx;
- fixed_t tz;
-
- fixed_t xscale;
-
- int x1;
- int 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
- tr_x = thing->x - viewx;
- tr_y = thing->y - viewy;
-
- gxt = FixedMul(tr_x,viewcos);
- gyt = -FixedMul(tr_y,viewsin);
-
- tz = gxt-gyt;
-
- // thing is behind view plane?
- if (tz < MINZ)
- return;
-
- xscale = FixedDiv(projection, tz);
-
- gxt = -FixedMul(tr_x,viewsin);
- gyt = FixedMul(tr_y,viewcos);
- tx = -(gyt+gxt);
-
- // too far off the side?
- if (abs(tx)>(tz<<2))
- return;
-
- // decide which patch to use for sprite relative to player
-#ifdef RANGECHECK
- if ((unsigned int) thing->sprite >= (unsigned int) 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;
-
- // off the right side?
- if (x1 > viewwidth)
- return;
-
- tx += spritewidth[lump];
- x2 = ((centerxfrac + FixedMul (tx,xscale) ) >>FRACBITS) - 1;
-
- // off the left side
- if (x2 < 0)
- return;
-
- // store information in a vissprite
- vis = R_NewVisSprite ();
- vis->mobjflags = thing->flags;
- vis->scale = xscale<<detailshift;
- vis->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)
- {
- // shadow draw
- vis->colormap = NULL;
- }
- else if (fixedcolormap)
- {
- // fixed map
- vis->colormap = fixedcolormap;
- }
- else if (thing->frame & FF_FULLBRIGHT)
- {
- // full bright
- vis->colormap = colormaps;
- }
-
- else
- {
- // diminished light
- index = xscale>>(LIGHTSCALESHIFT-detailshift);
-
- if (index >= MAXLIGHTSCALE)
- index = MAXLIGHTSCALE-1;
-
- vis->colormap = spritelights[index];
- }
-}
-
-
-
-
-//
-// R_AddSprites
-// During BSP traversal, this adds sprites by sector.
-//
-void R_AddSprites (sector_t* sec)
-{
- mobj_t* thing;
- int lightnum;
-
- // BSP is traversed by subsector.
- // A sector might have been split into several
- // subsectors during BSP building.
- // Thus we check whether its already added.
- if (sec->validcount == validcount)
- return;
-
- // Well, now it will be done.
- 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];
-
- // Handle all things in sector.
- for (thing = sec->thinglist ; thing ; thing = thing->snext)
- R_ProjectSprite (thing);
-}
-
-
-//
-// R_DrawPSprite
-//
-void R_DrawPSprite (pspdef_t* psp)
-{
- fixed_t tx;
- int x1;
- int x2;
- spritedef_t* sprdef;
- spriteframe_t* sprframe;
- int lump;
- boolean flip;
- vissprite_t* vis;
- vissprite_t avis;
-
- // decide which patch to use
-#ifdef RANGECHECK
- if ( (unsigned)psp->state->sprite >= (unsigned int) 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;
-
- // off the right side
- if (x1 > viewwidth)
- return;
-
- tx += spritewidth[lump];
- x2 = ((centerxfrac + FixedMul (tx, pspritescale) ) >>FRACBITS) - 1;
-
- // off the left side
- if (x2 < 0)
- return;
-
- // store information in a vissprite
- vis = &avis;
- vis->mobjflags = 0;
- vis->texturemid = (BASEYCENTER<<FRACBITS)+FRACUNIT/2-(psp->sy-spritetopoffset[lump]);
- vis->x1 = x1 < 0 ? 0 : x1;
- vis->x2 = x2 >= viewwidth ? viewwidth-1 : x2;
- vis->scale = pspritescale<<detailshift;
-
- if (flip)
- {
- vis->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)
- {
- // shadow draw
- vis->colormap = NULL;
- }
- else if (fixedcolormap)
- {
- // fixed color
- vis->colormap = fixedcolormap;
- }
- else if (psp->state->frame & FF_FULLBRIGHT)
- {
- // full bright
- vis->colormap = colormaps;
- }
- else
- {
- // local light
- vis->colormap = spritelights[MAXLIGHTSCALE-1];
- }
-
- R_DrawVisSprite (vis, vis->x1, vis->x2);
-}
-
-
-
-//
-// R_DrawPlayerSprites
-//
-void R_DrawPlayerSprites (void)
-{
- int i;
- int 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;
- i<NUMPSPRITES;
- i++,psp++)
- {
- if (psp->state)
- R_DrawPSprite (psp);
- }
-}
-
-
-
-
-//
-// R_SortVisSprites
-//
-vissprite_t vsprsortedhead;
-
-
-void R_SortVisSprites (void)
-{
- int i;
- int count;
- vissprite_t* ds;
- vissprite_t* best;
- vissprite_t unsorted;
- fixed_t bestscale;
-
- count = vissprite_p - vissprites;
-
- unsorted.next = unsorted.prev = &unsorted;
-
- if (!count)
- return;
-
- for (ds=vissprites ; ds<vissprite_p ; ds++)
- {
- ds->next = 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
-
- vsprsortedhead.next = vsprsortedhead.prev = &vsprsortedhead;
- for (i=0 ; i<count ; i++)
- {
- bestscale = INT_MAX;
- best = unsorted.next;
- for (ds=unsorted.next ; ds!= &unsorted ; ds=ds->next)
- {
- 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];
- short cliptop[SCREENWIDTH];
- int x;
- int r1;
- int r2;
- fixed_t scale;
- fixed_t 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) )
- {
- // does not cover sprite
- continue;
- }
-
- 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) ) )
- {
- // masked mid texture?
- if (ds->maskedtexturecol)
- R_RenderMaskedSegRange (ds, r1, r2);
- // seg is behind sprite
- continue;
- }
-
-
- // 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
- // but does not draw on side views
- if (!viewangleoffset)
- R_DrawPlayerSprites ();
-}
-
-
-
--- a/src/r_things.h
+++ /dev/null
@@ -1,73 +1,0 @@
-// Emacs style mode select -*- C++ -*-
-//-----------------------------------------------------------------------------
-//
-// Copyright(C) 1993-1996 Id Software, Inc.
-// Copyright(C) 2005 Simon Howard
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-// 02111-1307, USA.
-//
-// DESCRIPTION:
-// Rendering of moving objects, sprites.
-//
-//-----------------------------------------------------------------------------
-
-
-#ifndef __R_THINGS__
-#define __R_THINGS__
-
-
-
-#define MAXVISSPRITES 128
-
-extern vissprite_t vissprites[MAXVISSPRITES];
-extern vissprite_t* 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;
-extern fixed_t 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 );
-
-
-#endif
--- a/src/sounds.c
+++ /dev/null
@@ -1,230 +1,0 @@
-// Emacs style mode select -*- C++ -*-
-//-----------------------------------------------------------------------------
-//
-// Copyright(C) 1993-1996 Id Software, Inc.
-// Copyright(C) 2005 Simon Howard
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-// 02111-1307, USA.
-//
-// DESCRIPTION:
-// Created by a sound utility.
-// Kept as a sample, DOOM2 sounds.
-//
-//-----------------------------------------------------------------------------
-
-
-#include <stdlib.h>
-
-
-#include "doomtype.h"
-#include "sounds.h"
-
-//
-// Information about all the music
-//
-
-musicinfo_t S_music[] =
-{
- { NULL, 0, 0, 0 },
- { "e1m1", 0, 0, 0 },
- { "e1m2", 0, 0, 0 },
- { "e1m3", 0, 0, 0 },
- { "e1m4", 0, 0, 0 },
- { "e1m5", 0, 0, 0 },
- { "e1m6", 0, 0, 0 },
- { "e1m7", 0, 0, 0 },
- { "e1m8", 0, 0, 0 },
- { "e1m9", 0, 0, 0 },
- { "e2m1", 0, 0, 0 },
- { "e2m2", 0, 0, 0 },
- { "e2m3", 0, 0, 0 },
- { "e2m4", 0, 0, 0 },
- { "e2m5", 0, 0, 0 },
- { "e2m6", 0, 0, 0 },
- { "e2m7", 0, 0, 0 },
- { "e2m8", 0, 0, 0 },
- { "e2m9", 0, 0, 0 },
- { "e3m1", 0, 0, 0 },
- { "e3m2", 0, 0, 0 },
- { "e3m3", 0, 0, 0 },
- { "e3m4", 0, 0, 0 },
- { "e3m5", 0, 0, 0 },
- { "e3m6", 0, 0, 0 },
- { "e3m7", 0, 0, 0 },
- { "e3m8", 0, 0, 0 },
- { "e3m9", 0, 0, 0 },
- { "inter", 0, 0, 0 },
- { "intro", 0, 0, 0 },
- { "bunny", 0, 0, 0 },
- { "victor", 0, 0, 0 },
- { "introa", 0, 0, 0 },
- { "runnin", 0, 0, 0 },
- { "stalks", 0, 0, 0 },
- { "countd", 0, 0, 0 },
- { "betwee", 0, 0, 0 },
- { "doom", 0, 0, 0 },
- { "the_da", 0, 0, 0 },
- { "shawn", 0, 0, 0 },
- { "ddtblu", 0, 0, 0 },
- { "in_cit", 0, 0, 0 },
- { "dead", 0, 0, 0 },
- { "stlks2", 0, 0, 0 },
- { "theda2", 0, 0, 0 },
- { "doom2", 0, 0, 0 },
- { "ddtbl2", 0, 0, 0 },
- { "runni2", 0, 0, 0 },
- { "dead2", 0, 0, 0 },
- { "stlks3", 0, 0, 0 },
- { "romero", 0, 0, 0 },
- { "shawn2", 0, 0, 0 },
- { "messag", 0, 0, 0 },
- { "count2", 0, 0, 0 },
- { "ddtbl3", 0, 0, 0 },
- { "ampie", 0, 0, 0 },
- { "theda3", 0, 0, 0 },
- { "adrian", 0, 0, 0 },
- { "messg2", 0, 0, 0 },
- { "romer2", 0, 0, 0 },
- { "tense", 0, 0, 0 },
- { "shawn3", 0, 0, 0 },
- { "openin", 0, 0, 0 },
- { "evil", 0, 0, 0 },
- { "ultima", 0, 0, 0 },
- { "read_m", 0, 0, 0 },
- { "dm2ttl", 0, 0, 0 },
- { "dm2int", 0, 0, 0 }
-};
-
-
-//
-// Information about all the sfx
-//
-
-sfxinfo_t S_sfx[] =
-{
- // S_sfx[0] needs to be a dummy for odd reasons.
- { "none", false, 0, 0, -1, -1, 0, 0, 0 },
-
- { "pistol", false, 64, 0, -1, -1, 0, 0, 0 },
- { "shotgn", false, 64, 0, -1, -1, 0, 0, 0 },
- { "sgcock", false, 64, 0, -1, -1, 0, 0, 0 },
- { "dshtgn", false, 64, 0, -1, -1, 0, 0, 0 },
- { "dbopn", false, 64, 0, -1, -1, 0, 0, 0 },
- { "dbcls", false, 64, 0, -1, -1, 0, 0, 0 },
- { "dbload", false, 64, 0, -1, -1, 0, 0, 0 },
- { "plasma", false, 64, 0, -1, -1, 0, 0, 0 },
- { "bfg", false, 64, 0, -1, -1, 0, 0, 0 },
- { "sawup", false, 64, 0, -1, -1, 0, 0, 0 },
- { "sawidl", false, 118, 0, -1, -1, 0, 0, 0 },
- { "sawful", false, 64, 0, -1, -1, 0, 0, 0 },
- { "sawhit", false, 64, 0, -1, -1, 0, 0, 0 },
- { "rlaunc", false, 64, 0, -1, -1, 0, 0, 0 },
- { "rxplod", false, 70, 0, -1, -1, 0, 0, 0 },
- { "firsht", false, 70, 0, -1, -1, 0, 0, 0 },
- { "firxpl", false, 70, 0, -1, -1, 0, 0, 0 },
- { "pstart", false, 100, 0, -1, -1, 0, 0, 0 },
- { "pstop", false, 100, 0, -1, -1, 0, 0, 0 },
- { "doropn", false, 100, 0, -1, -1, 0, 0, 0 },
- { "dorcls", false, 100, 0, -1, -1, 0, 0, 0 },
- { "stnmov", false, 119, 0, -1, -1, 0, 0, 0 },
- { "swtchn", false, 78, 0, -1, -1, 0, 0, 0 },
- { "swtchx", false, 78, 0, -1, -1, 0, 0, 0 },
- { "plpain", false, 96, 0, -1, -1, 0, 0, 0 },
- { "dmpain", false, 96, 0, -1, -1, 0, 0, 0 },
- { "popain", false, 96, 0, -1, -1, 0, 0, 0 },
- { "vipain", false, 96, 0, -1, -1, 0, 0, 0 },
- { "mnpain", false, 96, 0, -1, -1, 0, 0, 0 },
- { "pepain", false, 96, 0, -1, -1, 0, 0, 0 },
- { "slop", false, 78, 0, -1, -1, 0, 0, 0 },
- { "itemup", true, 78, 0, -1, -1, 0, 0, 0 },
- { "wpnup", true, 78, 0, -1, -1, 0, 0, 0 },
- { "oof", false, 96, 0, -1, -1, 0, 0, 0 },
- { "telept", false, 32, 0, -1, -1, 0, 0, 0 },
- { "posit1", true, 98, 0, -1, -1, 0, 0, 0 },
- { "posit2", true, 98, 0, -1, -1, 0, 0, 0 },
- { "posit3", true, 98, 0, -1, -1, 0, 0, 0 },
- { "bgsit1", true, 98, 0, -1, -1, 0, 0, 0 },
- { "bgsit2", true, 98, 0, -1, -1, 0, 0, 0 },
- { "sgtsit", true, 98, 0, -1, -1, 0, 0, 0 },
- { "cacsit", true, 98, 0, -1, -1, 0, 0, 0 },
- { "brssit", true, 94, 0, -1, -1, 0, 0, 0 },
- { "cybsit", true, 92, 0, -1, -1, 0, 0, 0 },
- { "spisit", true, 90, 0, -1, -1, 0, 0, 0 },
- { "bspsit", true, 90, 0, -1, -1, 0, 0, 0 },
- { "kntsit", true, 90, 0, -1, -1, 0, 0, 0 },
- { "vilsit", true, 90, 0, -1, -1, 0, 0, 0 },
- { "mansit", true, 90, 0, -1, -1, 0, 0, 0 },
- { "pesit", true, 90, 0, -1, -1, 0, 0, 0 },
- { "sklatk", false, 70, 0, -1, -1, 0, 0, 0 },
- { "sgtatk", false, 70, 0, -1, -1, 0, 0, 0 },
- { "skepch", false, 70, 0, -1, -1, 0, 0, 0 },
- { "vilatk", false, 70, 0, -1, -1, 0, 0, 0 },
- { "claw", false, 70, 0, -1, -1, 0, 0, 0 },
- { "skeswg", false, 70, 0, -1, -1, 0, 0, 0 },
- { "pldeth", false, 32, 0, -1, -1, 0, 0, 0 },
- { "pdiehi", false, 32, 0, -1, -1, 0, 0, 0 },
- { "podth1", false, 70, 0, -1, -1, 0, 0, 0 },
- { "podth2", false, 70, 0, -1, -1, 0, 0, 0 },
- { "podth3", false, 70, 0, -1, -1, 0, 0, 0 },
- { "bgdth1", false, 70, 0, -1, -1, 0, 0, 0 },
- { "bgdth2", false, 70, 0, -1, -1, 0, 0, 0 },
- { "sgtdth", false, 70, 0, -1, -1, 0, 0, 0 },
- { "cacdth", false, 70, 0, -1, -1, 0, 0, 0 },
- { "skldth", false, 70, 0, -1, -1, 0, 0, 0 },
- { "brsdth", false, 32, 0, -1, -1, 0, 0, 0 },
- { "cybdth", false, 32, 0, -1, -1, 0, 0, 0 },
- { "spidth", false, 32, 0, -1, -1, 0, 0, 0 },
- { "bspdth", false, 32, 0, -1, -1, 0, 0, 0 },
- { "vildth", false, 32, 0, -1, -1, 0, 0, 0 },
- { "kntdth", false, 32, 0, -1, -1, 0, 0, 0 },
- { "pedth", false, 32, 0, -1, -1, 0, 0, 0 },
- { "skedth", false, 32, 0, -1, -1, 0, 0, 0 },
- { "posact", true, 120, 0, -1, -1, 0, 0, 0 },
- { "bgact", true, 120, 0, -1, -1, 0, 0, 0 },
- { "dmact", true, 120, 0, -1, -1, 0, 0, 0 },
- { "bspact", true, 100, 0, -1, -1, 0, 0, 0 },
- { "bspwlk", true, 100, 0, -1, -1, 0, 0, 0 },
- { "vilact", true, 100, 0, -1, -1, 0, 0, 0 },
- { "noway", false, 78, 0, -1, -1, 0, 0, 0 },
- { "barexp", false, 60, 0, -1, -1, 0, 0, 0 },
- { "punch", false, 64, 0, -1, -1, 0, 0, 0 },
- { "hoof", false, 70, 0, -1, -1, 0, 0, 0 },
- { "metal", false, 70, 0, -1, -1, 0, 0, 0 },
- { "chgun", false, 64, &S_sfx[sfx_pistol], 150, 0, 0, 0, 0 },
- { "tink", false, 60, 0, -1, -1, 0, 0, 0 },
- { "bdopn", false, 100, 0, -1, -1, 0, 0, 0 },
- { "bdcls", false, 100, 0, -1, -1, 0, 0, 0 },
- { "itmbk", false, 100, 0, -1, -1, 0, 0, 0 },
- { "flame", false, 32, 0, -1, -1, 0, 0, 0 },
- { "flamst", false, 32, 0, -1, -1, 0, 0, 0 },
- { "getpow", false, 60, 0, -1, -1, 0, 0, 0 },
- { "bospit", false, 70, 0, -1, -1, 0, 0, 0 },
- { "boscub", false, 70, 0, -1, -1, 0, 0, 0 },
- { "bossit", false, 70, 0, -1, -1, 0, 0, 0 },
- { "bospn", false, 70, 0, -1, -1, 0, 0, 0 },
- { "bosdth", false, 70, 0, -1, -1, 0, 0, 0 },
- { "manatk", false, 70, 0, -1, -1, 0, 0, 0 },
- { "mandth", false, 70, 0, -1, -1, 0, 0, 0 },
- { "sssit", false, 70, 0, -1, -1, 0, 0, 0 },
- { "ssdth", false, 70, 0, -1, -1, 0, 0, 0 },
- { "keenpn", false, 70, 0, -1, -1, 0, 0, 0 },
- { "keendt", false, 70, 0, -1, -1, 0, 0, 0 },
- { "skeact", false, 70, 0, -1, -1, 0, 0, 0 },
- { "skesit", false, 70, 0, -1, -1, 0, 0, 0 },
- { "skeatk", false, 70, 0, -1, -1, 0, 0, 0 },
- { "radio", false, 60, 0, -1, -1, 0, 0, 0 }
-};
-
--- a/src/sounds.h
+++ /dev/null
@@ -1,296 +1,0 @@
-// Emacs style mode select -*- C++ -*-
-//-----------------------------------------------------------------------------
-//
-// Copyright(C) 1993-1996 Id Software, Inc.
-// Copyright(C) 2005 Simon Howard
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-// 02111-1307, USA.
-//
-// DESCRIPTION:
-// Created by the sound utility written by Dave Taylor.
-// Kept as a sample, DOOM2 sounds. Frozen.
-//
-//-----------------------------------------------------------------------------
-
-#ifndef __SOUNDS__
-#define __SOUNDS__
-
-
-//
-// SoundFX struct.
-//
-typedef struct sfxinfo_struct sfxinfo_t;
-
-struct sfxinfo_struct
-{
- // up to 6-character name
- char* name;
-
- // Sfx singularity (only one at a time)
- int singularity;
-
- // Sfx priority
- int priority;
-
- // referenced sound if a link
- sfxinfo_t* link;
-
- // pitch if a link
- int pitch;
-
- // volume if a link
- int volume;
-
- // sound data
- void* data;
-
- // 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 is in use)
- int usefulness;
-
- // lump number of sfx
- int lumpnum;
-};
-
-
-
-
-//
-// MusicInfo struct.
-//
-typedef struct
-{
- // up to 6-character name
- char* name;
-
- // lump number of music
- int lumpnum;
-
- // music data
- void* data;
-
- // music handle once registered
- void *handle;
-
-} musicinfo_t;
-
-
-
-
-// the complete set of sound effects
-extern sfxinfo_t S_sfx[];
-
-// the complete set of music
-extern musicinfo_t S_music[];
-
-//
-// 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;
-
-#endif
--- a/src/st_lib.c
+++ /dev/null
@@ -1,294 +1,0 @@
-// Emacs style mode select -*- C++ -*-
-//-----------------------------------------------------------------------------
-//
-// Copyright(C) 1993-1996 Id Software, Inc.
-// Copyright(C) 2005 Simon Howard
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-// 02111-1307, USA.
-//
-// DESCRIPTION:
-// The status bar widget code.
-//
-//-----------------------------------------------------------------------------
-
-
-
-#include <ctype.h>
-
-#include "deh_main.h"
-#include "doomdef.h"
-
-#include "z_zone.h"
-#include "v_video.h"
-
-#include "i_swap.h"
-#include "i_system.h"
-
-#include "w_wad.h"
-
-#include "st_stuff.h"
-#include "st_lib.h"
-#include "r_local.h"
-
-
-// in AM_map.c
-extern boolean automapactive;
-
-
-
-
-//
-// Hack display negative frags.
-// Loads and store the stminus lump.
-//
-patch_t* sttminus;
-
-void STlib_init(void)
-{
- sttminus = (patch_t *) W_CacheLumpName(DEH_String("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.
-// Note: worth the trouble?
-//
-void
-STlib_drawNum
-( st_number_t* n,
- boolean refresh )
-{
-
- int numdigits = n->width;
- int num = *n->num;
-
- int w = SHORT(n->p[0]->width);
- int 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, do not 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;
- int h;
- int x;
- int 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 = false;
- b->val = val;
- b->on = on;
- b->p = i;
-}
-
-
-
-void
-STlib_updateBinIcon
-( st_binicon_t* bi,
- boolean refresh )
-{
- int x;
- int y;
- int w;
- int 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;
- }
-
-}
-
--- a/src/st_lib.h
+++ /dev/null
@@ -1,226 +1,0 @@
-// Emacs style mode select -*- C++ -*-
-//-----------------------------------------------------------------------------
-//
-// Copyright(C) 1993-1996 Id Software, Inc.
-// Copyright(C) 2005 Simon Howard
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-// 02111-1307, USA.
-//
-// DESCRIPTION:
-// The status bar widget code.
-//
-//-----------------------------------------------------------------------------
-
-#ifndef __STLIB__
-#define __STLIB__
-
-
-// We are referring to patches.
-#include "r_defs.h"
-
-
-//
-// Background and foreground screen numbers
-//
-#define BG 4
-#define FG 0
-
-
-
-//
-// Typedefs of widgets
-//
-
-// Number widget
-
-typedef struct
-{
- // upper right-hand corner
- // of the number (right-justified)
- int x;
- int y;
-
- // max # of digits in number
- int width;
-
- // last number value
- int oldnum;
-
- // pointer to current value
- int* num;
-
- // pointer to boolean stating
- // whether to update number
- boolean* on;
-
- // list of patches for 0-9
- patch_t** p;
-
- // user data
- int data;
-
-} st_number_t;
-
-
-
-// Percent widget ("child" of number widget,
-// or, more precisely, contains a number widget.)
-typedef struct
-{
- // number information
- st_number_t n;
-
- // percent sign graphic
- patch_t* p;
-
-} st_percent_t;
-
-
-
-// Multiple Icon widget
-typedef struct
-{
- // center-justified location of icons
- int x;
- int y;
-
- // last icon number
- int oldinum;
-
- // pointer to current icon
- int* inum;
-
- // pointer to boolean stating
- // whether to update icon
- boolean* on;
-
- // list of icons
- patch_t** p;
-
- // user data
- int data;
-
-} st_multicon_t;
-
-
-
-
-// Binary Icon widget
-
-typedef struct
-{
- // center-justified location of icon
- int x;
- int y;
-
- // last icon value
- boolean oldval;
-
- // pointer to current icon status
- boolean* val;
-
- // pointer to boolean
- // stating whether to update icon
- boolean* on;
-
-
- patch_t* p; // icon
- int data; // user data
-
-} st_binicon_t;
-
-
-
-//
-// Widget creation, access, and update routines
-//
-
-// Initializes widget library.
-// More precisely, initialize STMINUS,
-// everything else is done somewhere else.
-//
-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
--- a/src/st_stuff.c
+++ /dev/null
@@ -1,1408 +1,0 @@
-// Emacs style mode select -*- C++ -*-
-//-----------------------------------------------------------------------------
-//
-// Copyright(C) 1993-1996 Id Software, Inc.
-// Copyright(C) 2005 Simon Howard
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-// 02111-1307, USA.
-//
-// DESCRIPTION:
-// Status bar code.
-// Does the face/direction indicator animatin.
-// Does palette indicators as well (red pain/berserk, bright pickup)
-//
-//-----------------------------------------------------------------------------
-
-
-
-#include <stdio.h>
-
-#include "i_system.h"
-#include "i_video.h"
-#include "z_zone.h"
-#include "m_random.h"
-#include "w_wad.h"
-
-#include "deh_main.h"
-#include "deh_misc.h"
-#include "doomdef.h"
-
-#include "g_game.h"
-
-#include "st_stuff.h"
-#include "st_lib.h"
-#include "r_local.h"
-
-#include "p_local.h"
-#include "p_inter.h"
-
-#include "am_map.h"
-#include "m_cheat.h"
-
-#include "s_sound.h"
-
-// Needs access to LFB.
-#include "v_video.h"
-
-// State.
-#include "doomstat.h"
-
-// Data.
-#include "dstrings.h"
-#include "sounds.h"
-
-//
-// STATUS BAR DATA
-//
-
-
-// Palette indices.
-// For damage/bonus red-/gold-shifts
-#define STARTREDPALS 1
-#define STARTBONUSPALS 9
-#define NUMREDPALS 8
-#define NUMBONUSPALS 4
-// Radiation suit, green shift.
-#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 of status bar
-#define ST_X 0
-#define ST_X2 104
-
-#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.
-// Problem is, within which space? STbar? Screen?
-// Note: this could be read in by a lump.
-// Problem is, is the stuff rendered
-// into a buffer,
-// or into the frame buffer?
-
-// AMMO number pos.
-#define ST_AMMOWIDTH 3
-#define ST_AMMOX 44
-#define ST_AMMOY 171
-
-// HEALTH number pos.
-#define ST_HEALTHWIDTH 3
-#define ST_HEALTHX 90
-#define ST_HEALTHY 171
-
-// Weapon pos.
-#define ST_ARMSX 111
-#define ST_ARMSY 172
-#define ST_ARMSBGX 104
-#define ST_ARMSBGY 168
-#define ST_ARMSXSPACE 12
-#define ST_ARMSYSPACE 10
-
-// Frags pos.
-#define ST_FRAGSX 138
-#define ST_FRAGSY 171
-#define ST_FRAGSWIDTH 2
-
-// ARMOR number pos.
-#define ST_ARMORWIDTH 3
-#define ST_ARMORX 221
-#define ST_ARMORY 171
-
-// Key icon positions.
-#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
-
-// Ammunition counter.
-#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
-
-// Indicate maximum ammunition.
-// Only needed because backpack exists.
-#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
-
-// pistol
-#define ST_WEAPON0X 110
-#define ST_WEAPON0Y 172
-
-// shotgun
-#define ST_WEAPON1X 122
-#define ST_WEAPON1Y 172
-
-// chain gun
-#define ST_WEAPON2X 134
-#define ST_WEAPON2Y 172
-
-// missile launcher
-#define ST_WEAPON3X 110
-#define ST_WEAPON3Y 181
-
-// plasma gun
-#define ST_WEAPON4X 122
-#define ST_WEAPON4Y 181
-
- // bfg
-#define ST_WEAPON5X 134
-#define ST_WEAPON5Y 181
-
-// WPNS title
-#define ST_WPNSX 109
-#define ST_WPNSY 191
-
- // DETH title
-#define ST_DETHX 109
-#define ST_DETHY 191
-
-//Incoming messages window location
-//UNUSED
-// #define ST_MSGTEXTX (viewwindowx)
-// #define ST_MSGTEXTY (viewwindowy+viewheight-18)
-#define ST_MSGTEXTX 0
-#define ST_MSGTEXTY 0
-// Dimensions given in characters.
-#define ST_MSGWIDTH 52
-// Or shall I say, in lines?
-#define ST_MSGHEIGHT 1
-
-#define ST_OUTTEXTX 0
-#define ST_OUTTEXTY 6
-
-// Width, in characters again.
-#define ST_OUTWIDTH 52
- // Height, in lines.
-#define ST_OUTHEIGHT 1
-
-#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
-
-
-// main player in game
-static player_t* plyr;
-
-// ST_Start() has just been called
-static boolean st_firsttime;
-
-// used to execute ST_Init() only once
-static int veryfirsttime = 1;
-
-// lump number for PLAYPAL
-static int lu_palette;
-
-// used for timing
-static unsigned int st_clock;
-
-// used for making messages go away
-static int st_msgcounter=0;
-
-// used when in chat
-static st_chatstateenum_t st_chatstate;
-
-// whether in automap or first-person
-static st_stateenum_t st_gamestate;
-
-// whether left-side main status bar is active
-static boolean st_statusbaron;
-
-// whether status bar chat is active
-static boolean st_chat;
-
-// value of st_chat before message popped up
-static boolean st_oldchat;
-
-// whether chat window has the cursor on
-static boolean st_cursoron;
-
-// !deathmatch
-static boolean st_notdeathmatch;
-
-// !deathmatch && st_statusbaron
-static boolean st_armson;
-
-// !deathmatch
-static boolean st_fragson;
-
-// main bar left
-static patch_t* sbar;
-
-// 0-9, tall numbers
-static patch_t* tallnum[10];
-
-// tall % sign
-static patch_t* tallpercent;
-
-// 0-9, short, yellow (,different!) numbers
-static patch_t* shortnum[10];
-
-// 3 key-cards, 3 skulls
-static patch_t* keys[NUMCARDS];
-
-// face status patches
-static patch_t* faces[ST_NUMFACES];
-
-// face background
-static patch_t* faceback;
-
- // main bar right
-static patch_t* armsbg;
-
-// weapon ownership patches
-static patch_t* arms[6][2];
-
-// ready-weapon widget
-static st_number_t w_ready;
-
- // in deathmatch only, summary of frags stats
-static st_number_t w_frags;
-
-// health widget
-static st_percent_t w_health;
-
-// arms background
-static st_binicon_t w_armsbg;
-
-
-// weapon ownership widgets
-static st_multicon_t w_arms[6];
-
-// face status widget
-static st_multicon_t w_faces;
-
-// keycard widgets
-static st_multicon_t w_keyboxes[3];
-
-// armor widget
-static st_percent_t w_armor;
-
-// ammo widgets
-static st_number_t w_ammo[4];
-
-// max ammo widgets
-static st_number_t w_maxammo[4];
-
-
-
- // number of frags so far in deathmatch
-static int st_fragscount;
-
-// used to use appopriately pained face
-static int st_oldhealth = -1;
-
-// used for evil grin
-static boolean oldweaponsowned[NUMWEAPONS];
-
- // count until face changes
-static int st_facecount = 0;
-
-// current face index, used by w_faces
-static int st_faceindex = 0;
-
-// holds key-type for each key box on bar
-static int keyboxes[3];
-
-// a random number per tick
-static int st_randomnumber;
-
-cheatseq_t cheat_mus = CHEAT("idmus", 2);
-cheatseq_t cheat_god = CHEAT("iddqd", 0);
-cheatseq_t cheat_ammo = CHEAT("idkfa", 0);
-cheatseq_t cheat_ammonokey = CHEAT("idfa", 0);
-cheatseq_t cheat_noclip = CHEAT("idspispopd", 0);
-cheatseq_t cheat_commercial_noclip = CHEAT("idclip", 0);
-
-cheatseq_t cheat_powerup[7] =
-{
- CHEAT("idbeholdv", 0),
- CHEAT("idbeholds", 0),
- CHEAT("idbeholdi", 0),
- CHEAT("idbeholdr", 0),
- CHEAT("idbeholda", 0),
- CHEAT("idbeholdl", 0),
- CHEAT("idbehold", 0),
-};
-
-cheatseq_t cheat_choppers = CHEAT("idchoppers", 0);
-cheatseq_t cheat_clev = CHEAT("idclev", 2);
-cheatseq_t cheat_mypos = CHEAT("idmypos", 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);
- }
-
-}
-
-
-// Respond to keyboard input events,
-// intercept cheats.
-boolean
-ST_Responder (event_t* ev)
-{
- int i;
-
- // Filter automap on/off.
- 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 && gameskill != sk_nightmare)
- {
- // 'dqd' cheat for toggleable god mode
- if (cht_CheckCheat(&cheat_god, ev->data2))
- {
- plyr->cheats ^= CF_GODMODE;
- if (plyr->cheats & CF_GODMODE)
- {
- if (plyr->mo)
- plyr->mo->health = 100;
-
- plyr->health = deh_god_mode_health;
- plyr->message = DEH_String(STSTR_DQDON);
- }
- else
- plyr->message = DEH_String(STSTR_DQDOFF);
- }
- // 'fa' cheat for killer fucking arsenal
- else if (cht_CheckCheat(&cheat_ammonokey, ev->data2))
- {
- plyr->armorpoints = deh_idfa_armor;
- plyr->armortype = deh_idfa_armor_class;
-
- for (i=0;i<NUMWEAPONS;i++)
- plyr->weaponowned[i] = true;
-
- for (i=0;i<NUMAMMO;i++)
- plyr->ammo[i] = plyr->maxammo[i];
-
- plyr->message = DEH_String(STSTR_FAADDED);
- }
- // 'kfa' cheat for key full ammo
- else if (cht_CheckCheat(&cheat_ammo, ev->data2))
- {
- plyr->armorpoints = deh_idkfa_armor;
- plyr->armortype = deh_idkfa_armor_class;
-
- for (i=0;i<NUMWEAPONS;i++)
- plyr->weaponowned[i] = true;
-
- for (i=0;i<NUMAMMO;i++)
- plyr->ammo[i] = plyr->maxammo[i];
-
- for (i=0;i<NUMCARDS;i++)
- plyr->cards[i] = true;
-
- plyr->message = DEH_String(STSTR_KFAADDED);
- }
- // 'mus' cheat for changing music
- else if (cht_CheckCheat(&cheat_mus, ev->data2))
- {
-
- char buf[3];
- int musnum;
-
- plyr->message = DEH_String(STSTR_MUS);
- cht_GetParam(&cheat_mus, buf);
-
- if (gamemode == commercial)
- {
- musnum = mus_runnin + (buf[0]-'0')*10 + buf[1]-'0' - 1;
-
- if (((buf[0]-'0')*10 + buf[1]-'0') > 35)
- plyr->message = DEH_String(STSTR_NOMUS);
- else
- S_ChangeMusic(musnum, 1);
- }
- else
- {
- musnum = mus_e1m1 + (buf[0]-'1')*9 + (buf[1]-'1');
-
- if (((buf[0]-'1')*9 + buf[1]-'1') > 31)
- plyr->message = DEH_String(STSTR_NOMUS);
- else
- S_ChangeMusic(musnum, 1);
- }
- }
- else if ( (gamemission == doom
- && cht_CheckCheat(&cheat_noclip, ev->data2))
- || (gamemission != doom
- && cht_CheckCheat(&cheat_commercial_noclip,ev->data2)))
- {
- // Noclip cheat.
- // For Doom 1, use the idspipsopd cheat; for all others, use
- // idclip
-
- plyr->cheats ^= CF_NOCLIP;
-
- if (plyr->cheats & CF_NOCLIP)
- plyr->message = DEH_String(STSTR_NCON);
- else
- plyr->message = DEH_String(STSTR_NCOFF);
- }
- // 'behold?' power-up cheats
- for (i=0;i<6;i++)
- {
- if (cht_CheckCheat(&cheat_powerup[i], ev->data2))
- {
- if (!plyr->powers[i])
- P_GivePower( plyr, i);
- else if (i!=pw_strength)
- plyr->powers[i] = 1;
- else
- plyr->powers[i] = 0;
-
- plyr->message = DEH_String(STSTR_BEHOLDX);
- }
- }
-
- // 'behold' power-up menu
- if (cht_CheckCheat(&cheat_powerup[6], ev->data2))
- {
- plyr->message = DEH_String(STSTR_BEHOLD);
- }
- // 'choppers' invulnerability & chainsaw
- else if (cht_CheckCheat(&cheat_choppers, ev->data2))
- {
- plyr->weaponowned[wp_chainsaw] = true;
- plyr->powers[pw_invulnerability] = true;
- plyr->message = DEH_String(STSTR_CHOPPERS);
- }
- // 'mypos' for player position
- else if (cht_CheckCheat(&cheat_mypos, ev->data2))
- {
- 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 (!netgame && cht_CheckCheat(&cheat_clev, ev->data2))
- {
- char buf[3];
- int epsd;
- int map;
-
- cht_GetParam(&cheat_clev, buf);
-
- if (gamemode == commercial)
- {
- epsd = 1;
- map = (buf[0] - '0')*10 + buf[1] - '0';
- }
- else
- {
- epsd = buf[0] - '0';
- map = buf[1] - '0';
- }
-
- // Chex.exe always warps to episode 1.
-
- if (gameversion == exe_chex)
- {
- epsd = 1;
- }
-
- // Catch invalid maps.
- if (epsd < 1)
- return false;
-
- if (map < 1)
- return false;
-
- // Ohmygod - this is not going to work.
- if ((gamemode == retail)
- && ((epsd > 4) || (map > 9)))
- return false;
-
- if ((gamemode == registered)
- && ((epsd > 3) || (map > 9)))
- return false;
-
- if ((gamemode == shareware)
- && ((epsd > 1) || (map > 9)))
- return false;
-
- if ((gamemode == commercial)
- && (( epsd > 1) || (map > 34)))
- return false;
-
- // So be it.
- plyr->message = DEH_String(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;
- angle_t 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)
- {
- if (plyr->bonuscount)
- {
- // picking up bonus
- doevilgrin = false;
-
- for (i=0;i<NUMWEAPONS;i++)
- {
- if (oldweaponsowned[i] != plyr->weaponowned[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)
- {
- if (plyr->damagecount
- && plyr->attacker
- && plyr->attacker != plyr->mo)
- {
- // being attacked
- 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)
- {
- // whether right or left
- diffang = badguyangle - plyr->mo->angle;
- i = diffang > ANG180;
- }
- else
- {
- // whether left or right
- diffang = plyr->mo->angle - badguyangle;
- i = diffang <= ANG180;
- } // confusing, aint it?
-
-
- st_facecount = ST_TURNCOUNT;
- st_faceindex = ST_calcPainOffset();
-
- if (diffang < ANG45)
- {
- // head-on
- st_faceindex += ST_RAMPAGEOFFSET;
- }
- else if (i)
- {
- // turn face right
- st_faceindex += ST_TURNOFFSET;
- }
- else
- {
- // turn face left
- st_faceindex += ST_TURNOFFSET+1;
- }
- }
- }
- }
-
- 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();
-
- // used by the w_armsbg widget
- st_notdeathmatch = !deathmatch;
-
- // used by w_arms[] widgets
- st_armson = st_statusbaron && !deathmatch;
-
- // used by w_frags widget
- st_fragson = deathmatch && st_statusbaron;
- st_fragscount = 0;
-
- for (i=0 ; i<MAXPLAYERS ; i++)
- {
- if (i != consoleplayer)
- st_fragscount += plyr->frags[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;
- int 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;
-
- // used by w_arms[] widgets
- st_armson = st_statusbaron && !deathmatch;
-
- // used by w_frags widget
- st_fragson = deathmatch && st_statusbaron;
-
- 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();
-
-}
-
-typedef void (*load_callback_t)(char *lumpname, patch_t **variable);
-
-// Iterates through all graphics to be loaded or unloaded, along with
-// the variable they use, invoking the specified callback function.
-
-static void ST_loadUnloadGraphics(load_callback_t callback)
-{
-
- int i;
- int j;
- int facenum;
-
- char namebuf[9];
-
- // Load the numbers, tall and short
- for (i=0;i<10;i++)
- {
- sprintf(namebuf, DEH_String("STTNUM%d"), i);
- callback(namebuf, &tallnum[i]);
-
- sprintf(namebuf, DEH_String("STYSNUM%d"), i);
- callback(namebuf, &shortnum[i]);
- }
-
- // Load percent key.
- //Note: why not load STMINUS here, too?
-
- callback(DEH_String("STTPRCNT"), &tallpercent);
-
- // key cards
- for (i=0;i<NUMCARDS;i++)
- {
- sprintf(namebuf, DEH_String("STKEYS%d"), i);
- callback(namebuf, &keys[i]);
- }
-
- // arms background
- callback(DEH_String("STARMS"), &armsbg);
-
- // arms ownership widgets
- for (i=0; i<6; i++)
- {
- sprintf(namebuf, DEH_String("STGNUM%d"), i+2);
-
- // gray #
- callback(namebuf, &arms[i][0]);
-
- // yellow #
- arms[i][1] = shortnum[i+2];
- }
-
- // face backgrounds for different color players
- sprintf(namebuf, DEH_String("STFB%d"), consoleplayer);
- callback(namebuf, &faceback);
-
- // status bar background bits
- callback(DEH_String("STBAR"), &sbar);
-
- // face states
- facenum = 0;
- for (i=0; i<ST_NUMPAINFACES; i++)
- {
- for (j=0; j<ST_NUMSTRAIGHTFACES; j++)
- {
- sprintf(namebuf, DEH_String("STFST%d%d"), i, j);
- callback(namebuf, &faces[facenum]);
- ++facenum;
- }
- sprintf(namebuf, DEH_String("STFTR%d0"), i); // turn right
- callback(namebuf, &faces[facenum]);
- ++facenum;
- sprintf(namebuf, DEH_String("STFTL%d0"), i); // turn left
- callback(namebuf, &faces[facenum]);
- ++facenum;
- sprintf(namebuf, DEH_String("STFOUCH%d"), i); // ouch!
- callback(namebuf, &faces[facenum]);
- ++facenum;
- sprintf(namebuf, DEH_String("STFEVL%d"), i); // evil grin ;)
- callback(namebuf, &faces[facenum]);
- ++facenum;
- sprintf(namebuf, DEH_String("STFKILL%d"), i); // pissed off
- callback(namebuf, &faces[facenum]);
- ++facenum;
- }
-
- callback(DEH_String("STFGOD0"), &faces[facenum]);
- ++facenum;
- callback(DEH_String("STFDEAD0"), &faces[facenum]);
- ++facenum;
-}
-
-static void ST_loadCallback(char *lumpname, patch_t **variable)
-{
- *variable = W_CacheLumpName(lumpname, PU_STATIC);
-}
-
-void ST_loadGraphics(void)
-{
- ST_loadUnloadGraphics(ST_loadCallback);
-}
-
-void ST_loadData(void)
-{
- lu_palette = W_GetNumForName (DEH_String("PLAYPAL"));
- ST_loadGraphics();
-}
-
-static void ST_unloadCallback(char *lumpname, patch_t **variable)
-{
- W_ReleaseLumpName(lumpname);
- *variable = NULL;
-}
-
-void ST_unloadGraphics(void)
-{
- ST_loadUnloadGraphics(ST_unloadCallback);
-}
-
-void ST_unloadData(void)
-{
- ST_unloadGraphics();
-}
-
-void ST_initData(void)
-{
-
- int i;
-
- st_firsttime = true;
- plyr = &players[consoleplayer];
-
- st_clock = 0;
- st_chatstate = StartChatState;
- st_gamestate = FirstPersonState;
-
- st_statusbaron = true;
- st_oldchat = st_chat = false;
- st_cursoron = false;
-
- st_faceindex = 0;
- st_palette = -1;
-
- st_oldhealth = -1;
-
- for (i=0;i<NUMWEAPONS;i++)
- oldweaponsowned[i] = plyr->weaponowned[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 );
-
- // the last weapon type
- w_ready.data = plyr->readyweapon;
-
- // 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);
-}
--- a/src/st_stuff.h
+++ /dev/null
@@ -1,97 +1,0 @@
-// Emacs style mode select -*- C++ -*-
-//-----------------------------------------------------------------------------
-//
-// Copyright(C) 1993-1996 Id Software, Inc.
-// Copyright(C) 2005 Simon Howard
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-// 02111-1307, USA.
-//
-// DESCRIPTION:
-// Status bar code.
-// Does the face/direction indicator animatin.
-// Does palette indicators as well (red pain/berserk, bright pickup)
-//
-//-----------------------------------------------------------------------------
-
-#ifndef __STSTUFF_H__
-#define __STSTUFF_H__
-
-#include "doomtype.h"
-#include "d_event.h"
-#include "m_cheat.h"
-
-// Size of statusbar.
-// Now sensitive for scaling.
-#define ST_HEIGHT 32
-#define ST_WIDTH SCREENWIDTH
-#define ST_Y (SCREENHEIGHT - ST_HEIGHT)
-
-
-//
-// STATUS BAR
-//
-
-// Called by main loop.
-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 when the console player is spawned on each level.
-void ST_Start (void);
-
-// Called by startup code.
-void ST_Init (void);
-
-
-
-// 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;
-
-
-boolean ST_Responder(event_t* ev);
-
-extern cheatseq_t cheat_mus;
-extern cheatseq_t cheat_god;
-extern cheatseq_t cheat_ammo;
-extern cheatseq_t cheat_ammonokey;
-extern cheatseq_t cheat_noclip;
-extern cheatseq_t cheat_commercial_noclip;
-extern cheatseq_t cheat_powerup[7];
-extern cheatseq_t cheat_choppers;
-extern cheatseq_t cheat_clev;
-extern cheatseq_t cheat_mypos;
-
-
-#endif
--- a/src/wi_stuff.c
+++ /dev/null
@@ -1,1843 +1,0 @@
-// Emacs style mode select -*- C++ -*-
-//-----------------------------------------------------------------------------
-//
-// Copyright(C) 1993-1996 Id Software, Inc.
-// Copyright(C) 2005 Simon Howard
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-// 02111-1307, USA.
-//
-// DESCRIPTION:
-// Intermission screens.
-//
-//-----------------------------------------------------------------------------
-
-
-#include <stdio.h>
-
-#include "z_zone.h"
-
-#include "m_random.h"
-
-#include "deh_main.h"
-#include "i_swap.h"
-#include "i_system.h"
-
-#include "w_wad.h"
-
-#include "g_game.h"
-
-#include "r_local.h"
-#include "s_sound.h"
-
-#include "doomstat.h"
-
-// Data.
-#include "sounds.h"
-
-// Needs access to LFB.
-#include "v_video.h"
-
-#include "wi_stuff.h"
-
-//
-// Data needed to add patches to full screen intermission pics.
-// Patches are statistics messages, and animations.
-// Loads of by-pixel layout and placement, offsets etc.
-//
-
-
-//
-// Different vetween registered DOOM (1994) and
-// Ultimate DOOM - Final edition (retail, 1995?).
-// This is supposedly ignored for commercial
-// release (aka DOOM II), which had 34 maps
-// in one episode. So there.
-#define NUMEPISODES 4
-#define NUMMAPS 9
-
-
-// in tics
-//U #define PAUSELEN (TICRATE*2)
-//U #define SCORESTEP 100
-//U #define ANIMPERIOD 32
-// pixel distance from "(YOU)" to "PLAYER N"
-//U #define STARDIST 10
-//U #define WK 1
-
-
-// GLOBAL LOCATIONS
-#define WI_TITLEY 2
-#define WI_SPACINGY 33
-
-// SINGPLE-PLAYER STUFF
-#define SP_STATSX 50
-#define SP_STATSY 50
-
-#define SP_TIMEX 16
-#define SP_TIMEY (SCREENHEIGHT-32)
-
-
-// NET GAME STUFF
-#define NG_STATSY 50
-#define NG_STATSX (32 + SHORT(star->width)/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
-
-
-
-
-typedef enum
-{
- ANIM_ALWAYS,
- ANIM_RANDOM,
- ANIM_LEVEL
-
-} animenum_t;
-
-typedef struct
-{
- int x;
- int y;
-
-} point_t;
-
-
-//
-// Animation.
-// There is another anim_t used in p_spec.
-//
-typedef struct
-{
- animenum_t type;
-
- // period in tics between animations
- int period;
-
- // number of animation frames
- int nanims;
-
- // location of animation
- point_t loc;
-
- // ALWAYS: n/a,
- // RANDOM: period deviation (<256),
- // LEVEL: level
- int data1;
-
- // ALWAYS: n/a,
- // RANDOM: random base period,
- // LEVEL: n/a
- int data2;
-
- // actual graphics for frames of animations
- patch_t* p[3];
-
- // following must be initialized to zero before use!
-
- // next value of bcnt (used in conjunction with period)
- int nexttic;
-
- // last drawn animation frame
- int lastdrawn;
-
- // next frame number to animate
- int ctr;
-
- // used by RANDOM and LEVEL when animating
- int state;
-
-} anim_t;
-
-
-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).
-// Using patches saves a lot of space,
-// as they replace 320x200 full screen frames.
-//
-
-#define ANIM(type, period, nanims, x, y, nexttic) \
- { (type), (period), (nanims), { (x), (y) }, (nexttic), \
- 0, { NULL, NULL, NULL }, 0, 0, 0, 0 }
-
-
-static anim_t epsd0animinfo[] =
-{
- ANIM(ANIM_ALWAYS, TICRATE/3, 3, 224, 104, 0),
- ANIM(ANIM_ALWAYS, TICRATE/3, 3, 184, 160, 0),
- ANIM(ANIM_ALWAYS, TICRATE/3, 3, 112, 136, 0),
- ANIM(ANIM_ALWAYS, TICRATE/3, 3, 72, 112, 0),
- ANIM(ANIM_ALWAYS, TICRATE/3, 3, 88, 96, 0),
- ANIM(ANIM_ALWAYS, TICRATE/3, 3, 64, 48, 0),
- ANIM(ANIM_ALWAYS, TICRATE/3, 3, 192, 40, 0),
- ANIM(ANIM_ALWAYS, TICRATE/3, 3, 136, 16, 0),
- ANIM(ANIM_ALWAYS, TICRATE/3, 3, 80, 16, 0),
- ANIM(ANIM_ALWAYS, TICRATE/3, 3, 64, 24, 0),
-};
-
-static anim_t epsd1animinfo[] =
-{
- ANIM(ANIM_LEVEL, TICRATE/3, 1, 128, 136, 1),
- ANIM(ANIM_LEVEL, TICRATE/3, 1, 128, 136, 2),
- ANIM(ANIM_LEVEL, TICRATE/3, 1, 128, 136, 3),
- ANIM(ANIM_LEVEL, TICRATE/3, 1, 128, 136, 4),
- ANIM(ANIM_LEVEL, TICRATE/3, 1, 128, 136, 5),
- ANIM(ANIM_LEVEL, TICRATE/3, 1, 128, 136, 6),
- ANIM(ANIM_LEVEL, TICRATE/3, 1, 128, 136, 7),
- ANIM(ANIM_LEVEL, TICRATE/3, 3, 192, 144, 8),
- ANIM(ANIM_LEVEL, TICRATE/3, 1, 128, 136, 8),
-};
-
-static anim_t epsd2animinfo[] =
-{
- ANIM(ANIM_ALWAYS, TICRATE/3, 3, 104, 168, 0),
- ANIM(ANIM_ALWAYS, TICRATE/3, 3, 40, 136, 0),
- ANIM(ANIM_ALWAYS, TICRATE/3, 3, 160, 96, 0),
- ANIM(ANIM_ALWAYS, TICRATE/3, 3, 104, 80, 0),
- ANIM(ANIM_ALWAYS, TICRATE/3, 3, 120, 32, 0),
- ANIM(ANIM_ALWAYS, TICRATE/4, 3, 40, 0, 0),
-};
-
-static int NUMANIMS[NUMEPISODES] =
-{
- arrlen(epsd0animinfo),
- arrlen(epsd1animinfo),
- arrlen(epsd2animinfo),
-};
-
-static anim_t *anims[NUMEPISODES] =
-{
- epsd0animinfo,
- epsd1animinfo,
- epsd2animinfo
-};
-
-
-//
-// GENERAL DATA
-//
-
-//
-// Locally used stuff.
-//
-#define FB 0
-
-
-// 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
-
-// in seconds
-#define SHOWNEXTLOCDELAY 4
-//#define SHOWLASTLOCDELAY SHOWNEXTLOCDELAY
-
-
-// used to accelerate or skip a stage
-static int acceleratestage;
-
-// wbs->pnum
-static int me;
-
- // specifies current state
-static stateenum_t state;
-
-// contains information passed into intermission
-static wbstartstruct_t* wbs;
-
-static wbplayerstruct_t* plrs; // wbs->plyr[]
-
-// used for general timing
-static int cnt;
-
-// used for timing of background animation
-static int bcnt;
-
-// signals to refresh everything for one frame
-static int firstrefresh;
-
-static int cnt_kills[MAXPLAYERS];
-static int cnt_items[MAXPLAYERS];
-static int cnt_secret[MAXPLAYERS];
-static int cnt_time;
-static int cnt_par;
-static int cnt_pause;
-
-// # of commercial levels
-static int NUMCMAPS;
-
-
-//
-// GRAPHICS
-//
-
-// You Are Here graphic
-static patch_t* yah[3] = { NULL, NULL, NULL };
-
-// splat
-static patch_t* splat[2] = { NULL, NULL };
-
-// %, : graphics
-static patch_t* percent;
-static patch_t* colon;
-
-// 0-9 graphic
-static patch_t* num[10];
-
-// minus sign
-static patch_t* wiminus;
-
-// "Finished!" graphics
-static patch_t* finished;
-
-// "Entering" graphic
-static patch_t* entering;
-
-// "secret"
-static patch_t* sp_secret;
-
- // "Kills", "Scrt", "Items", "Frags"
-static patch_t* kills;
-static patch_t* secret;
-static patch_t* items;
-static patch_t* frags;
-
-// Time sucks.
-static patch_t* timepatch;
-static patch_t* par;
-static patch_t* sucks;
-
-// "killers", "victims"
-static patch_t* killers;
-static patch_t* victims;
-
-// "Total", your face, your dead face
-static patch_t* total;
-static patch_t* star;
-static patch_t* bstar;
-
-// "red P[1..MAXPLAYERS]"
-static patch_t* p[MAXPLAYERS];
-
-// "gray P[1..MAXPLAYERS]"
-static patch_t* bp[MAXPLAYERS];
-
- // Name graphics of each level (centered)
-static patch_t** lnames;
-
-//
-// CODE
-//
-
-// slam background
-// UNUSED 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 "<Levelname> Finished!"
-void WI_drawLF(void)
-{
- int y = WI_TITLEY;
-
- // draw <LevelName>
- 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 <LevelName>"
-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;
- int left;
- int top;
- int right;
- int 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 && c[i] != NULL);
-
- if (fits && i<2)
- {
- V_DrawPatch(lnodes[wbs->epsd][n].x, lnodes[wbs->epsd][n].y,
- FB, c[i]);
- }
- else
- {
- // DEBUG
- printf("Could not place patch on level %d", n+1);
- }
-}
-
-
-
-void WI_initAnimatedBack(void)
-{
- int i;
- anim_t* a;
-
- if (gamemode == commercial)
- return;
-
- if (wbs->epsd > 2)
- return;
-
- for (i=0;i<NUMANIMS[wbs->epsd];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 (gamemode == commercial)
- return;
-
- if (wbs->epsd > 2)
- return;
-
- for (i=0;i<NUMANIMS[wbs->epsd];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 (gamemode == commercial)
- return;
-
- if (wbs->epsd > 2)
- return;
-
- for (i=0 ; i<NUMANIMS[wbs->epsd] ; 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)
- {
- // make variable-length zeros 1 digit long
- digits = 1;
- }
- 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, do not 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);
-}
-
-
-
-//
-// Display level completion time and par,
-// or "sucks" message if overflow.
-//
-void
-WI_drawTime
-( int x,
- int y,
- int t )
-{
-
- int div;
- int 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;
-
- // draw
- if (div==60 || t / div)
- V_DrawPatch(x, y, FB, colon);
-
- } while (t / div);
- }
- else
- {
- // "sucks"
- V_DrawPatch(x - SHORT(sucks->width), y, FB, 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)
- {
- // Don't call WI_End yet. G_WorldDone doesnt immediately
- // change gamestate, so WI_Drawer is still going to get
- // run until that happens. If we do that after WI_End
- // (which unloads all the graphics), we're in trouble.
- //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;
- int last;
-
- WI_slamBackground();
-
- // draw animated background
- WI_drawAnimatedBack();
-
- if ( gamemode != commercial)
- {
- if (wbs->epsd > 2)
- {
- WI_drawEL();
- return;
- }
-
- last = (wbs->last == 8) ? wbs->next - 1 : wbs->last;
-
- // draw a splat on taken cities.
- for (i=0 ; i<=last ; i++)
- WI_drawOnLnode(i, splat);
-
- // splat the secret level?
- if (wbs->didsecret)
- WI_drawOnLnode(8, splat);
-
- // draw flashing ptr
- if (snl_pointeron)
- WI_drawOnLnode(wbs->next, yah);
- }
-
- // draws which level you are entering..
- if ( (gamemode != commercial)
- || wbs->next != 30)
- WI_drawEL();
-
-}
-
-void WI_drawNoState(void)
-{
- snl_pointeron = true;
- WI_drawShowNextLoc();
-}
-
-int WI_fragSum(int playernum)
-{
- int i;
- int frags = 0;
-
- for (i=0 ; i<MAXPLAYERS ; i++)
- {
- if (playeringame[i]
- && i!=playernum)
- {
- frags += plrs[playernum].frags[i];
- }
- }
-
-
- // JDC hack - negative frags.
- frags -= plrs[playernum].frags[playernum];
- // UNUSED if (frags < 0)
- // frags = 0;
-
- return frags;
-}
-
-
-
-static int dm_state;
-static int dm_frags[MAXPLAYERS][MAXPLAYERS];
-static int dm_totals[MAXPLAYERS];
-
-
-
-void WI_initDeathmatchStats(void)
-{
-
- int i;
- int j;
-
- state = StatCount;
- acceleratestage = 0;
- dm_state = 1;
-
- cnt_pause = TICRATE;
-
- for (i=0 ; i<MAXPLAYERS ; i++)
- {
- if (playeringame[i])
- {
- for (j=0 ; j<MAXPLAYERS ; j++)
- if (playeringame[j])
- dm_frags[i][j] = 0;
-
- dm_totals[i] = 0;
- }
- }
-
- WI_initAnimatedBack();
-}
-
-
-
-void WI_updateDeathmatchStats(void)
-{
-
- int i;
- int j;
-
- boolean stillticking;
-
- WI_updateAnimatedBack();
-
- if (acceleratestage && dm_state != 4)
- {
- acceleratestage = 0;
-
- for (i=0 ; i<MAXPLAYERS ; i++)
- {
- if (playeringame[i])
- {
- for (j=0 ; j<MAXPLAYERS ; j++)
- if (playeringame[j])
- dm_frags[i][j] = plrs[i].frags[j];
-
- dm_totals[i] = WI_fragSum(i);
- }
- }
-
-
- S_StartSound(0, sfx_barexp);
- dm_state = 4;
- }
-
-
- if (dm_state == 2)
- {
- if (!(bcnt&3))
- S_StartSound(0, sfx_pistol);
-
- stillticking = false;
-
- for (i=0 ; i<MAXPLAYERS ; i++)
- {
- if (playeringame[i])
- {
- for (j=0 ; j<MAXPLAYERS ; j++)
- {
- if (playeringame[j]
- && dm_frags[i][j] != plrs[i].frags[j])
- {
- if (plrs[i].frags[j] < 0)
- dm_frags[i][j]--;
- else
- dm_frags[i][j]++;
-
- if (dm_frags[i][j] > 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 ( gamemode == 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;
- int j;
- int x;
- int y;
- int w;
-
- int lh; // line height
-
- lh = WI_SPACINGY;
-
- WI_slamBackground();
-
- // draw animated background
- WI_drawAnimatedBack();
- 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?
- x = DM_MATRIXX + DM_SPACINGX;
- y = DM_MATRIXY;
-
- for (i=0 ; i<MAXPLAYERS ; i++)
- {
- if (playeringame[i])
- {
- V_DrawPatch(x-SHORT(p[i]->width)/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 ; i<MAXPLAYERS ; i++)
- {
- x = DM_MATRIXX + DM_SPACINGX;
-
- if (playeringame[i])
- {
- for (j=0 ; j<MAXPLAYERS ; j++)
- {
- if (playeringame[j])
- WI_drawNum(x+w, y, dm_frags[i][j], 2);
-
- x += DM_SPACINGX;
- }
- WI_drawNum(DM_TOTALSX+w, y, dm_totals[i], 2);
- }
- y += WI_SPACINGY;
- }
-}
-
-static int cnt_frags[MAXPLAYERS];
-static int dofrags;
-static int ng_state;
-
-void WI_initNetgameStats(void)
-{
-
- int i;
-
- state = StatCount;
- acceleratestage = 0;
- ng_state = 1;
-
- cnt_pause = TICRATE;
-
- for (i=0 ; i<MAXPLAYERS ; i++)
- {
- if (!playeringame[i])
- continue;
-
- cnt_kills[i] = cnt_items[i] = cnt_secret[i] = cnt_frags[i] = 0;
-
- dofrags += WI_fragSum(i);
- }
-
- dofrags = !!dofrags;
-
- WI_initAnimatedBack();
-}
-
-
-
-void WI_updateNetgameStats(void)
-{
-
- int i;
- int fsum;
-
- boolean stillticking;
-
- WI_updateAnimatedBack();
-
- if (acceleratestage && ng_state != 10)
- {
- acceleratestage = 0;
-
- for (i=0 ; i<MAXPLAYERS ; i++)
- {
- if (!playeringame[i])
- continue;
-
- cnt_kills[i] = (plrs[i].skills * 100) / wbs->maxkills;
- 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<MAXPLAYERS ; i++)
- {
- if (!playeringame[i])
- continue;
-
- cnt_kills[i] += 2;
-
- if (cnt_kills[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<MAXPLAYERS ; i++)
- {
- if (!playeringame[i])
- continue;
-
- cnt_items[i] += 2;
- if (cnt_items[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<MAXPLAYERS ; i++)
- {
- if (!playeringame[i])
- continue;
-
- cnt_secret[i] += 2;
-
- if (cnt_secret[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<MAXPLAYERS ; i++)
- {
- if (!playeringame[i])
- continue;
-
- cnt_frags[i] += 1;
-
- if (cnt_frags[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 ( gamemode == 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;
- int x;
- int y;
- int pwidth = SHORT(percent->width);
-
- WI_slamBackground();
-
- // draw animated background
- WI_drawAnimatedBack();
-
- 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 ; i<MAXPLAYERS ; i++)
- {
- if (!playeringame[i])
- continue;
-
- x = NG_STATSX;
- V_DrawPatch(x-SHORT(p[i]->width), 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 (gamemode == commercial)
- WI_initNoState();
- else
- WI_initShowNextLoc();
- }
- }
- else if (sp_state & 1)
- {
- if (!--cnt_pause)
- {
- sp_state++;
- cnt_pause = TICRATE;
- }
- }
-
-}
-
-void WI_drawStats(void)
-{
- // line height
- int lh;
-
- lh = (3*SHORT(num[0]->height))/2;
-
- WI_slamBackground();
-
- // draw animated background
- WI_drawAnimatedBack();
-
- 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, timepatch);
- WI_drawTime(SCREENWIDTH/2 - SP_TIMEX, SP_TIMEY, cnt_time);
-
- if (wbs->epsd < 3)
- {
- 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 ; i<MAXPLAYERS ; i++, player++)
- {
- if (playeringame[i])
- {
- if (player->cmd.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)
-{
- // counter for general background animation
- bcnt++;
-
- if (bcnt == 1)
- {
- // intermission music
- if ( gamemode == commercial )
- S_ChangeMusic(mus_dm2int, true);
- else
- S_ChangeMusic(mus_inter, true);
- }
-
- 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;
- }
-
-}
-
-typedef void (*load_callback_t)(char *lumpname, patch_t **variable);
-
-// Common load/unload function. Iterates over all the graphics
-// lumps to be loaded/unloaded into memory.
-
-static void WI_loadUnloadData(load_callback_t callback)
-{
- int i;
- int j;
- char name[9];
- anim_t* a;
-
- // UNUSED unsigned char *pic = screens[1];
- // if (gamemode == commercial)
- // {
- // darken the background image
- // while (pic != screens[1] + SCREENHEIGHT*SCREENWIDTH)
- // {
- // *pic = colormaps[256*25 + *pic];
- // pic++;
- // }
- //}
-
- if (gamemode == commercial)
- {
- for (i=0 ; i<NUMCMAPS ; i++)
- {
- sprintf(name, DEH_String("CWILV%2.2d"), i);
- callback(name, &lnames[i]);
- }
- }
- else
- {
- for (i=0 ; i<NUMMAPS ; i++)
- {
- sprintf(name, DEH_String("WILV%d%d"), wbs->epsd, i);
- callback(name, &lnames[i]);
- }
-
- // you are here
- callback(DEH_String("WIURH0"), &yah[0]);
-
- // you are here (alt.)
- callback(DEH_String("WIURH1"), &yah[1]);
-
- // splat
- callback(DEH_String("WISPLAT"), &splat[0]);
-
- if (wbs->epsd < 3)
- {
- for (j=0;j<NUMANIMS[wbs->epsd];j++)
- {
- a = &anims[wbs->epsd][j];
- for (i=0;i<a->nanims;i++)
- {
- // MONDO HACK!
- if (wbs->epsd != 1 || j != 8)
- {
- // animations
- sprintf(name, DEH_String("WIA%d%.2d%.2d"),
- wbs->epsd, j, i);
- callback(name, &a->p[i]);
- }
- else
- {
- // HACK ALERT!
- a->p[i] = anims[1][4].p[i];
- }
- }
- }
- }
- }
-
- // More hacks on minus sign.
- callback(DEH_String("WIMINUS"), &wiminus);
-
- for (i=0;i<10;i++)
- {
- // numbers 0-9
- sprintf(name, DEH_String("WINUM%d"), i);
- callback(name, &num[i]);
- }
-
- // percent sign
- callback(DEH_String("WIPCNT"), &percent);
-
- // "finished"
- callback(DEH_String("WIF"), &finished);
-
- // "entering"
- callback(DEH_String("WIENTER"), &entering);
-
- // "kills"
- callback(DEH_String("WIOSTK"), &kills);
-
- // "scrt"
- callback(DEH_String("WIOSTS"), &secret);
-
- // "secret"
- callback(DEH_String("WISCRT2"), &sp_secret);
-
- // french wad uses WIOBJ (?)
- if (W_CheckNumForName(DEH_String("WIOBJ")) >= 0)
- {
- // "items"
- if (netgame && !deathmatch)
- callback(DEH_String("WIOBJ"), &items);
- else
- callback(DEH_String("WIOSTI"), &items);
- } else {
- callback(DEH_String("WIOSTI"), &items);
- }
-
- // "frgs"
- callback(DEH_String("WIFRGS"), &frags);
-
- // ":"
- callback(DEH_String("WICOLON"), &colon);
-
- // "time"
- callback(DEH_String("WITIME"), &timepatch);
-
- // "sucks"
- callback(DEH_String("WISUCKS"), &sucks);
-
- // "par"
- callback(DEH_String("WIPAR"), &par);
-
- // "killers" (vertical)
- callback(DEH_String("WIKILRS"), &killers);
-
- // "victims" (horiz)
- callback(DEH_String("WIVCTMS"), &victims);
-
- // "total"
- callback(DEH_String("WIMSTT"), &total);
-
- for (i=0 ; i<MAXPLAYERS ; i++)
- {
- // "1,2,3,4"
- sprintf(name, DEH_String("STPB%d"), i);
- callback(name, &p[i]);
-
- // "1,2,3,4"
- sprintf(name, DEH_String("WIBP%d"), i+1);
- callback(name, &bp[i]);
- }
-
-}
-
-static void WI_loadCallback(char *name, patch_t **variable)
-{
- *variable = W_CacheLumpName(name, PU_STATIC);
-}
-
-void WI_loadData(void)
-{
- char bg_lumpname[9];
- patch_t *bg;
-
- if (gamemode == commercial)
- {
- NUMCMAPS = 32;
- lnames = (patch_t **) Z_Malloc(sizeof(patch_t*) * NUMCMAPS,
- PU_STATIC, NULL);
- }
- else
- {
- lnames = (patch_t **) Z_Malloc(sizeof(patch_t*) * NUMMAPS,
- PU_STATIC, NULL);
- }
-
- WI_loadUnloadData(WI_loadCallback);
-
- // These two graphics are special cased because we're sharing
- // them with the status bar code
-
- // your face
- star = W_CacheLumpName(DEH_String("STFST01"), PU_STATIC);
-
- // dead face
- bstar = W_CacheLumpName(DEH_String("STFDEAD0"), PU_STATIC);
-
- // Background image
-
- if (gamemode == commercial)
- {
- strcpy(bg_lumpname, DEH_String("INTERPIC"));
- }
- else if (gamemode == retail && wbs->epsd == 3)
- {
- strcpy(bg_lumpname, DEH_String("INTERPIC"));
- }
- else
- {
- sprintf(bg_lumpname, DEH_String("WIMAP%d"), wbs->epsd);
- }
-
- bg = W_CacheLumpName(bg_lumpname, PU_CACHE);
- V_DrawPatch(0, 0, 1, bg);
-}
-
-static void WI_unloadCallback(char *name, patch_t **variable)
-{
- W_ReleaseLumpName(name);
- *variable = NULL;
-}
-
-void WI_unloadData(void)
-{
- WI_loadUnloadData(WI_unloadCallback);
-
- // We do not free these lumps as they are shared with the status
- // bar code.
-
- // W_ReleaseLumpName("STFST01");
- // W_ReleaseLumpName("STFDEAD0");
-}
-
-void WI_Drawer (void)
-{
- switch (state)
- {
- case StatCount:
- if (deathmatch)
- WI_drawDeathmatchStats();
- else if (netgame)
- WI_drawNetgameStats();
- else
- WI_drawStats();
- break;
-
- case ShowNextLoc:
- WI_drawShowNextLoc();
- break;
-
- case NoState:
- WI_drawNoState();
- break;
- }
-}
-
-
-void WI_initVariables(wbstartstruct_t* wbstartstruct)
-{
-
- wbs = wbstartstruct;
-
-#ifdef RANGECHECKING
- if (gamemode != commercial)
- {
- if ( gamemode == retail )
- RNGCHECK(wbs->epsd, 0, 3);
- else
- RNGCHECK(wbs->epsd, 0, 2);
- }
- else
- {
- 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 ( gamemode != retail )
- 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();
-}
--- a/src/wi_stuff.h
+++ /dev/null
@@ -1,56 +1,0 @@
-// Emacs style mode select -*- C++ -*-
-//-----------------------------------------------------------------------------
-//
-// Copyright(C) 1993-1996 Id Software, Inc.
-// Copyright(C) 2005 Simon Howard
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-// 02111-1307, USA.
-//
-// DESCRIPTION:
-// Intermission.
-//
-//-----------------------------------------------------------------------------
-
-#ifndef __WI_STUFF__
-#define __WI_STUFF__
-
-//#include "v_video.h"
-
-#include "doomdef.h"
-
-// States for the intermission
-
-typedef enum
-{
- NoState = -1,
- StatCount,
- ShowNextLoc,
-} stateenum_t;
-
-// Called by main loop, animate the intermission.
-void WI_Ticker (void);
-
-// Called by main loop,
-// draws the intermission directly into the screen buffer.
-void WI_Drawer (void);
-
-// Setup for an intermission screen.
-void WI_Start(wbstartstruct_t* wbstartstruct);
-
-// Shut down the intermission screen
-void WI_End(void);
-
-#endif