summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Chapman <dave@dchapman.com>2006-03-28 15:44:01 +0000
committerDave Chapman <dave@dchapman.com>2006-03-28 15:44:01 +0000
commit47f4a458d636a889e955e68f896708f1276febc0 (patch)
tree99f770c02ef606f0abbdcd332ac39e69830d8007
parentfff7d6157d56f233cad5c2003475e47a5ff809a7 (diff)
downloadrockbox-47f4a458d636a889e955e68f896708f1276febc0.tar.gz
rockbox-47f4a458d636a889e955e68f896708f1276febc0.zip
Patch #2969 - Doom! Currently only working on the H300.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@9312 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--apps/plugin.c6
-rw-r--r--apps/plugin.h7
-rw-r--r--apps/plugins/Makefile5
-rw-r--r--apps/plugins/doom/Changelog47
-rw-r--r--apps/plugins/doom/Makefile145
-rw-r--r--apps/plugins/doom/am_map.c1702
-rw-r--r--apps/plugins/doom/am_map.h106
-rw-r--r--apps/plugins/doom/d_englsh.h705
-rw-r--r--apps/plugins/doom/d_event.h128
-rw-r--r--apps/plugins/doom/d_french.h437
-rw-r--r--apps/plugins/doom/d_items.c138
-rw-r--r--apps/plugins/doom/d_items.h57
-rw-r--r--apps/plugins/doom/d_main.c844
-rw-r--r--apps/plugins/doom/d_main.h74
-rw-r--r--apps/plugins/doom/d_net.c149
-rw-r--r--apps/plugins/doom/d_net.h213
-rw-r--r--apps/plugins/doom/d_player.h232
-rw-r--r--apps/plugins/doom/d_think.h92
-rw-r--r--apps/plugins/doom/d_ticcmd.h57
-rw-r--r--apps/plugins/doom/doomdata.h187
-rw-r--r--apps/plugins/doom/doomdef.c39
-rw-r--r--apps/plugins/doom/doomdef.h306
-rw-r--r--apps/plugins/doom/doomstat.c104
-rw-r--r--apps/plugins/doom/doomstat.h373
-rw-r--r--apps/plugins/doom/doomtype.h85
-rw-r--r--apps/plugins/doom/dstrings.c83
-rw-r--r--apps/plugins/doom/dstrings.h73
-rw-r--r--apps/plugins/doom/f_finale.c682
-rw-r--r--apps/plugins/doom/f_finale.h54
-rw-r--r--apps/plugins/doom/f_wipe.c193
-rw-r--r--apps/plugins/doom/f_wipe.h43
-rw-r--r--apps/plugins/doom/g_game.c2818
-rw-r--r--apps/plugins/doom/g_game.h192
-rw-r--r--apps/plugins/doom/hu_lib.c770
-rw-r--r--apps/plugins/doom/hu_lib.h264
-rw-r--r--apps/plugins/doom/hu_stuff.c1753
-rw-r--r--apps/plugins/doom/hu_stuff.h92
-rw-r--r--apps/plugins/doom/i_sound.c607
-rw-r--r--apps/plugins/doom/i_sound.h126
-rw-r--r--apps/plugins/doom/i_system.c134
-rw-r--r--apps/plugins/doom/i_system.h65
-rw-r--r--apps/plugins/doom/i_video.c454
-rw-r--r--apps/plugins/doom/i_video.h56
-rw-r--r--apps/plugins/doom/info.c5185
-rw-r--r--apps/plugins/doom/info.h1454
-rw-r--r--apps/plugins/doom/m_argv.c53
-rw-r--r--apps/plugins/doom/m_argv.h45
-rw-r--r--apps/plugins/doom/m_bbox.c58
-rw-r--r--apps/plugins/doom/m_bbox.h54
-rw-r--r--apps/plugins/doom/m_cheat.c104
-rw-r--r--apps/plugins/doom/m_cheat.h63
-rw-r--r--apps/plugins/doom/m_fixed.h94
-rw-r--r--apps/plugins/doom/m_menu.c1848
-rw-r--r--apps/plugins/doom/m_menu.h121
-rw-r--r--apps/plugins/doom/m_misc.c1077
-rw-r--r--apps/plugins/doom/m_misc.h112
-rw-r--r--apps/plugins/doom/m_random.c136
-rw-r--r--apps/plugins/doom/m_random.h148
-rw-r--r--apps/plugins/doom/m_swap.h104
-rw-r--r--apps/plugins/doom/p_ceilng.c468
-rw-r--r--apps/plugins/doom/p_doors.c672
-rw-r--r--apps/plugins/doom/p_enemy.c2623
-rw-r--r--apps/plugins/doom/p_enemy.h50
-rw-r--r--apps/plugins/doom/p_floor.c1035
-rw-r--r--apps/plugins/doom/p_genlin.c1154
-rw-r--r--apps/plugins/doom/p_inter.c904
-rw-r--r--apps/plugins/doom/p_inter.h77
-rw-r--r--apps/plugins/doom/p_lights.c437
-rw-r--r--apps/plugins/doom/p_map.c2207
-rw-r--r--apps/plugins/doom/p_map.h90
-rw-r--r--apps/plugins/doom/p_maputl.c700
-rw-r--r--apps/plugins/doom/p_maputl.h91
-rw-r--r--apps/plugins/doom/p_mobj.c1394
-rw-r--r--apps/plugins/doom/p_mobj.h409
-rw-r--r--apps/plugins/doom/p_plats.c434
-rw-r--r--apps/plugins/doom/p_pspr.c853
-rw-r--r--apps/plugins/doom/p_pspr.h93
-rw-r--r--apps/plugins/doom/p_saveg.c987
-rw-r--r--apps/plugins/doom/p_saveg.h63
-rw-r--r--apps/plugins/doom/p_setup.c1255
-rw-r--r--apps/plugins/doom/p_setup.h55
-rw-r--r--apps/plugins/doom/p_sight.c346
-rw-r--r--apps/plugins/doom/p_spec.c3255
-rw-r--r--apps/plugins/doom/p_spec.h1148
-rw-r--r--apps/plugins/doom/p_switch.c1138
-rw-r--r--apps/plugins/doom/p_telept.c322
-rw-r--r--apps/plugins/doom/p_tick.c255
-rw-r--r--apps/plugins/doom/p_tick.h66
-rw-r--r--apps/plugins/doom/p_user.c420
-rw-r--r--apps/plugins/doom/p_user.h45
-rw-r--r--apps/plugins/doom/r_bsp.c576
-rw-r--r--apps/plugins/doom/r_bsp.h78
-rw-r--r--apps/plugins/doom/r_data.c975
-rw-r--r--apps/plugins/doom/r_data.h105
-rw-r--r--apps/plugins/doom/r_defs.h422
-rw-r--r--apps/plugins/doom/r_draw.c677
-rw-r--r--apps/plugins/doom/r_draw.h99
-rw-r--r--apps/plugins/doom/r_main.c531
-rw-r--r--apps/plugins/doom/r_main.h125
-rw-r--r--apps/plugins/doom/r_plane.c434
-rw-r--r--apps/plugins/doom/r_plane.h65
-rw-r--r--apps/plugins/doom/r_segs.c843
-rw-r--r--apps/plugins/doom/r_segs.h42
-rw-r--r--apps/plugins/doom/r_sky.c53
-rw-r--r--apps/plugins/doom/r_sky.h53
-rw-r--r--apps/plugins/doom/r_state.h140
-rw-r--r--apps/plugins/doom/r_things.c976
-rw-r--r--apps/plugins/doom/r_things.h80
-rw-r--r--apps/plugins/doom/rockdoom.c706
-rw-r--r--apps/plugins/doom/rockmacros.h93
-rw-r--r--apps/plugins/doom/s_sound.c608
-rw-r--r--apps/plugins/doom/s_sound.h96
-rw-r--r--apps/plugins/doom/sounds.c240
-rw-r--r--apps/plugins/doom/sounds.h303
-rw-r--r--apps/plugins/doom/st_lib.c372
-rw-r--r--apps/plugins/doom/st_lib.h207
-rw-r--r--apps/plugins/doom/st_stuff.c1153
-rw-r--r--apps/plugins/doom/st_stuff.h101
-rw-r--r--apps/plugins/doom/tables.c2196
-rw-r--r--apps/plugins/doom/tables.h103
-rw-r--r--apps/plugins/doom/v_video.c700
-rw-r--r--apps/plugins/doom/v_video.h185
-rw-r--r--apps/plugins/doom/w_wad.c683
-rw-r--r--apps/plugins/doom/w_wad.h164
-rw-r--r--apps/plugins/doom/wi_stuff.c1989
-rw-r--r--apps/plugins/doom/wi_stuff.h62
-rw-r--r--apps/plugins/doom/z_bmalloc.c117
-rw-r--r--apps/plugins/doom/z_bmalloc.h51
-rw-r--r--apps/plugins/doom/z_zone.c666
-rw-r--r--apps/plugins/doom/z_zone.h117
130 files changed, 65584 insertions, 1 deletions
diff --git a/apps/plugin.c b/apps/plugin.c
index d69fbfc3aa..b18ccb0626 100644
--- a/apps/plugin.c
+++ b/apps/plugin.c
@@ -67,6 +67,8 @@
67#include "bmp.h" 67#include "bmp.h"
68#endif 68#endif
69 69
70#include "backdrop.h"
71
70#ifdef HAVE_REMOTE_LCD 72#ifdef HAVE_REMOTE_LCD
71#include "lcd-remote.h" 73#include "lcd-remote.h"
72#endif 74#endif
@@ -409,6 +411,10 @@ static const struct plugin_api rockbox_api = {
409 i2c_end, 411 i2c_end,
410 i2c_write, 412 i2c_write,
411#endif 413#endif
414
415 vsnprintf,
416 memchr,
417 load_main_backdrop
412}; 418};
413 419
414int plugin_load(const char* plugin, void* parameter) 420int plugin_load(const char* plugin, void* parameter)
diff --git a/apps/plugin.h b/apps/plugin.h
index a2182d6f9b..f9cca6ffc3 100644
--- a/apps/plugin.h
+++ b/apps/plugin.h
@@ -29,6 +29,7 @@
29#define MEM 2 29#define MEM 2
30#endif 30#endif
31 31
32#include <stdarg.h>
32#include <stdbool.h> 33#include <stdbool.h>
33#include <stdio.h> 34#include <stdio.h>
34#include <stdlib.h> 35#include <stdlib.h>
@@ -101,7 +102,7 @@
101#define PLUGIN_MAGIC 0x526F634B /* RocK */ 102#define PLUGIN_MAGIC 0x526F634B /* RocK */
102 103
103/* increase this every time the api struct changes */ 104/* increase this every time the api struct changes */
104#define PLUGIN_API_VERSION 16 105#define PLUGIN_API_VERSION 17
105 106
106/* update this to latest version if a change to the api struct breaks 107/* update this to latest version if a change to the api struct breaks
107 backwards compatibility (and please take the opportunity to sort in any 108 backwards compatibility (and please take the opportunity to sort in any
@@ -479,6 +480,10 @@ struct plugin_api {
479 void (*i2c_end)(void); 480 void (*i2c_end)(void);
480 int (*i2c_write)(int address, unsigned char* buf, int count ); 481 int (*i2c_write)(int address, unsigned char* buf, int count );
481#endif 482#endif
483
484 int (*vsnprintf)(char *buf, int size, const char *fmt, va_list ap);
485 void *(*memchr)(const void *s1, int c, size_t n);
486 bool (*load_main_backdrop)(char* filename);
482}; 487};
483 488
484/* plugin header */ 489/* plugin header */
diff --git a/apps/plugins/Makefile b/apps/plugins/Makefile
index 586eb605da..c59033aab4 100644
--- a/apps/plugins/Makefile
+++ b/apps/plugins/Makefile
@@ -84,6 +84,11 @@ ifneq (,$(strip $(foreach tgt,IPOD_VIDEO IPOD_NANO IPOD_COLOR IRIVER \
84 SUBDIRS += pacbox 84 SUBDIRS += pacbox
85endif 85endif
86 86
87# Build Doom for the H300 and color ipods
88ifneq (,$(strip $(foreach tgt, IRIVER_H300 IPOD_NANO IPOD_COLOR IPOD_VIDEO,$(findstring $(tgt),$(TARGET)))))
89 SUBDIRS += doom
90endif
91
87.PHONY: $(SUBDIRS) 92.PHONY: $(SUBDIRS)
88all: $(BUILDDIR)/libplugin.a $(ROCKS) $(SUBDIRS) $(DEPFILE) 93all: $(BUILDDIR)/libplugin.a $(ROCKS) $(SUBDIRS) $(DEPFILE)
89 94
diff --git a/apps/plugins/doom/Changelog b/apps/plugins/doom/Changelog
new file mode 100644
index 0000000000..2663af17ad
--- /dev/null
+++ b/apps/plugins/doom/Changelog
@@ -0,0 +1,47 @@
1Changelog:
2Fixed Nightmare mode
3Fixed end game
4Fixed quit crash
5Added more prboom rendering code -> speedup
6 expanded rendering code -> speedup
7Rewrote lowquality renderer and moved option to loader -> adds 1 fps to speed
8Changed Default Keys:
9 DOOM PLAYER
10 ------ ------
11 UP REC
12 DOWN DOWN
13 LEFT LEFT
14 RIGHT RIGHT
15 SHOOT MODE
16 OPEN DOWN
17 ESC ON
18 ENTER SELECT
19 WEAPON OFF
20Menu Keys now work independent of ingame keys
21All code reformatted and warnings reduced (only 6 now)
22New Menu code to select options and Base game
23 doom shareware doom1.wad
24 doom registered doom.wad
25 doom retail (ultimate doom) doomu.wad
26 doom 2 doom2.wad
27 plutonia plutonia.wad
28 tnt tnt.wad
29Doom directory is now /games/doom/
30Disabled mouse calls -> speedup
31Finally have the right timer. -> run is actually usable now
32Added a timedemo option for speed testing, only runs with doom shareware,
33 Ultimate doom, or registered doom saves timedemo information in /games/doom/timedemo.txt
34Merged Paul's Ipod changes, hopefully it works now
35Added addon code so that additional wadfiles can be added to the startup.
36
37# Version 0.8
38Extended the addon code to automatically search for wads in /games/doom/addons/
39Changed the memory allocation to use doom's block allocator exclusively this can
40 be used in other plugins that need malloc, realloc, and calloc (include z_zone.c, z_zone.h)
41Included linuxstb's code for the Ipod
42Redid the sound code partially from prboom
43 -> caches all sound at startup
44 -> helped reduce the number of pauses in the game
45All new renderer from prboom -> translucent sprites, dynamic palettes FASTER
46 more wads work properly (no more graphical errors in halflife)
47
diff --git a/apps/plugins/doom/Makefile b/apps/plugins/doom/Makefile
new file mode 100644
index 0000000000..c45ffe78da
--- /dev/null
+++ b/apps/plugins/doom/Makefile
@@ -0,0 +1,145 @@
1################################################################
2#
3# $Id$
4#
5# $Log$
6# Revision 1.1 2006/03/28 15:44:01 dave
7# Patch #2969 - Doom! Currently only working on the H300.
8#
9#
10
11INCLUDES = -I$(APPSDIR) -I.. -I. -I$(FIRMDIR)/include -I$(FIRMDIR)/export \
12 -I$(FIRMDIR)/common -I$(FIRMDIR)/drivers -I$(OUTDIR) -I$(BUILDDIR)
13CFLAGS = $(GCCOPTS) $(INCLUDES) $(TARGET) $(EXTRA_DEFINES) \
14 -DTARGET_ID=$(TARGET_ID) -DMEM=${MEMORYSIZE} -DPLUGIN \
15 -Wno-strict-prototypes -O2
16
17ifdef APPEXTRA
18 INCLUDES += $(patsubst %,-I$(APPSDIR)/%,$(subst :, ,$(APPEXTRA)))
19endif
20
21ifneq (,$(strip $(foreach tgt,IPOD_NANO IPOD_COLOR IPOD_VIDEO,$(findstring $(tgt),$(TARGET)))))
22ifndef SIMVER
23 CFLAGS += -mstructure-size-boundary=8
24endif
25else
26ifndef SIMVER
27 CFLAGS += -D__BIG_ENDIAN__
28endif
29endif
30
31LINKFILE := $(OBJDIR)/link.lds
32DEPFILE = $(OBJDIR)/dep-doom
33SRC = info.c doomdef.c doomstat.c dstrings.c tables.c \
34 f_finale.c f_wipe.c d_net.c d_items.c g_game.c m_menu.c m_argv.c \
35 m_cheat.c m_random.c am_map.c p_ceilng.c p_doors.c p_genlin.c \
36 p_enemy.c p_floor.c p_inter.c p_lights.c p_map.c p_maputl.c p_plats.c \
37 p_pspr.c p_setup.c p_sight.c p_spec.c p_switch.c p_mobj.c p_telept.c \
38 p_tick.c p_saveg.c p_user.c r_bsp.c r_data.c r_draw.c r_main.c \
39 r_plane.c r_segs.c r_sky.c r_things.c wi_stuff.c v_video.c st_lib.c \
40 st_stuff.c hu_stuff.c hu_lib.c s_sound.c z_zone.c z_bmalloc.c sounds.c \
41 d_main.c m_misc.c m_bbox.c i_system.c i_sound.c i_video.c \
42 w_wad.c rockdoom.c
43# fixmath2.S
44
45SOURCES = $(SRC)
46OBJS := $(SRC:%.c=$(OBJDIR)/%.o)
47#OBJS2 := $(SRC:%.c=$(OBJDIR)/%.o)
48#OBJS = $(patsubst %.S, $(OBJDIR)/%.o, $(OBJS2))
49DIRS = .
50
51
52ifndef SIMVER
53ifneq (,$(findstring RECORDER,$(TARGET))) ## Archos recorder targets
54 LDS := archos.lds
55 OUTPUT = $(OUTDIR)/doom.ovl
56else ## iRiver target
57 LDS := ../plugin.lds
58 OUTPUT = $(OUTDIR)/doom.rock
59endif
60else ## simulators
61 OUTPUT = $(OUTDIR)/doom.rock
62endif
63
64all: $(OUTPUT)
65
66ifndef SIMVER
67$(OBJDIR)/doom.elf: $(OBJS) $(LINKFILE)
68 @echo "LD "`basename $@`
69 @$(CC) $(GCCOPTS) $(LDFLAGS) -nostdlib -o $@ $(OBJS) -L$(BUILDDIR) -lplugin -lgcc\
70 -T$(LINKFILE) -Wl,-Map,$(OBJDIR)/doom.map
71
72$(OUTPUT): $(OBJDIR)/doom.elf
73 @echo "OBJCOPY "`basename $@`
74 @$(OC) -O binary $< $@
75else
76
77ifeq ($(SIMVER), x11)
78###################################################
79# This is the X11 simulator version
80
81$(OUTPUT): $(OBJS)
82 @echo "LD $@"
83 @$(CC) $(CFLAGS) -shared $(OBJS) -L$(BUILDDIR) -lplugin -o $@
84ifeq ($(findstring CYGWIN,$(UNAME)),CYGWIN)
85# 'x' must be kept or you'll have "Win32 error 5"
86# $ fgrep 5 /usr/include/w32api/winerror.h | head -1
87# #define ERROR_ACCESS_DENIED 5L
88else
89 @chmod -x $@
90endif
91
92else # end of x11-simulator
93ifeq ($(SIMVER), sdl)
94###################################################
95# This is the sdl simulator version
96
97$(OUTPUT): $(OBJS)
98 @echo "LD $@"
99 @$(CC) $(CFLAGS) -shared $(OBJS) -L$(BUILDDIR) -lplugin -o $@
100ifeq ($(findstring CYGWIN,$(UNAME)),CYGWIN)
101# 'x' must be kept or you'll have "Win32 error 5"
102# $ fgrep 5 /usr/include/w32api/winerror.h | head -1
103# #define ERROR_ACCESS_DENIED 5L
104else
105 @chmod -x $@
106endif
107
108else # end of sdl-simulator
109###################################################
110# This is the win32 simulator version
111DLLTOOLFLAGS = --export-all
112DLLWRAPFLAGS = -s --entry _DllMain@12 --target=i386-mingw32 -mno-cygwin
113
114$(OUTPUT): $(OBJS)
115 @echo "DLL "`basename $@`
116 @$(DLLTOOL) $(DLLTOOLFLAGS) -z $(OBJDIR)/$*.def $(OBJS)
117 @$(DLLWRAP) $(DLLWRAPFLAGS) --def $(OBJDIR)/$*.def $(OBJS) \
118 $(BUILDDIR)/libplugin.a -o $@
119ifeq ($(findstring CYGWIN,$(UNAME)),CYGWIN)
120# 'x' must be kept or you'll have "Win32 error 5"
121# $ fgrep 5 /usr/include/w32api/winerror.h | head -1
122# #define ERROR_ACCESS_DENIED 5L
123else
124 @chmod -x $@
125endif
126endif # end of win32-simulator
127endif
128endif # end of simulator section
129
130
131include $(TOOLSDIR)/make.inc
132
133# MEMORYSIZE should be passed on to this makefile with the chosen memory size
134# given in number of MB
135$(LINKFILE): $(LDS)
136 @echo "build "`basename $@`
137 @cat $< | $(CC) -DMEMORYSIZE=$(MEMORYSIZE) $(INCLUDES) $(TARGET) $(DEFINES) \
138 -E -P - >$@
139
140clean:
141 @echo "cleaning doom"
142 @rm -rf $(OBJDIR)/doom
143 @rm -f $(OBJDIR)/doom.* $(DEPFILE)
144
145-include $(DEPFILE)
diff --git a/apps/plugins/doom/am_map.c b/apps/plugins/doom/am_map.c
new file mode 100644
index 0000000000..9bdd4e4e70
--- /dev/null
+++ b/apps/plugins/doom/am_map.c
@@ -0,0 +1,1702 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION:
28 * the automap code
29 *
30 *-----------------------------------------------------------------------------
31 */
32
33#include "doomstat.h"
34
35#include "st_stuff.h"
36#include "r_main.h"
37#include "p_setup.h"
38#include "p_maputl.h"
39#include "w_wad.h"
40#include "v_video.h"
41#include "p_spec.h"
42#include "am_map.h"
43#include "dstrings.h"
44//#include "d_deh.h" // Ty 03/27/98 - externalizations
45#include "g_game.h"
46#include "rockmacros.h"
47
48
49//jff 1/7/98 default automap colors added
50int mapcolor_back; // map background
51int mapcolor_grid; // grid lines color
52int mapcolor_wall; // normal 1s wall color
53int mapcolor_fchg; // line at floor height change color
54int mapcolor_cchg; // line at ceiling height change color
55int mapcolor_clsd; // line at sector with floor=ceiling color
56int mapcolor_rkey; // red key color
57int mapcolor_bkey; // blue key color
58int mapcolor_ykey; // yellow key color
59int mapcolor_rdor; // red door color (diff from keys to allow option)
60int mapcolor_bdor; // blue door color (of enabling one but not other )
61int mapcolor_ydor; // yellow door color
62int mapcolor_tele; // teleporter line color
63int mapcolor_secr; // secret sector boundary color
64int mapcolor_exit; // jff 4/23/98 add exit line color
65int mapcolor_unsn; // computer map unseen line color
66int mapcolor_flat; // line with no floor/ceiling changes
67int mapcolor_sprt; // general sprite color
68int mapcolor_item; // item sprite color
69int mapcolor_frnd; // friendly sprite color
70int mapcolor_hair; // crosshair color
71int mapcolor_sngl; // single player arrow color
72int mapcolor_plyr[4] = { 112, 88, 64, 176 }; // colors for player arrows in multiplayer
73
74//jff 3/9/98 add option to not show secret sectors until entered
75int map_secret_after=0;
76//jff 4/3/98 add symbols for "no-color" for disable and "black color" for black
77#define NC 0
78#define BC 247
79
80// drawing stuff
81#define FB 0
82
83// scale on entry
84#define INITSCALEMTOF (.2*FRACUNIT)
85// how much the automap moves window per tic in frame-buffer coordinates
86// moves 140 pixels in 1 second
87#define F_PANINC 4
88// how much zoom-in per tic
89// goes to 2x in 1 second
90#define M_ZOOMIN ((int) (1.02*FRACUNIT))
91// how much zoom-out per tic
92// pulls out to 0.5x in 1 second
93#define M_ZOOMOUT ((int) (FRACUNIT/1.02))
94
95// translates between frame-buffer and map distances
96#define FTOM(x) FixedMul(((x)<<16),scale_ftom)
97#define MTOF(x) (FixedMul((x),scale_mtof)>>16)
98// translates between frame-buffer and map coordinates
99#define CXMTOF(x) (f_x + MTOF((x)-m_x))
100#define CYMTOF(y) (f_y + (f_h - MTOF((y)-m_y)))
101
102typedef struct
103{
104 int x, y;
105} fpoint_t;
106
107typedef struct
108{
109 fpoint_t a, b;
110} fline_t;
111
112typedef struct
113{
114 mpoint_t a, b;
115} mline_t;
116
117typedef struct
118{
119 fixed_t slp, islp;
120} islope_t;
121
122//
123// The vector graphics for the automap.
124// A line drawing of the player pointing right,
125// starting from the middle.
126//
127#define R ((8*PLAYERRADIUS)/7)
128mline_t player_arrow[] =
129 {
130 { { -R+R/8, 0 }, { R, 0 } }, // -----
131 { { R, 0 }, { R-R/2, R/4 } }, // ----->
132 { { R, 0 }, { R-R/2, -R/4 } },
133 { { -R+R/8, 0 }, { -R-R/8, R/4 } }, // >---->
134 { { -R+R/8, 0 }, { -R-R/8, -R/4 } },
135 { { -R+3*R/8, 0 }, { -R+R/8, R/4 } }, // >>--->
136 { { -R+3*R/8, 0 }, { -R+R/8, -R/4 } }
137 };
138#undef R
139#define NUMPLYRLINES (sizeof(player_arrow)/sizeof(mline_t))
140
141#define R ((8*PLAYERRADIUS)/7)
142mline_t cheat_player_arrow[] =
143 { // killough 3/22/98: He's alive, Jim :)
144 { { -R+R/8, 0 }, { R, 0 } }, // -----
145 { { R, 0 }, { R-R/2, R/4 } }, // ----->
146 { { R, 0 }, { R-R/2, -R/4 } },
147 { { -R+R/8, 0 }, { -R-R/8, R/4 } }, // >---->
148 { { -R+R/8, 0 }, { -R-R/8, -R/4 } },
149 { { -R+3*R/8, 0 }, { -R+R/8, R/4 } }, // >>--->
150 { { -R+3*R/8, 0 }, { -R+R/8, -R/4 } },
151 { { -R/10-R/6, R/4}, {-R/10-R/6, -R/4} }, // J
152 { { -R/10-R/6, -R/4}, {-R/10-R/6-R/8, -R/4} },
153 { { -R/10-R/6-R/8, -R/4}, {-R/10-R/6-R/8, -R/8} },
154 { { -R/10, R/4}, {-R/10, -R/4}}, // F
155 { { -R/10, R/4}, {-R/10+R/8, R/4}},
156 { { -R/10+R/4, R/4}, {-R/10+R/4, -R/4}}, // F
157 { { -R/10+R/4, R/4}, {-R/10+R/4+R/8, R/4}},
158 };
159#undef R
160#define NUMCHEATPLYRLINES (sizeof(cheat_player_arrow)/sizeof(mline_t))
161
162#define R (FRACUNIT)
163mline_t triangle_guy[] =
164 {
165 { { (fixed_t)(-.867*R), (fixed_t)(-.5*R) }, { (fixed_t)( .867*R), (fixed_t)(-.5*R) } },
166 { { (fixed_t)( .867*R), (fixed_t)(-.5*R) }, { (fixed_t)(0 ), (fixed_t)( R) } },
167 { { (fixed_t)(0 ), (fixed_t)( R) }, { (fixed_t)(-.867*R), (fixed_t)(-.5*R) } }
168 };
169#undef R
170#define NUMTRIANGLEGUYLINES (sizeof(triangle_guy)/sizeof(mline_t))
171
172//jff 1/5/98 new symbol for keys on automap
173#define R (FRACUNIT)
174mline_t cross_mark[] =
175 {
176 { { -R, 0 }, { R, 0} },
177 { { 0, -R }, { 0, R } },
178 };
179#undef R
180#define NUMCROSSMARKLINES (sizeof(cross_mark)/sizeof(mline_t))
181//jff 1/5/98 end of new symbol
182
183#define R (FRACUNIT)
184mline_t thintriangle_guy[] =
185 {
186 { { (fixed_t)(-.5*R), (fixed_t)(-.7*R) }, { (fixed_t)( R), (fixed_t)( 0) } },
187 { { (fixed_t)( R), (fixed_t)( 0) }, { (fixed_t)(-.5*R), (fixed_t)( .7*R) } },
188 { { (fixed_t)(-.5*R), (fixed_t)( .7*R) }, { (fixed_t)(-.5*R), (fixed_t)(-.7*R) } }
189 };
190#undef R
191#define NUMTHINTRIANGLEGUYLINES (sizeof(thintriangle_guy)/sizeof(mline_t))
192
193int ddt_cheating = 0; // killough 2/7/98: make global, rename to ddt_*
194
195static int leveljuststarted = 1; // kluge until AM_LevelInit() is called
196
197enum automapmode_e automapmode; // Mode that the automap is in
198
199// location of window on screen
200static int f_x;
201static int f_y;
202
203// size of window on screen
204static int f_w;
205static int f_h;
206
207static mpoint_t m_paninc; // how far the window pans each tic (map coords)
208static fixed_t mtof_zoommul; // how far the window zooms each tic (map coords)
209static fixed_t ftom_zoommul; // how far the window zooms each tic (fb coords)
210
211static fixed_t m_x, m_y; // LL x,y window location on the map (map coords)
212static fixed_t m_x2, m_y2; // UR x,y window location on the map (map coords)
213
214//
215// width/height of window on map (map coords)
216//
217static fixed_t m_w;
218static fixed_t m_h;
219
220// based on level size
221static fixed_t min_x;
222static fixed_t min_y;
223static fixed_t max_x;
224static fixed_t max_y;
225
226static fixed_t max_w; // max_x-min_x,
227static fixed_t max_h; // max_y-min_y
228
229// based on player size
230static fixed_t min_w;
231static fixed_t min_h;
232
233
234static fixed_t min_scale_mtof; // used to tell when to stop zooming out
235static fixed_t max_scale_mtof; // used to tell when to stop zooming in
236
237// old stuff for recovery later
238static fixed_t old_m_w, old_m_h;
239static fixed_t old_m_x, old_m_y;
240
241// old location used by the Follower routine
242static mpoint_t f_oldloc;
243
244// used by MTOF to scale from map-to-frame-buffer coords
245static fixed_t scale_mtof = (fixed_t)INITSCALEMTOF;
246// used by FTOM to scale from frame-buffer-to-map coords (=1/scale_mtof)
247static fixed_t scale_ftom;
248
249static player_t *plr; // the player represented by an arrow
250
251// killough 2/22/98: Remove limit on automap marks,
252// and make variables external for use in savegames.
253
254mpoint_t *markpoints = NULL; // where the points are
255int markpointnum = 0; // next point to be assigned (also number of points now)
256int markpointnum_max = 0; // killough 2/22/98
257
258static boolean stopped = true;
259
260//
261// AM_getIslope()
262//
263// Calculates the slope and slope according to the x-axis of a line
264// segment in map coordinates (with the upright y-axis n' all) so
265// that it can be used with the brain-dead drawing stuff.
266//
267// Passed the line slope is desired for and an islope_t structure for return
268// Returns nothing
269//
270void AM_getIslope
271( mline_t* ml,
272 islope_t* is )
273{
274 int dx, dy;
275
276 dy = ml->a.y - ml->b.y;
277 dx = ml->b.x - ml->a.x;
278 if (!dy)
279 is->islp = (dx<0?-INT_MAX:INT_MAX);
280 else
281 is->islp = FixedDiv(dx, dy);
282 if (!dx)
283 is->slp = (dy<0?-INT_MAX:INT_MAX);
284 else
285 is->slp = FixedDiv(dy, dx);
286}
287
288//
289// AM_activateNewScale()
290//
291// Changes the map scale after zooming or translating
292//
293// Passed nothing, returns nothing
294//
295void AM_activateNewScale(void)
296{
297 m_x += m_w/2;
298 m_y += m_h/2;
299 m_w = FTOM(f_w);
300 m_h = FTOM(f_h);
301 m_x -= m_w/2;
302 m_y -= m_h/2;
303 m_x2 = m_x + m_w;
304 m_y2 = m_y + m_h;
305}
306
307//
308// AM_saveScaleAndLoc()
309//
310// Saves the current center and zoom
311// Affects the variables that remember old scale and loc
312//
313// Passed nothing, returns nothing
314//
315void AM_saveScaleAndLoc(void)
316{
317 old_m_x = m_x;
318 old_m_y = m_y;
319 old_m_w = m_w;
320 old_m_h = m_h;
321}
322
323//
324// AM_restoreScaleAndLoc()
325//
326// restores the center and zoom from locally saved values
327// Affects global variables for location and scale
328//
329// Passed nothing, returns nothing
330//
331void AM_restoreScaleAndLoc(void)
332{
333 m_w = old_m_w;
334 m_h = old_m_h;
335 if (!(automapmode & am_follow))
336 {
337 m_x = old_m_x;
338 m_y = old_m_y;
339 }
340 else
341 {
342 m_x = plr->mo->x - m_w/2;
343 m_y = plr->mo->y - m_h/2;
344 }
345 m_x2 = m_x + m_w;
346 m_y2 = m_y + m_h;
347
348 // Change the scaling multipliers
349 scale_mtof = FixedDiv(f_w<<FRACBITS, m_w);
350 scale_ftom = FixedDiv(FRACUNIT, scale_mtof);
351}
352
353//
354// AM_addMark()
355//
356// Adds a marker at the current location
357// Affects global variables for marked points
358//
359// Passed nothing, returns nothing
360//
361void AM_addMark(void)
362{
363 // killough 2/22/98:
364 // remove limit on automap marks
365
366 if (markpointnum >= markpointnum_max)
367 markpoints = realloc(markpoints,
368 (markpointnum_max = markpointnum_max ?
369 markpointnum_max*2 : 16) * sizeof(*markpoints));
370
371 markpoints[markpointnum].x = m_x + m_w/2;
372 markpoints[markpointnum].y = m_y + m_h/2;
373 markpointnum++;
374}
375
376//
377// AM_findMinMaxBoundaries()
378//
379// Determines bounding box of all vertices,
380// sets global variables controlling zoom range.
381//
382// Passed nothing, returns nothing
383//
384void AM_findMinMaxBoundaries(void)
385{
386 int i;
387 fixed_t a;
388 fixed_t b;
389
390 min_x = min_y = INT_MAX;
391 max_x = max_y = -INT_MAX;
392
393 for (i=0;i<numvertexes;i++)
394 {
395 if (vertexes[i].x < min_x)
396 min_x = vertexes[i].x;
397 else if (vertexes[i].x > max_x)
398 max_x = vertexes[i].x;
399
400 if (vertexes[i].y < min_y)
401 min_y = vertexes[i].y;
402 else if (vertexes[i].y > max_y)
403 max_y = vertexes[i].y;
404 }
405
406 max_w = max_x - min_x;
407 max_h = max_y - min_y;
408
409 min_w = 2*PLAYERRADIUS; // const? never changed?
410 min_h = 2*PLAYERRADIUS;
411
412 a = FixedDiv(f_w<<FRACBITS, max_w);
413 b = FixedDiv(f_h<<FRACBITS, max_h);
414
415 min_scale_mtof = a < b ? a : b;
416 max_scale_mtof = FixedDiv(f_h<<FRACBITS, 2*PLAYERRADIUS);
417}
418
419//
420// AM_changeWindowLoc()
421//
422// Moves the map window by the global variables m_paninc.x, m_paninc.y
423//
424// Passed nothing, returns nothing
425//
426void AM_changeWindowLoc(void)
427{
428 if (m_paninc.x || m_paninc.y)
429 {
430 automapmode &= ~am_follow;
431 f_oldloc.x = INT_MAX;
432 }
433
434 m_x += m_paninc.x;
435 m_y += m_paninc.y;
436
437 if (m_x + m_w/2 > max_x)
438 m_x = max_x - m_w/2;
439 else if (m_x + m_w/2 < min_x)
440 m_x = min_x - m_w/2;
441
442 if (m_y + m_h/2 > max_y)
443 m_y = max_y - m_h/2;
444 else if (m_y + m_h/2 < min_y)
445 m_y = min_y - m_h/2;
446
447 m_x2 = m_x + m_w;
448 m_y2 = m_y + m_h;
449}
450
451
452//
453// AM_initVariables()
454//
455// Initialize the variables for the automap
456//
457// Affects the automap global variables
458// Status bar is notified that the automap has been entered
459// Passed nothing, returns nothing
460//
461void AM_initVariables(void)
462{
463 int pnum;
464 static event_t st_notify = { ev_keyup, AM_MSGENTERED, 0 , 0 };
465
466 automapmode |= am_active;
467
468 f_oldloc.x = INT_MAX;
469
470 m_paninc.x = m_paninc.y = 0;
471 ftom_zoommul = FRACUNIT;
472 mtof_zoommul = FRACUNIT;
473
474 m_w = FTOM(f_w);
475 m_h = FTOM(f_h);
476
477 // find player to center on initially
478 if (!playeringame[pnum = consoleplayer])
479 for (pnum=0;pnum<MAXPLAYERS;pnum++)
480 if (playeringame[pnum])
481 break;
482
483 plr = &players[pnum];
484 m_x = plr->mo->x - m_w/2;
485 m_y = plr->mo->y - m_h/2;
486 AM_changeWindowLoc();
487
488 // for saving & restoring
489 old_m_x = m_x;
490 old_m_y = m_y;
491 old_m_w = m_w;
492 old_m_h = m_h;
493
494 // inform the status bar of the change
495 ST_Responder(&st_notify);
496}
497
498//
499// AM_loadPics()
500//
501void AM_loadPics(void)
502{
503 // cph - mark numbers no longer needed cached
504}
505
506//
507// AM_unloadPics()
508//
509void AM_unloadPics(void)
510{
511 // cph - mark numbers no longer needed cached
512}
513
514//
515// AM_clearMarks()
516//
517// Sets the number of marks to 0, thereby clearing them from the display
518//
519// Affects the global variable markpointnum
520// Passed nothing, returns nothing
521//
522void AM_clearMarks(void)
523{
524 markpointnum = 0;
525}
526
527//
528// AM_LevelInit()
529//
530// Initialize the automap at the start of a new level
531// should be called at the start of every level
532//
533// Passed nothing, returns nothing
534// Affects automap's global variables
535//
536// CPhipps - get status bar height from status bar code
537void AM_LevelInit(void)
538{
539 leveljuststarted = 0;
540
541 f_x = f_y = 0;
542 f_w = SCREENWIDTH; // killough 2/7/98: get rid of finit_ vars
543 f_h = SCREENHEIGHT-ST_SCALED_HEIGHT;// to allow runtime setting of width/height
544
545 AM_findMinMaxBoundaries();
546 scale_mtof = FixedDiv(min_scale_mtof, (int) (0.7*FRACUNIT));
547 if (scale_mtof > max_scale_mtof)
548 scale_mtof = min_scale_mtof;
549 scale_ftom = FixedDiv(FRACUNIT, scale_mtof);
550}
551
552//
553// AM_Stop()
554//
555// Cease automap operations, unload patches, notify status bar
556//
557// Passed nothing, returns nothing
558//
559void AM_Stop (void)
560{
561 static event_t st_notify = { 0, ev_keyup, AM_MSGEXITED, 0 };
562
563 AM_unloadPics();
564 automapmode &= ~am_active;
565 ST_Responder(&st_notify);
566 stopped = true;
567}
568
569//
570// AM_Start()
571//
572// Start up automap operations,
573// if a new level, or game start, (re)initialize level variables
574// init map variables
575// load mark patches
576//
577// Passed nothing, returns nothing
578//
579void AM_Start()
580{
581 static int lastlevel = -1, lastepisode = -1;
582
583 if (!stopped)
584 AM_Stop();
585 stopped = false;
586 if (lastlevel != gamemap || lastepisode != gameepisode)
587 {
588 AM_LevelInit();
589 lastlevel = gamemap;
590 lastepisode = gameepisode;
591 }
592 AM_initVariables();
593 AM_loadPics();
594}
595
596//
597// AM_minOutWindowScale()
598//
599// Set the window scale to the maximum size
600//
601// Passed nothing, returns nothing
602//
603void AM_minOutWindowScale()
604{
605 scale_mtof = min_scale_mtof;
606 scale_ftom = FixedDiv(FRACUNIT, scale_mtof);
607 AM_activateNewScale();
608}
609
610//
611// AM_maxOutWindowScale(void)
612//
613// Set the window scale to the minimum size
614//
615// Passed nothing, returns nothing
616//
617void AM_maxOutWindowScale(void)
618{
619 scale_mtof = max_scale_mtof;
620 scale_ftom = FixedDiv(FRACUNIT, scale_mtof);
621 AM_activateNewScale();
622}
623
624//
625// AM_Responder()
626//
627// Handle events (user inputs) in automap mode
628//
629// Passed an input event, returns true if its handled
630//
631boolean AM_Responder
632( event_t* ev )
633{
634 int rc;
635 static int cheatstate=0;
636 static int bigstate=0;
637 static char buffer[20];
638 int ch; // phares
639
640 rc = false;
641
642 if (!(automapmode & am_active))
643 {
644 if (ev->type == ev_keydown && ev->data1 == key_map) // phares
645 {
646 AM_Start ();
647 rc = true;
648 }
649 }
650 else if (ev->type == ev_keydown)
651 {
652 rc = true;
653 ch = ev->data1; // phares
654 if (ch == key_map_right) // |
655 if (!(automapmode & am_follow)) // V
656 m_paninc.x = FTOM(F_PANINC);
657 else
658 rc = false;
659 else if (ch == key_map_left)
660 if (!(automapmode & am_follow))
661 m_paninc.x = -FTOM(F_PANINC);
662 else
663 rc = false;
664 else if (ch == key_map_up)
665 if (!(automapmode & am_follow))
666 m_paninc.y = FTOM(F_PANINC);
667 else
668 rc = false;
669 else if (ch == key_map_down)
670 if (!(automapmode & am_follow))
671 m_paninc.y = -FTOM(F_PANINC);
672 else
673 rc = false;
674 else if (ch == key_map_zoomout)
675 {
676 mtof_zoommul = M_ZOOMOUT;
677 ftom_zoommul = M_ZOOMIN;
678 }
679 else if (ch == key_map_zoomin)
680 {
681 mtof_zoommul = M_ZOOMIN;
682 ftom_zoommul = M_ZOOMOUT;
683 }
684 else if (ch == key_map)
685 {
686 bigstate = 0;
687 AM_Stop ();
688 }
689 else if (ch == key_map_gobig)
690 {
691 bigstate = !bigstate;
692 if (bigstate)
693 {
694 AM_saveScaleAndLoc();
695 AM_minOutWindowScale();
696 }
697 else
698 AM_restoreScaleAndLoc();
699 }
700 else if (ch == key_map_follow)
701 {
702 automapmode ^= am_follow; // CPhipps - put all automap mode stuff into one enum
703 f_oldloc.x = INT_MAX;
704 // Ty 03/27/98 - externalized
705 plr->message = (automapmode & am_follow) ? AMSTR_FOLLOWON : AMSTR_FOLLOWOFF;
706 }
707 else if (ch == key_map_grid)
708 {
709 automapmode ^= am_grid; // CPhipps
710 // Ty 03/27/98 - *not* externalized
711 plr->message = (automapmode & am_grid) ? AMSTR_GRIDON : AMSTR_GRIDOFF;
712 }
713 else if (ch == key_map_mark)
714 {
715 // Ty 03/27/98 - *not* externalized
716 snprintf(buffer, sizeof(buffer), "%s %d", AMSTR_MARKEDSPOT, markpointnum);
717 plr->message = buffer;
718 AM_addMark();
719 }
720 else if (ch == key_map_clear)
721 {
722 AM_clearMarks(); // Ty 03/27/98 - *not* externalized
723 plr->message = AMSTR_MARKSCLEARED; // ^
724 } // |
725 else if (ch == key_map_rotate) {
726 automapmode ^= am_rotate;
727 plr->message = (automapmode & am_rotate) ? AMSTR_ROTATEON : AMSTR_ROTATEOFF;
728 }
729 else if (ch == key_map_overlay) {
730 automapmode ^= am_overlay;
731 plr->message = (automapmode & am_overlay) ? AMSTR_OVERLAYON : AMSTR_OVERLAYOFF;
732 }
733 else // phares
734 {
735 cheatstate=0;
736 rc = false;
737 }
738 }
739 else if (ev->type == ev_keyup)
740 {
741 rc = false;
742 ch = ev->data1;
743 if (ch == key_map_right)
744 {
745 if (!(automapmode & am_follow))
746 m_paninc.x = 0;
747 }
748 else if (ch == key_map_left)
749 {
750 if (!(automapmode & am_follow))
751 m_paninc.x = 0;
752 }
753 else if (ch == key_map_up)
754 {
755 if (!(automapmode & am_follow))
756 m_paninc.y = 0;
757 }
758 else if (ch == key_map_down)
759 {
760 if (!(automapmode & am_follow))
761 m_paninc.y = 0;
762 }
763 else if ((ch == key_map_zoomout) || (ch == key_map_zoomin))
764 {
765 mtof_zoommul = FRACUNIT;
766 ftom_zoommul = FRACUNIT;
767 }
768 }
769 return rc;
770}
771
772//
773// AM_rotate()
774//
775// Rotation in 2D.
776// Used to rotate player arrow line character.
777//
778// Passed the coordinates of a point, and an angle
779// Returns the coordinates rotated by the angle
780//
781// CPhipps - made static & enhanced for automap rotation
782
783static void AM_rotate(fixed_t* x, fixed_t* y, angle_t a, fixed_t xorig, fixed_t yorig)
784{
785 fixed_t tmpx;
786
787 tmpx =
788 FixedMul(*x - xorig,finecosine[a>>ANGLETOFINESHIFT])
789 - FixedMul(*y - yorig,finesine[a>>ANGLETOFINESHIFT]);
790
791 *y = yorig +
792 FixedMul(*x - xorig,finesine[a>>ANGLETOFINESHIFT])
793 + FixedMul(*y - yorig,finecosine[a>>ANGLETOFINESHIFT]);
794
795 *x = tmpx + xorig;
796}
797
798//
799// AM_changeWindowScale()
800//
801// Automap zooming
802//
803// Passed nothing, returns nothing
804//
805void AM_changeWindowScale(void)
806{
807 // Change the scaling multipliers
808 scale_mtof = FixedMul(scale_mtof, mtof_zoommul);
809 scale_ftom = FixedDiv(FRACUNIT, scale_mtof);
810
811 if (scale_mtof < min_scale_mtof)
812 AM_minOutWindowScale();
813 else if (scale_mtof > max_scale_mtof)
814 AM_maxOutWindowScale();
815 else
816 AM_activateNewScale();
817}
818
819//
820// AM_doFollowPlayer()
821//
822// Turn on follow mode - the map scrolls opposite to player motion
823//
824// Passed nothing, returns nothing
825//
826void AM_doFollowPlayer(void)
827{
828 if (f_oldloc.x != plr->mo->x || f_oldloc.y != plr->mo->y)
829 {
830 m_x = FTOM(MTOF(plr->mo->x)) - m_w/2;
831 m_y = FTOM(MTOF(plr->mo->y)) - m_h/2;
832 m_x2 = m_x + m_w;
833 m_y2 = m_y + m_h;
834 f_oldloc.x = plr->mo->x;
835 f_oldloc.y = plr->mo->y;
836 }
837}
838
839//
840// AM_Ticker()
841//
842// Updates on gametic - enter follow mode, zoom, or change map location
843//
844// Passed nothing, returns nothing
845//
846void AM_Ticker (void)
847{
848 if (!(automapmode & am_active))
849 return;
850
851 if (automapmode & am_follow)
852 AM_doFollowPlayer();
853
854 // Change the zoom if necessary
855 if (ftom_zoommul != FRACUNIT)
856 AM_changeWindowScale();
857
858 // Change x,y location
859 if (m_paninc.x || m_paninc.y)
860 AM_changeWindowLoc();
861}
862
863//
864// AM_clipMline()
865//
866// Automap clipping of lines.
867//
868// Based on Cohen-Sutherland clipping algorithm but with a slightly
869// faster reject and precalculated slopes. If the speed is needed,
870// use a hash algorithm to handle the common cases.
871//
872// Passed the line's coordinates on map and in the frame buffer performs
873// clipping on them in the lines frame coordinates.
874// Returns true if any part of line was not clipped
875//
876boolean AM_clipMline
877( mline_t* ml,
878 fline_t* fl )
879{
880 enum
881 {
882 LEFT =1,
883 RIGHT =2,
884 BOTTOM =4,
885 TOP =8
886 };
887
888 register int outcode1 = 0;
889 register int outcode2 = 0;
890 register int outside;
891
892 fpoint_t tmp;
893 int dx;
894 int dy;
895
896
897#define DOOUTCODE(oc, mx, my) \
898 (oc) = 0; \
899 if ((my) < 0) (oc) |= TOP; \
900 else if ((my) >= f_h) (oc) |= BOTTOM; \
901 if ((mx) < 0) (oc) |= LEFT; \
902 else if ((mx) >= f_w) (oc) |= RIGHT;
903
904
905 // do trivial rejects and outcodes
906 if (ml->a.y > m_y2)
907 outcode1 = TOP;
908 else if (ml->a.y < m_y)
909 outcode1 = BOTTOM;
910
911 if (ml->b.y > m_y2)
912 outcode2 = TOP;
913 else if (ml->b.y < m_y)
914 outcode2 = BOTTOM;
915
916 if (outcode1 & outcode2)
917 return false; // trivially outside
918
919 if (ml->a.x < m_x)
920 outcode1 |= LEFT;
921 else if (ml->a.x > m_x2)
922 outcode1 |= RIGHT;
923
924 if (ml->b.x < m_x)
925 outcode2 |= LEFT;
926 else if (ml->b.x > m_x2)
927 outcode2 |= RIGHT;
928
929 if (outcode1 & outcode2)
930 return false; // trivially outside
931
932 // transform to frame-buffer coordinates.
933 fl->a.x = CXMTOF(ml->a.x);
934 fl->a.y = CYMTOF(ml->a.y);
935 fl->b.x = CXMTOF(ml->b.x);
936 fl->b.y = CYMTOF(ml->b.y);
937
938 DOOUTCODE(outcode1, fl->a.x, fl->a.y);
939 DOOUTCODE(outcode2, fl->b.x, fl->b.y);
940
941 if (outcode1 & outcode2)
942 return false;
943
944 while (outcode1 | outcode2)
945 {
946 // may be partially inside box
947 // find an outside point
948 if (outcode1)
949 outside = outcode1;
950 else
951 outside = outcode2;
952
953 // clip to each side
954 if (outside & TOP)
955 {
956 dy = fl->a.y - fl->b.y;
957 dx = fl->b.x - fl->a.x;
958 tmp.x = fl->a.x + (dx*(fl->a.y))/dy;
959 tmp.y = 0;
960 }
961 else if (outside & BOTTOM)
962 {
963 dy = fl->a.y - fl->b.y;
964 dx = fl->b.x - fl->a.x;
965 tmp.x = fl->a.x + (dx*(fl->a.y-f_h))/dy;
966 tmp.y = f_h-1;
967 }
968 else if (outside & RIGHT)
969 {
970 dy = fl->b.y - fl->a.y;
971 dx = fl->b.x - fl->a.x;
972 tmp.y = fl->a.y + (dy*(f_w-1 - fl->a.x))/dx;
973 tmp.x = f_w-1;
974 }
975 else if (outside & LEFT)
976 {
977 dy = fl->b.y - fl->a.y;
978 dx = fl->b.x - fl->a.x;
979 tmp.y = fl->a.y + (dy*(-fl->a.x))/dx;
980 tmp.x = 0;
981 }
982
983 if (outside == outcode1)
984 {
985 fl->a = tmp;
986 DOOUTCODE(outcode1, fl->a.x, fl->a.y);
987 }
988 else
989 {
990 fl->b = tmp;
991 DOOUTCODE(outcode2, fl->b.x, fl->b.y);
992 }
993
994 if (outcode1 & outcode2)
995 return false; // trivially outside
996 }
997
998 return true;
999}
1000#undef DOOUTCODE
1001
1002//
1003// AM_drawFline()
1004//
1005// Draw a line in the frame buffer.
1006// Classic Bresenham w/ whatever optimizations needed for speed
1007//
1008// Passed the frame coordinates of line, and the color to be drawn
1009// Returns nothing
1010//
1011
1012void AM_drawFline
1013( fline_t* fl,
1014 int color )
1015{
1016 register int x;
1017 register int y;
1018 register int dx;
1019 register int dy;
1020 register int sx;
1021 register int sy;
1022 register int ax;
1023 register int ay;
1024 register int d;
1025
1026#ifdef RANGECHECK // killough 2/22/98
1027 static int fuck = 0;
1028
1029 // For debugging only
1030 if
1031 (
1032 fl->a.x < 0 || fl->a.x >= f_w
1033 || fl->a.y < 0 || fl->a.y >= f_h
1034 || fl->b.x < 0 || fl->b.x >= f_w
1035 || fl->b.y < 0 || fl->b.y >= f_h
1036 )
1037 {
1038 //jff 8/3/98 use logical output routine
1039 printf("fuck %d \r", fuck++);
1040 return;
1041 }
1042#endif
1043
1044#define PUTDOT(xx,yy,cc) V_PlotPixel(FB,xx,yy,(byte)cc)
1045
1046 dx = fl->b.x - fl->a.x;
1047 ax = 2 * (dx<0 ? -dx : dx);
1048 sx = dx<0 ? -1 : 1;
1049
1050 dy = fl->b.y - fl->a.y;
1051 ay = 2 * (dy<0 ? -dy : dy);
1052 sy = dy<0 ? -1 : 1;
1053
1054 x = fl->a.x;
1055 y = fl->a.y;
1056
1057 if (ax > ay)
1058 {
1059 d = ay - ax/2;
1060 while (1)
1061 {
1062 PUTDOT(x,y,color);
1063 if (x == fl->b.x) return;
1064 if (d>=0)
1065 {
1066 y += sy;
1067 d -= ax;
1068 }
1069 x += sx;
1070 d += ay;
1071 }
1072 }
1073 else
1074 {
1075 d = ax - ay/2;
1076 while (1)
1077 {
1078 PUTDOT(x, y, color);
1079 if (y == fl->b.y) return;
1080 if (d >= 0)
1081 {
1082 x += sx;
1083 d -= ay;
1084 }
1085 y += sy;
1086 d += ax;
1087 }
1088 }
1089}
1090
1091
1092//
1093// AM_drawMline()
1094//
1095// Clip lines, draw visible parts of lines.
1096//
1097// Passed the map coordinates of the line, and the color to draw it
1098// Color -1 is special and prevents drawing. Color 247 is special and
1099// is translated to black, allowing Color 0 to represent feature disable
1100// in the defaults file.
1101// Returns nothing.
1102//
1103void AM_drawMline
1104( mline_t* ml,
1105 int color )
1106{
1107 static fline_t fl;
1108
1109 if (color==-1) // jff 4/3/98 allow not drawing any sort of line
1110 return; // by setting its color to -1
1111 if (color==247) // jff 4/3/98 if color is 247 (xparent), use black
1112 color=0;
1113
1114 if (AM_clipMline(ml, &fl))
1115 AM_drawFline(&fl, color); // draws it on frame buffer using fb coords
1116}
1117
1118//
1119// AM_drawGrid()
1120//
1121// Draws blockmap aligned grid lines.
1122//
1123// Passed the color to draw the grid lines
1124// Returns nothing
1125//
1126void AM_drawGrid(int color)
1127{
1128 fixed_t x, y;
1129 fixed_t start, end;
1130 mline_t ml;
1131
1132 // Figure out start of vertical gridlines
1133 start = m_x;
1134 if ((start-bmaporgx)%(MAPBLOCKUNITS<<FRACBITS))
1135 start += (MAPBLOCKUNITS<<FRACBITS)
1136 - ((start-bmaporgx)%(MAPBLOCKUNITS<<FRACBITS));
1137 end = m_x + m_w;
1138
1139 // draw vertical gridlines
1140 ml.a.y = m_y;
1141 ml.b.y = m_y+m_h;
1142 for (x=start; x<end; x+=(MAPBLOCKUNITS<<FRACBITS))
1143 {
1144 ml.a.x = x;
1145 ml.b.x = x;
1146 AM_drawMline(&ml, color);
1147 }
1148
1149 // Figure out start of horizontal gridlines
1150 start = m_y;
1151 if ((start-bmaporgy)%(MAPBLOCKUNITS<<FRACBITS))
1152 start += (MAPBLOCKUNITS<<FRACBITS)
1153 - ((start-bmaporgy)%(MAPBLOCKUNITS<<FRACBITS));
1154 end = m_y + m_h;
1155
1156 // draw horizontal gridlines
1157 ml.a.x = m_x;
1158 ml.b.x = m_x + m_w;
1159 for (y=start; y<end; y+=(MAPBLOCKUNITS<<FRACBITS))
1160 {
1161 ml.a.y = y;
1162 ml.b.y = y;
1163 AM_drawMline(&ml, color);
1164 }
1165}
1166
1167//
1168// AM_DoorColor()
1169//
1170// Returns the 'color' or key needed for a door linedef type
1171//
1172// Passed the type of linedef, returns:
1173// -1 if not a keyed door
1174// 0 if a red key required
1175// 1 if a blue key required
1176// 2 if a yellow key required
1177// 3 if a multiple keys required
1178//
1179// jff 4/3/98 add routine to get color of generalized keyed door
1180//
1181int AM_DoorColor(int type)
1182{
1183 if (GenLockedBase <= type && type< GenDoorBase)
1184 {
1185 type -= GenLockedBase;
1186 type = (type & LockedKey) >> LockedKeyShift;
1187 if (!type || type==7)
1188 return 3; //any or all keys
1189 else return (type-1)%3;
1190 }
1191 switch (type) // closed keyed door
1192 {
1193case 26: case 32: case 99: case 133:
1194 /*bluekey*/
1195 return 1;
1196case 27: case 34: case 136: case 137:
1197 /*yellowkey*/
1198 return 2;
1199case 28: case 33: case 134: case 135:
1200 /*redkey*/
1201 return 0;
1202 default:
1203 return -1; //not a keyed door
1204 }
1205 return -1; //not a keyed door
1206}
1207
1208//
1209// Determines visible lines, draws them.
1210// This is LineDef based, not LineSeg based.
1211//
1212// jff 1/5/98 many changes in this routine
1213// backward compatibility not needed, so just changes, no ifs
1214// addition of clauses for:
1215// doors opening, keyed door id, secret sectors,
1216// teleports, exit lines, key things
1217// ability to suppress any of added features or lines with no height changes
1218//
1219// support for gamma correction in automap abandoned
1220//
1221// jff 4/3/98 changed mapcolor_xxxx=0 as control to disable feature
1222// jff 4/3/98 changed mapcolor_xxxx=-1 to disable drawing line completely
1223//
1224void AM_drawWalls(void)
1225{
1226 int i;
1227 static mline_t l;
1228
1229 // draw the unclipped visible portions of all lines
1230 for (i=0;i<numlines;i++)
1231 {
1232 l.a.x = lines[i].v1->x;
1233 l.a.y = lines[i].v1->y;
1234 l.b.x = lines[i].v2->x;
1235 l.b.y = lines[i].v2->y;
1236
1237 if (automapmode & am_rotate) {
1238 AM_rotate(&l.a.x, &l.a.y, ANG90-plr->mo->angle, plr->mo->x, plr->mo->y);
1239 AM_rotate(&l.b.x, &l.b.y, ANG90-plr->mo->angle, plr->mo->x, plr->mo->y);
1240 }
1241
1242 // if line has been seen or IDDT has been used
1243 if (ddt_cheating || (lines[i].flags & ML_MAPPED))
1244 {
1245 if ((lines[i].flags & ML_DONTDRAW) && !ddt_cheating)
1246 continue;
1247 {
1248 /* cph - show keyed doors and lines */
1249 int amd;
1250 if ((mapcolor_bdor || mapcolor_ydor || mapcolor_rdor) &&
1251 !(lines[i].flags & ML_SECRET) && /* non-secret */
1252 (amd = AM_DoorColor(lines[i].special)) != -1
1253 )
1254 {
1255 {
1256 switch (amd) /* closed keyed door */
1257 {
1258 case 1:
1259 /*bluekey*/
1260 AM_drawMline(&l,
1261 mapcolor_bdor? mapcolor_bdor : mapcolor_cchg);
1262 continue;
1263 case 2:
1264 /*yellowkey*/
1265 AM_drawMline(&l,
1266 mapcolor_ydor? mapcolor_ydor : mapcolor_cchg);
1267 continue;
1268 case 0:
1269 /*redkey*/
1270 AM_drawMline(&l,
1271 mapcolor_rdor? mapcolor_rdor : mapcolor_cchg);
1272 continue;
1273 case 3:
1274 /*any or all*/
1275 AM_drawMline(&l,
1276 mapcolor_clsd? mapcolor_clsd : mapcolor_cchg);
1277 continue;
1278 }
1279 }
1280 }
1281 }
1282 if /* jff 4/23/98 add exit lines to automap */
1283 (
1284 mapcolor_exit &&
1285 (
1286 lines[i].special==11 ||
1287 lines[i].special==52 ||
1288 lines[i].special==197 ||
1289 lines[i].special==51 ||
1290 lines[i].special==124 ||
1291 lines[i].special==198
1292 )
1293 ) {
1294 AM_drawMline(&l, mapcolor_exit); /* exit line */
1295 continue;
1296 }
1297
1298 if (!lines[i].backsector)
1299 {
1300 // jff 1/10/98 add new color for 1S secret sector boundary
1301 if (mapcolor_secr && //jff 4/3/98 0 is disable
1302 (
1303 (
1304 map_secret_after &&
1305 P_WasSecret(lines[i].frontsector) &&
1306 !P_IsSecret(lines[i].frontsector)
1307 )
1308 ||
1309 (
1310 !map_secret_after &&
1311 P_WasSecret(lines[i].frontsector)
1312 )
1313 )
1314 )
1315 AM_drawMline(&l, mapcolor_secr); // line bounding secret sector
1316 else //jff 2/16/98 fixed bug
1317 AM_drawMline(&l, mapcolor_wall); // special was cleared
1318 }
1319 else /* now for 2S lines */
1320 {
1321 // jff 1/10/98 add color change for all teleporter types
1322 if
1323 (
1324 mapcolor_tele && !(lines[i].flags & ML_SECRET) &&
1325 (lines[i].special == 39 || lines[i].special == 97 ||
1326 lines[i].special == 125 || lines[i].special == 126)
1327 )
1328 { // teleporters
1329 AM_drawMline(&l, mapcolor_tele);
1330 }
1331 else if (lines[i].flags & ML_SECRET) // secret door
1332 {
1333 AM_drawMline(&l, mapcolor_wall); // wall color
1334 }
1335 else if
1336 (
1337 mapcolor_clsd &&
1338 !(lines[i].flags & ML_SECRET) && // non-secret closed door
1339 ((lines[i].backsector->floorheight==lines[i].backsector->ceilingheight) ||
1340 (lines[i].frontsector->floorheight==lines[i].frontsector->ceilingheight))
1341 )
1342 {
1343 AM_drawMline(&l, mapcolor_clsd); // non-secret closed door
1344 } //jff 1/6/98 show secret sector 2S lines
1345 else if
1346 (
1347 mapcolor_secr && //jff 2/16/98 fixed bug
1348 ( // special was cleared after getting it
1349 (map_secret_after &&
1350 (
1351 (P_WasSecret(lines[i].frontsector)
1352 && !P_IsSecret(lines[i].frontsector)) ||
1353 (P_WasSecret(lines[i].backsector)
1354 && !P_IsSecret(lines[i].backsector))
1355 )
1356 )
1357 || //jff 3/9/98 add logic to not show secret til after entered
1358 ( // if map_secret_after is true
1359 !map_secret_after &&
1360 (P_WasSecret(lines[i].frontsector) ||
1361 P_WasSecret(lines[i].backsector))
1362 )
1363 )
1364 )
1365 {
1366 AM_drawMline(&l, mapcolor_secr); // line bounding secret sector
1367 } //jff 1/6/98 end secret sector line change
1368 else if (lines[i].backsector->floorheight !=
1369 lines[i].frontsector->floorheight)
1370 {
1371 AM_drawMline(&l, mapcolor_fchg); // floor level change
1372 }
1373 else if (lines[i].backsector->ceilingheight !=
1374 lines[i].frontsector->ceilingheight)
1375 {
1376 AM_drawMline(&l, mapcolor_cchg); // ceiling level change
1377 }
1378 else if (mapcolor_flat && ddt_cheating)
1379 {
1380 AM_drawMline(&l, mapcolor_flat); //2S lines that appear only in IDDT
1381 }
1382 }
1383 } // now draw the lines only visible because the player has computermap
1384 else if (plr->powers[pw_allmap]) // computermap visible lines
1385 {
1386 if (!(lines[i].flags & ML_DONTDRAW)) // invisible flag lines do not show
1387 {
1388 if
1389 (
1390 mapcolor_flat
1391 ||
1392 !lines[i].backsector
1393 ||
1394 lines[i].backsector->floorheight
1395 != lines[i].frontsector->floorheight
1396 ||
1397 lines[i].backsector->ceilingheight
1398 != lines[i].frontsector->ceilingheight
1399 )
1400 AM_drawMline(&l, mapcolor_unsn);
1401 }
1402 }
1403 }
1404}
1405
1406//
1407// AM_drawLineCharacter()
1408//
1409// Draws a vector graphic according to numerous parameters
1410//
1411// Passed the structure defining the vector graphic shape, the number
1412// of vectors in it, the scale to draw it at, the angle to draw it at,
1413// the color to draw it with, and the map coordinates to draw it at.
1414// Returns nothing
1415//
1416void AM_drawLineCharacter
1417( mline_t* lineguy,
1418 int lineguylines,
1419 fixed_t scale,
1420 angle_t angle,
1421 int color,
1422 fixed_t x,
1423 fixed_t y )
1424{
1425 int i;
1426 mline_t l;
1427
1428 if (automapmode & am_rotate) angle -= plr->mo->angle - ANG90; // cph
1429
1430 for (i=0;i<lineguylines;i++)
1431 {
1432 l.a.x = lineguy[i].a.x;
1433 l.a.y = lineguy[i].a.y;
1434
1435 if (scale)
1436 {
1437 l.a.x = FixedMul(scale, l.a.x);
1438 l.a.y = FixedMul(scale, l.a.y);
1439 }
1440
1441 if (angle)
1442 AM_rotate(&l.a.x, &l.a.y, angle, 0, 0);
1443
1444 l.a.x += x;
1445 l.a.y += y;
1446
1447 l.b.x = lineguy[i].b.x;
1448 l.b.y = lineguy[i].b.y;
1449
1450 if (scale)
1451 {
1452 l.b.x = FixedMul(scale, l.b.x);
1453 l.b.y = FixedMul(scale, l.b.y);
1454 }
1455
1456 if (angle)
1457 AM_rotate(&l.b.x, &l.b.y, angle, 0, 0);
1458
1459 l.b.x += x;
1460 l.b.y += y;
1461
1462 AM_drawMline(&l, color);
1463 }
1464}
1465
1466//
1467// AM_drawPlayers()
1468//
1469// Draws the player arrow in single player,
1470// or all the player arrows in a netgame.
1471//
1472// Passed nothing, returns nothing
1473//
1474void AM_drawPlayers(void)
1475{
1476 int i;
1477
1478 if (!netgame)
1479 {
1480 if (ddt_cheating)
1481 AM_drawLineCharacter
1482 (
1483 cheat_player_arrow,
1484 NUMCHEATPLYRLINES,
1485 0,
1486 plr->mo->angle,
1487 mapcolor_sngl, //jff color
1488 plr->mo->x,
1489 plr->mo->y
1490 );
1491 else
1492 AM_drawLineCharacter
1493 (
1494 player_arrow,
1495 NUMPLYRLINES,
1496 0,
1497 plr->mo->angle,
1498 mapcolor_sngl, //jff color
1499 plr->mo->x,
1500 plr->mo->y);
1501 return;
1502 }
1503
1504 for (i=0;i<MAXPLAYERS;i++) {
1505 player_t* p = &players[i];
1506
1507 if ( (deathmatch && !singledemo) && p != plr)
1508 continue;
1509
1510 if (playeringame[i]) {
1511 fixed_t x = p->mo->x, y = p->mo->y;
1512 if (automapmode & am_rotate)
1513 AM_rotate(&x, &y, ANG90-plr->mo->angle, plr->mo->x, plr->mo->y);
1514
1515 AM_drawLineCharacter (player_arrow, NUMPLYRLINES, 0, p->mo->angle,
1516 p->powers[pw_invisibility] ? 246 /* *close* to black */
1517 : mapcolor_plyr[i], //jff 1/6/98 use default color
1518 x, y);
1519 }
1520 }
1521}
1522
1523//
1524// AM_drawThings()
1525//
1526// Draws the things on the automap in double IDDT cheat mode
1527//
1528// Passed colors and colorrange, no longer used
1529// Returns nothing
1530//
1531void AM_drawThings
1532( int colors,
1533 int colorrange)
1534{
1535 (void)colors;
1536 (void)colorrange;
1537 int i;
1538 mobj_t* t;
1539
1540 // for all sectors
1541 for (i=0;i<numsectors;i++)
1542 {
1543 t = sectors[i].thinglist;
1544 while (t) // for all things in that sector
1545 {
1546 fixed_t x = t->x, y = t->y;
1547
1548 if (automapmode & am_rotate)
1549 AM_rotate(&x, &y, ANG90-plr->mo->angle, plr->mo->x, plr->mo->y);
1550
1551 //jff 1/5/98 case over doomednum of thing being drawn
1552 if (mapcolor_rkey || mapcolor_ykey || mapcolor_bkey)
1553 {
1554 switch(t->info->doomednum)
1555 {
1556 //jff 1/5/98 treat keys special
1557 case 38: case 13: //jff red key
1558 AM_drawLineCharacter
1559 (
1560 cross_mark,
1561 NUMCROSSMARKLINES,
1562 16<<FRACBITS,
1563 t->angle,
1564 mapcolor_rkey!=-1? mapcolor_rkey : mapcolor_sprt,
1565 x, y
1566 );
1567 t = t->snext;
1568 continue;
1569 case 39: case 6: //jff yellow key
1570 AM_drawLineCharacter
1571 (
1572 cross_mark,
1573 NUMCROSSMARKLINES,
1574 16<<FRACBITS,
1575 t->angle,
1576 mapcolor_ykey!=-1? mapcolor_ykey : mapcolor_sprt,
1577 x, y
1578 );
1579 t = t->snext;
1580 continue;
1581 case 40: case 5: //jff blue key
1582 AM_drawLineCharacter
1583 (
1584 cross_mark,
1585 NUMCROSSMARKLINES,
1586 16<<FRACBITS,
1587 t->angle,
1588 mapcolor_bkey!=-1? mapcolor_bkey : mapcolor_sprt,
1589 x, y
1590 );
1591 t = t->snext;
1592 continue;
1593 default:
1594 break;
1595 }
1596 }
1597 //jff 1/5/98 end added code for keys
1598 //jff previously entire code
1599 AM_drawLineCharacter
1600 (
1601 thintriangle_guy,
1602 NUMTHINTRIANGLEGUYLINES,
1603 16<<FRACBITS,
1604 t->angle,
1605 t->flags & MF_FRIEND && !t->player ? mapcolor_frnd :
1606 /* bbm 2/28/03 Show countable items in yellow. */
1607 t->flags & MF_COUNTITEM ? mapcolor_item : mapcolor_sprt,
1608 x, y
1609 );
1610 t = t->snext;
1611 }
1612 }
1613}
1614
1615//
1616// AM_drawMarks()
1617//
1618// Draw the marked locations on the automap
1619//
1620// Passed nothing, returns nothing
1621//
1622// killough 2/22/98:
1623// Rewrote AM_drawMarks(). Removed limit on marks.
1624//
1625void AM_drawMarks(void)
1626{
1627 int i;
1628 for (i=0;i<markpointnum;i++) // killough 2/22/98: remove automap mark limit
1629 if (markpoints[i].x != -1)
1630 {
1631 int w = 5;
1632 int h = 6;
1633 int fx = markpoints[i].x;
1634 int fy = markpoints[i].y;
1635 int j = i;
1636
1637 if (automapmode & am_rotate)
1638 AM_rotate(&fx, &fy, ANG90-plr->mo->angle, plr->mo->x, plr->mo->y);
1639
1640 fx = CXMTOF(fx); fy = CYMTOF(fy);
1641
1642 do
1643 {
1644 int d = j % 10;
1645 if (d==1) // killough 2/22/98: less spacing for '1'
1646 fx++;
1647
1648 if (fx >= f_x && fx < f_w - w && fy >= f_y && fy < f_h - h) {
1649 // cph - construct patch name and draw marker
1650 char namebuf[] = { 'A', 'M', 'M', 'N', 'U', 'M', '0'+d, 0 };
1651
1652 V_DrawNamePatch(fx, fy, FB, namebuf, CR_DEFAULT, VPT_NONE);
1653 }
1654 fx -= w-1; // killough 2/22/98: 1 space backwards
1655 j /= 10;
1656 }
1657 while (j>0);
1658 }
1659}
1660
1661//
1662// AM_drawCrosshair()
1663//
1664// Draw the single point crosshair representing map center
1665//
1666// Passed the color to draw the pixel with
1667// Returns nothing
1668//
1669// CPhipps - made static inline, and use the general pixel plotter function
1670
1671inline static void AM_drawCrosshair(int color)
1672{
1673 // single point for now
1674 V_PlotPixel(FB, f_w/2, f_h/2, (byte)color);
1675}
1676
1677//
1678// AM_Drawer()
1679//
1680// Draws the entire automap
1681//
1682// Passed nothing, returns nothing
1683//
1684void AM_Drawer (void)
1685{
1686 // CPhipps - all automap modes put into one enum
1687 if (!(automapmode & am_active)) return;
1688
1689 if (!(automapmode & am_overlay)) // cph - If not overlay mode, clear background for the automap
1690 V_FillRect(FB, f_x, f_y, f_w, f_h, (byte)mapcolor_back); //jff 1/5/98 background default color
1691 if (automapmode & am_grid)
1692 AM_drawGrid(mapcolor_grid); //jff 1/7/98 grid default color
1693 AM_drawWalls();
1694 AM_drawPlayers();
1695 if (ddt_cheating==2)
1696 AM_drawThings(mapcolor_sprt, 0); //jff 1/5/98 default double IDDT sprite
1697 AM_drawCrosshair(mapcolor_hair); //jff 1/7/98 default crosshair color
1698
1699 AM_drawMarks();
1700
1701 V_MarkRect(f_x, f_y, f_w, f_h);
1702}
diff --git a/apps/plugins/doom/am_map.h b/apps/plugins/doom/am_map.h
new file mode 100644
index 0000000000..5599a3c400
--- /dev/null
+++ b/apps/plugins/doom/am_map.h
@@ -0,0 +1,106 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION:
28 * AutoMap module.
29 *
30 *-----------------------------------------------------------------------------*/
31
32#ifndef __AMMAP_H__
33#define __AMMAP_H__
34
35#include "d_event.h"
36#include "m_fixed.h"
37
38// Used by ST StatusBar stuff.
39#define AM_MSGHEADER (('a'<<24)+('m'<<16))
40#define AM_MSGENTERED (AM_MSGHEADER | ('e'<<8))
41#define AM_MSGEXITED (AM_MSGHEADER | ('x'<<8))
42
43// Called by main loop.
44boolean AM_Responder (event_t* ev);
45
46// Called by main loop.
47void AM_Ticker (void);
48
49// Called by main loop,
50// called instead of view drawer if automap active.
51void AM_Drawer (void);
52
53// Called to force the automap to quit
54// if the level is completed while it is up.
55void AM_Stop (void);
56
57// killough 2/22/98: for saving automap information in savegame:
58
59extern void AM_Start(void);
60
61//jff 4/16/98 make externally available
62
63extern void AM_clearMarks(void);
64
65typedef struct
66{
67 fixed_t x,y;
68} mpoint_t;
69
70extern mpoint_t *markpoints;
71extern int markpointnum, markpointnum_max;
72
73// end changes -- killough 2/22/98
74
75// killough 5/2/98: moved from m_misc.c
76
77//jff 1/7/98 automap colors added
78extern int mapcolor_back; // map background
79extern int mapcolor_grid; // grid lines color
80extern int mapcolor_wall; // normal 1s wall color
81extern int mapcolor_fchg; // line at floor height change color
82extern int mapcolor_cchg; // line at ceiling height change color
83extern int mapcolor_clsd; // line at sector with floor=ceiling color
84extern int mapcolor_rkey; // red key color
85extern int mapcolor_bkey; // blue key color
86extern int mapcolor_ykey; // yellow key color
87extern int mapcolor_rdor; // red door color (diff from keys to allow option)
88extern int mapcolor_bdor; // blue door color (of enabling one not other)
89extern int mapcolor_ydor; // yellow door color
90extern int mapcolor_tele; // teleporter line color
91extern int mapcolor_secr; // secret sector boundary color
92//jff 4/23/98
93extern int mapcolor_exit; // exit line
94extern int mapcolor_unsn; // computer map unseen line color
95extern int mapcolor_flat; // line with no floor/ceiling changes
96extern int mapcolor_sprt; // general sprite color
97extern int mapcolor_item; // item sprite color
98extern int mapcolor_frnd; // friendly sprite color
99extern int mapcolor_hair; // crosshair color
100extern int mapcolor_sngl; // single player arrow color
101extern int mapcolor_plyr[4]; // colors for players in multiplayer
102extern int mapcolor_me; // consoleplayer's chosen colour
103//jff 3/9/98
104extern int map_secret_after; // secrets do not appear til after bagged
105
106#endif
diff --git a/apps/plugins/doom/d_englsh.h b/apps/plugins/doom/d_englsh.h
new file mode 100644
index 0000000000..596b8772e8
--- /dev/null
+++ b/apps/plugins/doom/d_englsh.h
@@ -0,0 +1,705 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION:
28 * Printed strings for translation.
29 * English language support (default).
30 * See dstrings.h for suggestions about foreign language BEX support
31 *
32 *-----------------------------------------------------------------------------*/
33
34#ifndef __D_ENGLSH__
35#define __D_ENGLSH__
36
37/* d_main.c */
38#define D_DEVSTR "Development mode ON.\n"
39#define D_CDROM "CD-ROM Version: default.cfg from c:\\doomdata\n"
40
41/* m_menu.c */
42#define PRESSKEY "press a key."
43#define PRESSYN "press y or n."
44#define QUITMSG "are you sure you want to\nquit this great game?"
45#define LOADNET "you can't do load while in a net game!\n\n"PRESSKEY
46#define QLOADNET "you can't quickload during a netgame!\n\n"PRESSKEY
47#define QSAVESPOT "you haven't picked a quicksave slot yet!\n\n"PRESSKEY
48#define SAVEDEAD "you can't save if you aren't playing!\n\n"PRESSKEY
49#define QSPROMPT "quicksave over your game named\n\n'%s'?\n\n"PRESSYN
50#define QLPROMPT "do you want to quickload the game named\n\n'%s'?\n\n"PRESSYN
51
52#define NEWGAME \
53 "you can't start a new game\n"\
54 "while in a network game.\n\n"PRESSKEY
55
56#define NIGHTMARE \
57 "are you sure? this skill level\n"\
58 "isn't even remotely fair.\n\n"PRESSYN
59
60#define SWSTRING \
61 "this is the shareware version of doom.\n\n"\
62 "you need to order the entire trilogy.\n\n"PRESSKEY
63
64#define MSGOFF "Messages OFF"
65#define MSGON "Messages ON"
66#define NETEND "you can't end a netgame!\n\n"PRESSKEY
67#define ENDGAME "are you sure you want to end the game?\n\n"PRESSYN
68#define RESTARTLEVEL "restart the level?\n\n"PRESSYN
69
70#define DOSY "(press y to quit)"
71
72#define DETAILHI "High detail"
73#define DETAILLO "Low detail"
74#define GAMMALVL0 "Gamma correction OFF"
75#define GAMMALVL1 "Gamma correction level 1"
76#define GAMMALVL2 "Gamma correction level 2"
77#define GAMMALVL3 "Gamma correction level 3"
78#define GAMMALVL4 "Gamma correction level 4"
79#define EMPTYSTRING "empty slot"
80
81/* p_inter.c */
82#define GOTARMOR "Picked up the armor."
83#define GOTMEGA "Picked up the MegaArmor!"
84#define GOTHTHBONUS "Picked up a health bonus."
85#define GOTARMBONUS "Picked up an armor bonus."
86#define GOTSTIM "Picked up a stimpack."
87#define GOTMEDINEED "Picked up a medikit that you REALLY need!"
88#define GOTMEDIKIT "Picked up a medikit."
89#define GOTSUPER "Supercharge!"
90
91#define GOTBLUECARD "Picked up a blue keycard."
92#define GOTYELWCARD "Picked up a yellow keycard."
93#define GOTREDCARD "Picked up a red keycard."
94#define GOTBLUESKUL "Picked up a blue skull key."
95#define GOTYELWSKUL "Picked up a yellow skull key."
96#define GOTREDSKULL "Picked up a red skull key."
97
98#define GOTINVUL "Invulnerability!"
99#define GOTBERSERK "Berserk!"
100#define GOTINVIS "Partial Invisibility"
101#define GOTSUIT "Radiation Shielding Suit"
102#define GOTMAP "Computer Area Map"
103#define GOTVISOR "Light Amplification Visor"
104#define GOTMSPHERE "MegaSphere!"
105
106#define GOTCLIP "Picked up a clip."
107#define GOTCLIPBOX "Picked up a box of bullets."
108#define GOTROCKET "Picked up a rocket."
109#define GOTROCKBOX "Picked up a box of rockets."
110#define GOTCELL "Picked up an energy cell."
111#define GOTCELLBOX "Picked up an energy cell pack."
112#define GOTSHELLS "Picked up 4 shotgun shells."
113#define GOTSHELLBOX "Picked up a box of shotgun shells."
114#define GOTBACKPACK "Picked up a backpack full of ammo!"
115
116#define GOTBFG9000 "You got the BFG9000! Oh, yes."
117#define GOTCHAINGUN "You got the chaingun!"
118#define GOTCHAINSAW "A chainsaw! Find some meat!"
119#define GOTLAUNCHER "You got the rocket launcher!"
120#define GOTPLASMA "You got the plasma gun!"
121#define GOTSHOTGUN "You got the shotgun!"
122#define GOTSHOTGUN2 "You got the super shotgun!"
123
124/* p_doors.c */
125#define PD_BLUEO "You need a blue key to activate this object"
126#define PD_REDO "You need a red key to activate this object"
127#define PD_YELLOWO "You need a yellow key to activate this object"
128#define PD_BLUEK "You need a blue key to open this door"
129#define PD_REDK "You need a red key to open this door"
130#define PD_YELLOWK "You need a yellow key to open this door"
131/* jff 02/05/98 Create messages specific to card and skull keys */
132#define PD_BLUEC "You need a blue card to open this door"
133#define PD_REDC "You need a red card to open this door"
134#define PD_YELLOWC "You need a yellow card to open this door"
135#define PD_BLUES "You need a blue skull to open this door"
136#define PD_REDS "You need a red skull to open this door"
137#define PD_YELLOWS "You need a yellow skull to open this door"
138#define PD_ANY "Any key will open this door"
139#define PD_ALL3 "You need all three keys to open this door"
140#define PD_ALL6 "You need all six keys to open this door"
141
142/* g_game.c */
143#define GGSAVED "game saved."
144
145/* hu_stuff.c */
146#define HUSTR_MSGU "[Message unsent]"
147
148#define HUSTR_E1M1 "E1M1: Hangar"
149#define HUSTR_E1M2 "E1M2: Nuclear Plant"
150#define HUSTR_E1M3 "E1M3: Toxin Refinery"
151#define HUSTR_E1M4 "E1M4: Command Control"
152#define HUSTR_E1M5 "E1M5: Phobos Lab"
153#define HUSTR_E1M6 "E1M6: Central Processing"
154#define HUSTR_E1M7 "E1M7: Computer Station"
155#define HUSTR_E1M8 "E1M8: Phobos Anomaly"
156#define HUSTR_E1M9 "E1M9: Military Base"
157
158#define HUSTR_E2M1 "E2M1: Deimos Anomaly"
159#define HUSTR_E2M2 "E2M2: Containment Area"
160#define HUSTR_E2M3 "E2M3: Refinery"
161#define HUSTR_E2M4 "E2M4: Deimos Lab"
162#define HUSTR_E2M5 "E2M5: Command Center"
163#define HUSTR_E2M6 "E2M6: Halls of the Damned"
164#define HUSTR_E2M7 "E2M7: Spawning Vats"
165#define HUSTR_E2M8 "E2M8: Tower of Babel"
166#define HUSTR_E2M9 "E2M9: Fortress of Mystery"
167
168#define HUSTR_E3M1 "E3M1: Hell Keep"
169#define HUSTR_E3M2 "E3M2: Slough of Despair"
170#define HUSTR_E3M3 "E3M3: Pandemonium"
171#define HUSTR_E3M4 "E3M4: House of Pain"
172#define HUSTR_E3M5 "E3M5: Unholy Cathedral"
173#define HUSTR_E3M6 "E3M6: Mt. Erebus"
174#define HUSTR_E3M7 "E3M7: Limbo"
175#define HUSTR_E3M8 "E3M8: Dis"
176#define HUSTR_E3M9 "E3M9: Warrens"
177
178#define HUSTR_E4M1 "E4M1: Hell Beneath"
179#define HUSTR_E4M2 "E4M2: Perfect Hatred"
180#define HUSTR_E4M3 "E4M3: Sever The Wicked"
181#define HUSTR_E4M4 "E4M4: Unruly Evil"
182#define HUSTR_E4M5 "E4M5: They Will Repent"
183#define HUSTR_E4M6 "E4M6: Against Thee Wickedly"
184#define HUSTR_E4M7 "E4M7: And Hell Followed"
185#define HUSTR_E4M8 "E4M8: Unto The Cruel"
186#define HUSTR_E4M9 "E4M9: Fear"
187
188#define HUSTR_1 "level 1: entryway"
189#define HUSTR_2 "level 2: underhalls"
190#define HUSTR_3 "level 3: the gantlet"
191#define HUSTR_4 "level 4: the focus"
192#define HUSTR_5 "level 5: the waste tunnels"
193#define HUSTR_6 "level 6: the crusher"
194#define HUSTR_7 "level 7: dead simple"
195#define HUSTR_8 "level 8: tricks and traps"
196#define HUSTR_9 "level 9: the pit"
197#define HUSTR_10 "level 10: refueling base"
198#define HUSTR_11 "level 11: 'o' of destruction!"
199
200#define HUSTR_12 "level 12: the factory"
201#define HUSTR_13 "level 13: downtown"
202#define HUSTR_14 "level 14: the inmost dens"
203#define HUSTR_15 "level 15: industrial zone"
204#define HUSTR_16 "level 16: suburbs"
205#define HUSTR_17 "level 17: tenements"
206#define HUSTR_18 "level 18: the courtyard"
207#define HUSTR_19 "level 19: the citadel"
208#define HUSTR_20 "level 20: gotcha!"
209
210#define HUSTR_21 "level 21: nirvana"
211#define HUSTR_22 "level 22: the catacombs"
212#define HUSTR_23 "level 23: barrels o' fun"
213#define HUSTR_24 "level 24: the chasm"
214#define HUSTR_25 "level 25: bloodfalls"
215#define HUSTR_26 "level 26: the abandoned mines"
216#define HUSTR_27 "level 27: monster condo"
217#define HUSTR_28 "level 28: the spirit world"
218#define HUSTR_29 "level 29: the living end"
219#define HUSTR_30 "level 30: icon of sin"
220
221#define HUSTR_31 "level 31: wolfenstein"
222#define HUSTR_32 "level 32: grosse"
223
224#define PHUSTR_1 "level 1: congo"
225#define PHUSTR_2 "level 2: well of souls"
226#define PHUSTR_3 "level 3: aztec"
227#define PHUSTR_4 "level 4: caged"
228#define PHUSTR_5 "level 5: ghost town"
229#define PHUSTR_6 "level 6: baron's lair"
230#define PHUSTR_7 "level 7: caughtyard"
231#define PHUSTR_8 "level 8: realm"
232#define PHUSTR_9 "level 9: abattoire"
233#define PHUSTR_10 "level 10: onslaught"
234#define PHUSTR_11 "level 11: hunted"
235
236#define PHUSTR_12 "level 12: speed"
237#define PHUSTR_13 "level 13: the crypt"
238#define PHUSTR_14 "level 14: genesis"
239#define PHUSTR_15 "level 15: the twilight"
240#define PHUSTR_16 "level 16: the omen"
241#define PHUSTR_17 "level 17: compound"
242#define PHUSTR_18 "level 18: neurosphere"
243#define PHUSTR_19 "level 19: nme"
244#define PHUSTR_20 "level 20: the death domain"
245
246#define PHUSTR_21 "level 21: slayer"
247#define PHUSTR_22 "level 22: impossible mission"
248#define PHUSTR_23 "level 23: tombstone"
249#define PHUSTR_24 "level 24: the final frontier"
250#define PHUSTR_25 "level 25: the temple of darkness"
251#define PHUSTR_26 "level 26: bunker"
252#define PHUSTR_27 "level 27: anti-christ"
253#define PHUSTR_28 "level 28: the sewers"
254#define PHUSTR_29 "level 29: odyssey of noises"
255#define PHUSTR_30 "level 30: the gateway of hell"
256
257#define PHUSTR_31 "level 31: cyberden"
258#define PHUSTR_32 "level 32: go 2 it"
259
260#define THUSTR_1 "level 1: system control"
261#define THUSTR_2 "level 2: human bbq"
262#define THUSTR_3 "level 3: power control"
263#define THUSTR_4 "level 4: wormhole"
264#define THUSTR_5 "level 5: hanger"
265#define THUSTR_6 "level 6: open season"
266#define THUSTR_7 "level 7: prison"
267#define THUSTR_8 "level 8: metal"
268#define THUSTR_9 "level 9: stronghold"
269#define THUSTR_10 "level 10: redemption"
270#define THUSTR_11 "level 11: storage facility"
271
272#define THUSTR_12 "level 12: crater"
273#define THUSTR_13 "level 13: nukage processing"
274#define THUSTR_14 "level 14: steel works"
275#define THUSTR_15 "level 15: dead zone"
276#define THUSTR_16 "level 16: deepest reaches"
277#define THUSTR_17 "level 17: processing area"
278#define THUSTR_18 "level 18: mill"
279#define THUSTR_19 "level 19: shipping/respawning"
280#define THUSTR_20 "level 20: central processing"
281
282#define THUSTR_21 "level 21: administration center"
283#define THUSTR_22 "level 22: habitat"
284#define THUSTR_23 "level 23: lunar mining project"
285#define THUSTR_24 "level 24: quarry"
286#define THUSTR_25 "level 25: baron's den"
287#define THUSTR_26 "level 26: ballistyx"
288#define THUSTR_27 "level 27: mount pain"
289#define THUSTR_28 "level 28: heck"
290#define THUSTR_29 "level 29: river styx"
291#define THUSTR_30 "level 30: last call"
292
293#define THUSTR_31 "level 31: pharaoh"
294#define THUSTR_32 "level 32: caribbean"
295
296#define HUSTR_CHATMACRO1 "I'm ready to kick butt!"
297#define HUSTR_CHATMACRO2 "I'm OK."
298#define HUSTR_CHATMACRO3 "I'm not looking too good!"
299#define HUSTR_CHATMACRO4 "Help!"
300#define HUSTR_CHATMACRO5 "You suck!"
301#define HUSTR_CHATMACRO6 "Next time, scumbag..."
302#define HUSTR_CHATMACRO7 "Come here!"
303#define HUSTR_CHATMACRO8 "I'll take care of it."
304#define HUSTR_CHATMACRO9 "Yes"
305#define HUSTR_CHATMACRO0 "No"
306
307#define HUSTR_TALKTOSELF1 "You mumble to yourself"
308#define HUSTR_TALKTOSELF2 "Who's there?"
309#define HUSTR_TALKTOSELF3 "You scare yourself"
310#define HUSTR_TALKTOSELF4 "You start to rave"
311#define HUSTR_TALKTOSELF5 "You've lost it..."
312
313#define HUSTR_MESSAGESENT "[Message Sent]"
314
315/* The following should NOT be changed unless it seems
316 * just AWFULLY necessary */
317
318#define HUSTR_PLRGREEN "Player 1: "
319#define HUSTR_PLRINDIGO "Player 2: "
320#define HUSTR_PLRBROWN "Player 3: "
321#define HUSTR_PLRRED "Player 4: "
322
323#define HUSTR_KEYGREEN 'g'
324#define HUSTR_KEYINDIGO 'i'
325#define HUSTR_KEYBROWN 'b'
326#define HUSTR_KEYRED 'r'
327
328/* am_map.c */
329
330#define AMSTR_FOLLOWON "Follow Mode ON"
331#define AMSTR_FOLLOWOFF "Follow Mode OFF"
332
333#define AMSTR_GRIDON "Grid ON"
334#define AMSTR_GRIDOFF "Grid OFF"
335
336#define AMSTR_MARKEDSPOT "Marked Spot"
337#define AMSTR_MARKSCLEARED "All Marks Cleared"
338
339#define AMSTR_ROTATEON "Rotate Mode ON"
340#define AMSTR_ROTATEOFF "Rotate Mode OFF"
341
342#define AMSTR_OVERLAYON "Overlay Mode ON"
343#define AMSTR_OVERLAYOFF "Overlay Mode OFF"
344
345/* st_stuff.c */
346
347#define STSTR_MUS "Music Change"
348#define STSTR_NOMUS "IMPOSSIBLE SELECTION"
349#define STSTR_DQDON "Degreelessness Mode On"
350#define STSTR_DQDOFF "Degreelessness Mode Off"
351
352#define STSTR_KFAADDED "Very Happy Ammo Added"
353#define STSTR_FAADDED "Ammo (no keys) Added"
354
355#define STSTR_NCON "No Clipping Mode ON"
356#define STSTR_NCOFF "No Clipping Mode OFF"
357
358#define STSTR_BEHOLD "inVuln, Str, Inviso, Rad, Allmap, or Lite-amp"
359#define STSTR_BEHOLDX "Power-up Toggled"
360
361#define STSTR_CHOPPERS "... doesn't suck - GM"
362#define STSTR_CLEV "Changing Level..."
363
364#define STSTR_COMPON "Compatibility Mode On" /* phares */
365#define STSTR_COMPOFF "Compatibility Mode Off" /* phares */
366
367/* f_finale.c */
368
369#define E1TEXT \
370 "Once you beat the big badasses and\n"\
371 "clean out the moon base you're supposed\n"\
372 "to win, aren't you? Aren't you? Where's\n"\
373 "your fat reward and ticket home? What\n"\
374 "the hell is this? It's not supposed to\n"\
375 "end this way!\n"\
376 "\n" \
377 "It stinks like rotten meat, but looks\n"\
378 "like the lost Deimos base. Looks like\n"\
379 "you're stuck on The Shores of Hell.\n"\
380 "The only way out is through.\n"\
381 "\n"\
382 "To continue the DOOM experience, play\n"\
383 "The Shores of Hell and its amazing\n"\
384 "sequel, Inferno!\n"
385
386
387#define E2TEXT \
388 "You've done it! The hideous cyber-\n"\
389 "demon lord that ruled the lost Deimos\n"\
390 "moon base has been slain and you\n"\
391 "are triumphant! But ... where are\n"\
392 "you? You clamber to the edge of the\n"\
393 "moon and look down to see the awful\n"\
394 "truth.\n" \
395 "\n"\
396 "Deimos floats above Hell itself!\n"\
397 "You've never heard of anyone escaping\n"\
398 "from Hell, but you'll make the bastards\n"\
399 "sorry they ever heard of you! Quickly,\n"\
400 "you rappel down to the surface of\n"\
401 "Hell.\n"\
402 "\n" \
403 "Now, it's on to the final chapter of\n"\
404 "DOOM! -- Inferno."
405
406
407#define E3TEXT \
408 "The loathsome spiderdemon that\n"\
409 "masterminded the invasion of the moon\n"\
410 "bases and caused so much death has had\n"\
411 "its ass kicked for all time.\n"\
412 "\n"\
413 "A hidden doorway opens and you enter.\n"\
414 "You've proven too tough for Hell to\n"\
415 "contain, and now Hell at last plays\n"\
416 "fair -- for you emerge from the door\n"\
417 "to see the green fields of Earth!\n"\
418 "Home at last.\n" \
419 "\n"\
420 "You wonder what's been happening on\n"\
421 "Earth while you were battling evil\n"\
422 "unleashed. It's good that no Hell-\n"\
423 "spawn could have come through that\n"\
424 "door with you ..."
425
426
427#define E4TEXT \
428 "the spider mastermind must have sent forth\n"\
429 "its legions of hellspawn before your\n"\
430 "final confrontation with that terrible\n"\
431 "beast from hell. but you stepped forward\n"\
432 "and brought forth eternal damnation and\n"\
433 "suffering upon the horde as a true hero\n"\
434 "would in the face of something so evil.\n"\
435 "\n"\
436 "besides, someone was gonna pay for what\n"\
437 "happened to daisy, your pet rabbit.\n"\
438 "\n"\
439 "but now, you see spread before you more\n"\
440 "potential pain and gibbitude as a nation\n"\
441 "of demons run amok among our cities.\n"\
442 "\n"\
443 "next stop, hell on earth!"
444
445
446/* after level 6, put this: */
447
448#define C1TEXT \
449 "YOU HAVE ENTERED DEEPLY INTO THE INFESTED\n" \
450 "STARPORT. BUT SOMETHING IS WRONG. THE\n" \
451 "MONSTERS HAVE BROUGHT THEIR OWN REALITY\n" \
452 "WITH THEM, AND THE STARPORT'S TECHNOLOGY\n" \
453 "IS BEING SUBVERTED BY THEIR PRESENCE.\n" \
454 "\n"\
455 "AHEAD, YOU SEE AN OUTPOST OF HELL, A\n" \
456 "FORTIFIED ZONE. IF YOU CAN GET PAST IT,\n" \
457 "YOU CAN PENETRATE INTO THE HAUNTED HEART\n" \
458 "OF THE STARBASE AND FIND THE CONTROLLING\n" \
459 "SWITCH WHICH HOLDS EARTH'S POPULATION\n" \
460 "HOSTAGE."
461
462/* After level 11, put this: */
463
464#define C2TEXT \
465 "YOU HAVE WON! YOUR VICTORY HAS ENABLED\n" \
466 "HUMANKIND TO EVACUATE EARTH AND ESCAPE\n"\
467 "THE NIGHTMARE. NOW YOU ARE THE ONLY\n"\
468 "HUMAN LEFT ON THE FACE OF THE PLANET.\n"\
469 "CANNIBAL MUTATIONS, CARNIVOROUS ALIENS,\n"\
470 "AND EVIL SPIRITS ARE YOUR ONLY NEIGHBORS.\n"\
471 "YOU SIT BACK AND WAIT FOR DEATH, CONTENT\n"\
472 "THAT YOU HAVE SAVED YOUR SPECIES.\n"\
473 "\n"\
474 "BUT THEN, EARTH CONTROL BEAMS DOWN A\n"\
475 "MESSAGE FROM SPACE: \"SENSORS HAVE LOCATED\n"\
476 "THE SOURCE OF THE ALIEN INVASION. IF YOU\n"\
477 "GO THERE, YOU MAY BE ABLE TO BLOCK THEIR\n"\
478 "ENTRY. THE ALIEN BASE IS IN THE HEART OF\n"\
479 "YOUR OWN HOME CITY, NOT FAR FROM THE\n"\
480 "STARPORT.\" SLOWLY AND PAINFULLY YOU GET\n"\
481 "UP AND RETURN TO THE FRAY."
482
483
484/* After level 20, put this: */
485
486#define C3TEXT \
487 "YOU ARE AT THE CORRUPT HEART OF THE CITY,\n"\
488 "SURROUNDED BY THE CORPSES OF YOUR ENEMIES.\n"\
489 "YOU SEE NO WAY TO DESTROY THE CREATURES'\n"\
490 "ENTRYWAY ON THIS SIDE, SO YOU CLENCH YOUR\n"\
491 "TEETH AND PLUNGE THROUGH IT.\n"\
492 "\n"\
493 "THERE MUST BE A WAY TO CLOSE IT ON THE\n"\
494 "OTHER SIDE. WHAT DO YOU CARE IF YOU'VE\n"\
495 "GOT TO GO THROUGH HELL TO GET TO IT?"
496
497
498/* After level 29, put this: */
499
500#define C4TEXT \
501 "THE HORRENDOUS VISAGE OF THE BIGGEST\n"\
502 "DEMON YOU'VE EVER SEEN CRUMBLES BEFORE\n"\
503 "YOU, AFTER YOU PUMP YOUR ROCKETS INTO\n"\
504 "HIS EXPOSED BRAIN. THE MONSTER SHRIVELS\n"\
505 "UP AND DIES, ITS THRASHING LIMBS\n"\
506 "DEVASTATING UNTOLD MILES OF HELL'S\n"\
507 "SURFACE.\n"\
508 "\n"\
509 "YOU'VE DONE IT. THE INVASION IS OVER.\n"\
510 "EARTH IS SAVED. HELL IS A WRECK. YOU\n"\
511 "WONDER WHERE BAD FOLKS WILL GO WHEN THEY\n"\
512 "DIE, NOW. WIPING THE SWEAT FROM YOUR\n"\
513 "FOREHEAD YOU BEGIN THE LONG TREK BACK\n"\
514 "HOME. REBUILDING EARTH OUGHT TO BE A\n"\
515 "LOT MORE FUN THAN RUINING IT WAS.\n"
516
517/* Before level 31, put this: */
518
519#define C5TEXT \
520 "CONGRATULATIONS, YOU'VE FOUND THE SECRET\n"\
521 "LEVEL! LOOKS LIKE IT'S BEEN BUILT BY\n"\
522 "HUMANS, RATHER THAN DEMONS. YOU WONDER\n"\
523 "WHO THE INMATES OF THIS CORNER OF HELL\n"\
524 "WILL BE."
525
526
527/* Before level 32, put this: */
528
529#define C6TEXT \
530 "CONGRATULATIONS, YOU'VE FOUND THE\n"\
531 "SUPER SECRET LEVEL! YOU'D BETTER\n"\
532 "BLAZE THROUGH THIS ONE!\n"
533
534/*** Plutonia ***/
535/* after map 06 */
536
537#define P1TEXT \
538 "You gloat over the steaming carcass of the\n"\
539 "Guardian. With its death, you've wrested\n"\
540 "the Accelerator from the stinking claws\n"\
541 "of Hell. You relax and glance around the\n"\
542 "room. Damn! There was supposed to be at\n"\
543 "least one working prototype, but you can't\n"\
544 "see it. The demons must have taken it.\n"\
545 "\n"\
546 "You must find the prototype, or all your\n"\
547 "struggles will have been wasted. Keep\n"\
548 "moving, keep fighting, keep killing.\n"\
549 "Oh yes, keep living, too."
550
551
552/* after map 11 */
553
554#define P2TEXT \
555 "Even the deadly Arch-Vile labyrinth could\n"\
556 "not stop you, and you've gotten to the\n"\
557 "prototype Accelerator which is soon\n"\
558 "efficiently and permanently deactivated.\n"\
559 "\n"\
560 "You're good at that kind of thing."
561
562
563/* after map 20 */
564
565#define P3TEXT \
566 "You've bashed and battered your way into\n"\
567 "the heart of the devil-hive. Time for a\n"\
568 "Search-and-Destroy mission, aimed at the\n"\
569 "Gatekeeper, whose foul offspring is\n"\
570 "cascading to Earth. Yeah, he's bad. But\n"\
571 "you know who's worse!\n"\
572 "\n"\
573 "Grinning evilly, you check your gear, and\n"\
574 "get ready to give the bastard a little Hell\n"\
575 "of your own making!"
576
577/* after map 30 */
578
579#define P4TEXT \
580 "The Gatekeeper's evil face is splattered\n"\
581 "all over the place. As its tattered corpse\n"\
582 "collapses, an inverted Gate forms and\n"\
583 "sucks down the shards of the last\n"\
584 "prototype Accelerator, not to mention the\n"\
585 "few remaining demons. You're done. Hell\n"\
586 "has gone back to pounding bad dead folks \n"\
587 "instead of good live ones. Remember to\n"\
588 "tell your grandkids to put a rocket\n"\
589 "launcher in your coffin. If you go to Hell\n"\
590 "when you die, you'll need it for some\n"\
591 "final cleaning-up ..."
592
593/* before map 31 */
594
595#define P5TEXT \
596 "You've found the second-hardest level we\n"\
597 "got. Hope you have a saved game a level or\n"\
598 "two previous. If not, be prepared to die\n"\
599 "aplenty. For master marines only."
600
601/* before map 32 */
602
603#define P6TEXT \
604 "Betcha wondered just what WAS the hardest\n"\
605 "level we had ready for ya? Now you know.\n"\
606 "No one gets out alive."
607
608/*** TNT: Evilution ***/
609
610#define T1TEXT \
611 "You've fought your way out of the infested\n"\
612 "experimental labs. It seems that UAC has\n"\
613 "once again gulped it down. With their\n"\
614 "high turnover, it must be hard for poor\n"\
615 "old UAC to buy corporate health insurance\n"\
616 "nowadays..\n"\
617 "\n"\
618 "Ahead lies the military complex, now\n"\
619 "swarming with diseased horrors hot to get\n"\
620 "their teeth into you. With luck, the\n"\
621 "complex still has some warlike ordnance\n"\
622 "laying around."
623
624
625#define T2TEXT \
626 "You hear the grinding of heavy machinery\n"\
627 "ahead. You sure hope they're not stamping\n"\
628 "out new hellspawn, but you're ready to\n"\
629 "ream out a whole herd if you have to.\n"\
630 "They might be planning a blood feast, but\n"\
631 "you feel about as mean as two thousand\n"\
632 "maniacs packed into one mad killer.\n"\
633 "\n"\
634 "You don't plan to go down easy."
635
636
637#define T3TEXT \
638 "The vista opening ahead looks real damn\n"\
639 "familiar. Smells familiar, too -- like\n"\
640 "fried excrement. You didn't like this\n"\
641 "place before, and you sure as hell ain't\n"\
642 "planning to like it now. The more you\n"\
643 "brood on it, the madder you get.\n"\
644 "Hefting your gun, an evil grin trickles\n"\
645 "onto your face. Time to take some names."
646
647#define T4TEXT \
648 "Suddenly, all is silent, from one horizon\n"\
649 "to the other. The agonizing echo of Hell\n"\
650 "fades away, the nightmare sky turns to\n"\
651 "blue, the heaps of monster corpses start \n"\
652 "to evaporate along with the evil stench \n"\
653 "that filled the air. Jeeze, maybe you've\n"\
654 "done it. Have you really won?\n"\
655 "\n"\
656 "Something rumbles in the distance.\n"\
657 "A blue light begins to glow inside the\n"\
658 "ruined skull of the demon-spitter."
659
660
661#define T5TEXT \
662 "What now? Looks totally different. Kind\n"\
663 "of like King Tut's condo. Well,\n"\
664 "whatever's here can't be any worse\n"\
665 "than usual. Can it? Or maybe it's best\n"\
666 "to let sleeping gods lie.."
667
668
669#define T6TEXT \
670 "Time for a vacation. You've burst the\n"\
671 "bowels of hell and by golly you're ready\n"\
672 "for a break. You mutter to yourself,\n"\
673 "Maybe someone else can kick Hell's ass\n"\
674 "next time around. Ahead lies a quiet town,\n"\
675 "with peaceful flowing water, quaint\n"\
676 "buildings, and presumably no Hellspawn.\n"\
677 "\n"\
678 "As you step off the transport, you hear\n"\
679 "the stomp of a cyberdemon's iron shoe."
680
681
682
683/*
684 * Character cast strings F_FINALE.C
685 */
686#define CC_ZOMBIE "ZOMBIEMAN"
687#define CC_SHOTGUN "SHOTGUN GUY"
688#define CC_HEAVY "HEAVY WEAPON DUDE"
689#define CC_IMP "IMP"
690#define CC_DEMON "DEMON"
691#define CC_LOST "LOST SOUL"
692#define CC_CACO "CACODEMON"
693#define CC_HELL "HELL KNIGHT"
694#define CC_BARON "BARON OF HELL"
695#define CC_ARACH "ARACHNOTRON"
696#define CC_PAIN "PAIN ELEMENTAL"
697#define CC_REVEN "REVENANT"
698#define CC_MANCU "MANCUBUS"
699#define CC_ARCH "ARCH-VILE"
700#define CC_SPIDER "THE SPIDER MASTERMIND"
701#define CC_CYBER "THE CYBERDEMON"
702#define CC_HERO "OUR HERO"
703
704
705#endif
diff --git a/apps/plugins/doom/d_event.h b/apps/plugins/doom/d_event.h
new file mode 100644
index 0000000000..6896fd5c37
--- /dev/null
+++ b/apps/plugins/doom/d_event.h
@@ -0,0 +1,128 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION:
28 * Event information structures.
29 *
30 *-----------------------------------------------------------------------------*/
31
32
33#ifndef __D_EVENT__
34#define __D_EVENT__
35
36
37#include "doomtype.h"
38
39
40//
41// Event handling.
42//
43
44// Input event types.
45typedef enum
46{
47 ev_keydown,
48 ev_keyup,
49 ev_mouse,
50 ev_joystick
51} evtype_t;
52
53// Event structure.
54typedef struct
55{
56 evtype_t type;
57 int data1; // keys / mouse/joystick buttons
58 int data2; // mouse/joystick x move
59 int data3; // mouse/joystick y move
60} event_t;
61
62
63typedef enum
64{
65 ga_nothing,
66 ga_loadlevel,
67 ga_newgame,
68 ga_loadgame,
69 ga_savegame,
70 ga_playdemo,
71 ga_completed,
72 ga_victory,
73 ga_worlddone,
74} gameaction_t;
75
76
77
78//
79// Button/action code definitions.
80//
81typedef enum
82{
83 // Press "Fire".
84 BT_ATTACK = 1,
85
86 // Use button, to open doors, activate switches.
87 BT_USE = 2,
88
89 // Flag: game events, not really buttons.
90 BT_SPECIAL = 128,
91 BT_SPECIALMASK = 3,
92
93 // Flag, weapon change pending.
94 // If true, the next 4 bits hold weapon num.
95 BT_CHANGE = 4,
96
97 // The 4bit weapon mask and shift, convenience.
98 //BT_WEAPONMASK = (8+16+32),
99 BT_WEAPONMASK = (8+16+32+64), // extended to pick up SSG // phares
100 BT_WEAPONSHIFT = 3,
101
102 // Special events
103 BTS_LOADGAME = 0, // Loads a game
104 // Pause the game.
105 BTS_PAUSE = 1,
106 // Save the game at each console.
107 BTS_SAVEGAME = 2,
108 BTS_RESTARTLEVEL= 3, // Restarts the current level
109
110 // Savegame slot numbers occupy the second byte of buttons.
111 BTS_SAVEMASK = (4+8+16),
112 BTS_SAVESHIFT = 2,
113
114} buttoncode_t;
115
116
117//
118// GLOBAL VARIABLES
119//
120#define MAXEVENTS 64
121
122extern event_t events[MAXEVENTS];
123extern int eventhead;
124extern int eventtail;
125
126extern gameaction_t gameaction;
127
128#endif
diff --git a/apps/plugins/doom/d_french.h b/apps/plugins/doom/d_french.h
new file mode 100644
index 0000000000..6910ad0094
--- /dev/null
+++ b/apps/plugins/doom/d_french.h
@@ -0,0 +1,437 @@
1// Emacs style mode select -*- C++ -*-
2//-----------------------------------------------------------------------------
3//
4// $Id$
5//
6// Copyright (C) 1993-1996 by id Software, Inc.
7//
8// This program is free software; you can redistribute it and/or
9// modify it under the terms of the GNU General Public License
10// as published by the Free Software Foundation; either version 2
11// of the License, or (at your option) any later version.
12//
13// This program is distributed in the hope that it will be useful,
14// but WITHOUT ANY WARRANTY; without even the implied warranty of
15// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16// GNU General Public License for more details.
17//
18// DESCRIPTION:
19// Printed strings, french translation.
20//
21//-----------------------------------------------------------------------------
22
23
24#ifndef __D_FRENCH__
25#define __D_FRENCH__
26
27//
28// D_Main.C
29//
30#define D_DEVSTR "MODE DEVELOPPEMENT ON.\n"
31#define D_CDROM "VERSION CD-ROM: DEFAULT.CFG DANS C:\\DOOMDATA\n"
32
33//
34// M_Menu.C
35//
36#define PRESSKEY "APPUYEZ SUR UNE TOUCHE."
37#define PRESSYN "APPUYEZ SUR Y OU N"
38#define QUITMSG "VOUS VOULEZ VRAIMENT\nQUITTER CE SUPER JEU?"
39#define LOADNET "VOUS NE POUVEZ PAS CHARGER\nUN JEU EN RESEAU!\n\n"PRESSKEY
40#define QLOADNET "CHARGEMENT RAPIDE INTERDIT EN RESEAU!\n\n"PRESSKEY
41#define QSAVESPOT "VOUS N'AVEZ PAS CHOISI UN EMPLACEMENT!\n\n"PRESSKEY
42#define SAVEDEAD "VOUS NE POUVEZ PAS SAUVER SI VOUS NE JOUEZ "\
43"PAS!\n\n"PRESSKEY
44#define QSPROMPT "SAUVEGARDE RAPIDE DANS LE FICHIER \n\n'%s'?\n\n"PRESSYN
45#define QLPROMPT "VOULEZ-VOUS CHARGER LA SAUVEGARDE"\
46"\n\n'%s'?\n\n"PRESSYN
47#define NEWGAME "VOUS NE POUVEZ PAS LANCER\n"\
48"UN NOUVEAU JEU SUR RESEAU.\n\n"PRESSKEY
49#define NIGHTMARE "VOUS CONFIRMEZ? CE NIVEAU EST\n"\
50"VRAIMENT IMPITOYABLE!n"PRESSYN
51#define SWSTRING "CECI EST UNE VERSION SHAREWARE DE DOOM.\n\n"\
52"VOUS DEVRIEZ COMMANDER LA TRILOGIE COMPLETE.\n\n"PRESSKEY
53#define MSGOFF "MESSAGES OFF"
54#define MSGON "MESSAGES ON"
55#define NETEND "VOUS NE POUVEZ PAS METTRE FIN A UN JEU SUR "\
56"RESEAU!\n\n"PRESSKEY
57#define ENDGAME "VOUS VOULEZ VRAIMENT METTRE FIN AU JEU?\n\n"PRESSYN
58
59#define DOSY "(APPUYEZ SUR Y POUR REVENIR AU OS.)"
60
61#define DETAILHI "GRAPHISMES MAXIMUM "
62#define DETAILLO "GRAPHISMES MINIMUM "
63#define GAMMALVL0 "CORRECTION GAMMA OFF"
64#define GAMMALVL1 "CORRECTION GAMMA NIVEAU 1"
65#define GAMMALVL2 "CORRECTION GAMMA NIVEAU 2"
66#define GAMMALVL3 "CORRECTION GAMMA NIVEAU 3"
67#define GAMMALVL4 "CORRECTION GAMMA NIVEAU 4"
68#define EMPTYSTRING "EMPLACEMENT VIDE"
69
70//
71// P_inter.C
72//
73#define GOTARMOR "ARMURE RECUPEREE."
74#define GOTMEGA "MEGA-ARMURE RECUPEREE!"
75#define GOTHTHBONUS "BONUS DE SANTE RECUPERE."
76#define GOTARMBONUS "BONUS D'ARMURE RECUPERE."
77#define GOTSTIM "STIMPACK RECUPERE."
78#define GOTMEDINEED "MEDIKIT RECUPERE. VOUS EN AVEZ VRAIMENT BESOIN!"
79#define GOTMEDIKIT "MEDIKIT RECUPERE."
80#define GOTSUPER "SUPERCHARGE!"
81
82#define GOTBLUECARD "CARTE MAGNETIQUE BLEUE RECUPEREE."
83#define GOTYELWCARD "CARTE MAGNETIQUE JAUNE RECUPEREE."
84#define GOTREDCARD "CARTE MAGNETIQUE ROUGE RECUPEREE."
85#define GOTBLUESKUL "CLEF CRANE BLEUE RECUPEREE."
86#define GOTYELWSKUL "CLEF CRANE JAUNE RECUPEREE."
87#define GOTREDSKULL "CLEF CRANE ROUGE RECUPEREE."
88
89#define GOTINVUL "INVULNERABILITE!"
90#define GOTBERSERK "BERSERK!"
91#define GOTINVIS "INVISIBILITE PARTIELLE "
92#define GOTSUIT "COMBINAISON ANTI-RADIATIONS "
93#define GOTMAP "CARTE INFORMATIQUE "
94#define GOTVISOR "VISEUR A AMPLIFICATION DE LUMIERE "
95#define GOTMSPHERE "MEGASPHERE!"
96
97#define GOTCLIP "CHARGEUR RECUPERE."
98#define GOTCLIPBOX "BOITE DE BALLES RECUPEREE."
99#define GOTROCKET "ROQUETTE RECUPEREE."
100#define GOTROCKBOX "CAISSE DE ROQUETTES RECUPEREE."
101#define GOTCELL "CELLULE D'ENERGIE RECUPEREE."
102#define GOTCELLBOX "PACK DE CELLULES D'ENERGIE RECUPERE."
103#define GOTSHELLS "4 CARTOUCHES RECUPEREES."
104#define GOTSHELLBOX "BOITE DE CARTOUCHES RECUPEREE."
105#define GOTBACKPACK "SAC PLEIN DE MUNITIONS RECUPERE!"
106
107#define GOTBFG9000 "VOUS AVEZ UN BFG9000! OH, OUI!"
108#define GOTCHAINGUN "VOUS AVEZ LA MITRAILLEUSE!"
109#define GOTCHAINSAW "UNE TRONCONNEUSE!"
110#define GOTLAUNCHER "VOUS AVEZ UN LANCE-ROQUETTES!"
111#define GOTPLASMA "VOUS AVEZ UN FUSIL A PLASMA!"
112#define GOTSHOTGUN "VOUS AVEZ UN FUSIL!"
113#define GOTSHOTGUN2 "VOUS AVEZ UN SUPER FUSIL!"
114
115//
116// P_Doors.C
117//
118#define PD_BLUEO "IL VOUS FAUT UNE CLEF BLEUE"
119#define PD_REDO "IL VOUS FAUT UNE CLEF ROUGE"
120#define PD_YELLOWO "IL VOUS FAUT UNE CLEF JAUNE"
121#define PD_BLUEK PD_BLUEO
122#define PD_REDK PD_REDO
123#define PD_YELLOWK PD_YELLOWO
124
125//
126// G_game.C
127//
128#define GGSAVED "JEU SAUVEGARDE."
129
130//
131// HU_stuff.C
132//
133#define HUSTR_MSGU "[MESSAGE NON ENVOYE]"
134
135#define HUSTR_E1M1 "E1M1: HANGAR"
136#define HUSTR_E1M2 "E1M2: USINE NUCLEAIRE "
137#define HUSTR_E1M3 "E1M3: RAFFINERIE DE TOXINES "
138#define HUSTR_E1M4 "E1M4: CENTRE DE CONTROLE "
139#define HUSTR_E1M5 "E1M5: LABORATOIRE PHOBOS "
140#define HUSTR_E1M6 "E1M6: TRAITEMENT CENTRAL "
141#define HUSTR_E1M7 "E1M7: CENTRE INFORMATIQUE "
142#define HUSTR_E1M8 "E1M8: ANOMALIE PHOBOS "
143#define HUSTR_E1M9 "E1M9: BASE MILITAIRE "
144
145#define HUSTR_E2M1 "E2M1: ANOMALIE DEIMOS "
146#define HUSTR_E2M2 "E2M2: ZONE DE CONFINEMENT "
147#define HUSTR_E2M3 "E2M3: RAFFINERIE"
148#define HUSTR_E2M4 "E2M4: LABORATOIRE DEIMOS "
149#define HUSTR_E2M5 "E2M5: CENTRE DE CONTROLE "
150#define HUSTR_E2M6 "E2M6: HALLS DES DAMNES "
151#define HUSTR_E2M7 "E2M7: CUVES DE REPRODUCTION "
152#define HUSTR_E2M8 "E2M8: TOUR DE BABEL "
153#define HUSTR_E2M9 "E2M9: FORTERESSE DU MYSTERE "
154
155#define HUSTR_E3M1 "E3M1: DONJON DE L'ENFER "
156#define HUSTR_E3M2 "E3M2: BOURBIER DU DESESPOIR "
157#define HUSTR_E3M3 "E3M3: PANDEMONIUM"
158#define HUSTR_E3M4 "E3M4: MAISON DE LA DOULEUR "
159#define HUSTR_E3M5 "E3M5: CATHEDRALE PROFANE "
160#define HUSTR_E3M6 "E3M6: MONT EREBUS"
161#define HUSTR_E3M7 "E3M7: LIMBES"
162#define HUSTR_E3M8 "E3M8: DIS"
163#define HUSTR_E3M9 "E3M9: CLAPIERS"
164
165#define HUSTR_1 "NIVEAU 1: ENTREE "
166#define HUSTR_2 "NIVEAU 2: HALLS SOUTERRAINS "
167#define HUSTR_3 "NIVEAU 3: LE FEU NOURRI "
168#define HUSTR_4 "NIVEAU 4: LE FOYER "
169#define HUSTR_5 "NIVEAU 5: LES EGOUTS "
170#define HUSTR_6 "NIVEAU 6: LE BROYEUR "
171#define HUSTR_7 "NIVEAU 7: L'HERBE DE LA MORT"
172#define HUSTR_8 "NIVEAU 8: RUSES ET PIEGES "
173#define HUSTR_9 "NIVEAU 9: LE PUITS "
174#define HUSTR_10 "NIVEAU 10: BASE DE RAVITAILLEMENT "
175#define HUSTR_11 "NIVEAU 11: LE CERCLE DE LA MORT!"
176
177#define HUSTR_12 "NIVEAU 12: L'USINE "
178#define HUSTR_13 "NIVEAU 13: LE CENTRE VILLE"
179#define HUSTR_14 "NIVEAU 14: LES ANTRES PROFONDES "
180#define HUSTR_15 "NIVEAU 15: LA ZONE INDUSTRIELLE "
181#define HUSTR_16 "NIVEAU 16: LA BANLIEUE"
182#define HUSTR_17 "NIVEAU 17: LES IMMEUBLES"
183#define HUSTR_18 "NIVEAU 18: LA COUR "
184#define HUSTR_19 "NIVEAU 19: LA CITADELLE "
185#define HUSTR_20 "NIVEAU 20: JE T'AI EU!"
186
187#define HUSTR_21 "NIVEAU 21: LE NIRVANA"
188#define HUSTR_22 "NIVEAU 22: LES CATACOMBES "
189#define HUSTR_23 "NIVEAU 23: LA GRANDE FETE "
190#define HUSTR_24 "NIVEAU 24: LE GOUFFRE "
191#define HUSTR_25 "NIVEAU 25: LES CHUTES DE SANG"
192#define HUSTR_26 "NIVEAU 26: LES MINES ABANDONNEES "
193#define HUSTR_27 "NIVEAU 27: CHEZ LES MONSTRES "
194#define HUSTR_28 "NIVEAU 28: LE MONDE DE L'ESPRIT "
195#define HUSTR_29 "NIVEAU 29: LA LIMITE "
196#define HUSTR_30 "NIVEAU 30: L'ICONE DU PECHE "
197
198#define HUSTR_31 "NIVEAU 31: WOLFENSTEIN"
199#define HUSTR_32 "NIVEAU 32: LE MASSACRE"
200
201
202#define HUSTR_CHATMACRO1 "JE SUIS PRET A LEUR EN FAIRE BAVER!"
203#define HUSTR_CHATMACRO2 "JE VAIS BIEN."
204#define HUSTR_CHATMACRO3 "JE N'AI PAS L'AIR EN FORME!"
205#define HUSTR_CHATMACRO4 "AU SECOURS!"
206#define HUSTR_CHATMACRO5 "TU CRAINS!"
207#define HUSTR_CHATMACRO6 "LA PROCHAINE FOIS, MINABLE..."
208#define HUSTR_CHATMACRO7 "VIENS ICI!"
209#define HUSTR_CHATMACRO8 "JE VAIS M'EN OCCUPER."
210#define HUSTR_CHATMACRO9 "OUI"
211#define HUSTR_CHATMACRO0 "NON"
212
213#define HUSTR_TALKTOSELF1 "VOUS PARLEZ TOUT SEUL "
214#define HUSTR_TALKTOSELF2 "QUI EST LA?"
215#define HUSTR_TALKTOSELF3 "VOUS VOUS FAITES PEUR "
216#define HUSTR_TALKTOSELF4 "VOUS COMMENCEZ A DELIRER "
217#define HUSTR_TALKTOSELF5 "VOUS ETES LARGUE..."
218
219#define HUSTR_MESSAGESENT "[MESSAGE ENVOYE]"
220
221// The following should NOT be changed unless it seems
222// just AWFULLY necessary
223
224#define HUSTR_PLRGREEN "VERT: "
225#define HUSTR_PLRINDIGO "INDIGO: "
226#define HUSTR_PLRBROWN "BRUN: "
227#define HUSTR_PLRRED "ROUGE: "
228
229#define HUSTR_KEYGREEN 'g' // french key should be "V"
230#define HUSTR_KEYINDIGO 'i'
231#define HUSTR_KEYBROWN 'b'
232#define HUSTR_KEYRED 'r'
233
234//
235// AM_map.C
236//
237
238#define AMSTR_FOLLOWON "MODE POURSUITE ON"
239#define AMSTR_FOLLOWOFF "MODE POURSUITE OFF"
240
241#define AMSTR_GRIDON "GRILLE ON"
242#define AMSTR_GRIDOFF "GRILLE OFF"
243
244#define AMSTR_MARKEDSPOT "REPERE MARQUE "
245#define AMSTR_MARKSCLEARED "REPERES EFFACES "
246
247//
248// ST_stuff.C
249//
250
251#define STSTR_MUS "CHANGEMENT DE MUSIQUE "
252#define STSTR_NOMUS "IMPOSSIBLE SELECTION"
253#define STSTR_DQDON "INVULNERABILITE ON "
254#define STSTR_DQDOFF "INVULNERABILITE OFF"
255
256#define STSTR_KFAADDED "ARMEMENT MAXIMUM! "
257#define STSTR_FAADDED "ARMES (SAUF CLEFS) AJOUTEES"
258
259#define STSTR_NCON "BARRIERES ON"
260#define STSTR_NCOFF "BARRIERES OFF"
261
262#define STSTR_BEHOLD " inVuln, Str, Inviso, Rad, Allmap, or Lite-amp"
263#define STSTR_BEHOLDX "AMELIORATION ACTIVEE"
264
265#define STSTR_CHOPPERS "... DOESN'T SUCK - GM"
266#define STSTR_CLEV "CHANGEMENT DE NIVEAU..."
267
268//
269// F_Finale.C
270//
271#define E1TEXT "APRES AVOIR VAINCU LES GROS MECHANTS\n"\
272"ET NETTOYE LA BASE LUNAIRE, VOUS AVEZ\n"\
273"GAGNE, NON? PAS VRAI? OU EST DONC VOTRE\n"\
274" RECOMPENSE ET VOTRE BILLET DE\n"\
275"RETOUR? QU'EST-QUE CA VEUT DIRE?CE"\
276"N'EST PAS LA FIN ESPEREE!\n"\
277"\n" \
278"CA SENT LA VIANDE PUTREFIEE, MAIS\n"\
279"ON DIRAIT LA BASE DEIMOS. VOUS ETES\n"\
280"APPAREMMENT BLOQUE AUX PORTES DE L'ENFER.\n"\
281"LA SEULE ISSUE EST DE L'AUTRE COTE.\n"\
282"\n"\
283"POUR VIVRE LA SUITE DE DOOM, JOUEZ\n"\
284"A 'AUX PORTES DE L'ENFER' ET A\n"\
285"L'EPISODE SUIVANT, 'L'ENFER'!\n"
286
287#define E2TEXT "VOUS AVEZ REUSSI. L'INFAME DEMON\n"\
288"QUI CONTROLAIT LA BASE LUNAIRE DE\n"\
289"DEIMOS EST MORT, ET VOUS AVEZ\n"\
290"TRIOMPHE! MAIS... OU ETES-VOUS?\n"\
291"VOUS GRIMPEZ JUSQU'AU BORD DE LA\n"\
292"LUNE ET VOUS DECOUVREZ L'ATROCE\n"\
293"VERITE.\n" \
294"\n"\
295"DEIMOS EST AU-DESSUS DE L'ENFER!\n"\
296"VOUS SAVEZ QUE PERSONNE NE S'EN\n"\
297"EST JAMAIS ECHAPPE, MAIS CES FUMIERS\n"\
298"VONT REGRETTER DE VOUS AVOIR CONNU!\n"\
299"VOUS REDESCENDEZ RAPIDEMENT VERS\n"\
300"LA SURFACE DE L'ENFER.\n"\
301"\n" \
302"VOICI MAINTENANT LE CHAPITRE FINAL DE\n"\
303"DOOM! -- L'ENFER."
304
305#define E3TEXT "LE DEMON ARACHNEEN ET REPUGNANT\n"\
306"QUI A DIRIGE L'INVASION DES BASES\n"\
307"LUNAIRES ET SEME LA MORT VIENT DE SE\n"\
308"FAIRE PULVERISER UNE FOIS POUR TOUTES.\n"\
309"\n"\
310"UNE PORTE SECRETE S'OUVRE. VOUS ENTREZ.\n"\
311"VOUS AVEZ PROUVE QUE VOUS POUVIEZ\n"\
312"RESISTER AUX HORREURS DE L'ENFER.\n"\
313"IL SAIT ETRE BEAU JOUEUR, ET LORSQUE\n"\
314"VOUS SORTEZ, VOUS REVOYEZ LES VERTES\n"\
315"PRAIRIES DE LA TERRE, VOTRE PLANETE.\n"\
316"\n"\
317"VOUS VOUS DEMANDEZ CE QUI S'EST PASSE\n"\
318"SUR TERRE PENDANT QUE VOUS AVEZ\n"\
319"COMBATTU LE DEMON. HEUREUSEMENT,\n"\
320"AUCUN GERME DU MAL N'A FRANCHI\n"\
321"CETTE PORTE AVEC VOUS..."
322
323
324
325// after level 6, put this:
326
327#define C1TEXT "VOUS ETES AU PLUS PROFOND DE L'ASTROPORT\n" \
328"INFESTE DE MONSTRES, MAIS QUELQUE CHOSE\n" \
329"NE VA PAS. ILS ONT APPORTE LEUR PROPRE\n" \
330"REALITE, ET LA TECHNOLOGIE DE L'ASTROPORT\n" \
331"EST AFFECTEE PAR LEUR PRESENCE.\n" \
332"\n"\
333"DEVANT VOUS, VOUS VOYEZ UN POSTE AVANCE\n" \
334"DE L'ENFER, UNE ZONE FORTIFIEE. SI VOUS\n" \
335"POUVEZ PASSER, VOUS POURREZ PENETRER AU\n" \
336"COEUR DE LA BASE HANTEE ET TROUVER \n" \
337"L'INTERRUPTEUR DE CONTROLE QUI GARDE LA \n" \
338"POPULATION DE LA TERRE EN OTAGE."
339
340// After level 11, put this:
341
342#define C2TEXT "VOUS AVEZ GAGNE! VOTRE VICTOIRE A PERMIS\n" \
343"A L'HUMANITE D'EVACUER LA TERRE ET \n"\
344"D'ECHAPPER AU CAUCHEMAR. VOUS ETES \n"\
345"MAINTENANT LE DERNIER HUMAIN A LA SURFACE \n"\
346"DE LA PLANETE. VOUS ETES ENTOURE DE \n"\
347"MUTANTS CANNIBALES, D'EXTRATERRESTRES \n"\
348"CARNIVORES ET D'ESPRITS DU MAL. VOUS \n"\
349"ATTENDEZ CALMEMENT LA MORT, HEUREUX \n"\
350"D'AVOIR PU SAUVER VOTRE RACE.\n"\
351"MAIS UN MESSAGE VOUS PARVIENT SOUDAIN\n"\
352"DE L'ESPACE: \"NOS CAPTEURS ONT LOCALISE\n"\
353"LA SOURCE DE L'INVASION EXTRATERRESTRE.\n"\
354"SI VOUS Y ALLEZ, VOUS POURREZ PEUT-ETRE\n"\
355"LES ARRETER. LEUR BASE EST SITUEE AU COEUR\n"\
356"DE VOTRE VILLE NATALE, PRES DE L'ASTROPORT.\n"\
357"VOUS VOUS RELEVEZ LENTEMENT ET PENIBLEMENT\n"\
358"ET VOUS REPARTEZ POUR LE FRONT."
359
360// After level 20, put this:
361
362#define C3TEXT "VOUS ETES AU COEUR DE LA CITE CORROMPUE,\n"\
363"ENTOURE PAR LES CADAVRES DE VOS ENNEMIS.\n"\
364"VOUS NE VOYEZ PAS COMMENT DETRUIRE LA PORTE\n"\
365"DES CREATURES DE CE COTE. VOUS SERREZ\n"\
366"LES DENTS ET PLONGEZ DANS L'OUVERTURE.\n"\
367"\n"\
368"IL DOIT Y AVOIR UN MOYEN DE LA FERMER\n"\
369"DE L'AUTRE COTE. VOUS ACCEPTEZ DE\n"\
370"TRAVERSER L'ENFER POUR LE FAIRE?"
371
372// After level 29, put this:
373
374#define C4TEXT "LE VISAGE HORRIBLE D'UN DEMON D'UNE\n"\
375"TAILLE INCROYABLE S'EFFONDRE DEVANT\n"\
376"VOUS LORSQUE VOUS TIREZ UNE SALVE DE\n"\
377"ROQUETTES DANS SON CERVEAU. LE MONSTRE\n"\
378"SE RATATINE, SES MEMBRES DECHIQUETES\n"\
379"SE REPANDANT SUR DES CENTAINES DE\n"\
380"KILOMETRES A LA SURFACE DE L'ENFER.\n"\
381"\n"\
382"VOUS AVEZ REUSSI. L'INVASION N'AURA.\n"\
383"PAS LIEU. LA TERRE EST SAUVEE. L'ENFER\n"\
384"EST ANEANTI. EN VOUS DEMANDANT OU IRONT\n"\
385"MAINTENANT LES DAMNES, VOUS ESSUYEZ\n"\
386"VOTRE FRONT COUVERT DE SUEUR ET REPARTEZ\n"\
387"VERS LA TERRE. SA RECONSTRUCTION SERA\n"\
388"BEAUCOUP PLUS DROLE QUE SA DESTRUCTION.\n"
389
390// Before level 31, put this:
391
392#define C5TEXT "FELICITATIONS! VOUS AVEZ TROUVE LE\n"\
393"NIVEAU SECRET! IL SEMBLE AVOIR ETE\n"\
394"CONSTRUIT PAR LES HUMAINS. VOUS VOUS\n"\
395"DEMANDEZ QUELS PEUVENT ETRE LES\n"\
396"HABITANTS DE CE COIN PERDU DE L'ENFER."
397
398// Before level 32, put this:
399
400#define C6TEXT "FELICITATIONS! VOUS AVEZ DECOUVERT\n"\
401"LE NIVEAU SUPER SECRET! VOUS FERIEZ\n"\
402"MIEUX DE FONCER DANS CELUI-LA!\n"
403
404//
405// Character cast strings F_FINALE.C
406//
407#define CC_ZOMBIE "ZOMBIE"
408#define CC_SHOTGUN "TYPE AU FUSIL"
409#define CC_HEAVY "MEC SUPER-ARME"
410#define CC_IMP "DIABLOTIN"
411#define CC_DEMON "DEMON"
412#define CC_LOST "AME PERDUE"
413#define CC_CACO "CACODEMON"
414#define CC_HELL "CHEVALIER DE L'ENFER"
415#define CC_BARON "BARON DE L'ENFER"
416#define CC_ARACH "ARACHNOTRON"
417#define CC_PAIN "ELEMENTAIRE DE LA DOULEUR"
418#define CC_REVEN "REVENANT"
419#define CC_MANCU "MANCUBUS"
420#define CC_ARCH "ARCHI-INFAME"
421#define CC_SPIDER "L'ARAIGNEE CERVEAU"
422#define CC_CYBER "LE CYBERDEMON"
423#define CC_HERO "NOTRE HEROS"
424
425
426
427#endif
428//-----------------------------------------------------------------------------
429//
430// $Log$
431// Revision 1.1 2006/03/28 15:44:01 dave
432// Patch #2969 - Doom! Currently only working on the H300.
433//
434//
435//-----------------------------------------------------------------------------
436
437
diff --git a/apps/plugins/doom/d_items.c b/apps/plugins/doom/d_items.c
new file mode 100644
index 0000000000..de4cfaa8e2
--- /dev/null
+++ b/apps/plugins/doom/d_items.c
@@ -0,0 +1,138 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION:
28 * Something to do with weapon sprite frames. Don't ask me.
29 *
30 *-----------------------------------------------------------------------------
31 */
32
33// We are referring to sprite numbers.
34#include "doomtype.h"
35#include "info.h"
36
37#ifdef __GNUG__
38#pragma implementation "d_items.h"
39#endif
40#include "d_items.h"
41
42
43//
44// PSPRITE ACTIONS for waepons.
45// This struct controls the weapon animations.
46//
47// Each entry is:
48// ammo/amunition type
49// upstate
50// downstate
51// readystate
52// atkstate, i.e. attack/fire/hit frame
53// flashstate, muzzle flash
54//
55weaponinfo_t weaponinfo[NUMWEAPONS] =
56 {
57 {
58 // fist
59 am_noammo,
60 S_PUNCHUP,
61 S_PUNCHDOWN,
62 S_PUNCH,
63 S_PUNCH1,
64 S_NULL
65 },
66 {
67 // pistol
68 am_clip,
69 S_PISTOLUP,
70 S_PISTOLDOWN,
71 S_PISTOL,
72 S_PISTOL1,
73 S_PISTOLFLASH
74 },
75 {
76 // shotgun
77 am_shell,
78 S_SGUNUP,
79 S_SGUNDOWN,
80 S_SGUN,
81 S_SGUN1,
82 S_SGUNFLASH1
83 },
84 {
85 // chaingun
86 am_clip,
87 S_CHAINUP,
88 S_CHAINDOWN,
89 S_CHAIN,
90 S_CHAIN1,
91 S_CHAINFLASH1
92 },
93 {
94 // missile launcher
95 am_misl,
96 S_MISSILEUP,
97 S_MISSILEDOWN,
98 S_MISSILE,
99 S_MISSILE1,
100 S_MISSILEFLASH1
101 },
102 {
103 // plasma rifle
104 am_cell,
105 S_PLASMAUP,
106 S_PLASMADOWN,
107 S_PLASMA,
108 S_PLASMA1,
109 S_PLASMAFLASH1
110 },
111 {
112 // bfg 9000
113 am_cell,
114 S_BFGUP,
115 S_BFGDOWN,
116 S_BFG,
117 S_BFG1,
118 S_BFGFLASH1
119 },
120 {
121 // chainsaw
122 am_noammo,
123 S_SAWUP,
124 S_SAWDOWN,
125 S_SAW,
126 S_SAW1,
127 S_NULL
128 },
129 {
130 // super shotgun
131 am_shell,
132 S_DSGUNUP,
133 S_DSGUNDOWN,
134 S_DSGUN,
135 S_DSGUN1,
136 S_DSGUNFLASH1
137 },
138 };
diff --git a/apps/plugins/doom/d_items.h b/apps/plugins/doom/d_items.h
new file mode 100644
index 0000000000..313fdb8649
--- /dev/null
+++ b/apps/plugins/doom/d_items.h
@@ -0,0 +1,57 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION:
28 * Items: key cards, artifacts, weapon, ammunition.
29 *
30 *-----------------------------------------------------------------------------*/
31
32
33#ifndef __D_ITEMS__
34#define __D_ITEMS__
35
36#include "doomdef.h"
37
38#ifdef __GNUG__
39#pragma interface
40#endif
41
42
43/* Weapon info: sprite frames, ammunition use. */
44typedef struct
45{
46 ammotype_t ammo;
47 int upstate;
48 int downstate;
49 int readystate;
50 int atkstate;
51 int flashstate;
52
53} weaponinfo_t;
54
55extern weaponinfo_t weaponinfo[NUMWEAPONS];
56
57#endif
diff --git a/apps/plugins/doom/d_main.c b/apps/plugins/doom/d_main.c
new file mode 100644
index 0000000000..d76779cb2b
--- /dev/null
+++ b/apps/plugins/doom/d_main.c
@@ -0,0 +1,844 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION:
28 * DOOM main program (D_DoomMain) and game loop (D_DoomLoop),
29 * plus functions to determine game mode (shareware, registered),
30 * parse command line parameters, configure game parameters (turbo),
31 * and call the startup functions.
32 *
33 *-----------------------------------------------------------------------------
34 */
35
36
37#include "rockmacros.h"
38
39#include "doomdef.h"
40#include "doomtype.h"
41#include "doomstat.h"
42#include "dstrings.h"
43#include "sounds.h"
44#include "z_zone.h"
45#include "w_wad.h"
46#include "s_sound.h"
47#include "v_video.h"
48#include "f_finale.h"
49#include "f_wipe.h"
50#include "m_argv.h"
51#include "m_misc.h"
52#include "m_menu.h"
53#include "i_system.h"
54#include "i_sound.h"
55#include "i_video.h"
56#include "g_game.h"
57#include "hu_stuff.h"
58#include "wi_stuff.h"
59#include "st_stuff.h"
60#include "am_map.h"
61#include "p_setup.h"
62#include "r_draw.h"
63#include "r_main.h"
64#include "d_main.h"
65#include "am_map.h"
66#include "m_swap.h"
67
68// CPhipps - removed wadfiles[] stuff
69
70boolean devparm; // started game with -devparm
71
72// jff 1/24/98 add new versions of these variables to remember command line
73boolean clnomonsters; // checkparm of -nomonsters
74boolean clrespawnparm; // checkparm of -respawn
75boolean clfastparm; // checkparm of -fast
76// jff 1/24/98 end definition of command line version of play mode switches
77
78boolean nomonsters; // working -nomonsters
79boolean respawnparm; // working -respawn
80boolean fastparm; // working -fast
81
82boolean singletics = false; // debug flag to cancel adaptiveness
83
84boolean doomexit;
85
86//jff 1/22/98 parms for disabling music and sound
87boolean nosfxparm;
88boolean nomusicparm;
89
90//jff 4/18/98
91extern boolean inhelpscreens;
92
93skill_t startskill;
94int startepisode;
95int startmap;
96boolean autostart;
97int debugfile;
98int ffmap;
99
100boolean advancedemo;
101
102extern boolean timingdemo, singledemo, demoplayback, fastdemo; // killough
103
104int basetic;
105
106void D_DoAdvanceDemo (void);
107
108/*
109 * D_PostEvent - Event handling
110 *
111 * Called by I/O functions when an event is received.
112 * Try event handlers for each code area in turn.
113 * cph - in the true spirit of the Boom source, let the
114 * short ciruit operator madness begin!
115 */
116
117void D_PostEvent(event_t *ev)
118{
119 /* cph - suppress all input events at game start
120 * FIXME: This is a lousy kludge */
121 if (gametic < 3) return;
122 M_Responder(ev) ||
123 (gamestate == GS_LEVEL && (
124 HU_Responder(ev) ||
125 ST_Responder(ev) ||
126 AM_Responder(ev)
127 )
128 ) ||
129 G_Responder(ev);
130}
131
132//
133// D_Wipe
134//
135// CPhipps - moved the screen wipe code from D_Display to here
136// The screens to wipe between are already stored, this just does the timing
137// and screen updating
138
139static void D_Wipe(void)
140{
141 boolean done;
142 int wipestart = I_GetTime () - 1;
143
144 do
145 {
146 int nowtime, tics;
147 do
148 {
149 //I_uSleep(5000); // CPhipps - don't thrash cpu in this loop
150 nowtime = I_GetTime();
151 tics = nowtime - wipestart;
152 }
153 while (!tics);
154 wipestart = nowtime;
155
156 done = wipe_ScreenWipe(0,0,SCREENWIDTH,SCREENHEIGHT,tics);
157 I_UpdateNoBlit();
158 M_Drawer(); // menu is drawn even on top of wipes
159 I_FinishUpdate(); // page flip or blit buffer
160 }
161 while (!done);
162}
163
164//
165// D_Display
166// draw current display, possibly wiping it from the previous
167//
168
169// wipegamestate can be set to -1 to force a wipe on the next draw
170gamestate_t wipegamestate = GS_DEMOSCREEN;
171extern boolean setsizeneeded;
172extern int showMessages;
173
174void D_Display (void)
175{
176 static boolean isborderstate = false;
177 static boolean borderwillneedredraw = false;
178 static boolean inhelpscreensstate = false;
179 static gamestate_t oldgamestate = -1;
180 boolean wipe;
181 boolean viewactive = false, isborder = false;
182
183 if (nodrawers) // for comparative timing / profiling
184 return;
185
186 // save the current screen if about to wipe
187 if ((wipe = gamestate != wipegamestate))
188 wipe_StartScreen(0, 0, SCREENWIDTH, SCREENHEIGHT);
189
190 if (gamestate != GS_LEVEL) { // Not a level
191 switch (oldgamestate) {
192 case -1:
193 case GS_LEVEL:
194 V_SetPalette(0); // cph - use default (basic) palette
195 default:
196 break;
197 }
198
199 switch (gamestate) {
200 case GS_INTERMISSION:
201 WI_Drawer();
202 break;
203 case GS_FINALE:
204 F_Drawer();
205 break;
206 case GS_DEMOSCREEN:
207 D_PageDrawer();
208 break;
209 default:
210 break;
211 }
212 } else if (gametic != basetic) { // In a level
213 boolean redrawborderstuff;
214
215 HU_Erase();
216
217 if (setsizeneeded) { // change the view size if needed
218 R_ExecuteSetViewSize();
219 oldgamestate = -1; // force background redraw
220 }
221
222 // Work out if the player view is visible, and if there is a border
223 viewactive = (!(automapmode & am_active) || (automapmode & am_overlay)) && !inhelpscreens;
224 isborder = viewactive ? (viewheight != SCREENHEIGHT) : (!inhelpscreens && (automapmode & am_active));
225
226 if (oldgamestate != GS_LEVEL) {
227 R_FillBackScreen (); // draw the pattern into the back screen
228 redrawborderstuff = isborder;
229 } else {
230 // CPhipps -
231 // If there is a border, and either there was no border last time,
232 // or the border might need refreshing, then redraw it.
233 redrawborderstuff = isborder && (!isborderstate || borderwillneedredraw);
234 // The border may need redrawing next time if the border surrounds the screen,
235 // and there is a menu being displayed
236 borderwillneedredraw = menuactive && isborder && viewactive && (viewwidth != SCREENWIDTH);
237 }
238
239 if (redrawborderstuff)
240 R_DrawViewBorder();
241
242 // Now do the drawing
243 if (viewactive)
244 R_RenderPlayerView (&players[displayplayer]);
245 if (automapmode & am_active)
246 AM_Drawer();
247 ST_Drawer((viewheight != SCREENHEIGHT) || ((automapmode & am_active) && !(automapmode & am_overlay)), redrawborderstuff);
248 R_DrawViewBorder();
249
250 HU_Drawer();
251 }
252
253 inhelpscreensstate = inhelpscreens;
254 isborderstate = isborder;
255 oldgamestate = wipegamestate = gamestate;
256
257 // draw pause pic
258 if (paused) {
259 static int x;
260
261 if (!x) { // Cache results of x pos calc
262 int lump = W_GetNumForName("M_PAUSE");
263 const patch_t* p = W_CacheLumpNum(lump);
264 x = (320 - SHORT(p->width))/2;
265 W_UnlockLumpNum(lump);
266 }
267
268 // CPhipps - updated for new patch drawing
269 V_DrawNamePatch(x, (!(automapmode & am_active) || (automapmode & am_overlay))
270 ? 4+(viewwindowy*200/SCREENHEIGHT) : 4, // cph - Must un-stretch viewwindowy
271 0, "M_PAUSE", CR_DEFAULT, VPT_STRETCH);
272 }
273
274 // menus go directly to the screen
275 M_Drawer(); // menu is drawn even on top of everything
276 D_BuildNewTiccmds();
277
278 // normal update
279 if (!wipe)
280 I_FinishUpdate (); // page flip or blit buffer
281 else {
282 // wipe update
283 wipe_EndScreen(0, 0, SCREENWIDTH, SCREENHEIGHT);
284 D_Wipe();
285 }
286}
287
288//
289// D_DoomLoop()
290//
291// Not a globally visible function,
292// just included for source reference,
293// called by D_DoomMain, never exits.
294// Manages timing and IO,
295// calls all ?_Responder, ?_Ticker, and ?_Drawer,
296// calls I_GetTime, I_StartFrame, and I_StartTic
297//
298
299extern boolean demorecording;
300
301static void D_DoomLoop (void)
302{
303 basetic = gametic;
304
305 I_SubmitSound();
306
307 while (!doomexit)
308 {
309 // frame syncronous IO operations
310 //I_StartFrame ();
311
312 // process one or more tics
313 if (singletics)
314 {
315 I_StartTic ();
316 G_BuildTiccmd (&netcmds[consoleplayer][maketic%BACKUPTICS]);
317 if (advancedemo)
318 D_DoAdvanceDemo ();
319 M_Ticker ();
320 G_Ticker ();
321 gametic++;
322 maketic++;
323 }
324 else
325 TryRunTics (); // will run at least one tic
326
327 // killough 3/16/98: change consoleplayer to displayplayer
328 if (players[displayplayer].mo) // cph 2002/08/10
329 S_UpdateSounds(players[displayplayer].mo);// move positional sounds
330
331 // Update display, next frame, with current state.
332 D_Display();
333
334 // Sound mixing for the buffer is snychronous.
335// I_UpdateSound();
336 rb->yield();
337 }
338}
339
340//
341// DEMO LOOP
342//
343
344static int demosequence; // killough 5/2/98: made static
345static int pagetic;
346static const char *pagename; // CPhipps - const
347
348//
349// D_PageTicker
350// Handles timing for warped projection
351//
352void D_PageTicker(void)
353{
354 if (--pagetic < 0)
355 D_AdvanceDemo();
356}
357
358//
359// D_PageDrawer
360//
361void D_PageDrawer(void)
362{
363 // CPhipps - updated for new patch drawing
364 V_DrawNamePatch(0, 0, 0, pagename, CR_DEFAULT, VPT_STRETCH);
365}
366
367//
368// D_AdvanceDemo
369// Called after each demo or intro demosequence finishes
370//
371void D_AdvanceDemo (void)
372{
373 advancedemo = true;
374}
375
376/* killough 11/98: functions to perform demo sequences
377 * cphipps 10/99: constness fixes
378 */
379
380static void D_SetPageName(const char *name)
381{
382 pagename = name;
383}
384
385static void D_DrawTitle1(const char *name)
386{
387 S_StartMusic(mus_intro);
388 pagetic = (TICRATE*170)/35;
389 D_SetPageName(name);
390}
391
392static void D_DrawTitle2(const char *name)
393{
394 S_StartMusic(mus_dm2ttl);
395 D_SetPageName(name);
396}
397
398/* killough 11/98: tabulate demo sequences
399 */
400
401static struct
402{
403 void (*func)(const char *);
404 const char *name;
405} const demostates[][4] =
406 {
407 {
408 {D_DrawTitle1, "TITLEPIC"},
409 {D_DrawTitle1, "TITLEPIC"},
410 {D_DrawTitle2, "TITLEPIC"},
411 {D_DrawTitle1, "TITLEPIC"},
412 },
413
414 {
415 {G_DeferedPlayDemo, "demo1"},
416 {G_DeferedPlayDemo, "demo1"},
417 {G_DeferedPlayDemo, "demo1"},
418 {G_DeferedPlayDemo, "demo1"},
419 },
420 {
421 {D_SetPageName, "CREDIT"},
422 {D_SetPageName, "CREDIT"},
423 {D_SetPageName, "CREDIT"},
424 {D_SetPageName, "CREDIT"},
425 },
426
427 {
428 {G_DeferedPlayDemo, "demo2"},
429 {G_DeferedPlayDemo, "demo2"},
430 {G_DeferedPlayDemo, "demo2"},
431 {G_DeferedPlayDemo, "demo2"},
432 },
433
434 {
435 {D_SetPageName, "HELP2"},
436 {D_SetPageName, "HELP2"},
437 {D_SetPageName, "CREDIT"},
438 {D_DrawTitle1, "TITLEPIC"},
439 },
440
441 {
442 {G_DeferedPlayDemo, "demo3"},
443 {G_DeferedPlayDemo, "demo3"},
444 {G_DeferedPlayDemo, "demo3"},
445 {G_DeferedPlayDemo, "demo3"},
446 },
447
448 {
449 {NULL,0},
450 {NULL,0},
451 {NULL,0},
452 {D_SetPageName, "CREDIT"},
453 },
454
455 {
456 {NULL,0},
457 {NULL,0},
458 {NULL,0},
459 {G_DeferedPlayDemo, "demo4"},
460 },
461
462 {
463 {NULL,0},
464 {NULL,0},
465 {NULL,0},
466 {NULL,0},
467 }
468 };
469
470/*
471 * This cycles through the demo sequences.
472 * killough 11/98: made table-driven
473 */
474
475void D_DoAdvanceDemo(void)
476{
477 players[consoleplayer].playerstate = PST_LIVE; /* not reborn */
478 advancedemo = usergame = paused = false;
479 gameaction = ga_nothing;
480
481 pagetic = TICRATE * 11; /* killough 11/98: default behavior */
482 gamestate = GS_DEMOSCREEN;
483
484 if (netgame && !demoplayback) {
485 demosequence = 0;
486 } else
487 if (!demostates[++demosequence][gamemode].func)
488 demosequence = 0;
489 demostates[demosequence][gamemode].func(demostates[demosequence][gamemode].name);
490}
491
492//
493// D_StartTitle
494//
495void D_StartTitle (void)
496{
497 gameaction = ga_nothing;
498 demosequence = -1;
499 D_AdvanceDemo();
500}
501
502//
503// D_AddFile
504//
505// Rewritten by Lee Killough
506//
507// Ty 08/29/98 - add source parm to indicate where this came from
508// CPhipps - static, const char* parameter
509// - source is an enum
510// - modified to allocate & use new wadfiles array
511void D_AddFile (const char *file, wad_source_t source)
512{
513 wadfiles = realloc(wadfiles, sizeof(*wadfiles)*(numwadfiles+1));
514 wadfiles[numwadfiles].name =
515 AddDefaultExtension(strcpy(malloc(strlen(file)+5), file), ".wad");
516 wadfiles[numwadfiles].src = source; // Ty 08/29/98
517 numwadfiles++;
518}
519
520//
521// CheckIWAD
522//
523// Verify a file is indeed tagged as an IWAD
524// Scan its lumps for levelnames and return gamemode as indicated
525// Detect missing wolf levels in DOOM II
526//
527// The filename to check is passed in iwadname, the gamemode detected is
528// returned in gmode, hassec returns the presence of secret levels
529//
530// jff 4/19/98 Add routine to test IWAD for validity and determine
531// the gamemode from it. Also note if DOOM II, whether secret levels exist
532// CPhipps - const char* for iwadname, made static
533#if 0
534static void CheckIWAD(const char *iwadname,GameMode_t *gmode,boolean *hassec)
535{
536 if ( !fileexists (iwadname) )
537 {
538 int ud=0,rg=0,sw=0,cm=0,sc=0;
539 int handle;
540
541 // Identify IWAD correctly
542 if ( (handle = open (iwadname,O_RDONLY)) != -1)
543 {
544 wadinfo_t header;
545
546 // read IWAD header
547 read (handle, &header, sizeof(header));
548 if (!strncmp(header.identification,"IWAD",4))
549 {
550 size_t length;
551 filelump_t *fileinfo;
552
553 // read IWAD directory
554 header.numlumps = LONG(header.numlumps);
555 header.infotableofs = LONG(header.infotableofs);
556 length = header.numlumps;
557 fileinfo = malloc(length*sizeof(filelump_t));
558 lseek (handle, header.infotableofs, SEEK_SET);
559 read (handle, fileinfo, length*sizeof(filelump_t));
560 close(handle);
561
562 // scan directory for levelname lumps
563 while (length--)
564 if (fileinfo[length].name[0] == 'E' &&
565 fileinfo[length].name[2] == 'M' &&
566 fileinfo[length].name[4] == 0)
567 {
568 if (fileinfo[length].name[1] == '4')
569 ++ud;
570 else if (fileinfo[length].name[1] == '3')
571 ++rg;
572 else if (fileinfo[length].name[1] == '2')
573 ++rg;
574 else if (fileinfo[length].name[1] == '1')
575 ++sw;
576 }
577 else if (fileinfo[length].name[0] == 'M' &&
578 fileinfo[length].name[1] == 'A' &&
579 fileinfo[length].name[2] == 'P' &&
580 fileinfo[length].name[5] == 0)
581 {
582 ++cm;
583 if (fileinfo[length].name[3] == '3')
584 if (fileinfo[length].name[4] == '1' ||
585 fileinfo[length].name[4] == '2')
586 ++sc;
587 }
588
589 free(fileinfo);
590 }
591 else // missing IWAD tag in header
592 I_Error("CheckIWAD: IWAD tag %s not present", iwadname);
593 }
594 else // error from open call
595 I_Error("CheckIWAD: Can't open IWAD %s", iwadname);
596
597 // Determine game mode from levels present
598 // Must be a full set for whichever mode is present
599 // Lack of wolf-3d levels also detected here
600
601 *gmode = indetermined;
602 *hassec = false;
603 if (cm>=30)
604 {
605 *gmode = commercial;
606 *hassec = sc>=2;
607 }
608 else if (ud>=9)
609 *gmode = retail;
610 else if (rg>=18)
611 *gmode = registered;
612 else if (sw>=9)
613 *gmode = shareware;
614 }
615 else // error from access call
616 I_Error("CheckIWAD: IWAD %s not readable", iwadname);
617}
618#endif
619void D_DoomMainSetup(void)
620{
621 int p;
622
623 nomonsters = M_CheckParm ("-nomonsters");
624 respawnparm = M_CheckParm ("-respawn");
625 fastparm = M_CheckParm ("-fast");
626 devparm = M_CheckParm ("-devparm");
627 if (M_CheckParm ("-altdeath"))
628 deathmatch = 2;
629 else if (M_CheckParm ("-deathmatch"))
630 deathmatch = 1;
631
632 printf("Welcome to Rockdoom");
633
634 switch ( gamemode )
635 {
636 case retail:
637 printf ("The Ultimate DOOM Startup v%d.%d",DVERSION/100,DVERSION%100);
638 break;
639 case shareware:
640 printf ("DOOM Shareware Startup v%d.%d",DVERSION/100,DVERSION%100);
641 break;
642 case registered:
643 printf ("DOOM Registered Startup v%d.%d",DVERSION/100,DVERSION%100);
644 break;
645 case commercial:
646 switch (gamemission)
647 {
648 case pack_plut:
649 printf ("DOOM 2: Plutonia Experiment v%d.%d",DVERSION/100,DVERSION%100);
650 break;
651 case pack_tnt:
652 printf ("DOOM 2: TNT - Evilution v%d.%d",DVERSION/100,DVERSION%100);
653 break;
654 default:
655 printf ("DOOM 2: Hell on Earth v%d.%d",DVERSION/100,DVERSION%100);
656 break;
657 }
658 break;
659 default:
660 printf ("Public DOOM v%d.%d",DVERSION/100,DVERSION%100);
661 break;
662 }
663
664 if (devparm)
665 printf(D_DEVSTR);
666
667 // turbo option
668 if ((p=M_CheckParm ("-turbo")))
669 {
670 int scale = 200;
671 extern int forwardmove[2];
672 extern int sidemove[2];
673
674 if (p<myargc-1)
675 scale = atoi (myargv[p+1]);
676 if (scale < 10)
677 scale = 10;
678 if (scale > 400)
679 scale = 400;
680 printf ("turbo scale: %d%%\n",scale);
681 forwardmove[0] = forwardmove[0]*scale/100;
682 forwardmove[1] = forwardmove[1]*scale/100;
683 sidemove[0] = sidemove[0]*scale/100;
684 sidemove[1] = sidemove[1]*scale/100;
685 }
686
687 // get skill / episode / map from parms
688 startskill = sk_medium;
689 startepisode = 1;
690 startmap = 1;
691 autostart = false;
692
693 p = M_CheckParm ("-skill");
694 if (p && p < myargc-1)
695 {
696 startskill = myargv[p+1][0]-'1';
697 autostart = true;
698 }
699
700 p = M_CheckParm ("-episode");
701 if (p && p < myargc-1)
702 {
703 startepisode = myargv[p+1][0]-'0';
704 startmap = 1;
705 autostart = true;
706 }
707
708 p = M_CheckParm ("-warp");
709 if (p && p < myargc-1)
710 {
711 if (gamemode == commercial)
712 startmap = atoi (myargv[p+1]);
713 else
714 {
715 startepisode = myargv[p+1][0]-'0';
716 startmap = myargv[p+2][0]-'0';
717 }
718 autostart = true;
719 }
720
721 // CPhipps - move up netgame init
722 printf("D_InitNetGame: Checking for network game.\n");
723 D_InitNetGame();
724
725 // init subsystems
726 printf ("V_Init: allocate screens.\n");
727 V_Init ();
728
729 printf ("W_Init: Init WADfiles.\n");
730 W_Init();
731
732 V_InitColorTranslation(); //jff 4/24/98 load color translation lumps
733
734 // Check for -file in shareware
735 if (modifiedgame)
736 {
737 // These are the lumps that will be checked in IWAD,
738 // if any one is not present, execution will be aborted.
739 char name[23][8]=
740 {
741 "e2m1","e2m2","e2m3","e2m4","e2m5","e2m6","e2m7","e2m8","e2m9",
742 "e3m1","e3m3","e3m3","e3m4","e3m5","e3m6","e3m7","e3m8","e3m9",
743 "dphoof","bfgga0","heada1","cybra1","spida1d1"
744 };
745 int i;
746
747 if ( gamemode == shareware)
748 I_Error("\nYou cannot -file with the shareware version. Register!");
749
750 // Check for fake IWAD with right name,
751 // but w/o all the lumps of the registered version.
752 if (gamemode == registered)
753 for (i = 0;i < 23; i++)
754 if (W_CheckNumForName(name[i])<0)
755 I_Error("\nThis is not the registered version.");
756 }
757
758 // Iff additonal PWAD files are used, print modified banner
759 if (modifiedgame)
760 printf ("ATTENTION: This version of DOOM has been modified.\n");
761
762 // Check and print which version is executed.
763 switch ( gamemode )
764 {
765 case shareware:
766 case indetermined:
767 printf ("Shareware!\n");
768 break;
769 case registered:
770 case retail:
771 case commercial:
772 printf ("Commercial product - do not distribute!\n");
773 break;
774 default:
775 // Ouch.
776 break;
777 }
778
779 printf ("M_Init: Init miscellaneous info.\n");
780 M_Init ();
781
782 printf ("R_Init: Init DOOM refresh daemon - ");
783 R_Init ();
784
785 printf ("P_Init: Init Playloop state.\n");
786 P_Init ();
787
788 printf ("I_Init: Setting up machine state.\n");
789 I_Init ();
790
791 printf ("S_Init: Setting up sound.\n");
792 S_Init (snd_SfxVolume /* *8 */, snd_MusicVolume /* *8*/ );
793
794 printf ("HU_Init: Setting up heads up display.\n");
795 HU_Init ();
796
797 I_InitGraphics ();
798
799 printf ("ST_Init: Init status bar.\n");
800 ST_Init ();
801
802 // check for a driver that wants intermission stats
803 p = M_CheckParm ("-statcopy");
804 if (p && p<myargc-1)
805 {
806 // for statistics driver
807 extern void* statcopy;
808
809 statcopy = (void*)atoi(myargv[p+1]);
810 printf ("External statistics registered.\n");
811 }
812
813 // start the apropriate game based on parms
814 p = M_CheckParm ("-record");
815 if (p && p < myargc-1)
816 {
817 G_RecordDemo (myargv[p+1]);
818 autostart = true;
819 }
820
821 p = M_CheckParm ("-loadgame");
822 if (p && p < myargc-1)
823 G_LoadGame (atoi(myargv[p+1]), false);
824
825 if ( gameaction != ga_loadgame )
826 {
827 if (!singledemo) { /* killough 12/98 */
828 if (autostart || netgame)
829 G_InitNew (startskill, startepisode, startmap);
830 else
831 D_StartTitle (); // start up intro loop
832 }
833 }
834}
835
836//
837// D_DoomMain
838//
839void D_DoomMain (void)
840{
841 D_DoomMainSetup(); // get this crap off the stack
842
843 D_DoomLoop (); // never returns
844}
diff --git a/apps/plugins/doom/d_main.h b/apps/plugins/doom/d_main.h
new file mode 100644
index 0000000000..c7a861e9ac
--- /dev/null
+++ b/apps/plugins/doom/d_main.h
@@ -0,0 +1,74 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION:
28 * Main startup and splash screenstuff.
29 *
30 *-----------------------------------------------------------------------------*/
31
32#ifndef __D_MAIN__
33#define __D_MAIN__
34
35#include "d_event.h"
36#include "w_wad.h"
37#include "doomdef.h"
38
39#ifdef __GNUG__
40#pragma interface
41#endif
42
43// jff make startskill globally visible
44extern skill_t startskill;
45
46//jff 1/24/98 make command line copies of play modes available
47extern boolean clnomonsters; // checkparm of -nomonsters
48extern boolean clrespawnparm; // checkparm of -respawn
49extern boolean clfastparm; // checkparm of -fast
50//jff end of external declaration of command line playmode
51
52extern boolean nosfxparm;
53extern boolean nomusicparm;
54extern int ffmap;
55
56// Called by IO functions when input is detected.
57void D_PostEvent(event_t* ev);
58
59// Demo stuff
60extern boolean advancedemo;
61void D_AdvanceDemo(void);
62void D_DoAdvanceDemo (void);
63
64//
65// BASE LEVEL
66//
67
68void D_PageTicker(void);
69void D_PageDrawer(void);
70void D_StartTitle(void);
71void D_DoomMain(void);
72void D_AddFile (const char *file, wad_source_t source);
73
74#endif
diff --git a/apps/plugins/doom/d_net.c b/apps/plugins/doom/d_net.c
new file mode 100644
index 0000000000..f70c4435a6
--- /dev/null
+++ b/apps/plugins/doom/d_net.c
@@ -0,0 +1,149 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION:
28 * Network client. Passes information to/from server, staying
29 * synchronised.
30 * Contains the main wait loop, waiting for network input or
31 * time before doing the next tic.
32 * Rewritten for LxDoom, but based around bits of the old code.
33 *
34 *-----------------------------------------------------------------------------
35 */
36
37#include "m_menu.h"
38#include "i_system.h"
39#include "i_video.h"
40#include "i_sound.h"
41#include "g_game.h"
42#include "doomdef.h"
43#include "doomstat.h"
44
45#include "rockmacros.h"
46
47#define NCMD_EXIT 0x80000000
48#define NCMD_RETRANSMIT 0x40000000
49#define NCMD_SETUP 0x20000000
50#define NCMD_KILL 0x10000000 // kill game
51#define NCMD_CHECKSUM 0x0fffffff
52
53
54doomcom_t* doomcom;
55
56static boolean server=0;
57static int remotetic; // Tic expected from the remote
58static int remotesend; // Tic expected by the remote
59
60//
61// NETWORKING
62//
63// gametic is the tic about to (or currently being) run
64// maketic is the tick that hasn't had control made for it yet
65// nettics[] has the maketics for all players
66//
67// a gametic cannot be run until nettics[] > gametic for all players
68//
69
70static ticcmd_t* localcmds;
71
72ticcmd_t netcmds[MAXPLAYERS][BACKUPTICS];
73
74int maketic;
75int ticdup=1;
76
77void G_BuildTiccmd (ticcmd_t *cmd);
78void D_DoAdvanceDemo (void);
79
80void D_InitNetGame (void)
81{
82 int i;
83
84 doomcom = Z_Malloc(sizeof *doomcom, PU_STATIC, NULL);
85 doomcom->consoleplayer = 0;
86 doomcom->numnodes = 0; doomcom->numplayers = 1;
87 localcmds = netcmds[consoleplayer];
88
89 for (i=0; i<doomcom->numplayers; i++)
90 playeringame[i] = true;
91 for (; i<MAXPLAYERS; i++)
92 playeringame[i] = false;
93
94 consoleplayer = displayplayer = doomcom->consoleplayer;
95}
96
97void D_BuildNewTiccmds()
98{
99 static int lastmadetic;
100 int newtics = I_GetTime() - lastmadetic;
101 lastmadetic += newtics;
102 while (newtics--)
103 {
104 I_StartTic();
105 if (maketic - gametic > BACKUPTICS/2) break;
106 G_BuildTiccmd(&localcmds[maketic%BACKUPTICS]);
107 maketic++;
108 }
109}
110
111//
112// TryRunTics
113//
114extern boolean advancedemo;
115
116void TryRunTics (void)
117{
118 int runtics;
119 int entertime = I_GetTime();
120
121 // Wait for tics to run
122 while (1) {
123 D_BuildNewTiccmds();
124 runtics = (server ? remotetic : maketic) - gametic;
125 if (!runtics) {
126// if (server) I_WaitForPacket(ms_to_next_tick);
127// else I_uSleep(ms_to_next_tick*1000);
128// rb->sleep(ms_to_next_tick);
129 if (I_GetTime() - entertime > 10) {
130 remotesend--;
131// {
132// char buf[sizeof(packet_header_t)+1];
133// packet_set((packet_header_t *)buf, PKT_RETRANS, remotetic);
134// buf[sizeof(buf)-1] = consoleplayer;
135// I_SendPacket((packet_header_t *)buf, sizeof buf);
136// }
137 M_Ticker(); return;
138 }
139 } else break;
140 }
141
142 while (runtics--) {
143 if (advancedemo)
144 D_DoAdvanceDemo ();
145 M_Ticker ();
146 G_Ticker ();
147 gametic++;
148 }
149}
diff --git a/apps/plugins/doom/d_net.h b/apps/plugins/doom/d_net.h
new file mode 100644
index 0000000000..6b586e3c96
--- /dev/null
+++ b/apps/plugins/doom/d_net.h
@@ -0,0 +1,213 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION:
28 * Networking stuff.
29 *
30 *-----------------------------------------------------------------------------*/
31
32
33#ifndef __D_NET__
34#define __D_NET__
35
36#include "d_player.h"
37
38
39#ifdef __GNUG__
40#pragma interface
41#endif
42
43
44//
45// Network play related stuff.
46// There is a data struct that stores network
47// communication related stuff, and another
48// one that defines the actual packets to
49// be transmitted.
50//
51
52#define DOOMCOM_ID 0x12345678l
53
54// Max computers/players in a game.
55#define MAXNETNODES 8
56
57
58// Networking and tick handling related.
59#define BACKUPTICS 12
60
61typedef enum
62{
63 CMD_SEND = 1,
64 CMD_GET = 2
65
66} command_t;
67
68
69//
70// Network packet data.
71//
72typedef struct
73{
74 // High bit is retransmit request.
75 unsigned checksum;
76 // Only valid if NCMD_RETRANSMIT.
77 byte retransmitfrom;
78
79 byte starttic;
80 byte player;
81 byte numtics;
82 ticcmd_t cmds[BACKUPTICS];
83
84} doomdata_t;
85
86//
87// Startup packet difference
88// SG: 4/12/98
89// Added so we can send more startup data to synch things like
90// bobbing, recoil, etc.
91// this is just mapped over the ticcmd_t array when setup packet is sent
92//
93// Note: the original code takes care of startskill, deathmatch, nomonsters
94// respawn, startepisode, startmap
95// Note: for phase 1 we need to add monsters_remember, variable_friction,
96// weapon_recoil, allow_pushers, over_under, player_bobbing,
97// fastparm, demo_insurance, and the rngseed
98//Stick all options into bytes so we don't need to mess with bitfields
99//WARNING: make sure this doesn't exceed the size of the ticcmds area!
100//sizeof(ticcmd_t)*BACKUPTICS
101//This is the current length of our extra stuff
102//
103//killough 5/2/98: this should all be replaced by calls to G_WriteOptions()
104//and G_ReadOptions(), which were specifically designed to set up packets.
105//By creating a separate struct and functions to read/write the options,
106//you now have two functions and data to maintain instead of just one.
107//If the array in g_game.c which G_WriteOptions()/G_ReadOptions() operates
108//on, is too large (more than sizeof(ticcmd_t)*BACKUPTICS), it can
109//either be shortened, or the net code needs to divide it up
110//automatically into packets. The STARTUPLEN below is non-portable.
111//There's a portable way to do it without having to know the sizes.
112
113#define STARTUPLEN 12
114typedef struct
115{
116 byte monsters_remember;
117 byte variable_friction;
118 byte weapon_recoil;
119 byte allow_pushers;
120 byte over_under;
121 byte player_bobbing;
122 byte fastparm;
123 byte demo_insurance;
124 unsigned long rngseed;
125 char filler[sizeof(ticcmd_t)*BACKUPTICS-STARTUPLEN];
126} startup_t;
127
128typedef enum {
129 // Leave space, so low values corresponding to normal netgame setup packets can be ignored
130 nm_plcolour = 3,
131 nm_savegamename = 4,
132} netmisctype_t;
133
134typedef struct
135{
136 netmisctype_t type;
137 size_t len;
138 byte value[sizeof(ticcmd_t)*BACKUPTICS - sizeof(netmisctype_t) - sizeof(size_t)];
139} netmisc_t;
140
141typedef struct
142{
143 // Supposed to be DOOMCOM_ID?
144 long id;
145
146 // DOOM executes an int to execute commands.
147 short intnum;
148 // Communication between DOOM and the driver.
149 // Is CMD_SEND or CMD_GET.
150 short command;
151 // Is dest for send, set by get (-1 = no packet).
152 short remotenode;
153
154 // Number of bytes in doomdata to be sent
155 short datalength;
156
157 // Info common to all nodes.
158 // Console is allways node 0.
159 short numnodes;
160 // Flag: 1 = no duplication, 2-5 = dup for slow nets.
161 short ticdup;
162 // Flag: 1 = send a backup tic in every packet.
163 short extratics;
164 // Flag: 1 = deathmatch.
165 short deathmatch;
166 // Flag: -1 = new game, 0-5 = load savegame
167 short savegame;
168 short episode; // 1-3
169 short map; // 1-9
170 short skill; // 1-5
171
172 // Info specific to this node.
173 short consoleplayer;
174 short numplayers;
175
176 // These are related to the 3-display mode,
177 // in which two drones looking left and right
178 // were used to render two additional views
179 // on two additional computers.
180 // Probably not operational anymore.
181 // 1 = left, 0 = center, -1 = right
182 short angleoffset;
183 // 1 = drone
184 short drone;
185
186 // The packet data to be sent.
187 doomdata_t data;
188
189} doomcom_t;
190
191// Create any new ticcmds and broadcast to other players.
192void NetUpdate (void);
193// Create any new ticcmds
194void D_BuildNewTiccmds (void);
195
196// Broadcasts special packets to other players
197// to notify of game exit
198void D_QuitNetGame (void);
199
200//? how many ticks to run?
201void TryRunTics (void);
202
203// CPhipps - move to header file
204void D_InitNetGame (void); // This does the setup
205void D_CheckNetGame(void); // This waits for game start
206
207// CPhipps - misc info broadcast
208void D_NetSendMisc(netmisctype_t type, size_t len, void* data);
209
210// CPhipps - ask server for a wad file we need
211boolean D_NetGetWad(const char* name);
212
213#endif
diff --git a/apps/plugins/doom/d_player.h b/apps/plugins/doom/d_player.h
new file mode 100644
index 0000000000..f86b68f9be
--- /dev/null
+++ b/apps/plugins/doom/d_player.h
@@ -0,0 +1,232 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION:
28 * Player state structure.
29 *
30 *-----------------------------------------------------------------------------*/
31
32
33#ifndef __D_PLAYER__
34#define __D_PLAYER__
35
36
37// The player data structure depends on a number
38// of other structs: items (internal inventory),
39// animation states (closely tied to the sprites
40// used to represent them, unfortunately).
41#include "d_items.h"
42#include "p_pspr.h"
43
44// In addition, the player is just a special
45// case of the generic moving object/actor.
46#include "p_mobj.h"
47
48// Finally, for odd reasons, the player input
49// is buffered within the player data struct,
50// as commands per game tick.
51#include "d_ticcmd.h"
52
53#ifdef __GNUG__
54#pragma interface
55#endif
56
57
58//
59// Player states.
60//
61typedef enum
62{
63 // Playing or camping.
64 PST_LIVE,
65 // Dead on the ground, view follows killer.
66 PST_DEAD,
67 // Ready to restart/respawn???
68 PST_REBORN
69
70} playerstate_t;
71
72
73//
74// Player internal flags, for cheats and debug.
75//
76typedef enum
77{
78 // No clipping, walk through barriers.
79 CF_NOCLIP = 1,
80 // No damage, no health loss.
81 CF_GODMODE = 2,
82 // Not really a cheat, just a debug aid.
83 CF_NOMOMENTUM = 4
84
85} cheat_t;
86
87
88//
89// Extended player object info: player_t
90//
91typedef struct player_s
92{
93 mobj_t* mo;
94 playerstate_t playerstate;
95 ticcmd_t cmd;
96
97 // Determine POV,
98 // including viewpoint bobbing during movement.
99 // Focal origin above r.z
100 fixed_t viewz;
101 // Base height above floor for viewz.
102 fixed_t viewheight;
103 // Bob/squat speed.
104 fixed_t deltaviewheight;
105 // bounded/scaled total momentum.
106 fixed_t bob;
107
108 /* killough 10/98: used for realistic bobbing (i.e. not simply overall speed)
109 * mo->momx and mo->momy represent true momenta experienced by player.
110 * This only represents the thrust that the player applies himself.
111 * This avoids anomolies with such things as Boom ice and conveyors.
112 */
113 fixed_t momx, momy; // killough 10/98
114
115 // This is only used between levels,
116 // mo->health is used during levels.
117 int health;
118 int armorpoints;
119 // Armor type is 0-2.
120 int armortype;
121
122 // Power ups. invinc and invis are tic counters.
123 int powers[NUMPOWERS];
124 boolean cards[NUMCARDS];
125 boolean backpack;
126
127 // Frags, kills of other players.
128 int frags[MAXPLAYERS];
129 weapontype_t readyweapon;
130
131 // Is wp_nochange if not changing.
132 weapontype_t pendingweapon;
133
134 boolean weaponowned[NUMWEAPONS];
135 int ammo[NUMAMMO];
136 int maxammo[NUMAMMO];
137
138 // True if button down last tic.
139 int attackdown;
140 int usedown;
141
142 // Bit flags, for cheats and debug.
143 // See cheat_t, above.
144 int cheats;
145
146 // Refired shots are less accurate.
147 int refire;
148
149 // For intermission stats.
150 int killcount;
151 int itemcount;
152 int secretcount;
153
154 // Hint messages. // CPhipps - const
155 const char* message;
156
157 // For screen flashing (red or bright).
158 int damagecount;
159 int bonuscount;
160
161 // Who did damage (NULL for floors/ceilings).
162 mobj_t* attacker;
163
164 // So gun flashes light up areas.
165 int extralight;
166
167 // Current PLAYPAL, ???
168 // can be set to REDCOLORMAP for pain, etc.
169 int fixedcolormap;
170
171 // Player skin colorshift,
172 // 0-3 for which color to draw player.
173 int colormap;
174
175 // Overlay view sprites (gun, etc).
176 pspdef_t psprites[NUMPSPRITES];
177
178 // True if secret level has been done.
179 boolean didsecret;
180
181} player_t;
182
183
184//
185// INTERMISSION
186// Structure passed e.g. to WI_Start(wb)
187//
188typedef struct
189{
190 boolean in; // whether the player is in game
191
192 // Player stats, kills, collected items etc.
193 int skills;
194 int sitems;
195 int ssecret;
196 int stime;
197 int frags[4];
198 int score; // current score on entry, modified on return
199
200} wbplayerstruct_t;
201
202typedef struct
203{
204 int epsd; // episode # (0-2)
205
206 // if true, splash the secret level
207 boolean didsecret;
208
209 // previous and next levels, origin 0
210 int last;
211 int next;
212
213 int maxkills;
214 int maxitems;
215 int maxsecret;
216 int maxfrags;
217
218 // the par time
219 int partime;
220
221 // index of this player in game
222 int pnum;
223
224 wbplayerstruct_t plyr[MAXPLAYERS];
225
226 // CPhipps - total game time for completed levels so far
227 int totaltimes;
228
229} wbstartstruct_t;
230
231
232#endif
diff --git a/apps/plugins/doom/d_think.h b/apps/plugins/doom/d_think.h
new file mode 100644
index 0000000000..55e9996e1b
--- /dev/null
+++ b/apps/plugins/doom/d_think.h
@@ -0,0 +1,92 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION:
28 * MapObj data. Map Objects or mobjs are actors, entities,
29 * thinker, take-your-pick... anything that moves, acts, or
30 * suffers state changes of more or less violent nature.
31 *
32 *-----------------------------------------------------------------------------*/
33
34#ifndef __D_THINK__
35#define __D_THINK__
36
37#ifdef __GNUG__
38#pragma interface
39#endif
40
41/*
42 * Experimental stuff.
43 * To compile this as "ANSI C with classes"
44 * we will need to handle the various
45 * action functions cleanly.
46 */
47// killough 11/98: convert back to C instead of C++
48typedef void (*actionf_t)();
49//typedef void (*actionf_v)();
50//typedef void (*actionf_p1)( void* );
51//typedef void (*actionf_p2)( void*, void* );
52
53/* Note: In d_deh.c you will find references to these
54 * wherever code pointers and function handlers exist
55 */
56/*
57typedef union
58{
59 actionf_p1 acp1;
60 actionf_v acv;
61 actionf_p2 acp2;
62
63} actionf_t;
64*/
65
66/* Historically, "think_t" is yet another
67 * function pointer to a routine to handle
68 * an actor.
69 */
70typedef actionf_t think_t;
71
72
73/* Doubly linked list of actors. */
74typedef struct thinker_s
75{
76 struct thinker_s* prev;
77 struct thinker_s* next;
78 think_t function;
79
80 /* killough 8/29/98: we maintain thinkers in several equivalence classes,
81 * according to various criteria, so as to allow quicker searches.
82 */
83
84 struct thinker_s *cnext, *cprev; /* Next, previous thinkers in same class */
85
86 /* killough 11/98: count of how many other objects reference
87 * this one using pointers. Used for garbage collection.
88 */
89 unsigned references;
90} thinker_t;
91
92#endif
diff --git a/apps/plugins/doom/d_ticcmd.h b/apps/plugins/doom/d_ticcmd.h
new file mode 100644
index 0000000000..1193a32df1
--- /dev/null
+++ b/apps/plugins/doom/d_ticcmd.h
@@ -0,0 +1,57 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION:
28 * System specific interface stuff.
29 *
30 *-----------------------------------------------------------------------------*/
31
32#ifndef __D_TICCMD__
33#define __D_TICCMD__
34
35#include "doomtype.h"
36
37#ifdef __GNUG__
38#pragma interface
39#endif
40
41/* The data sampled per tick (single player)
42 * and transmitted to other peers (multiplayer).
43 * Mainly movements/button commands per game tick,
44 * plus a checksum for internal state consistency.
45 * CPhipps - explicitely signed the elements, since they have to be signed to work right
46 */
47typedef struct
48{
49 signed char forwardmove; /* *2048 for move */
50 signed char sidemove; /* *2048 for move */
51 signed short angleturn; /* <<16 for angle delta */
52 short consistancy; /* checks for net game */
53 byte chatchar;
54 byte buttons;
55} ticcmd_t;
56
57#endif
diff --git a/apps/plugins/doom/doomdata.h b/apps/plugins/doom/doomdata.h
new file mode 100644
index 0000000000..f56524e6cd
--- /dev/null
+++ b/apps/plugins/doom/doomdata.h
@@ -0,0 +1,187 @@
1// Emacs style mode select -*- C++ -*-
2//-----------------------------------------------------------------------------
3//
4// $Id$
5//
6// Copyright (C) 1993-1996 by id Software, Inc.
7//
8// This program is free software; you can redistribute it and/or
9// modify it under the terms of the GNU General Public License
10// as published by the Free Software Foundation; either version 2
11// of the License, or (at your option) any later version.
12//
13// This program is distributed in the hope that it will be useful,
14// but WITHOUT ANY WARRANTY; without even the implied warranty of
15// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16// GNU General Public License for more details.
17//
18// DESCRIPTION:
19// all external data is defined here
20// most of the data is loaded into different structures at run time
21// some internal structures shared by many modules are here
22//
23//-----------------------------------------------------------------------------
24
25#ifndef __DOOMDATA__
26#define __DOOMDATA__
27
28// The most basic types we use, portability.
29#include "doomtype.h"
30
31// Some global defines, that configure the game.
32#include "doomdef.h"
33
34#include "rockmacros.h"
35
36//
37// Map level types.
38// The following data structures define the persistent format
39// used in the lumps of the WAD files.
40//
41
42// Lump order in a map WAD: each map needs a couple of lumps
43// to provide a complete scene geometry description.
44enum {
45 ML_LABEL, // A separator, name, ExMx or MAPxx
46 ML_THINGS, // Monsters, items..
47 ML_LINEDEFS, // LineDefs, from editing
48 ML_SIDEDEFS, // SideDefs, from editing
49 ML_VERTEXES, // Vertices, edited and BSP splits generated
50 ML_SEGS, // LineSegs, from LineDefs split by BSP
51 ML_SSECTORS, // SubSectors, list of LineSegs
52 ML_NODES, // BSP nodes
53 ML_SECTORS, // Sectors, from editing
54 ML_REJECT, // LUT, sector-sector visibility
55 ML_BLOCKMAP // LUT, motion clipping, walls/grid element
56};
57
58// A single Vertex.
59typedef struct {
60 short x,y;
61} PACKEDATTR mapvertex_t;
62
63// A SideDef, defining the visual appearance of a wall,
64// by setting textures and offsets.
65typedef struct {
66 short textureoffset;
67 short rowoffset;
68 char toptexture[8];
69 char bottomtexture[8];
70 char midtexture[8];
71 short sector; // Front sector, towards viewer.
72} PACKEDATTR mapsidedef_t;
73
74// A LineDef, as used for editing, and as input to the BSP builder.
75
76typedef struct {
77 short v1;
78 short v2;
79 short flags;
80 short special;
81 short tag;
82 short sidenum[2]; // sidenum[1] will be -1 if one sided
83} PACKEDATTR maplinedef_t;
84
85
86//
87// LineDef attributes.
88//
89
90// Solid, is an obstacle.
91#define ML_BLOCKING 1
92
93// Blocks monsters only.
94#define ML_BLOCKMONSTERS 2
95
96// Backside will not be present at all
97// if not two sided.
98#define ML_TWOSIDED 4
99
100// If a texture is pegged, the texture will have
101// the end exposed to air held constant at the
102// top or bottom of the texture (stairs or pulled
103// down things) and will move with a height change
104// of one of the neighbor sectors.
105// Unpegged textures allways have the first row of
106// the texture at the top pixel of the line for both
107// top and bottom textures (use next to windows).
108
109// upper texture unpegged
110#define ML_DONTPEGTOP 8
111
112// lower texture unpegged
113#define ML_DONTPEGBOTTOM 16
114
115// In AutoMap: don't map as two sided: IT'S A SECRET!
116#define ML_SECRET 32
117
118// Sound rendering: don't let sound cross two of these.
119#define ML_SOUNDBLOCK 64
120
121// Don't draw on the automap at all.
122#define ML_DONTDRAW 128
123
124// Set if already seen, thus drawn in automap.
125#define ML_MAPPED 256
126
127//jff 3/21/98 Set if line absorbs use by player
128//allow multiple push/switch triggers to be used on one push
129#define ML_PASSUSE 512
130
131// Sector definition, from editing.
132typedef struct {
133 short floorheight;
134 short ceilingheight;
135 char floorpic[8];
136 char ceilingpic[8];
137 short lightlevel;
138 short special;
139 short tag;
140} PACKEDATTR mapsector_t;
141
142// SubSector, as generated by BSP.
143typedef struct {
144 unsigned short numsegs;
145 unsigned short firstseg; // Index of first one; segs are stored sequentially.
146} PACKEDATTR mapsubsector_t;
147
148// LineSeg, generated by splitting LineDefs
149// using partition lines selected by BSP builder.
150typedef struct {
151 short v1;
152 short v2;
153 short angle;
154 short linedef;
155 short side;
156 short offset;
157} PACKEDATTR mapseg_t;
158
159// BSP node structure.
160
161// Indicate a leaf.
162#define NF_SUBSECTOR 0x8000
163
164typedef struct {
165 short x; // Partition line from (x,y) to x+dx,y+dy)
166 short y;
167 short dx;
168 short dy;
169 // Bounding box for each child, clip against view frustum.
170 short bbox[2][4];
171 // If NF_SUBSECTOR its a subsector, else it's a node of another subtree.
172 unsigned short children[2];
173} PACKEDATTR mapnode_t;
174
175// Thing definition, position, orientation and type,
176// plus skill/visibility flags and attributes.
177typedef struct {
178 short x;
179 short y;
180 short angle;
181 short type;
182 short options;
183} PACKEDATTR mapthing_t;
184
185
186
187#endif // __DOOMDATA__
diff --git a/apps/plugins/doom/doomdef.c b/apps/plugins/doom/doomdef.c
new file mode 100644
index 0000000000..d4ad61e979
--- /dev/null
+++ b/apps/plugins/doom/doomdef.c
@@ -0,0 +1,39 @@
1// Emacs style mode select -*- C++ -*-
2//-----------------------------------------------------------------------------
3//
4// $Id$
5//
6// Copyright (C) 1993-1996 by id Software, Inc.
7//
8// This program is free software; you can redistribute it and/or
9// modify it under the terms of the GNU General Public License
10// as published by the Free Software Foundation; either version 2
11// of the License, or (at your option) any later version.
12//
13// This program is distributed in the hope that it will be useful,
14// but WITHOUT ANY WARRANTY; without even the implied warranty of
15// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16// GNU General Public License for more details.
17//
18// $Log$
19// Revision 1.1 2006/03/28 15:44:01 dave
20// Patch #2969 - Doom! Currently only working on the H300.
21//
22//
23// DESCRIPTION:
24// DoomDef - basic defines for DOOM, e.g. Version, game mode
25// and skill level, and display parameters.
26//
27//-----------------------------------------------------------------------------
28
29
30#ifdef __GNUG__
31#pragma implementation "doomdef.h"
32#endif
33#include "doomdef.h"
34
35// Location for any defines turned variables.
36
37// None.
38
39
diff --git a/apps/plugins/doom/doomdef.h b/apps/plugins/doom/doomdef.h
new file mode 100644
index 0000000000..f76b09263a
--- /dev/null
+++ b/apps/plugins/doom/doomdef.h
@@ -0,0 +1,306 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION:
28 * Internally used data structures for virtually everything,
29 * key definitions, lots of other stuff.
30 *
31 *-----------------------------------------------------------------------------*/
32
33#ifndef __DOOMDEF__
34#define __DOOMDEF__
35
36// killough 4/25/98: Make gcc extensions mean nothing on other compilers
37#ifndef __GNUC__
38#define __attribute__(x)
39#endif
40
41//
42// Global parameters/defines.
43//
44// DOOM version
45enum { DVERSION = 110 };
46
47// Game mode handling - identify IWAD version
48// to handle IWAD dependend animations etc.
49typedef enum {
50 shareware, // DOOM 1 shareware, E1, M9
51 registered, // DOOM 1 registered, E3, M27
52 commercial, // DOOM 2 retail, E1 M34 (DOOM 2 german edition not handled)
53 retail, // DOOM 1 retail, E4, M36
54 indetermined // Well, no IWAD found.
55} GameMode_t;
56
57// Mission packs - might be useful for TC stuff?
58typedef enum {
59 doom, // DOOM 1
60 doom2, // DOOM 2
61 pack_tnt, // TNT mission pack
62 pack_plut, // Plutonia pack
63 none
64} GameMission_t;
65
66// Identify language to use, software localization.
67typedef enum {
68 english,
69 french,
70 german,
71 unknown
72} Language_t;
73
74//
75// For resize of screen, at start of game.
76//
77
78#define BASE_WIDTH 320
79
80// It is educational but futile to change this
81// scaling e.g. to 2. Drawing of status bar,
82// menues etc. is tied to the scale implied
83// by the graphics.
84
85#define INV_ASPECT_RATIO 0.625 // 0.75, ideally
86
87// killough 2/8/98: MAX versions for maximum screen sizes
88// allows us to avoid the overhead of dynamic allocation
89// when multiple screen sizes are supported
90
91// proff 08/17/98: Changed for high-res
92#define MAX_SCREENWIDTH 1600
93#define MAX_SCREENHEIGHT 1200
94
95#define SCREENWIDTH 320
96#define SCREENHEIGHT 200
97
98// The maximum number of players, multiplayer/networking.
99#define MAXPLAYERS 4
100
101// phares 5/14/98:
102// DOOM Editor Numbers (aka doomednum in mobj_t)
103
104#define DEN_PLAYER5 4001
105#define DEN_PLAYER6 4002
106#define DEN_PLAYER7 4003
107#define DEN_PLAYER8 4004
108
109// State updates, number of tics / second.
110#define TICRATE 35
111
112// The current state of the game: whether we are playing, gazing
113// at the intermission screen, the game final animation, or a demo.
114
115typedef enum {
116 GS_LEVEL,
117 GS_INTERMISSION,
118 GS_FINALE,
119 GS_DEMOSCREEN
120} gamestate_t;
121
122//
123// Difficulty/skill settings/filters.
124//
125
126// Skill flags.
127#define MTF_EASY 1
128#define MTF_NORMAL 2
129#define MTF_HARD 4
130// Deaf monsters/do not react to sound.
131#define MTF_AMBUSH 8
132
133/* killough 11/98 */
134#define MTF_NOTSINGLE 16
135#define MTF_NOTDM 32
136#define MTF_NOTCOOP 64
137#define MTF_FRIEND 128
138#define MTF_RESERVED 256
139
140typedef enum {
141 sk_none=-1, //jff 3/24/98 create unpicked skill setting
142 sk_baby=0,
143 sk_easy,
144 sk_medium,
145 sk_hard,
146 sk_nightmare
147} skill_t;
148
149//
150// Key cards.
151//
152
153typedef enum {
154 it_bluecard,
155 it_yellowcard,
156 it_redcard,
157 it_blueskull,
158 it_yellowskull,
159 it_redskull,
160 NUMCARDS
161} card_t;
162
163// The defined weapons, including a marker
164// indicating user has not changed weapon.
165typedef enum {
166 wp_fist,
167 wp_pistol,
168 wp_shotgun,
169 wp_chaingun,
170 wp_missile,
171 wp_plasma,
172 wp_bfg,
173 wp_chainsaw,
174 wp_supershotgun,
175
176 NUMWEAPONS,
177 wp_nochange // No pending weapon change.
178} weapontype_t;
179
180// Ammunition types defined.
181typedef enum {
182 am_clip, // Pistol / chaingun ammo.
183 am_shell, // Shotgun / double barreled shotgun.
184 am_cell, // Plasma rifle, BFG.
185 am_misl, // Missile launcher.
186 NUMAMMO,
187 am_noammo // Unlimited for chainsaw / fist.
188} ammotype_t;
189
190// Power up artifacts.
191typedef enum {
192 pw_invulnerability,
193 pw_strength,
194 pw_invisibility,
195 pw_ironfeet,
196 pw_allmap,
197 pw_infrared,
198 NUMPOWERS
199} powertype_t;
200
201// Power up durations (how many seconds till expiration).
202typedef enum {
203 INVULNTICS = (30*TICRATE),
204 INVISTICS = (60*TICRATE),
205 INFRATICS = (120*TICRATE),
206 IRONTICS = (60*TICRATE)
207} powerduration_t;
208
209//
210// DOOM keyboard definition.
211// This is the stuff configured by Setup.Exe.
212// Most key data are simple ascii (uppercased).
213//
214#define KEY_RIGHTARROW 0xae
215#define KEY_LEFTARROW 0xac
216#define KEY_UPARROW 0xad
217#define KEY_DOWNARROW 0xaf
218#define KEY_ESCAPE 0x1B
219#define KEY_ENTER 0x0D
220#define KEY_TAB 0x09
221#define KEY_F1 (0x80+0x3b)
222#define KEY_F2 (0x80+0x3c)
223#define KEY_F3 (0x80+0x3d)
224#define KEY_F4 (0x80+0x3e)
225#define KEY_F5 (0x80+0x3f)
226#define KEY_F6 (0x80+0x40)
227#define KEY_F7 (0x80+0x41)
228#define KEY_F8 (0x80+0x42)
229#define KEY_F9 (0x80+0x43)
230#define KEY_F10 (0x80+0x44)
231#define KEY_F11 (0x80+0x57)
232#define KEY_F12 (0x80+0x58)
233#define KEY_BACKSPACE 0x7F
234#define KEY_PAUSE 0xff
235#define KEY_EQUALS 0x3d
236#define KEY_MINUS 0x2d
237#define KEY_RSHIFT (0x80+0x36)
238#define KEY_RCTRL (0x80+0x1d)
239#define KEY_RALT (0x80+0x38)
240#define KEY_LALT KEY_RALT
241#define KEY_CAPSLOCK 0xba // phares
242
243// phares 3/2/98:
244#define KEY_INSERT 0xd2
245#define KEY_HOME 0xc7
246#define KEY_PAGEUP 0xc9
247#define KEY_PAGEDOWN 0xd1
248#define KEY_DEL 0xc8
249#define KEY_END 0xcf
250#define KEY_SCROLLLOCK 0xc6
251#define KEY_SPACEBAR 0x20
252// phares 3/2/98
253
254#define KEY_NUMLOCK 0xC5 // killough 3/6/98
255
256// cph - Add the numeric keypad keys, as suggested by krose 4/22/99:
257// The way numbers are assigned to keys is a mess, but it's too late to
258// change that easily. At least these additions are don neatly.
259// Codes 0x100-0x200 are reserved for number pad
260
261#define KEY_KEYPAD0 (0x100 + '0')
262#define KEY_KEYPAD1 (0x100 + '1')
263#define KEY_KEYPAD2 (0x100 + '2')
264#define KEY_KEYPAD3 (0x100 + '3')
265#define KEY_KEYPAD4 (0x100 + '4')
266#define KEY_KEYPAD5 (0x100 + '5')
267#define KEY_KEYPAD6 (0x100 + '6')
268#define KEY_KEYPAD7 (0x100 + '7')
269#define KEY_KEYPAD8 (0x100 + '8')
270#define KEY_KEYPAD9 (0x100 + '9')
271#define KEY_KEYPADENTER (0x100 + KEY_ENTER)
272#define KEY_KEYPADDIVIDE (0x100 + '/')
273#define KEY_KEYPADMULTIPLY (0x100 + '*')
274#define KEY_KEYPADMINUS (0x100 + '-')
275#define KEY_KEYPADPLUS (0x100 + '+')
276#define KEY_KEYPADPERIOD (0x100 + '.')
277
278// phares 4/19/98:
279// Defines Setup Screen groups that config variables appear in.
280// Used when resetting the defaults for every item in a Setup group.
281
282typedef enum {
283 ss_none,
284 ss_keys,
285 ss_weap,
286 ss_stat,
287 ss_auto,
288 ss_enem,
289 ss_mess,
290 ss_chat,
291 ss_gen, /* killough 10/98 */
292 ss_comp, /* killough 10/98 */
293 ss_max
294} ss_types;
295
296// phares 3/20/98:
297//
298// Player friction is variable, based on controlling
299// linedefs. More friction can create mud, sludge,
300// magnetized floors, etc. Less friction can create ice.
301
302#define MORE_FRICTION_MOMENTUM 15000 // mud factor based on momentum
303#define ORIG_FRICTION 0xE800 // original value
304#define ORIG_FRICTION_FACTOR 2048 // original value
305
306#endif // __DOOMDEF__
diff --git a/apps/plugins/doom/doomstat.c b/apps/plugins/doom/doomstat.c
new file mode 100644
index 0000000000..75cc209919
--- /dev/null
+++ b/apps/plugins/doom/doomstat.c
@@ -0,0 +1,104 @@
1// Emacs style mode select -*- C++ -*-
2//-----------------------------------------------------------------------------
3//
4// $Id$
5//
6// Copyright (C) 1993-1996 by id Software, Inc.
7//
8// This program is free software; you can redistribute it and/or
9// modify it under the terms of the GNU General Public License
10// as published by the Free Software Foundation; either version 2
11// of the License, or (at your option) any later version.
12//
13// This program is distributed in the hope that it will be useful,
14// but WITHOUT ANY WARRANTY; without even the implied warranty of
15// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16// GNU General Public License for more details.
17//
18// $Log$
19// Revision 1.1 2006/03/28 15:44:01 dave
20// Patch #2969 - Doom! Currently only working on the H300.
21//
22//
23// DESCRIPTION:
24// Put all global tate variables here.
25//
26//-----------------------------------------------------------------------------
27
28#ifdef __GNUG__
29#pragma implementation "doomstat.h"
30#endif
31#include "doomstat.h"
32
33
34// Game Mode - identify IWAD as shareware, retail etc.
35GameMode_t gamemode IDATA_ATTR= indetermined;
36GameMission_t gamemission IDATA_ATTR = doom;
37
38// Language.
39Language_t language = english;
40
41// Set if homebrew PWAD stuff has been added.
42boolean modifiedgame;
43
44//-----------------------------------------------------------------------------
45
46// CPhipps - compatibility vars
47complevel_t compatibility_level=prboom_3_compatibility, default_compatibility_level=prboom_3_compatibility;
48
49int comp[COMP_TOTAL] IBSS_ATTR, default_comp[COMP_TOTAL]; // killough 10/98
50
51// v1.1-like pitched sounds
52int pitched_sounds=0; // killough
53
54int default_translucency; // config file says // phares
55boolean general_translucency IBSS_ATTR; // true if translucency is ok // phares
56
57int demo_insurance, default_demo_insurance; // killough 1/16/98
58
59int allow_pushers IDATA_ATTR = 1; // MT_PUSH Things // phares 3/10/98
60int default_allow_pushers; // killough 3/1/98: make local to each game
61
62int variable_friction IDATA_ATTR = 1; // ice & mud // phares 3/10/98
63int default_variable_friction; // killough 3/1/98: make local to each game
64
65int weapon_recoil IBSS_ATTR; // weapon recoil // phares
66int default_weapon_recoil; // killough 3/1/98: make local to each game
67
68int player_bobbing IBSS_ATTR; // whether player bobs or not // phares 2/25/98
69int default_player_bobbing; // killough 3/1/98: make local to each game
70
71int monsters_remember IBSS_ATTR; // killough 3/1/98
72int default_monsters_remember;
73
74int monster_infighting IDATA_ATTR=1; // killough 7/19/98: monster<=>monster attacks
75int default_monster_infighting=1;
76
77int monster_friction IDATA_ATTR=1; // killough 10/98: monsters affected by friction
78int default_monster_friction=1;
79
80#ifdef DOGS
81int dogs, default_dogs; // killough 7/19/98: Marine's best friend :)
82int dog_jumping, default_dog_jumping; // killough 10/98
83#endif
84
85// killough 8/8/98: distance friends tend to move towards players
86int distfriend = 128, default_distfriend = 128;
87
88// killough 9/8/98: whether monsters are allowed to strafe or retreat
89int monster_backing IBSS_ATTR, default_monster_backing;
90
91// killough 9/9/98: whether monsters are able to avoid hazards (e.g. crushers)
92int monster_avoid_hazards IBSS_ATTR, default_monster_avoid_hazards;
93
94// killough 9/9/98: whether monsters help friends
95int help_friends IBSS_ATTR, default_help_friends;
96
97int flashing_hom; // killough 10/98
98
99int doom_weapon_toggles; // killough 10/98
100
101int monkeys IBSS_ATTR, default_monkeys;
102
103boolean nosfxparm=0;
104boolean rockblock=1;
diff --git a/apps/plugins/doom/doomstat.h b/apps/plugins/doom/doomstat.h
new file mode 100644
index 0000000000..42cd4f5716
--- /dev/null
+++ b/apps/plugins/doom/doomstat.h
@@ -0,0 +1,373 @@
1// Emacs style mode select -*- C++ -*-
2//-----------------------------------------------------------------------------
3//
4// $Id$
5//
6// Copyright (C) 1993-1996 by id Software, Inc.
7//
8// This program is free software; you can redistribute it and/or
9// modify it under the terms of the GNU General Public License
10// as published by the Free Software Foundation; either version 2
11// of the License, or (at your option) any later version.
12//
13// This program is distributed in the hope that it will be useful,
14// but WITHOUT ANY WARRANTY; without even the implied warranty of
15// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16// GNU General Public License for more details.
17//
18// DESCRIPTION:
19// All the global variables that store the internal state.
20// Theoretically speaking, the internal state of the engine
21// should be found by looking at the variables collected
22// here, and every relevant module will have to include
23// this header file.
24// In practice, things are a bit messy.
25//
26//-----------------------------------------------------------------------------
27
28
29#ifndef __D_STATE__
30#define __D_STATE__
31
32// We need globally shared data structures,
33// for defining the global state variables.
34#include "doomdata.h"
35#include "d_net.h"
36
37// We need the playr data structure as well.
38#include "d_player.h"
39
40
41#ifdef __GNUG__
42#pragma interface
43#endif
44
45
46// ------------------------
47// Command line parameters.
48//
49extern boolean nomonsters; // checkparm of -nomonsters
50extern boolean respawnparm; // checkparm of -respawn
51extern boolean fastparm; // checkparm of -fast
52
53extern boolean devparm; // DEBUG: launched with -devparm
54
55enum automapmode_e {
56 am_active = 1, // currently shown
57 am_overlay= 2, // covers the screen, i.e. not overlay mode
58 am_rotate = 4, // rotates to the player facing direction
59 am_follow = 8, // keep the player centred
60 am_grid =16, // show grid
61};
62extern enum automapmode_e automapmode; // Mode that the automap is in
63
64// -----------------------------------------------------
65// Game Mode - identify IWAD as shareware, retail etc.
66//
67extern GameMode_t gamemode;
68extern GameMission_t gamemission;
69
70// Set if homebrew PWAD stuff has been added.
71extern boolean modifiedgame;
72
73// CPhipps - new compatibility handling
74extern complevel_t compatibility_level, default_compatibility_level;
75
76// CPhipps - old compatibility testing flags aliased to new handling
77#define compatibility (compatibility_level<=boom_compatibility_compatibility)
78#define demo_compatibility (compatibility_level <= doom_demo_compatibility)
79#define mbf_features (compatibility_level>=mbf_compatibility)
80
81extern int default_translucency;
82extern boolean general_translucency; // true if translucency is ok // phares
83
84extern int demo_insurance, default_demo_insurance; // killough 4/5/98
85
86// -------------------------------------------
87// killough 10/98: compatibility vector
88
89enum {
90 comp_telefrag,
91 comp_dropoff,
92 comp_vile,
93 comp_pain,
94 comp_skull,
95 comp_blazing,
96 comp_doorlight,
97 comp_model,
98 comp_god,
99 comp_falloff,
100 comp_floors,
101 comp_skymap,
102 comp_pursuit,
103 comp_doorstuck,
104 comp_staylift,
105 comp_zombie,
106 comp_stairs,
107 comp_infcheat,
108 comp_zerotags,
109 comp_moveblock,
110 comp_respawn, /* cph - this is the inverse of comp_respawnfix from eternity */
111 comp_sound,
112 COMP_NUM, /* cph - should be last in sequence */
113 COMP_TOTAL=32 // Some extra room for additional variables
114};
115
116extern int comp[COMP_TOTAL], default_comp[COMP_TOTAL];
117
118extern boolean nosfxparm;
119extern boolean rockblock;
120
121// -------------------------------------------
122// Language.
123extern Language_t language;
124
125
126// -------------------------------------------
127// Selected skill type, map etc.
128//
129
130// Defaults for menu, methinks.
131extern skill_t startskill;
132extern int startepisode;
133extern int startmap;
134
135extern boolean autostart;
136
137// Selected by user.
138extern skill_t gameskill;
139extern int gameepisode;
140extern int gamemap;
141
142// Nightmare mode flag, single player.
143extern boolean respawnmonsters;
144
145// Netgame? Only true if >1 player.
146extern boolean netgame;
147
148// Flag: true only if started as net deathmatch.
149// An enum might handle altdeath/cooperative better.
150extern boolean deathmatch;
151
152// -------------------------
153// Internal parameters for sound rendering.
154// These have been taken from the DOS version,
155// but are not (yet) supported with Linux
156// (e.g. no sound volume adjustment with menu.
157
158// These are not used, but should be (menu).
159// From m_menu.c:
160// Sound FX volume has default, 0 - 15
161// Music volume has default, 0 - 15
162// These are multiplied by 8.
163extern int snd_SfxVolume; // maximum volume for sound
164extern int snd_MusicVolume; // maximum volume for music
165
166// Current music/sfx card - index useless
167// w/o a reference LUT in a sound module.
168// Ideally, this would use indices found
169// in: /usr/include/linux/soundcard.h
170extern int snd_MusicDevice;
171extern int snd_SfxDevice;
172// Config file? Same disclaimer as above.
173extern int snd_DesiredMusicDevice;
174extern int snd_DesiredSfxDevice;
175
176
177// -------------------------
178// Status flags for refresh.
179//
180
181// Depending on view size - no status bar?
182// Note that there is no way to disable the
183// status bar explicitely.
184extern boolean statusbaractive;
185
186extern boolean automapactive; // In AutoMap mode?
187extern boolean menuactive; // Menu overlayed?
188extern boolean paused; // Game Pause?
189
190
191extern boolean viewactive;
192
193extern boolean nodrawers;
194extern boolean noblit;
195
196extern int viewwindowx;
197extern int viewwindowy;
198extern int viewheight;
199extern int viewwidth;
200extern int scaledviewwidth;
201
202// This one is related to the 3-screen display mode.
203// ANG90 = left side, ANG270 = right
204extern int viewangleoffset;
205
206// Player taking events, and displaying.
207extern int consoleplayer;
208extern int displayplayer;
209
210
211// -------------------------------------
212// Scores, rating.
213// Statistics on a given map, for intermission.
214//
215extern int totalkills, totallive;
216extern int totalitems;
217extern int totalsecret;
218
219// Timer, for scores.
220extern int levelstarttic; // gametic at level start
221extern int basetic; /* killough 9/29/98: levelstarttic, adjusted */
222extern int leveltime; // tics in game play for par
223
224
225
226// --------------------------------------
227// DEMO playback/recording related stuff.
228// No demo, there is a human player in charge?
229// Disable save/end game?
230extern boolean usergame;
231
232//?
233extern boolean demoplayback;
234extern boolean demorecording;
235
236// Quit after playing a demo from cmdline.
237extern boolean singledemo;
238
239
240
241
242//?
243extern gamestate_t gamestate;
244
245//-----------------------------
246// Internal parameters, fixed.
247// These are set by the engine, and not changed
248// according to user inputs. Partly load from
249// WAD, partly set at startup time.
250
251extern int gametic;
252
253// Bookkeeping on players - state.
254extern player_t players[MAXPLAYERS];
255
256// Alive? Disconnected?
257extern boolean playeringame[MAXPLAYERS];
258
259
260// Player spawn spots for deathmatch.
261#define MAX_DM_STARTS 10
262//extern mapthing_t deathmatchstarts[MAX_DM_STARTS];
263extern mapthing_t *deathmatchstarts; // killough
264extern size_t num_deathmatchstarts; // killough
265extern mapthing_t* deathmatch_p;
266
267// Player spawn spots.
268extern mapthing_t playerstarts[MAXPLAYERS];
269
270// Intermission stats.
271// Parameters for world map / intermission.
272extern wbstartstruct_t wminfo;
273
274
275// LUT of ammunition limits for each kind.
276// This doubles with BackPack powerup item.
277extern int maxammo[NUMAMMO];
278
279//-----------------------------------------
280// Internal parameters, used for engine.
281//
282
283// File handling stuff.
284extern char basedefault[];
285extern int debugfile;
286
287// if true, load all graphics at level load
288extern boolean precache;
289
290
291// wipegamestate can be set to -1
292// to force a wipe on the next draw
293extern gamestate_t wipegamestate;
294
295extern int mouseSensitivity;
296//?
297// debug flag to cancel adaptiveness
298extern boolean singletics;
299
300extern int bodyqueslot;
301
302
303
304// Needed to store the number of the dummy sky flat.
305// Used for rendering,
306// as well as tracking projectiles etc.
307extern int skyflatnum;
308
309// Netgame stuff (buffers and pointers, i.e. indices).
310extern doomcom_t* doomcom;
311extern doomdata_t* netbuffer; // This points inside doomcom.
312
313extern int rndindex;
314
315extern int maketic;
316
317extern ticcmd_t netcmds[][BACKUPTICS];
318
319extern int ticdup;
320
321extern int nettics[MAXNETNODES];
322
323//-----------------------------------------------------------------------------
324
325// v1.1-like pitched sounds
326extern int pitched_sounds; // killough 2/21/98
327
328extern int allow_pushers; // MT_PUSH Things // phares 3/10/98
329extern int default_allow_pushers;
330
331extern int variable_friction; // ice & mud // phares 3/10/98
332extern int default_variable_friction;
333
334extern int monsters_remember; // killough 3/1/98
335extern int default_monsters_remember;
336
337extern int weapon_recoil; // weapon recoil // phares
338extern int default_weapon_recoil;
339
340extern int player_bobbing; // whether player bobs or not // phares 2/25/98
341extern int default_player_bobbing; // killough 3/1/98: make local to each game
342
343#ifdef DOGS
344extern int dogs, default_dogs; // killough 7/19/98: Marine's best friend :)
345extern int dog_jumping, default_dog_jumping; // killough 10/98
346#endif
347
348/* killough 8/8/98: distance friendly monsters tend to stay from player */
349extern int distfriend, default_distfriend;
350
351/* killough 9/8/98: whether monsters are allowed to strafe or retreat */
352extern int monster_backing, default_monster_backing;
353
354/* killough 9/9/98: whether monsters intelligently avoid hazards */
355extern int monster_avoid_hazards, default_monster_avoid_hazards;
356
357/* killough 10/98: whether monsters are affected by friction */
358extern int monster_friction, default_monster_friction;
359
360/* killough 9/9/98: whether monsters help friends */
361extern int help_friends, default_help_friends;
362
363extern int flashing_hom; // killough 10/98
364
365extern int doom_weapon_toggles; // killough 10/98
366
367/* killough 7/19/98: whether monsters should fight against each other */
368extern int monster_infighting, default_monster_infighting;
369
370extern int monkeys, default_monkeys;
371
372
373#endif
diff --git a/apps/plugins/doom/doomtype.h b/apps/plugins/doom/doomtype.h
new file mode 100644
index 0000000000..59b33758da
--- /dev/null
+++ b/apps/plugins/doom/doomtype.h
@@ -0,0 +1,85 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION:
28 * Simple basic typedefs, isolated here to make it easier
29 * separating modules.
30 *
31 *-----------------------------------------------------------------------------*/
32#ifndef __DOOMTYPE__
33#define __DOOMTYPE__
34#include "rockmacros.h"
35
36#ifndef __BYTEBOOL__
37#define __BYTEBOOL__
38// Fixed to use builtin bool type with C++.
39#ifdef __cplusplus
40typedef bool boolean;
41#else
42//typedef enum {false, true} boolean;
43//#define boolean bool
44typedef enum _boolean { FALSE, TRUE } boolean;
45#endif
46typedef unsigned char byte;
47#endif
48
49typedef signed long long int_64_t;
50typedef unsigned long long uint_64_t;
51
52#define MAXCHAR ((char)0x7f)
53#define MAXSHORT ((short)0x7fff)
54
55// Max pos 32-bit int.
56#define MAXINT ((int)0x7fffffff)
57#define MAXLONG ((long)0x7fffffff)
58#define MINCHAR ((char)0x80)
59#define MINSHORT ((short)0x8000)
60
61// Max negative 32-bit integer.
62#define MININT ((int)0x80000000)
63#define MINLONG ((long)0x80000000)
64
65/* cph - move compatibility levels here so we can use them in d_server.c */
66typedef enum {
67 doom_12_compatibility, /* Behave like early doom versions */
68 doom_demo_compatibility, /* As compatible as possible for
69 * playing original Doom demos */
70 doom_compatibility, /* Compatible with original Doom levels */
71 boom_compatibility_compatibility, /* Boom's compatibility mode */
72 boom_201_compatibility, /* Compatible with Boom v2.01 */
73 boom_202_compatibility, /* Compatible with Boom v2.01 */
74 lxdoom_1_compatibility, /* LxDoom v1.3.2+ */
75 mbf_compatibility, /* MBF */
76 prboom_1_compatibility, /* PrBoom 2.03beta? */
77 prboom_2_compatibility, /* PrBoom 2.1.0-2.1.1 */
78 prboom_3_compatibility, /* Latest PrBoom */
79 MAX_COMPATIBILITY_LEVEL, /* Must be last entry */
80 /* Aliases follow */
81 boom_compatibility = boom_201_compatibility, /* Alias used by G_Compatibility */
82 best_compatibility = prboom_3_compatibility,
83} complevel_t;
84
85#endif
diff --git a/apps/plugins/doom/dstrings.c b/apps/plugins/doom/dstrings.c
new file mode 100644
index 0000000000..104e99c479
--- /dev/null
+++ b/apps/plugins/doom/dstrings.c
@@ -0,0 +1,83 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION:
28 * Globally defined strings.
29 *
30 *-----------------------------------------------------------------------------
31 */
32
33#ifdef __GNUG__
34#pragma implementation "dstrings.h"
35#endif
36#include "dstrings.h"
37
38
39// killough 1/18/98: remove hardcoded limit, add const:
40const char *const endmsg[]=
41 {
42 // DOOM1
43 QUITMSG,
44 "please don't leave, there's more\ndemons to toast!",
45 "let's beat it -- this is turning\ninto a bloodbath!",
46 "i wouldn't leave if i were you.\ndos is much worse.",
47 "you're trying to say you like dos\nbetter than me, right?",
48 "don't leave yet -- there's a\ndemon around that corner!",
49 "ya know, next time you come in here\ni'm gonna toast ya.",
50 "go ahead and leave. see if i care.", // 1/15/98 killough
51
52 // QuitDOOM II messages
53 "you want to quit?\nthen, thou hast lost an eighth!",
54 "don't go now, there's a \ndimensional shambler waiting\nat the dos prompt!",
55 "get outta here and go back\nto your boring programs.",
56 "if i were your boss, i'd \n deathmatch ya in a minute!",
57 "look, bud. you leave now\nand you forfeit your body count!",
58 "just leave. when you come\nback, i'll be waiting with a bat.",
59 "you're lucky i don't smack\nyou for thinking about leaving.", // 1/15/98 killough
60
61 // FinalDOOM?
62
63 // Note that these ending "bad taste" strings were commented out
64 // in the original id code as the #else case of an #if 1
65 // Obviously they were internal playthings before the release of
66 // DOOM2 and were not intended for public use.
67 //
68 // Following messages commented out for now. Bad taste. // phares
69
70 // "fuck you, pussy!\nget the fuck out!",
71 // "you quit and i'll jizz\nin your cystholes!",
72 // "if you leave, i'll make\nthe lord drink my jizz.",
73 // "hey, ron! can we say\n'fuck' in the game?",
74 // "i'd leave: this is just\nmore monsters and levels.\nwhat a load.",
75 // "suck it down, asshole!\nyou're a fucking wimp!",
76 // "don't quit now! we're \nstill spending your money!",
77
78 // Internal debug. Different style, too.
79 "THIS IS NO MESSAGE!\nPage intentionally left blank.", // 1/15/98 killough
80 };
81
82// killough 1/18/98: remove hardcoded limit and replace with var (silly hack):
83const size_t NUM_QUITMESSAGES = sizeof(endmsg)/sizeof(*endmsg) - 1;
diff --git a/apps/plugins/doom/dstrings.h b/apps/plugins/doom/dstrings.h
new file mode 100644
index 0000000000..4402c21f1f
--- /dev/null
+++ b/apps/plugins/doom/dstrings.h
@@ -0,0 +1,73 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION:
28 * DOOM strings, by language.
29 * Note: In BOOM, some new strings hav ebeen defined that are
30 * not found in the French version. A better approach is
31 * to create a BEX text-replacement file for other
32 * languages since any language can be supported that way
33 * without recompiling the program.
34 *
35 *-----------------------------------------------------------------------------*/
36
37#ifndef __DSTRINGS__
38#define __DSTRINGS__
39
40#include "d_englsh.h"
41#include "rockmacros.h"
42
43/* Note this is not externally modifiable through DEH/BEX
44 * Misc. other strings.
45 * #define SAVEGAMENAME "boomsav" * killough 3/22/98 *
46 * Ty 05/04/98 - replaced with a modifiable string, see d_deh.c
47 */
48
49// Misc. other strings.
50#define SAVEGAMENAME GAMEBASE"doomsav"
51
52/*
53 * File locations,
54 * relative to current position.
55 * Path names are OS-sensitive.
56 */
57#define DEVMAPS "devmaps"
58#define DEVDATA "devdata"
59
60
61/* Not done in french?
62 * QuitDOOM messages *
63 * killough 1/18/98:
64 * replace hardcoded limit with extern var (silly hack, I know)
65 */
66
67#include <stddef.h>
68
69extern const size_t NUM_QUITMESSAGES; /* Calculated in dstrings.c */
70
71extern const char* const endmsg[]; /* killough 1/18/98 const added */
72
73#endif
diff --git a/apps/plugins/doom/f_finale.c b/apps/plugins/doom/f_finale.c
new file mode 100644
index 0000000000..4deb3df689
--- /dev/null
+++ b/apps/plugins/doom/f_finale.c
@@ -0,0 +1,682 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION:
28 * Game completion, final screen animation.
29 *
30 *-----------------------------------------------------------------------------
31 */
32
33#include "doomstat.h"
34#include "d_event.h"
35#include "d_englsh.h"
36#include "m_swap.h"
37#include "v_video.h"
38#include "w_wad.h"
39#include "s_sound.h"
40#include "sounds.h"
41//#include "d_deh.h" // Ty 03/22/98 - externalizations
42#include "f_finale.h" // CPhipps - hmm...
43#include "rockmacros.h"
44
45// Stage of animation:
46// 0 = text, 1 = art screen, 2 = character cast
47static int finalestage; // cph -
48static int finalecount; // made static
49static const char* finaletext; // cph -
50static const char* finaleflat; // made static const
51
52// defines for the end mission display text // phares
53
54#define TEXTSPEED 3 // original value // phares
55#define TEXTWAIT 250 // original value // phares
56#define NEWTEXTSPEED 0.01f // new value // phares
57#define NEWTEXTWAIT 1000 // new value // phares
58
59// CPhipps - removed the old finale screen text message strings;
60// they were commented out for ages already
61// Ty 03/22/98 - ... the new s_WHATEVER extern variables are used
62// in the code below instead.
63
64void F_StartCast (void);
65void F_CastTicker (void);
66boolean F_CastResponder (event_t *ev);
67void F_CastDrawer (void);
68
69void WI_checkForAccelerate(void); // killough 3/28/98: used to
70extern int acceleratestage; // accelerate intermission screens
71static int midstage; // whether we're in "mid-stage"
72
73//
74// F_StartFinale
75//
76void F_StartFinale (void)
77{
78 gameaction = ga_nothing;
79 gamestate = GS_FINALE;
80 automapmode &= ~am_active;
81
82 // killough 3/28/98: clear accelerative text flags
83 acceleratestage = midstage = 0;
84
85 // Okay - IWAD dependend stuff.
86 // This has been changed severly, and
87 // some stuff might have changed in the process.
88 switch ( gamemode )
89 {
90
91 // DOOM 1 - E1, E3 or E4, but each nine missions
92 case shareware:
93 case registered:
94 case retail:
95 {
96 S_ChangeMusic(mus_victor, true);
97
98 switch (gameepisode)
99 {
100 case 1:
101 finaleflat = "FLOOR4_8";
102 finaletext = E1TEXT;
103 break;
104 case 2:
105 finaleflat = "SFLR6_1";
106 finaletext = E2TEXT;
107 break;
108 case 3:
109 finaleflat = "MFLR8_4";
110 finaletext = E3TEXT;
111 break;
112 case 4:
113 finaleflat = "MFLR8_3";
114 finaletext = E4TEXT;
115 break;
116 default:
117 // Ouch.
118 break;
119 }
120 break;
121 }
122
123 // DOOM II and missions packs with E1, M34
124 case commercial:
125 {
126 S_ChangeMusic(mus_read_m, true);
127
128 // Ty 08/27/98 - added the gamemission logic
129 switch (gamemap)
130 {
131 case 6:
132 finaleflat = "SLIME16";
133 finaletext = (gamemission==pack_tnt) ? T1TEXT :
134 (gamemission==pack_plut) ? P1TEXT : C1TEXT;
135 break;
136 case 11:
137 finaleflat = "RROCK14";
138 finaletext = (gamemission==pack_tnt) ? T2TEXT :
139 (gamemission==pack_plut) ? P2TEXT : C2TEXT;
140 break;
141 case 20:
142 finaleflat = "RROCK07";
143 finaletext = (gamemission==pack_tnt) ? T3TEXT :
144 (gamemission==pack_plut) ? P3TEXT : C3TEXT;
145 break;
146 case 30:
147 finaleflat = "RROCK17";
148 finaletext = (gamemission==pack_tnt) ? T4TEXT :
149 (gamemission==pack_plut) ? P4TEXT : C4TEXT;
150 break;
151 case 15:
152 finaleflat = "RROCK13";
153 finaletext = (gamemission==pack_tnt) ? T5TEXT :
154 (gamemission==pack_plut) ? P5TEXT : C5TEXT;
155 break;
156 case 31:
157 finaleflat = "RROCK19";
158 finaletext = (gamemission==pack_tnt) ? T6TEXT :
159 (gamemission==pack_plut) ? P6TEXT : C6TEXT;
160 break;
161 default:
162 // Ouch.
163 break;
164 }
165 break;
166 }
167
168
169 // Indeterminate.
170 default:
171 S_ChangeMusic(mus_read_m, true);
172 finaleflat = "F_SKY1"; // Not used anywhere else.
173 finaletext = C1TEXT; // FIXME - other text, music?
174 break;
175 }
176
177 finalestage = 0;
178 finalecount = 0;
179
180}
181
182
183
184boolean F_Responder (event_t *event)
185{
186 if (finalestage == 2)
187 return F_CastResponder (event);
188
189 return false;
190}
191
192// Get_TextSpeed() returns the value of the text display speed // phares
193// Rewritten to allow user-directed acceleration -- killough 3/28/98
194
195static float Get_TextSpeed(void)
196{
197 return midstage ? NEWTEXTSPEED : (midstage=acceleratestage) ?
198 acceleratestage=0, NEWTEXTSPEED : TEXTSPEED;
199}
200
201//
202// F_Ticker
203//
204// killough 3/28/98: almost totally rewritten, to use
205// player-directed acceleration instead of constant delays.
206// Now the player can accelerate the text display by using
207// the fire/use keys while it is being printed. The delay
208// automatically responds to the user, and gives enough
209// time to read.
210//
211// killough 5/10/98: add back v1.9 demo compatibility
212//
213
214void F_Ticker(void)
215{
216 int i;
217 if (!demo_compatibility)
218 WI_checkForAccelerate(); // killough 3/28/98: check for acceleration
219 else
220 if (gamemode == commercial && finalecount > 50) // check for skipping
221 for (i=0; i<MAXPLAYERS; i++)
222 if (players[i].cmd.buttons)
223 goto next_level; // go on to the next level
224
225 // advance animation
226 finalecount++;
227
228 if (finalestage == 2)
229 F_CastTicker();
230
231 if (!finalestage)
232 {
233 float speed = demo_compatibility ? TEXTSPEED : Get_TextSpeed();
234 /* killough 2/28/98: changed to allow acceleration */
235 if (finalecount > strlen(finaletext)*speed +
236 (midstage ? NEWTEXTWAIT : TEXTWAIT) ||
237 (midstage && acceleratestage)) {
238 if (gamemode != commercial) // Doom 1 / Ultimate Doom episode end
239 { // with enough time, it's automatic
240 finalecount = 0;
241 finalestage = 1;
242 wipegamestate = -1; // force a wipe
243 if (gameepisode == 3)
244 S_StartMusic(mus_bunny);
245 }
246 else // you must press a button to continue in Doom 2
247 if (!demo_compatibility && midstage)
248 {
249next_level:
250 if (gamemap == 30)
251 F_StartCast(); // cast of Doom 2 characters
252 else
253 gameaction = ga_worlddone; // next level, e.g. MAP07
254 }
255 }
256 }
257}
258
259
260//
261// F_TextWrite
262//
263// This program displays the background and text at end-mission // phares
264// text time. It draws both repeatedly so that other displays, // |
265// like the main menu, can be drawn over it dynamically and // V
266// erased dynamically. The TEXTSPEED constant is changed into
267// the Get_TextSpeed function so that the speed of writing the // ^
268// text can be increased, and there's still time to read what's // |
269// written. // phares
270// CPhipps - reformatted
271
272#include "hu_stuff.h"
273extern patchnum_t hu_font[HU_FONTSIZE];
274
275
276void F_TextWrite (void)
277{
278 V_DrawBackground(finaleflat, 0);
279 { // draw some of the text onto the screen
280 int cx = 10;
281 int cy = 10;
282 const char* ch = finaletext; // CPhipps - const
283 int count = (int)((float)(finalecount - 10)/Get_TextSpeed()); // phares
284 int w;
285
286 if (count < 0)
287 count = 0;
288
289 for ( ; count ; count-- ) {
290 int c = *ch++;
291
292 if (!c)
293 break;
294 if (c == '\n') {
295 cx = 10;
296 cy += 11;
297 continue;
298 }
299
300 c = toupper(c) - HU_FONTSTART;
301 if (c < 0 || c> HU_FONTSIZE) {
302 cx += 4;
303 continue;
304 }
305
306 w = SHORT (hu_font[c].width);
307 if (cx+w > SCREENWIDTH)
308 break;
309 // CPhipps - patch drawing updated
310 V_DrawNumPatch(cx, cy, 0, hu_font[c].lumpnum, CR_DEFAULT, VPT_STRETCH);
311 cx+=w;
312 }
313 }
314}
315
316//
317// Final DOOM 2 animation
318// Casting by id Software.
319// in order of appearance
320//
321typedef struct
322{
323 const char *name; // CPhipps - const**
324 mobjtype_t type;
325} castinfo_t;
326
327#define MAX_CASTORDER 18 /* Ty - hard coded for now */
328static const castinfo_t castorder[] = { // CPhipps - static const, initialised here
329 { CC_ZOMBIE, MT_POSSESSED },
330 { CC_SHOTGUN, MT_SHOTGUY },
331 { CC_HEAVY, MT_CHAINGUY },
332 { CC_IMP, MT_TROOP },
333 { CC_DEMON, MT_SERGEANT },
334 { CC_LOST, MT_SKULL },
335 { CC_CACO, MT_HEAD },
336 { CC_HELL, MT_KNIGHT },
337 { CC_BARON, MT_BRUISER },
338 { CC_ARACH, MT_BABY },
339 { CC_PAIN, MT_PAIN },
340 { CC_REVEN, MT_UNDEAD },
341 { CC_MANCU, MT_FATSO },
342 { CC_ARCH, MT_VILE },
343 { CC_SPIDER, MT_SPIDER },
344 { CC_CYBER, MT_CYBORG },
345 { CC_HERO, MT_PLAYER },
346 { NULL, 0}
347 };
348
349int castnum;
350int casttics;
351state_t* caststate;
352boolean castdeath;
353int castframes;
354int castonmelee;
355boolean castattacking;
356
357
358//
359// F_StartCast
360//
361extern gamestate_t wipegamestate;
362
363void F_StartCast (void)
364{
365 wipegamestate = -1; // force a screen wipe
366 castnum = 0;
367 caststate = &states[mobjinfo[castorder[castnum].type].seestate];
368 casttics = caststate->tics;
369 castdeath = false;
370 finalestage = 2;
371 castframes = 0;
372 castonmelee = 0;
373 castattacking = false;
374 S_ChangeMusic(mus_evil, true);
375}
376
377
378//
379// F_CastTicker
380//
381void F_CastTicker (void)
382{
383 int st;
384 int sfx;
385
386 if (--casttics > 0)
387 return; // not time to change state yet
388
389 if (caststate->tics == -1 || caststate->nextstate == S_NULL)
390 {
391 // switch from deathstate to next monster
392 castnum++;
393 castdeath = false;
394 if (castorder[castnum].name == NULL)
395 castnum = 0;
396 if (mobjinfo[castorder[castnum].type].seesound)
397 S_StartSound (NULL, mobjinfo[castorder[castnum].type].seesound);
398 caststate = &states[mobjinfo[castorder[castnum].type].seestate];
399 castframes = 0;
400 }
401 else
402 {
403 // just advance to next state in animation
404 if (caststate == &states[S_PLAY_ATK1])
405 goto stopattack; // Oh, gross hack!
406 st = caststate->nextstate;
407 caststate = &states[st];
408 castframes++;
409
410 // sound hacks....
411 switch (st)
412 {
413 case S_PLAY_ATK1: sfx = sfx_dshtgn; break;
414 case S_POSS_ATK2: sfx = sfx_pistol; break;
415 case S_SPOS_ATK2: sfx = sfx_shotgn; break;
416 case S_VILE_ATK2: sfx = sfx_vilatk; break;
417 case S_SKEL_FIST2: sfx = sfx_skeswg; break;
418 case S_SKEL_FIST4: sfx = sfx_skepch; break;
419 case S_SKEL_MISS2: sfx = sfx_skeatk; break;
420 case S_FATT_ATK8:
421 case S_FATT_ATK5:
422 case S_FATT_ATK2: sfx = sfx_firsht; break;
423 case S_CPOS_ATK2:
424 case S_CPOS_ATK3:
425 case S_CPOS_ATK4: sfx = sfx_shotgn; break;
426 case S_TROO_ATK3: sfx = sfx_claw; break;
427 case S_SARG_ATK2: sfx = sfx_sgtatk; break;
428 case S_BOSS_ATK2:
429 case S_BOS2_ATK2:
430 case S_HEAD_ATK2: sfx = sfx_firsht; break;
431 case S_SKULL_ATK2: sfx = sfx_sklatk; break;
432 case S_SPID_ATK2:
433 case S_SPID_ATK3: sfx = sfx_shotgn; break;
434 case S_BSPI_ATK2: sfx = sfx_plasma; break;
435 case S_CYBER_ATK2:
436 case S_CYBER_ATK4:
437 case S_CYBER_ATK6: sfx = sfx_rlaunc; break;
438 case S_PAIN_ATK3: sfx = sfx_sklatk; break;
439 default: sfx = 0; break;
440 }
441
442 if (sfx)
443 S_StartSound (NULL, sfx);
444 }
445
446 if (castframes == 12)
447 {
448 // go into attack frame
449 castattacking = true;
450 if (castonmelee)
451 caststate=&states[mobjinfo[castorder[castnum].type].meleestate];
452 else
453 caststate=&states[mobjinfo[castorder[castnum].type].missilestate];
454 castonmelee ^= 1;
455 if (caststate == &states[S_NULL])
456 {
457 if (castonmelee)
458 caststate=
459 &states[mobjinfo[castorder[castnum].type].meleestate];
460 else
461 caststate=
462 &states[mobjinfo[castorder[castnum].type].missilestate];
463 }
464 }
465
466 if (castattacking)
467 {
468 if (castframes == 24
469 || caststate == &states[mobjinfo[castorder[castnum].type].seestate] )
470 {
471stopattack:
472 castattacking = false;
473 castframes = 0;
474 caststate = &states[mobjinfo[castorder[castnum].type].seestate];
475 }
476 }
477
478 casttics = caststate->tics;
479 if (casttics == -1)
480 casttics = 15;
481}
482
483
484//
485// F_CastResponder
486//
487
488boolean F_CastResponder (event_t* ev)
489{
490 if (ev->type != ev_keydown)
491 return false;
492
493 if (castdeath)
494 return true; // already in dying frames
495
496 // go into death frame
497 castdeath = true;
498 caststate = &states[mobjinfo[castorder[castnum].type].deathstate];
499 casttics = caststate->tics;
500 castframes = 0;
501 castattacking = false;
502 if (mobjinfo[castorder[castnum].type].deathsound)
503 S_StartSound (NULL, mobjinfo[castorder[castnum].type].deathsound);
504
505 return true;
506}
507
508
509static void F_CastPrint (const char* text) // CPhipps - static, const char*
510{
511 const char* ch; // CPhipps - const
512 int c;
513 int cx;
514 int w;
515 int width;
516
517 // find width
518 ch = text;
519 width = 0;
520
521 while (ch)
522 {
523 c = *ch++;
524 if (!c)
525 break;
526 c = toupper(c) - HU_FONTSTART;
527 if (c < 0 || c> HU_FONTSIZE)
528 {
529 width += 4;
530 continue;
531 }
532
533 w = SHORT (hu_font[c].width);
534 width += w;
535 }
536
537 // draw it
538 cx = 160-width/2;
539 ch = text;
540 while (ch)
541 {
542 c = *ch++;
543 if (!c)
544 break;
545 c = toupper(c) - HU_FONTSTART;
546 if (c < 0 || c> HU_FONTSIZE)
547 {
548 cx += 4;
549 continue;
550 }
551
552 w = SHORT (hu_font[c].width);
553 // CPhipps - patch drawing updated
554 V_DrawNumPatch(cx, 180, 0, hu_font[c].lumpnum, CR_DEFAULT, VPT_STRETCH);
555 cx+=w;
556 }
557}
558
559
560//
561// F_CastDrawer
562//
563void V_DrawPatchFlipped (int x, int y, int scrn, patch_t *patch);
564
565void F_CastDrawer (void)
566{
567 spritedef_t* sprdef;
568 spriteframe_t* sprframe;
569 int lump;
570 boolean flip;
571
572 // erase the entire screen to a background
573 V_DrawNamePatch(0,0,0, "BOSSBACK", CR_DEFAULT, VPT_STRETCH); // Ty 03/30/98 bg texture extern
574
575 F_CastPrint (castorder[castnum].name);
576
577 // draw the current frame in the middle of the screen
578 sprdef = &sprites[caststate->sprite];
579 sprframe = &sprdef->spriteframes[ caststate->frame & FF_FRAMEMASK];
580 lump = sprframe->lump[0];
581 flip = (boolean)sprframe->flip[0];
582
583 // CPhipps - patch drawing updated
584 V_DrawNumPatch(160, 170, 0, lump+firstspritelump, CR_DEFAULT,
585 VPT_STRETCH | (flip ? VPT_FLIP : 0));
586}
587
588
589//
590// F_BunnyScroll
591//
592static const char pfub2[] = { "PFUB2" };
593static const char pfub1[] = { "PFUB1" };
594
595static void F_BunnyScroll (void)
596{
597 char name[10];
598 int stage;
599 static int laststage;
600
601 V_MarkRect (0, 0, SCREENWIDTH, SCREENHEIGHT);
602 {
603 int scrolled = 320 - (finalecount-230)/2;
604 if (scrolled <= 0) {
605 V_DrawNamePatch(0, 0, 0, pfub2, CR_DEFAULT, VPT_STRETCH);
606 } else if (scrolled >= 320) {
607 V_DrawNamePatch(0, 0, 0, pfub1, CR_DEFAULT, VPT_STRETCH);
608 } else {
609#define SCRN 2
610
611 int realscrolled = (SCREENWIDTH * scrolled) / 320;
612
613 V_AllocScreen(SCRN);
614 V_DrawNamePatch(0, 0, SCRN, pfub2, CR_DEFAULT, VPT_STRETCH);
615 V_CopyRect(realscrolled, 0, SCRN, SCREENWIDTH-realscrolled, SCREENHEIGHT, 0, 0, 0, VPT_NONE);
616 V_DrawNamePatch(0, 0, SCRN, pfub1, CR_DEFAULT, VPT_STRETCH);
617 V_CopyRect(0, 0, SCRN, realscrolled, SCREENHEIGHT, SCREENWIDTH-realscrolled, 0, 0, VPT_NONE);
618 V_FreeScreen(SCRN);
619 }
620 }
621
622 if (finalecount < 1130)
623 return;
624 if (finalecount < 1180)
625 {
626 // CPhipps - patch drawing updated
627 V_DrawNamePatch((320-13*8)/2, (200-8*8)/2,0, "END0", CR_DEFAULT, VPT_STRETCH);
628 laststage = 0;
629 return;
630 }
631
632 stage = (finalecount-1180) / 5;
633 if (stage > 6)
634 stage = 6;
635 if (stage > laststage)
636 {
637 S_StartSound (NULL, sfx_pistol);
638 laststage = stage;
639 }
640
641 snprintf (name,sizeof(name), "END%i",stage);
642 // CPhipps - patch drawing updated
643 V_DrawNamePatch((320-13*8)/2, (200-8*8)/2, 0, name, CR_DEFAULT, VPT_STRETCH);
644}
645
646
647//
648// F_Drawer
649//
650void F_Drawer (void)
651{
652 if (finalestage == 2)
653 {
654 F_CastDrawer ();
655 return;
656 }
657
658 if (!finalestage)
659 F_TextWrite ();
660 else
661 {
662 switch (gameepisode)
663 {
664 // CPhipps - patch drawing updated
665 case 1:
666 if ( gamemode == retail )
667 V_DrawNamePatch(0, 0, 0, "CREDIT", CR_DEFAULT, VPT_STRETCH);
668 else
669 V_DrawNamePatch(0, 0, 0, "HELP2", CR_DEFAULT, VPT_STRETCH);
670 break;
671 case 2:
672 V_DrawNamePatch(0, 0, 0, "VICTORY2", CR_DEFAULT, VPT_STRETCH);
673 break;
674 case 3:
675 F_BunnyScroll ();
676 break;
677 case 4:
678 V_DrawNamePatch(0, 0, 0, "ENDPIC", CR_DEFAULT, VPT_STRETCH);
679 break;
680 }
681 }
682}
diff --git a/apps/plugins/doom/f_finale.h b/apps/plugins/doom/f_finale.h
new file mode 100644
index 0000000000..63e2fbd3e4
--- /dev/null
+++ b/apps/plugins/doom/f_finale.h
@@ -0,0 +1,54 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION:
28 * Related to f_finale.c, which is called at the end of a level
29 *
30 *-----------------------------------------------------------------------------*/
31
32
33#ifndef __F_FINALE__
34#define __F_FINALE__
35
36#include "doomtype.h"
37#include "d_event.h"
38
39/*
40 * FINALE
41 */
42
43/* Called by main loop. */
44boolean F_Responder (event_t* ev);
45
46/* Called by main loop. */
47void F_Ticker (void);
48
49/* Called by main loop. */
50void F_Drawer (void);
51
52void F_StartFinale (void);
53
54#endif
diff --git a/apps/plugins/doom/f_wipe.c b/apps/plugins/doom/f_wipe.c
new file mode 100644
index 0000000000..a6251f295e
--- /dev/null
+++ b/apps/plugins/doom/f_wipe.c
@@ -0,0 +1,193 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION:
28 * Mission begin melt/wipe screen special effect.
29 *
30 *-----------------------------------------------------------------------------
31 */
32
33#include "rockmacros.h"
34#include "z_zone.h"
35#include "doomdef.h"
36#include "i_video.h"
37#include "v_video.h"
38#include "m_random.h"
39#include "f_wipe.h"
40
41
42
43//
44// SCREEN WIPE PACKAGE
45//
46
47// CPhipps - macros for the source and destination screens
48#define SRC_SCR 2
49#define DEST_SCR 3
50
51static byte *wipe_scr_start;
52static byte *wipe_scr_end;
53static byte *wipe_scr;
54
55static void wipe_shittyColMajorXform(short *array, int width, int height)
56{
57 short *dest = Z_Malloc(width*height*sizeof(short), PU_STATIC, 0);
58 int x, y;
59
60 for(y=0;y<height;y++)
61 for(x=0;x<width;x++)
62 dest[x*height+y] = array[y*width+x];
63 memcpy(array, dest, width*height*sizeof(short));
64 Z_Free(dest);
65}
66
67static int *y;
68
69static int wipe_initMelt(int width, int height, int ticks)
70{
71 (void)ticks;
72 int i;
73
74 // copy start screen to main screen
75 memcpy(wipe_scr, wipe_scr_start, width*height);
76
77 // makes this wipe faster (in theory)
78 // to have stuff in column-major format
79 wipe_shittyColMajorXform((short*)wipe_scr_start, width/2, height);
80 wipe_shittyColMajorXform((short*)wipe_scr_end, width/2, height);
81
82 // setup initial column positions (y<0 => not ready to scroll yet)
83 y = (int *) malloc(width*sizeof(int));
84 y[0] = -(M_Random()%16);
85 for (i=1;i<width;i++)
86 {
87 int r = (M_Random()%3) - 1;
88 y[i] = y[i-1] + r;
89 if (y[i] > 0)
90 y[i] = 0;
91 else
92 if (y[i] == -16)
93 y[i] = -15;
94 }
95 return 0;
96}
97
98static int wipe_doMelt(int width, int height, int ticks)
99{
100 boolean done = true;
101 int i;
102
103 width /= 2;
104
105 while (ticks--)
106 for (i=0;i<width;i++)
107 if (y[i]<0)
108 {
109 y[i]++;
110 done = false;
111 }
112 else
113 if (y[i] < height)
114 {
115 short *s, *d;
116 int j, dy, idx;
117
118 dy = (y[i] < 16) ? y[i]+1 : 8;
119 if (y[i]+dy >= height)
120 dy = height - y[i];
121 s = &((short *)wipe_scr_end)[i*height+y[i]];
122 d = &((short *)wipe_scr)[y[i]*width+i];
123 idx = 0;
124 for (j=dy;j;j--)
125 {
126 d[idx] = *(s++);
127 idx += width;
128 }
129 y[i] += dy;
130 s = &((short *)wipe_scr_start)[i*height];
131 d = &((short *)wipe_scr)[y[i]*width+i];
132 idx = 0;
133 for (j=height-y[i];j;j--)
134 {
135 d[idx] = *(s++);
136 idx += width;
137 }
138 done = false;
139 }
140 return done;
141}
142
143// CPhipps - modified to allocate and deallocate screens[2 to 3] as needed, saving memory
144
145static int wipe_exitMelt(int width, int height, int ticks)
146{
147 (void)width;
148 (void)height;
149 (void)ticks;
150 free(y);
151 free(wipe_scr_start);
152 free(wipe_scr_end);
153 // Paranoia
154 y = NULL;
155 wipe_scr_start = wipe_scr_end = screens[SRC_SCR] = screens[DEST_SCR] = NULL;
156 return 0;
157}
158
159int wipe_StartScreen(int x, int y, int width, int height)
160{
161 wipe_scr_start = screens[SRC_SCR] = malloc(SCREENWIDTH * SCREENHEIGHT);
162 V_CopyRect(x, y, 0, width, height, x, y, SRC_SCR, VPT_NONE ); // Copy start screen to buffer
163 return 0;
164}
165
166int wipe_EndScreen(int x, int y, int width, int height)
167{
168 wipe_scr_end = screens[DEST_SCR] = malloc(SCREENWIDTH * SCREENHEIGHT);
169 V_CopyRect(x, y, 0, width, height, x, y, DEST_SCR, VPT_NONE); // Copy end screen to buffer
170 V_CopyRect(x, y, SRC_SCR, width, height, x, y, 0 , VPT_NONE); // restore start screen
171 return 0;
172}
173
174// killough 3/5/98: reformatted and cleaned up
175int wipe_ScreenWipe(int x, int y, int width, int height, int ticks)
176{
177 (void)x;
178 (void)y;
179 static boolean go; // when zero, stop the wipe
180 if (!go) // initial stuff
181 {
182 go = 1;
183 wipe_scr = screens[0];
184 wipe_initMelt(width, height, ticks);
185 }
186 V_MarkRect(0, 0, width, height); // do a piece of wipe-in
187 if (wipe_doMelt(width, height, ticks)) // final stuff
188 {
189 wipe_exitMelt(width, height, ticks);
190 go = 0;
191 }
192 return !go;
193}
diff --git a/apps/plugins/doom/f_wipe.h b/apps/plugins/doom/f_wipe.h
new file mode 100644
index 0000000000..ec19a812ef
--- /dev/null
+++ b/apps/plugins/doom/f_wipe.h
@@ -0,0 +1,43 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION:
28 * Mission start screen wipe/melt, special effects.
29 *
30 *-----------------------------------------------------------------------------*/
31
32#ifndef __F_WIPE_H__
33#define __F_WIPE_H__
34
35/*
36 * SCREEN WIPE PACKAGE
37 */
38
39int wipe_ScreenWipe (int x, int y, int width, int height, int ticks);
40int wipe_StartScreen(int x, int y, int width, int height);
41int wipe_EndScreen (int x, int y, int width, int height);
42
43#endif
diff --git a/apps/plugins/doom/g_game.c b/apps/plugins/doom/g_game.c
new file mode 100644
index 0000000000..426ab1ca13
--- /dev/null
+++ b/apps/plugins/doom/g_game.c
@@ -0,0 +1,2818 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION: none
28 * The original Doom description was none, basically because this file
29 * has everything. This ties up the game logic, linking the menu and
30 * input code to the underlying game by creating & respawning players,
31 * building game tics, calling the underlying thing logic.
32 *
33 *-----------------------------------------------------------------------------
34 */
35
36#include "doomdef.h"
37#include "doomstat.h"
38#include "z_zone.h"
39#include "f_finale.h"
40#include "m_argv.h"
41#include "m_misc.h"
42#include "m_menu.h"
43#include "m_random.h"
44#include "i_system.h"
45#include "p_map.h"
46#include "p_setup.h"
47#include "p_saveg.h"
48#include "p_tick.h"
49
50#include "d_main.h"
51
52#include "wi_stuff.h"
53#include "hu_stuff.h"
54#include "st_stuff.h"
55#include "am_map.h"
56
57// Needs access to LFB.
58#include "v_video.h"
59
60#include "w_wad.h"
61#include "r_main.h"
62#include "s_sound.h"
63
64// Data.
65#include "dstrings.h"
66#include "sounds.h"
67
68// SKY handling - still the wrong place.
69#include "r_data.h"
70#include "r_sky.h"
71#include "p_inter.h"
72#include "g_game.h"
73
74#include "rockmacros.h"
75
76#define SAVEGAMESIZE 0x20000
77#define SAVESTRINGSIZE 24
78
79static size_t savegamesize = SAVEGAMESIZE; // killough
80static boolean netdemo;
81static const byte *demobuffer; /* cph - only used for playback */
82static int demofd; /* cph - record straight to file */
83static const byte *demo_p;
84static short consistancy[MAXPLAYERS][BACKUPTICS];
85
86gameaction_t gameaction;
87gamestate_t gamestate;
88skill_t gameskill;
89boolean respawnmonsters;
90int gameepisode;
91int gamemap;
92boolean paused;
93// CPhipps - moved *_loadgame vars here
94static boolean forced_loadgame = false;
95static boolean command_loadgame = false;
96
97boolean usergame; // ok to save / end game
98boolean timingdemo; // if true, exit with report on completion
99boolean fastdemo; // if true, run at full speed -- killough
100boolean nodrawers; // for comparative timing purposes
101boolean noblit; // for comparative timing purposes
102int starttime; // for comparative timing purposes
103boolean deathmatch; // only if started as net death
104boolean netgame; // only true if packets are broadcast
105boolean playeringame[MAXPLAYERS];
106player_t players[MAXPLAYERS];
107int consoleplayer; // player taking events and displaying
108int displayplayer; // view being displayed
109int gametic;
110int levelstarttic; // gametic at level start
111int basetic; /* killough 9/29/98: for demo sync */
112int totalkills, totallive, totalitems, totalsecret; // for intermission
113boolean demorecording;
114boolean demoplayback;
115boolean singledemo; // quit after playing a demo from cmdline
116wbstartstruct_t wminfo; // parms for world map / intermission
117boolean haswolflevels = false;// jff 4/18/98 wolf levels present
118static byte *savebuffer; // CPhipps - static
119int autorun = false; // always running? // phares
120int totalleveltimes; // CPhipps - total time for all completed levels
121int longtics;
122
123//
124// controls (have defaults)
125//
126int key_right;
127int key_left;
128int key_up;
129int key_down;
130int key_menu_right; // phares 3/7/98
131int key_menu_left; // |
132int key_menu_up; // V
133int key_menu_down;
134int key_menu_backspace; // ^
135int key_menu_escape; // |
136int key_menu_enter; // phares 3/7/98
137int key_strafeleft;
138int key_straferight;
139int key_fire;
140int key_use;
141int key_strafe;
142int key_speed;
143int key_escape = KEY_ESCAPE; // phares 4/13/98
144int key_weapon;
145
146int key_savegame; // phares
147int key_loadgame; // |
148int key_autorun; // V
149int key_reverse;
150int key_zoomin;
151int key_zoomout;
152
153int key_reverse;
154
155int key_chat;
156int key_backspace;
157int key_enter;
158int key_map_right;
159int key_map_left;
160int key_map_up;
161int key_map_down;
162int key_map_zoomin;
163int key_map_zoomout;
164int key_map;
165int key_map_gobig;
166int key_map_follow;
167int key_map_mark;
168int key_map_clear;
169int key_map_grid;
170int key_map_overlay; // cph - map overlay
171int key_map_rotate; // cph - map rotation
172int key_help = KEY_F1; // phares 4/13/98
173int key_soundvolume;
174int key_hud;
175int key_quicksave;
176int key_endgame;
177int key_messages;
178int key_quickload;
179int key_quit;
180int key_gamma;
181int key_spy;
182int key_pause;
183int key_setup;
184int destination_keys[MAXPLAYERS];
185int key_weapontoggle;
186int key_weapon1;
187int key_weapon2;
188int key_weapon3;
189int key_weapon4;
190int key_weapon5;
191int key_weapon6;
192int key_weapon7; // ^
193int key_weapon8; // |
194int key_weapon9; // phares
195
196int key_screenshot; // killough 2/22/98: screenshot key
197int mousebfire;
198int mousebstrafe;
199int mousebforward;
200int joybfire;
201int joybstrafe;
202int joybuse;
203int joybspeed;
204
205#define MAXPLMOVE (forwardmove[1])
206#define TURBOTHRESHOLD 0x32
207#define SLOWTURNTICS 6
208#define QUICKREVERSE (short)32768 // 180 degree reverse // phares
209#define NUMKEYS 512
210
211fixed_t forwardmove[2] = {0x19, 0x32};
212fixed_t sidemove[2] = {0x18, 0x28};
213fixed_t angleturn[3] = {640, 1280, 320}; // + slow turn
214
215// CPhipps - made lots of key/button state vars static
216static boolean gamekeydown[NUMKEYS];
217static int turnheld; // for accelerative turning
218
219static boolean mousearray[4];
220static boolean *mousebuttons = &mousearray[1]; // allow [-1]
221
222// mouse values are used once
223static int mousex;
224static int mousey;
225static unsigned int dclicktime;
226static unsigned int dclickstate;
227static unsigned int dclicks;
228static unsigned int dclicktime2;
229static unsigned int dclickstate2;
230static unsigned int dclicks2;
231
232// joystick values are repeated
233static int joyxmove;
234static int joyymove;
235static boolean joyarray[5];
236static boolean *joybuttons = &joyarray[1]; // allow [-1]
237
238// Game events info
239static buttoncode_t special_event; // Event triggered by local player, to send
240static byte savegameslot; // Slot to load if gameaction == ga_loadgame
241char savedescription[SAVEDESCLEN]; // Description to save in savegame if gameaction == ga_savegame
242
243//jff 3/24/98 declare startskill external, define defaultskill here
244extern skill_t startskill; //note 0-based
245int defaultskill; //note 1-based
246
247// killough 2/8/98: make corpse queue variable in size
248int bodyqueslot, bodyquesize; // killough 2/8/98
249mobj_t **bodyque = 0; // phares 8/10/98
250
251void* statcopy; // for statistics driver
252
253static void G_DoSaveGame (boolean menu);
254static const byte* G_ReadDemoHeader(const byte* demo_p);
255
256//
257// G_BuildTiccmd
258// Builds a ticcmd from all of the available inputs
259// or reads it from the demo buffer.
260// If recording a demo, write it out
261//
262static inline signed char fudgef(signed char b)
263{
264 static int c;
265 if (!b || !demo_compatibility || longtics) return b;
266 if (++c & 0x1f) return b;
267 b |= 1; if (b>2) b-=2;
268 return b;
269}
270
271static inline signed short fudgea(signed short b)
272{
273 if (!b || !demo_compatibility || !longtics) return b;
274 b |= 1; if (b>2) b-=2;
275 return b;
276}
277
278void G_BuildTiccmd(ticcmd_t* cmd)
279{
280 boolean strafe;
281 boolean bstrafe;
282 int speed;
283 int tspeed;
284 int forward;
285 int side;
286 int newweapon=0; // phares
287 /* cphipps - remove needless I_BaseTiccmd call, just set the ticcmd to zero */
288 memset(cmd,0,sizeof*cmd);
289 cmd->consistancy = consistancy[consoleplayer][maketic%BACKUPTICS];
290
291 strafe = gamekeydown[key_strafe] || mousebuttons[mousebstrafe]
292 || joybuttons[joybstrafe];
293 speed = autorun || gamekeydown[key_speed] || joybuttons[joybspeed]; // phares
294
295 forward = side = 0;
296
297 // use two stage accelerative turning
298 // on the keyboard and joystick
299 if (joyxmove < 0 || joyxmove > 0 ||
300 gamekeydown[key_right] || gamekeydown[key_left])
301 turnheld += ticdup;
302 else
303 turnheld = 0;
304
305 if (turnheld < SLOWTURNTICS)
306 tspeed = 2; // slow turn
307 else
308 tspeed = speed;
309
310 // turn 180 degrees in one keystroke? // phares
311 // |
312 if (gamekeydown[key_reverse]) // V
313 {
314 cmd->angleturn += QUICKREVERSE; // ^
315 gamekeydown[key_reverse] = false; // |
316 } // phares
317
318 // let movement keys cancel each other out
319
320 if (strafe)
321 {
322 if (gamekeydown[key_right])
323 side += sidemove[speed];
324 if (gamekeydown[key_left])
325 side -= sidemove[speed];
326 if (joyxmove > 0)
327 side += sidemove[speed];
328 if (joyxmove < 0)
329 side -= sidemove[speed];
330 }
331 else
332 {
333 if (gamekeydown[key_right])
334 cmd->angleturn -= angleturn[tspeed];
335 if (gamekeydown[key_left])
336 cmd->angleturn += angleturn[tspeed];
337 if (joyxmove > 0)
338 cmd->angleturn -= angleturn[tspeed];
339 if (joyxmove < 0)
340 cmd->angleturn += angleturn[tspeed];
341 }
342
343 if (gamekeydown[key_up])
344 forward += forwardmove[speed];
345 if (gamekeydown[key_down])
346 forward -= forwardmove[speed];
347 if (joyymove < 0)
348 forward += forwardmove[speed];
349 if (joyymove > 0)
350 forward -= forwardmove[speed];
351 if (gamekeydown[key_straferight])
352 side += sidemove[speed];
353 if (gamekeydown[key_strafeleft])
354 side -= sidemove[speed];
355
356 // buttons
357 cmd->chatchar = HU_dequeueChatChar();
358
359 if (gamekeydown[key_fire] || mousebuttons[mousebfire] ||
360 joybuttons[joybfire])
361 cmd->buttons |= BT_ATTACK;
362
363 if (gamekeydown[key_use] || joybuttons[joybuse])
364 {
365 cmd->buttons |= BT_USE;
366 // clear double clicks if hit use button
367 dclicks = 0;
368 }
369
370 // Toggle between the top 2 favorite weapons. // phares
371 // If not currently aiming one of these, switch to // phares
372 // the favorite. Only switch if you possess the weapon. // phares
373
374 // killough 3/22/98:
375 //
376 // Perform automatic weapons switch here rather than in p_pspr.c,
377 // except in demo_compatibility mode.
378 //
379 // killough 3/26/98, 4/2/98: fix autoswitch when no weapons are left
380
381 if ((!demo_compatibility && players[consoleplayer].attackdown && // killough
382 !P_CheckAmmo(&players[consoleplayer])) || gamekeydown[key_weapontoggle])
383 newweapon = P_SwitchWeapon(&players[consoleplayer]); // phares
384 else
385 { // phares 02/26/98: Added gamemode checks
386 if(gamekeydown[key_weapon])
387 {
388 volatile unsigned int wpcheck; // I don't know why this is needed, but it is
389 for(wpcheck=0; wpcheck<9; wpcheck++)
390 if(players[consoleplayer].weaponowned[wpcheck] && wpcheck>players[consoleplayer].readyweapon )
391 {
392 newweapon=wpcheck;
393 break;
394 }
395 if(players[consoleplayer].weaponowned[wp_chainsaw]&&newweapon==0)
396 newweapon=1;
397 }
398 else
399 {
400 newweapon =
401 gamekeydown[key_weapon1] ? wp_fist : // killough 5/2/98: reformatted
402 gamekeydown[key_weapon2] ? wp_pistol :
403 gamekeydown[key_weapon3] ? wp_shotgun :
404 gamekeydown[key_weapon4] ? wp_chaingun :
405 gamekeydown[key_weapon5] ? wp_missile :
406 gamekeydown[key_weapon6] && gamemode != shareware ? wp_plasma :
407 gamekeydown[key_weapon7] && gamemode != shareware ? wp_bfg :
408 gamekeydown[key_weapon8] ? wp_chainsaw :
409 gamekeydown[key_weapon9] && gamemode == commercial ? wp_supershotgun :
410 wp_nochange;
411 }
412
413 // killough 3/22/98: For network and demo consistency with the
414 // new weapons preferences, we must do the weapons switches here
415 // instead of in p_user.c. But for old demos we must do it in
416 // p_user.c according to the old rules. Therefore demo_compatibility
417 // determines where the weapons switch is made.
418
419 // killough 2/8/98:
420 // Allow user to switch to fist even if they have chainsaw.
421 // Switch to fist or chainsaw based on preferences.
422 // Switch to shotgun or SSG based on preferences.
423
424 if (!demo_compatibility)
425 {
426 const player_t *player = &players[consoleplayer];
427
428 // only select chainsaw from '1' if it's owned, it's
429 // not already in use, and the player prefers it or
430 // the fist is already in use, or the player does not
431 // have the berserker strength.
432
433 if (newweapon==wp_fist && player->weaponowned[wp_chainsaw] &&
434 player->readyweapon!=wp_chainsaw &&
435 (player->readyweapon==wp_fist ||
436 !player->powers[pw_strength] ||
437 P_WeaponPreferred(wp_chainsaw, wp_fist)))
438 newweapon = wp_chainsaw;
439
440 // Select SSG from '3' only if it's owned and the player
441 // does not have a shotgun, or if the shotgun is already
442 // in use, or if the SSG is not already in use and the
443 // player prefers it.
444 if(!gamekeydown[key_weapon])
445 if (newweapon == wp_shotgun && gamemode == commercial &&
446 player->weaponowned[wp_supershotgun] &&
447 (!player->weaponowned[wp_shotgun] ||
448 player->readyweapon == wp_shotgun ||
449 (player->readyweapon != wp_supershotgun &&
450 P_WeaponPreferred(wp_supershotgun, wp_shotgun))))
451 newweapon = wp_supershotgun;
452
453 }
454 // killough 2/8/98, 3/22/98 -- end of weapon selection changes
455 }
456
457 if(newweapon >wp_nochange) // something is messed up with the weapon switching code above allowing it to give values greater
458 { // then wp_nochange which really screws the game up
459 newweapon=0;
460 }
461 if (newweapon != wp_nochange)
462 {
463 cmd->buttons |= BT_CHANGE;
464 cmd->buttons |= newweapon<<BT_WEAPONSHIFT;
465 }
466
467 // mouse
468 if (mousebuttons[mousebforward])
469 forward += forwardmove[speed];
470
471 // forward double click
472 if (mousebuttons[mousebforward] != dclickstate && dclicktime > 1 )
473 {
474 dclickstate = mousebuttons[mousebforward];
475 if (dclickstate)
476 dclicks++;
477 if (dclicks == 2)
478 {
479 cmd->buttons |= BT_USE;
480 dclicks = 0;
481 }
482 else
483 dclicktime = 0;
484 }
485 else
486 if ((dclicktime += ticdup) > 20)
487 {
488 dclicks = 0;
489 dclickstate = 0;
490 }
491
492 // strafe double click
493
494 bstrafe = mousebuttons[mousebstrafe] || joybuttons[joybstrafe];
495 if (bstrafe != dclickstate2 && dclicktime2 > 1 )
496 {
497 dclickstate2 = bstrafe;
498 if (dclickstate2)
499 dclicks2++;
500 if (dclicks2 == 2)
501 {
502 cmd->buttons |= BT_USE;
503 dclicks2 = 0;
504 }
505 else
506 dclicktime2 = 0;
507 }
508 else
509 if ((dclicktime2 += ticdup) > 20)
510 {
511 dclicks2 = 0;
512 dclickstate2 = 0;
513 }
514 forward += mousey;
515 if (strafe)
516 side += mousex / 4; /* mead Don't want to strafe as fast as turns.*/
517 else
518 cmd->angleturn -= mousex; /* mead now have enough dynamic range 2-10-00 */
519
520 mousex = mousey = 0;
521
522 if (forward > MAXPLMOVE)
523 forward = MAXPLMOVE;
524 else if (forward < -MAXPLMOVE)
525 forward = -MAXPLMOVE;
526 if (side > MAXPLMOVE)
527 side = MAXPLMOVE;
528 else if (side < -MAXPLMOVE)
529 side = -MAXPLMOVE;
530
531 cmd->forwardmove += fudgef(forward);
532 cmd->sidemove += side;
533 cmd->angleturn = fudgea(cmd->angleturn);
534
535 // CPhipps - special events (game new/load/save/pause)
536 if (special_event & BT_SPECIAL) {
537 cmd->buttons = special_event;
538 special_event = 0;
539 }
540}
541
542//
543// G_RestartLevel
544//
545
546void G_RestartLevel(void)
547{
548 special_event = BT_SPECIAL | (BTS_RESTARTLEVEL & BT_SPECIALMASK);
549}
550
551#include "z_bmalloc.h"
552//
553// G_DoLoadLevel
554//
555extern gamestate_t wipegamestate;
556
557static void G_DoLoadLevel (void)
558{
559 int i;
560
561 // Set the sky map.
562 // First thing, we have a dummy sky texture name,
563 // a flat. The data is in the WAD only because
564 // we look for an actual index, instead of simply
565 // setting one.
566
567 skyflatnum = R_FlatNumForName ( SKYFLATNAME );
568
569 // DOOM determines the sky texture to be used
570 // depending on the current episode, and the game version.
571 if (gamemode == commercial)
572 // || gamemode == pack_tnt //jff 3/27/98 sorry guys pack_tnt,pack_plut
573 // || gamemode == pack_plut) //aren't gamemodes, this was matching retail
574 {
575 skytexture = R_TextureNumForName ("SKY3");
576 if (gamemap < 12)
577 skytexture = R_TextureNumForName ("SKY1");
578 else
579 if (gamemap < 21)
580 skytexture = R_TextureNumForName ("SKY2");
581 }
582 else //jff 3/27/98 and lets not forget about DOOM and Ultimate DOOM huh?
583 switch (gameepisode)
584 {
585 case 1:
586 skytexture = R_TextureNumForName ("SKY1");
587 break;
588 case 2:
589 skytexture = R_TextureNumForName ("SKY2");
590 break;
591 case 3:
592 skytexture = R_TextureNumForName ("SKY3");
593 break;
594 case 4: // Special Edition sky
595 skytexture = R_TextureNumForName ("SKY4");
596 break;
597 }//jff 3/27/98 end sky setting fix
598
599 levelstarttic = gametic; // for time calculation
600
601 if (!demo_compatibility && !mbf_features) // killough 9/29/98
602 basetic = gametic;
603
604 if (wipegamestate == GS_LEVEL)
605 wipegamestate = -1; // force a wipe
606
607 gamestate = GS_LEVEL;
608
609 for (i=0 ; i<MAXPLAYERS ; i++)
610 {
611 if (playeringame[i] && players[i].playerstate == PST_DEAD)
612 players[i].playerstate = PST_REBORN;
613 memset (players[i].frags,0,sizeof(players[i].frags));
614 }
615
616 // initialize the msecnode_t freelist. phares 3/25/98
617 // any nodes in the freelist are gone by now, cleared
618 // by Z_FreeTags() when the previous level ended or player
619 // died.
620
621 {
622 DECLARE_BLOCK_MEMORY_ALLOC_ZONE(secnodezone);
623 NULL_BLOCK_MEMORY_ALLOC_ZONE(secnodezone);
624 //extern msecnode_t *headsecnode; // phares 3/25/98
625 //headsecnode = NULL;
626 }
627
628 P_SetupLevel (gameepisode, gamemap, 0, gameskill);
629 displayplayer = consoleplayer; // view the guy you are playing
630 gameaction = ga_nothing;
631 Z_CheckHeap ();
632
633 // clear cmd building stuff
634 memset (gamekeydown, 0, sizeof(gamekeydown));
635 joyxmove = joyymove = 0;
636 mousex = mousey = 0;
637 special_event = 0; paused = false;
638 memset (mousebuttons, 0, sizeof(mousebuttons));
639 memset (joybuttons, 0, sizeof(joybuttons));
640
641 // killough 5/13/98: in case netdemo has consoleplayer other than green
642 ST_Start();
643 HU_Start();
644
645 // killough: make -timedemo work on multilevel demos
646 // Move to end of function to minimize noise -- killough 2/22/98:
647
648 if (timingdemo)
649 {
650 static int first=1;
651 if (first)
652 {
653 starttime = I_GetTime ();
654 first=0;
655 }
656 }
657}
658
659//
660// G_Responder
661// Get info needed to make ticcmd_ts for the players.
662//
663boolean G_Responder (event_t* ev)
664{
665 // allow spy mode changes even during the demo
666 // killough 2/22/98: even during DM demo
667 //
668 // killough 11/98: don't autorepeat spy mode switch
669
670 if (ev->data1 == key_spy && netgame && (demoplayback || !deathmatch) &&
671 gamestate == GS_LEVEL)
672 {
673 if (ev->type == ev_keyup)
674 gamekeydown[key_spy] = false;
675 if (ev->type == ev_keydown && !gamekeydown[key_spy])
676 {
677 gamekeydown[key_spy] = true;
678 do // spy mode
679 if (++displayplayer >= MAXPLAYERS)
680 displayplayer = 0;
681 while (!playeringame[displayplayer] && displayplayer!=consoleplayer);
682
683 ST_Start(); // killough 3/7/98: switch status bar views too
684 HU_Start();
685 S_UpdateSounds(players[displayplayer].mo);
686 }
687 return true;
688 }
689
690 // any other key pops up menu if in demos
691 //
692 // killough 8/2/98: enable automap in -timedemo demos
693 //
694 // killough 9/29/98: make any key pop up menu regardless of
695 // which kind of demo, and allow other events during playback
696
697 if (gameaction == ga_nothing && (demoplayback || gamestate == GS_DEMOSCREEN))
698 {
699 // killough 9/29/98: allow user to pause demos during playback
700 if (ev->type == ev_keydown && ev->data1 == key_pause)
701 {
702 if (paused ^= 2)
703 S_PauseSound();
704 else
705 S_ResumeSound();
706 return true;
707 }
708 // killough 10/98:
709 // Don't pop up menu, if paused in middle
710 // of demo playback, or if automap active.
711 // Don't suck up keys, which may be cheats
712
713 return gamestate == GS_DEMOSCREEN &&
714 !(paused & 2) && !(automapmode & am_active) &&
715 ((ev->type == ev_keydown) ||
716 (ev->type == ev_mouse && ev->data1) ||
717 (ev->type == ev_joystick && ev->data1)) ?
718 M_StartControlPanel(), true : false;
719 }
720
721 if (gamestate == GS_FINALE && F_Responder(ev))
722 return true; // finale ate the event
723
724 switch (ev->type)
725 {
726 case ev_keydown:
727 if (ev->data1 == key_pause) // phares
728 {
729 special_event = BT_SPECIAL | (BTS_PAUSE & BT_SPECIALMASK);
730 return true;
731 }
732 if (ev->data1 <NUMKEYS)
733 gamekeydown[ev->data1] = true;
734 return true; // eat key down events
735
736 case ev_keyup:
737 if (ev->data1 <NUMKEYS)
738 gamekeydown[ev->data1] = false;
739 return false; // always let key up events filter down
740
741 case ev_mouse:
742 mousebuttons[0] = ev->data1 & 1;
743 mousebuttons[1] = ev->data1 & 2;
744 mousebuttons[2] = ev->data1 & 4;
745// mousex = ev->data2*(mouseSensitivity+5)/10;
746// mousey = ev->data3*(mouseSensitivity+5)/10;
747 return true; // eat events
748
749 case ev_joystick:
750 joybuttons[0] = ev->data1 & 1;
751 joybuttons[1] = ev->data1 & 2;
752 joybuttons[2] = ev->data1 & 4;
753 joybuttons[3] = ev->data1 & 8;
754 joyxmove = ev->data2;
755 joyymove = ev->data3;
756 return true; // eat events
757
758 default:
759 break;
760 }
761 return false;
762}
763
764//
765// G_Ticker
766// Make ticcmd_ts for the players.
767//
768extern int mapcolor_me;
769
770void G_Ticker (void)
771{
772 int i;
773 static gamestate_t prevgamestate;
774
775 P_MapStart();
776 // do player reborns if needed
777 for (i=0 ; i<MAXPLAYERS ; i++)
778 if (playeringame[i] && players[i].playerstate == PST_REBORN)
779 G_DoReborn (i);
780 P_MapEnd();
781
782 // do things to change the game state
783 while (gameaction != ga_nothing)
784 {
785 switch (gameaction)
786 {
787 case ga_loadlevel:
788 // force players to be initialized on level reload
789 for (i=0 ; i<MAXPLAYERS ; i++)
790 players[i].playerstate = PST_REBORN;
791 G_DoLoadLevel ();
792 break;
793 case ga_newgame:
794 G_DoNewGame ();
795 break;
796 case ga_loadgame:
797 G_DoLoadGame ();
798 break;
799 case ga_savegame:
800 G_DoSaveGame (false);
801 break;
802 case ga_playdemo:
803 G_DoPlayDemo ();
804 break;
805 case ga_completed:
806 G_DoCompleted ();
807 break;
808 case ga_victory:
809 F_StartFinale ();
810 break;
811 case ga_worlddone:
812 G_DoWorldDone ();
813 break;
814 case ga_nothing:
815 break;
816 }
817 }
818
819 if (paused & 2 || (!demoplayback && menuactive && !netgame))
820 basetic++; // For revenant tracers and RNG -- we must maintain sync
821 else
822 {
823 // get commands, check consistancy, and build new consistancy check
824 int buf = (gametic/ticdup)%BACKUPTICS;
825
826 for (i=0 ; i<MAXPLAYERS ; i++)
827 {
828 if (playeringame[i])
829 {
830 ticcmd_t *cmd = &players[i].cmd;
831
832 memcpy(cmd, &netcmds[i][buf], sizeof *cmd);
833
834 if (demoplayback)
835 G_ReadDemoTiccmd (cmd);
836 if (demorecording)
837 G_WriteDemoTiccmd (cmd);
838
839 // check for turbo cheats
840 // killough 2/14/98, 2/20/98 -- only warn in netgames and demos
841
842 if ((netgame || demoplayback) && cmd->forwardmove > TURBOTHRESHOLD &&
843 !(gametic&31) && ((gametic>>5)&3) == i )
844 {
845 extern char *player_names[];
846 /* cph - don't use sprintf, use doom_printf */
847 doom_printf ("%s is turbo!", player_names[i]);
848 }
849
850 if (netgame && !netdemo && !(gametic%ticdup) )
851 {
852 if (gametic > BACKUPTICS
853 && consistancy[i][buf] != cmd->consistancy)
854 I_Error("G_Ticker: Consistency failure (%i should be %i)",
855 cmd->consistancy, consistancy[i][buf]);
856 if (players[i].mo)
857 consistancy[i][buf] = players[i].mo->x;
858 else
859 consistancy[i][buf] = 0; // killough 2/14/98
860 }
861 }
862 }
863
864 // check for special buttons
865 for (i=0 ; i<MAXPLAYERS ; i++)
866 {
867 if (playeringame[i])
868 {
869 if (players[i].cmd.buttons & BT_SPECIAL)
870 {
871 switch (players[i].cmd.buttons & BT_SPECIALMASK)
872 {
873 case BTS_PAUSE:
874 paused ^= 1;
875 if (paused)
876 S_PauseSound ();
877 else
878 S_ResumeSound ();
879 break;
880
881 case BTS_SAVEGAME:
882 if (!savedescription[0])
883 strcpy(savedescription, "NET GAME");
884 savegameslot =
885 (players[i].cmd.buttons & BTS_SAVEMASK)>>BTS_SAVESHIFT;
886 gameaction = ga_savegame;
887 break;
888
889 // CPhipps - remote loadgame request
890 case BTS_LOADGAME:
891 savegameslot =
892 (players[i].cmd.buttons & BTS_SAVEMASK)>>BTS_SAVESHIFT;
893 gameaction = ga_loadgame;
894 forced_loadgame = netgame; // Force if a netgame
895 command_loadgame = false;
896 break;
897
898 // CPhipps - Restart the level
899 case BTS_RESTARTLEVEL:
900 if (demoplayback || (compatibility_level < lxdoom_1_compatibility))
901 break; // CPhipps - Ignore in demos or old games
902 gameaction = ga_loadlevel;
903 break;
904 }
905 players[i].cmd.buttons = 0;
906 }
907 }
908 }
909 }
910
911 // cph - if the gamestate changed, we may need to clean up the old gamestate
912 if (gamestate != prevgamestate) {
913 switch (prevgamestate) {
914 case GS_INTERMISSION:
915 WI_End();
916 default:
917 break;
918 }
919 prevgamestate = gamestate;
920 }
921
922 // do main actions
923 switch (gamestate)
924 {
925 case GS_LEVEL:
926 P_Ticker ();
927 ST_Ticker ();
928 AM_Ticker ();
929 HU_Ticker ();
930 break;
931
932 case GS_INTERMISSION:
933 WI_Ticker ();
934 break;
935
936 case GS_FINALE:
937 F_Ticker ();
938 break;
939
940 case GS_DEMOSCREEN:
941 D_PageTicker ();
942 break;
943 }
944}
945
946
947//
948// PLAYER STRUCTURE FUNCTIONS
949// also see P_SpawnPlayer in P_Things
950//
951
952//
953// G_PlayerFinishLevel
954// Can when a player completes a level.
955//
956void G_PlayerFinishLevel(int player)
957{
958 player_t *p = &players[player];
959 memset(p->powers, 0, sizeof (p->powers));
960 memset(p->cards, 0, sizeof (p->cards));
961 p->mo->flags &= ~MF_SHADOW; // cancel invisibility
962 p->extralight = 0; // cancel gun flashes
963 p->fixedcolormap = 0; // cancel ir gogles
964 p->damagecount = 0; // no palette changes
965 p->bonuscount = 0;
966}
967
968// CPhipps - G_SetPlayerColour
969// Player colours stuff
970//
971// G_SetPlayerColour
972
973#include "r_draw.h"
974extern byte playernumtotrans[MAXPLAYERS];
975
976void G_ChangedPlayerColour(int pn, int cl)
977{
978 int i;
979
980 if (!netgame) return;
981
982 mapcolor_plyr[pn] = cl;
983
984 // Rebuild colour translation tables accordingly
985 R_InitTranslationTables();
986 // Change translations on existing player mobj's
987 for (i=0; i<MAXPLAYERS; i++) {
988 if ((gamestate == GS_LEVEL) && playeringame[i] && (players[i].mo != NULL)) {
989 players[i].mo->flags &= ~MF_TRANSLATION;
990 players[i].mo->flags |= playernumtotrans[i] << MF_TRANSSHIFT;
991 }
992 }
993}
994
995//
996// G_PlayerReborn
997// Called after a player dies
998// almost everything is cleared and initialized
999//
1000void G_PlayerReborn (int player)
1001{
1002 player_t *p;
1003 int i;
1004 int frags[MAXPLAYERS];
1005 int killcount;
1006 int itemcount;
1007 int secretcount;
1008
1009 memcpy (frags, players[player].frags, sizeof frags);
1010 killcount = players[player].killcount;
1011 itemcount = players[player].itemcount;
1012 secretcount = players[player].secretcount;
1013
1014 p = &players[player];
1015
1016 // killough 3/10/98,3/21/98: preserve cheats across idclev
1017 {
1018 int cheats = p->cheats;
1019 memset (p, 0, sizeof(*p));
1020 p->cheats = cheats;
1021 }
1022
1023 memcpy(players[player].frags, frags, sizeof(players[player].frags));
1024 players[player].killcount = killcount;
1025 players[player].itemcount = itemcount;
1026 players[player].secretcount = secretcount;
1027
1028 p->usedown = p->attackdown = true; // don't do anything immediately
1029 p->playerstate = PST_LIVE;
1030 p->health = MAXHEALTH;
1031 p->readyweapon = p->pendingweapon = wp_pistol;
1032 p->weaponowned[wp_fist] = true;
1033 p->weaponowned[wp_pistol] = true;
1034 p->ammo[am_clip] = 50;
1035
1036 for (i=0 ; i<NUMAMMO ; i++)
1037 p->maxammo[i] = maxammo[i];
1038
1039}
1040
1041//
1042// G_CheckSpot
1043// Returns false if the player cannot be respawned
1044// at the given mapthing_t spot
1045// because something is occupying it
1046//
1047
1048void P_SpawnPlayer(mapthing_t *mthing);
1049
1050boolean G_CheckSpot(int playernum, mapthing_t *mthing)
1051{
1052 fixed_t x,y;
1053 subsector_t *ss;
1054 int i;
1055
1056 if (!players[playernum].mo)
1057 {
1058 // first spawn of level, before corpses
1059 for (i=0 ; i<playernum ; i++)
1060 if (players[i].mo->x == mthing->x << FRACBITS
1061 && players[i].mo->y == mthing->y << FRACBITS)
1062 return false;
1063 return true;
1064 }
1065
1066 x = mthing->x << FRACBITS;
1067 y = mthing->y << FRACBITS;
1068
1069 // killough 4/2/98: fix bug where P_CheckPosition() uses a non-solid
1070 // corpse to detect collisions with other players in DM starts
1071 //
1072 // Old code:
1073 // if (!P_CheckPosition (players[playernum].mo, x, y))
1074 // return false;
1075
1076 players[playernum].mo->flags |= MF_SOLID;
1077 i = P_CheckPosition(players[playernum].mo, x, y);
1078 players[playernum].mo->flags &= ~MF_SOLID;
1079 if (!i)
1080 return false;
1081
1082 // flush an old corpse if needed
1083 // killough 2/8/98: make corpse queue have an adjustable limit
1084 // killough 8/1/98: Fix bugs causing strange crashes
1085
1086 if (bodyquesize > 0)
1087 {
1088 static mobj_t **bodyque;
1089 static int queuesize;
1090 if (queuesize < bodyquesize)
1091 {
1092 bodyque = realloc(bodyque, bodyquesize*sizeof*bodyque);
1093 memset(bodyque+queuesize, 0,
1094 (bodyquesize-queuesize)*sizeof*bodyque);
1095 queuesize = bodyquesize;
1096 }
1097 if (bodyqueslot >= bodyquesize)
1098 P_RemoveMobj(bodyque[bodyqueslot % bodyquesize]);
1099 bodyque[bodyqueslot++ % bodyquesize] = players[playernum].mo;
1100 }
1101 else
1102 if (!bodyquesize)
1103 P_RemoveMobj(players[playernum].mo);
1104
1105 // spawn a teleport fog
1106 ss = R_PointInSubsector (x,y);
1107 { // Teleport fog at respawn point
1108 fixed_t xa=0,ya=0;
1109 int an;
1110 mobj_t *mo;
1111
1112 /* BUG: an can end up negative, because mthing->angle is (signed) short.
1113 * We have to emulate original Doom's behaviour, deferencing past the start
1114 * of the array, into the previous array (finetangent) */
1115 an = ( ANG45 * ((signed)mthing->angle/45) ) >> ANGLETOFINESHIFT;
1116 switch (an) {
1117 case -4096: xa = finetangent[2048]; // finecosine[-4096]
1118 ya = finetangent[0]; // finesine[-4096]
1119 break;
1120 case -3072: xa = finetangent[3072]; // finecosine[-3072]
1121 ya = finetangent[1024]; // finesine[-3072]
1122 break;
1123 case -2048: xa = finesine[0]; // finecosine[-2048]
1124 ya = finetangent[2048]; // finesine[-2048]
1125 break;
1126 case -1024: xa = finesine[1024]; // finecosine[-1024]
1127 ya = finetangent[3072]; // finesine[-1024]
1128 break;
1129 case 1024:
1130 case 2048:
1131 case 3072:
1132 case 4096:
1133 case 0: xa = finecosine[an];
1134 ya = finesine[an];
1135 break;
1136 default: I_Error("G_CheckSpot: unexpected angle %d\n",an);
1137 }
1138
1139
1140 mo = P_SpawnMobj(x+20*xa, y+20*ya, ss->sector->floorheight, MT_TFOG);
1141
1142 if (players[consoleplayer].viewz != 1)
1143 S_StartSound(mo, sfx_telept); // don't start sound on first frame
1144 }
1145
1146 return true;
1147}
1148
1149
1150//
1151// G_DeathMatchSpawnPlayer
1152// Spawns a player at one of the random death match spots
1153// called at level load and each death
1154//
1155void G_DeathMatchSpawnPlayer (int playernum)
1156{
1157 int j, selections = deathmatch_p - deathmatchstarts;
1158
1159 if (selections < MAXPLAYERS)
1160 I_Error("G_DeathMatchSpawnPlayer: Only %i deathmatch spots, %d required",
1161 selections, MAXPLAYERS);
1162
1163 for (j=0 ; j<20 ; j++)
1164 {
1165 int i = P_Random(pr_dmspawn) % selections;
1166 if (G_CheckSpot (playernum, &deathmatchstarts[i]) )
1167 {
1168 deathmatchstarts[i].type = playernum+1;
1169 P_SpawnPlayer (&deathmatchstarts[i]);
1170 return;
1171 }
1172 }
1173
1174 // no good spot, so the player will probably get stuck
1175 P_SpawnPlayer (&playerstarts[playernum]);
1176}
1177
1178//
1179// G_DoReborn
1180//
1181
1182void G_DoReborn (int playernum)
1183{
1184 if (!netgame)
1185 gameaction = ga_loadlevel; // reload the level from scratch
1186 else
1187 { // respawn at the start
1188 int i;
1189
1190 // first dissasociate the corpse
1191 players[playernum].mo->player = NULL;
1192
1193 // spawn at random spot if in death match
1194 if (deathmatch)
1195 {
1196 G_DeathMatchSpawnPlayer (playernum);
1197 return;
1198 }
1199
1200 if (G_CheckSpot (playernum, &playerstarts[playernum]) )
1201 {
1202 P_SpawnPlayer (&playerstarts[playernum]);
1203 return;
1204 }
1205
1206 // try to spawn at one of the other players spots
1207 for (i=0 ; i<MAXPLAYERS ; i++)
1208 {
1209 if (G_CheckSpot (playernum, &playerstarts[i]) )
1210 {
1211 playerstarts[i].type = playernum+1; // fake as other player
1212 P_SpawnPlayer (&playerstarts[i]);
1213 playerstarts[i].type = i+1; // restore
1214 return;
1215 }
1216 // he's going to be inside something. Too bad.
1217 }
1218 P_SpawnPlayer (&playerstarts[playernum]);
1219 }
1220}
1221
1222// DOOM Par Times
1223int pars[4][10] =
1224 {
1225 {0},
1226 {0,30,75,120,90,165,180,180,30,165},
1227 {0,90,90,90,120,90,360,240,30,170},
1228 {0,90,45,90,150,90,90,165,30,135}
1229 };
1230
1231// DOOM II Par Times
1232int cpars[32] =
1233 {
1234 30,90,120,120,90,150,120,120,270,90, // 1-10
1235 210,150,150,150,210,150,420,150,210,150, // 11-20
1236 240,150,180,150,150,300,330,420,300,180, // 21-30
1237 120,30 // 31-32
1238 };
1239
1240static boolean secretexit;
1241
1242void G_ExitLevel (void)
1243{
1244 secretexit = false;
1245 gameaction = ga_completed;
1246}
1247
1248// Here's for the german edition.
1249// IF NO WOLF3D LEVELS, NO SECRET EXIT!
1250
1251void G_SecretExitLevel (void)
1252{
1253 if (gamemode!=commercial || haswolflevels)
1254 secretexit = true;
1255 else
1256 secretexit = false;
1257 gameaction = ga_completed;
1258}
1259
1260//
1261// G_DoCompleted
1262//
1263
1264void G_DoCompleted (void)
1265{
1266 int i;
1267
1268 gameaction = ga_nothing;
1269
1270 for (i=0; i<MAXPLAYERS; i++)
1271 if (playeringame[i])
1272 G_PlayerFinishLevel(i); // take away cards and stuff
1273
1274 if (automapmode & am_active)
1275 AM_Stop();
1276
1277 if (gamemode != commercial) // kilough 2/7/98
1278 switch(gamemap)
1279 {
1280 // cph - Remove ExM8 special case, so it gets summary screen displayed
1281 case 9:
1282 for (i=0 ; i<MAXPLAYERS ; i++)
1283 players[i].didsecret = true;
1284 break;
1285 }
1286
1287 wminfo.didsecret = players[consoleplayer].didsecret;
1288 wminfo.epsd = gameepisode -1;
1289 wminfo.last = gamemap -1;
1290
1291 // wminfo.next is 0 biased, unlike gamemap
1292 if (gamemode == commercial)
1293 {
1294 if (secretexit)
1295 switch(gamemap)
1296 {
1297 case 15:
1298 wminfo.next = 30; break;
1299 case 31:
1300 wminfo.next = 31; break;
1301 }
1302 else
1303 switch(gamemap)
1304 {
1305 case 31:
1306 case 32:
1307 wminfo.next = 15; break;
1308 default:
1309 wminfo.next = gamemap;
1310 }
1311 }
1312 else
1313 {
1314 if (secretexit)
1315 wminfo.next = 8; // go to secret level
1316 else
1317 if (gamemap == 9)
1318 {
1319 // returning from secret level
1320 switch (gameepisode)
1321 {
1322 case 1:
1323 wminfo.next = 3;
1324 break;
1325 case 2:
1326 wminfo.next = 5;
1327 break;
1328 case 3:
1329 wminfo.next = 6;
1330 break;
1331 case 4:
1332 wminfo.next = 2;
1333 break;
1334 }
1335 }
1336 else
1337 wminfo.next = gamemap; // go to next level
1338 }
1339
1340 wminfo.maxkills = totalkills;
1341 wminfo.maxitems = totalitems;
1342 wminfo.maxsecret = totalsecret;
1343 wminfo.maxfrags = 0;
1344
1345 if ( gamemode == commercial )
1346 wminfo.partime = TICRATE*cpars[gamemap-1];
1347 else
1348 wminfo.partime = TICRATE*pars[gameepisode][gamemap];
1349
1350 wminfo.pnum = consoleplayer;
1351
1352 for (i=0 ; i<MAXPLAYERS ; i++)
1353 {
1354 wminfo.plyr[i].in = playeringame[i];
1355 wminfo.plyr[i].skills = players[i].killcount;
1356 wminfo.plyr[i].sitems = players[i].itemcount;
1357 wminfo.plyr[i].ssecret = players[i].secretcount;
1358 wminfo.plyr[i].stime = leveltime;
1359 memcpy (wminfo.plyr[i].frags, players[i].frags,
1360 sizeof(wminfo.plyr[i].frags));
1361 }
1362
1363 /* cph - modified so that only whole seconds are added to the totalleveltimes
1364 * value; so our total is compatible with the "naive" total of just adding
1365 * the times in seconds shown for each level. Also means our total time
1366 * will agree with Compet-n.
1367 */
1368 wminfo.totaltimes = (totalleveltimes += (leveltime - leveltime%35));
1369
1370 gamestate = GS_INTERMISSION;
1371 automapmode &= ~am_active;
1372
1373 if (statcopy)
1374 memcpy (statcopy, &wminfo, sizeof(wminfo));
1375
1376 WI_Start (&wminfo);
1377}
1378
1379
1380//
1381// G_WorldDone
1382//
1383
1384void G_WorldDone (void)
1385{
1386 gameaction = ga_worlddone;
1387
1388 if (secretexit)
1389 players[consoleplayer].didsecret = true;
1390
1391 if (gamemode == commercial)
1392 {
1393 switch (gamemap)
1394 {
1395 case 15:
1396 case 31:
1397 if (!secretexit)
1398 break;
1399 case 6:
1400 case 11:
1401 case 20:
1402 case 30:
1403 F_StartFinale ();
1404 break;
1405 }
1406 }
1407 else if (gamemap == 8)
1408 gameaction = ga_victory; // cph - after ExM8 summary screen, show victory stuff
1409}
1410
1411void G_DoWorldDone (void)
1412{
1413 idmusnum = -1; //jff 3/17/98 allow new level's music to be loaded
1414 gamestate = GS_LEVEL;
1415 gamemap = wminfo.next+1;
1416 G_DoLoadLevel();
1417 gameaction = ga_nothing;
1418 AM_clearMarks(); //jff 4/12/98 clear any marks on the automap
1419}
1420
1421// killough 2/28/98: A ridiculously large number
1422// of players, the most you'll ever need in a demo
1423// or savegame. This is used to prevent problems, in
1424// case more players in a game are supported later.
1425
1426#define MIN_MAXPLAYERS 32
1427
1428extern boolean setsizeneeded;
1429void R_ExecuteSetViewSize(void);
1430
1431//CPhipps - savename variable redundant
1432
1433/* killough 12/98:
1434 * This function returns a signature for the current wad.
1435 * It is used to distinguish between wads, for the purposes
1436 * of savegame compatibility warnings, and options lookups.
1437 */
1438
1439static uint_64_t G_UpdateSignature(uint_64_t s, const char *name)
1440{
1441 int i, lump = W_CheckNumForName(name);
1442 if (lump != -1 && (i = lump+10) < numlumps)
1443 do
1444 {
1445 int size = W_LumpLength(i);
1446 const byte *p = W_CacheLumpNum(i);
1447 while (size--)
1448 s <<= 1, s += *p++;
1449 W_UnlockLumpNum(i);
1450 }
1451 while (--i > lump);
1452 return s;
1453}
1454
1455static uint_64_t G_Signature(void)
1456{
1457 static uint_64_t s = 0;
1458 static boolean computed = false;
1459 char name[9];
1460 int episode, map;
1461
1462 if (!computed) {
1463 computed = true;
1464 if (gamemode == commercial)
1465 for (map = haswolflevels ? 32 : 30; map; map--)
1466 snprintf(name, sizeof(name), "map%02d", map), s = G_UpdateSignature(s, name);
1467 else
1468 for (episode = gamemode==retail ? 4 :
1469 gamemode==shareware ? 1 : 3; episode; episode--)
1470 for (map = 9; map; map--)
1471 snprintf(name, sizeof(name), "E%dM%d", episode, map), s = G_UpdateSignature(s, name);
1472 }
1473 return s;
1474}
1475
1476//
1477// killough 5/15/98: add forced loadgames, which allow user to override checks
1478//
1479
1480void G_ForcedLoadGame(void)
1481{
1482 // CPhipps - net loadgames are always forced, so we only reach here
1483 // in single player
1484 gameaction = ga_loadgame;
1485 forced_loadgame = true;
1486}
1487
1488// killough 3/16/98: add slot info
1489// killough 5/15/98: add command-line
1490void G_LoadGame(int slot, boolean command)
1491{
1492 if (!demoplayback && !command) {
1493 // CPhipps - handle savegame filename in G_DoLoadGame
1494 // - Delay load so it can be communicated in net game
1495 // - store info in special_event
1496 special_event = BT_SPECIAL | (BTS_LOADGAME & BT_SPECIALMASK) |
1497 ((slot << BTS_SAVESHIFT) & BTS_SAVEMASK);
1498 forced_loadgame = netgame; // CPhipps - always force load netgames
1499 } else {
1500 // Do the old thing, immediate load
1501 gameaction = ga_loadgame;
1502 forced_loadgame = false;
1503 savegameslot = slot;
1504 demoplayback = false;
1505 }
1506 command_loadgame = command;
1507}
1508
1509// killough 5/15/98:
1510// Consistency Error when attempting to load savegame.
1511
1512static void G_LoadGameErr(const char *msg)
1513{
1514 (void) msg; // Need to fix, but right now we're ignoring a forced load
1515 Z_Free(savebuffer); // Free the savegame buffer
1516// M_ForcedLoadGame(msg); // Print message asking for 'Y' to force
1517 if (command_loadgame) // If this was a command-line -loadgame
1518 {
1519 D_StartTitle(); // Start the title screen
1520 gamestate = GS_DEMOSCREEN; // And set the game state accordingly
1521 }
1522}
1523
1524// CPhipps - size of version header
1525#define VERSIONSIZE 16
1526
1527const char * comp_lev_str[MAX_COMPATIBILITY_LEVEL] =
1528 { "doom v1.2", "demo", "doom", "\"boom compatibility\"", "boom v2.01", "boom v2.02", "lxdoom v1.3.2+",
1529 "MBF", "PrBoom 2.03beta", "PrBoom v2.1.0-2.1.1",
1530 "Current PrBoom" };
1531
1532static const struct {
1533 unsigned int comp_level;
1534 const char* ver_printf;
1535 int version;
1536} version_headers[] = {
1537 { prboom_1_compatibility, "PrBoom %d", 260},
1538 /* cph - we don't need a new version_header for prboom_3_comp/v2.1.1, since
1539 * the file format is unchanged. */
1540 { prboom_3_compatibility, "PrBoom %d", 210}
1541 };
1542
1543static const size_t num_version_headers = sizeof(version_headers) / sizeof(version_headers[0]);
1544
1545void G_DoLoadGame(void)
1546{
1547 int length, i;
1548 // CPhipps - do savegame filename stuff here
1549 char name[100+1]; // killough 3/22/98
1550 int savegame_compatibility = -1;
1551
1552 G_SaveGameName(name,sizeof(name),savegameslot, demoplayback);
1553
1554 gameaction = ga_nothing;
1555
1556 length = M_ReadFile(name, &savebuffer);
1557 save_p = savebuffer + SAVESTRINGSIZE;
1558
1559 // CPhipps - read the description field, compare with supported ones
1560 for (i=0; (size_t)i<num_version_headers; i++) {
1561 char vcheck[VERSIONSIZE];
1562 // killough 2/22/98: "proprietary" version string :-)
1563 snprintf (vcheck,sizeof(vcheck), version_headers[i].ver_printf, version_headers[i].version);
1564
1565 if (!strncmp(save_p, vcheck, VERSIONSIZE)) {
1566 savegame_compatibility = version_headers[i].comp_level;
1567 i = num_version_headers;
1568 }
1569 }
1570 if (savegame_compatibility == -1) {
1571 if (forced_loadgame) {
1572 savegame_compatibility = MAX_COMPATIBILITY_LEVEL-1;
1573 } else {
1574 G_LoadGameErr("Unrecognised savegame version!\nAre you sure? (y/n) ");
1575 return;
1576 }
1577 }
1578
1579 save_p += VERSIONSIZE;
1580
1581 // CPhipps - always check savegames even when forced,
1582 // only print a warning if forced
1583 { // killough 3/16/98: check lump name checksum (independent of order)
1584 uint_64_t checksum = 0;
1585
1586 checksum = G_Signature();
1587
1588 if (memcmp(&checksum, save_p, sizeof checksum)) {
1589 if (!forced_loadgame) {
1590 char *msg = malloc(strlen(save_p + sizeof checksum) + 128);
1591 strcpy(msg,"Incompatible Savegame!!!\n");
1592 if (save_p[sizeof checksum])
1593 strcat(strcat(msg,"Wads expected:\n\n"), save_p + sizeof checksum);
1594 strcat(msg, "\nAre you sure?");
1595 G_LoadGameErr(msg);
1596 free(msg);
1597 return;
1598 } else
1599 printf("G_DoLoadGame: Incompatible savegame\n");
1600 }
1601 save_p += sizeof checksum;
1602 }
1603
1604 save_p += strlen(save_p)+1;
1605
1606 /* cph - FIXME - compatibility flag? */
1607 compatibility_level = savegame_compatibility;
1608 save_p++;
1609
1610 gameskill = *save_p++;
1611 gameepisode = *save_p++;
1612 gamemap = *save_p++;
1613
1614 for (i=0 ; i<MAXPLAYERS ; i++)
1615 playeringame[i] = *save_p++;
1616 save_p += MIN_MAXPLAYERS-MAXPLAYERS; // killough 2/28/98
1617
1618 idmusnum = *save_p++; // jff 3/17/98 restore idmus music
1619 if (idmusnum==255) idmusnum=-1; // jff 3/18/98 account for unsigned byte
1620
1621 /* killough 3/1/98: Read game options
1622 * killough 11/98: move down to here
1623 */
1624 save_p = (char*)G_ReadOptions(save_p);
1625
1626 // load a base level
1627 G_InitNew (gameskill, gameepisode, gamemap);
1628
1629 /* get the times - killough 11/98: save entire word */
1630 memcpy(&leveltime, save_p, sizeof leveltime);
1631 save_p += sizeof leveltime;
1632
1633 /* cph - total episode time */
1634 if (compatibility_level >= prboom_2_compatibility) {
1635 memcpy(&totalleveltimes, save_p, sizeof totalleveltimes);
1636 save_p += sizeof totalleveltimes;
1637 }
1638 else totalleveltimes = 0;
1639
1640 // killough 11/98: load revenant tracer state
1641 basetic = gametic - *save_p++;
1642
1643 // dearchive all the modifications
1644 P_UnArchivePlayers ();
1645 P_UnArchiveWorld ();
1646 P_UnArchiveThinkers ();
1647 P_UnArchiveSpecials ();
1648 P_UnArchiveRNG (); // killough 1/18/98: load RNG information
1649 P_UnArchiveMap (); // killough 1/22/98: load automap information
1650
1651 if (*save_p != 0xe6)
1652 I_Error ("G_DoLoadGame: Bad savegame");
1653
1654 // done
1655 Z_Free (savebuffer);
1656
1657 if (setsizeneeded)
1658 R_ExecuteSetViewSize ();
1659
1660 // draw the pattern into the back screen
1661 R_FillBackScreen ();
1662
1663 /* killough 12/98: support -recordfrom and -loadgame -playdemo */
1664 if (!command_loadgame)
1665 singledemo = false; /* Clear singledemo flag if loading from menu */
1666 else
1667 if (singledemo) {
1668 gameaction = ga_loadgame; /* Mark that we're loading a game before demo */
1669 G_DoPlayDemo(); /* This will detect it and won't reinit level */
1670 } else /* Command line + record means it's a recordfrom */
1671 if (demorecording)
1672 G_BeginRecording();
1673}
1674
1675//
1676// G_SaveGame
1677// Called by the menu task.
1678// Description is a 24 byte text string
1679//
1680
1681void G_SaveGame(int slot, char *description)
1682{
1683 strcpy(savedescription, description);
1684 if (demoplayback) {
1685 /* cph - We're doing a user-initiated save game while a demo is
1686 * running so, go outside normal mechanisms
1687 */
1688 savegameslot = slot;
1689 G_DoSaveGame(true);
1690 }
1691 // CPhipps - store info in special_event
1692 special_event = BT_SPECIAL | (BTS_SAVEGAME & BT_SPECIALMASK) |
1693 ((slot << BTS_SAVESHIFT) & BTS_SAVEMASK);
1694#ifdef HAVE_NET
1695 D_NetSendMisc(nm_savegamename, strlen(savedescription)+1, savedescription);
1696#endif
1697}
1698
1699// Check for overrun and realloc if necessary -- Lee Killough 1/22/98
1700void CheckSaveGame(size_t size)
1701{
1702 size_t pos = save_p - savebuffer;
1703 size += 1024; // breathing room
1704 if (pos+size > savegamesize)
1705 save_p = (savebuffer = realloc(savebuffer,
1706 savegamesize += (size+1023) & ~1023)) + pos;
1707}
1708
1709/* killough 3/22/98: form savegame name in one location
1710 * (previously code was scattered around in multiple places)
1711 * cph - Avoid possible buffer overflow problems by passing
1712 * size to this function and using snprintf */
1713
1714void G_SaveGameName(char *name, size_t size, int slot, boolean demoplayback)
1715{
1716 const char* sgn = demoplayback ? "demosav" : SAVEGAMENAME;
1717 snprintf (name, size, "%s%d.dsg", sgn, slot);
1718}
1719
1720static void G_DoSaveGame (boolean menu)
1721{
1722 char name[100+1];
1723 char name2[VERSIONSIZE];
1724 char *description;
1725 int length, i;
1726
1727 gameaction = ga_nothing; // cph - cancel savegame at top of this function,
1728 // in case later problems cause a premature exit
1729
1730 G_SaveGameName(name,sizeof(name),savegameslot, demoplayback && !menu);
1731
1732 description = savedescription;
1733
1734 save_p = savebuffer = malloc(savegamesize);
1735
1736 CheckSaveGame(SAVESTRINGSIZE+VERSIONSIZE+sizeof(unsigned long));
1737 memcpy (save_p, description, SAVESTRINGSIZE);
1738 save_p += SAVESTRINGSIZE;
1739 memset (name2,0,sizeof(name2));
1740
1741 // CPhipps - scan for the version header
1742 for (i=0; (size_t)i<num_version_headers; i++)
1743 if (version_headers[i].comp_level == compatibility_level) {
1744 // killough 2/22/98: "proprietary" version string :-)
1745 snprintf (name2,sizeof(name2),version_headers[i].ver_printf,version_headers[i].version);
1746 memcpy (save_p, name2, VERSIONSIZE);
1747 i = num_version_headers+1;
1748 }
1749
1750 if ((size_t)i == num_version_headers) {
1751 doom_printf("No savegame signature known for\nthis compatibility level\n"
1752 "%d/%d, %d registered", compatibility_level,
1753 MAX_COMPATIBILITY_LEVEL, (signed)num_version_headers);
1754 free(savebuffer); // cph - free data
1755 return;
1756 }
1757
1758 save_p += VERSIONSIZE;
1759
1760 { /* killough 3/16/98, 12/98: store lump name checksum */
1761 uint_64_t checksum = G_Signature();
1762 memcpy(save_p, &checksum, sizeof checksum);
1763 save_p += sizeof checksum;
1764 }
1765
1766 // killough 3/16/98: store pwad filenames in savegame
1767 {
1768 // CPhipps - changed for new wadfiles handling
1769 int i = 0;
1770 for (*save_p = 0; (size_t)i<numwadfiles; i++)
1771 {
1772 const char *const w = wadfiles[i].name;
1773 CheckSaveGame(strlen(w)+2);
1774 strcat(strcat(save_p, w), "\n");
1775 }
1776 save_p += strlen(save_p)+1;
1777 }
1778
1779 CheckSaveGame(GAME_OPTION_SIZE+MIN_MAXPLAYERS+10);
1780
1781 /* cph - FIXME? - Save compatibility level */
1782 *save_p++ = 0;
1783
1784 *save_p++ = gameskill;
1785 *save_p++ = gameepisode;
1786 *save_p++ = gamemap;
1787
1788 for (i=0 ; i<MAXPLAYERS ; i++)
1789 *save_p++ = playeringame[i];
1790
1791 for (;i<MIN_MAXPLAYERS;i++) // killough 2/28/98
1792 *save_p++ = 0;
1793
1794 *save_p++ = idmusnum; // jff 3/17/98 save idmus state
1795
1796 save_p = G_WriteOptions(save_p); // killough 3/1/98: save game options
1797
1798 /* cph - FIXME - endianness? */
1799 /* killough 11/98: save entire word */
1800 memcpy(save_p, &leveltime, sizeof leveltime);
1801 save_p += sizeof leveltime;
1802
1803 /* cph - total episode time */
1804 if (compatibility_level >= prboom_2_compatibility) {
1805 memcpy(save_p, &totalleveltimes, sizeof totalleveltimes);
1806 save_p += sizeof totalleveltimes;
1807 }
1808 else totalleveltimes = 0;
1809
1810 // killough 11/98: save revenant tracer state
1811 *save_p++ = (gametic-basetic) & 255;
1812
1813 // killough 3/22/98: add Z_CheckHeap after each call to ensure consistency
1814 Z_CheckHeap();
1815 P_ArchivePlayers();
1816 Z_CheckHeap();
1817
1818 // phares 9/13/98: Move mobj_t->index out of P_ArchiveThinkers so the
1819 // indices can be used by P_ArchiveWorld when the sectors are saved.
1820 // This is so we can save the index of the mobj_t of the thinker that
1821 // caused a sound, referenced by sector_t->soundtarget.
1822 P_ThinkerToIndex();
1823
1824 P_ArchiveWorld();
1825 Z_CheckHeap();
1826 P_ArchiveThinkers();
1827
1828 // phares 9/13/98: Move index->mobj_t out of P_ArchiveThinkers, simply
1829 // for symmetry with the P_ThinkerToIndex call above.
1830
1831 P_IndexToThinker();
1832
1833 Z_CheckHeap();
1834 P_ArchiveSpecials();
1835 P_ArchiveRNG(); // killough 1/18/98: save RNG information
1836 Z_CheckHeap();
1837 P_ArchiveMap(); // killough 1/22/98: save automap information
1838
1839 *save_p++ = 0xe6; // consistancy marker
1840
1841 length = save_p - savebuffer;
1842
1843 Z_CheckHeap();
1844 doom_printf( "%s", M_WriteFile(name, savebuffer, length)
1845 ? GGSAVED /* Ty - externalised */
1846 : "Game save failed!"); // CPhipps - not externalised
1847
1848 free(savebuffer); // killough
1849 savebuffer = save_p = NULL;
1850
1851 savedescription[0] = 0;
1852}
1853
1854static skill_t d_skill;
1855static int d_episode;
1856static int d_map;
1857
1858void G_DeferedInitNew(skill_t skill, int episode, int map)
1859{
1860 d_skill = skill;
1861 d_episode = episode;
1862 d_map = map;
1863 gameaction = ga_newgame;
1864}
1865
1866extern int variable_friction;
1867extern int default_variable_friction; // ice & mud
1868
1869extern int weapon_recoil, default_weapon_recoil; // weapon recoil
1870
1871extern int allow_pushers;
1872extern int default_allow_pushers; // MT_PUSH Things
1873
1874extern int player_bobbing;
1875extern int default_player_bobbing; // whether player bobs or not
1876
1877extern int monsters_remember, default_monsters_remember;
1878
1879/* cph -
1880 * G_Compatibility
1881 *
1882 * Initialises the comp[] array based on the compatibility_level
1883 * For reference, MBF did:
1884 * for (i=0; i < COMP_TOTAL; i++)
1885 * comp[i] = compatibility;
1886 *
1887 * Instead, we have a lookup table showing at what version a fix was
1888 * introduced.
1889 */
1890
1891void G_Compatibility(void)
1892{
1893 static const complevel_t fix_levels[COMP_NUM] = {
1894 mbf_compatibility, /* comp_telefrag - monsters used to telefrag only
1895 * on MAP30, now they do it for spawners only */
1896 mbf_compatibility, /* comp_dropoff - MBF encourages things to drop
1897 * off of overhangs */
1898 boom_compatibility,/* comp_vile - original Doom archville bugs like
1899 * ghosts */
1900 boom_compatibility,/* comp_pain - original Doom limits Pain Elements
1901 * from spawning too many skulls */
1902 boom_compatibility,/* comp_skull - original Doom let skulls be spit
1903 * through walls by Pain Elementals */
1904 boom_compatibility,/* comp_blazing - original Doom duplicated
1905 * blazing door sound */
1906 mbf_compatibility, /* comp_doorlight - MBF made door lighting changes
1907 * more gradual */
1908 boom_compatibility,/* comp_model - improvements to the game physics */
1909 boom_compatibility,/* comp_god - fixes to God mode */
1910 mbf_compatibility, /* comp_falloff - MBF encourages things to drop
1911 * off of overhangs */
1912 boom_compatibility_compatibility,
1913 /* comp_floors - fixes for moving floors bugs */
1914 boom_compatibility,/* comp_skymap */
1915 mbf_compatibility, /* comp_pursuit - MBF AI change, limited pursuit? */
1916 boom_compatibility,/* comp_doorstuck - monsters stuck in doors fix */
1917 mbf_compatibility, /* comp_staylift - MBF AI change, monsters try
1918 * to stay on lifts */
1919 lxdoom_1_compatibility, /* comp_zombie - prevent dead players
1920 * triggering stuff */
1921 boom_compatibility_compatibility, /* comp_stairs - see p_floor.c */
1922 mbf_compatibility, /* comp_infcheat - FIXME */
1923 boom_compatibility,/* comp_zerotags - allow zero tags in wads */
1924 lxdoom_1_compatibility, /* comp_moveblock - enables keygrab and
1925 * mancubi shots going thru walls */
1926 prboom_2_compatibility, /* comp_respawn - objects which aren't on the map
1927 * at game start respawn at (0,0) */
1928 boom_compatibility_compatibility, /* comp_sound - see s_sound.c */
1929 };
1930 int i;
1931 for (i=0; i<COMP_NUM; i++)
1932 comp[i] = compatibility_level < fix_levels[i];
1933 for (; i<COMP_TOTAL; i++) comp[i] = 1;
1934}
1935
1936#ifdef DOGS
1937/* killough 7/19/98: Marine's best friend :) */
1938static int G_GetHelpers(void)
1939{
1940 int j = M_CheckParm ("-dog");
1941
1942 if (!j)
1943 j = M_CheckParm ("-dogs");
1944return j ? j+1 < myargc ? atoi(myargv[j+1]) : 1 : default_dogs;
1945}
1946#endif
1947
1948
1949// killough 3/1/98: function to reload all the default parameter
1950// settings before a new game begins
1951
1952void G_ReloadDefaults(void)
1953{
1954 // killough 3/1/98: Initialize options based on config file
1955 // (allows functions above to load different values for demos
1956 // and savegames without messing up defaults).
1957
1958 weapon_recoil = default_weapon_recoil; // weapon recoil
1959
1960 player_bobbing = default_player_bobbing; // whether player bobs or not
1961
1962 variable_friction = allow_pushers = true;
1963
1964 monsters_remember = default_monsters_remember; // remember former enemies
1965
1966 monster_infighting = default_monster_infighting; // killough 7/19/98
1967
1968#ifdef DOGS
1969 dogs = netgame ? 0 : G_GetHelpers(); // killough 7/19/98
1970 dog_jumping = default_dog_jumping;
1971#endif
1972
1973 distfriend = default_distfriend; // killough 8/8/98
1974
1975 monster_backing = default_monster_backing; // killough 9/8/98
1976
1977 monster_avoid_hazards = default_monster_avoid_hazards; // killough 9/9/98
1978
1979 monster_friction = default_monster_friction; // killough 10/98
1980
1981 help_friends = default_help_friends; // killough 9/9/98
1982
1983 monkeys = default_monkeys;
1984
1985 // jff 1/24/98 reset play mode to command line spec'd version
1986 // killough 3/1/98: moved to here
1987// respawnparm = clrespawnparm;
1988// fastparm = clfastparm;
1989// nomonsters = clnomonsters;
1990
1991 //jff 3/24/98 set startskill from defaultskill in config file, unless
1992 // it has already been set by a -skill parameter
1993 if (startskill==sk_none)
1994 startskill = (skill_t)(defaultskill-1);
1995
1996 demoplayback = false;
1997 singledemo = false; // killough 9/29/98: don't stop after 1 demo
1998 netdemo = false;
1999
2000 // killough 2/21/98:
2001 memset(playeringame+1, 0, sizeof(*playeringame)*(MAXPLAYERS-1));
2002
2003 consoleplayer = 0;
2004
2005 compatibility_level = default_compatibility_level;
2006 {
2007 int i = M_CheckParm("-complevel");
2008 if (i && (1+i) < myargc) compatibility_level = atoi(myargv[i+1]);
2009 }
2010 if ((signed)compatibility_level == -1)
2011 compatibility_level = MAX_COMPATIBILITY_LEVEL-1;
2012
2013 if (mbf_features)
2014 memcpy(comp, default_comp, sizeof comp);
2015 else
2016 G_Compatibility();
2017
2018 // killough 3/31/98, 4/5/98: demo sync insurance
2019 demo_insurance = default_demo_insurance == 1;
2020
2021 rngseed += 1 + gametic; // CPhipps
2022// rngseed += I_GetRandomTimeSeed() + gametic; // CPhipps
2023}
2024
2025void G_DoNewGame (void)
2026{
2027 G_ReloadDefaults(); // killough 3/1/98
2028 netgame = false; // killough 3/1/98
2029 deathmatch = false;
2030 G_InitNew (d_skill, d_episode, d_map);
2031 gameaction = ga_nothing;
2032
2033 //jff 4/26/98 wake up the status bar in case were coming out of a DM demo
2034 ST_Start();
2035}
2036
2037// killough 4/10/98: New function to fix bug which caused Doom
2038// lockups when idclev was used in conjunction with -fast.
2039
2040void G_SetFastParms(int fast_pending)
2041{
2042 static int fast = 0; // remembers fast state
2043 int i;
2044 if (fast != fast_pending) { /* only change if necessary */
2045 if ((fast = fast_pending))
2046 {
2047 for (i=S_SARG_RUN1; i<=S_SARG_PAIN2; i++)
2048 if (states[i].tics != 1 || demo_compatibility) // killough 4/10/98
2049 states[i].tics >>= 1; // don't change 1->0 since it causes cycles
2050 mobjinfo[MT_BRUISERSHOT].speed = 20*FRACUNIT;
2051 mobjinfo[MT_HEADSHOT].speed = 20*FRACUNIT;
2052 mobjinfo[MT_TROOPSHOT].speed = 20*FRACUNIT;
2053 }
2054 else
2055 {
2056 for (i=S_SARG_RUN1; i<=S_SARG_PAIN2; i++)
2057 states[i].tics <<= 1;
2058 mobjinfo[MT_BRUISERSHOT].speed = 15*FRACUNIT;
2059 mobjinfo[MT_HEADSHOT].speed = 10*FRACUNIT;
2060 mobjinfo[MT_TROOPSHOT].speed = 10*FRACUNIT;
2061 }
2062 }
2063}
2064
2065// The sky texture to be used instead of the F_SKY1 dummy.
2066extern int skytexture;
2067
2068//
2069// G_InitNew
2070// Can be called by the startup code or the menu task,
2071// consoleplayer, displayplayer, playeringame[] should be set.
2072//
2073
2074void G_InitNew(skill_t skill, int episode, int map)
2075{
2076 int i;
2077
2078 if (paused)
2079 {
2080 paused = false;
2081 S_ResumeSound();
2082 }
2083
2084 if (skill > sk_nightmare)
2085 skill = sk_nightmare;
2086
2087 if (episode < 1)
2088 episode = 1;
2089
2090 if (gamemode == retail)
2091 {
2092 if (episode > 4)
2093 episode = 4;
2094 }
2095 else
2096 if (gamemode == shareware)
2097 {
2098 if (episode > 1)
2099 episode = 1; // only start episode 1 on shareware
2100 }
2101 else
2102 if (episode > 3)
2103 episode = 3;
2104
2105 if (map < 1)
2106 map = 1;
2107 if (map > 9 && gamemode != commercial)
2108 map = 9;
2109
2110 G_SetFastParms(fastparm || skill == sk_nightmare); // killough 4/10/98
2111
2112 M_ClearRandom();
2113
2114 respawnmonsters = skill == sk_nightmare || respawnparm;
2115
2116 // force players to be initialized upon first level load
2117 for (i=0 ; i<MAXPLAYERS ; i++)
2118 players[i].playerstate = PST_REBORN;
2119
2120 usergame = true; // will be set false if a demo
2121 paused = false;
2122 automapmode &= ~am_active;
2123 gameepisode = episode;
2124 gamemap = map;
2125 gameskill = skill;
2126
2127 totalleveltimes = 0; // cph
2128
2129 //jff 4/16/98 force marks on automap cleared every new level start
2130 AM_clearMarks();
2131
2132 G_DoLoadLevel ();
2133}
2134
2135
2136//
2137// DEMO RECORDING
2138//
2139
2140unsigned char DEMOMARKER=0x80;
2141
2142void G_ReadDemoTiccmd (ticcmd_t* cmd)
2143{
2144 if (*demo_p == DEMOMARKER)
2145 G_CheckDemoStatus(); // end of demo data stream
2146 else
2147 {
2148 cmd->forwardmove = ((signed char)*demo_p++);
2149 cmd->sidemove = ((signed char)*demo_p++);
2150 if (!longtics) {
2151 cmd->angleturn = ((unsigned char)*demo_p++)<<8;
2152 } else {
2153 unsigned int lowbyte = (unsigned char)*demo_p++;
2154 cmd->angleturn = (((signed int)(*demo_p++))<<8) + lowbyte;
2155 }
2156 cmd->buttons = (unsigned char)*demo_p++;
2157 }
2158}
2159
2160/* Demo limits removed -- killough
2161 * cph - record straight to file
2162 */
2163void G_WriteDemoTiccmd (ticcmd_t* cmd)
2164{
2165 char buf[5];
2166 char *p = buf;
2167
2168 *p++ = cmd->forwardmove;
2169 *p++ = cmd->sidemove;
2170 if (!longtics) {
2171 *p++ = (cmd->angleturn+128)>>8;
2172 } else {
2173 signed short a = cmd->angleturn;
2174 *p++ = a & 0xff;
2175 *p++ = (a >> 8) & 0xff;
2176 }
2177 *p++ = cmd->buttons;
2178 if (write(demofd, buf, p-buf) != p-buf)
2179 I_Error("G_WriteDemoTiccmd: error writing demo");
2180
2181 /* cph - alias demo_p to it so we can read it back */
2182 demo_p = buf;
2183 G_ReadDemoTiccmd (cmd); // make SURE it is exactly the same
2184}
2185
2186//
2187// G_RecordDemo
2188//
2189
2190void G_RecordDemo (const char* name)
2191{
2192 char demoname[100];
2193 usergame = false;
2194 AddDefaultExtension(strcpy(demoname, name), ".lmp"); // 1/18/98 killough
2195 demorecording = true;
2196 /* cph - Record demos straight to file
2197 * If file already exists, try to continue existing demo
2198 */
2199 if (fileexists(demoname)) {
2200 demofd = open(demoname, O_WRONLY | O_APPEND);
2201 } else {
2202 demofd = open(demoname, O_WRONLY | O_RDONLY);
2203 if (demofd) {
2204 int slot = -1;
2205 int rc;
2206 {
2207 byte buf[200];
2208 size_t len;
2209 read(demofd, buf, sizeof(buf));
2210
2211 len = G_ReadDemoHeader(buf) - buf;
2212 lseek(demofd, len, SEEK_SET);
2213 }
2214 do {
2215 byte buf[4];
2216 rc = read(demofd, buf, sizeof(buf));
2217 if (buf[0] == DEMOMARKER) break;
2218 if (buf[3] & BT_SPECIAL)
2219 if ((buf[3] & BT_SPECIALMASK) == BTS_SAVEGAME)
2220 slot = (buf[3] & BTS_SAVEMASK)>>BTS_SAVESHIFT;
2221 } while (rc == /* sizeof(buf) is out of scope here */ 4 );
2222 if (slot == -1) I_Error("G_RecordDemo: No save in demo, can't continue");
2223 lseek(demofd, -rc, SEEK_CUR);
2224 G_LoadGame(slot, false);
2225 autostart = false;
2226 }
2227 }
2228 if (!demofd) I_Error("G_RecordDemo: failed to open %s", name);
2229}
2230
2231// These functions are used to read and write game-specific options in demos
2232// and savegames so that demo sync is preserved and savegame restoration is
2233// complete. Not all options (for example "compatibility"), however, should
2234// be loaded and saved here. It is extremely important to use the same
2235// positions as before for the variables, so if one becomes obsolete, the
2236// byte(s) should still be skipped over or padded with 0's.
2237// Lee Killough 3/1/98
2238
2239extern int forceOldBsp;
2240
2241byte *G_WriteOptions(byte *demo_p)
2242{
2243 byte *target = demo_p + GAME_OPTION_SIZE;
2244
2245 *demo_p++ = monsters_remember; // part of monster AI
2246
2247 *demo_p++ = variable_friction; // ice & mud
2248
2249 *demo_p++ = weapon_recoil; // weapon recoil
2250
2251 *demo_p++ = allow_pushers; // MT_PUSH Things
2252
2253 *demo_p++ = 0;
2254
2255 *demo_p++ = player_bobbing; // whether player bobs or not
2256
2257 // killough 3/6/98: add parameters to savegame, move around some in demos
2258 *demo_p++ = respawnparm;
2259 *demo_p++ = fastparm;
2260 *demo_p++ = nomonsters;
2261
2262 *demo_p++ = demo_insurance; // killough 3/31/98
2263
2264 // killough 3/26/98: Added rngseed. 3/31/98: moved here
2265 *demo_p++ = (byte)((rngseed >> 24) & 0xff);
2266 *demo_p++ = (byte)((rngseed >> 16) & 0xff);
2267 *demo_p++ = (byte)((rngseed >> 8) & 0xff);
2268 *demo_p++ = (byte)( rngseed & 0xff);
2269
2270 // Options new to v2.03 begin here
2271
2272 *demo_p++ = monster_infighting; // killough 7/19/98
2273
2274#ifdef DOGS
2275 *demo_p++ = dogs; // killough 7/19/98
2276#else
2277 *demo_p++ = 0;
2278#endif
2279
2280 *demo_p++ = 0;
2281 *demo_p++ = 0;
2282
2283 *demo_p++ = (distfriend >> 8) & 0xff; // killough 8/8/98
2284 *demo_p++ = distfriend & 0xff; // killough 8/8/98
2285
2286 *demo_p++ = monster_backing; // killough 9/8/98
2287
2288 *demo_p++ = monster_avoid_hazards; // killough 9/9/98
2289
2290 *demo_p++ = monster_friction; // killough 10/98
2291
2292 *demo_p++ = help_friends; // killough 9/9/98
2293
2294#ifdef DOGS
2295 *demo_p++ = dog_jumping;
2296#else
2297 *demo_p++ = 0;
2298#endif
2299
2300 *demo_p++ = monkeys;
2301
2302 { // killough 10/98: a compatibility vector now
2303 int i;
2304 for (i=0; i < COMP_TOTAL; i++)
2305 *demo_p++ = comp[i] != 0;
2306 }
2307
2308 *demo_p++ = (compatibility_level >= prboom_2_compatibility) && forceOldBsp; // cph 2002/07/20
2309
2310 //----------------
2311 // Padding at end
2312 //----------------
2313 while (demo_p < target)
2314 *demo_p++ = 0;
2315
2316 if (demo_p != target)
2317 I_Error("G_WriteOptions: GAME_OPTION_SIZE is too small");
2318
2319 return target;
2320}
2321
2322/* Same, but read instead of write
2323 * cph - const byte*'s
2324 */
2325
2326const byte *G_ReadOptions(const byte *demo_p)
2327{
2328 const byte *target = demo_p + GAME_OPTION_SIZE;
2329
2330 monsters_remember = *demo_p++;
2331
2332 variable_friction = *demo_p; // ice & mud
2333 demo_p++;
2334
2335 weapon_recoil = *demo_p; // weapon recoil
2336 demo_p++;
2337
2338 allow_pushers = *demo_p; // MT_PUSH Things
2339 demo_p++;
2340
2341 demo_p++;
2342
2343 player_bobbing = *demo_p; // whether player bobs or not
2344 demo_p++;
2345
2346 // killough 3/6/98: add parameters to savegame, move from demo
2347 respawnparm = *demo_p++;
2348 fastparm = *demo_p++;
2349 nomonsters = *demo_p++;
2350
2351 demo_insurance = *demo_p++; // killough 3/31/98
2352
2353 // killough 3/26/98: Added rngseed to demos; 3/31/98: moved here
2354
2355 rngseed = *demo_p++ & 0xff;
2356 rngseed <<= 8;
2357 rngseed += *demo_p++ & 0xff;
2358 rngseed <<= 8;
2359 rngseed += *demo_p++ & 0xff;
2360 rngseed <<= 8;
2361 rngseed += *demo_p++ & 0xff;
2362
2363 // Options new to v2.03
2364 if (mbf_features)
2365 {
2366 monster_infighting = *demo_p++; // killough 7/19/98
2367
2368#ifdef DOGS
2369 dogs = *demo_p++; // killough 7/19/98
2370#else
2371 demo_p++;
2372#endif
2373
2374 demo_p += 2;
2375
2376 distfriend = *demo_p++ << 8; // killough 8/8/98
2377 distfriend+= *demo_p++;
2378
2379 monster_backing = *demo_p++; // killough 9/8/98
2380
2381 monster_avoid_hazards = *demo_p++; // killough 9/9/98
2382
2383 monster_friction = *demo_p++; // killough 10/98
2384
2385 help_friends = *demo_p++; // killough 9/9/98
2386
2387#ifdef DOGS
2388 dog_jumping = *demo_p++; // killough 10/98
2389#else
2390 demo_p++;
2391#endif
2392
2393 monkeys = *demo_p++;
2394
2395 { // killough 10/98: a compatibility vector now
2396 int i;
2397 for (i=0; i < COMP_TOTAL; i++)
2398 comp[i] = *demo_p++;
2399 }
2400
2401 forceOldBsp = *demo_p++; // cph 2002/07/20
2402 }
2403 else /* defaults for versions <= 2.02 */
2404 {
2405 /* cph - comp[] has already been set up right by G_Compatibility */
2406
2407 monster_infighting = 1; // killough 7/19/98
2408
2409 monster_backing = 0; // killough 9/8/98
2410
2411 monster_avoid_hazards = 0; // killough 9/9/98
2412
2413 monster_friction = 0; // killough 10/98
2414
2415 help_friends = 0; // killough 9/9/98
2416
2417#ifdef DOGS
2418 dogs = 0; // killough 7/19/98
2419 dog_jumping = 0; // killough 10/98
2420#endif
2421
2422 monkeys = 0;
2423 }
2424
2425 return target;
2426}
2427
2428void G_BeginRecording (void)
2429{
2430 int i;
2431 byte *demostart, *demo_p;
2432 demostart = demo_p = malloc(1000);
2433
2434 /* cph - 3 demo record formats supported: MBF+, BOOM, and Doom v1.9 */
2435 if (mbf_features) {
2436 { /* Write version code into demo */
2437 unsigned char v=0;
2438 switch(compatibility_level) {
2439 case doom_12_compatibility:
2440 case doom_demo_compatibility:
2441 case doom_compatibility:
2442 case boom_compatibility_compatibility:
2443 case boom_201_compatibility:
2444 case boom_202_compatibility:
2445 case lxdoom_1_compatibility:
2446 case prboom_1_compatibility:
2447 case MAX_COMPATIBILITY_LEVEL:
2448 case mbf_compatibility: v = 204; break;
2449 case prboom_2_compatibility: v = 210; break;
2450 case prboom_3_compatibility: v = 211; break;
2451 }
2452 *demo_p++ = v;
2453 }
2454
2455 // signature
2456 *demo_p++ = 0x1d;
2457 *demo_p++ = 'M';
2458 *demo_p++ = 'B';
2459 *demo_p++ = 'F';
2460 *demo_p++ = 0xe6;
2461 *demo_p++ = '\0';
2462
2463 /* killough 2/22/98: save compatibility flag in new demos
2464 * cph - FIXME? MBF demos will always be not in compat. mode */
2465 *demo_p++ = 0;
2466
2467 *demo_p++ = gameskill;
2468 *demo_p++ = gameepisode;
2469 *demo_p++ = gamemap;
2470 *demo_p++ = deathmatch;
2471 *demo_p++ = consoleplayer;
2472
2473 demo_p = G_WriteOptions(demo_p); // killough 3/1/98: Save game options
2474
2475 for (i=0 ; i<MAXPLAYERS ; i++)
2476 *demo_p++ = playeringame[i];
2477
2478 // killough 2/28/98:
2479 // We always store at least MIN_MAXPLAYERS bytes in demo, to
2480 // support enhancements later w/o losing demo compatibility
2481
2482 for (; i<MIN_MAXPLAYERS; i++)
2483 *demo_p++ = 0;
2484
2485 } else if (compatibility_level > doom_compatibility) {
2486 byte v=0, c=0; /* Nominally, version and compatibility bits */
2487 switch (compatibility_level) {
2488 case boom_compatibility_compatibility: v = 202, c = 1; break;
2489 case boom_201_compatibility: v = 201; c = 0; break;
2490 case boom_202_compatibility: v = 202, c = 0; break;
2491 default: I_Error("G_BeginRecording: Boom compatibility level unrecognised?");
2492 }
2493 *demo_p++ = v;
2494
2495 // signature
2496 *demo_p++ = 0x1d;
2497 *demo_p++ = 'B';
2498 *demo_p++ = 'o';
2499 *demo_p++ = 'o';
2500 *demo_p++ = 'm';
2501 *demo_p++ = 0xe6;
2502
2503 /* CPhipps - save compatibility level in demos */
2504 *demo_p++ = c;
2505
2506 *demo_p++ = gameskill;
2507 *demo_p++ = gameepisode;
2508 *demo_p++ = gamemap;
2509 *demo_p++ = deathmatch;
2510 *demo_p++ = consoleplayer;
2511
2512 demo_p = G_WriteOptions(demo_p); // killough 3/1/98: Save game options
2513
2514 for (i=0 ; i<MAXPLAYERS ; i++)
2515 *demo_p++ = playeringame[i];
2516
2517 // killough 2/28/98:
2518 // We always store at least MIN_MAXPLAYERS bytes in demo, to
2519 // support enhancements later w/o losing demo compatibility
2520
2521 for (; i<MIN_MAXPLAYERS; i++)
2522 *demo_p++ = 0;
2523 } else { // cph - write old v1.9 demos (might even sync)
2524 longtics = M_CheckParm("-longtics");
2525 *demo_p++ = longtics ? 111 : 109; // v1.9 has best chance of syncing these
2526 *demo_p++ = gameskill;
2527 *demo_p++ = gameepisode;
2528 *demo_p++ = gamemap;
2529 *demo_p++ = deathmatch;
2530 *demo_p++ = respawnparm;
2531 *demo_p++ = fastparm;
2532 *demo_p++ = nomonsters;
2533 *demo_p++ = consoleplayer;
2534 for (i=0; i<4; i++) // intentionally hard-coded 4 -- killough
2535 *demo_p++ = playeringame[i];
2536 }
2537
2538 if (write(demofd, demostart, demo_p-demostart) != (signed)(size_t)(demo_p-demostart))
2539 I_Error("G_BeginRecording: Error writing demo header");
2540 free(demostart);
2541}
2542
2543
2544//
2545// G_PlayDemo
2546//
2547
2548static const char *defdemoname;
2549
2550void G_DeferedPlayDemo (const char* name)
2551{
2552 defdemoname = name;
2553 gameaction = ga_playdemo;
2554}
2555
2556static int demolumpnum = -1;
2557
2558static const byte* G_ReadDemoHeader(const byte *demo_p)
2559{
2560 skill_t skill;
2561 int i, episode, map;
2562 int demover;
2563 const byte *option_p = NULL; /* killough 11/98 */
2564
2565 basetic = gametic; // killough 9/29/98
2566
2567 // killough 2/22/98, 2/28/98: autodetect old demos and act accordingly.
2568 // Old demos turn on demo_compatibility => compatibility; new demos load
2569 // compatibility flag, and other flags as well, as a part of the demo.
2570
2571 demover = *demo_p++;
2572
2573 if (demover < 200) // Autodetect old demos
2574 {
2575 compatibility_level = doom_demo_compatibility;
2576 if (demover >= 111) longtics = 1;
2577
2578 G_Compatibility();
2579
2580 // killough 3/2/98: force these variables to be 0 in demo_compatibility
2581
2582 variable_friction = 0;
2583
2584 weapon_recoil = 0;
2585
2586 allow_pushers = 0;
2587
2588 monster_infighting = 1; // killough 7/19/98
2589
2590#ifdef DOGS
2591 dogs = 0; // killough 7/19/98
2592 dog_jumping = 0; // killough 10/98
2593#endif
2594
2595 monster_backing = 0; // killough 9/8/98
2596
2597 monster_avoid_hazards = 0; // killough 9/9/98
2598
2599 monster_friction = 0; // killough 10/98
2600 help_friends = 0; // killough 9/9/98
2601 monkeys = 0;
2602
2603 // killough 3/6/98: rearrange to fix savegame bugs (moved fastparm,
2604 // respawnparm, nomonsters flags to G_LoadOptions()/G_SaveOptions())
2605
2606 if ((skill=demover) >= 100) // For demos from versions >= 1.4
2607 {
2608 skill = *demo_p++;
2609 episode = *demo_p++;
2610 map = *demo_p++;
2611 deathmatch = *demo_p++;
2612 respawnparm = *demo_p++;
2613 fastparm = *demo_p++;
2614 nomonsters = *demo_p++;
2615 consoleplayer = *demo_p++;
2616 }
2617 else
2618 {
2619 episode = *demo_p++;
2620 map = *demo_p++;
2621 deathmatch = respawnparm = fastparm =
2622 nomonsters = consoleplayer = 0;
2623 }
2624 }
2625 else // new versions of demos
2626 {
2627 demo_p += 6; // skip signature;
2628 switch (demover) {
2629 case 200: /* BOOM */
2630 case 201:
2631 if (!*demo_p++)
2632 compatibility_level = boom_201_compatibility;
2633 else
2634 compatibility_level = boom_compatibility_compatibility;
2635 break;
2636 case 202:
2637 if (!*demo_p++)
2638 compatibility_level = boom_202_compatibility;
2639 else
2640 compatibility_level = boom_compatibility_compatibility;
2641 break;
2642 case 203:
2643 /* LxDoom or MBF - determine from signature
2644 * cph - load compatibility level */
2645 switch (demobuffer[2]) {
2646 case 'B': /* LxDoom */
2647 /* cph - DEMOSYNC - LxDoom demos recorded in compatibility modes support dropped */
2648 compatibility_level = lxdoom_1_compatibility;
2649 break;
2650 case 'M':
2651 compatibility_level = mbf_compatibility;
2652 demo_p++;
2653 break;
2654 }
2655 break;
2656 case 210:
2657 compatibility_level = prboom_2_compatibility;
2658 demo_p++;
2659 break;
2660 case 211:
2661 compatibility_level = prboom_3_compatibility;
2662 demo_p++;
2663 break;
2664 }
2665 G_Compatibility();
2666 skill = *demo_p++;
2667 episode = *demo_p++;
2668 map = *demo_p++;
2669 deathmatch = *demo_p++;
2670 consoleplayer = *demo_p++;
2671
2672 /* killough 11/98: save option pointer for below */
2673 if (mbf_features)
2674 option_p = demo_p;
2675
2676 demo_p = G_ReadOptions(demo_p); // killough 3/1/98: Read game options
2677
2678 if (demover == 200) // killough 6/3/98: partially fix v2.00 demos
2679 demo_p += 128-GAME_OPTION_SIZE;
2680 }
2681
2682// printf( "G_DoPlayDemo: playing demo with %s compatibility\n",
2683// comp_lev_str[compatibility_level]);
2684
2685 if (demo_compatibility) // only 4 players can exist in old demos
2686 {
2687 for (i=0; i<4; i++) // intentionally hard-coded 4 -- killough
2688 playeringame[i] = *demo_p++;
2689 for (;i < MAXPLAYERS; i++)
2690 playeringame[i] = 0;
2691 }
2692 else
2693 {
2694 for (i=0 ; i < MAXPLAYERS; i++)
2695 playeringame[i] = *demo_p++;
2696 demo_p += MIN_MAXPLAYERS - MAXPLAYERS;
2697 }
2698
2699 if (playeringame[1])
2700 {
2701 netgame = true;
2702 netdemo = true;
2703 }
2704
2705 if (gameaction != ga_loadgame) { /* killough 12/98: support -loadgame */
2706 G_InitNew(skill, episode, map);
2707 }
2708
2709 for (i=0; i<MAXPLAYERS;i++) // killough 4/24/98
2710 players[i].cheats = 0;
2711
2712 return demo_p;
2713}
2714
2715void G_DoPlayDemo(void)
2716{
2717 char basename[9];
2718
2719 ExtractFileBase(defdemoname,basename); // killough
2720 basename[8] = 0;
2721 demobuffer = demo_p = W_CacheLumpNum(demolumpnum = W_GetNumForName(basename));
2722 /* cph - store lump number for unlocking later */
2723
2724 demo_p = G_ReadDemoHeader(demo_p);
2725
2726 gameaction = ga_nothing;
2727 usergame = false;
2728
2729 demoplayback = true;
2730}
2731
2732//
2733// G_TimeDemo
2734//
2735
2736void G_TimeDemo(const char *name) // CPhipps - const char*
2737{
2738 timingdemo = true;
2739 singletics = true;
2740 defdemoname = name;
2741 gameaction = ga_playdemo;
2742}
2743
2744
2745/* G_CheckDemoStatus
2746 *
2747 * Called after a death or level completion to allow demos to be cleaned up
2748 * Returns true if a new demo loop action will take place
2749 */
2750
2751boolean G_CheckDemoStatus (void)
2752{
2753 if (demorecording)
2754 {
2755 demorecording = false;
2756 write(demofd, &DEMOMARKER, 1);
2757 close(demofd);
2758 I_Error("G_CheckDemoStatus: Demo recorded");
2759 return false; // killough
2760 }
2761
2762 if (timingdemo)
2763 {
2764// int endtime = I_GetTime_RealTime ();
2765 int endtime = I_GetTime ();
2766 // killough -- added fps information and made it work for longer demos:
2767 unsigned realtics = endtime-starttime;
2768 int fd=open("/games/doom/timedemo.txt",O_WRONLY | O_CREAT);
2769 fprintf (fd,"Timed %d gametics in %d realtics = %d frames per second",
2770 (unsigned) gametic, realtics,
2771 (unsigned) gametic * (double) TICRATE / realtics);
2772 close(fd);
2773 I_Error ("%d gametics in %d realtics",
2774 (unsigned) gametic,realtics,
2775 (unsigned) gametic * (double) TICRATE / realtics);
2776 return false;
2777 }
2778
2779 if (demoplayback)
2780 {
2781 if (singledemo)
2782 I_Error("Done Playing Demo");
2783 return false;
2784// exit(0); // killough
2785
2786 if (demolumpnum != -1) {
2787 // cph - unlock the demo lump
2788 W_UnlockLumpNum(demolumpnum);
2789 demolumpnum = -1;
2790 }
2791 G_ReloadDefaults(); // killough 3/1/98
2792 netgame = false; // killough 3/29/98
2793 deathmatch = false;
2794 D_AdvanceDemo ();
2795 return true;
2796 }
2797 return false;
2798}
2799
2800// killough 1/22/98: this is a "Doom printf" for messages. I've gotten
2801// tired of using players->message=... and so I've added this dprintf.
2802//
2803// killough 3/6/98: Made limit static to allow z_zone functions to call
2804// this function, without calling realloc(), which seems to cause problems.
2805
2806#define MAX_MESSAGE_SIZE 1024
2807static char msg[MAX_MESSAGE_SIZE];
2808
2809// CPhipps - renamed to doom_printf to avoid name collision with glibc
2810void doom_printf(const char *s, ...)
2811{
2812 va_list v;
2813 va_start(v,s);
2814 vsnprintf(msg,sizeof(msg),s,v); /* print message in buffer */
2815 va_end(v);
2816 players[consoleplayer].message = msg; // set new message
2817}
2818
diff --git a/apps/plugins/doom/g_game.h b/apps/plugins/doom/g_game.h
new file mode 100644
index 0000000000..6a2d3dcd97
--- /dev/null
+++ b/apps/plugins/doom/g_game.h
@@ -0,0 +1,192 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION: Main game control interface.
28 *-----------------------------------------------------------------------------*/
29
30#ifndef __G_GAME__
31#define __G_GAME__
32
33#include "doomdef.h"
34#include "d_event.h"
35#include "d_ticcmd.h"
36
37//
38// GAME
39//
40
41// killough 5/2/98: number of bytes reserved for saving options
42#define GAME_OPTION_SIZE 64
43
44boolean G_Responder(event_t *ev);
45boolean G_CheckDemoStatus(void);
46boolean G_CheckDemoStatus(void);
47void G_DeathMatchSpawnPlayer(int playernum);
48void G_InitNew(skill_t skill, int episode, int map);
49void G_DeferedInitNew(skill_t skill, int episode, int map);
50void G_DeferedPlayDemo(const char *demo); // CPhipps - const
51void G_LoadGame(int slot, boolean is_command); // killough 5/15/98
52void G_ForcedLoadGame(void); // killough 5/15/98: forced loadgames
53void G_DoLoadGame(void);
54void G_SaveGame(int slot, char *description); // Called by M_Responder.
55void G_BeginRecording(void);
56// CPhipps - const on these string params
57void G_RecordDemo(const char *name); // Only called by startup code.
58void G_PlayDemo(const char *name);
59void G_TimeDemo(const char *name);
60void G_ExitLevel(void);
61void G_SecretExitLevel(void);
62void G_WorldDone(void);
63void G_EndGame(void); /* cph - make m_menu.c call a G_* function for this */
64void G_Ticker(void);
65void G_ReloadDefaults(void); // killough 3/1/98: loads game defaults
66void G_SaveGameName(char *, size_t, int, boolean); /* killough 3/22/98: sets savegame filename */
67void G_SetFastParms(int); // killough 4/10/98: sets -fast parameters
68void G_DoNewGame(void);
69void G_DoReborn(int playernum);
70void G_DoPlayDemo(void);
71void G_DoCompleted(void);
72void G_ReadDemoTiccmd(ticcmd_t *cmd);
73void G_WriteDemoTiccmd(ticcmd_t *cmd);
74void G_DoWorldDone(void);
75void G_Compatibility(void);
76const byte *G_ReadOptions(const byte *demo_p); /* killough 3/1/98 - cph: const byte* */
77byte *G_WriteOptions(byte *demo_p); // killough 3/1/98
78void G_PlayerReborn(int player);
79void G_InitNew(skill_t skill, int episode, int map);
80void G_RestartLevel(void); // CPhipps - menu involked level restart
81void G_DoLoadGame(void);
82void G_DoVictory(void);
83void G_BuildTiccmd (ticcmd_t* cmd); // CPhipps - move decl to header
84void G_ChangedPlayerColour(int pn, int cl); // CPhipps - On-the-fly player colour changing
85void G_MakeSpecialEvent(buttoncode_t bc, ...); /* cph - new event stuff */
86
87// killough 1/18/98: Doom-style printf; killough 4/25/98: add gcc attributes
88// CPhipps - renames to doom_printf to avoid name collision with glibc
89void doom_printf(const char *, ...) __attribute__((format(printf,1,2)));
90
91// killough 5/2/98: moved from m_misc.c:
92
93extern int key_right;
94extern int key_left;
95extern int key_up;
96extern int key_down;
97extern int key_menu_right; // phares 3/7/98
98extern int key_menu_left; // |
99extern int key_menu_up; // V
100extern int key_menu_down;
101extern int key_menu_backspace; // ^
102extern int key_menu_escape; // |
103extern int key_menu_enter; // phares 3/7/98
104extern int key_strafeleft;
105extern int key_straferight;
106
107extern int key_fire;
108extern int key_use;
109extern int key_strafe;
110extern int key_speed;
111extern int key_escape; // phares
112extern int key_savegame; // |
113extern int key_loadgame; // V
114extern int key_autorun;
115extern int key_reverse;
116extern int key_zoomin;
117extern int key_zoomout;
118extern int key_chat;
119extern int key_backspace;
120extern int key_enter;
121extern int key_help;
122extern int key_soundvolume;
123extern int key_hud;
124extern int key_quicksave;
125extern int key_endgame;
126extern int key_messages;
127extern int key_quickload;
128extern int key_quit;
129extern int key_gamma;
130extern int key_spy;
131extern int key_pause;
132extern int key_setup;
133extern int key_forward;
134extern int key_leftturn;
135extern int key_rightturn;
136extern int key_backward;
137extern int key_weapon;
138extern int key_weapontoggle;
139extern int key_weapon1;
140extern int key_weapon2;
141extern int key_weapon3;
142extern int key_weapon4;
143extern int key_weapon5;
144extern int key_weapon6;
145extern int key_weapon7;
146extern int key_weapon8;
147extern int key_weapon9;
148extern int destination_keys[MAXPLAYERS];
149extern int key_map_right;
150extern int key_map_left;
151extern int key_map_up;
152extern int key_map_down;
153extern int key_map_zoomin;
154extern int key_map_zoomout;
155extern int key_map;
156extern int key_map_gobig;
157extern int key_map_follow;
158extern int key_map_mark; // ^
159extern int key_map_clear; // |
160extern int key_map_grid; // phares
161extern int key_map_rotate; // cph - map rotation
162extern int key_map_overlay;// cph - map overlay
163extern int key_screenshot; // killough 2/22/98 -- add key for screenshot
164extern int autorun; // always running? // phares
165
166extern int joybfire;
167extern int joybuse;
168extern int joybstrafe;
169extern int joybspeed;
170
171extern int mousebfire;
172extern int mousebstrafe;
173extern int mousebforward;
174
175
176extern int defaultskill; //jff 3/24/98 default skill
177extern boolean haswolflevels; //jff 4/18/98 wolf levels present
178
179extern int bodyquesize; // killough 2/8/98: adustable corpse limit
180
181// killough 5/2/98: moved from d_deh.c:
182// Par times (new item with BOOM) - from g_game.c
183extern int pars[4][10]; // hardcoded array size
184extern int cpars[32]; // hardcoded array size
185// CPhipps - Make savedesciption visible in wider scope
186#define SAVEDESCLEN 32
187extern char savedescription[SAVEDESCLEN]; // Description to save in savegame
188
189/* cph - compatibility level strings */
190extern const char * comp_lev_str[];
191
192#endif
diff --git a/apps/plugins/doom/hu_lib.c b/apps/plugins/doom/hu_lib.c
new file mode 100644
index 0000000000..2ac3d35dde
--- /dev/null
+++ b/apps/plugins/doom/hu_lib.c
@@ -0,0 +1,770 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION: heads-up text and input code
28 *
29 *-----------------------------------------------------------------------------
30 */
31
32#include "doomdef.h"
33#include "doomstat.h"
34#include "v_video.h"
35#include "m_swap.h"
36#include "hu_lib.h"
37#include "hu_stuff.h"
38#include "r_main.h"
39#include "r_draw.h"
40
41#include "rockmacros.h"
42
43// boolean : whether the screen is always erased
44#define noterased viewwindowx
45
46extern int key_backspace; // phares
47extern int key_enter; // phares
48
49//
50// not used currently
51// code to initialize HUlib would go here if needed
52//
53void HUlib_init(void)
54{
55}
56
57////////////////////////////////////////////////////////
58//
59// Basic text line widget
60//
61////////////////////////////////////////////////////////
62
63//
64// HUlib_clearTextLine()
65//
66// Blank the internal text line in a hu_textline_t widget
67//
68// Passed a hu_textline_t, returns nothing
69//
70void HUlib_clearTextLine(hu_textline_t* t)
71{
72 t->linelen = // killough 1/23 98: support multiple lines
73 t->len = 0;
74 t->l[0] = 0;
75 t->needsupdate = true;
76}
77
78//
79// HUlib_initTextLine()
80//
81// Initialize a hu_textline_t widget. Set the position, font, start char
82// of the font, and color range to be used.
83//
84// Passed a hu_textline_t, and the values used to initialize
85// Returns nothing
86//
87void HUlib_initTextLine(hu_textline_t* t, int x, int y,
88 const patchnum_t* f, int sc, int cm )
89//jff 2/16/98 add color range parameter
90{
91 t->x = x;
92 t->y = y;
93 t->f = f;
94 t->sc = sc;
95 t->cm = cm;
96 HUlib_clearTextLine(t);
97}
98
99//
100// HUlib_addCharToTextLine()
101//
102// Adds a character at the end of the text line in a hu_textline_t widget
103//
104// Passed the hu_textline_t and the char to add
105// Returns false if already at length limit, true if the character added
106//
107boolean HUlib_addCharToTextLine
108( hu_textline_t* t,
109 char ch )
110{
111 // killough 1/23/98 -- support multiple lines
112 if (t->linelen == HU_MAXLINELENGTH)
113 return false;
114 else
115 {
116 t->linelen++;
117 if (ch == '\n')
118 t->linelen=0;
119
120 t->l[t->len++] = ch;
121 t->l[t->len] = 0;
122 t->needsupdate = 4;
123 return true;
124 }
125
126}
127
128//
129// HUlib_delCharFromTextLine()
130//
131// Deletes a character at the end of the text line in a hu_textline_t widget
132//
133// Passed the hu_textline_t
134// Returns false if already empty, true if the character deleted
135//
136boolean HUlib_delCharFromTextLine(hu_textline_t* t)
137{
138 if (!t->len) return false;
139 else
140 {
141 t->l[--t->len] = 0;
142 t->needsupdate = 4;
143 return true;
144 }
145}
146
147//
148// HUlib_drawTextLine()
149//
150// Draws a hu_textline_t widget
151//
152// Passed the hu_textline_t and flag whether to draw a cursor
153// Returns nothing
154//
155void HUlib_drawTextLine
156( hu_textline_t* l,
157 boolean drawcursor )
158{
159
160 int i;
161 int w;
162 int x;
163 unsigned char c;
164 int oc = l->cm; //jff 2/17/98 remember default color
165 int y = l->y; // killough 1/18/98 -- support multiple lines
166
167 // draw the new stuff
168 x = l->x;
169 for (i=0;i<l->len;i++)
170 {
171 c = toupper(l->l[i]); //jff insure were not getting a cheap toupper conv.
172
173 if (c=='\n') // killough 1/18/98 -- support multiple lines
174 x=0,y+=8;
175 else if (c=='\t') // killough 1/23/98 -- support tab stops
176 x=x-x%80+80;
177 else if (c=='\x1b') //jff 2/17/98 escape code for color change
178 { //jff 3/26/98 changed to actual escape char
179 if (++i<l->len)
180 if (l->l[i]>='0' && l->l[i]<='9')
181 l->cm = l->l[i]-'0';
182 }
183 else if (c != ' ' && c >= l->sc && c <= 127)
184 {
185 w = SHORT(l->f[c - l->sc].width);
186 if (x+w > BASE_WIDTH)
187 break;
188 // killough 1/18/98 -- support multiple lines:
189 // CPhipps - patch drawing updated
190 V_DrawNumPatch(x, y, FG, l->f[c - l->sc].lumpnum, l->cm, VPT_TRANS | VPT_STRETCH);
191 x += w;
192 }
193 else
194 {
195 x += 4;
196 if (x >= BASE_WIDTH)
197 break;
198 }
199 }
200 l->cm = oc; //jff 2/17/98 restore original color
201
202 // draw the cursor if requested
203 if (drawcursor && x + SHORT(l->f['_' - l->sc].width) <= BASE_WIDTH)
204 {
205 // killough 1/18/98 -- support multiple lines
206 // CPhipps - patch drawing updated
207 V_DrawNumPatch(x, y, FG, l->f['_' - l->sc].lumpnum, CR_DEFAULT, VPT_NONE | VPT_STRETCH);
208 }
209}
210
211//
212// HUlib_eraseTextLine()
213//
214// Erases a hu_textline_t widget when screen border is behind text
215// Sorta called by HU_Erase and just better darn get things straight
216//
217// Passed the hu_textline_t
218// Returns nothing
219//
220void HUlib_eraseTextLine(hu_textline_t* l)
221{
222 int lh;
223 int y;
224 int yoffset;
225
226 // Only erases when NOT in automap and the screen is reduced,
227 // and the text must either need updating or refreshing
228 // (because of a recent change back from the automap)
229
230 if (!(automapmode & am_active) && viewwindowx && l->needsupdate)
231 {
232 lh = SHORT(l->f[0].height) + 1;
233 for (y=l->y,yoffset=y*SCREENWIDTH ; y<l->y+lh ; y++,yoffset+=SCREENWIDTH)
234 {
235 if (y < viewwindowy || y >= viewwindowy + viewheight)
236 R_VideoErase(yoffset, SCREENWIDTH); // erase entire line
237 else
238 {
239 // erase left border
240 R_VideoErase(yoffset, viewwindowx);
241 // erase right border
242 R_VideoErase(yoffset + viewwindowx + viewwidth, viewwindowx);
243 }
244 }
245 }
246
247 if (l->needsupdate) l->needsupdate--;
248}
249
250////////////////////////////////////////////////////////
251//
252// Player message widget (up to 4 lines of text)
253//
254////////////////////////////////////////////////////////
255
256//
257// HUlib_initSText()
258//
259// Initialize a hu_stext_t widget. Set the position, number of lines, font,
260// start char of the font, and color range to be used, and whether enabled.
261//
262// Passed a hu_stext_t, and the values used to initialize
263// Returns nothing
264//
265void HUlib_initSText
266( hu_stext_t* s,
267 int x,
268 int y,
269 int h,
270 const patchnum_t* font,
271 int startchar,
272 int cm, //jff 2/16/98 add color range parameter
273 boolean* on )
274{
275
276 int i;
277
278 s->h = h;
279 s->on = on;
280 s->laston = true;
281 s->cl = 0;
282 for (i=0;i<h;i++)
283 HUlib_initTextLine
284 (
285 &s->l[i],
286 x,
287 y - i*(SHORT(font[0].height)+1),
288 font,
289 startchar,
290 cm
291 );
292}
293
294//
295// HUlib_addLineToSText()
296//
297// Adds a blank line to a hu_stext_t widget
298//
299// Passed a hu_stext_t
300// Returns nothing
301//
302void HUlib_addLineToSText(hu_stext_t* s)
303{
304
305 int i;
306
307 // add a clear line
308 if (++s->cl == s->h)
309 s->cl = 0;
310 HUlib_clearTextLine(&s->l[s->cl]);
311
312 // everything needs updating
313 for (i=0 ; i<s->h ; i++)
314 s->l[i].needsupdate = 4;
315
316}
317
318//
319// HUlib_addMessageToSText()
320//
321// Adds a message line with prefix to a hu_stext_t widget
322//
323// Passed a hu_stext_t, the prefix string, and a message string
324// Returns nothing
325//
326void HUlib_addMessageToSText(hu_stext_t* s, const char* prefix, const char* msg)
327{
328 HUlib_addLineToSText(s);
329 if (prefix)
330 while (*prefix)
331 HUlib_addCharToTextLine(&s->l[s->cl], *(prefix++));
332
333 while (*msg)
334 HUlib_addCharToTextLine(&s->l[s->cl], *(msg++));
335}
336
337//
338// HUlib_drawSText()
339//
340// Displays a hu_stext_t widget
341//
342// Passed a hu_stext_t
343// Returns nothing
344//
345void HUlib_drawSText(hu_stext_t* s)
346{
347 int i, idx;
348 hu_textline_t *l;
349
350 if (!*s->on)
351 return; // if not on, don't draw
352
353 // draw everything
354 for (i=0 ; i<s->h ; i++)
355 {
356 idx = s->cl - i;
357 if (idx < 0)
358 idx += s->h; // handle queue of lines
359
360 l = &s->l[idx];
361
362 // need a decision made here on whether to skip the draw
363 HUlib_drawTextLine(l, false); // no cursor, please
364 }
365}
366
367//
368// HUlib_eraseSText()
369//
370// Erases a hu_stext_t widget, when the screen is not fullsize
371//
372// Passed a hu_stext_t
373// Returns nothing
374//
375void HUlib_eraseSText(hu_stext_t* s)
376{
377 int i;
378
379 for (i=0 ; i<s->h ; i++)
380 {
381 if (s->laston && !*s->on)
382 s->l[i].needsupdate = 4;
383 HUlib_eraseTextLine(&s->l[i]);
384 }
385 s->laston = *s->on;
386}
387
388////////////////////////////////////////////////////////
389//
390// Scrolling message review widget
391//
392// jff added 2/26/98
393//
394////////////////////////////////////////////////////////
395
396//
397// HUlib_initMText()
398//
399// Initialize a hu_mtext_t widget. Set the position, width, number of lines,
400// font, start char of the font, color range, background font, and whether
401// enabled.
402//
403// Passed a hu_mtext_t, and the values used to initialize
404// Returns nothing
405//
406void HUlib_initMText(hu_mtext_t *m, int x, int y, int w, int h,
407 const patchnum_t* font, int startchar, int cm,
408 const patchnum_t* bgfont, boolean *on)
409{
410 int i;
411
412 m->nl = 0;
413 m->nr = 0;
414 m->cl = -1; //jff 4/28/98 prepare for pre-increment
415 m->x = x;
416 m->y = y;
417 m->w = w;
418 m->h = h;
419 m->bg = bgfont;
420 m->on = on;
421 for (i=0;i<HU_MAXMESSAGES;i++)
422 {
423 HUlib_initTextLine
424 (
425 &m->l[i],
426 x,
427 y + (hud_list_bgon? i+1 : i)*HU_REFRESHSPACING,
428 font,
429 startchar,
430 cm
431 );
432 }
433}
434
435//
436// HUlib_addLineToMText()
437//
438// Adds a blank line to a hu_mtext_t widget
439//
440// Passed a hu_mtext_t
441// Returns nothing
442//
443void HUlib_addLineToMText(hu_mtext_t* m)
444{
445 // add a clear line
446 if (++m->cl == hud_msg_lines)
447 m->cl = 0;
448 HUlib_clearTextLine(&m->l[m->cl]);
449
450 if (m->nl<hud_msg_lines)
451 m->nl++;
452
453 // needs updating
454 m->l[m->cl].needsupdate = 4;
455}
456
457//
458// HUlib_addMessageToMText()
459//
460// Adds a message line with prefix to a hu_mtext_t widget
461//
462// Passed a hu_mtext_t, the prefix string, and a message string
463// Returns nothing
464//
465void HUlib_addMessageToMText(hu_mtext_t* m, const char* prefix, const char* msg)
466{
467 HUlib_addLineToMText(m);
468 if (prefix)
469 while (*prefix)
470 HUlib_addCharToTextLine(&m->l[m->cl], *(prefix++));
471
472 while (*msg)
473 HUlib_addCharToTextLine(&m->l[m->cl], *(msg++));
474}
475
476//
477// HUlib_drawMBg()
478//
479// Draws a background box which the message display review widget can
480// display over
481//
482// Passed position, width, height, and the background patches
483// Returns nothing
484//
485void HUlib_drawMBg
486( int x,
487 int y,
488 int w,
489 int h,
490 const patchnum_t* bgp
491)
492{
493 int xs = bgp[0].width;
494 int ys = bgp[0].height;
495 int i,j;
496
497 // CPhipps - patch drawing updated
498 // top rows
499 V_DrawNumPatch(x, y, FG, bgp[0].lumpnum, CR_DEFAULT, VPT_STRETCH); // ul
500 for (j=x+xs;j<x+w-xs;j+=xs) // uc
501 V_DrawNumPatch(j, y, FG, bgp[1].lumpnum, CR_DEFAULT, VPT_STRETCH);
502 V_DrawNumPatch(j, y, FG, bgp[2].lumpnum, CR_DEFAULT, VPT_STRETCH); // ur
503
504 // middle rows
505 for (i=y+ys;i<y+h-ys;i+=ys)
506 {
507 V_DrawNumPatch(x, i, FG, bgp[3].lumpnum, CR_DEFAULT, VPT_STRETCH); // cl
508 for (j=x+xs;j<x+w-xs;j+=xs) // cc
509 V_DrawNumPatch(j, i, FG, bgp[4].lumpnum, CR_DEFAULT, VPT_STRETCH);
510 V_DrawNumPatch(j, i, FG, bgp[5].lumpnum, CR_DEFAULT, VPT_STRETCH); // cr
511 }
512
513 // bottom row
514 V_DrawNumPatch(x, i, FG, bgp[6].lumpnum, CR_DEFAULT, VPT_STRETCH); // ll
515 for (j=x+xs;j<x+w-xs;j+=xs) // lc
516 V_DrawNumPatch(j, i, FG, bgp[7].lumpnum, CR_DEFAULT, VPT_STRETCH);
517 V_DrawNumPatch(j, i, FG, bgp[8].lumpnum, CR_DEFAULT, VPT_STRETCH); // lr
518}
519
520//
521// HUlib_drawMText()
522//
523// Displays a hu_mtext_t widget
524//
525// Passed a hu_mtext_t
526// Returns nothing
527//
528void HUlib_drawMText(hu_mtext_t* m)
529{
530 int i, idx, y;
531 hu_textline_t *l;
532
533 if (!*m->on)
534 return; // if not on, don't draw
535
536 // draw everything
537 if (hud_list_bgon)
538 HUlib_drawMBg(m->x,m->y,m->w,m->h,m->bg);
539 y = m->y + HU_REFRESHSPACING;
540 for (i=0 ; i<m->nl ; i++)
541 {
542 idx = m->cl - i;
543 if (idx < 0)
544 idx += m->nl; // handle queue of lines
545
546 l = &m->l[idx];
547 if (hud_list_bgon)
548 {
549 l->x = m->x + 4;
550 l->y = m->y + (i+1)*HU_REFRESHSPACING;
551 }
552 else
553 {
554 l->x = m->x;
555 l->y = m->y + i*HU_REFRESHSPACING;
556 }
557
558 // need a decision made here on whether to skip the draw
559 HUlib_drawTextLine(l, false); // no cursor, please
560 }
561}
562
563//
564// HUlib_eraseMBg()
565//
566// Erases background behind hu_mtext_t widget, when the screen is not fullsize
567//
568// Passed a hu_mtext_t
569// Returns nothing
570//
571static void HUlib_eraseMBg(hu_mtext_t* m)
572{
573 int lh;
574 int y;
575 int yoffset;
576
577 // Only erases when NOT in automap and the screen is reduced,
578 // and the text must either need updating or refreshing
579 // (because of a recent change back from the automap)
580
581 if (!(automapmode & am_active) && viewwindowx)
582 {
583 lh = SHORT(m->l[0].f[0].height) + 1;
584 for (y=m->y,yoffset=y*SCREENWIDTH ; y<m->y+lh*(hud_msg_lines+2) ; y++,yoffset+=SCREENWIDTH)
585 {
586 if (y < viewwindowy || y >= viewwindowy + viewheight)
587 R_VideoErase(yoffset, SCREENWIDTH); // erase entire line
588 else
589 {
590 // erase left border
591 R_VideoErase(yoffset, viewwindowx);
592 // erase right border
593 R_VideoErase(yoffset + viewwindowx + viewwidth, viewwindowx);
594
595 }
596 }
597 }
598}
599
600//
601// HUlib_eraseMText()
602//
603// Erases a hu_mtext_t widget, when the screen is not fullsize
604//
605// Passed a hu_mtext_t
606// Returns nothing
607//
608void HUlib_eraseMText(hu_mtext_t* m)
609{
610 int i;
611
612 if (hud_list_bgon)
613 HUlib_eraseMBg(m);
614
615 for (i=0 ; i< m->nl ; i++)
616 {
617 m->l[i].needsupdate = 4;
618 HUlib_eraseTextLine(&m->l[i]);
619 }
620}
621
622////////////////////////////////////////////////////////
623//
624// Interactive text entry widget
625//
626////////////////////////////////////////////////////////
627
628//
629// HUlib_initIText()
630//
631// Initialize a hu_itext_t widget. Set the position, font,
632// start char of the font, color range, and whether enabled.
633//
634// Passed a hu_itext_t, and the values used to initialize
635// Returns nothing
636//
637void HUlib_initIText
638( hu_itext_t* it,
639 int x,
640 int y,
641 const patchnum_t* font,
642 int startchar,
643 int cm, //jff 2/16/98 add color range parameter
644 boolean* on )
645{
646 it->lm = 0; // default left margin is start of text
647 it->on = on;
648 it->laston = true;
649 HUlib_initTextLine(&it->l, x, y, font, startchar, cm);
650}
651
652// The following deletion routines adhere to the left margin restriction
653
654//
655// HUlib_delCharFromIText()
656//
657// Deletes a character at the end of the text line in a hu_itext_t widget
658//
659// Passed the hu_itext_t
660// Returns nothing
661//
662void HUlib_delCharFromIText(hu_itext_t* it)
663{
664 if (it->l.len != it->lm)
665 HUlib_delCharFromTextLine(&it->l);
666}
667
668//
669// HUlib_eraseLineFromIText()
670//
671// Deletes all characters from a hu_itext_t widget
672//
673// Passed the hu_itext_t
674// Returns nothing
675//
676void HUlib_eraseLineFromIText(hu_itext_t* it)
677{
678 while (it->lm != it->l.len)
679 HUlib_delCharFromTextLine(&it->l);
680}
681
682//
683// HUlib_resetIText()
684//
685// Deletes all characters from a hu_itext_t widget
686// Resets left margin as well
687//
688// Passed the hu_itext_t
689// Returns nothing
690//
691void HUlib_resetIText(hu_itext_t* it)
692{
693 it->lm = 0;
694 HUlib_clearTextLine(&it->l);
695}
696
697//
698// HUlib_addPrefixToIText()
699//
700// Adds a prefix string passed to a hu_itext_t widget
701// Sets left margin to length of string added
702//
703// Passed the hu_itext_t and the prefix string
704// Returns nothing
705//
706void HUlib_addPrefixToIText
707( hu_itext_t* it,
708 char* str )
709{
710 while (*str)
711 HUlib_addCharToTextLine(&it->l, *(str++));
712 it->lm = it->l.len;
713}
714
715//
716// HUlib_keyInIText()
717//
718// Wrapper function for handling general keyed input.
719//
720// Passed the hu_itext_t and the char input
721// Returns true if it ate the key
722//
723boolean HUlib_keyInIText
724( hu_itext_t* it,
725 unsigned char ch )
726{
727
728 if (ch >= ' ' && ch <= '_')
729 HUlib_addCharToTextLine(&it->l, (char) ch);
730 else if (ch == key_backspace) // phares
731 HUlib_delCharFromIText(it);
732 else if (ch != key_enter) // phares
733 return false; // did not eat key
734
735 return true; // ate the key
736}
737
738//
739// HUlib_drawIText()
740//
741// Displays a hu_itext_t widget
742//
743// Passed the hu_itext_t
744// Returns nothing
745//
746void HUlib_drawIText(hu_itext_t* it)
747{
748 hu_textline_t *l = &it->l;
749
750 if (!*it->on)
751 return;
752 HUlib_drawTextLine(l, true); // draw the line w/ cursor
753}
754
755//
756// HUlib_eraseIText()
757//
758// Erases a hu_itext_t widget when the screen is not fullsize
759//
760// Passed the hu_itext_t
761// Returns nothing
762//
763void HUlib_eraseIText(hu_itext_t* it)
764{
765 if (it->laston && !*it->on)
766 it->l.needsupdate = 4;
767 HUlib_eraseTextLine(&it->l);
768 it->laston = *it->on;
769}
770
diff --git a/apps/plugins/doom/hu_lib.h b/apps/plugins/doom/hu_lib.h
new file mode 100644
index 0000000000..76d26bbb0f
--- /dev/null
+++ b/apps/plugins/doom/hu_lib.h
@@ -0,0 +1,264 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION: none
28 *
29 *-----------------------------------------------------------------------------*/
30
31#ifndef __HULIB__
32#define __HULIB__
33
34// We are referring to patches.
35#include "r_defs.h"
36#include "v_video.h" //jff 2/16/52 include color range defs
37
38
39/* background and foreground screen numbers
40 * different from other modules. */
41#define BG 1
42#define FG 0
43
44/* font stuff
45 * #define HU_CHARERASE KEYD_BACKSPACE / not used / phares
46 */
47
48#define HU_MAXLINES 4
49#define HU_MAXLINELENGTH 80
50#define HU_REFRESHSPACING 8 /*jff 2/26/98 space lines in text refresh widget*/
51/*jff 2/26/98 maximum number of messages allowed in refresh list */
52#define HU_MAXMESSAGES 16
53
54/*
55 * Typedefs of widgets
56 */
57
58/* Text Line widget
59 * (parent of Scrolling Text and Input Text widgets) */
60typedef struct
61{
62 // left-justified position of scrolling text window
63 int x;
64 int y;
65
66 const patchnum_t* f; // font
67 int sc; // start character
68 //const char *cr; //jff 2/16/52 output color range
69 // Proff - Made this an int again. Needed for OpenGL
70 int cm; //jff 2/16/52 output color range
71
72 // killough 1/23/98: Support multiple lines:
73 #define MAXLINES 25
74
75 int linelen;
76 char l[HU_MAXLINELENGTH*MAXLINES+1]; // line of text
77 int len; // current line length
78
79 // whether this line needs to be udpated
80 int needsupdate;
81
82} hu_textline_t;
83
84
85
86// Scrolling Text window widget
87// (child of Text Line widget)
88typedef struct
89{
90 hu_textline_t l[HU_MAXLINES]; // text lines to draw
91 int h; // height in lines
92 int cl; // current line number
93
94 // pointer to boolean stating whether to update window
95 boolean* on;
96 boolean laston; // last value of *->on.
97
98} hu_stext_t;
99
100//jff 2/26/98 new widget to display last hud_msg_lines of messages
101// Message refresh window widget
102typedef struct
103{
104 hu_textline_t l[HU_MAXMESSAGES]; // text lines to draw
105 int nl; // height in lines
106 int nr; // total height in rows
107 int cl; // current line number
108
109 int x,y,w,h; // window position and size
110 const patchnum_t *bg; // patches for background
111
112 // pointer to boolean stating whether to update window
113 boolean* on;
114 boolean laston; // last value of *->on.
115
116} hu_mtext_t;
117
118
119
120// Input Text Line widget
121// (child of Text Line widget)
122typedef struct
123{
124 hu_textline_t l; // text line to input on
125
126 // left margin past which I am not to delete characters
127 int lm;
128
129 // pointer to boolean stating whether to update window
130 boolean* on;
131 boolean laston; // last value of *->on;
132
133} hu_itext_t;
134
135
136//
137// Widget creation, access, and update routines
138//
139
140// initializes heads-up widget library
141void HUlib_init(void);
142
143//
144// textline code
145//
146
147// clear a line of text
148void HUlib_clearTextLine(hu_textline_t *t);
149
150void HUlib_initTextLine
151(
152 hu_textline_t *t,
153 int x,
154 int y,
155 const patchnum_t *f,
156 int sc,
157 int cm //jff 2/16/98 add color range parameter
158);
159
160// returns success
161boolean HUlib_addCharToTextLine(hu_textline_t *t, char ch);
162
163// returns success
164boolean HUlib_delCharFromTextLine(hu_textline_t *t);
165
166// draws tline
167void HUlib_drawTextLine(hu_textline_t *l, boolean drawcursor);
168
169// erases text line
170void HUlib_eraseTextLine(hu_textline_t *l);
171
172
173//
174// Scrolling Text window widget routines
175//
176
177// initialize an stext widget
178void HUlib_initSText
179( hu_stext_t* s,
180 int x,
181 int y,
182 int h,
183 const patchnum_t* font,
184 int startchar,
185 int cm, //jff 2/16/98 add color range parameter
186 boolean* on );
187
188// add a new line
189void HUlib_addLineToSText(hu_stext_t* s);
190
191// add a text message to an stext widget
192void HUlib_addMessageToSText(hu_stext_t* s, const char* prefix, const char* msg);
193
194// draws stext
195void HUlib_drawSText(hu_stext_t* s);
196
197// erases all stext lines
198void HUlib_eraseSText(hu_stext_t* s);
199
200//jff 2/26/98 message refresh widget
201// initialize refresh text widget
202void HUlib_initMText(hu_mtext_t *m, int x, int y, int w, int h, const patchnum_t* font,
203 int startchar, int cm, const patchnum_t* bgfont, boolean *on);
204
205//jff 2/26/98 message refresh widget
206// add a text line to refresh text widget
207void HUlib_addLineToMText( hu_mtext_t* m );
208
209//jff 2/26/98 message refresh widget
210// add a text message to refresh text widget
211void HUlib_addMessageToMText(hu_mtext_t* m, const char* prefix, const char* msg);
212
213//jff 2/26/98 new routine to display a background on which
214// the list of last hud_msg_lines are displayed
215void HUlib_drawMBg
216( int x,
217 int y,
218 int w,
219 int h,
220 const patchnum_t* bgp
221);
222
223//jff 2/26/98 message refresh widget
224// draws mtext
225void HUlib_drawMText(hu_mtext_t* m);
226
227//jff 4/28/98 erases behind message list
228void HUlib_eraseMText(hu_mtext_t* m);
229
230// Input Text Line widget routines
231void HUlib_initIText
232( hu_itext_t* it,
233 int x,
234 int y,
235 const patchnum_t* font,
236 int startchar,
237 int cm, //jff 2/16/98 add color range parameter
238 boolean* on );
239
240// enforces left margin
241void HUlib_delCharFromIText(hu_itext_t* it);
242
243// enforces left margin
244void HUlib_eraseLineFromIText(hu_itext_t* it);
245
246// resets line and left margin
247void HUlib_resetIText(hu_itext_t* it);
248
249// left of left-margin
250void HUlib_addPrefixToIText
251( hu_itext_t* it,
252 char* str );
253
254// whether eaten
255boolean HUlib_keyInIText
256( hu_itext_t* it,
257 unsigned char ch );
258
259void HUlib_drawIText(hu_itext_t* it);
260
261// erases all itext lines
262void HUlib_eraseIText(hu_itext_t* it);
263
264#endif
diff --git a/apps/plugins/doom/hu_stuff.c b/apps/plugins/doom/hu_stuff.c
new file mode 100644
index 0000000000..fd7bd0d4f4
--- /dev/null
+++ b/apps/plugins/doom/hu_stuff.c
@@ -0,0 +1,1753 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION: Heads-up displays
28 *
29 *-----------------------------------------------------------------------------
30 */
31
32// killough 5/3/98: remove unnecessary headers
33
34#include "doomstat.h"
35#include "hu_stuff.h"
36#include "hu_lib.h"
37#include "st_stuff.h" /* jff 2/16/98 need loc of status bar */
38#include "w_wad.h"
39#include "s_sound.h"
40#include "dstrings.h"
41#include "sounds.h"
42//#include "d_deh.h" /* Ty 03/27/98 - externalization of mapnamesx arrays */
43#include "g_game.h"
44#include "m_swap.h"
45
46// global heads up display controls
47
48int hud_active; //jff 2/17/98 controls heads-up display mode
49int hud_displayed; //jff 2/23/98 turns heads-up display on/off
50int hud_nosecrets; //jff 2/18/98 allows secrets line to be disabled in HUD
51int hud_distributed; //jff 3/4/98 display HUD in different places on screen
52int hud_graph_keys=1; //jff 3/7/98 display HUD keys as graphics
53
54//
55// Locally used constants, shortcuts.
56//
57// Ty 03/28/98 -
58// These four shortcuts modifed to reflect char ** of mapnamesx[]
59#define HU_TITLE (mapnames[(gameepisode-1)*9+gamemap-1])
60#define HU_TITLE2 (mapnames2[gamemap-1])
61#define HU_TITLEP (mapnamesp[gamemap-1])
62#define HU_TITLET (mapnamest[gamemap-1])
63#define HU_TITLEHEIGHT 1
64#define HU_TITLEX 0
65//jff 2/16/98 change 167 to ST_Y-1
66// CPhipps - changed to ST_TY
67// proff - changed to 200-ST_HEIGHT for stretching
68#define HU_TITLEY ((200-ST_HEIGHT) - 1 - SHORT(hu_font[0].height))
69
70//jff 2/16/98 add coord text widget coordinates
71// proff - changed to SCREENWIDTH to 320 for stretching
72#define HU_COORDX (320 - 13*SHORT(hu_font2['A'-HU_FONTSTART].width))
73//jff 3/3/98 split coord widget into three lines in upper right of screen
74#define HU_COORDX_Y (1 + 0*SHORT(hu_font['A'-HU_FONTSTART].height))
75#define HU_COORDY_Y (2 + 1*SHORT(hu_font['A'-HU_FONTSTART].height))
76#define HU_COORDZ_Y (3 + 2*SHORT(hu_font['A'-HU_FONTSTART].height))
77
78//jff 2/16/98 add ammo, health, armor widgets, 2/22/98 less gap
79#define HU_GAPY 8
80#define HU_HUDHEIGHT (6*HU_GAPY)
81#define HU_HUDX 2
82#define HU_HUDY (200-HU_HUDHEIGHT-1)
83#define HU_MONSECX (HU_HUDX)
84#define HU_MONSECY (HU_HUDY+0*HU_GAPY)
85#define HU_KEYSX (HU_HUDX)
86//jff 3/7/98 add offset for graphic key widget
87#define HU_KEYSGX (HU_HUDX+4*SHORT(hu_font2['A'-HU_FONTSTART].width))
88#define HU_KEYSY (HU_HUDY+1*HU_GAPY)
89#define HU_WEAPX (HU_HUDX)
90#define HU_WEAPY (HU_HUDY+2*HU_GAPY)
91#define HU_AMMOX (HU_HUDX)
92#define HU_AMMOY (HU_HUDY+3*HU_GAPY)
93#define HU_HEALTHX (HU_HUDX)
94#define HU_HEALTHY (HU_HUDY+4*HU_GAPY)
95#define HU_ARMORX (HU_HUDX)
96#define HU_ARMORY (HU_HUDY+5*HU_GAPY)
97
98//jff 3/4/98 distributed HUD positions
99#define HU_HUDX_LL 2
100#define HU_HUDY_LL (200-2*HU_GAPY-1)
101// proff/nicolas 09/20/98: Changed for high-res
102#define HU_HUDX_LR (320-120)
103#define HU_HUDY_LR (200-2*HU_GAPY-1)
104// proff/nicolas 09/20/98: Changed for high-res
105#define HU_HUDX_UR (320-96)
106#define HU_HUDY_UR 2
107#define HU_MONSECX_D (HU_HUDX_LL)
108#define HU_MONSECY_D (HU_HUDY_LL+0*HU_GAPY)
109#define HU_KEYSX_D (HU_HUDX_LL)
110#define HU_KEYSGX_D (HU_HUDX_LL+4*SHORT(hu_font2['A'-HU_FONTSTART].width))
111#define HU_KEYSY_D (HU_HUDY_LL+1*HU_GAPY)
112#define HU_WEAPX_D (HU_HUDX_LR)
113#define HU_WEAPY_D (HU_HUDY_LR+0*HU_GAPY)
114#define HU_AMMOX_D (HU_HUDX_LR)
115#define HU_AMMOY_D (HU_HUDY_LR+1*HU_GAPY)
116#define HU_HEALTHX_D (HU_HUDX_UR)
117#define HU_HEALTHY_D (HU_HUDY_UR+0*HU_GAPY)
118#define HU_ARMORX_D (HU_HUDX_UR)
119#define HU_ARMORY_D (HU_HUDY_UR+1*HU_GAPY)
120
121//#define HU_INPUTTOGGLE 't' // not used // phares
122#define HU_INPUTX HU_MSGX
123#define HU_INPUTY (HU_MSGY + HU_MSGHEIGHT*(SHORT(hu_font[0].height) +1))
124#define HU_INPUTWIDTH 64
125#define HU_INPUTHEIGHT 1
126
127#define key_alt KEY_RALT
128#define key_shift KEY_RSHIFT
129
130const char* chat_macros[] =
131 // Ty 03/27/98 - *not* externalized
132 // CPhipps - const char*
133 {
134 HUSTR_CHATMACRO0,
135 HUSTR_CHATMACRO1,
136 HUSTR_CHATMACRO2,
137 HUSTR_CHATMACRO3,
138 HUSTR_CHATMACRO4,
139 HUSTR_CHATMACRO5,
140 HUSTR_CHATMACRO6,
141 HUSTR_CHATMACRO7,
142 HUSTR_CHATMACRO8,
143 HUSTR_CHATMACRO9
144 };
145
146const char* player_names[] =
147 // Ty 03/27/98 - *not* externalized
148 // CPhipps - const char*
149 {
150 HUSTR_PLRGREEN,
151 HUSTR_PLRINDIGO,
152 HUSTR_PLRBROWN,
153 HUSTR_PLRRED
154 };
155
156//jff 3/17/98 translate player colmap to text color ranges
157int plyrcoltran[MAXPLAYERS]={CR_GREEN,CR_GRAY,CR_BROWN,CR_RED};
158
159char chat_char; // remove later.
160static player_t* plr;
161
162// font sets
163patchnum_t hu_font[HU_FONTSIZE];
164patchnum_t hu_font2[HU_FONTSIZE];
165patchnum_t hu_fontk[HU_FONTSIZE];//jff 3/7/98 added for graphic key indicators
166patchnum_t hu_msgbg[9]; //jff 2/26/98 add patches for message background
167
168// widgets
169static hu_textline_t w_title;
170static hu_stext_t w_message;
171static hu_itext_t w_chat;
172static hu_itext_t w_inputbuffer[MAXPLAYERS];
173static hu_textline_t w_coordx; //jff 2/16/98 new coord widget for automap
174static hu_textline_t w_coordy; //jff 3/3/98 split coord widgets automap
175static hu_textline_t w_coordz; //jff 3/3/98 split coord widgets automap
176static hu_textline_t w_ammo; //jff 2/16/98 new ammo widget for hud
177static hu_textline_t w_health; //jff 2/16/98 new health widget for hud
178static hu_textline_t w_armor; //jff 2/16/98 new armor widget for hud
179static hu_textline_t w_weapon; //jff 2/16/98 new weapon widget for hud
180static hu_textline_t w_keys; //jff 2/16/98 new keys widget for hud
181static hu_textline_t w_gkeys; //jff 3/7/98 graphic keys widget for hud
182static hu_textline_t w_monsec; //jff 2/16/98 new kill/secret widget for hud
183static hu_mtext_t w_rtext; //jff 2/26/98 text message refresh widget
184
185static boolean always_off = false;
186static char chat_dest[MAXPLAYERS];
187boolean chat_on;
188static boolean message_on;
189static boolean message_list; //2/26/98 enable showing list of messages
190boolean message_dontfuckwithme;
191static boolean message_nottobefuckedwith;
192static int message_counter;
193extern int showMessages;
194extern boolean automapactive;
195static boolean headsupactive = false;
196
197//jff 2/16/98 hud supported automap colors added
198int hudcolor_titl; // color range of automap level title
199int hudcolor_xyco; // color range of new coords on automap
200//jff 2/16/98 hud text colors, controls added
201int hudcolor_mesg; // color range of scrolling messages
202int hudcolor_chat; // color range of chat lines
203int hud_msg_lines; // number of message lines in window
204//jff 2/26/98 hud text colors, controls added
205int hudcolor_list; // list of messages color
206int hud_list_bgon; // enable for solid window background for message list
207
208//jff 2/16/98 initialization strings for ammo, health, armor widgets
209static char hud_coordstrx[32];
210static char hud_coordstry[32];
211static char hud_coordstrz[32];
212static char hud_ammostr[80];
213static char hud_healthstr[80];
214static char hud_armorstr[80];
215static char hud_weapstr[80];
216static char hud_keysstr[80];
217static char hud_gkeysstr[80]; //jff 3/7/98 add support for graphic key display
218static char hud_monsecstr[80];
219
220//jff 2/16/98 declaration of color switch points
221extern int ammo_red;
222extern int ammo_yellow;
223extern int health_red;
224extern int health_yellow;
225extern int health_green;
226extern int armor_red;
227extern int armor_yellow;
228extern int armor_green;
229
230//
231// Builtin map names.
232// The actual names can be found in DStrings.h.
233//
234// Ty 03/27/98 - externalized map name arrays - now in d_deh.c
235// and converted to arrays of pointers to char *
236// See modified HUTITLEx macros
237char* mapnames[] = // DOOM shareware/registered/retail (Ultimate) names.
238 {
239
240 HUSTR_E1M1,
241 HUSTR_E1M2,
242 HUSTR_E1M3,
243 HUSTR_E1M4,
244 HUSTR_E1M5,
245 HUSTR_E1M6,
246 HUSTR_E1M7,
247 HUSTR_E1M8,
248 HUSTR_E1M9,
249
250 HUSTR_E2M1,
251 HUSTR_E2M2,
252 HUSTR_E2M3,
253 HUSTR_E2M4,
254 HUSTR_E2M5,
255 HUSTR_E2M6,
256 HUSTR_E2M7,
257 HUSTR_E2M8,
258 HUSTR_E2M9,
259
260 HUSTR_E3M1,
261 HUSTR_E3M2,
262 HUSTR_E3M3,
263 HUSTR_E3M4,
264 HUSTR_E3M5,
265 HUSTR_E3M6,
266 HUSTR_E3M7,
267 HUSTR_E3M8,
268 HUSTR_E3M9,
269
270 HUSTR_E4M1,
271 HUSTR_E4M2,
272 HUSTR_E4M3,
273 HUSTR_E4M4,
274 HUSTR_E4M5,
275 HUSTR_E4M6,
276 HUSTR_E4M7,
277 HUSTR_E4M8,
278 HUSTR_E4M9,
279
280 "NEWLEVEL",
281 "NEWLEVEL",
282 "NEWLEVEL",
283 "NEWLEVEL",
284 "NEWLEVEL",
285 "NEWLEVEL",
286 "NEWLEVEL",
287 "NEWLEVEL",
288 "NEWLEVEL"
289 };
290
291char* mapnames2[] = // DOOM 2 map names.
292 {
293 HUSTR_1,
294 HUSTR_2,
295 HUSTR_3,
296 HUSTR_4,
297 HUSTR_5,
298 HUSTR_6,
299 HUSTR_7,
300 HUSTR_8,
301 HUSTR_9,
302 HUSTR_10,
303 HUSTR_11,
304
305 HUSTR_12,
306 HUSTR_13,
307 HUSTR_14,
308 HUSTR_15,
309 HUSTR_16,
310 HUSTR_17,
311 HUSTR_18,
312 HUSTR_19,
313 HUSTR_20,
314
315 HUSTR_21,
316 HUSTR_22,
317 HUSTR_23,
318 HUSTR_24,
319 HUSTR_25,
320 HUSTR_26,
321 HUSTR_27,
322 HUSTR_28,
323 HUSTR_29,
324 HUSTR_30,
325 HUSTR_31,
326 HUSTR_32
327 };
328
329
330char* mapnamesp[] = // Plutonia WAD map names.
331 {
332 PHUSTR_1,
333 PHUSTR_2,
334 PHUSTR_3,
335 PHUSTR_4,
336 PHUSTR_5,
337 PHUSTR_6,
338 PHUSTR_7,
339 PHUSTR_8,
340 PHUSTR_9,
341 PHUSTR_10,
342 PHUSTR_11,
343
344 PHUSTR_12,
345 PHUSTR_13,
346 PHUSTR_14,
347 PHUSTR_15,
348 PHUSTR_16,
349 PHUSTR_17,
350 PHUSTR_18,
351 PHUSTR_19,
352 PHUSTR_20,
353
354 PHUSTR_21,
355 PHUSTR_22,
356 PHUSTR_23,
357 PHUSTR_24,
358 PHUSTR_25,
359 PHUSTR_26,
360 PHUSTR_27,
361 PHUSTR_28,
362 PHUSTR_29,
363 PHUSTR_30,
364 PHUSTR_31,
365 PHUSTR_32
366 };
367
368
369char *mapnamest[] = // TNT WAD map names.
370 {
371 THUSTR_1,
372 THUSTR_2,
373 THUSTR_3,
374 THUSTR_4,
375 THUSTR_5,
376 THUSTR_6,
377 THUSTR_7,
378 THUSTR_8,
379 THUSTR_9,
380 THUSTR_10,
381 THUSTR_11,
382
383 THUSTR_12,
384 THUSTR_13,
385 THUSTR_14,
386 THUSTR_15,
387 THUSTR_16,
388 THUSTR_17,
389 THUSTR_18,
390 THUSTR_19,
391 THUSTR_20,
392
393 THUSTR_21,
394 THUSTR_22,
395 THUSTR_23,
396 THUSTR_24,
397 THUSTR_25,
398 THUSTR_26,
399 THUSTR_27,
400 THUSTR_28,
401 THUSTR_29,
402 THUSTR_30,
403 THUSTR_31,
404 THUSTR_32
405 };
406
407// key tables
408// jff 5/10/98 french support removed,
409// as it was not being used and couldn't be easily tested
410//
411const char* shiftxform;
412
413const char english_shiftxform[] =
414 {
415 0,
416 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
417 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
418 21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
419 31,
420 ' ', '!', '"', '#', '$', '%', '&',
421 '"', // shift-'
422 '(', ')', '*', '+',
423 '<', // shift-,
424 '_', // shift--
425 '>', // shift-.
426 '?', // shift-/
427 ')', // shift-0
428 '!', // shift-1
429 '@', // shift-2
430 '#', // shift-3
431 '$', // shift-4
432 '%', // shift-5
433 '^', // shift-6
434 '&', // shift-7
435 '*', // shift-8
436 '(', // shift-9
437 ':',
438 ':', // shift-;
439 '<',
440 '+', // shift-=
441 '>', '?', '@',
442 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
443 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
444 '[', // shift-[
445 '!', // shift-backslash - OH MY GOD DOES WATCOM SUCK
446 ']', // shift-]
447 '"', '_',
448 '\'', // shift-`
449 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
450 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
451 '{', '|', '}', '~', 127
452 };
453
454//
455// HU_Init()
456//
457// Initialize the heads-up display, text that overwrites the primary display
458//
459// Passed nothing, returns nothing
460//
461void HU_Init(void)
462{
463 int i;
464 int j;
465 char buffer[9];
466
467 shiftxform = english_shiftxform;
468
469 // load the heads-up font
470 j = HU_FONTSTART;
471 for (i=0;i<HU_FONTSIZE;i++,j++)
472 {
473 if ('0'<=j && j<='9')
474 {
475 snprintf(buffer, sizeof(buffer), "DIG%d",j-48);
476 R_SetPatchNum(&hu_font2[i], buffer);
477 snprintf(buffer, sizeof(buffer), "STCFN%s%d", (j/10>0?"0":"00"), j); //NOTE ROCKHACK: "STCFN%.3d"
478 R_SetPatchNum(&hu_font[i], buffer);
479 }
480 else if ('A'<=j && j<='Z')
481 {
482 snprintf(buffer, sizeof(buffer), "DIG%c",j);
483 R_SetPatchNum(&hu_font2[i], buffer);
484 snprintf(buffer, sizeof(buffer), "STCFN%s%d", (j/10>0?"0":"00"), j); //NOTE ROCKHACK: "STCFN%.3d"
485 R_SetPatchNum(&hu_font[i], buffer);
486 }
487 else if (j=='-')
488 {
489 R_SetPatchNum(&hu_font2[i], "DIG45");
490 R_SetPatchNum(&hu_font[i], "STCFN045");
491 }
492 else if (j=='/')
493 {
494 R_SetPatchNum(&hu_font2[i], "DIG47");
495 R_SetPatchNum(&hu_font[i], "STCFN047");
496 }
497 else if (j==':')
498 {
499 R_SetPatchNum(&hu_font2[i], "DIG58");
500 R_SetPatchNum(&hu_font[i], "STCFN058");
501 }
502 else if (j=='[')
503 {
504 R_SetPatchNum(&hu_font2[i], "DIG91");
505 R_SetPatchNum(&hu_font[i], "STCFN091");
506 }
507 else if (j==']')
508 {
509 R_SetPatchNum(&hu_font2[i], "DIG93");
510 R_SetPatchNum(&hu_font[i], "STCFN093");
511 }
512 else if (j<97)
513 {
514 snprintf(buffer, sizeof(buffer), "STCFN%s%d", (j/10>0?"0":"00"), j); //NOTE ROCKHACK: "STCFN%.3d"
515 R_SetPatchNum(&hu_font2[i], buffer);
516 R_SetPatchNum(&hu_font[i], buffer);
517 //jff 2/23/98 make all font chars defined, useful or not
518 }
519 else if (j>122)
520 {
521 snprintf(buffer, sizeof(buffer), "STBR%d", j); //NOTE: "STBR%.3d"
522 R_SetPatchNum(&hu_font2[i], buffer);
523 R_SetPatchNum(&hu_font[i], buffer);
524 }
525 else
526 hu_font[i] = hu_font[0]; //jff 2/16/98 account for gap
527 }
528
529 // CPhipps - load patches for message background
530 for (i=0; i<9; i++) {
531 snprintf(buffer, sizeof(buffer), "BOX%c%c", "UCL"[i/3], "LCR"[i%3]);
532 R_SetPatchNum(&hu_msgbg[i], buffer);
533 }
534
535 // CPhipps - load patches for keys and double keys
536 for (i=0; i<6; i++) {
537 snprintf(buffer, sizeof(buffer), "STKEYS%d", i);
538 R_SetPatchNum(&hu_fontk[i], buffer);
539 }
540}
541
542//
543// HU_Stop()
544//
545// Make the heads-up displays inactive
546//
547// Passed nothing, returns nothing
548//
549void HU_Stop(void)
550{
551 headsupactive = false;
552}
553
554//
555// HU_Start(void)
556//
557// Create and initialize the heads-up widgets, software machines to
558// maintain, update, and display information over the primary display
559//
560// This routine must be called after any change to the heads up configuration
561// in order for the changes to take effect in the actual displays
562//
563// Passed nothing, returns nothing
564//
565void HU_Start(void)
566{
567
568 int i;
569 const char* s; /* cph - const */
570
571 if (headsupactive) // stop before starting
572 HU_Stop();
573
574 plr = &players[displayplayer]; // killough 3/7/98
575 message_on = false;
576 message_dontfuckwithme = false;
577 message_nottobefuckedwith = false;
578 chat_on = false;
579
580 // create the message widget
581 // messages to player in upper-left of screen
582 HUlib_initSText
583 (
584 &w_message,
585 HU_MSGX,
586 HU_MSGY,
587 HU_MSGHEIGHT,
588 hu_font,
589 HU_FONTSTART,
590 hudcolor_mesg,
591 &message_on
592 );
593
594 //jff 2/16/98 added some HUD widgets
595 // create the map title widget - map title display in lower left of automap
596 HUlib_initTextLine
597 (
598 &w_title,
599 HU_TITLEX,
600 HU_TITLEY,
601 hu_font,
602 HU_FONTSTART,
603 hudcolor_titl
604 );
605
606 // create the hud health widget
607 // bargraph and number for amount of health,
608 // lower left or upper right of screen
609 HUlib_initTextLine
610 (
611 &w_health,
612 hud_distributed? HU_HEALTHX_D : HU_HEALTHX, //3/4/98 distribute
613 hud_distributed? HU_HEALTHY_D : HU_HEALTHY,
614 hu_font2,
615 HU_FONTSTART,
616 CR_GREEN
617 );
618
619 // create the hud armor widget
620 // bargraph and number for amount of armor,
621 // lower left or upper right of screen
622 HUlib_initTextLine
623 (
624 &w_armor,
625 hud_distributed? HU_ARMORX_D : HU_ARMORX, //3/4/98 distribute
626 hud_distributed? HU_ARMORY_D : HU_ARMORY,
627 hu_font2,
628 HU_FONTSTART,
629 CR_GREEN
630 );
631
632 // create the hud ammo widget
633 // bargraph and number for amount of ammo for current weapon,
634 // lower left or lower right of screen
635 HUlib_initTextLine
636 (
637 &w_ammo,
638 hud_distributed? HU_AMMOX_D : HU_AMMOX, //3/4/98 distribute
639 hud_distributed? HU_AMMOY_D : HU_AMMOY,
640 hu_font2,
641 HU_FONTSTART,
642 CR_GOLD
643 );
644
645 // create the hud weapons widget
646 // list of numbers of weapons possessed
647 // lower left or lower right of screen
648 HUlib_initTextLine
649 (
650 &w_weapon,
651 hud_distributed? HU_WEAPX_D : HU_WEAPX, //3/4/98 distribute
652 hud_distributed? HU_WEAPY_D : HU_WEAPY,
653 hu_font2,
654 HU_FONTSTART,
655 CR_GRAY
656 );
657
658 // create the hud keys widget
659 // display of key letters possessed
660 // lower left of screen
661 HUlib_initTextLine
662 (
663 &w_keys,
664 hud_distributed? HU_KEYSX_D : HU_KEYSX, //3/4/98 distribute
665 hud_distributed? HU_KEYSY_D : HU_KEYSY,
666 hu_font2,
667 HU_FONTSTART,
668 CR_GRAY
669 );
670
671 // create the hud graphic keys widget
672 // display of key graphics possessed
673 // lower left of screen
674 HUlib_initTextLine
675 (
676 &w_gkeys,
677 hud_distributed? HU_KEYSGX_D : HU_KEYSGX, //3/4/98 distribute
678 hud_distributed? HU_KEYSY_D : HU_KEYSY,
679 hu_fontk,
680 HU_FONTSTART,
681 CR_RED
682 );
683
684 // create the hud monster/secret widget
685 // totals and current values for kills, items, secrets
686 // lower left of screen
687 HUlib_initTextLine
688 (
689 &w_monsec,
690 hud_distributed? HU_MONSECX_D : HU_MONSECX, //3/4/98 distribute
691 hud_distributed? HU_MONSECY_D : HU_MONSECY,
692 hu_font2,
693 HU_FONTSTART,
694 CR_GRAY
695 );
696
697 // create the hud text refresh widget
698 // scrolling display of last hud_msg_lines messages received
699 if (hud_msg_lines>HU_MAXMESSAGES)
700 hud_msg_lines=HU_MAXMESSAGES;
701 //jff 4/21/98 if setup has disabled message list while active, turn it off
702 message_list = hud_msg_lines > 1; //jff 8/8/98 initialize both ways
703 //jff 2/26/98 add the text refresh widget initialization
704 HUlib_initMText
705 (
706 &w_rtext,
707 0,
708 0,
709 320,
710 // SCREENWIDTH,
711 (hud_msg_lines+2)*HU_REFRESHSPACING,
712 hu_font,
713 HU_FONTSTART,
714 hudcolor_list,
715 hu_msgbg,
716 &message_list
717 );
718
719 // initialize the automap's level title widget
720 if (gamestate == GS_LEVEL) /* cph - stop SEGV here when not in level */
721 switch (gamemode)
722 {
723 case shareware:
724 case registered:
725 case retail:
726 s = HU_TITLE;
727 break;
728
729 case commercial:
730 default: // Ty 08/27/98 - modified to check mission for TNT/Plutonia
731 s = (gamemission==pack_tnt) ? HU_TITLET :
732 (gamemission==pack_plut) ? HU_TITLEP : HU_TITLE2;
733 break;
734 } else s = "";
735 while (*s)
736 HUlib_addCharToTextLine(&w_title, *(s++));
737
738 // create the automaps coordinate widget
739 // jff 3/3/98 split coord widget into three lines: x,y,z
740 // jff 2/16/98 added
741 HUlib_initTextLine
742 (
743 &w_coordx,
744 HU_COORDX,
745 HU_COORDX_Y,
746 hu_font,
747 HU_FONTSTART,
748 hudcolor_xyco
749 );
750 HUlib_initTextLine
751 (
752 &w_coordy,
753 HU_COORDX,
754 HU_COORDY_Y,
755 hu_font,
756 HU_FONTSTART,
757 hudcolor_xyco
758 );
759 HUlib_initTextLine
760 (
761 &w_coordz,
762 HU_COORDX,
763 HU_COORDZ_Y,
764 hu_font,
765 HU_FONTSTART,
766 hudcolor_xyco
767 );
768
769 // initialize the automaps coordinate widget
770 //jff 3/3/98 split coordstr widget into 3 parts
771 snprintf(hud_coordstrx,sizeof(hud_coordstrx),"X: %-5d",0); //jff 2/22/98 added z
772 s = hud_coordstrx;
773 while (*s)
774 HUlib_addCharToTextLine(&w_coordx, *(s++));
775 snprintf(hud_coordstry,sizeof(hud_coordstry),"Y: %-5d",0); //jff 3/3/98 split x,y,z
776 s = hud_coordstry;
777 while (*s)
778 HUlib_addCharToTextLine(&w_coordy, *(s++));
779 snprintf(hud_coordstrz,sizeof(hud_coordstrz),"Z: %-5d",0); //jff 3/3/98 split x,y,z
780 s = hud_coordstrz;
781 while (*s)
782 HUlib_addCharToTextLine(&w_coordz, *(s++));
783
784 //jff 2/16/98 initialize ammo widget
785 strcpy(hud_ammostr,"AMM ");
786 s = hud_ammostr;
787 while (*s)
788 HUlib_addCharToTextLine(&w_ammo, *(s++));
789
790 //jff 2/16/98 initialize health widget
791 strcpy(hud_healthstr,"HEL ");
792 s = hud_healthstr;
793 while (*s)
794 HUlib_addCharToTextLine(&w_health, *(s++));
795
796 //jff 2/16/98 initialize armor widget
797 strcpy(hud_armorstr,"ARM ");
798 s = hud_armorstr;
799 while (*s)
800 HUlib_addCharToTextLine(&w_armor, *(s++));
801
802 //jff 2/17/98 initialize weapons widget
803 strcpy(hud_weapstr,"WEA ");
804 s = hud_weapstr;
805 while (*s)
806 HUlib_addCharToTextLine(&w_weapon, *(s++));
807
808 //jff 2/17/98 initialize keys widget
809 if (!deathmatch) //jff 3/17/98 show frags in deathmatch mode
810 strcpy(hud_keysstr,"KEY ");
811 else
812 strcpy(hud_keysstr,"FRG ");
813 s = hud_keysstr;
814 while (*s)
815 HUlib_addCharToTextLine(&w_keys, *(s++));
816
817 //jff 2/17/98 initialize graphic keys widget
818 strcpy(hud_gkeysstr," ");
819 s = hud_gkeysstr;
820 while (*s)
821 HUlib_addCharToTextLine(&w_gkeys, *(s++));
822
823 //jff 2/17/98 initialize kills/items/secret widget
824 strcpy(hud_monsecstr,"STS ");
825 s = hud_monsecstr;
826 while (*s)
827 HUlib_addCharToTextLine(&w_monsec, *(s++));
828
829 // create the chat widget
830 HUlib_initIText
831 (
832 &w_chat,
833 HU_INPUTX,
834 HU_INPUTY,
835 hu_font,
836 HU_FONTSTART,
837 hudcolor_chat,
838 &chat_on
839 );
840
841 // create the inputbuffer widgets, one per player
842 for (i=0 ; i<MAXPLAYERS ; i++)
843 HUlib_initIText
844 (
845 &w_inputbuffer[i],
846 0,
847 0,
848 0,
849 0,
850 hudcolor_chat,
851 &always_off
852 );
853
854 // now allow the heads-up display to run
855 headsupactive = true;
856}
857
858//
859// HU_MoveHud()
860//
861// Move the HUD display from distributed to compact mode or vice-versa
862//
863// Passed nothing, returns nothing
864//
865//jff 3/9/98 create this externally callable to avoid glitch
866// when menu scatter's HUD due to delay in change of position
867//
868void HU_MoveHud(void)
869{
870 static int ohud_distributed=-1;
871
872 //jff 3/4/98 move displays around on F5 changing hud_distributed
873 if (hud_distributed!=ohud_distributed)
874 {
875 w_ammo.x = hud_distributed? HU_AMMOX_D : HU_AMMOX;
876 w_ammo.y = hud_distributed? HU_AMMOY_D : HU_AMMOY;
877 w_weapon.x = hud_distributed? HU_WEAPX_D : HU_WEAPX;
878 w_weapon.y = hud_distributed? HU_WEAPY_D : HU_WEAPY;
879 w_keys.x = hud_distributed? HU_KEYSX_D : HU_KEYSX;
880 w_keys.y = hud_distributed? HU_KEYSY_D : HU_KEYSY;
881 w_gkeys.x = hud_distributed? HU_KEYSGX_D : HU_KEYSGX;
882 w_gkeys.y = hud_distributed? HU_KEYSY_D : HU_KEYSY;
883 w_monsec.x = hud_distributed? HU_MONSECX_D : HU_MONSECX;
884 w_monsec.y = hud_distributed? HU_MONSECY_D : HU_MONSECY;
885 w_health.x = hud_distributed? HU_HEALTHX_D : HU_HEALTHX;
886 w_health.y = hud_distributed? HU_HEALTHY_D : HU_HEALTHY;
887 w_armor.x = hud_distributed? HU_ARMORX_D : HU_ARMORX;
888 w_armor.y = hud_distributed? HU_ARMORY_D : HU_ARMORY;
889 }
890 ohud_distributed = hud_distributed;
891}
892
893//
894// HU_Drawer()
895//
896// Draw all the pieces of the heads-up display
897//
898// Passed nothing, returns nothing
899//
900void HU_Drawer(void)
901{
902 char *s;
903 player_t *plr;
904 char ammostr[80]; //jff 3/8/98 allow plenty room for dehacked mods
905 char healthstr[80];//jff
906 char armorstr[80]; //jff
907 int i,doit;
908
909 plr = &players[displayplayer]; // killough 3/7/98
910 // draw the automap widgets if automap is displayed
911 if (automapmode & am_active)
912 {
913 // map title
914 HUlib_drawTextLine(&w_title, false);
915
916 //jff 2/16/98 output new coord display
917 // x-coord
918 snprintf(hud_coordstrx,sizeof(hud_coordstrx),"X: %-5d", (plr->mo->x)>>FRACBITS);
919 HUlib_clearTextLine(&w_coordx);
920 s = hud_coordstrx;
921 while (*s)
922 HUlib_addCharToTextLine(&w_coordx, *(s++));
923 HUlib_drawTextLine(&w_coordx, false);
924
925 //jff 3/3/98 split coord display into x,y,z lines
926 // y-coord
927 snprintf(hud_coordstry,sizeof(hud_coordstry),"Y: %-5d", (plr->mo->y)>>FRACBITS);
928 HUlib_clearTextLine(&w_coordy);
929 s = hud_coordstry;
930 while (*s)
931 HUlib_addCharToTextLine(&w_coordy, *(s++));
932 HUlib_drawTextLine(&w_coordy, false);
933
934 //jff 3/3/98 split coord display into x,y,z lines
935 //jff 2/22/98 added z
936 // z-coord
937 snprintf(hud_coordstrz,sizeof(hud_coordstrz),"Z: %-5d", (plr->mo->z)>>FRACBITS);
938 HUlib_clearTextLine(&w_coordz);
939 s = hud_coordstrz;
940 while (*s)
941 HUlib_addCharToTextLine(&w_coordz, *(s++));
942 HUlib_drawTextLine(&w_coordz, false);
943 }
944
945 // draw the weapon/health/ammo/armor/kills/keys displays if optioned
946 //jff 2/17/98 allow new hud stuff to be turned off
947 // killough 2/21/98: really allow new hud stuff to be turned off COMPLETELY
948 if
949 (
950 hud_active>0 && // hud optioned on
951 hud_displayed && // hud on from fullscreen key
952 viewheight==SCREENHEIGHT && // fullscreen mode is active
953 !(automapmode & am_active) // automap is not active
954 )
955 {
956 doit = !(gametic&1); //jff 3/4/98 speed update up for slow systems
957 if (doit) //jff 8/7/98 update every time, avoid lag in update
958 {
959 HU_MoveHud(); // insure HUD display coords are correct
960
961 // do the hud ammo display
962 // clear the widgets internal line
963 HUlib_clearTextLine(&w_ammo);
964 strcpy(hud_ammostr,"AMM ");
965 if (weaponinfo[plr->readyweapon].ammo == am_noammo)
966 { // special case for weapon with no ammo selected - blank bargraph + N/A
967 strcat(hud_ammostr,"\x7f\x7f\x7f\x7f\x7f\x7f\x7f N/A");
968 w_ammo.cm = CR_GRAY;
969 }
970 else
971 {
972 int ammo = plr->ammo[weaponinfo[plr->readyweapon].ammo];
973 int fullammo = plr->maxammo[weaponinfo[plr->readyweapon].ammo];
974 int ammopct = (100*ammo)/fullammo;
975 int ammobars = ammopct/4;
976
977 // build the numeric amount init string
978 snprintf(ammostr,sizeof(ammostr),"%d/%d",ammo,fullammo);
979 // build the bargraph string
980 // full bargraph chars
981 for (i=4;i<4+ammobars/4;)
982 hud_ammostr[i++] = 123;
983 // plus one last character with 0,1,2,3 bars
984 switch(ammobars%4)
985 {
986 case 0:
987 break;
988 case 1:
989 hud_ammostr[i++] = 126;
990 break;
991 case 2:
992 hud_ammostr[i++] = 125;
993 break;
994 case 3:
995 hud_ammostr[i++] = 124;
996 break;
997 }
998 // pad string with blank bar characters
999 while(i<4+7)
1000 hud_ammostr[i++] = 127;
1001 hud_ammostr[i] = '\0';
1002 strcat(hud_ammostr,ammostr);
1003
1004 // set the display color from the percentage of total ammo held
1005 if (ammopct<ammo_red)
1006 w_ammo.cm = CR_RED;
1007 else if (ammopct<ammo_yellow)
1008 w_ammo.cm = CR_GOLD;
1009 else
1010 w_ammo.cm = CR_GREEN;
1011 }
1012 // transfer the init string to the widget
1013 s = hud_ammostr;
1014 while (*s)
1015 HUlib_addCharToTextLine(&w_ammo, *(s++));
1016 }
1017 // display the ammo widget every frame
1018 HUlib_drawTextLine(&w_ammo, false);
1019
1020 // do the hud health display
1021 if (doit)
1022 {
1023 int health = plr->health;
1024 int healthbars = health>100? 25 : health/4;
1025
1026 // clear the widgets internal line
1027 HUlib_clearTextLine(&w_health);
1028
1029 // build the numeric amount init string
1030 snprintf(healthstr,sizeof(healthstr),"%3d",health);
1031 // build the bargraph string
1032 // full bargraph chars
1033 for (i=4;i<4+healthbars/4;)
1034 hud_healthstr[i++] = 123;
1035 // plus one last character with 0,1,2,3 bars
1036 switch(healthbars%4)
1037 {
1038 case 0:
1039 break;
1040 case 1:
1041 hud_healthstr[i++] = 126;
1042 break;
1043 case 2:
1044 hud_healthstr[i++] = 125;
1045 break;
1046 case 3:
1047 hud_healthstr[i++] = 124;
1048 break;
1049 }
1050 // pad string with blank bar characters
1051 while(i<4+7)
1052 hud_healthstr[i++] = 127;
1053 hud_healthstr[i] = '\0';
1054 strcat(hud_healthstr,healthstr);
1055
1056 // set the display color from the amount of health posessed
1057 if (health<health_red)
1058 w_health.cm = CR_RED;
1059 else if (health<health_yellow)
1060 w_health.cm = CR_GOLD;
1061 else if (health<=health_green)
1062 w_health.cm = CR_GREEN;
1063 else
1064 w_health.cm = CR_BLUE;
1065
1066 // transfer the init string to the widget
1067 s = hud_healthstr;
1068 while (*s)
1069 HUlib_addCharToTextLine(&w_health, *(s++));
1070 }
1071 // display the health widget every frame
1072 HUlib_drawTextLine(&w_health, false);
1073
1074 // do the hud armor display
1075 if (doit)
1076 {
1077 int armor = plr->armorpoints;
1078 int armorbars = armor>100? 25 : armor/4;
1079
1080 // clear the widgets internal line
1081 HUlib_clearTextLine(&w_armor);
1082 // build the numeric amount init string
1083 snprintf(armorstr,sizeof(armorstr),"%3d",armor);
1084 // build the bargraph string
1085 // full bargraph chars
1086 for (i=4;i<4+armorbars/4;)
1087 hud_armorstr[i++] = 123;
1088 // plus one last character with 0,1,2,3 bars
1089 switch(armorbars%4)
1090 {
1091 case 0:
1092 break;
1093 case 1:
1094 hud_armorstr[i++] = 126;
1095 break;
1096 case 2:
1097 hud_armorstr[i++] = 125;
1098 break;
1099 case 3:
1100 hud_armorstr[i++] = 124;
1101 break;
1102 }
1103 // pad string with blank bar characters
1104 while(i<4+7)
1105 hud_armorstr[i++] = 127;
1106 hud_armorstr[i] = '\0';
1107 strcat(hud_armorstr,armorstr);
1108
1109 // set the display color from the amount of armor posessed
1110 if (armor<armor_red)
1111 w_armor.cm = CR_RED;
1112 else if (armor<armor_yellow)
1113 w_armor.cm = CR_GOLD;
1114 else if (armor<=armor_green)
1115 w_armor.cm = CR_GREEN;
1116 else
1117 w_armor.cm = CR_BLUE;
1118
1119 // transfer the init string to the widget
1120 s = hud_armorstr;
1121 while (*s)
1122 HUlib_addCharToTextLine(&w_armor, *(s++));
1123 }
1124 // display the armor widget every frame
1125 HUlib_drawTextLine(&w_armor, false);
1126
1127 // do the hud weapon display
1128 if (doit)
1129 {
1130 int w;
1131 int ammo,fullammo,ammopct;
1132
1133 // clear the widgets internal line
1134 HUlib_clearTextLine(&w_weapon);
1135 i=4; hud_weapstr[i] = '\0'; //jff 3/7/98 make sure ammo goes away
1136
1137 // do each weapon that exists in current gamemode
1138 for (w=0;w<=wp_supershotgun;w++) //jff 3/4/98 show fists too, why not?
1139 {
1140 int ok=1;
1141 //jff avoid executing for weapons that do not exist
1142 switch (gamemode)
1143 {
1144 case shareware:
1145 if (w>=wp_plasma && w!=wp_chainsaw)
1146 ok=0;
1147 break;
1148 case retail:
1149 case registered:
1150 if (w>=wp_supershotgun)
1151 ok=0;
1152 break;
1153 default:
1154 case commercial:
1155 break;
1156 }
1157 if (!ok) continue;
1158
1159 ammo = plr->ammo[weaponinfo[w].ammo];
1160 fullammo = plr->maxammo[weaponinfo[w].ammo];
1161 ammopct=0;
1162
1163 // skip weapons not currently posessed
1164 if (!plr->weaponowned[w])
1165 continue;
1166
1167 ammopct = fullammo? (100*ammo)/fullammo : 100;
1168
1169 // display each weapon number in a color related to the ammo for it
1170 hud_weapstr[i++] = '\x1b'; //jff 3/26/98 use ESC not '\' for paths
1171 if (weaponinfo[w].ammo==am_noammo) //jff 3/14/98 show berserk on HUD
1172 hud_weapstr[i++] = plr->powers[pw_strength]? '0'+CR_GREEN : '0'+CR_GRAY;
1173 else if (ammopct<ammo_red)
1174 hud_weapstr[i++] = '0'+CR_RED;
1175 else if (ammopct<ammo_yellow)
1176 hud_weapstr[i++] = '0'+CR_GOLD;
1177 else
1178 hud_weapstr[i++] = '0'+CR_GREEN;
1179 hud_weapstr[i++] = '0'+w+1;
1180 hud_weapstr[i++] = ' ';
1181 hud_weapstr[i] = '\0';
1182 }
1183
1184 // transfer the init string to the widget
1185 s = hud_weapstr;
1186 while (*s)
1187 HUlib_addCharToTextLine(&w_weapon, *(s++));
1188 }
1189 // display the weapon widget every frame
1190 HUlib_drawTextLine(&w_weapon, false);
1191
1192 if (doit && hud_active>1)
1193 {
1194 int k;
1195
1196 hud_keysstr[4] = '\0'; //jff 3/7/98 make sure deleted keys go away
1197 //jff add case for graphic key display
1198 if (!deathmatch && hud_graph_keys)
1199 {
1200 i=0;
1201 hud_gkeysstr[i] = '\0'; //jff 3/7/98 init graphic keys widget string
1202 // build text string whose characters call out graphic keys from fontk
1203 for (k=0;k<6;k++)
1204 {
1205 // skip keys not possessed
1206 if (!plr->cards[k])
1207 continue;
1208
1209 hud_gkeysstr[i++] = '!'+k; // key number plus '!' is char for key
1210 hud_gkeysstr[i++] = ' '; // spacing
1211 hud_gkeysstr[i++] = ' ';
1212 }
1213 hud_gkeysstr[i]='\0';
1214 }
1215 else // not possible in current code, unless deathmatching,
1216 {
1217 i=4;
1218 hud_keysstr[i] = '\0'; //jff 3/7/98 make sure deleted keys go away
1219
1220 // if deathmatch, build string showing top four frag counts
1221 if (deathmatch) //jff 3/17/98 show frags, not keys, in deathmatch
1222 {
1223 int top1=-999,top2=-999,top3=-999,top4=-999;
1224 int idx1=-1,idx2=-1,idx3=-1,idx4=-1;
1225 int fragcount,m;
1226 char numbuf[32];
1227
1228 // scan thru players
1229 for (k=0;k<MAXPLAYERS;k++)
1230 {
1231 // skip players not in game
1232 if (!playeringame[k])
1233 continue;
1234
1235 fragcount = 0;
1236 // compute number of times they've fragged each player
1237 // minus number of times they've been fragged by them
1238 for (m=0;m<MAXPLAYERS;m++)
1239 {
1240 if (!playeringame[m]) continue;
1241 fragcount += (m!=k)? players[k].frags[m] : -players[k].frags[m];
1242 }
1243
1244 // very primitive sort of frags to find top four
1245 if (fragcount>top1)
1246 {
1247 top4=top3; top3=top2; top2 = top1; top1=fragcount;
1248 idx4=idx3; idx3=idx2; idx2 = idx1; idx1=k;
1249 }
1250 else if (fragcount>top2)
1251 {
1252 top4=top3; top3=top2; top2=fragcount;
1253 idx4=idx3; idx3=idx2; idx2=k;
1254 }
1255 else if (fragcount>top3)
1256 {
1257 top4=top3; top3=fragcount;
1258 idx4=idx3; idx3=k;
1259 }
1260 else if (fragcount>top4)
1261 {
1262 top4=fragcount;
1263 idx4=k;
1264 }
1265 }
1266 // if the biggest number exists, put it in the init string
1267 if (idx1>-1)
1268 {
1269 snprintf(numbuf,sizeof(numbuf),"%5d",top1);
1270 // make frag count in player's color via escape code
1271 hud_keysstr[i++] = '\x1b'; //jff 3/26/98 use ESC not '\' for paths
1272 hud_keysstr[i++] = '0'+plyrcoltran[idx1&3];
1273 s = numbuf;
1274 while (*s)
1275 hud_keysstr[i++] = *(s++);
1276 }
1277 // if the second biggest number exists, put it in the init string
1278 if (idx2>-1)
1279 {
1280 snprintf(numbuf,sizeof(numbuf),"%5d",top2);
1281 // make frag count in player's color via escape code
1282 hud_keysstr[i++] = '\x1b'; //jff 3/26/98 use ESC not '\' for paths
1283 hud_keysstr[i++] = '0'+plyrcoltran[idx2&3];
1284 s = numbuf;
1285 while (*s)
1286 hud_keysstr[i++] = *(s++);
1287 }
1288 // if the third biggest number exists, put it in the init string
1289 if (idx3>-1)
1290 {
1291 snprintf(numbuf,sizeof(numbuf),"%5d",top3);
1292 // make frag count in player's color via escape code
1293 hud_keysstr[i++] = '\x1b'; //jff 3/26/98 use ESC not '\' for paths
1294 hud_keysstr[i++] = '0'+plyrcoltran[idx3&3];
1295 s = numbuf;
1296 while (*s)
1297 hud_keysstr[i++] = *(s++);
1298 }
1299 // if the fourth biggest number exists, put it in the init string
1300 if (idx4>-1)
1301 {
1302 snprintf(numbuf,sizeof(numbuf),"%5d",top4);
1303 // make frag count in player's color via escape code
1304 hud_keysstr[i++] = '\x1b'; //jff 3/26/98 use ESC not '\' for paths
1305 hud_keysstr[i++] = '0'+plyrcoltran[idx4&3];
1306 s = numbuf;
1307 while (*s)
1308 hud_keysstr[i++] = *(s++);
1309 }
1310 hud_keysstr[i] = '\0';
1311 } //jff 3/17/98 end of deathmatch clause
1312 else // build alphabetical key display (not used currently)
1313 {
1314 // scan the keys
1315 for (k=0;k<6;k++)
1316 {
1317 // skip any not possessed by the displayed player's stats
1318 if (!plr->cards[k])
1319 continue;
1320
1321 // use color escapes to make text in key's color
1322 hud_keysstr[i++] = '\x1b'; //jff 3/26/98 use ESC not '\' for paths
1323 switch(k)
1324 {
1325 case 0:
1326 hud_keysstr[i++] = '0'+CR_BLUE;
1327 hud_keysstr[i++] = 'B';
1328 hud_keysstr[i++] = 'C';
1329 hud_keysstr[i++] = ' ';
1330 break;
1331 case 1:
1332 hud_keysstr[i++] = '0'+CR_GOLD;
1333 hud_keysstr[i++] = 'Y';
1334 hud_keysstr[i++] = 'C';
1335 hud_keysstr[i++] = ' ';
1336 break;
1337 case 2:
1338 hud_keysstr[i++] = '0'+CR_RED;
1339 hud_keysstr[i++] = 'R';
1340 hud_keysstr[i++] = 'C';
1341 hud_keysstr[i++] = ' ';
1342 break;
1343 case 3:
1344 hud_keysstr[i++] = '0'+CR_BLUE;
1345 hud_keysstr[i++] = 'B';
1346 hud_keysstr[i++] = 'S';
1347 hud_keysstr[i++] = ' ';
1348 break;
1349 case 4:
1350 hud_keysstr[i++] = '0'+CR_GOLD;
1351 hud_keysstr[i++] = 'Y';
1352 hud_keysstr[i++] = 'S';
1353 hud_keysstr[i++] = ' ';
1354 break;
1355 case 5:
1356 hud_keysstr[i++] = '0'+CR_RED;
1357 hud_keysstr[i++] = 'R';
1358 hud_keysstr[i++] = 'S';
1359 hud_keysstr[i++] = ' ';
1360 break;
1361 }
1362 hud_keysstr[i]='\0';
1363 }
1364 }
1365 }
1366 }
1367 // display the keys/frags line each frame
1368 if (hud_active>1)
1369 {
1370 HUlib_clearTextLine(&w_keys); // clear the widget strings
1371 HUlib_clearTextLine(&w_gkeys);
1372
1373 // transfer the built string (frags or key title) to the widget
1374 s = hud_keysstr; //jff 3/7/98 display key titles/key text or frags
1375 while (*s)
1376 HUlib_addCharToTextLine(&w_keys, *(s++));
1377 HUlib_drawTextLine(&w_keys, false);
1378
1379 //jff 3/17/98 show graphic keys in non-DM only
1380 if (!deathmatch) //jff 3/7/98 display graphic keys
1381 {
1382 // transfer the graphic key text to the widget
1383 s = hud_gkeysstr;
1384 while (*s)
1385 HUlib_addCharToTextLine(&w_gkeys, *(s++));
1386 // display the widget
1387 HUlib_drawTextLine(&w_gkeys, false);
1388 }
1389 }
1390
1391 // display the hud kills/items/secret display if optioned
1392 if (!hud_nosecrets)
1393 {
1394 if (hud_active>1 && doit)
1395 {
1396 // clear the internal widget text buffer
1397 HUlib_clearTextLine(&w_monsec);
1398 //jff 3/26/98 use ESC not '\' for paths
1399 // build the init string with fixed colors
1400 snprintf
1401 (
1402 hud_monsecstr,sizeof(hud_monsecstr),
1403 "STS \x1b\x36K \x1b\x33%d \x1b\x36M \x1b\x33%d \x1b\x37I \x1b\x33%d/%d \x1b\x35S \x1b\x33%d/%d",
1404 plr->killcount,totallive,
1405 plr->itemcount,totalitems,
1406 plr->secretcount,totalsecret
1407 );
1408 // transfer the init string to the widget
1409 s = hud_monsecstr;
1410 while (*s)
1411 HUlib_addCharToTextLine(&w_monsec, *(s++));
1412 }
1413 // display the kills/items/secrets each frame, if optioned
1414 if (hud_active>1)
1415 HUlib_drawTextLine(&w_monsec, false);
1416 }
1417 }
1418
1419 //jff 3/4/98 display last to give priority
1420 HU_Erase(); // jff 4/24/98 Erase current lines before drawing current
1421 // needed when screen not fullsize
1422
1423 //jff 4/21/98 if setup has disabled message list while active, turn it off
1424 if (hud_msg_lines<=1)
1425 message_list = false;
1426
1427 // if the message review not enabled, show the standard message widget
1428 if (!message_list)
1429 HUlib_drawSText(&w_message);
1430
1431 // if the message review is enabled show the scrolling message review
1432 if (hud_msg_lines>1 && message_list)
1433 HUlib_drawMText(&w_rtext);
1434
1435 // display the interactive buffer for chat entry
1436 HUlib_drawIText(&w_chat);
1437}
1438
1439//
1440// HU_Erase()
1441//
1442// Erase hud display lines that can be trashed by small screen display
1443//
1444// Passed nothing, returns nothing
1445//
1446void HU_Erase(void)
1447{
1448 // erase the message display or the message review display
1449 if (!message_list)
1450 HUlib_eraseSText(&w_message);
1451 else
1452 HUlib_eraseMText(&w_rtext);
1453
1454 // erase the interactive text buffer for chat entry
1455 HUlib_eraseIText(&w_chat);
1456
1457 // erase the automap title
1458 HUlib_eraseTextLine(&w_title);
1459}
1460
1461//
1462// HU_Ticker()
1463//
1464// Update the hud displays once per frame
1465//
1466// Passed nothing, returns nothing
1467//
1468static boolean bsdown; // Is backspace down?
1469static int bscounter;
1470
1471void HU_Ticker(void)
1472{
1473 int i, rc;
1474 char c;
1475
1476 // tick down message counter if message is up
1477 if (message_counter && !--message_counter)
1478 {
1479 message_on = false;
1480 message_nottobefuckedwith = false;
1481 }
1482 if (bsdown && bscounter++ > 9) {
1483 HUlib_keyInIText(&w_chat, (unsigned char)key_backspace);
1484 bscounter = 8;
1485 }
1486
1487 // if messages on, or "Messages Off" is being displayed
1488 // this allows the notification of turning messages off to be seen
1489 if (showMessages || message_dontfuckwithme)
1490 {
1491 // display message if necessary
1492 if ((plr->message && !message_nottobefuckedwith)
1493 || (plr->message && message_dontfuckwithme))
1494 {
1495 //post the message to the message widget
1496 HUlib_addMessageToSText(&w_message, 0, plr->message);
1497 //jff 2/26/98 add message to refresh text widget too
1498 HUlib_addMessageToMText(&w_rtext, 0, plr->message);
1499
1500 // clear the message to avoid posting multiple times
1501 plr->message = 0;
1502 // note a message is displayed
1503 message_on = true;
1504 // start the message persistence counter
1505 message_counter = HU_MSGTIMEOUT;
1506 // transfer "Messages Off" exception to the "being displayed" variable
1507 message_nottobefuckedwith = message_dontfuckwithme;
1508 // clear the flag that "Messages Off" is being posted
1509 message_dontfuckwithme = 0;
1510 }
1511 }
1512
1513 // check for incoming chat characters
1514 if (netgame)
1515 {
1516 for (i=0; i<MAXPLAYERS; i++)
1517 {
1518 if (!playeringame[i])
1519 continue;
1520 if (i != consoleplayer
1521 && (c = players[i].cmd.chatchar))
1522 {
1523 if (c <= HU_BROADCAST)
1524 chat_dest[i] = c;
1525 else
1526 {
1527 if (c >= 'a' && c <= 'z')
1528 c = (char) shiftxform[(unsigned char) c];
1529 rc = HUlib_keyInIText(&w_inputbuffer[i], c);
1530 if (rc && c == KEY_ENTER)
1531 {
1532 if (w_inputbuffer[i].l.len
1533 && (chat_dest[i] == consoleplayer+1
1534 || chat_dest[i] == HU_BROADCAST))
1535 {
1536 HUlib_addMessageToSText(&w_message,
1537 player_names[i],
1538 w_inputbuffer[i].l.l);
1539
1540 message_nottobefuckedwith = true;
1541 message_on = true;
1542 message_counter = HU_MSGTIMEOUT;
1543 if ( gamemode == commercial )
1544 S_StartSound(0, sfx_radio);
1545 else
1546 S_StartSound(0, sfx_tink);
1547 }
1548 HUlib_resetIText(&w_inputbuffer[i]);
1549 }
1550 }
1551 players[i].cmd.chatchar = 0;
1552 }
1553 }
1554 }
1555}
1556
1557#define QUEUESIZE 128
1558
1559static char chatchars[QUEUESIZE];
1560static int head = 0;
1561static int tail = 0;
1562
1563//
1564// HU_queueChatChar()
1565//
1566// Add an incoming character to the circular chat queue
1567//
1568// Passed the character to queue, returns nothing
1569//
1570void HU_queueChatChar(char c)
1571{
1572 if (((head + 1) & (QUEUESIZE-1)) == tail)
1573 {
1574 plr->message = HUSTR_MSGU;
1575 }
1576 else
1577 {
1578 chatchars[head] = c;
1579 head = (head + 1) & (QUEUESIZE-1);
1580 }
1581}
1582
1583//
1584// HU_dequeueChatChar()
1585//
1586// Remove the earliest added character from the circular chat queue
1587//
1588// Passed nothing, returns the character dequeued
1589//
1590char HU_dequeueChatChar(void)
1591{
1592 char c;
1593
1594 if (head != tail)
1595 {
1596 c = chatchars[tail];
1597 tail = (tail + 1) & (QUEUESIZE-1);
1598 }
1599 else
1600 {
1601 c = 0;
1602 }
1603 return c;
1604}
1605
1606//
1607// HU_Responder()
1608//
1609// Responds to input events that affect the heads up displays
1610//
1611// Passed the event to respond to, returns true if the event was handled
1612//
1613boolean HU_Responder(event_t *ev)
1614{
1615
1616 static char lastmessage[HU_MAXLINELENGTH+1];
1617 const char* macromessage; // CPhipps - const char*
1618 boolean eatkey = false;
1619 static boolean shiftdown = false;
1620 static boolean altdown = false;
1621 unsigned char c;
1622 int i;
1623 int numplayers;
1624
1625 static int num_nobrainers = 0;
1626
1627 numplayers = 0;
1628 for (i=0 ; i<MAXPLAYERS ; i++)
1629 numplayers += playeringame[i];
1630
1631 if (ev->data1 == key_shift)
1632 {
1633 shiftdown = ev->type == ev_keydown;
1634 return false;
1635 }
1636 else if (ev->data1 == key_alt)
1637 {
1638 altdown = ev->type == ev_keydown;
1639 return false;
1640 }
1641 else if (ev->data1 == key_backspace)
1642 {
1643 bsdown = ev->type == ev_keydown;
1644 bscounter = 0;
1645 }
1646
1647 if (ev->type != ev_keydown)
1648 return false;
1649
1650 if (!chat_on)
1651 {
1652 if (ev->data1 == key_enter) // phares
1653 {
1654#ifndef INSTRUMENTED // never turn on message review if INSTRUMENTED defined
1655 if (hud_msg_lines>1) // it posts multi-line messages that will trash
1656 {
1657 if (message_list) HU_Erase(); //jff 4/28/98 erase behind messages
1658 message_list = !message_list; //jff 2/26/98 toggle list of messages
1659 }
1660#endif
1661 if (!message_list) // if not message list, refresh message
1662 {
1663 message_on = true;
1664 message_counter = HU_MSGTIMEOUT;
1665 }
1666 eatkey = true;
1667 }//jff 2/26/98 no chat if message review is displayed
1668 else if (!message_list && netgame && ev->data1 == key_chat)
1669 {
1670 eatkey = chat_on = true;
1671 HUlib_resetIText(&w_chat);
1672 HU_queueChatChar(HU_BROADCAST);
1673 }//jff 2/26/98 no chat if message review is displayed
1674 // killough 10/02/98: no chat if demo playback
1675 else if (!demoplayback && !message_list && netgame && numplayers > 2)
1676 {
1677 for (i=0; i<MAXPLAYERS ; i++)
1678 {
1679 if (ev->data1 == destination_keys[i])
1680 {
1681 if (playeringame[i] && i!=consoleplayer)
1682 {
1683 eatkey = chat_on = true;
1684 HUlib_resetIText(&w_chat);
1685 HU_queueChatChar((char)(i+1));
1686 break;
1687 }
1688 else if (i == consoleplayer)
1689 {
1690 num_nobrainers++;
1691 if (num_nobrainers < 3)
1692 plr->message = HUSTR_TALKTOSELF1;
1693 else if (num_nobrainers < 6)
1694 plr->message = HUSTR_TALKTOSELF2;
1695 else if (num_nobrainers < 9)
1696 plr->message = HUSTR_TALKTOSELF3;
1697 else if (num_nobrainers < 32)
1698 plr->message = HUSTR_TALKTOSELF4;
1699 else
1700 plr->message = HUSTR_TALKTOSELF5;
1701 }
1702 }
1703 }
1704 }
1705 }//jff 2/26/98 no chat functions if message review is displayed
1706 else if (!message_list)
1707 {
1708 c = ev->data1;
1709 // send a macro
1710 if (altdown)
1711 {
1712 c = c - '0';
1713 if (c > 9)
1714 return false;
1715 macromessage = chat_macros[c];
1716
1717 // kill last message with a '\n'
1718 HU_queueChatChar((char)key_enter); // DEBUG!!! // phares
1719
1720 // send the macro message
1721 while (*macromessage)
1722 HU_queueChatChar(*macromessage++);
1723 HU_queueChatChar((char)key_enter); // phares
1724
1725 // leave chat mode and notify that it was sent
1726 chat_on = false;
1727 strcpy(lastmessage, chat_macros[c]);
1728 plr->message = lastmessage;
1729 eatkey = true;
1730 }
1731 else
1732 {
1733 if (shiftdown || (c >= 'a' && c <= 'z'))
1734 c = shiftxform[c];
1735 eatkey = HUlib_keyInIText(&w_chat, c);
1736 if (eatkey)
1737 HU_queueChatChar(c);
1738
1739 if (c == key_enter) // phares
1740 {
1741 chat_on = false;
1742 if (w_chat.l.len)
1743 {
1744 strcpy(lastmessage, w_chat.l.l);
1745 plr->message = lastmessage;
1746 }
1747 }
1748 else if (c == key_escape) // phares
1749 chat_on = false;
1750 }
1751 }
1752 return eatkey;
1753}
diff --git a/apps/plugins/doom/hu_stuff.h b/apps/plugins/doom/hu_stuff.h
new file mode 100644
index 0000000000..76c6a90313
--- /dev/null
+++ b/apps/plugins/doom/hu_stuff.h
@@ -0,0 +1,92 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION: Head up display
28 *
29 *-----------------------------------------------------------------------------*/
30
31#ifndef __HU_STUFF_H__
32#define __HU_STUFF_H__
33
34#include "d_event.h"
35
36/*
37 * Globally visible constants.
38 */
39#define HU_FONTSTART '!' /* the first font characters */
40#define HU_FONTEND (0x7f) /*jff 2/16/98 '_' the last font characters */
41
42/* Calculate # of glyphs in font. */
43#define HU_FONTSIZE (HU_FONTEND - HU_FONTSTART + 1)
44
45#define HU_BROADCAST 5
46
47/*#define HU_MSGREFRESH KEYD_ENTER phares */
48#define HU_MSGX 0
49#define HU_MSGY 0
50#define HU_MSGWIDTH 64 /* in characters */
51#define HU_MSGHEIGHT 1 /* in lines */
52
53#define HU_MSGTIMEOUT (4*TICRATE)
54
55/*
56 * Heads up text
57 */
58void HU_Init(void);
59void HU_Start(void);
60
61boolean HU_Responder(event_t* ev);
62
63void HU_Ticker(void);
64void HU_Drawer(void);
65char HU_dequeueChatChar(void);
66void HU_Erase(void);
67
68/* killough 5/2/98: moved from m_misc.c: */
69
70/* jff 2/16/98 hud supported automap colors added */
71extern int hudcolor_titl; /* color range of automap level title */
72extern int hudcolor_xyco; /* color range of new coords on automap */
73/* jff 2/16/98 hud text colors, controls added */
74extern int hudcolor_mesg; /* color range of scrolling messages */
75extern int hudcolor_chat; /* color range of chat lines */
76/* jff 2/26/98 hud message list color and background enable */
77extern int hudcolor_list; /* color of list of past messages */
78extern int hud_list_bgon; /* solid window background for list of messages */
79extern int hud_msg_lines; /* number of message lines in window up to 16 */
80extern int hud_distributed; /* whether hud is all in lower left or distributed */
81/* jff 2/23/98 hud is currently displayed */
82extern int hud_displayed; /* hud is displayed */
83/* jff 2/18/98 hud/status control */
84extern int hud_active; /* hud mode 0=off, 1=small, 2=full */
85extern int hud_nosecrets; /* status does not list secrets/items/kills */
86
87extern char* mapnames[];
88extern char* mapnames2[];
89extern char* mapnamesp[];
90extern char* mapnamest[];
91
92#endif
diff --git a/apps/plugins/doom/i_sound.c b/apps/plugins/doom/i_sound.c
new file mode 100644
index 0000000000..471b0ee193
--- /dev/null
+++ b/apps/plugins/doom/i_sound.c
@@ -0,0 +1,607 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION:
28 * System interface for sound.
29 *
30 *-----------------------------------------------------------------------------
31 */
32
33#include "z_zone.h"
34
35#include "i_system.h"
36#include "i_sound.h"
37#include "m_argv.h"
38#include "m_misc.h"
39#include "w_wad.h"
40#include "m_swap.h"
41#include "d_main.h"
42#include "doomdef.h"
43#include "rockmacros.h"
44
45// The number of internal mixing channels,
46// the samples calculated for each mixing step,
47// the size of the 16bit, 2 hardware channel (stereo)
48// mixing buffer, and the samplerate of the raw data.
49
50// Needed for calling the actual sound output.
51#define SAMPLECOUNT 512
52
53#define NUM_CHANNELS 16
54// It is 2 for 16bit, and 2 for two channels.
55#define BUFMUL 4
56#define MIXBUFFERSIZE (SAMPLECOUNT*BUFMUL)
57
58#define SAMPLERATE 11025 // 44100 22050 11025
59#define SAMPLESIZE 2 // 16bit
60
61// The global mixing buffer.
62// Basically, samples from all active internal channels
63// are modifed and added, and stored in the buffer
64// that is submitted to the audio device.
65signed short mixbuffer[MIXBUFFERSIZE];
66
67typedef struct {
68 // SFX id of the playing sound effect.
69 // Used to catch duplicates (like chainsaw).
70 int id;
71 // The channel step amount...
72 unsigned int step;
73 // ... and a 0.16 bit remainder of last step.
74 unsigned int stepremainder;
75 unsigned int samplerate;
76 // The channel data pointers, start and end.
77 const unsigned char* data;
78 const unsigned char* enddata;
79 // Time/gametic that the channel started playing,
80 // used to determine oldest, which automatically
81 // has lowest priority.
82 // In case number of active sounds exceeds
83 // available channels.
84 int starttime;
85 // Hardware left and right channel volume lookup.
86 int *leftvol_lookup;
87 int *rightvol_lookup;
88} channel_info_t;
89
90channel_info_t channelinfo[NUM_CHANNELS];
91
92int *vol_lookup; // Volume lookups.
93
94int steptable[256]; // Pitch to stepping lookup. (Not setup properly right now)
95
96//
97// This function loads the sound data from the WAD lump for single sound.
98// It is used to cache all the sounddata at startup.
99//
100void* getsfx( const char* sfxname )
101{
102 unsigned char* sfx;
103 unsigned char* paddedsfx;
104 int size;
105 char name[20];
106 int sfxlump;
107
108 // Get the sound data from the WAD, allocate lump
109 // in zone memory.
110 snprintf(name, sizeof(name), "ds%s", sfxname);
111
112 // Now, there is a severe problem with the sound handling, in it is not
113 // (yet/anymore) gamemode aware. That means, sounds from DOOM II will be
114 // requested even with DOOM shareware.
115 // The sound list is wired into sounds.c, which sets the external variable.
116 // I do not do runtime patches to that variable. Instead, we will use a
117 // default sound for replacement.
118 if ( W_CheckNumForName(name) == -1 )
119 sfxlump = W_GetNumForName("dspistol");
120 else
121 sfxlump = W_GetNumForName(name);
122
123 size = W_LumpLength( sfxlump );
124
125 sfx = (unsigned char*)W_CacheLumpNum( sfxlump);
126
127 paddedsfx = (unsigned char*)malloc( size ); // Allocate from memory.
128 memcpy(paddedsfx, sfx, size ); // Now copy and pad.
129 W_UnlockLumpNum(sfxlump); // Remove the cached lump.
130
131 return (void *) (paddedsfx); // Return allocated data.
132}
133
134/* cph
135 * stopchan
136 * Stops a sound
137 */
138static void stopchan(int i)
139{
140 channelinfo[i].data=NULL;
141}
142
143//
144// This function adds a sound to the
145// list of currently active sounds,
146// which is maintained as a given number
147// (eight, usually) of internal channels.
148// Returns a handle.
149//
150int addsfx( int sfxid, int channel)
151{
152 stopchan(channel);
153
154 // We will handle the new SFX.
155 // Set pointer to raw data.
156 {
157 int lump = S_sfx[sfxid].lumpnum;
158 size_t len = W_LumpLength(lump);
159
160 /* Find padded length */
161 len -= 8;
162 channelinfo[channel].data = S_sfx[sfxid].data;
163
164 /* Set pointer to end of raw data. */
165 channelinfo[channel].enddata = channelinfo[channel].data + len - 1;
166 channelinfo[channel].samplerate = (channelinfo[channel].data[3]<<8)+channelinfo[channel].data[2];
167 channelinfo[channel].data += 8; /* Skip header */
168 }
169
170 channelinfo[channel].stepremainder = 0;
171 // Should be gametic, I presume.
172 channelinfo[channel].starttime = gametic;
173
174 // Preserve sound SFX id,
175 // e.g. for avoiding duplicates of chainsaw.
176 channelinfo[channel].id = sfxid;
177
178 return channel;
179}
180
181static void updateSoundParams(int handle, int volume, int seperation, int pitch)
182{
183 int rightvol;
184 int leftvol;
185 int slot = handle;
186 int step = steptable[pitch];
187#ifdef RANGECHECK
188 if (handle>=NUM_CHANNELS)
189 I_Error("I_UpdateSoundParams: handle out of range");
190#endif
191 // Set stepping
192 // MWM 2000-12-24: Calculates proportion of channel samplerate
193 // to global samplerate for mixing purposes.
194 // Patched to shift left *then* divide, to minimize roundoff errors
195 // as well as to use SAMPLERATE as defined above, not to assume 11025 Hz
196 if (pitched_sounds)
197 channelinfo[slot].step = step + (((channelinfo[slot].samplerate<<16)/SAMPLERATE)-65536);
198 else
199 channelinfo[slot].step = ((channelinfo[slot].samplerate<<16)/SAMPLERATE);
200
201 // Separation, that is, orientation/stereo.
202 // range is: 1 - 256
203 seperation += 1;
204
205 // Per left/right channel.
206 // x^2 seperation,
207 // adjust volume properly.
208 leftvol = volume - ((volume*seperation*seperation) >> 16);
209 seperation = seperation - 257;
210 rightvol= volume - ((volume*seperation*seperation) >> 16);
211
212 // Sanity check, clamp volume.
213 if (rightvol < 0 || rightvol > 127)
214 I_Error("rightvol out of bounds");
215
216 if (leftvol < 0 || leftvol > 127)
217 I_Error("leftvol out of bounds");
218
219 // Get the proper lookup table piece
220 // for this volume level???
221 channelinfo[slot].leftvol_lookup = &vol_lookup[leftvol*256];
222 channelinfo[slot].rightvol_lookup = &vol_lookup[rightvol*256];
223}
224
225void I_UpdateSoundParams(int handle, int volume, int seperation, int pitch)
226{
227 updateSoundParams(handle, volume, seperation, pitch);
228}
229
230//
231// SFX API
232// Note: this was called by S_Init.
233// However, whatever they did in the
234// old DPMS based DOS version, this
235// were simply dummies in the Linux
236// version.
237// See soundserver initdata().
238//
239void I_SetChannels()
240{
241 // Init internal lookups (raw data, mixing buffer, channels).
242 // This function sets up internal lookups used during
243 // the mixing process.
244 int i;
245 int j;
246 int* steptablemid = steptable + 128;
247
248 // Okay, reset internal mixing channels to zero.
249 for (i=0; i<NUM_CHANNELS; i++)
250 memset(&channelinfo[i],0,sizeof(channel_info_t));
251
252 // This table provides step widths for pitch parameters.
253 for (i=-128 ; i<128 ; i++)
254 steptablemid[i]=2;
255// steptablemid[i] = (int)(pow(1.2, ((double)i/(64.0*SAMPLERATE/11025)))*65536.0);
256
257 // Generates volume lookup tables
258 // which also turn the unsigned samples
259 // into signed samples.
260 for (i=0 ; i<128 ; i++)
261 for (j=0 ; j<256 ; j++)
262 vol_lookup[i*256+j] = 3*(i*(j-128)*256)/191;
263}
264
265void I_SetSfxVolume(int volume)
266{
267 // Identical to DOS.
268 // Basically, this should propagate
269 // the menu/config file setting
270 // to the state variable used in
271 // the mixing.
272 snd_SfxVolume = volume;
273}
274
275// MUSIC API - dummy. Some code from DOS version.
276void I_SetMusicVolume(int volume)
277{
278 // Internal state variable.
279 snd_MusicVolume = volume;
280 // Now set volume on output device.
281 // Whatever( snd_MusciVolume );
282}
283
284//
285// Retrieve the raw data lump index
286// for a given SFX name.
287//
288int I_GetSfxLumpNum(sfxinfo_t* sfx)
289{
290 char namebuf[9];
291 snprintf(namebuf, sizeof(namebuf), "ds%s", sfx->name);
292 return W_GetNumForName(namebuf);
293}
294
295//
296// Starting a sound means adding it
297// to the current list of active sounds
298// in the internal channels.
299// As the SFX info struct contains
300// e.g. a pointer to the raw data,
301// it is ignored.
302// As our sound handling does not handle
303// priority, it is ignored.
304// Pitching (that is, increased speed of playback)
305// is set, but currently not used by mixing.
306//
307int I_StartSound(int id, int channel, int vol, int sep, int pitch, int priority)
308{
309 (void)priority;
310 int handle;
311
312 // Returns a handle (not used).
313 handle = addsfx(id,channel);
314
315#ifdef RANGECHECK
316 if (handle>=NUM_CHANNELS)
317 I_Error("I_StartSound: handle out of range");
318#endif
319 updateSoundParams(handle, vol, sep, pitch);
320
321 return handle;
322}
323
324void I_StopSound (int handle)
325{
326#ifdef RANGECHECK
327 if (handle>=NUM_CHANNELS)
328 I_Error("I_StopSound: handle out of range");
329#endif
330 stopchan(handle);
331}
332
333int I_SoundIsPlaying(int handle)
334{
335#ifdef RANGECHECK
336 if (handle>=NUM_CHANNELS)
337 I_Error("I_SoundIsPlaying: handle out of range");
338#endif
339 return channelinfo[handle].data != NULL;
340}
341
342//
343// This function loops all active (internal) sound
344// channels, retrieves a given number of samples
345// from the raw sound data, modifies it according
346// to the current (internal) channel parameters,
347// mixes the per channel samples into the given
348// mixing buffer, and clamping it to the allowed
349// range.
350//
351// This function currently supports only 16bit.
352//
353
354bool swap=0;
355bool lastswap=1;
356 // Pointers in global mixbuffer, left, right, end.
357 signed short* leftout;
358 signed short* rightout;
359 signed short* leftend;
360
361void I_UpdateSound( void )
362{
363 // Mix current sound data.
364 // Data, from raw sound, for right and left.
365 register unsigned char sample;
366 register int dl;
367 register int dr;
368
369 // Step in mixbuffer, left and right, thus two.
370 int step;
371
372 // Mixing channel index.
373 int chan;
374
375 if(lastswap==swap)
376 return;
377 lastswap=swap;
378
379 // Left and right channel
380 // are in global mixbuffer, alternating.
381 leftout = (swap ? mixbuffer : mixbuffer + SAMPLECOUNT*2);
382 rightout = (swap ? mixbuffer : mixbuffer + SAMPLECOUNT*2)+1;
383 step = 2;
384
385 // Determine end, for left channel only
386 // (right channel is implicit).
387 leftend = (swap ? mixbuffer : mixbuffer + SAMPLECOUNT*2) + SAMPLECOUNT*step;
388
389 // Mix sounds into the mixing buffer.
390 // Loop over step*SAMPLECOUNT,
391 // that is 512 values for two channels.
392 while (leftout != leftend)
393 {
394 // Reset left/right value.
395 dl = 0;
396 dr = 0;
397
398 // Love thy L2 chache - made this a loop.
399 // Now more channels could be set at compile time
400 // as well. Thus loop those channels.
401 for ( chan = 0; chan < NUM_CHANNELS; chan++ )
402 {
403 // Check channel, if active.
404 if (channelinfo[chan].data)
405 {
406 // Get the raw data from the channel.
407 sample = (((unsigned int)channelinfo[chan].data[0] * (0x10000 - channelinfo[chan].stepremainder))
408 + ((unsigned int)channelinfo[chan].data[1] * (channelinfo[chan].stepremainder))) >> 16;
409 // Add left and right part
410 // for this channel (sound)
411 // to the current data.
412 // Adjust volume accordingly.
413 dl += channelinfo[chan].leftvol_lookup[sample];
414 dr += channelinfo[chan].rightvol_lookup[sample];
415 // Increment index ???
416 channelinfo[chan].stepremainder += channelinfo[chan].step;
417 // MSB is next sample???
418 channelinfo[chan].data += channelinfo[chan].stepremainder >> 16;
419 // Limit to LSB???
420 channelinfo[chan].stepremainder &= 0xffff;
421
422 // Check whether we are done.
423 if (channelinfo[chan].data >= channelinfo[chan].enddata)
424 stopchan(chan);
425 }
426 }
427
428 // Clamp to range. Left hardware channel.
429 // Has been char instead of short.
430 // if (dl > 127) *leftout = 127;
431 // else if (dl < -128) *leftout = -128;
432 // else *leftout = dl;
433
434 if (dl > 0x7fff)
435 *leftout = 0x7fff;
436 else if (dl < -0x8000)
437 *leftout = -0x8000;
438 else
439 *leftout = (signed short)dl;
440
441 // Same for right hardware channel.
442 if (dr > 0x7fff)
443 *rightout = 0x7fff;
444 else if (dr < -0x8000)
445 *rightout = -0x8000;
446 else
447 *rightout = (signed short)dr;
448
449 // Increment current pointers in mixbuffer.
450 leftout += step;
451 rightout += step;
452 }
453}
454
455//
456// This would be used to write out the mixbuffer
457// during each game loop update.
458// Updates sound buffer and audio device at runtime.
459// It is called during Timer interrupt with SNDINTR.
460// Mixing now done synchronous, and
461// only output be done asynchronous?
462//
463
464void get_more(unsigned char** start, size_t* size)
465{
466 // This code works fine, the only problem is that doom runs slower then the sound
467 // updates (sometimes). This code forces the update if the sound hasn't been
468 // remixed.
469 if(lastswap!=swap)
470 I_UpdateSound(); // Force sound update (We don't want stutters)
471
472 *start = (unsigned char*)((swap ? mixbuffer : mixbuffer + SAMPLECOUNT*2));
473 *size = SAMPLECOUNT*2*sizeof(short);
474 swap=!swap;
475}
476
477
478void I_SubmitSound(void)
479{
480 if (nosfxparm)
481 return;
482
483#if !defined(SIMULATOR)
484 rb->pcm_play_data(&get_more, NULL, 0);
485#endif
486}
487
488void I_ShutdownSound(void)
489{
490#if !defined(SIMULATOR)
491 rb->pcm_play_stop();
492 rb->pcm_set_frequency(44100); // 44100
493#endif
494}
495
496void I_InitSound()
497{
498 int i;
499
500 // Initialize external data (all sounds) at start, keep static.
501 printf( "I_InitSound: ");
502#if !defined(SIMULATOR)
503 rb->pcm_play_stop();
504 rb->pcm_set_frequency(SAMPLERATE);
505#endif
506
507 vol_lookup=malloc(128*256*sizeof(int));
508
509 for (i=1 ; i<NUMSFX ; i++)
510 {
511 if (!S_sfx[i].link) // Alias? Example is the chaingun sound linked to pistol.
512 S_sfx[i].data = getsfx( S_sfx[i].name); // Load data from WAD file.
513 else
514 S_sfx[i].data = S_sfx[i].link->data; // Previously loaded already?
515 }
516
517 printf( " pre-cached all sound data\n");
518
519 // Now initialize mixbuffer with zero.
520 for ( i = 0; i< MIXBUFFERSIZE; i++ )
521 mixbuffer[i] = 0;
522
523 // Finished initialization.
524 printf("I_InitSound: sound module ready\n");
525}
526
527//
528// MUSIC API.
529// Still no music done.
530// Remains. Dummies.
531//
532void I_InitMusic(void) {
533}
534void I_ShutdownMusic(void) {
535}
536
537static int looping=0;
538static int musicdies=-1;
539
540void I_PlaySong(int handle, int looping)
541{
542 // UNUSED.
543 handle = looping = 0;
544 musicdies = gametic + TICRATE*30;
545}
546
547void I_PauseSong (int handle)
548{
549 // UNUSED.
550 handle = 0;
551}
552
553void I_ResumeSong (int handle)
554{
555 // UNUSED.
556 handle = 0;
557}
558
559void I_StopSong(int handle)
560{
561 // UNUSED.
562 handle = 0;
563
564 looping = 0;
565 musicdies = 0;
566}
567
568void I_UnRegisterSong(int handle)
569{
570 // UNUSED.
571 handle = 0;
572}
573
574int I_RegisterSong(const void *data)
575{
576 // UNUSED.
577 data = NULL;
578
579 return 1;
580}
581
582// Is the song playing?
583int I_QrySongPlaying(int handle)
584{
585 // UNUSED.
586 handle = 0;
587 return looping || musicdies > gametic;
588}
589
590// Interrupt handler.
591void I_HandleSoundTimer( int ignore )
592{
593 (void)ignore;
594}
595
596// Get the interrupt. Set duration in millisecs.
597int I_SoundSetTimer( int duration_of_tick )
598{
599 (void)duration_of_tick;
600 // Error is -1.
601 return 0;
602}
603
604// Remove the interrupt. Set duration to zero.
605void I_SoundDelTimer(void)
606{
607}
diff --git a/apps/plugins/doom/i_sound.h b/apps/plugins/doom/i_sound.h
new file mode 100644
index 0000000000..2e733b1c62
--- /dev/null
+++ b/apps/plugins/doom/i_sound.h
@@ -0,0 +1,126 @@
1// Emacs style mode select -*- C++ -*-
2//-----------------------------------------------------------------------------
3//
4// $Id$
5//
6// Copyright (C) 1993-1996 by id Software, Inc.
7//
8// This program is free software; you can redistribute it and/or
9// modify it under the terms of the GNU General Public License
10// as published by the Free Software Foundation; either version 2
11// of the License, or (at your option) any later version.
12//
13// This program is distributed in the hope that it will be useful,
14// but WITHOUT ANY WARRANTY; without even the implied warranty of
15// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16// GNU General Public License for more details.
17//
18//
19// DESCRIPTION:
20// System interface, sound.
21//
22//-----------------------------------------------------------------------------
23
24#ifndef __I_SOUND__
25#define __I_SOUND__
26
27#include "doomdef.h"
28
29// UNIX hack, to be removed.
30#ifdef SNDSERV
31extern FILE* sndserver;
32extern char* sndserver_filename;
33#endif
34
35#include "doomstat.h"
36#include "sounds.h"
37
38
39
40// Init at program start...
41void I_InitSound(void);
42
43// ... update sound buffer and audio device at runtime...
44void I_UpdateSound(void);
45void I_SubmitSound(void);
46
47// ... shut down and relase at program termination.
48void I_ShutdownSound(void);
49
50
51//
52// SFX I/O
53//
54
55// Initialize channels?
56void I_SetChannels(void);
57
58// Get raw data lump index for sound descriptor.
59int I_GetSfxLumpNum (sfxinfo_t* sfxinfo );
60
61
62// Starts a sound in a particular sound channel.
63int
64I_StartSound
65( int id,
66 int vol,
67 int cnum,
68 int sep,
69 int pitch,
70 int priority );
71
72
73// Stops a sound channel.
74void I_StopSound(int handle);
75
76// Called by S_*() functions
77// to see if a channel is still playing.
78// Returns 0 if no longer playing, 1 if playing.
79int I_SoundIsPlaying(int handle);
80
81// Updates the volume, separation,
82// and pitch of a sound channel.
83void
84I_UpdateSoundParams
85( int handle,
86 int vol,
87 int sep,
88 int pitch );
89
90
91//
92// MUSIC I/O
93//
94void I_InitMusic(void);
95void I_ShutdownMusic(void);
96// Volume.
97void I_SetMusicVolume(int volume);
98// PAUSE game handling.
99void I_PauseSong(int handle);
100void I_ResumeSong(int handle);
101// Registers a song handle to song data.
102int I_RegisterSong(const void *data);
103// Called by anything that wishes to start music.
104// plays a song, and when the song is done,
105// starts playing it again in an endless loop.
106// Horrible thing to do, considering.
107void
108I_PlaySong
109( int handle,
110 int looping );
111// Stops a song over 3 seconds.
112void I_StopSong(int handle);
113// See above (register), then think backwards
114void I_UnRegisterSong(int handle);
115
116
117
118#endif
119//-----------------------------------------------------------------------------
120//
121// $Log$
122// Revision 1.1 2006/03/28 15:44:01 dave
123// Patch #2969 - Doom! Currently only working on the H300.
124//
125//
126//-----------------------------------------------------------------------------
diff --git a/apps/plugins/doom/i_system.c b/apps/plugins/doom/i_system.c
new file mode 100644
index 0000000000..1e564054f8
--- /dev/null
+++ b/apps/plugins/doom/i_system.c
@@ -0,0 +1,134 @@
1// Emacs style mode select -*- C++ -*-
2//-----------------------------------------------------------------------------
3//
4// $Id$
5//
6// Copyright (C) 1993-1996 by id Software, Inc.
7//
8// This program is free software; you can redistribute it and/or
9// modify it under the terms of the GNU General Public License
10// as published by the Free Software Foundation; either version 2
11// of the License, or (at your option) any later version.
12//
13// This program is distributed in the hope that it will be useful,
14// but WITHOUT ANY WARRANTY; without even the implied warranty of
15// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16// GNU General Public License for more details.
17//
18// $Log$
19// Revision 1.1 2006/03/28 15:44:01 dave
20// Patch #2969 - Doom! Currently only working on the H300.
21//
22//
23// DESCRIPTION:
24//
25//-----------------------------------------------------------------------------
26
27#include "doomdef.h"
28#include "m_misc.h"
29#include "i_video.h"
30#include "i_sound.h"
31
32#include "d_net.h"
33#include "g_game.h"
34#include "z_zone.h"
35
36#ifdef __GNUG__
37#pragma implementation "i_system.h"
38#endif
39#include "i_system.h"
40
41#include "rockmacros.h"
42
43//
44// I_GetTime
45// returns time in 1/35th second tics
46//
47#if (CONFIG_CPU != PP5020)
48volatile unsigned int doomtimer=0;
49
50void doomtime(void)
51{
52 doomtimer++;
53}
54#endif
55
56int I_GetTime (void)
57{
58#ifdef SIMULATOR
59#if HZ==100
60 return ((7*(*rb->current_tick))/20);
61#else
62 #error FIX - I assumed HZ was 100
63#endif
64#else
65#if (CONFIG_CPU == PP5020)
66 return (USEC_TIMER * 7)/200000;
67#else
68 return doomtimer;
69#endif
70#endif
71}
72
73//
74// I_Init
75//
76
77// I was looking into this and comparing the speed versus Prboom
78// Turns out they are running the game much slower then I thought the game was
79// played. This explains why run was unusable other then through straight stretches
80// The game is much slower now (in terms of game speed).
81void I_Init (void)
82{
83#if (CONFIG_CPU != PP5020) && !defined(SIMULATOR)
84 rb->timer_register(1, NULL, CPU_FREQ/TICRATE, 1, doomtime);
85#endif
86 I_InitSound();
87}
88
89//
90// I_Quit
91//
92extern boolean doomexit;
93void I_Quit (void)
94{
95 I_ShutdownSound();
96 I_ShutdownMusic();
97 I_ShutdownGraphics();
98#if (CONFIG_CPU != PP5020) && !defined(SIMULATOR)
99 rb->timer_unregister();
100#endif
101 doomexit=1;
102}
103
104void I_WaitVBL(int count)
105{
106 rb->sleep(count);
107}
108
109//
110// I_Error
111//
112extern boolean demorecording;
113
114void I_Error (char *error, ...)
115{
116 char p_buf[50];
117 va_list ap;
118
119 va_start(ap, error);
120 vsnprintf(p_buf,sizeof(p_buf), error, ap);
121 va_end(ap);
122
123 printf("%s",p_buf);
124
125 // Shutdown. Here might be other errors.
126 if (demorecording)
127 G_CheckDemoStatus();
128/*
129 I_ShutdownGraphics();
130*/
131
132 I_Quit();
133 rb->sleep(HZ*2);
134}
diff --git a/apps/plugins/doom/i_system.h b/apps/plugins/doom/i_system.h
new file mode 100644
index 0000000000..e594cb24ab
--- /dev/null
+++ b/apps/plugins/doom/i_system.h
@@ -0,0 +1,65 @@
1// Emacs style mode select -*- C++ -*-
2//-----------------------------------------------------------------------------
3//
4// $Id$
5//
6// Copyright (C) 1993-1996 by id Software, Inc.
7//
8// This program is free software; you can redistribute it and/or
9// modify it under the terms of the GNU General Public License
10// as published by the Free Software Foundation; either version 2
11// of the License, or (at your option) any later version.
12//
13// This program is distributed in the hope that it will be useful,
14// but WITHOUT ANY WARRANTY; without even the implied warranty of
15// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16// GNU General Public License for more details.
17//
18// DESCRIPTION:
19// System specific interface stuff.
20//
21//-----------------------------------------------------------------------------
22
23
24#ifndef __I_SYSTEM__
25#define __I_SYSTEM__
26
27#include "d_ticcmd.h"
28#include "d_event.h"
29
30#ifdef __GNUG__
31#pragma interface
32#endif
33
34
35// Called by DoomMain.
36void I_Init (void);
37
38// Called by D_DoomLoop,
39// returns current time in tics.
40int I_GetTime (void);
41
42//
43// Called by D_DoomLoop,
44// called before processing any tics in a frame
45// (just after displaying a frame).
46// Time consuming syncronous operations
47// are performed here (joystick reading).
48// Can call D_PostEvent.
49//
50void I_StartFrame (void);
51
52//
53// Called by D_DoomLoop,
54// called before processing each tic in a frame.
55// Quick syncronous operations are performed here.
56// Can call D_PostEvent.
57void I_StartTic (void);
58
59// Called by M_Responder when quit is selected.
60// Clean exit, displays sell blurb.
61void I_Quit (void);
62
63void I_Error (char *error, ...);
64
65#endif
diff --git a/apps/plugins/doom/i_video.c b/apps/plugins/doom/i_video.c
new file mode 100644
index 0000000000..b77205ff84
--- /dev/null
+++ b/apps/plugins/doom/i_video.c
@@ -0,0 +1,454 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 * $Id$
5 *
6 * Copyright (C) 1993-1996 by id Software, Inc.
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * $Log$
19 * Revision 1.1 2006/03/28 15:44:01 dave
20 * Patch #2969 - Doom! Currently only working on the H300.
21 *
22 *
23 * DESCRIPTION:
24 * DOOM graphics and buttons. H300 Port by Karl Kurbjun
25 * IPOD port by Dave Chapman and Paul Louden
26 * Additional work by Thom Johansen
27 *
28 *-----------------------------------------------------------------------------
29 */
30
31#include "doomstat.h"
32#include "i_system.h"
33#include "v_video.h"
34#include "m_argv.h"
35#include "d_main.h"
36
37#include "doomdef.h"
38
39#include "rockmacros.h"
40
41static fb_data palette[256] IBSS_ATTR;
42static fb_data *paldata=NULL;
43
44#if !defined(CPU_COLDFIRE) || defined(SIMULATOR)
45/*
46 This code is credit to the IDOOM port. It is not used for the H300, but
47 serves as a good reference point for other targets.
48*/
49static fb_data * xtable = 0;
50static fb_data * ytable1 = 0;
51static fb_data * ytable2 = 0;
52
53#define FLOOR4(a) \
54 (( a >> 2) << 2)
55
56static int video_w, video_h;
57
58static void genscalexytable(void)
59{
60 // shall we use uint8_t intead of ints?
61 int y = video_h-1;
62 int x = video_w-1;
63 int i = 1 + (x>y?x:y);
64 xtable = malloc(sizeof(int)*video_w );
65 ytable1 = malloc(sizeof(int)*video_h );
66 ytable2 = malloc(sizeof(int)*video_h );
67
68 while(i--)
69 {
70 if(y>=0)
71 {
72 ytable1[y] = ((y*SCREENHEIGHT) / video_h) * SCREENWIDTH;
73 ytable2[y] = y*video_w;
74 y--;
75 }
76 if(x>=0)
77 {
78 xtable[x] = (x*SCREENWIDTH) / video_w;
79 x--;
80 }
81 }
82}
83#endif
84
85//
86// I_ShutdownGraphics (NOT USED)
87//
88void I_ShutdownGraphics(void)
89{
90}
91
92//
93// I_StartFrame (NOT USED)
94//
95void I_StartFrame (void)
96{
97}
98
99//
100// I_GetEvent (NOT USED)
101//
102void I_GetEvent(void)
103{
104}
105
106//
107// I_StartTic
108//
109
110#if CONFIG_KEYPAD == IPOD_4G_PAD
111//#define DOOMBUTTON_SCROLLWHEEL
112#define DOOMBUTTON_UP BUTTON_MENU
113#define DOOMBUTTON_WEAPON BUTTON_SELECT
114#define DOOMBUTTON_LEFT BUTTON_LEFT
115#define DOOMBUTTON_RIGHT BUTTON_RIGHT
116#define DOOMBUTTON_SHOOT BUTTON_PLAY
117#define DOOMBUTTON_ENTER BUTTON_SELECT
118#define DOOMBUTTON_OPEN BUTTON_MENU
119#else
120#define DOOMBUTTON_UP BUTTON_UP
121#define DOOMBUTTON_DOWN BUTTON_DOWN
122#define DOOMBUTTON_LEFT BUTTON_LEFT
123#define DOOMBUTTON_RIGHT BUTTON_RIGHT
124#define DOOMBUTTON_SHOOT BUTTON_REC
125#define DOOMBUTTON_OPEN BUTTON_MODE
126#define DOOMBUTTON_ESC BUTTON_OFF
127#define DOOMBUTTON_ENTER BUTTON_SELECT
128#define DOOMBUTTON_WEAPON BUTTON_ON
129#endif
130
131int getkey(event_t * event)
132{
133 // Same button handling as rockboy
134 static unsigned int oldbuttonstate = 0, newbuttonstate=0;
135
136 static int released, pressed;
137
138#if CONFIG_KEYPAD == IRIVER_H300_PAD
139 static unsigned int holdbutton=0;
140 static int hswitch=0;
141 if (rb->button_hold()&~holdbutton)
142 {
143 if(hswitch==0)
144 {
145 event->type = ev_keydown;
146 hswitch=1;
147 }
148 else
149 {
150 event->type = ev_keyup;
151 hswitch=0;
152 }
153 event->data1=KEY_RSHIFT;
154 D_PostEvent(event);
155 }
156 holdbutton=rb->button_hold();
157#endif
158
159 newbuttonstate = rb->button_status();
160 released = ~newbuttonstate & oldbuttonstate;
161 pressed = newbuttonstate & ~oldbuttonstate;
162 oldbuttonstate = newbuttonstate;
163 if(released)
164 {
165 event->type = ev_keyup;
166 if(released & DOOMBUTTON_LEFT)
167 {
168 event->data1=KEY_LEFTARROW;
169 D_PostEvent(event);
170 }
171 if(released & DOOMBUTTON_RIGHT)
172 {
173 event->data1=KEY_RIGHTARROW;
174 D_PostEvent(event);
175 }
176#ifdef DOOMBUTTON_DOWN
177 if(released & DOOMBUTTON_DOWN)
178 {
179 event->data1=KEY_DOWNARROW;
180 D_PostEvent(event);
181 }
182#endif
183 if(released & DOOMBUTTON_UP)
184 {
185 event->data1=KEY_UPARROW;
186 D_PostEvent(event);
187 }
188 if(released & DOOMBUTTON_SHOOT)
189 {
190 event->data1=KEY_RCTRL;
191 D_PostEvent(event);
192 }
193 if(released & DOOMBUTTON_OPEN)
194 {
195 event->data1=' ';
196 D_PostEvent(event);
197 }
198#ifdef DOOMBUTTON_ESC
199 if(released & DOOMBUTTON_ESC)
200 {
201 event->data1=KEY_ESCAPE;
202 D_PostEvent(event);
203 }
204#endif
205#ifdef DOOMBUTTON_ENTER
206 if(released & DOOMBUTTON_ENTER)
207 {
208 event->data1=KEY_ENTER;
209 D_PostEvent(event);
210 }
211#endif
212#ifdef DOOMBUTTON_WEAPON
213 if(released & DOOMBUTTON_WEAPON)
214 {
215 event->data1 ='w';
216 D_PostEvent(event);
217 }
218#endif
219 }
220 if(pressed)
221 {
222 event->type = ev_keydown;
223 if(pressed & DOOMBUTTON_LEFT)
224 {
225 event->data1=KEY_LEFTARROW;
226 D_PostEvent(event);
227 }
228 if(pressed & DOOMBUTTON_RIGHT)
229 {
230 event->data1=KEY_RIGHTARROW;
231 D_PostEvent(event);
232 }
233#ifdef DOOMBUTTON_DOWN
234 if(pressed & DOOMBUTTON_DOWN)
235 {
236 event->data1=KEY_DOWNARROW;
237 D_PostEvent(event);
238 }
239#endif
240 if(pressed & DOOMBUTTON_UP)
241 {
242 event->data1=KEY_UPARROW;
243 D_PostEvent(event);
244 }
245 if(pressed & DOOMBUTTON_SHOOT)
246 {
247 event->data1=KEY_RCTRL;
248 D_PostEvent(event);
249 }
250 if(pressed & DOOMBUTTON_OPEN)
251 {
252 event->data1=' ';
253 D_PostEvent(event);
254 }
255#ifdef DOOMBUTTON_ESC
256 if(pressed & DOOMBUTTON_ESC)
257 {
258 event->data1=KEY_ESCAPE;
259 D_PostEvent(event);
260 }
261#endif
262#ifdef DOOMBUTTON_ENTER
263 if(pressed & DOOMBUTTON_ENTER)
264 {
265 event->data1=KEY_ENTER;
266 D_PostEvent(event);
267 }
268#endif
269#ifdef DOOMBUTTON_WEAPON
270 if(pressed & DOOMBUTTON_WEAPON)
271 {
272 event->data1='w';
273 D_PostEvent(event);
274 }
275#endif
276 }
277 if(pressed || released)
278 return 1;
279 else
280 return 0;
281}
282
283event_t event;
284void I_StartTic (void)
285{
286 getkey(&event);
287}
288
289
290///////////////////////////////////////////////////////////
291// Palette stuff.
292//
293static void I_UploadNewPalette(int pal)
294{
295 // This is used to replace the current 256 colour cmap with a new one
296 // Used by 256 colour PseudoColor modes
297 static int cachedgamma;
298 static size_t num_pals;
299
300 if ((paldata == NULL) || (cachedgamma != usegamma)) {
301 int lump = W_GetNumForName("PLAYPAL");
302 const byte *pall = W_CacheLumpNum(lump);
303 register const byte *const gtable = gammatable[cachedgamma = usegamma];
304 register int i;
305
306 num_pals = W_LumpLength(lump) / (3*256);
307 num_pals *= 256;
308
309 if (!paldata) {
310 // First call - allocate and prepare colour array
311 paldata = malloc(sizeof(*paldata)*num_pals);
312 }
313
314 // set the colormap entries
315 for (i=0 ; (size_t)i<num_pals ; i++) {
316 int r = gtable[pall[0]];
317 int g = gtable[pall[1]];
318 int b = gtable[pall[2]];
319 pall+=3;
320 paldata[i] = LCD_RGBPACK(r,g,b);
321 }
322
323 W_UnlockLumpNum(lump);
324 num_pals/=256;
325 }
326
327#ifdef RANGECHECK
328 if ((size_t)pal >= num_pals)
329 I_Error("I_UploadNewPalette: Palette number out of range (%d>=%d)",
330 pal, num_pals);
331#endif
332 memcpy(palette,paldata+256*pal,256*sizeof(fb_data));
333}
334
335//
336// I_UpdateNoBlit
337//
338void I_UpdateNoBlit (void)
339{
340}
341
342//
343// I_FinishUpdate
344//
345
346void I_FinishUpdate (void)
347{
348#if defined(CPU_COLDFIRE) && !defined(SIMULATOR)
349 /*
350 Faster screen update than the lookuptables -> I'm wasting 7 pixels of width
351 though. This code also doesn't use the framebuffer so rockbox's drawing
352 functions will not work on top of the doom drawing.
353 */
354
355 // Start the write
356 *(volatile unsigned short *) 0xf0000000 = 0x21; // register
357 *(volatile unsigned short *) 0xf0000002 = 0; // value
358 *(volatile unsigned short *) 0xf0000000 = 0x22; // GRAM
359
360 unsigned char *screenptr=screens[0];
361 int wcnt=0, hcnt=0;
362
363 *(volatile unsigned short *) 0xf0000002 = 0;
364 *(volatile unsigned short *) 0xf0000002 = 0;
365 *(volatile unsigned short *) 0xf0000002 = 0;
366
367 while(hcnt<LCD_HEIGHT)
368 {
369 while(wcnt<LCD_WIDTH-7)
370 {
371 if((wcnt&0x01))
372 screenptr++; // Skip every so many pixels in Doom buffer
373 *(volatile unsigned short *)0xf0000002 = palette[*screenptr];
374 screenptr++;
375 wcnt++;
376 }
377 screenptr++;
378 // move on past those 7 pixels
379 *(volatile unsigned short *) 0xf0000002 = 0;
380 *(volatile unsigned short *) 0xf0000002 = 0;
381 *(volatile unsigned short *) 0xf0000002 = 0;
382 *(volatile unsigned short *) 0xf0000002 = 0;
383 *(volatile unsigned short *) 0xf0000002 = 0;
384 *(volatile unsigned short *) 0xf0000002 = 0;
385 *(volatile unsigned short *) 0xf0000002 = 0;
386 wcnt=0;
387 hcnt++;
388 if((hcnt&0x07)==0x07)
389 screenptr+=SCREENWIDTH; // Skip every 7th line
390 }
391#else
392 // The IDOOM code for screen updates
393 unsigned char paletteIndex;
394 int x, y;
395
396 for (y = 0; y < video_h; y++)
397 {
398 for (x = 0; x < video_w; x++)
399 {
400#if LCD_HEIGHT >= SCREENHEIGHT
401 paletteIndex = screens[0][((y*SCREENHEIGHT) / video_h)
402 * SCREENWIDTH + x];
403 rb->lcd_framebuffer[y * video_w + x] = palette[paletteIndex];
404#else
405 paletteIndex = screens[0][ytable1[y] +xtable[x]];
406 rb->lcd_framebuffer[x + ytable2[y]] = palette[paletteIndex];
407#endif
408 }
409 }
410 rb->lcd_update();
411#endif
412}
413
414//
415// I_ReadScreen
416//
417void I_ReadScreen (byte* scr)
418{
419 memcpy (scr, screens[0], SCREENWIDTH*SCREENHEIGHT);
420}
421
422//
423// I_SetPalette
424//
425void I_SetPalette (int pal)
426{
427 I_UploadNewPalette(pal);
428}
429
430//
431// I_InitGraphics
432//
433void I_InitGraphics(void)
434{
435 static int firsttime=1;
436
437 if (!firsttime)
438 return;
439 firsttime = 0;
440
441 printf("Starting Graphics engine\n");
442
443 /* Note: The other screens are initialized later */
444 screens[0] = malloc (SCREENWIDTH * SCREENHEIGHT * sizeof(unsigned char));
445
446#if defined(CPU_COLDFIRE) && !defined(SIMULATOR)
447 coldfire_set_macsr(EMAC_FRACTIONAL | EMAC_SATURATE);
448#else
449
450 video_h = LCD_HEIGHT;
451 video_w = FLOOR4(LCD_WIDTH); // From IDOOM, the width has to be a multiple of 4
452 genscalexytable();
453#endif
454}
diff --git a/apps/plugins/doom/i_video.h b/apps/plugins/doom/i_video.h
new file mode 100644
index 0000000000..fd8f269d6b
--- /dev/null
+++ b/apps/plugins/doom/i_video.h
@@ -0,0 +1,56 @@
1// Emacs style mode select -*- C++ -*-
2//-----------------------------------------------------------------------------
3//
4// $Id$
5//
6// Copyright (C) 1993-1996 by id Software, Inc.
7//
8// This program is free software; you can redistribute it and/or
9// modify it under the terms of the GNU General Public License
10// as published by the Free Software Foundation; either version 2
11// of the License, or (at your option) any later version.
12//
13// This program is distributed in the hope that it will be useful,
14// but WITHOUT ANY WARRANTY; without even the implied warranty of
15// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16// GNU General Public License for more details.
17//
18// DESCRIPTION:
19// System specific interface stuff.
20//
21//-----------------------------------------------------------------------------
22
23
24#ifndef __I_VIDEO__
25#define __I_VIDEO__
26
27
28#include "doomtype.h"
29#include "rockmacros.h"
30
31#ifdef __GNUG__
32#pragma interface
33#endif
34
35
36// Called by D_DoomMain,
37// determines the hardware configuration
38// and sets up the video mode
39void I_InitGraphics (void);
40
41void I_ShutdownGraphics(void);
42
43// Takes full 8 bit values.
44void I_SetPalette (int pal);
45
46void I_UpdateNoBlit (void);
47void I_FinishUpdate (void) ICODE_ATTR;
48
49// Wait for vertical retrace or pause a bit.
50void I_WaitVBL(int count);
51
52void I_ReadScreen (byte* scr);
53
54
55
56#endif
diff --git a/apps/plugins/doom/info.c b/apps/plugins/doom/info.c
new file mode 100644
index 0000000000..015270f0f5
--- /dev/null
+++ b/apps/plugins/doom/info.c
@@ -0,0 +1,5185 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION:
28 * Thing frame/state LUT,
29 * generated by multigen utilitiy.
30 * This one is the original DOOM version, preserved.
31 * BOOM changes include commenting and addition of predefined lumps
32 * for providing things that aren't in the IWAD without sending a
33 * separate must-use wad file around with the EXE.
34 *
35 *-----------------------------------------------------------------------------
36 */
37
38// Data.
39#include "sounds.h"
40#include "m_fixed.h"
41
42#ifdef __GNUG__
43#pragma implementation "info.h"
44#endif
45#include "info.h"
46
47#include "p_mobj.h"
48
49#include "rockmacros.h"
50
51// ********************************************************************
52// Sprite names
53// ********************************************************************
54// This is the list of sprite 4-character prefixes. They are searched
55// through, with a NULL entry terminating the list. In DOOM originally
56// this NULL entry was missing, and coincidentally the next thing in
57// memory was the dummy state_t[] entry that started with zero bytes.
58// killough 1/17/98: add an explicit NULL entry.
59// NUMSPRITES is an enum from info.h where all these are listed
60// as SPR_xxxx
61
62const char *sprnames[NUMSPRITES+1] = {
63 "TROO","SHTG","PUNG","PISG","PISF","SHTF","SHT2","CHGG","CHGF","MISG",
64 "MISF","SAWG","PLSG","PLSF","BFGG","BFGF","BLUD","PUFF","BAL1","BAL2",
65 "PLSS","PLSE","MISL","BFS1","BFE1","BFE2","TFOG","IFOG","PLAY","POSS",
66 "SPOS","VILE","FIRE","FATB","FBXP","SKEL","MANF","FATT","CPOS","SARG",
67 "HEAD","BAL7","BOSS","BOS2","SKUL","SPID","BSPI","APLS","APBX","CYBR",
68 "PAIN","SSWV","KEEN","BBRN","BOSF","ARM1","ARM2","BAR1","BEXP","FCAN",
69 "BON1","BON2","BKEY","RKEY","YKEY","BSKU","RSKU","YSKU","STIM","MEDI",
70 "SOUL","PINV","PSTR","PINS","MEGA","SUIT","PMAP","PVIS","CLIP","AMMO",
71 "ROCK","BROK","CELL","CELP","SHEL","SBOX","BPAK","BFUG","MGUN","CSAW",
72 "LAUN","PLAS","SHOT","SGN2","COLU","SMT2","GOR1","POL2","POL5","POL4",
73 "POL3","POL1","POL6","GOR2","GOR3","GOR4","GOR5","SMIT","COL1","COL2",
74 "COL3","COL4","CAND","CBRA","COL6","TRE1","TRE2","ELEC","CEYE","FSKU",
75 "COL5","TBLU","TGRN","TRED","SMBT","SMGT","SMRT","HDB1","HDB2","HDB3",
76 "HDB4","HDB5","HDB6","POB1","POB2","BRS1","TLMP","TLP2",NULL
77 };
78
79// ********************************************************************
80// Function addresses or Code Pointers
81// ********************************************************************
82// These function addresses are the Code Pointers that have been
83// modified for years by Dehacked enthusiasts. The new BEX format
84// allows more extensive changes (see d_deh.c)
85
86// Doesn't work with g++, needs actionf_p1
87void A_Light0();
88void A_WeaponReady();
89void A_Lower();
90void A_Raise();
91void A_Punch();
92void A_ReFire();
93void A_FirePistol();
94void A_Light1();
95void A_FireShotgun();
96void A_Light2();
97void A_FireShotgun2();
98void A_CheckReload();
99void A_OpenShotgun2();
100void A_LoadShotgun2();
101void A_CloseShotgun2();
102void A_FireCGun();
103void A_GunFlash();
104void A_FireMissile();
105void A_Saw();
106void A_FirePlasma();
107void A_BFGsound();
108void A_FireBFG();
109void A_BFGSpray();
110void A_Explode();
111void A_Pain();
112void A_PlayerScream();
113void A_Fall();
114void A_XScream();
115void A_Look();
116void A_Chase();
117void A_FaceTarget();
118void A_PosAttack();
119void A_Scream();
120void A_SPosAttack();
121void A_VileChase();
122void A_VileStart();
123void A_VileTarget();
124void A_VileAttack();
125void A_StartFire();
126void A_Fire();
127void A_FireCrackle();
128void A_Tracer();
129void A_SkelWhoosh();
130void A_SkelFist();
131void A_SkelMissile();
132void A_FatRaise();
133void A_FatAttack1();
134void A_FatAttack2();
135void A_FatAttack3();
136void A_BossDeath();
137void A_CPosAttack();
138void A_CPosRefire();
139void A_TroopAttack();
140void A_SargAttack();
141void A_HeadAttack();
142void A_BruisAttack();
143void A_SkullAttack();
144void A_Metal();
145void A_SpidRefire();
146void A_BabyMetal();
147void A_BspiAttack();
148void A_Hoof();
149void A_CyberAttack();
150void A_PainAttack();
151void A_PainDie();
152void A_KeenDie();
153void A_BrainPain();
154void A_BrainScream();
155void A_BrainDie();
156void A_BrainAwake();
157void A_BrainSpit();
158void A_SpawnSound();
159void A_SpawnFly();
160void A_BrainExplode();
161void A_Die();
162void A_Stop();
163void A_Detonate(); /* killough 8/9/98: detonate a bomb or other device */
164void A_Mushroom(); /* killough 10/98: mushroom effect */
165
166// ********************************************************************
167// State or "frame" information
168// ********************************************************************
169// Each of the states, otherwise known as "frames", is outlined
170// here. The data in each element of the array is the way it is
171// initialized, with sprite names identified by their enumerator
172// value such as SPR_SHTG. These correlate to the above sprite
173// array so don't change them around unless you understand what
174// you're doing.
175//
176// The commented name beginning with S_ at the end of each line
177// is there to help figure out where the next-frame pointer is
178// pointing. These are also additionally identified in info.h
179// as enumerated values. From a change-and-recompile point of
180// view this is fairly workable, but it adds a lot to the effort
181// when trying to change things externally. See also the d_deh.c
182// parts where frame rewiring is done for more details and the
183// extended way a BEX file can handle this.
184
185state_t states[NUMSTATES] = {
186 {SPR_TROO,0,-1,NULL,S_NULL,0,0}, // S_NULL
187 {SPR_SHTG,4,0,A_Light0,S_NULL,0,0}, // S_LIGHTDONE
188 {SPR_PUNG,0,1,A_WeaponReady,S_PUNCH,0,0}, // S_PUNCH
189 {SPR_PUNG,0,1,A_Lower,S_PUNCHDOWN,0,0}, // S_PUNCHDOWN
190 {SPR_PUNG,0,1,A_Raise,S_PUNCHUP,0,0}, // S_PUNCHUP
191 {SPR_PUNG,1,4,NULL,S_PUNCH2,0,0}, // S_PUNCH1
192 {SPR_PUNG,2,4,A_Punch,S_PUNCH3,0,0}, // S_PUNCH2
193 {SPR_PUNG,3,5,NULL,S_PUNCH4,0,0}, // S_PUNCH3
194 {SPR_PUNG,2,4,NULL,S_PUNCH5,0,0}, // S_PUNCH4
195 {SPR_PUNG,1,5,A_ReFire,S_PUNCH,0,0}, // S_PUNCH5
196 {SPR_PISG,0,1,A_WeaponReady,S_PISTOL,0,0},// S_PISTOL
197 {SPR_PISG,0,1,A_Lower,S_PISTOLDOWN,0,0}, // S_PISTOLDOWN
198 {SPR_PISG,0,1,A_Raise,S_PISTOLUP,0,0}, // S_PISTOLUP
199 {SPR_PISG,0,4,NULL,S_PISTOL2,0,0}, // S_PISTOL1
200 {SPR_PISG,1,6,A_FirePistol,S_PISTOL3,0,0},// S_PISTOL2
201 {SPR_PISG,2,4,NULL,S_PISTOL4,0,0}, // S_PISTOL3
202 {SPR_PISG,1,5,A_ReFire,S_PISTOL,0,0}, // S_PISTOL4
203 {SPR_PISF,32768,7,A_Light1,S_LIGHTDONE,0,0}, // S_PISTOLFLASH
204 {SPR_SHTG,0,1,A_WeaponReady,S_SGUN,0,0}, // S_SGUN
205 {SPR_SHTG,0,1,A_Lower,S_SGUNDOWN,0,0}, // S_SGUNDOWN
206 {SPR_SHTG,0,1,A_Raise,S_SGUNUP,0,0}, // S_SGUNUP
207 {SPR_SHTG,0,3,NULL,S_SGUN2,0,0}, // S_SGUN1
208 {SPR_SHTG,0,7,A_FireShotgun,S_SGUN3,0,0}, // S_SGUN2
209 {SPR_SHTG,1,5,NULL,S_SGUN4,0,0}, // S_SGUN3
210 {SPR_SHTG,2,5,NULL,S_SGUN5,0,0}, // S_SGUN4
211 {SPR_SHTG,3,4,NULL,S_SGUN6,0,0}, // S_SGUN5
212 {SPR_SHTG,2,5,NULL,S_SGUN7,0,0}, // S_SGUN6
213 {SPR_SHTG,1,5,NULL,S_SGUN8,0,0}, // S_SGUN7
214 {SPR_SHTG,0,3,NULL,S_SGUN9,0,0}, // S_SGUN8
215 {SPR_SHTG,0,7,A_ReFire,S_SGUN,0,0}, // S_SGUN9
216 {SPR_SHTF,32768,4,A_Light1,S_SGUNFLASH2,0,0}, // S_SGUNFLASH1
217 {SPR_SHTF,32769,3,A_Light2,S_LIGHTDONE,0,0}, // S_SGUNFLASH2
218 {SPR_SHT2,0,1,A_WeaponReady,S_DSGUN,0,0}, // S_DSGUN
219 {SPR_SHT2,0,1,A_Lower,S_DSGUNDOWN,0,0}, // S_DSGUNDOWN
220 {SPR_SHT2,0,1,A_Raise,S_DSGUNUP,0,0}, // S_DSGUNUP
221 {SPR_SHT2,0,3,NULL,S_DSGUN2,0,0}, // S_DSGUN1
222 {SPR_SHT2,0,7,A_FireShotgun2,S_DSGUN3,0,0}, // S_DSGUN2
223 {SPR_SHT2,1,7,NULL,S_DSGUN4,0,0}, // S_DSGUN3
224 {SPR_SHT2,2,7,A_CheckReload,S_DSGUN5,0,0}, // S_DSGUN4
225 {SPR_SHT2,3,7,A_OpenShotgun2,S_DSGUN6,0,0}, // S_DSGUN5
226 {SPR_SHT2,4,7,NULL,S_DSGUN7,0,0}, // S_DSGUN6
227 {SPR_SHT2,5,7,A_LoadShotgun2,S_DSGUN8,0,0}, // S_DSGUN7
228 {SPR_SHT2,6,6,NULL,S_DSGUN9,0,0}, // S_DSGUN8
229 {SPR_SHT2,7,6,A_CloseShotgun2,S_DSGUN10,0,0}, // S_DSGUN9
230 {SPR_SHT2,0,5,A_ReFire,S_DSGUN,0,0}, // S_DSGUN10
231 {SPR_SHT2,1,7,NULL,S_DSNR2,0,0}, // S_DSNR1
232 {SPR_SHT2,0,3,NULL,S_DSGUNDOWN,0,0}, // S_DSNR2
233 {SPR_SHT2,32776,5,A_Light1,S_DSGUNFLASH2,0,0}, // S_DSGUNFLASH1
234 {SPR_SHT2,32777,4,A_Light2,S_LIGHTDONE,0,0}, // S_DSGUNFLASH2
235 {SPR_CHGG,0,1,A_WeaponReady,S_CHAIN,0,0}, // S_CHAIN
236 {SPR_CHGG,0,1,A_Lower,S_CHAINDOWN,0,0}, // S_CHAINDOWN
237 {SPR_CHGG,0,1,A_Raise,S_CHAINUP,0,0}, // S_CHAINUP
238 {SPR_CHGG,0,4,A_FireCGun,S_CHAIN2,0,0}, // S_CHAIN1
239 {SPR_CHGG,1,4,A_FireCGun,S_CHAIN3,0,0}, // S_CHAIN2
240 {SPR_CHGG,1,0,A_ReFire,S_CHAIN,0,0}, // S_CHAIN3
241 {SPR_CHGF,32768,5,A_Light1,S_LIGHTDONE,0,0}, // S_CHAINFLASH1
242 {SPR_CHGF,32769,5,A_Light2,S_LIGHTDONE,0,0}, // S_CHAINFLASH2
243 {SPR_MISG,0,1,A_WeaponReady,S_MISSILE,0,0}, // S_MISSILE
244 {SPR_MISG,0,1,A_Lower,S_MISSILEDOWN,0,0}, // S_MISSILEDOWN
245 {SPR_MISG,0,1,A_Raise,S_MISSILEUP,0,0}, // S_MISSILEUP
246 {SPR_MISG,1,8,A_GunFlash,S_MISSILE2,0,0}, // S_MISSILE1
247 {SPR_MISG,1,12,A_FireMissile,S_MISSILE3,0,0}, // S_MISSILE2
248 {SPR_MISG,1,0,A_ReFire,S_MISSILE,0,0}, // S_MISSILE3
249 {SPR_MISF,32768,3,A_Light1,S_MISSILEFLASH2,0,0}, // S_MISSILEFLASH1
250 {SPR_MISF,32769,4,NULL,S_MISSILEFLASH3,0,0}, // S_MISSILEFLASH2
251 {SPR_MISF,32770,4,A_Light2,S_MISSILEFLASH4,0,0}, // S_MISSILEFLASH3
252 {SPR_MISF,32771,4,A_Light2,S_LIGHTDONE,0,0}, // S_MISSILEFLASH4
253 {SPR_SAWG,2,4,A_WeaponReady,S_SAWB,0,0}, // S_SAW
254 {SPR_SAWG,3,4,A_WeaponReady,S_SAW,0,0}, // S_SAWB
255 {SPR_SAWG,2,1,A_Lower,S_SAWDOWN,0,0}, // S_SAWDOWN
256 {SPR_SAWG,2,1,A_Raise,S_SAWUP,0,0}, // S_SAWUP
257 {SPR_SAWG,0,4,A_Saw,S_SAW2,0,0}, // S_SAW1
258 {SPR_SAWG,1,4,A_Saw,S_SAW3,0,0}, // S_SAW2
259 {SPR_SAWG,1,0,A_ReFire,S_SAW,0,0}, // S_SAW3
260 {SPR_PLSG,0,1,A_WeaponReady,S_PLASMA,0,0}, // S_PLASMA
261 {SPR_PLSG,0,1,A_Lower,S_PLASMADOWN,0,0}, // S_PLASMADOWN
262 {SPR_PLSG,0,1,A_Raise,S_PLASMAUP,0,0}, // S_PLASMAUP
263 {SPR_PLSG,0,3,A_FirePlasma,S_PLASMA2,0,0}, // S_PLASMA1
264 {SPR_PLSG,1,20,A_ReFire,S_PLASMA,0,0}, // S_PLASMA2
265 {SPR_PLSF,32768,4,A_Light1,S_LIGHTDONE,0,0}, // S_PLASMAFLASH1
266 {SPR_PLSF,32769,4,A_Light1,S_LIGHTDONE,0,0}, // S_PLASMAFLASH2
267 {SPR_BFGG,0,1,A_WeaponReady,S_BFG,0,0}, // S_BFG
268 {SPR_BFGG,0,1,A_Lower,S_BFGDOWN,0,0}, // S_BFGDOWN
269 {SPR_BFGG,0,1,A_Raise,S_BFGUP,0,0}, // S_BFGUP
270 {SPR_BFGG,0,20,A_BFGsound,S_BFG2,0,0}, // S_BFG1
271 {SPR_BFGG,1,10,A_GunFlash,S_BFG3,0,0}, // S_BFG2
272 {SPR_BFGG,1,10,A_FireBFG,S_BFG4,0,0}, // S_BFG3
273 {SPR_BFGG,1,20,A_ReFire,S_BFG,0,0}, // S_BFG4
274 {SPR_BFGF,32768,11,A_Light1,S_BFGFLASH2,0,0}, // S_BFGFLASH1
275 {SPR_BFGF,32769,6,A_Light2,S_LIGHTDONE,0,0}, // S_BFGFLASH2
276 {SPR_BLUD,2,8,NULL,S_BLOOD2,0,0}, // S_BLOOD1
277 {SPR_BLUD,1,8,NULL,S_BLOOD3,0,0}, // S_BLOOD2
278 {SPR_BLUD,0,8,NULL,S_NULL,0,0}, // S_BLOOD3
279 {SPR_PUFF,32768,4,NULL,S_PUFF2,0,0}, // S_PUFF1
280 {SPR_PUFF,1,4,NULL,S_PUFF3,0,0}, // S_PUFF2
281 {SPR_PUFF,2,4,NULL,S_PUFF4,0,0}, // S_PUFF3
282 {SPR_PUFF,3,4,NULL,S_NULL,0,0}, // S_PUFF4
283 {SPR_BAL1,32768,4,NULL,S_TBALL2,0,0}, // S_TBALL1
284 {SPR_BAL1,32769,4,NULL,S_TBALL1,0,0}, // S_TBALL2
285 {SPR_BAL1,32770,6,NULL,S_TBALLX2,0,0}, // S_TBALLX1
286 {SPR_BAL1,32771,6,NULL,S_TBALLX3,0,0}, // S_TBALLX2
287 {SPR_BAL1,32772,6,NULL,S_NULL,0,0}, // S_TBALLX3
288 {SPR_BAL2,32768,4,NULL,S_RBALL2,0,0}, // S_RBALL1
289 {SPR_BAL2,32769,4,NULL,S_RBALL1,0,0}, // S_RBALL2
290 {SPR_BAL2,32770,6,NULL,S_RBALLX2,0,0}, // S_RBALLX1
291 {SPR_BAL2,32771,6,NULL,S_RBALLX3,0,0}, // S_RBALLX2
292 {SPR_BAL2,32772,6,NULL,S_NULL,0,0}, // S_RBALLX3
293 {SPR_PLSS,32768,6,NULL,S_PLASBALL2,0,0}, // S_PLASBALL
294 {SPR_PLSS,32769,6,NULL,S_PLASBALL,0,0}, // S_PLASBALL2
295 {SPR_PLSE,32768,4,NULL,S_PLASEXP2,0,0}, // S_PLASEXP
296 {SPR_PLSE,32769,4,NULL,S_PLASEXP3,0,0}, // S_PLASEXP2
297 {SPR_PLSE,32770,4,NULL,S_PLASEXP4,0,0}, // S_PLASEXP3
298 {SPR_PLSE,32771,4,NULL,S_PLASEXP5,0,0}, // S_PLASEXP4
299 {SPR_PLSE,32772,4,NULL,S_NULL,0,0}, // S_PLASEXP5
300 {SPR_MISL,32768,1,NULL,S_ROCKET,0,0}, // S_ROCKET
301 {SPR_BFS1,32768,4,NULL,S_BFGSHOT2,0,0}, // S_BFGSHOT
302 {SPR_BFS1,32769,4,NULL,S_BFGSHOT,0,0}, // S_BFGSHOT2
303 {SPR_BFE1,32768,8,NULL,S_BFGLAND2,0,0}, // S_BFGLAND
304 {SPR_BFE1,32769,8,NULL,S_BFGLAND3,0,0}, // S_BFGLAND2
305 {SPR_BFE1,32770,8,A_BFGSpray,S_BFGLAND4,0,0}, // S_BFGLAND3
306 {SPR_BFE1,32771,8,NULL,S_BFGLAND5,0,0}, // S_BFGLAND4
307 {SPR_BFE1,32772,8,NULL,S_BFGLAND6,0,0}, // S_BFGLAND5
308 {SPR_BFE1,32773,8,NULL,S_NULL,0,0}, // S_BFGLAND6
309 {SPR_BFE2,32768,8,NULL,S_BFGEXP2,0,0}, // S_BFGEXP
310 {SPR_BFE2,32769,8,NULL,S_BFGEXP3,0,0}, // S_BFGEXP2
311 {SPR_BFE2,32770,8,NULL,S_BFGEXP4,0,0}, // S_BFGEXP3
312 {SPR_BFE2,32771,8,NULL,S_NULL,0,0}, // S_BFGEXP4
313 {SPR_MISL,32769,8,A_Explode,S_EXPLODE2,0,0}, // S_EXPLODE1
314 {SPR_MISL,32770,6,NULL,S_EXPLODE3,0,0}, // S_EXPLODE2
315 {SPR_MISL,32771,4,NULL,S_NULL,0,0}, // S_EXPLODE3
316 {SPR_TFOG,32768,6,NULL,S_TFOG01,0,0}, // S_TFOG
317 {SPR_TFOG,32769,6,NULL,S_TFOG02,0,0}, // S_TFOG01
318 {SPR_TFOG,32768,6,NULL,S_TFOG2,0,0}, // S_TFOG02
319 {SPR_TFOG,32769,6,NULL,S_TFOG3,0,0}, // S_TFOG2
320 {SPR_TFOG,32770,6,NULL,S_TFOG4,0,0}, // S_TFOG3
321 {SPR_TFOG,32771,6,NULL,S_TFOG5,0,0}, // S_TFOG4
322 {SPR_TFOG,32772,6,NULL,S_TFOG6,0,0}, // S_TFOG5
323 {SPR_TFOG,32773,6,NULL,S_TFOG7,0,0}, // S_TFOG6
324 {SPR_TFOG,32774,6,NULL,S_TFOG8,0,0}, // S_TFOG7
325 {SPR_TFOG,32775,6,NULL,S_TFOG9,0,0}, // S_TFOG8
326 {SPR_TFOG,32776,6,NULL,S_TFOG10,0,0}, // S_TFOG9
327 {SPR_TFOG,32777,6,NULL,S_NULL,0,0}, // S_TFOG10
328 {SPR_IFOG,32768,6,NULL,S_IFOG01,0,0}, // S_IFOG
329 {SPR_IFOG,32769,6,NULL,S_IFOG02,0,0}, // S_IFOG01
330 {SPR_IFOG,32768,6,NULL,S_IFOG2,0,0}, // S_IFOG02
331 {SPR_IFOG,32769,6,NULL,S_IFOG3,0,0}, // S_IFOG2
332 {SPR_IFOG,32770,6,NULL,S_IFOG4,0,0}, // S_IFOG3
333 {SPR_IFOG,32771,6,NULL,S_IFOG5,0,0}, // S_IFOG4
334 {SPR_IFOG,32772,6,NULL,S_NULL,0,0}, // S_IFOG5
335 {SPR_PLAY,0,-1,NULL,S_NULL,0,0}, // S_PLAY
336 {SPR_PLAY,0,4,NULL,S_PLAY_RUN2,0,0}, // S_PLAY_RUN1
337 {SPR_PLAY,1,4,NULL,S_PLAY_RUN3,0,0}, // S_PLAY_RUN2
338 {SPR_PLAY,2,4,NULL,S_PLAY_RUN4,0,0}, // S_PLAY_RUN3
339 {SPR_PLAY,3,4,NULL,S_PLAY_RUN1,0,0}, // S_PLAY_RUN4
340 {SPR_PLAY,4,12,NULL,S_PLAY,0,0}, // S_PLAY_ATK1
341 {SPR_PLAY,32773,6,NULL,S_PLAY_ATK1,0,0}, // S_PLAY_ATK2
342 {SPR_PLAY,6,4,NULL,S_PLAY_PAIN2,0,0}, // S_PLAY_PAIN
343 {SPR_PLAY,6,4,A_Pain,S_PLAY,0,0}, // S_PLAY_PAIN2
344 {SPR_PLAY,7,10,NULL,S_PLAY_DIE2,0,0}, // S_PLAY_DIE1
345 {SPR_PLAY,8,10,A_PlayerScream,S_PLAY_DIE3,0,0}, // S_PLAY_DIE2
346 {SPR_PLAY,9,10,A_Fall,S_PLAY_DIE4,0,0}, // S_PLAY_DIE3
347 {SPR_PLAY,10,10,NULL,S_PLAY_DIE5,0,0}, // S_PLAY_DIE4
348 {SPR_PLAY,11,10,NULL,S_PLAY_DIE6,0,0}, // S_PLAY_DIE5
349 {SPR_PLAY,12,10,NULL,S_PLAY_DIE7,0,0}, // S_PLAY_DIE6
350 {SPR_PLAY,13,-1,NULL,S_NULL,0,0}, // S_PLAY_DIE7
351 {SPR_PLAY,14,5,NULL,S_PLAY_XDIE2,0,0}, // S_PLAY_XDIE1
352 {SPR_PLAY,15,5,A_XScream,S_PLAY_XDIE3,0,0}, // S_PLAY_XDIE2
353 {SPR_PLAY,16,5,A_Fall,S_PLAY_XDIE4,0,0}, // S_PLAY_XDIE3
354 {SPR_PLAY,17,5,NULL,S_PLAY_XDIE5,0,0}, // S_PLAY_XDIE4
355 {SPR_PLAY,18,5,NULL,S_PLAY_XDIE6,0,0}, // S_PLAY_XDIE5
356 {SPR_PLAY,19,5,NULL,S_PLAY_XDIE7,0,0}, // S_PLAY_XDIE6
357 {SPR_PLAY,20,5,NULL,S_PLAY_XDIE8,0,0}, // S_PLAY_XDIE7
358 {SPR_PLAY,21,5,NULL,S_PLAY_XDIE9,0,0}, // S_PLAY_XDIE8
359 {SPR_PLAY,22,-1,NULL,S_NULL,0,0}, // S_PLAY_XDIE9
360 {SPR_POSS,0,10,A_Look,S_POSS_STND2,0,0}, // S_POSS_STND
361 {SPR_POSS,1,10,A_Look,S_POSS_STND,0,0}, // S_POSS_STND2
362 {SPR_POSS,0,4,A_Chase,S_POSS_RUN2,0,0}, // S_POSS_RUN1
363 {SPR_POSS,0,4,A_Chase,S_POSS_RUN3,0,0}, // S_POSS_RUN2
364 {SPR_POSS,1,4,A_Chase,S_POSS_RUN4,0,0}, // S_POSS_RUN3
365 {SPR_POSS,1,4,A_Chase,S_POSS_RUN5,0,0}, // S_POSS_RUN4
366 {SPR_POSS,2,4,A_Chase,S_POSS_RUN6,0,0}, // S_POSS_RUN5
367 {SPR_POSS,2,4,A_Chase,S_POSS_RUN7,0,0}, // S_POSS_RUN6
368 {SPR_POSS,3,4,A_Chase,S_POSS_RUN8,0,0}, // S_POSS_RUN7
369 {SPR_POSS,3,4,A_Chase,S_POSS_RUN1,0,0}, // S_POSS_RUN8
370 {SPR_POSS,4,10,A_FaceTarget,S_POSS_ATK2,0,0}, // S_POSS_ATK1
371 {SPR_POSS,5,8,A_PosAttack,S_POSS_ATK3,0,0}, // S_POSS_ATK2
372 {SPR_POSS,4,8,NULL,S_POSS_RUN1,0,0}, // S_POSS_ATK3
373 {SPR_POSS,6,3,NULL,S_POSS_PAIN2,0,0}, // S_POSS_PAIN
374 {SPR_POSS,6,3,A_Pain,S_POSS_RUN1,0,0}, // S_POSS_PAIN2
375 {SPR_POSS,7,5,NULL,S_POSS_DIE2,0,0}, // S_POSS_DIE1
376 {SPR_POSS,8,5,A_Scream,S_POSS_DIE3,0,0}, // S_POSS_DIE2
377 {SPR_POSS,9,5,A_Fall,S_POSS_DIE4,0,0}, // S_POSS_DIE3
378 {SPR_POSS,10,5,NULL,S_POSS_DIE5,0,0}, // S_POSS_DIE4
379 {SPR_POSS,11,-1,NULL,S_NULL,0,0}, // S_POSS_DIE5
380 {SPR_POSS,12,5,NULL,S_POSS_XDIE2,0,0}, // S_POSS_XDIE1
381 {SPR_POSS,13,5,A_XScream,S_POSS_XDIE3,0,0}, // S_POSS_XDIE2
382 {SPR_POSS,14,5,A_Fall,S_POSS_XDIE4,0,0}, // S_POSS_XDIE3
383 {SPR_POSS,15,5,NULL,S_POSS_XDIE5,0,0}, // S_POSS_XDIE4
384 {SPR_POSS,16,5,NULL,S_POSS_XDIE6,0,0}, // S_POSS_XDIE5
385 {SPR_POSS,17,5,NULL,S_POSS_XDIE7,0,0}, // S_POSS_XDIE6
386 {SPR_POSS,18,5,NULL,S_POSS_XDIE8,0,0}, // S_POSS_XDIE7
387 {SPR_POSS,19,5,NULL,S_POSS_XDIE9,0,0}, // S_POSS_XDIE8
388 {SPR_POSS,20,-1,NULL,S_NULL,0,0}, // S_POSS_XDIE9
389 {SPR_POSS,10,5,NULL,S_POSS_RAISE2,0,0}, // S_POSS_RAISE1
390 {SPR_POSS,9,5,NULL,S_POSS_RAISE3,0,0}, // S_POSS_RAISE2
391 {SPR_POSS,8,5,NULL,S_POSS_RAISE4,0,0}, // S_POSS_RAISE3
392 {SPR_POSS,7,5,NULL,S_POSS_RUN1,0,0}, // S_POSS_RAISE4
393 {SPR_SPOS,0,10,A_Look,S_SPOS_STND2,0,0}, // S_SPOS_STND
394 {SPR_SPOS,1,10,A_Look,S_SPOS_STND,0,0}, // S_SPOS_STND2
395 {SPR_SPOS,0,3,A_Chase,S_SPOS_RUN2,0,0}, // S_SPOS_RUN1
396 {SPR_SPOS,0,3,A_Chase,S_SPOS_RUN3,0,0}, // S_SPOS_RUN2
397 {SPR_SPOS,1,3,A_Chase,S_SPOS_RUN4,0,0}, // S_SPOS_RUN3
398 {SPR_SPOS,1,3,A_Chase,S_SPOS_RUN5,0,0}, // S_SPOS_RUN4
399 {SPR_SPOS,2,3,A_Chase,S_SPOS_RUN6,0,0}, // S_SPOS_RUN5
400 {SPR_SPOS,2,3,A_Chase,S_SPOS_RUN7,0,0}, // S_SPOS_RUN6
401 {SPR_SPOS,3,3,A_Chase,S_SPOS_RUN8,0,0}, // S_SPOS_RUN7
402 {SPR_SPOS,3,3,A_Chase,S_SPOS_RUN1,0,0}, // S_SPOS_RUN8
403 {SPR_SPOS,4,10,A_FaceTarget,S_SPOS_ATK2,0,0}, // S_SPOS_ATK1
404 {SPR_SPOS,32773,10,A_SPosAttack,S_SPOS_ATK3,0,0}, // S_SPOS_ATK2
405 {SPR_SPOS,4,10,NULL,S_SPOS_RUN1,0,0}, // S_SPOS_ATK3
406 {SPR_SPOS,6,3,NULL,S_SPOS_PAIN2,0,0}, // S_SPOS_PAIN
407 {SPR_SPOS,6,3,A_Pain,S_SPOS_RUN1,0,0}, // S_SPOS_PAIN2
408 {SPR_SPOS,7,5,NULL,S_SPOS_DIE2,0,0}, // S_SPOS_DIE1
409 {SPR_SPOS,8,5,A_Scream,S_SPOS_DIE3,0,0}, // S_SPOS_DIE2
410 {SPR_SPOS,9,5,A_Fall,S_SPOS_DIE4,0,0}, // S_SPOS_DIE3
411 {SPR_SPOS,10,5,NULL,S_SPOS_DIE5,0,0}, // S_SPOS_DIE4
412 {SPR_SPOS,11,-1,NULL,S_NULL,0,0}, // S_SPOS_DIE5
413 {SPR_SPOS,12,5,NULL,S_SPOS_XDIE2,0,0}, // S_SPOS_XDIE1
414 {SPR_SPOS,13,5,A_XScream,S_SPOS_XDIE3,0,0}, // S_SPOS_XDIE2
415 {SPR_SPOS,14,5,A_Fall,S_SPOS_XDIE4,0,0}, // S_SPOS_XDIE3
416 {SPR_SPOS,15,5,NULL,S_SPOS_XDIE5,0,0}, // S_SPOS_XDIE4
417 {SPR_SPOS,16,5,NULL,S_SPOS_XDIE6,0,0}, // S_SPOS_XDIE5
418 {SPR_SPOS,17,5,NULL,S_SPOS_XDIE7,0,0}, // S_SPOS_XDIE6
419 {SPR_SPOS,18,5,NULL,S_SPOS_XDIE8,0,0}, // S_SPOS_XDIE7
420 {SPR_SPOS,19,5,NULL,S_SPOS_XDIE9,0,0}, // S_SPOS_XDIE8
421 {SPR_SPOS,20,-1,NULL,S_NULL,0,0}, // S_SPOS_XDIE9
422 {SPR_SPOS,11,5,NULL,S_SPOS_RAISE2,0,0}, // S_SPOS_RAISE1
423 {SPR_SPOS,10,5,NULL,S_SPOS_RAISE3,0,0}, // S_SPOS_RAISE2
424 {SPR_SPOS,9,5,NULL,S_SPOS_RAISE4,0,0}, // S_SPOS_RAISE3
425 {SPR_SPOS,8,5,NULL,S_SPOS_RAISE5,0,0}, // S_SPOS_RAISE4
426 {SPR_SPOS,7,5,NULL,S_SPOS_RUN1,0,0}, // S_SPOS_RAISE5
427 {SPR_VILE,0,10,A_Look,S_VILE_STND2,0,0}, // S_VILE_STND
428 {SPR_VILE,1,10,A_Look,S_VILE_STND,0,0}, // S_VILE_STND2
429 {SPR_VILE,0,2,A_VileChase,S_VILE_RUN2,0,0}, // S_VILE_RUN1
430 {SPR_VILE,0,2,A_VileChase,S_VILE_RUN3,0,0}, // S_VILE_RUN2
431 {SPR_VILE,1,2,A_VileChase,S_VILE_RUN4,0,0}, // S_VILE_RUN3
432 {SPR_VILE,1,2,A_VileChase,S_VILE_RUN5,0,0}, // S_VILE_RUN4
433 {SPR_VILE,2,2,A_VileChase,S_VILE_RUN6,0,0}, // S_VILE_RUN5
434 {SPR_VILE,2,2,A_VileChase,S_VILE_RUN7,0,0}, // S_VILE_RUN6
435 {SPR_VILE,3,2,A_VileChase,S_VILE_RUN8,0,0}, // S_VILE_RUN7
436 {SPR_VILE,3,2,A_VileChase,S_VILE_RUN9,0,0}, // S_VILE_RUN8
437 {SPR_VILE,4,2,A_VileChase,S_VILE_RUN10,0,0}, // S_VILE_RUN9
438 {SPR_VILE,4,2,A_VileChase,S_VILE_RUN11,0,0}, // S_VILE_RUN10
439 {SPR_VILE,5,2,A_VileChase,S_VILE_RUN12,0,0}, // S_VILE_RUN11
440 {SPR_VILE,5,2,A_VileChase,S_VILE_RUN1,0,0}, // S_VILE_RUN12
441 {SPR_VILE,32774,0,A_VileStart,S_VILE_ATK2,0,0}, // S_VILE_ATK1
442 {SPR_VILE,32774,10,A_FaceTarget,S_VILE_ATK3,0,0}, // S_VILE_ATK2
443 {SPR_VILE,32775,8,A_VileTarget,S_VILE_ATK4,0,0}, // S_VILE_ATK3
444 {SPR_VILE,32776,8,A_FaceTarget,S_VILE_ATK5,0,0}, // S_VILE_ATK4
445 {SPR_VILE,32777,8,A_FaceTarget,S_VILE_ATK6,0,0}, // S_VILE_ATK5
446 {SPR_VILE,32778,8,A_FaceTarget,S_VILE_ATK7,0,0}, // S_VILE_ATK6
447 {SPR_VILE,32779,8,A_FaceTarget,S_VILE_ATK8,0,0}, // S_VILE_ATK7
448 {SPR_VILE,32780,8,A_FaceTarget,S_VILE_ATK9,0,0}, // S_VILE_ATK8
449 {SPR_VILE,32781,8,A_FaceTarget,S_VILE_ATK10,0,0}, // S_VILE_ATK9
450 {SPR_VILE,32782,8,A_VileAttack,S_VILE_ATK11,0,0}, // S_VILE_ATK10
451 {SPR_VILE,32783,20,NULL,S_VILE_RUN1,0,0}, // S_VILE_ATK11
452 {SPR_VILE,32794,10,NULL,S_VILE_HEAL2,0,0}, // S_VILE_HEAL1
453 {SPR_VILE,32795,10,NULL,S_VILE_HEAL3,0,0}, // S_VILE_HEAL2
454 {SPR_VILE,32796,10,NULL,S_VILE_RUN1,0,0}, // S_VILE_HEAL3
455 {SPR_VILE,16,5,NULL,S_VILE_PAIN2,0,0}, // S_VILE_PAIN
456 {SPR_VILE,16,5,A_Pain,S_VILE_RUN1,0,0}, // S_VILE_PAIN2
457 {SPR_VILE,16,7,NULL,S_VILE_DIE2,0,0}, // S_VILE_DIE1
458 {SPR_VILE,17,7,A_Scream,S_VILE_DIE3,0,0}, // S_VILE_DIE2
459 {SPR_VILE,18,7,A_Fall,S_VILE_DIE4,0,0}, // S_VILE_DIE3
460 {SPR_VILE,19,7,NULL,S_VILE_DIE5,0,0}, // S_VILE_DIE4
461 {SPR_VILE,20,7,NULL,S_VILE_DIE6,0,0}, // S_VILE_DIE5
462 {SPR_VILE,21,7,NULL,S_VILE_DIE7,0,0}, // S_VILE_DIE6
463 {SPR_VILE,22,7,NULL,S_VILE_DIE8,0,0}, // S_VILE_DIE7
464 {SPR_VILE,23,5,NULL,S_VILE_DIE9,0,0}, // S_VILE_DIE8
465 {SPR_VILE,24,5,NULL,S_VILE_DIE10,0,0}, // S_VILE_DIE9
466 {SPR_VILE,25,-1,NULL,S_NULL,0,0}, // S_VILE_DIE10
467 {SPR_FIRE,32768,2,A_StartFire,S_FIRE2,0,0}, // S_FIRE1
468 {SPR_FIRE,32769,2,A_Fire,S_FIRE3,0,0}, // S_FIRE2
469 {SPR_FIRE,32768,2,A_Fire,S_FIRE4,0,0}, // S_FIRE3
470 {SPR_FIRE,32769,2,A_Fire,S_FIRE5,0,0}, // S_FIRE4
471 {SPR_FIRE,32770,2,A_FireCrackle,S_FIRE6,0,0}, // S_FIRE5
472 {SPR_FIRE,32769,2,A_Fire,S_FIRE7,0,0}, // S_FIRE6
473 {SPR_FIRE,32770,2,A_Fire,S_FIRE8,0,0}, // S_FIRE7
474 {SPR_FIRE,32769,2,A_Fire,S_FIRE9,0,0}, // S_FIRE8
475 {SPR_FIRE,32770,2,A_Fire,S_FIRE10,0,0}, // S_FIRE9
476 {SPR_FIRE,32771,2,A_Fire,S_FIRE11,0,0}, // S_FIRE10
477 {SPR_FIRE,32770,2,A_Fire,S_FIRE12,0,0}, // S_FIRE11
478 {SPR_FIRE,32771,2,A_Fire,S_FIRE13,0,0}, // S_FIRE12
479 {SPR_FIRE,32770,2,A_Fire,S_FIRE14,0,0}, // S_FIRE13
480 {SPR_FIRE,32771,2,A_Fire,S_FIRE15,0,0}, // S_FIRE14
481 {SPR_FIRE,32772,2,A_Fire,S_FIRE16,0,0}, // S_FIRE15
482 {SPR_FIRE,32771,2,A_Fire,S_FIRE17,0,0}, // S_FIRE16
483 {SPR_FIRE,32772,2,A_Fire,S_FIRE18,0,0}, // S_FIRE17
484 {SPR_FIRE,32771,2,A_Fire,S_FIRE19,0,0}, // S_FIRE18
485 {SPR_FIRE,32772,2,A_FireCrackle,S_FIRE20,0,0}, // S_FIRE19
486 {SPR_FIRE,32773,2,A_Fire,S_FIRE21,0,0}, // S_FIRE20
487 {SPR_FIRE,32772,2,A_Fire,S_FIRE22,0,0}, // S_FIRE21
488 {SPR_FIRE,32773,2,A_Fire,S_FIRE23,0,0}, // S_FIRE22
489 {SPR_FIRE,32772,2,A_Fire,S_FIRE24,0,0}, // S_FIRE23
490 {SPR_FIRE,32773,2,A_Fire,S_FIRE25,0,0}, // S_FIRE24
491 {SPR_FIRE,32774,2,A_Fire,S_FIRE26,0,0}, // S_FIRE25
492 {SPR_FIRE,32775,2,A_Fire,S_FIRE27,0,0}, // S_FIRE26
493 {SPR_FIRE,32774,2,A_Fire,S_FIRE28,0,0}, // S_FIRE27
494 {SPR_FIRE,32775,2,A_Fire,S_FIRE29,0,0}, // S_FIRE28
495 {SPR_FIRE,32774,2,A_Fire,S_FIRE30,0,0}, // S_FIRE29
496 {SPR_FIRE,32775,2,A_Fire,S_NULL,0,0}, // S_FIRE30
497 {SPR_PUFF,1,4,NULL,S_SMOKE2,0,0}, // S_SMOKE1
498 {SPR_PUFF,2,4,NULL,S_SMOKE3,0,0}, // S_SMOKE2
499 {SPR_PUFF,1,4,NULL,S_SMOKE4,0,0}, // S_SMOKE3
500 {SPR_PUFF,2,4,NULL,S_SMOKE5,0,0}, // S_SMOKE4
501 {SPR_PUFF,3,4,NULL,S_NULL,0,0}, // S_SMOKE5
502 {SPR_FATB,32768,2,A_Tracer,S_TRACER2,0,0}, // S_TRACER
503 {SPR_FATB,32769,2,A_Tracer,S_TRACER,0,0}, // S_TRACER2
504 {SPR_FBXP,32768,8,NULL,S_TRACEEXP2,0,0}, // S_TRACEEXP1
505 {SPR_FBXP,32769,6,NULL,S_TRACEEXP3,0,0}, // S_TRACEEXP2
506 {SPR_FBXP,32770,4,NULL,S_NULL,0,0}, // S_TRACEEXP3
507 {SPR_SKEL,0,10,A_Look,S_SKEL_STND2,0,0}, // S_SKEL_STND
508 {SPR_SKEL,1,10,A_Look,S_SKEL_STND,0,0}, // S_SKEL_STND2
509 {SPR_SKEL,0,2,A_Chase,S_SKEL_RUN2,0,0}, // S_SKEL_RUN1
510 {SPR_SKEL,0,2,A_Chase,S_SKEL_RUN3,0,0}, // S_SKEL_RUN2
511 {SPR_SKEL,1,2,A_Chase,S_SKEL_RUN4,0,0}, // S_SKEL_RUN3
512 {SPR_SKEL,1,2,A_Chase,S_SKEL_RUN5,0,0}, // S_SKEL_RUN4
513 {SPR_SKEL,2,2,A_Chase,S_SKEL_RUN6,0,0}, // S_SKEL_RUN5
514 {SPR_SKEL,2,2,A_Chase,S_SKEL_RUN7,0,0}, // S_SKEL_RUN6
515 {SPR_SKEL,3,2,A_Chase,S_SKEL_RUN8,0,0}, // S_SKEL_RUN7
516 {SPR_SKEL,3,2,A_Chase,S_SKEL_RUN9,0,0}, // S_SKEL_RUN8
517 {SPR_SKEL,4,2,A_Chase,S_SKEL_RUN10,0,0}, // S_SKEL_RUN9
518 {SPR_SKEL,4,2,A_Chase,S_SKEL_RUN11,0,0}, // S_SKEL_RUN10
519 {SPR_SKEL,5,2,A_Chase,S_SKEL_RUN12,0,0}, // S_SKEL_RUN11
520 {SPR_SKEL,5,2,A_Chase,S_SKEL_RUN1,0,0}, // S_SKEL_RUN12
521 {SPR_SKEL,6,0,A_FaceTarget,S_SKEL_FIST2,0,0}, // S_SKEL_FIST1
522 {SPR_SKEL,6,6,A_SkelWhoosh,S_SKEL_FIST3,0,0}, // S_SKEL_FIST2
523 {SPR_SKEL,7,6,A_FaceTarget,S_SKEL_FIST4,0,0}, // S_SKEL_FIST3
524 {SPR_SKEL,8,6,A_SkelFist,S_SKEL_RUN1,0,0}, // S_SKEL_FIST4
525 {SPR_SKEL,32777,0,A_FaceTarget,S_SKEL_MISS2,0,0}, // S_SKEL_MISS1
526 {SPR_SKEL,32777,10,A_FaceTarget,S_SKEL_MISS3,0,0}, // S_SKEL_MISS2
527 {SPR_SKEL,10,10,A_SkelMissile,S_SKEL_MISS4,0,0}, // S_SKEL_MISS3
528 {SPR_SKEL,10,10,A_FaceTarget,S_SKEL_RUN1,0,0}, // S_SKEL_MISS4
529 {SPR_SKEL,11,5,NULL,S_SKEL_PAIN2,0,0}, // S_SKEL_PAIN
530 {SPR_SKEL,11,5,A_Pain,S_SKEL_RUN1,0,0}, // S_SKEL_PAIN2
531 {SPR_SKEL,11,7,NULL,S_SKEL_DIE2,0,0}, // S_SKEL_DIE1
532 {SPR_SKEL,12,7,NULL,S_SKEL_DIE3,0,0}, // S_SKEL_DIE2
533 {SPR_SKEL,13,7,A_Scream,S_SKEL_DIE4,0,0}, // S_SKEL_DIE3
534 {SPR_SKEL,14,7,A_Fall,S_SKEL_DIE5,0,0}, // S_SKEL_DIE4
535 {SPR_SKEL,15,7,NULL,S_SKEL_DIE6,0,0}, // S_SKEL_DIE5
536 {SPR_SKEL,16,-1,NULL,S_NULL,0,0}, // S_SKEL_DIE6
537 {SPR_SKEL,16,5,NULL,S_SKEL_RAISE2,0,0}, // S_SKEL_RAISE1
538 {SPR_SKEL,15,5,NULL,S_SKEL_RAISE3,0,0}, // S_SKEL_RAISE2
539 {SPR_SKEL,14,5,NULL,S_SKEL_RAISE4,0,0}, // S_SKEL_RAISE3
540 {SPR_SKEL,13,5,NULL,S_SKEL_RAISE5,0,0}, // S_SKEL_RAISE4
541 {SPR_SKEL,12,5,NULL,S_SKEL_RAISE6,0,0}, // S_SKEL_RAISE5
542 {SPR_SKEL,11,5,NULL,S_SKEL_RUN1,0,0}, // S_SKEL_RAISE6
543 {SPR_MANF,32768,4,NULL,S_FATSHOT2,0,0}, // S_FATSHOT1
544 {SPR_MANF,32769,4,NULL,S_FATSHOT1,0,0}, // S_FATSHOT2
545 {SPR_MISL,32769,8,NULL,S_FATSHOTX2,0,0}, // S_FATSHOTX1
546 {SPR_MISL,32770,6,NULL,S_FATSHOTX3,0,0}, // S_FATSHOTX2
547 {SPR_MISL,32771,4,NULL,S_NULL,0,0}, // S_FATSHOTX3
548 {SPR_FATT,0,15,A_Look,S_FATT_STND2,0,0}, // S_FATT_STND
549 {SPR_FATT,1,15,A_Look,S_FATT_STND,0,0}, // S_FATT_STND2
550 {SPR_FATT,0,4,A_Chase,S_FATT_RUN2,0,0}, // S_FATT_RUN1
551 {SPR_FATT,0,4,A_Chase,S_FATT_RUN3,0,0}, // S_FATT_RUN2
552 {SPR_FATT,1,4,A_Chase,S_FATT_RUN4,0,0}, // S_FATT_RUN3
553 {SPR_FATT,1,4,A_Chase,S_FATT_RUN5,0,0}, // S_FATT_RUN4
554 {SPR_FATT,2,4,A_Chase,S_FATT_RUN6,0,0}, // S_FATT_RUN5
555 {SPR_FATT,2,4,A_Chase,S_FATT_RUN7,0,0}, // S_FATT_RUN6
556 {SPR_FATT,3,4,A_Chase,S_FATT_RUN8,0,0}, // S_FATT_RUN7
557 {SPR_FATT,3,4,A_Chase,S_FATT_RUN9,0,0}, // S_FATT_RUN8
558 {SPR_FATT,4,4,A_Chase,S_FATT_RUN10,0,0}, // S_FATT_RUN9
559 {SPR_FATT,4,4,A_Chase,S_FATT_RUN11,0,0}, // S_FATT_RUN10
560 {SPR_FATT,5,4,A_Chase,S_FATT_RUN12,0,0}, // S_FATT_RUN11
561 {SPR_FATT,5,4,A_Chase,S_FATT_RUN1,0,0}, // S_FATT_RUN12
562 {SPR_FATT,6,20,A_FatRaise,S_FATT_ATK2,0,0}, // S_FATT_ATK1
563 {SPR_FATT,32775,10,A_FatAttack1,S_FATT_ATK3,0,0}, // S_FATT_ATK2
564 {SPR_FATT,8,5,A_FaceTarget,S_FATT_ATK4,0,0}, // S_FATT_ATK3
565 {SPR_FATT,6,5,A_FaceTarget,S_FATT_ATK5,0,0}, // S_FATT_ATK4
566 {SPR_FATT,32775,10,A_FatAttack2,S_FATT_ATK6,0,0}, // S_FATT_ATK5
567 {SPR_FATT,8,5,A_FaceTarget,S_FATT_ATK7,0,0}, // S_FATT_ATK6
568 {SPR_FATT,6,5,A_FaceTarget,S_FATT_ATK8,0,0}, // S_FATT_ATK7
569 {SPR_FATT,32775,10,A_FatAttack3,S_FATT_ATK9,0,0}, // S_FATT_ATK8
570 {SPR_FATT,8,5,A_FaceTarget,S_FATT_ATK10,0,0}, // S_FATT_ATK9
571 {SPR_FATT,6,5,A_FaceTarget,S_FATT_RUN1,0,0}, // S_FATT_ATK10
572 {SPR_FATT,9,3,NULL,S_FATT_PAIN2,0,0}, // S_FATT_PAIN
573 {SPR_FATT,9,3,A_Pain,S_FATT_RUN1,0,0}, // S_FATT_PAIN2
574 {SPR_FATT,10,6,NULL,S_FATT_DIE2,0,0}, // S_FATT_DIE1
575 {SPR_FATT,11,6,A_Scream,S_FATT_DIE3,0,0}, // S_FATT_DIE2
576 {SPR_FATT,12,6,A_Fall,S_FATT_DIE4,0,0}, // S_FATT_DIE3
577 {SPR_FATT,13,6,NULL,S_FATT_DIE5,0,0}, // S_FATT_DIE4
578 {SPR_FATT,14,6,NULL,S_FATT_DIE6,0,0}, // S_FATT_DIE5
579 {SPR_FATT,15,6,NULL,S_FATT_DIE7,0,0}, // S_FATT_DIE6
580 {SPR_FATT,16,6,NULL,S_FATT_DIE8,0,0}, // S_FATT_DIE7
581 {SPR_FATT,17,6,NULL,S_FATT_DIE9,0,0}, // S_FATT_DIE8
582 {SPR_FATT,18,6,NULL,S_FATT_DIE10,0,0}, // S_FATT_DIE9
583 {SPR_FATT,19,-1,A_BossDeath,S_NULL,0,0}, // S_FATT_DIE10
584 {SPR_FATT,17,5,NULL,S_FATT_RAISE2,0,0}, // S_FATT_RAISE1
585 {SPR_FATT,16,5,NULL,S_FATT_RAISE3,0,0}, // S_FATT_RAISE2
586 {SPR_FATT,15,5,NULL,S_FATT_RAISE4,0,0}, // S_FATT_RAISE3
587 {SPR_FATT,14,5,NULL,S_FATT_RAISE5,0,0}, // S_FATT_RAISE4
588 {SPR_FATT,13,5,NULL,S_FATT_RAISE6,0,0}, // S_FATT_RAISE5
589 {SPR_FATT,12,5,NULL,S_FATT_RAISE7,0,0}, // S_FATT_RAISE6
590 {SPR_FATT,11,5,NULL,S_FATT_RAISE8,0,0}, // S_FATT_RAISE7
591 {SPR_FATT,10,5,NULL,S_FATT_RUN1,0,0}, // S_FATT_RAISE8
592 {SPR_CPOS,0,10,A_Look,S_CPOS_STND2,0,0}, // S_CPOS_STND
593 {SPR_CPOS,1,10,A_Look,S_CPOS_STND,0,0}, // S_CPOS_STND2
594 {SPR_CPOS,0,3,A_Chase,S_CPOS_RUN2,0,0}, // S_CPOS_RUN1
595 {SPR_CPOS,0,3,A_Chase,S_CPOS_RUN3,0,0}, // S_CPOS_RUN2
596 {SPR_CPOS,1,3,A_Chase,S_CPOS_RUN4,0,0}, // S_CPOS_RUN3
597 {SPR_CPOS,1,3,A_Chase,S_CPOS_RUN5,0,0}, // S_CPOS_RUN4
598 {SPR_CPOS,2,3,A_Chase,S_CPOS_RUN6,0,0}, // S_CPOS_RUN5
599 {SPR_CPOS,2,3,A_Chase,S_CPOS_RUN7,0,0}, // S_CPOS_RUN6
600 {SPR_CPOS,3,3,A_Chase,S_CPOS_RUN8,0,0}, // S_CPOS_RUN7
601 {SPR_CPOS,3,3,A_Chase,S_CPOS_RUN1,0,0}, // S_CPOS_RUN8
602 {SPR_CPOS,4,10,A_FaceTarget,S_CPOS_ATK2,0,0}, // S_CPOS_ATK1
603 {SPR_CPOS,32773,4,A_CPosAttack,S_CPOS_ATK3,0,0}, // S_CPOS_ATK2
604 {SPR_CPOS,32772,4,A_CPosAttack,S_CPOS_ATK4,0,0}, // S_CPOS_ATK3
605 {SPR_CPOS,5,1,A_CPosRefire,S_CPOS_ATK2,0,0}, // S_CPOS_ATK4
606 {SPR_CPOS,6,3,NULL,S_CPOS_PAIN2,0,0}, // S_CPOS_PAIN
607 {SPR_CPOS,6,3,A_Pain,S_CPOS_RUN1,0,0}, // S_CPOS_PAIN2
608 {SPR_CPOS,7,5,NULL,S_CPOS_DIE2,0,0}, // S_CPOS_DIE1
609 {SPR_CPOS,8,5,A_Scream,S_CPOS_DIE3,0,0}, // S_CPOS_DIE2
610 {SPR_CPOS,9,5,A_Fall,S_CPOS_DIE4,0,0}, // S_CPOS_DIE3
611 {SPR_CPOS,10,5,NULL,S_CPOS_DIE5,0,0}, // S_CPOS_DIE4
612 {SPR_CPOS,11,5,NULL,S_CPOS_DIE6,0,0}, // S_CPOS_DIE5
613 {SPR_CPOS,12,5,NULL,S_CPOS_DIE7,0,0}, // S_CPOS_DIE6
614 {SPR_CPOS,13,-1,NULL,S_NULL,0,0}, // S_CPOS_DIE7
615 {SPR_CPOS,14,5,NULL,S_CPOS_XDIE2,0,0}, // S_CPOS_XDIE1
616 {SPR_CPOS,15,5,A_XScream,S_CPOS_XDIE3,0,0}, // S_CPOS_XDIE2
617 {SPR_CPOS,16,5,A_Fall,S_CPOS_XDIE4,0,0}, // S_CPOS_XDIE3
618 {SPR_CPOS,17,5,NULL,S_CPOS_XDIE5,0,0}, // S_CPOS_XDIE4
619 {SPR_CPOS,18,5,NULL,S_CPOS_XDIE6,0,0}, // S_CPOS_XDIE5
620 {SPR_CPOS,19,-1,NULL,S_NULL,0,0}, // S_CPOS_XDIE6
621 {SPR_CPOS,13,5,NULL,S_CPOS_RAISE2,0,0}, // S_CPOS_RAISE1
622 {SPR_CPOS,12,5,NULL,S_CPOS_RAISE3,0,0}, // S_CPOS_RAISE2
623 {SPR_CPOS,11,5,NULL,S_CPOS_RAISE4,0,0}, // S_CPOS_RAISE3
624 {SPR_CPOS,10,5,NULL,S_CPOS_RAISE5,0,0}, // S_CPOS_RAISE4
625 {SPR_CPOS,9,5,NULL,S_CPOS_RAISE6,0,0}, // S_CPOS_RAISE5
626 {SPR_CPOS,8,5,NULL,S_CPOS_RAISE7,0,0}, // S_CPOS_RAISE6
627 {SPR_CPOS,7,5,NULL,S_CPOS_RUN1,0,0}, // S_CPOS_RAISE7
628 {SPR_TROO,0,10,A_Look,S_TROO_STND2,0,0}, // S_TROO_STND
629 {SPR_TROO,1,10,A_Look,S_TROO_STND,0,0}, // S_TROO_STND2
630 {SPR_TROO,0,3,A_Chase,S_TROO_RUN2,0,0}, // S_TROO_RUN1
631 {SPR_TROO,0,3,A_Chase,S_TROO_RUN3,0,0}, // S_TROO_RUN2
632 {SPR_TROO,1,3,A_Chase,S_TROO_RUN4,0,0}, // S_TROO_RUN3
633 {SPR_TROO,1,3,A_Chase,S_TROO_RUN5,0,0}, // S_TROO_RUN4
634 {SPR_TROO,2,3,A_Chase,S_TROO_RUN6,0,0}, // S_TROO_RUN5
635 {SPR_TROO,2,3,A_Chase,S_TROO_RUN7,0,0}, // S_TROO_RUN6
636 {SPR_TROO,3,3,A_Chase,S_TROO_RUN8,0,0}, // S_TROO_RUN7
637 {SPR_TROO,3,3,A_Chase,S_TROO_RUN1,0,0}, // S_TROO_RUN8
638 {SPR_TROO,4,8,A_FaceTarget,S_TROO_ATK2,0,0}, // S_TROO_ATK1
639 {SPR_TROO,5,8,A_FaceTarget,S_TROO_ATK3,0,0}, // S_TROO_ATK2
640 {SPR_TROO,6,6,A_TroopAttack,S_TROO_RUN1,0,0}, // S_TROO_ATK3
641 {SPR_TROO,7,2,NULL,S_TROO_PAIN2,0,0}, // S_TROO_PAIN
642 {SPR_TROO,7,2,A_Pain,S_TROO_RUN1,0,0}, // S_TROO_PAIN2
643 {SPR_TROO,8,8,NULL,S_TROO_DIE2,0,0}, // S_TROO_DIE1
644 {SPR_TROO,9,8,A_Scream,S_TROO_DIE3,0,0}, // S_TROO_DIE2
645 {SPR_TROO,10,6,NULL,S_TROO_DIE4,0,0}, // S_TROO_DIE3
646 {SPR_TROO,11,6,A_Fall,S_TROO_DIE5,0,0}, // S_TROO_DIE4
647 {SPR_TROO,12,-1,NULL,S_NULL,0,0}, // S_TROO_DIE5
648 {SPR_TROO,13,5,NULL,S_TROO_XDIE2,0,0}, // S_TROO_XDIE1
649 {SPR_TROO,14,5,A_XScream,S_TROO_XDIE3,0,0}, // S_TROO_XDIE2
650 {SPR_TROO,15,5,NULL,S_TROO_XDIE4,0,0}, // S_TROO_XDIE3
651 {SPR_TROO,16,5,A_Fall,S_TROO_XDIE5,0,0}, // S_TROO_XDIE4
652 {SPR_TROO,17,5,NULL,S_TROO_XDIE6,0,0}, // S_TROO_XDIE5
653 {SPR_TROO,18,5,NULL,S_TROO_XDIE7,0,0}, // S_TROO_XDIE6
654 {SPR_TROO,19,5,NULL,S_TROO_XDIE8,0,0}, // S_TROO_XDIE7
655 {SPR_TROO,20,-1,NULL,S_NULL,0,0}, // S_TROO_XDIE8
656 {SPR_TROO,12,8,NULL,S_TROO_RAISE2,0,0}, // S_TROO_RAISE1
657 {SPR_TROO,11,8,NULL,S_TROO_RAISE3,0,0}, // S_TROO_RAISE2
658 {SPR_TROO,10,6,NULL,S_TROO_RAISE4,0,0}, // S_TROO_RAISE3
659 {SPR_TROO,9,6,NULL,S_TROO_RAISE5,0,0}, // S_TROO_RAISE4
660 {SPR_TROO,8,6,NULL,S_TROO_RUN1,0,0}, // S_TROO_RAISE5
661 {SPR_SARG,0,10,A_Look,S_SARG_STND2,0,0}, // S_SARG_STND
662 {SPR_SARG,1,10,A_Look,S_SARG_STND,0,0}, // S_SARG_STND2
663 {SPR_SARG,0,2,A_Chase,S_SARG_RUN2,0,0}, // S_SARG_RUN1
664 {SPR_SARG,0,2,A_Chase,S_SARG_RUN3,0,0}, // S_SARG_RUN2
665 {SPR_SARG,1,2,A_Chase,S_SARG_RUN4,0,0}, // S_SARG_RUN3
666 {SPR_SARG,1,2,A_Chase,S_SARG_RUN5,0,0}, // S_SARG_RUN4
667 {SPR_SARG,2,2,A_Chase,S_SARG_RUN6,0,0}, // S_SARG_RUN5
668 {SPR_SARG,2,2,A_Chase,S_SARG_RUN7,0,0}, // S_SARG_RUN6
669 {SPR_SARG,3,2,A_Chase,S_SARG_RUN8,0,0}, // S_SARG_RUN7
670 {SPR_SARG,3,2,A_Chase,S_SARG_RUN1,0,0}, // S_SARG_RUN8
671 {SPR_SARG,4,8,A_FaceTarget,S_SARG_ATK2,0,0}, // S_SARG_ATK1
672 {SPR_SARG,5,8,A_FaceTarget,S_SARG_ATK3,0,0}, // S_SARG_ATK2
673 {SPR_SARG,6,8,A_SargAttack,S_SARG_RUN1,0,0}, // S_SARG_ATK3
674 {SPR_SARG,7,2,NULL,S_SARG_PAIN2,0,0}, // S_SARG_PAIN
675 {SPR_SARG,7,2,A_Pain,S_SARG_RUN1,0,0}, // S_SARG_PAIN2
676 {SPR_SARG,8,8,NULL,S_SARG_DIE2,0,0}, // S_SARG_DIE1
677 {SPR_SARG,9,8,A_Scream,S_SARG_DIE3,0,0}, // S_SARG_DIE2
678 {SPR_SARG,10,4,NULL,S_SARG_DIE4,0,0}, // S_SARG_DIE3
679 {SPR_SARG,11,4,A_Fall,S_SARG_DIE5,0,0}, // S_SARG_DIE4
680 {SPR_SARG,12,4,NULL,S_SARG_DIE6,0,0}, // S_SARG_DIE5
681 {SPR_SARG,13,-1,NULL,S_NULL,0,0}, // S_SARG_DIE6
682 {SPR_SARG,13,5,NULL,S_SARG_RAISE2,0,0}, // S_SARG_RAISE1
683 {SPR_SARG,12,5,NULL,S_SARG_RAISE3,0,0}, // S_SARG_RAISE2
684 {SPR_SARG,11,5,NULL,S_SARG_RAISE4,0,0}, // S_SARG_RAISE3
685 {SPR_SARG,10,5,NULL,S_SARG_RAISE5,0,0}, // S_SARG_RAISE4
686 {SPR_SARG,9,5,NULL,S_SARG_RAISE6,0,0}, // S_SARG_RAISE5
687 {SPR_SARG,8,5,NULL,S_SARG_RUN1,0,0}, // S_SARG_RAISE6
688 {SPR_HEAD,0,10,A_Look,S_HEAD_STND,0,0}, // S_HEAD_STND
689 {SPR_HEAD,0,3,A_Chase,S_HEAD_RUN1,0,0}, // S_HEAD_RUN1
690 {SPR_HEAD,1,5,A_FaceTarget,S_HEAD_ATK2,0,0}, // S_HEAD_ATK1
691 {SPR_HEAD,2,5,A_FaceTarget,S_HEAD_ATK3,0,0}, // S_HEAD_ATK2
692 {SPR_HEAD,32771,5,A_HeadAttack,S_HEAD_RUN1,0,0}, // S_HEAD_ATK3
693 {SPR_HEAD,4,3,NULL,S_HEAD_PAIN2,0,0}, // S_HEAD_PAIN
694 {SPR_HEAD,4,3,A_Pain,S_HEAD_PAIN3,0,0}, // S_HEAD_PAIN2
695 {SPR_HEAD,5,6,NULL,S_HEAD_RUN1,0,0}, // S_HEAD_PAIN3
696 {SPR_HEAD,6,8,NULL,S_HEAD_DIE2,0,0}, // S_HEAD_DIE1
697 {SPR_HEAD,7,8,A_Scream,S_HEAD_DIE3,0,0}, // S_HEAD_DIE2
698 {SPR_HEAD,8,8,NULL,S_HEAD_DIE4,0,0}, // S_HEAD_DIE3
699 {SPR_HEAD,9,8,NULL,S_HEAD_DIE5,0,0}, // S_HEAD_DIE4
700 {SPR_HEAD,10,8,A_Fall,S_HEAD_DIE6,0,0}, // S_HEAD_DIE5
701 {SPR_HEAD,11,-1,NULL,S_NULL,0,0}, // S_HEAD_DIE6
702 {SPR_HEAD,11,8,NULL,S_HEAD_RAISE2,0,0}, // S_HEAD_RAISE1
703 {SPR_HEAD,10,8,NULL,S_HEAD_RAISE3,0,0}, // S_HEAD_RAISE2
704 {SPR_HEAD,9,8,NULL,S_HEAD_RAISE4,0,0}, // S_HEAD_RAISE3
705 {SPR_HEAD,8,8,NULL,S_HEAD_RAISE5,0,0}, // S_HEAD_RAISE4
706 {SPR_HEAD,7,8,NULL,S_HEAD_RAISE6,0,0}, // S_HEAD_RAISE5
707 {SPR_HEAD,6,8,NULL,S_HEAD_RUN1,0,0}, // S_HEAD_RAISE6
708 {SPR_BAL7,32768,4,NULL,S_BRBALL2,0,0}, // S_BRBALL1
709 {SPR_BAL7,32769,4,NULL,S_BRBALL1,0,0}, // S_BRBALL2
710 {SPR_BAL7,32770,6,NULL,S_BRBALLX2,0,0}, // S_BRBALLX1
711 {SPR_BAL7,32771,6,NULL,S_BRBALLX3,0,0}, // S_BRBALLX2
712 {SPR_BAL7,32772,6,NULL,S_NULL,0,0}, // S_BRBALLX3
713 {SPR_BOSS,0,10,A_Look,S_BOSS_STND2,0,0}, // S_BOSS_STND
714 {SPR_BOSS,1,10,A_Look,S_BOSS_STND,0,0}, // S_BOSS_STND2
715 {SPR_BOSS,0,3,A_Chase,S_BOSS_RUN2,0,0}, // S_BOSS_RUN1
716 {SPR_BOSS,0,3,A_Chase,S_BOSS_RUN3,0,0}, // S_BOSS_RUN2
717 {SPR_BOSS,1,3,A_Chase,S_BOSS_RUN4,0,0}, // S_BOSS_RUN3
718 {SPR_BOSS,1,3,A_Chase,S_BOSS_RUN5,0,0}, // S_BOSS_RUN4
719 {SPR_BOSS,2,3,A_Chase,S_BOSS_RUN6,0,0}, // S_BOSS_RUN5
720 {SPR_BOSS,2,3,A_Chase,S_BOSS_RUN7,0,0}, // S_BOSS_RUN6
721 {SPR_BOSS,3,3,A_Chase,S_BOSS_RUN8,0,0}, // S_BOSS_RUN7
722 {SPR_BOSS,3,3,A_Chase,S_BOSS_RUN1,0,0}, // S_BOSS_RUN8
723 {SPR_BOSS,4,8,A_FaceTarget,S_BOSS_ATK2,0,0}, // S_BOSS_ATK1
724 {SPR_BOSS,5,8,A_FaceTarget,S_BOSS_ATK3,0,0}, // S_BOSS_ATK2
725 {SPR_BOSS,6,8,A_BruisAttack,S_BOSS_RUN1,0,0}, // S_BOSS_ATK3
726 {SPR_BOSS,7,2,NULL,S_BOSS_PAIN2,0,0}, // S_BOSS_PAIN
727 {SPR_BOSS,7,2,A_Pain,S_BOSS_RUN1,0,0}, // S_BOSS_PAIN2
728 {SPR_BOSS,8,8,NULL,S_BOSS_DIE2,0,0}, // S_BOSS_DIE1
729 {SPR_BOSS,9,8,A_Scream,S_BOSS_DIE3,0,0}, // S_BOSS_DIE2
730 {SPR_BOSS,10,8,NULL,S_BOSS_DIE4,0,0}, // S_BOSS_DIE3
731 {SPR_BOSS,11,8,A_Fall,S_BOSS_DIE5,0,0}, // S_BOSS_DIE4
732 {SPR_BOSS,12,8,NULL,S_BOSS_DIE6,0,0}, // S_BOSS_DIE5
733 {SPR_BOSS,13,8,NULL,S_BOSS_DIE7,0,0}, // S_BOSS_DIE6
734 {SPR_BOSS,14,-1,A_BossDeath,S_NULL,0,0}, // S_BOSS_DIE7
735 {SPR_BOSS,14,8,NULL,S_BOSS_RAISE2,0,0}, // S_BOSS_RAISE1
736 {SPR_BOSS,13,8,NULL,S_BOSS_RAISE3,0,0}, // S_BOSS_RAISE2
737 {SPR_BOSS,12,8,NULL,S_BOSS_RAISE4,0,0}, // S_BOSS_RAISE3
738 {SPR_BOSS,11,8,NULL,S_BOSS_RAISE5,0,0}, // S_BOSS_RAISE4
739 {SPR_BOSS,10,8,NULL,S_BOSS_RAISE6,0,0}, // S_BOSS_RAISE5
740 {SPR_BOSS,9,8,NULL,S_BOSS_RAISE7,0,0}, // S_BOSS_RAISE6
741 {SPR_BOSS,8,8,NULL,S_BOSS_RUN1,0,0}, // S_BOSS_RAISE7
742 {SPR_BOS2,0,10,A_Look,S_BOS2_STND2,0,0}, // S_BOS2_STND
743 {SPR_BOS2,1,10,A_Look,S_BOS2_STND,0,0}, // S_BOS2_STND2
744 {SPR_BOS2,0,3,A_Chase,S_BOS2_RUN2,0,0}, // S_BOS2_RUN1
745 {SPR_BOS2,0,3,A_Chase,S_BOS2_RUN3,0,0}, // S_BOS2_RUN2
746 {SPR_BOS2,1,3,A_Chase,S_BOS2_RUN4,0,0}, // S_BOS2_RUN3
747 {SPR_BOS2,1,3,A_Chase,S_BOS2_RUN5,0,0}, // S_BOS2_RUN4
748 {SPR_BOS2,2,3,A_Chase,S_BOS2_RUN6,0,0}, // S_BOS2_RUN5
749 {SPR_BOS2,2,3,A_Chase,S_BOS2_RUN7,0,0}, // S_BOS2_RUN6
750 {SPR_BOS2,3,3,A_Chase,S_BOS2_RUN8,0,0}, // S_BOS2_RUN7
751 {SPR_BOS2,3,3,A_Chase,S_BOS2_RUN1,0,0}, // S_BOS2_RUN8
752 {SPR_BOS2,4,8,A_FaceTarget,S_BOS2_ATK2,0,0}, // S_BOS2_ATK1
753 {SPR_BOS2,5,8,A_FaceTarget,S_BOS2_ATK3,0,0}, // S_BOS2_ATK2
754 {SPR_BOS2,6,8,A_BruisAttack,S_BOS2_RUN1,0,0}, // S_BOS2_ATK3
755 {SPR_BOS2,7,2,NULL,S_BOS2_PAIN2,0,0}, // S_BOS2_PAIN
756 {SPR_BOS2,7,2,A_Pain,S_BOS2_RUN1,0,0}, // S_BOS2_PAIN2
757 {SPR_BOS2,8,8,NULL,S_BOS2_DIE2,0,0}, // S_BOS2_DIE1
758 {SPR_BOS2,9,8,A_Scream,S_BOS2_DIE3,0,0}, // S_BOS2_DIE2
759 {SPR_BOS2,10,8,NULL,S_BOS2_DIE4,0,0}, // S_BOS2_DIE3
760 {SPR_BOS2,11,8,A_Fall,S_BOS2_DIE5,0,0}, // S_BOS2_DIE4
761 {SPR_BOS2,12,8,NULL,S_BOS2_DIE6,0,0}, // S_BOS2_DIE5
762 {SPR_BOS2,13,8,NULL,S_BOS2_DIE7,0,0}, // S_BOS2_DIE6
763 {SPR_BOS2,14,-1,NULL,S_NULL,0,0}, // S_BOS2_DIE7
764 {SPR_BOS2,14,8,NULL,S_BOS2_RAISE2,0,0}, // S_BOS2_RAISE1
765 {SPR_BOS2,13,8,NULL,S_BOS2_RAISE3,0,0}, // S_BOS2_RAISE2
766 {SPR_BOS2,12,8,NULL,S_BOS2_RAISE4,0,0}, // S_BOS2_RAISE3
767 {SPR_BOS2,11,8,NULL,S_BOS2_RAISE5,0,0}, // S_BOS2_RAISE4
768 {SPR_BOS2,10,8,NULL,S_BOS2_RAISE6,0,0}, // S_BOS2_RAISE5
769 {SPR_BOS2,9,8,NULL,S_BOS2_RAISE7,0,0}, // S_BOS2_RAISE6
770 {SPR_BOS2,8,8,NULL,S_BOS2_RUN1,0,0}, // S_BOS2_RAISE7
771 {SPR_SKUL,32768,10,A_Look,S_SKULL_STND2,0,0}, // S_SKULL_STND
772 {SPR_SKUL,32769,10,A_Look,S_SKULL_STND,0,0}, // S_SKULL_STND2
773 {SPR_SKUL,32768,6,A_Chase,S_SKULL_RUN2,0,0}, // S_SKULL_RUN1
774 {SPR_SKUL,32769,6,A_Chase,S_SKULL_RUN1,0,0}, // S_SKULL_RUN2
775 {SPR_SKUL,32770,10,A_FaceTarget,S_SKULL_ATK2,0,0}, // S_SKULL_ATK1
776 {SPR_SKUL,32771,4,A_SkullAttack,S_SKULL_ATK3,0,0}, // S_SKULL_ATK2
777 {SPR_SKUL,32770,4,NULL,S_SKULL_ATK4,0,0}, // S_SKULL_ATK3
778 {SPR_SKUL,32771,4,NULL,S_SKULL_ATK3,0,0}, // S_SKULL_ATK4
779 {SPR_SKUL,32772,3,NULL,S_SKULL_PAIN2,0,0}, // S_SKULL_PAIN
780 {SPR_SKUL,32772,3,A_Pain,S_SKULL_RUN1,0,0}, // S_SKULL_PAIN2
781 {SPR_SKUL,32773,6,NULL,S_SKULL_DIE2,0,0}, // S_SKULL_DIE1
782 {SPR_SKUL,32774,6,A_Scream,S_SKULL_DIE3,0,0}, // S_SKULL_DIE2
783 {SPR_SKUL,32775,6,NULL,S_SKULL_DIE4,0,0}, // S_SKULL_DIE3
784 {SPR_SKUL,32776,6,A_Fall,S_SKULL_DIE5,0,0}, // S_SKULL_DIE4
785 {SPR_SKUL,9,6,NULL,S_SKULL_DIE6,0,0}, // S_SKULL_DIE5
786 {SPR_SKUL,10,6,NULL,S_NULL,0,0}, // S_SKULL_DIE6
787 {SPR_SPID,0,10,A_Look,S_SPID_STND2,0,0}, // S_SPID_STND
788 {SPR_SPID,1,10,A_Look,S_SPID_STND,0,0}, // S_SPID_STND2
789 {SPR_SPID,0,3,A_Metal,S_SPID_RUN2,0,0}, // S_SPID_RUN1
790 {SPR_SPID,0,3,A_Chase,S_SPID_RUN3,0,0}, // S_SPID_RUN2
791 {SPR_SPID,1,3,A_Chase,S_SPID_RUN4,0,0}, // S_SPID_RUN3
792 {SPR_SPID,1,3,A_Chase,S_SPID_RUN5,0,0}, // S_SPID_RUN4
793 {SPR_SPID,2,3,A_Metal,S_SPID_RUN6,0,0}, // S_SPID_RUN5
794 {SPR_SPID,2,3,A_Chase,S_SPID_RUN7,0,0}, // S_SPID_RUN6
795 {SPR_SPID,3,3,A_Chase,S_SPID_RUN8,0,0}, // S_SPID_RUN7
796 {SPR_SPID,3,3,A_Chase,S_SPID_RUN9,0,0}, // S_SPID_RUN8
797 {SPR_SPID,4,3,A_Metal,S_SPID_RUN10,0,0}, // S_SPID_RUN9
798 {SPR_SPID,4,3,A_Chase,S_SPID_RUN11,0,0}, // S_SPID_RUN10
799 {SPR_SPID,5,3,A_Chase,S_SPID_RUN12,0,0}, // S_SPID_RUN11
800 {SPR_SPID,5,3,A_Chase,S_SPID_RUN1,0,0}, // S_SPID_RUN12
801 {SPR_SPID,32768,20,A_FaceTarget,S_SPID_ATK2,0,0}, // S_SPID_ATK1
802 {SPR_SPID,32774,4,A_SPosAttack,S_SPID_ATK3,0,0}, // S_SPID_ATK2
803 {SPR_SPID,32775,4,A_SPosAttack,S_SPID_ATK4,0,0}, // S_SPID_ATK3
804 {SPR_SPID,32775,1,A_SpidRefire,S_SPID_ATK2,0,0}, // S_SPID_ATK4
805 {SPR_SPID,8,3,NULL,S_SPID_PAIN2,0,0}, // S_SPID_PAIN
806 {SPR_SPID,8,3,A_Pain,S_SPID_RUN1,0,0}, // S_SPID_PAIN2
807 {SPR_SPID,9,20,A_Scream,S_SPID_DIE2,0,0}, // S_SPID_DIE1
808 {SPR_SPID,10,10,A_Fall,S_SPID_DIE3,0,0}, // S_SPID_DIE2
809 {SPR_SPID,11,10,NULL,S_SPID_DIE4,0,0}, // S_SPID_DIE3
810 {SPR_SPID,12,10,NULL,S_SPID_DIE5,0,0}, // S_SPID_DIE4
811 {SPR_SPID,13,10,NULL,S_SPID_DIE6,0,0}, // S_SPID_DIE5
812 {SPR_SPID,14,10,NULL,S_SPID_DIE7,0,0}, // S_SPID_DIE6
813 {SPR_SPID,15,10,NULL,S_SPID_DIE8,0,0}, // S_SPID_DIE7
814 {SPR_SPID,16,10,NULL,S_SPID_DIE9,0,0}, // S_SPID_DIE8
815 {SPR_SPID,17,10,NULL,S_SPID_DIE10,0,0}, // S_SPID_DIE9
816 {SPR_SPID,18,30,NULL,S_SPID_DIE11,0,0}, // S_SPID_DIE10
817 {SPR_SPID,18,-1,A_BossDeath,S_NULL,0,0}, // S_SPID_DIE11
818 {SPR_BSPI,0,10,A_Look,S_BSPI_STND2,0,0}, // S_BSPI_STND
819 {SPR_BSPI,1,10,A_Look,S_BSPI_STND,0,0}, // S_BSPI_STND2
820 {SPR_BSPI,0,20,NULL,S_BSPI_RUN1,0,0}, // S_BSPI_SIGHT
821 {SPR_BSPI,0,3,A_BabyMetal,S_BSPI_RUN2,0,0}, // S_BSPI_RUN1
822 {SPR_BSPI,0,3,A_Chase,S_BSPI_RUN3,0,0}, // S_BSPI_RUN2
823 {SPR_BSPI,1,3,A_Chase,S_BSPI_RUN4,0,0}, // S_BSPI_RUN3
824 {SPR_BSPI,1,3,A_Chase,S_BSPI_RUN5,0,0}, // S_BSPI_RUN4
825 {SPR_BSPI,2,3,A_Chase,S_BSPI_RUN6,0,0}, // S_BSPI_RUN5
826 {SPR_BSPI,2,3,A_Chase,S_BSPI_RUN7,0,0}, // S_BSPI_RUN6
827 {SPR_BSPI,3,3,A_BabyMetal,S_BSPI_RUN8,0,0}, // S_BSPI_RUN7
828 {SPR_BSPI,3,3,A_Chase,S_BSPI_RUN9,0,0}, // S_BSPI_RUN8
829 {SPR_BSPI,4,3,A_Chase,S_BSPI_RUN10,0,0}, // S_BSPI_RUN9
830 {SPR_BSPI,4,3,A_Chase,S_BSPI_RUN11,0,0}, // S_BSPI_RUN10
831 {SPR_BSPI,5,3,A_Chase,S_BSPI_RUN12,0,0}, // S_BSPI_RUN11
832 {SPR_BSPI,5,3,A_Chase,S_BSPI_RUN1,0,0}, // S_BSPI_RUN12
833 {SPR_BSPI,32768,20,A_FaceTarget,S_BSPI_ATK2,0,0}, // S_BSPI_ATK1
834 {SPR_BSPI,32774,4,A_BspiAttack,S_BSPI_ATK3,0,0}, // S_BSPI_ATK2
835 {SPR_BSPI,32775,4,NULL,S_BSPI_ATK4,0,0}, // S_BSPI_ATK3
836 {SPR_BSPI,32775,1,A_SpidRefire,S_BSPI_ATK2,0,0}, // S_BSPI_ATK4
837 {SPR_BSPI,8,3,NULL,S_BSPI_PAIN2,0,0}, // S_BSPI_PAIN
838 {SPR_BSPI,8,3,A_Pain,S_BSPI_RUN1,0,0}, // S_BSPI_PAIN2
839 {SPR_BSPI,9,20,A_Scream,S_BSPI_DIE2,0,0}, // S_BSPI_DIE1
840 {SPR_BSPI,10,7,A_Fall,S_BSPI_DIE3,0,0}, // S_BSPI_DIE2
841 {SPR_BSPI,11,7,NULL,S_BSPI_DIE4,0,0}, // S_BSPI_DIE3
842 {SPR_BSPI,12,7,NULL,S_BSPI_DIE5,0,0}, // S_BSPI_DIE4
843 {SPR_BSPI,13,7,NULL,S_BSPI_DIE6,0,0}, // S_BSPI_DIE5
844 {SPR_BSPI,14,7,NULL,S_BSPI_DIE7,0,0}, // S_BSPI_DIE6
845 {SPR_BSPI,15,-1,A_BossDeath,S_NULL,0,0}, // S_BSPI_DIE7
846 {SPR_BSPI,15,5,NULL,S_BSPI_RAISE2,0,0}, // S_BSPI_RAISE1
847 {SPR_BSPI,14,5,NULL,S_BSPI_RAISE3,0,0}, // S_BSPI_RAISE2
848 {SPR_BSPI,13,5,NULL,S_BSPI_RAISE4,0,0}, // S_BSPI_RAISE3
849 {SPR_BSPI,12,5,NULL,S_BSPI_RAISE5,0,0}, // S_BSPI_RAISE4
850 {SPR_BSPI,11,5,NULL,S_BSPI_RAISE6,0,0}, // S_BSPI_RAISE5
851 {SPR_BSPI,10,5,NULL,S_BSPI_RAISE7,0,0}, // S_BSPI_RAISE6
852 {SPR_BSPI,9,5,NULL,S_BSPI_RUN1,0,0}, // S_BSPI_RAISE7
853 {SPR_APLS,32768,5,NULL,S_ARACH_PLAZ2,0,0}, // S_ARACH_PLAZ
854 {SPR_APLS,32769,5,NULL,S_ARACH_PLAZ,0,0}, // S_ARACH_PLAZ2
855 {SPR_APBX,32768,5,NULL,S_ARACH_PLEX2,0,0}, // S_ARACH_PLEX
856 {SPR_APBX,32769,5,NULL,S_ARACH_PLEX3,0,0}, // S_ARACH_PLEX2
857 {SPR_APBX,32770,5,NULL,S_ARACH_PLEX4,0,0}, // S_ARACH_PLEX3
858 {SPR_APBX,32771,5,NULL,S_ARACH_PLEX5,0,0}, // S_ARACH_PLEX4
859 {SPR_APBX,32772,5,NULL,S_NULL,0,0}, // S_ARACH_PLEX5
860 {SPR_CYBR,0,10,A_Look,S_CYBER_STND2,0,0}, // S_CYBER_STND
861 {SPR_CYBR,1,10,A_Look,S_CYBER_STND,0,0}, // S_CYBER_STND2
862 {SPR_CYBR,0,3,A_Hoof,S_CYBER_RUN2,0,0}, // S_CYBER_RUN1
863 {SPR_CYBR,0,3,A_Chase,S_CYBER_RUN3,0,0}, // S_CYBER_RUN2
864 {SPR_CYBR,1,3,A_Chase,S_CYBER_RUN4,0,0}, // S_CYBER_RUN3
865 {SPR_CYBR,1,3,A_Chase,S_CYBER_RUN5,0,0}, // S_CYBER_RUN4
866 {SPR_CYBR,2,3,A_Chase,S_CYBER_RUN6,0,0}, // S_CYBER_RUN5
867 {SPR_CYBR,2,3,A_Chase,S_CYBER_RUN7,0,0}, // S_CYBER_RUN6
868 {SPR_CYBR,3,3,A_Metal,S_CYBER_RUN8,0,0}, // S_CYBER_RUN7
869 {SPR_CYBR,3,3,A_Chase,S_CYBER_RUN1,0,0}, // S_CYBER_RUN8
870 {SPR_CYBR,4,6,A_FaceTarget,S_CYBER_ATK2,0,0}, // S_CYBER_ATK1
871 {SPR_CYBR,5,12,A_CyberAttack,S_CYBER_ATK3,0,0}, // S_CYBER_ATK2
872 {SPR_CYBR,4,12,A_FaceTarget,S_CYBER_ATK4,0,0}, // S_CYBER_ATK3
873 {SPR_CYBR,5,12,A_CyberAttack,S_CYBER_ATK5,0,0}, // S_CYBER_ATK4
874 {SPR_CYBR,4,12,A_FaceTarget,S_CYBER_ATK6,0,0}, // S_CYBER_ATK5
875 {SPR_CYBR,5,12,A_CyberAttack,S_CYBER_RUN1,0,0}, // S_CYBER_ATK6
876 {SPR_CYBR,6,10,A_Pain,S_CYBER_RUN1,0,0}, // S_CYBER_PAIN
877 {SPR_CYBR,7,10,NULL,S_CYBER_DIE2,0,0}, // S_CYBER_DIE1
878 {SPR_CYBR,8,10,A_Scream,S_CYBER_DIE3,0,0}, // S_CYBER_DIE2
879 {SPR_CYBR,9,10,NULL,S_CYBER_DIE4,0,0}, // S_CYBER_DIE3
880 {SPR_CYBR,10,10,NULL,S_CYBER_DIE5,0,0}, // S_CYBER_DIE4
881 {SPR_CYBR,11,10,NULL,S_CYBER_DIE6,0,0}, // S_CYBER_DIE5
882 {SPR_CYBR,12,10,A_Fall,S_CYBER_DIE7,0,0}, // S_CYBER_DIE6
883 {SPR_CYBR,13,10,NULL,S_CYBER_DIE8,0,0}, // S_CYBER_DIE7
884 {SPR_CYBR,14,10,NULL,S_CYBER_DIE9,0,0}, // S_CYBER_DIE8
885 {SPR_CYBR,15,30,NULL,S_CYBER_DIE10,0,0}, // S_CYBER_DIE9
886 {SPR_CYBR,15,-1,A_BossDeath,S_NULL,0,0}, // S_CYBER_DIE10
887 {SPR_PAIN,0,10,A_Look,S_PAIN_STND,0,0}, // S_PAIN_STND
888 {SPR_PAIN,0,3,A_Chase,S_PAIN_RUN2,0,0}, // S_PAIN_RUN1
889 {SPR_PAIN,0,3,A_Chase,S_PAIN_RUN3,0,0}, // S_PAIN_RUN2
890 {SPR_PAIN,1,3,A_Chase,S_PAIN_RUN4,0,0}, // S_PAIN_RUN3
891 {SPR_PAIN,1,3,A_Chase,S_PAIN_RUN5,0,0}, // S_PAIN_RUN4
892 {SPR_PAIN,2,3,A_Chase,S_PAIN_RUN6,0,0}, // S_PAIN_RUN5
893 {SPR_PAIN,2,3,A_Chase,S_PAIN_RUN1,0,0}, // S_PAIN_RUN6
894 {SPR_PAIN,3,5,A_FaceTarget,S_PAIN_ATK2,0,0}, // S_PAIN_ATK1
895 {SPR_PAIN,4,5,A_FaceTarget,S_PAIN_ATK3,0,0}, // S_PAIN_ATK2
896 {SPR_PAIN,32773,5,A_FaceTarget,S_PAIN_ATK4,0,0}, // S_PAIN_ATK3
897 {SPR_PAIN,32773,0,A_PainAttack,S_PAIN_RUN1,0,0}, // S_PAIN_ATK4
898 {SPR_PAIN,6,6,NULL,S_PAIN_PAIN2,0,0}, // S_PAIN_PAIN
899 {SPR_PAIN,6,6,A_Pain,S_PAIN_RUN1,0,0}, // S_PAIN_PAIN2
900 {SPR_PAIN,32775,8,NULL,S_PAIN_DIE2,0,0}, // S_PAIN_DIE1
901 {SPR_PAIN,32776,8,A_Scream,S_PAIN_DIE3,0,0}, // S_PAIN_DIE2
902 {SPR_PAIN,32777,8,NULL,S_PAIN_DIE4,0,0}, // S_PAIN_DIE3
903 {SPR_PAIN,32778,8,NULL,S_PAIN_DIE5,0,0}, // S_PAIN_DIE4
904 {SPR_PAIN,32779,8,A_PainDie,S_PAIN_DIE6,0,0}, // S_PAIN_DIE5
905 {SPR_PAIN,32780,8,NULL,S_NULL,0,0}, // S_PAIN_DIE6
906 {SPR_PAIN,12,8,NULL,S_PAIN_RAISE2,0,0}, // S_PAIN_RAISE1
907 {SPR_PAIN,11,8,NULL,S_PAIN_RAISE3,0,0}, // S_PAIN_RAISE2
908 {SPR_PAIN,10,8,NULL,S_PAIN_RAISE4,0,0}, // S_PAIN_RAISE3
909 {SPR_PAIN,9,8,NULL,S_PAIN_RAISE5,0,0}, // S_PAIN_RAISE4
910 {SPR_PAIN,8,8,NULL,S_PAIN_RAISE6,0,0}, // S_PAIN_RAISE5
911 {SPR_PAIN,7,8,NULL,S_PAIN_RUN1,0,0}, // S_PAIN_RAISE6
912 {SPR_SSWV,0,10,A_Look,S_SSWV_STND2,0,0}, // S_SSWV_STND
913 {SPR_SSWV,1,10,A_Look,S_SSWV_STND,0,0}, // S_SSWV_STND2
914 {SPR_SSWV,0,3,A_Chase,S_SSWV_RUN2,0,0}, // S_SSWV_RUN1
915 {SPR_SSWV,0,3,A_Chase,S_SSWV_RUN3,0,0}, // S_SSWV_RUN2
916 {SPR_SSWV,1,3,A_Chase,S_SSWV_RUN4,0,0}, // S_SSWV_RUN3
917 {SPR_SSWV,1,3,A_Chase,S_SSWV_RUN5,0,0}, // S_SSWV_RUN4
918 {SPR_SSWV,2,3,A_Chase,S_SSWV_RUN6,0,0}, // S_SSWV_RUN5
919 {SPR_SSWV,2,3,A_Chase,S_SSWV_RUN7,0,0}, // S_SSWV_RUN6
920 {SPR_SSWV,3,3,A_Chase,S_SSWV_RUN8,0,0}, // S_SSWV_RUN7
921 {SPR_SSWV,3,3,A_Chase,S_SSWV_RUN1,0,0}, // S_SSWV_RUN8
922 {SPR_SSWV,4,10,A_FaceTarget,S_SSWV_ATK2,0,0}, // S_SSWV_ATK1
923 {SPR_SSWV,5,10,A_FaceTarget,S_SSWV_ATK3,0,0}, // S_SSWV_ATK2
924 {SPR_SSWV,32774,4,A_CPosAttack,S_SSWV_ATK4,0,0}, // S_SSWV_ATK3
925 {SPR_SSWV,5,6,A_FaceTarget,S_SSWV_ATK5,0,0}, // S_SSWV_ATK4
926 {SPR_SSWV,32774,4,A_CPosAttack,S_SSWV_ATK6,0,0}, // S_SSWV_ATK5
927 {SPR_SSWV,5,1,A_CPosRefire,S_SSWV_ATK2,0,0}, // S_SSWV_ATK6
928 {SPR_SSWV,7,3,NULL,S_SSWV_PAIN2,0,0}, // S_SSWV_PAIN
929 {SPR_SSWV,7,3,A_Pain,S_SSWV_RUN1,0,0}, // S_SSWV_PAIN2
930 {SPR_SSWV,8,5,NULL,S_SSWV_DIE2,0,0}, // S_SSWV_DIE1
931 {SPR_SSWV,9,5,A_Scream,S_SSWV_DIE3,0,0}, // S_SSWV_DIE2
932 {SPR_SSWV,10,5,A_Fall,S_SSWV_DIE4,0,0}, // S_SSWV_DIE3
933 {SPR_SSWV,11,5,NULL,S_SSWV_DIE5,0,0}, // S_SSWV_DIE4
934 {SPR_SSWV,12,-1,NULL,S_NULL,0,0}, // S_SSWV_DIE5
935 {SPR_SSWV,13,5,NULL,S_SSWV_XDIE2,0,0}, // S_SSWV_XDIE1
936 {SPR_SSWV,14,5,A_XScream,S_SSWV_XDIE3,0,0}, // S_SSWV_XDIE2
937 {SPR_SSWV,15,5,A_Fall,S_SSWV_XDIE4,0,0}, // S_SSWV_XDIE3
938 {SPR_SSWV,16,5,NULL,S_SSWV_XDIE5,0,0}, // S_SSWV_XDIE4
939 {SPR_SSWV,17,5,NULL,S_SSWV_XDIE6,0,0}, // S_SSWV_XDIE5
940 {SPR_SSWV,18,5,NULL,S_SSWV_XDIE7,0,0}, // S_SSWV_XDIE6
941 {SPR_SSWV,19,5,NULL,S_SSWV_XDIE8,0,0}, // S_SSWV_XDIE7
942 {SPR_SSWV,20,5,NULL,S_SSWV_XDIE9,0,0}, // S_SSWV_XDIE8
943 {SPR_SSWV,21,-1,NULL,S_NULL,0,0}, // S_SSWV_XDIE9
944 {SPR_SSWV,12,5,NULL,S_SSWV_RAISE2,0,0}, // S_SSWV_RAISE1
945 {SPR_SSWV,11,5,NULL,S_SSWV_RAISE3,0,0}, // S_SSWV_RAISE2
946 {SPR_SSWV,10,5,NULL,S_SSWV_RAISE4,0,0}, // S_SSWV_RAISE3
947 {SPR_SSWV,9,5,NULL,S_SSWV_RAISE5,0,0}, // S_SSWV_RAISE4
948 {SPR_SSWV,8,5,NULL,S_SSWV_RUN1,0,0}, // S_SSWV_RAISE5
949 {SPR_KEEN,0,-1,NULL,S_KEENSTND,0,0}, // S_KEENSTND
950 {SPR_KEEN,0,6,NULL,S_COMMKEEN2,0,0}, // S_COMMKEEN
951 {SPR_KEEN,1,6,NULL,S_COMMKEEN3,0,0}, // S_COMMKEEN2
952 {SPR_KEEN,2,6,A_Scream,S_COMMKEEN4,0,0}, // S_COMMKEEN3
953 {SPR_KEEN,3,6,NULL,S_COMMKEEN5,0,0}, // S_COMMKEEN4
954 {SPR_KEEN,4,6,NULL,S_COMMKEEN6,0,0}, // S_COMMKEEN5
955 {SPR_KEEN,5,6,NULL,S_COMMKEEN7,0,0}, // S_COMMKEEN6
956 {SPR_KEEN,6,6,NULL,S_COMMKEEN8,0,0}, // S_COMMKEEN7
957 {SPR_KEEN,7,6,NULL,S_COMMKEEN9,0,0}, // S_COMMKEEN8
958 {SPR_KEEN,8,6,NULL,S_COMMKEEN10,0,0}, // S_COMMKEEN9
959 {SPR_KEEN,9,6,NULL,S_COMMKEEN11,0,0}, // S_COMMKEEN10
960 {SPR_KEEN,10,6,A_KeenDie,S_COMMKEEN12,0,0},// S_COMMKEEN11
961 {SPR_KEEN,11,-1,NULL,S_NULL,0,0}, // S_COMMKEEN12
962 {SPR_KEEN,12,4,NULL,S_KEENPAIN2,0,0}, // S_KEENPAIN
963 {SPR_KEEN,12,8,A_Pain,S_KEENSTND,0,0}, // S_KEENPAIN2
964 {SPR_BBRN,0,-1,NULL,S_NULL,0,0}, // S_BRAIN
965 {SPR_BBRN,1,36,A_BrainPain,S_BRAIN,0,0}, // S_BRAIN_PAIN
966 {SPR_BBRN,0,100,A_BrainScream,S_BRAIN_DIE2,0,0}, // S_BRAIN_DIE1
967 {SPR_BBRN,0,10,NULL,S_BRAIN_DIE3,0,0}, // S_BRAIN_DIE2
968 {SPR_BBRN,0,10,NULL,S_BRAIN_DIE4,0,0}, // S_BRAIN_DIE3
969 {SPR_BBRN,0,-1,A_BrainDie,S_NULL,0,0}, // S_BRAIN_DIE4
970 {SPR_SSWV,0,10,A_Look,S_BRAINEYE,0,0}, // S_BRAINEYE
971 {SPR_SSWV,0,181,A_BrainAwake,S_BRAINEYE1,0,0}, // S_BRAINEYESEE
972 {SPR_SSWV,0,150,A_BrainSpit,S_BRAINEYE1,0,0}, // S_BRAINEYE1
973 {SPR_BOSF,32768,3,A_SpawnSound,S_SPAWN2,0,0}, // S_SPAWN1
974 {SPR_BOSF,32769,3,A_SpawnFly,S_SPAWN3,0,0}, // S_SPAWN2
975 {SPR_BOSF,32770,3,A_SpawnFly,S_SPAWN4,0,0}, // S_SPAWN3
976 {SPR_BOSF,32771,3,A_SpawnFly,S_SPAWN1,0,0}, // S_SPAWN4
977 {SPR_FIRE,32768,4,A_Fire,S_SPAWNFIRE2,0,0}, // S_SPAWNFIRE1
978 {SPR_FIRE,32769,4,A_Fire,S_SPAWNFIRE3,0,0}, // S_SPAWNFIRE2
979 {SPR_FIRE,32770,4,A_Fire,S_SPAWNFIRE4,0,0}, // S_SPAWNFIRE3
980 {SPR_FIRE,32771,4,A_Fire,S_SPAWNFIRE5,0,0}, // S_SPAWNFIRE4
981 {SPR_FIRE,32772,4,A_Fire,S_SPAWNFIRE6,0,0}, // S_SPAWNFIRE5
982 {SPR_FIRE,32773,4,A_Fire,S_SPAWNFIRE7,0,0}, // S_SPAWNFIRE6
983 {SPR_FIRE,32774,4,A_Fire,S_SPAWNFIRE8,0,0}, // S_SPAWNFIRE7
984 {SPR_FIRE,32775,4,A_Fire,S_NULL,0,0}, // S_SPAWNFIRE8
985 {SPR_MISL,32769,10,NULL,S_BRAINEXPLODE2,0,0}, // S_BRAINEXPLODE1
986 {SPR_MISL,32770,10,NULL,S_BRAINEXPLODE3,0,0}, // S_BRAINEXPLODE2
987 {SPR_MISL,32771,10,A_BrainExplode,S_NULL,0,0}, // S_BRAINEXPLODE3
988 {SPR_ARM1,0,6,NULL,S_ARM1A,0,0}, // S_ARM1
989 {SPR_ARM1,32769,7,NULL,S_ARM1,0,0}, // S_ARM1A
990 {SPR_ARM2,0,6,NULL,S_ARM2A,0,0}, // S_ARM2
991 {SPR_ARM2,32769,6,NULL,S_ARM2,0,0}, // S_ARM2A
992 {SPR_BAR1,0,6,NULL,S_BAR2,0,0}, // S_BAR1
993 {SPR_BAR1,1,6,NULL,S_BAR1,0,0}, // S_BAR2
994 {SPR_BEXP,32768,5,NULL,S_BEXP2,0,0}, // S_BEXP
995 {SPR_BEXP,32769,5,A_Scream,S_BEXP3,0,0}, // S_BEXP2
996 {SPR_BEXP,32770,5,NULL,S_BEXP4,0,0}, // S_BEXP3
997 {SPR_BEXP,32771,10,A_Explode,S_BEXP5,0,0}, // S_BEXP4
998 {SPR_BEXP,32772,10,NULL,S_NULL,0,0}, // S_BEXP5
999 {SPR_FCAN,32768,4,NULL,S_BBAR2,0,0}, // S_BBAR1
1000 {SPR_FCAN,32769,4,NULL,S_BBAR3,0,0}, // S_BBAR2
1001 {SPR_FCAN,32770,4,NULL,S_BBAR1,0,0}, // S_BBAR3
1002 {SPR_BON1,0,6,NULL,S_BON1A,0,0}, // S_BON1
1003 {SPR_BON1,1,6,NULL,S_BON1B,0,0}, // S_BON1A
1004 {SPR_BON1,2,6,NULL,S_BON1C,0,0}, // S_BON1B
1005 {SPR_BON1,3,6,NULL,S_BON1D,0,0}, // S_BON1C
1006 {SPR_BON1,2,6,NULL,S_BON1E,0,0}, // S_BON1D
1007 {SPR_BON1,1,6,NULL,S_BON1,0,0}, // S_BON1E
1008 {SPR_BON2,0,6,NULL,S_BON2A,0,0}, // S_BON2
1009 {SPR_BON2,1,6,NULL,S_BON2B,0,0}, // S_BON2A
1010 {SPR_BON2,2,6,NULL,S_BON2C,0,0}, // S_BON2B
1011 {SPR_BON2,3,6,NULL,S_BON2D,0,0}, // S_BON2C
1012 {SPR_BON2,2,6,NULL,S_BON2E,0,0}, // S_BON2D
1013 {SPR_BON2,1,6,NULL,S_BON2,0,0}, // S_BON2E
1014 {SPR_BKEY,0,10,NULL,S_BKEY2,0,0}, // S_BKEY
1015 {SPR_BKEY,32769,10,NULL,S_BKEY,0,0}, // S_BKEY2
1016 {SPR_RKEY,0,10,NULL,S_RKEY2,0,0}, // S_RKEY
1017 {SPR_RKEY,32769,10,NULL,S_RKEY,0,0}, // S_RKEY2
1018 {SPR_YKEY,0,10,NULL,S_YKEY2,0,0}, // S_YKEY
1019 {SPR_YKEY,32769,10,NULL,S_YKEY,0,0}, // S_YKEY2
1020 {SPR_BSKU,0,10,NULL,S_BSKULL2,0,0}, // S_BSKULL
1021 {SPR_BSKU,32769,10,NULL,S_BSKULL,0,0}, // S_BSKULL2
1022 {SPR_RSKU,0,10,NULL,S_RSKULL2,0,0}, // S_RSKULL
1023 {SPR_RSKU,32769,10,NULL,S_RSKULL,0,0}, // S_RSKULL2
1024 {SPR_YSKU,0,10,NULL,S_YSKULL2,0,0}, // S_YSKULL
1025 {SPR_YSKU,32769,10,NULL,S_YSKULL,0,0}, // S_YSKULL2
1026 {SPR_STIM,0,-1,NULL,S_NULL,0,0}, // S_STIM
1027 {SPR_MEDI,0,-1,NULL,S_NULL,0,0}, // S_MEDI
1028 {SPR_SOUL,32768,6,NULL,S_SOUL2,0,0}, // S_SOUL
1029 {SPR_SOUL,32769,6,NULL,S_SOUL3,0,0}, // S_SOUL2
1030 {SPR_SOUL,32770,6,NULL,S_SOUL4,0,0}, // S_SOUL3
1031 {SPR_SOUL,32771,6,NULL,S_SOUL5,0,0}, // S_SOUL4
1032 {SPR_SOUL,32770,6,NULL,S_SOUL6,0,0}, // S_SOUL5
1033 {SPR_SOUL,32769,6,NULL,S_SOUL,0,0}, // S_SOUL6
1034 {SPR_PINV,32768,6,NULL,S_PINV2,0,0}, // S_PINV
1035 {SPR_PINV,32769,6,NULL,S_PINV3,0,0}, // S_PINV2
1036 {SPR_PINV,32770,6,NULL,S_PINV4,0,0}, // S_PINV3
1037 {SPR_PINV,32771,6,NULL,S_PINV,0,0}, // S_PINV4
1038 {SPR_PSTR,32768,-1,NULL,S_NULL,0,0}, // S_PSTR
1039 {SPR_PINS,32768,6,NULL,S_PINS2,0,0}, // S_PINS
1040 {SPR_PINS,32769,6,NULL,S_PINS3,0,0}, // S_PINS2
1041 {SPR_PINS,32770,6,NULL,S_PINS4,0,0}, // S_PINS3
1042 {SPR_PINS,32771,6,NULL,S_PINS,0,0}, // S_PINS4
1043 {SPR_MEGA,32768,6,NULL,S_MEGA2,0,0}, // S_MEGA
1044 {SPR_MEGA,32769,6,NULL,S_MEGA3,0,0}, // S_MEGA2
1045 {SPR_MEGA,32770,6,NULL,S_MEGA4,0,0}, // S_MEGA3
1046 {SPR_MEGA,32771,6,NULL,S_MEGA,0,0}, // S_MEGA4
1047 {SPR_SUIT,32768,-1,NULL,S_NULL,0,0}, // S_SUIT
1048 {SPR_PMAP,32768,6,NULL,S_PMAP2,0,0}, // S_PMAP
1049 {SPR_PMAP,32769,6,NULL,S_PMAP3,0,0}, // S_PMAP2
1050 {SPR_PMAP,32770,6,NULL,S_PMAP4,0,0}, // S_PMAP3
1051 {SPR_PMAP,32771,6,NULL,S_PMAP5,0,0}, // S_PMAP4
1052 {SPR_PMAP,32770,6,NULL,S_PMAP6,0,0}, // S_PMAP5
1053 {SPR_PMAP,32769,6,NULL,S_PMAP,0,0}, // S_PMAP6
1054 {SPR_PVIS,32768,6,NULL,S_PVIS2,0,0}, // S_PVIS
1055 {SPR_PVIS,1,6,NULL,S_PVIS,0,0}, // S_PVIS2
1056 {SPR_CLIP,0,-1,NULL,S_NULL,0,0}, // S_CLIP
1057 {SPR_AMMO,0,-1,NULL,S_NULL,0,0}, // S_AMMO
1058 {SPR_ROCK,0,-1,NULL,S_NULL,0,0}, // S_ROCK
1059 {SPR_BROK,0,-1,NULL,S_NULL,0,0}, // S_BROK
1060 {SPR_CELL,0,-1,NULL,S_NULL,0,0}, // S_CELL
1061 {SPR_CELP,0,-1,NULL,S_NULL,0,0}, // S_CELP
1062 {SPR_SHEL,0,-1,NULL,S_NULL,0,0}, // S_SHEL
1063 {SPR_SBOX,0,-1,NULL,S_NULL,0,0}, // S_SBOX
1064 {SPR_BPAK,0,-1,NULL,S_NULL,0,0}, // S_BPAK
1065 {SPR_BFUG,0,-1,NULL,S_NULL,0,0}, // S_BFUG
1066 {SPR_MGUN,0,-1,NULL,S_NULL,0,0}, // S_MGUN
1067 {SPR_CSAW,0,-1,NULL,S_NULL,0,0}, // S_CSAW
1068 {SPR_LAUN,0,-1,NULL,S_NULL,0,0}, // S_LAUN
1069 {SPR_PLAS,0,-1,NULL,S_NULL,0,0}, // S_PLAS
1070 {SPR_SHOT,0,-1,NULL,S_NULL,0,0}, // S_SHOT
1071 {SPR_SGN2,0,-1,NULL,S_NULL,0,0}, // S_SHOT2
1072 {SPR_COLU,32768,-1,NULL,S_NULL,0,0}, // S_COLU
1073 {SPR_SMT2,0,-1,NULL,S_NULL,0,0}, // S_STALAG
1074 {SPR_GOR1,0,10,NULL,S_BLOODYTWITCH2,0,0}, // S_BLOODYTWITCH
1075 {SPR_GOR1,1,15,NULL,S_BLOODYTWITCH3,0,0}, // S_BLOODYTWITCH2
1076 {SPR_GOR1,2,8,NULL,S_BLOODYTWITCH4,0,0}, // S_BLOODYTWITCH3
1077 {SPR_GOR1,1,6,NULL,S_BLOODYTWITCH,0,0}, // S_BLOODYTWITCH4
1078 {SPR_PLAY,13,-1,NULL,S_NULL,0,0}, // S_DEADTORSO
1079 {SPR_PLAY,18,-1,NULL,S_NULL,0,0}, // S_DEADBOTTOM
1080 {SPR_POL2,0,-1,NULL,S_NULL,0,0}, // S_HEADSONSTICK
1081 {SPR_POL5,0,-1,NULL,S_NULL,0,0}, // S_GIBS
1082 {SPR_POL4,0,-1,NULL,S_NULL,0,0}, // S_HEADONASTICK
1083 {SPR_POL3,32768,6,NULL,S_HEADCANDLES2,0,0}, // S_HEADCANDLES
1084 {SPR_POL3,32769,6,NULL,S_HEADCANDLES,0,0}, // S_HEADCANDLES2
1085 {SPR_POL1,0,-1,NULL,S_NULL,0,0}, // S_DEADSTICK
1086 {SPR_POL6,0,6,NULL,S_LIVESTICK2,0,0}, // S_LIVESTICK
1087 {SPR_POL6,1,8,NULL,S_LIVESTICK,0,0}, // S_LIVESTICK2
1088 {SPR_GOR2,0,-1,NULL,S_NULL,0,0}, // S_MEAT2
1089 {SPR_GOR3,0,-1,NULL,S_NULL,0,0}, // S_MEAT3
1090 {SPR_GOR4,0,-1,NULL,S_NULL,0,0}, // S_MEAT4
1091 {SPR_GOR5,0,-1,NULL,S_NULL,0,0}, // S_MEAT5
1092 {SPR_SMIT,0,-1,NULL,S_NULL,0,0}, // S_STALAGTITE
1093 {SPR_COL1,0,-1,NULL,S_NULL,0,0}, // S_TALLGRNCOL
1094 {SPR_COL2,0,-1,NULL,S_NULL,0,0}, // S_SHRTGRNCOL
1095 {SPR_COL3,0,-1,NULL,S_NULL,0,0}, // S_TALLREDCOL
1096 {SPR_COL4,0,-1,NULL,S_NULL,0,0}, // S_SHRTREDCOL
1097 {SPR_CAND,32768,-1,NULL,S_NULL,0,0}, // S_CANDLESTIK
1098 {SPR_CBRA,32768,-1,NULL,S_NULL,0,0}, // S_CANDELABRA
1099 {SPR_COL6,0,-1,NULL,S_NULL,0,0}, // S_SKULLCOL
1100 {SPR_TRE1,0,-1,NULL,S_NULL,0,0}, // S_TORCHTREE
1101 {SPR_TRE2,0,-1,NULL,S_NULL,0,0}, // S_BIGTREE
1102 {SPR_ELEC,0,-1,NULL,S_NULL,0,0}, // S_TECHPILLAR
1103 {SPR_CEYE,32768,6,NULL,S_EVILEYE2,0,0}, // S_EVILEYE
1104 {SPR_CEYE,32769,6,NULL,S_EVILEYE3,0,0}, // S_EVILEYE2
1105 {SPR_CEYE,32770,6,NULL,S_EVILEYE4,0,0}, // S_EVILEYE3
1106 {SPR_CEYE,32769,6,NULL,S_EVILEYE,0,0}, // S_EVILEYE4
1107 {SPR_FSKU,32768,6,NULL,S_FLOATSKULL2,0,0}, // S_FLOATSKULL
1108 {SPR_FSKU,32769,6,NULL,S_FLOATSKULL3,0,0}, // S_FLOATSKULL2
1109 {SPR_FSKU,32770,6,NULL,S_FLOATSKULL,0,0}, // S_FLOATSKULL3
1110 {SPR_COL5,0,14,NULL,S_HEARTCOL2,0,0}, // S_HEARTCOL
1111 {SPR_COL5,1,14,NULL,S_HEARTCOL,0,0}, // S_HEARTCOL2
1112 {SPR_TBLU,32768,4,NULL,S_BLUETORCH2,0,0}, // S_BLUETORCH
1113 {SPR_TBLU,32769,4,NULL,S_BLUETORCH3,0,0}, // S_BLUETORCH2
1114 {SPR_TBLU,32770,4,NULL,S_BLUETORCH4,0,0}, // S_BLUETORCH3
1115 {SPR_TBLU,32771,4,NULL,S_BLUETORCH,0,0}, // S_BLUETORCH4
1116 {SPR_TGRN,32768,4,NULL,S_GREENTORCH2,0,0}, // S_GREENTORCH
1117 {SPR_TGRN,32769,4,NULL,S_GREENTORCH3,0,0}, // S_GREENTORCH2
1118 {SPR_TGRN,32770,4,NULL,S_GREENTORCH4,0,0}, // S_GREENTORCH3
1119 {SPR_TGRN,32771,4,NULL,S_GREENTORCH,0,0}, // S_GREENTORCH4
1120 {SPR_TRED,32768,4,NULL,S_REDTORCH2,0,0}, // S_REDTORCH
1121 {SPR_TRED,32769,4,NULL,S_REDTORCH3,0,0}, // S_REDTORCH2
1122 {SPR_TRED,32770,4,NULL,S_REDTORCH4,0,0}, // S_REDTORCH3
1123 {SPR_TRED,32771,4,NULL,S_REDTORCH,0,0}, // S_REDTORCH4
1124 {SPR_SMBT,32768,4,NULL,S_BTORCHSHRT2,0,0}, // S_BTORCHSHRT
1125 {SPR_SMBT,32769,4,NULL,S_BTORCHSHRT3,0,0}, // S_BTORCHSHRT2
1126 {SPR_SMBT,32770,4,NULL,S_BTORCHSHRT4,0,0}, // S_BTORCHSHRT3
1127 {SPR_SMBT,32771,4,NULL,S_BTORCHSHRT,0,0}, // S_BTORCHSHRT4
1128 {SPR_SMGT,32768,4,NULL,S_GTORCHSHRT2,0,0}, // S_GTORCHSHRT
1129 {SPR_SMGT,32769,4,NULL,S_GTORCHSHRT3,0,0}, // S_GTORCHSHRT2
1130 {SPR_SMGT,32770,4,NULL,S_GTORCHSHRT4,0,0}, // S_GTORCHSHRT3
1131 {SPR_SMGT,32771,4,NULL,S_GTORCHSHRT,0,0}, // S_GTORCHSHRT4
1132 {SPR_SMRT,32768,4,NULL,S_RTORCHSHRT2,0,0}, // S_RTORCHSHRT
1133 {SPR_SMRT,32769,4,NULL,S_RTORCHSHRT3,0,0}, // S_RTORCHSHRT2
1134 {SPR_SMRT,32770,4,NULL,S_RTORCHSHRT4,0,0}, // S_RTORCHSHRT3
1135 {SPR_SMRT,32771,4,NULL,S_RTORCHSHRT,0,0}, // S_RTORCHSHRT4
1136 {SPR_HDB1,0,-1,NULL,S_NULL,0,0}, // S_HANGNOGUTS
1137 {SPR_HDB2,0,-1,NULL,S_NULL,0,0}, // S_HANGBNOBRAIN
1138 {SPR_HDB3,0,-1,NULL,S_NULL,0,0}, // S_HANGTLOOKDN
1139 {SPR_HDB4,0,-1,NULL,S_NULL,0,0}, // S_HANGTSKULL
1140 {SPR_HDB5,0,-1,NULL,S_NULL,0,0}, // S_HANGTLOOKUP
1141 {SPR_HDB6,0,-1,NULL,S_NULL,0,0}, // S_HANGTNOBRAIN
1142 {SPR_POB1,0,-1,NULL,S_NULL,0,0}, // S_COLONGIBS
1143 {SPR_POB2,0,-1,NULL,S_NULL,0,0}, // S_SMALLPOOL
1144 {SPR_BRS1,0,-1,NULL,S_NULL,0,0}, // S_BRAINSTEM
1145 {SPR_TLMP,32768,4,NULL,S_TECHLAMP2,0,0}, // S_TECHLAMP
1146 {SPR_TLMP,32769,4,NULL,S_TECHLAMP3,0,0}, // S_TECHLAMP2
1147 {SPR_TLMP,32770,4,NULL,S_TECHLAMP4,0,0}, // S_TECHLAMP3
1148 {SPR_TLMP,32771,4,NULL,S_TECHLAMP,0,0}, // S_TECHLAMP4
1149 {SPR_TLP2,32768,4,NULL,S_TECH2LAMP2,0,0}, // S_TECH2LAMP
1150 {SPR_TLP2,32769,4,NULL,S_TECH2LAMP3,0,0}, // S_TECH2LAMP2
1151 {SPR_TLP2,32770,4,NULL,S_TECH2LAMP4,0,0}, // S_TECH2LAMP3
1152 {SPR_TLP2,32771,4,NULL,S_TECH2LAMP,0,0}, // S_TECH2LAMP4
1153 {SPR_TNT1,0,-1,NULL,S_TNT1,0,0}, // S_TNT1 // phares 3/8/98
1154
1155 // killough 8/9/98: grenade
1156 {SPR_MISL,32768,1000,A_Die,S_GRENADE,0,0}, // S_GRENADE
1157
1158 // killough 8/10/98: variable damage explosion
1159 {SPR_MISL,32769,4,A_Scream,S_DETONATE2,0,0}, // S_DETONATE
1160 {SPR_MISL,32770,6,A_Detonate,S_DETONATE3,0,0}, // S_DETONATE2
1161 {SPR_MISL,32771,10,NULL,S_NULL,0,0}, // S_DETONATE3
1162
1163#ifdef DOGS
1164 // killough 7/19/98: Marine's best friend :)
1165 {SPR_DOGS,0,10,A_Look,S_DOGS_STND2,0,0}, // S_DOGS_STND
1166 {SPR_DOGS,1,10,A_Look,S_DOGS_STND,0,0}, // S_DOGS_STND2
1167 {SPR_DOGS,0,2,A_Chase,S_DOGS_RUN2,0,0}, // S_DOGS_RUN1
1168 {SPR_DOGS,0,2,A_Chase,S_DOGS_RUN3,0,0}, // S_DOGS_RUN2
1169 {SPR_DOGS,1,2,A_Chase,S_DOGS_RUN4,0,0}, // S_DOGS_RUN3
1170 {SPR_DOGS,1,2,A_Chase,S_DOGS_RUN5,0,0}, // S_DOGS_RUN4
1171 {SPR_DOGS,2,2,A_Chase,S_DOGS_RUN6,0,0}, // S_DOGS_RUN5
1172 {SPR_DOGS,2,2,A_Chase,S_DOGS_RUN7,0,0}, // S_DOGS_RUN6
1173 {SPR_DOGS,3,2,A_Chase,S_DOGS_RUN8,0,0}, // S_DOGS_RUN7
1174 {SPR_DOGS,3,2,A_Chase,S_DOGS_RUN1,0,0}, // S_DOGS_RUN8
1175 {SPR_DOGS,4,8,A_FaceTarget,S_DOGS_ATK2,0,0}, // S_DOGS_ATK1
1176 {SPR_DOGS,5,8,A_FaceTarget,S_DOGS_ATK3,0,0}, // S_DOGS_ATK2
1177 {SPR_DOGS,6,8,A_SargAttack,S_DOGS_RUN1,0,0}, // S_DOGS_ATK3
1178 {SPR_DOGS,7,2,NULL,S_DOGS_PAIN2,0,0}, // S_DOGS_PAIN
1179 {SPR_DOGS,7,2,A_Pain,S_DOGS_RUN1,0,0}, // S_DOGS_PAIN2
1180 {SPR_DOGS,8,8,NULL,S_DOGS_DIE2,0,0}, // S_DOGS_DIE1
1181 {SPR_DOGS,9,8,A_Scream,S_DOGS_DIE3,0,0}, // S_DOGS_DIE2
1182 {SPR_DOGS,10,4,NULL,S_DOGS_DIE4,0,0}, // S_DOGS_DIE3
1183 {SPR_DOGS,11,4,A_Fall,S_DOGS_DIE5,0,0}, // S_DOGS_DIE4
1184 {SPR_DOGS,12,4,NULL,S_DOGS_DIE6,0,0}, // S_DOGS_DIE5
1185 {SPR_DOGS,13,-1,NULL,S_NULL,0,0}, // S_DOGS_DIE6
1186 {SPR_DOGS,13,5,NULL,S_DOGS_RAISE2,0,0}, // S_DOGS_RAISE1
1187 {SPR_DOGS,12,5,NULL,S_DOGS_RAISE3,0,0}, // S_DOGS_RAISE2
1188 {SPR_DOGS,11,5,NULL,S_DOGS_RAISE4,0,0}, // S_DOGS_RAISE3
1189 {SPR_DOGS,10,5,NULL,S_DOGS_RAISE5,0,0}, // S_DOGS_RAISE4
1190 {SPR_DOGS,9,5,NULL,S_DOGS_RAISE6,0,0}, // S_DOGS_RAISE5
1191 {SPR_DOGS,8,5,NULL,S_DOGS_RUN1,0,0}, // S_DOGS_RAISE6
1192#endif
1193
1194 // killough 10/98: mushroom effect
1195 {SPR_MISL,32769,8,A_Mushroom,S_EXPLODE2,0,0}, // S_MUSHROOM
1196 };
1197
1198// ********************************************************************
1199// Object "Thing" definitions
1200// ********************************************************************
1201// Now we get to the actual objects and their characteristics. If
1202// you've seen Dehacked, much of this is where the Bits are set,
1203// commented below as "flags", as well as where you wire in which
1204// frames are the beginning frames for near and far attack, death,
1205// and such. Sounds are hooked in here too, as well as how much
1206// mass, speed and so forth a Thing has. Everything you ever wanted
1207// to know...
1208//
1209// Like all this other stuff, the MT_* entries are enumerated in info.h
1210//
1211// Note that these are all just indices of the elements involved, and
1212// not real pointers to them. For example, the player's death sequence
1213// is S_PLAY_DIE1, which just evaluates to the index in the states[]
1214// array above, which actually knows what happens then and what the
1215// sprite looks like, if it makes noise or not, etc.
1216//
1217// Additional comments about each of the entries are located in info.h
1218// next to the mobjinfo_t structure definition.
1219//
1220// This goes on for the next 3000+ lines...
1221
1222mobjinfo_t mobjinfo[NUMMOBJTYPES] = {
1223 { // MT_PLAYER
1224 -1, // doomednum
1225 S_PLAY, // spawnstate
1226 100, // spawnhealth
1227 S_PLAY_RUN1, // seestate
1228 sfx_None, // seesound
1229 0, // reactiontime
1230 sfx_None, // attacksound
1231 S_PLAY_PAIN, // painstate
1232 255, // painchance
1233 sfx_plpain, // painsound
1234 S_NULL, // meleestate
1235 S_PLAY_ATK1, // missilestate
1236 S_PLAY_DIE1, // deathstate
1237 S_PLAY_XDIE1, // xdeathstate
1238 sfx_pldeth, // deathsound
1239 0, // speed
1240 16*FRACUNIT, // radius
1241 56*FRACUNIT, // height
1242 100, // mass
1243 0, // damage
1244 sfx_None, // activesound
1245 MF_SOLID|MF_SHOOTABLE|MF_DROPOFF|MF_PICKUP|MF_NOTDMATCH, // flags
1246 S_NULL // raisestate
1247 },
1248
1249 { // MT_POSSESSED
1250 3004, // doomednum
1251 S_POSS_STND, // spawnstate
1252 20, // spawnhealth
1253 S_POSS_RUN1, // seestate
1254 sfx_posit1, // seesound
1255 8, // reactiontime
1256 sfx_pistol, // attacksound
1257 S_POSS_PAIN, // painstate
1258 200, // painchance
1259 sfx_popain, // painsound
1260 0, // meleestate
1261 S_POSS_ATK1, // missilestate
1262 S_POSS_DIE1, // deathstate
1263 S_POSS_XDIE1, // xdeathstate
1264 sfx_podth1, // deathsound
1265 8, // speed
1266 20*FRACUNIT, // radius
1267 56*FRACUNIT, // height
1268 100, // mass
1269 0, // damage
1270 sfx_posact, // activesound
1271 MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL, // flags
1272 S_POSS_RAISE1 // raisestate
1273 },
1274
1275 { // MT_SHOTGUY
1276 9, // doomednum
1277 S_SPOS_STND, // spawnstate
1278 30, // spawnhealth
1279 S_SPOS_RUN1, // seestate
1280 sfx_posit2, // seesound
1281 8, // reactiontime
1282 0, // attacksound
1283 S_SPOS_PAIN, // painstate
1284 170, // painchance
1285 sfx_popain, // painsound
1286 0, // meleestate
1287 S_SPOS_ATK1, // missilestate
1288 S_SPOS_DIE1, // deathstate
1289 S_SPOS_XDIE1, // xdeathstate
1290 sfx_podth2, // deathsound
1291 8, // speed
1292 20*FRACUNIT, // radius
1293 56*FRACUNIT, // height
1294 100, // mass
1295 0, // damage
1296 sfx_posact, // activesound
1297 MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL, // flags
1298 S_SPOS_RAISE1 // raisestate
1299 },
1300
1301 { // MT_VILE
1302 64, // doomednum
1303 S_VILE_STND, // spawnstate
1304 700, // spawnhealth
1305 S_VILE_RUN1, // seestate
1306 sfx_vilsit, // seesound
1307 8, // reactiontime
1308 0, // attacksound
1309 S_VILE_PAIN, // painstate
1310 10, // painchance
1311 sfx_vipain, // painsound
1312 0, // meleestate
1313 S_VILE_ATK1, // missilestate
1314 S_VILE_DIE1, // deathstate
1315 S_NULL, // xdeathstate
1316 sfx_vildth, // deathsound
1317 15, // speed
1318 20*FRACUNIT, // radius
1319 56*FRACUNIT, // height
1320 500, // mass
1321 0, // damage
1322 sfx_vilact, // activesound
1323 MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL, // flags
1324 S_NULL // raisestate
1325 },
1326
1327 { // MT_FIRE
1328 -1, // doomednum
1329 S_FIRE1, // spawnstate
1330 1000, // spawnhealth
1331 S_NULL, // seestate
1332 sfx_None, // seesound
1333 8, // reactiontime
1334 sfx_None, // attacksound
1335 S_NULL, // painstate
1336 0, // painchance
1337 sfx_None, // painsound
1338 S_NULL, // meleestate
1339 S_NULL, // missilestate
1340 S_NULL, // deathstate
1341 S_NULL, // xdeathstate
1342 sfx_None, // deathsound
1343 0, // speed
1344 20*FRACUNIT, // radius
1345 16*FRACUNIT, // height
1346 100, // mass
1347 0, // damage
1348 sfx_None, // activesound
1349 MF_NOBLOCKMAP|MF_NOGRAVITY|MF_TRANSLUCENT, // flags // killough 2/21/98
1350 S_NULL // raisestate
1351 },
1352
1353 { // MT_UNDEAD
1354 66, // doomednum
1355 S_SKEL_STND, // spawnstate
1356 300, // spawnhealth
1357 S_SKEL_RUN1, // seestate
1358 sfx_skesit, // seesound
1359 8, // reactiontime
1360 0, // attacksound
1361 S_SKEL_PAIN, // painstate
1362 100, // painchance
1363 sfx_popain, // painsound
1364 S_SKEL_FIST1, // meleestate
1365 S_SKEL_MISS1, // missilestate
1366 S_SKEL_DIE1, // deathstate
1367 S_NULL, // xdeathstate
1368 sfx_skedth, // deathsound
1369 10, // speed
1370 20*FRACUNIT, // radius
1371 56*FRACUNIT, // height
1372 500, // mass
1373 0, // damage
1374 sfx_skeact, // activesound
1375 MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL, // flags
1376 S_SKEL_RAISE1 // raisestate
1377 },
1378
1379 { // MT_TRACER
1380 -1, // doomednum
1381 S_TRACER, // spawnstate
1382 1000, // spawnhealth
1383 S_NULL, // seestate
1384 sfx_skeatk, // seesound
1385 8, // reactiontime
1386 sfx_None, // attacksound
1387 S_NULL, // painstate
1388 0, // painchance
1389 sfx_None, // painsound
1390 S_NULL, // meleestate
1391 S_NULL, // missilestate
1392 S_TRACEEXP1, // deathstate
1393 S_NULL, // xdeathstate
1394 sfx_barexp, // deathsound
1395 10*FRACUNIT, // speed
1396 11*FRACUNIT, // radius
1397 8*FRACUNIT, // height
1398 100, // mass
1399 10, // damage
1400 sfx_None, // activesound
1401 MF_NOBLOCKMAP|MF_MISSILE|MF_DROPOFF|MF_NOGRAVITY, // flags
1402 S_NULL // raisestate
1403 },
1404
1405 { // MT_SMOKE
1406 -1, // doomednum
1407 S_SMOKE1, // spawnstate
1408 1000, // spawnhealth
1409 S_NULL, // seestate
1410 sfx_None, // seesound
1411 8, // reactiontime
1412 sfx_None, // attacksound
1413 S_NULL, // painstate
1414 0, // painchance
1415 sfx_None, // painsound
1416 S_NULL, // meleestate
1417 S_NULL, // missilestate
1418 S_NULL, // deathstate
1419 S_NULL, // xdeathstate
1420 sfx_None, // deathsound
1421 0, // speed
1422 20*FRACUNIT, // radius
1423 16*FRACUNIT, // height
1424 100, // mass
1425 0, // damage
1426 sfx_None, // activesound
1427 MF_NOBLOCKMAP|MF_NOGRAVITY|MF_TRANSLUCENT, // flags // phares
1428 S_NULL // raisestate
1429 },
1430
1431 { // MT_FATSO
1432 67, // doomednum
1433 S_FATT_STND, // spawnstate
1434 600, // spawnhealth
1435 S_FATT_RUN1, // seestate
1436 sfx_mansit, // seesound
1437 8, // reactiontime
1438 0, // attacksound
1439 S_FATT_PAIN, // painstate
1440 80, // painchance
1441 sfx_mnpain, // painsound
1442 0, // meleestate
1443 S_FATT_ATK1, // missilestate
1444 S_FATT_DIE1, // deathstate
1445 S_NULL, // xdeathstate
1446 sfx_mandth, // deathsound
1447 8, // speed
1448 48*FRACUNIT, // radius
1449 64*FRACUNIT, // height
1450 1000, // mass
1451 0, // damage
1452 sfx_posact, // activesound
1453 MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL, // flags
1454 S_FATT_RAISE1 // raisestate
1455 },
1456
1457 { // MT_FATSHOT
1458 -1, // doomednum
1459 S_FATSHOT1, // spawnstate
1460 1000, // spawnhealth
1461 S_NULL, // seestate
1462 sfx_firsht, // seesound
1463 8, // reactiontime
1464 sfx_None, // attacksound
1465 S_NULL, // painstate
1466 0, // painchance
1467 sfx_None, // painsound
1468 S_NULL, // meleestate
1469 S_NULL, // missilestate
1470 S_FATSHOTX1, // deathstate
1471 S_NULL, // xdeathstate
1472 sfx_firxpl, // deathsound
1473 20*FRACUNIT, // speed
1474 6*FRACUNIT, // radius
1475 8*FRACUNIT, // height
1476 100, // mass
1477 8, // damage
1478 sfx_None, // activesound
1479 MF_NOBLOCKMAP|MF_MISSILE|MF_DROPOFF|MF_NOGRAVITY|MF_TRANSLUCENT, // flags \\ killough 2/21/98
1480 S_NULL // raisestate
1481 },
1482
1483 { // MT_CHAINGUY
1484 65, // doomednum
1485 S_CPOS_STND, // spawnstate
1486 70, // spawnhealth
1487 S_CPOS_RUN1, // seestate
1488 sfx_posit2, // seesound
1489 8, // reactiontime
1490 0, // attacksound
1491 S_CPOS_PAIN, // painstate
1492 170, // painchance
1493 sfx_popain, // painsound
1494 0, // meleestate
1495 S_CPOS_ATK1, // missilestate
1496 S_CPOS_DIE1, // deathstate
1497 S_CPOS_XDIE1, // xdeathstate
1498 sfx_podth2, // deathsound
1499 8, // speed
1500 20*FRACUNIT, // radius
1501 56*FRACUNIT, // height
1502 100, // mass
1503 0, // damage
1504 sfx_posact, // activesound
1505 MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL, // flags
1506 S_CPOS_RAISE1 // raisestate
1507 },
1508
1509 { // MT_TROOP
1510 3001, // doomednum
1511 S_TROO_STND, // spawnstate
1512 60, // spawnhealth
1513 S_TROO_RUN1, // seestate
1514 sfx_bgsit1, // seesound
1515 8, // reactiontime
1516 0, // attacksound
1517 S_TROO_PAIN, // painstate
1518 200, // painchance
1519 sfx_popain, // painsound
1520 S_TROO_ATK1, // meleestate
1521 S_TROO_ATK1, // missilestate
1522 S_TROO_DIE1, // deathstate
1523 S_TROO_XDIE1, // xdeathstate
1524 sfx_bgdth1, // deathsound
1525 8, // speed
1526 20*FRACUNIT, // radius
1527 56*FRACUNIT, // height
1528 100, // mass
1529 0, // damage
1530 sfx_bgact, // activesound
1531 MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL, // killough |MF_TRANSLUCENT, // flags // phares
1532 S_TROO_RAISE1 // raisestate
1533 },
1534
1535 { // MT_SERGEANT
1536 3002, // doomednum
1537 S_SARG_STND, // spawnstate
1538 150, // spawnhealth
1539 S_SARG_RUN1, // seestate
1540 sfx_sgtsit, // seesound
1541 8, // reactiontime
1542 sfx_sgtatk, // attacksound
1543 S_SARG_PAIN, // painstate
1544 180, // painchance
1545 sfx_dmpain, // painsound
1546 S_SARG_ATK1, // meleestate
1547 0, // missilestate
1548 S_SARG_DIE1, // deathstate
1549 S_NULL, // xdeathstate
1550 sfx_sgtdth, // deathsound
1551 10, // speed
1552 30*FRACUNIT, // radius
1553 56*FRACUNIT, // height
1554 400, // mass
1555 0, // damage
1556 sfx_dmact, // activesound
1557 MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL, // flags
1558 S_SARG_RAISE1 // raisestate
1559 },
1560
1561 { // MT_SHADOWS
1562 58, // doomednum
1563 S_SARG_STND, // spawnstate
1564 150, // spawnhealth
1565 S_SARG_RUN1, // seestate
1566 sfx_sgtsit, // seesound
1567 8, // reactiontime
1568 sfx_sgtatk, // attacksound
1569 S_SARG_PAIN, // painstate
1570 180, // painchance
1571 sfx_dmpain, // painsound
1572 S_SARG_ATK1, // meleestate
1573 0, // missilestate
1574 S_SARG_DIE1, // deathstate
1575 S_NULL, // xdeathstate
1576 sfx_sgtdth, // deathsound
1577 10, // speed
1578 30*FRACUNIT, // radius
1579 56*FRACUNIT, // height
1580 400, // mass
1581 0, // damage
1582 sfx_dmact, // activesound
1583 MF_SOLID|MF_SHOOTABLE|MF_SHADOW|MF_COUNTKILL, // flags
1584 S_SARG_RAISE1 // raisestate
1585 },
1586
1587 { // MT_HEAD
1588 3005, // doomednum
1589 S_HEAD_STND, // spawnstate
1590 400, // spawnhealth
1591 S_HEAD_RUN1, // seestate
1592 sfx_cacsit, // seesound
1593 8, // reactiontime
1594 0, // attacksound
1595 S_HEAD_PAIN, // painstate
1596 128, // painchance
1597 sfx_dmpain, // painsound
1598 0, // meleestate
1599 S_HEAD_ATK1, // missilestate
1600 S_HEAD_DIE1, // deathstate
1601 S_NULL, // xdeathstate
1602 sfx_cacdth, // deathsound
1603 8, // speed
1604 31*FRACUNIT, // radius
1605 56*FRACUNIT, // height
1606 400, // mass
1607 0, // damage
1608 sfx_dmact, // activesound
1609 MF_SOLID|MF_SHOOTABLE|MF_FLOAT|MF_NOGRAVITY|MF_COUNTKILL, // flags
1610 S_HEAD_RAISE1 // raisestate
1611 },
1612
1613 { // MT_BRUISER
1614 3003, // doomednum
1615 S_BOSS_STND, // spawnstate
1616 1000, // spawnhealth
1617 S_BOSS_RUN1, // seestate
1618 sfx_brssit, // seesound
1619 8, // reactiontime
1620 0, // attacksound
1621 S_BOSS_PAIN, // painstate
1622 50, // painchance
1623 sfx_dmpain, // painsound
1624 S_BOSS_ATK1, // meleestate
1625 S_BOSS_ATK1, // missilestate
1626 S_BOSS_DIE1, // deathstate
1627 S_NULL, // xdeathstate
1628 sfx_brsdth, // deathsound
1629 8, // speed
1630 24*FRACUNIT, // radius
1631 64*FRACUNIT, // height
1632 1000, // mass
1633 0, // damage
1634 sfx_dmact, // activesound
1635 MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL, // flags
1636 S_BOSS_RAISE1 // raisestate
1637 },
1638
1639 { // MT_BRUISERSHOT
1640 -1, // doomednum
1641 S_BRBALL1, // spawnstate
1642 1000, // spawnhealth
1643 S_NULL, // seestate
1644 sfx_firsht, // seesound
1645 8, // reactiontime
1646 sfx_None, // attacksound
1647 S_NULL, // painstate
1648 0, // painchance
1649 sfx_None, // painsound
1650 S_NULL, // meleestate
1651 S_NULL, // missilestate
1652 S_BRBALLX1, // deathstate
1653 S_NULL, // xdeathstate
1654 sfx_firxpl, // deathsound
1655 15*FRACUNIT, // speed
1656 6*FRACUNIT, // radius
1657 8*FRACUNIT, // height
1658 100, // mass
1659 8, // damage
1660 sfx_None, // activesound
1661 MF_NOBLOCKMAP|MF_MISSILE|MF_DROPOFF|MF_NOGRAVITY|MF_TRANSLUCENT, // flags killough 2/21/98
1662 S_NULL // raisestate
1663 },
1664
1665 { // MT_KNIGHT
1666 69, // doomednum
1667 S_BOS2_STND, // spawnstate
1668 500, // spawnhealth
1669 S_BOS2_RUN1, // seestate
1670 sfx_kntsit, // seesound
1671 8, // reactiontime
1672 0, // attacksound
1673 S_BOS2_PAIN, // painstate
1674 50, // painchance
1675 sfx_dmpain, // painsound
1676 S_BOS2_ATK1, // meleestate
1677 S_BOS2_ATK1, // missilestate
1678 S_BOS2_DIE1, // deathstate
1679 S_NULL, // xdeathstate
1680 sfx_kntdth, // deathsound
1681 8, // speed
1682 24*FRACUNIT, // radius
1683 64*FRACUNIT, // height
1684 1000, // mass
1685 0, // damage
1686 sfx_dmact, // activesound
1687 MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL, // flags
1688 S_BOS2_RAISE1 // raisestate
1689 },
1690
1691 { // MT_SKULL
1692 3006, // doomednum
1693 S_SKULL_STND, // spawnstate
1694 100, // spawnhealth
1695 S_SKULL_RUN1, // seestate
1696 0, // seesound
1697 8, // reactiontime
1698 sfx_sklatk, // attacksound
1699 S_SKULL_PAIN, // painstate
1700 256, // painchance
1701 sfx_dmpain, // painsound
1702 0, // meleestate
1703 S_SKULL_ATK1, // missilestate
1704 S_SKULL_DIE1, // deathstate
1705 S_NULL, // xdeathstate
1706 sfx_firxpl, // deathsound
1707 8, // speed
1708 16*FRACUNIT, // radius
1709 56*FRACUNIT, // height
1710 50, // mass
1711 3, // damage
1712 sfx_dmact, // activesound
1713 MF_SOLID|MF_SHOOTABLE|MF_FLOAT|MF_NOGRAVITY, // flags
1714 S_NULL // raisestate
1715 },
1716
1717 { // MT_SPIDER
1718 7, // doomednum
1719 S_SPID_STND, // spawnstate
1720 3000, // spawnhealth
1721 S_SPID_RUN1, // seestate
1722 sfx_spisit, // seesound
1723 8, // reactiontime
1724 sfx_shotgn, // attacksound
1725 S_SPID_PAIN, // painstate
1726 40, // painchance
1727 sfx_dmpain, // painsound
1728 0, // meleestate
1729 S_SPID_ATK1, // missilestate
1730 S_SPID_DIE1, // deathstate
1731 S_NULL, // xdeathstate
1732 sfx_spidth, // deathsound
1733 12, // speed
1734 128*FRACUNIT, // radius
1735 100*FRACUNIT, // height
1736 1000, // mass
1737 0, // damage
1738 sfx_dmact, // activesound
1739 MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL, // flags
1740 S_NULL // raisestate
1741 },
1742
1743 { // MT_BABY
1744 68, // doomednum
1745 S_BSPI_STND, // spawnstate
1746 500, // spawnhealth
1747 S_BSPI_SIGHT, // seestate
1748 sfx_bspsit, // seesound
1749 8, // reactiontime
1750 0, // attacksound
1751 S_BSPI_PAIN, // painstate
1752 128, // painchance
1753 sfx_dmpain, // painsound
1754 0, // meleestate
1755 S_BSPI_ATK1, // missilestate
1756 S_BSPI_DIE1, // deathstate
1757 S_NULL, // xdeathstate
1758 sfx_bspdth, // deathsound
1759 12, // speed
1760 64*FRACUNIT, // radius
1761 64*FRACUNIT, // height
1762 600, // mass
1763 0, // damage
1764 sfx_bspact, // activesound
1765 MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL, // flags
1766 S_BSPI_RAISE1 // raisestate
1767 },
1768
1769 { // MT_CYBORG
1770 16, // doomednum
1771 S_CYBER_STND, // spawnstate
1772 4000, // spawnhealth
1773 S_CYBER_RUN1, // seestate
1774 sfx_cybsit, // seesound
1775 8, // reactiontime
1776 0, // attacksound
1777 S_CYBER_PAIN, // painstate
1778 20, // painchance
1779 sfx_dmpain, // painsound
1780 0, // meleestate
1781 S_CYBER_ATK1, // missilestate
1782 S_CYBER_DIE1, // deathstate
1783 S_NULL, // xdeathstate
1784 sfx_cybdth, // deathsound
1785 16, // speed
1786 40*FRACUNIT, // radius
1787 110*FRACUNIT, // height
1788 1000, // mass
1789 0, // damage
1790 sfx_dmact, // activesound
1791 MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL, // flags
1792 S_NULL // raisestate
1793 },
1794
1795 { // MT_PAIN
1796 71, // doomednum
1797 S_PAIN_STND, // spawnstate
1798 400, // spawnhealth
1799 S_PAIN_RUN1, // seestate
1800 sfx_pesit, // seesound
1801 8, // reactiontime
1802 0, // attacksound
1803 S_PAIN_PAIN, // painstate
1804 128, // painchance
1805 sfx_pepain, // painsound
1806 0, // meleestate
1807 S_PAIN_ATK1, // missilestate
1808 S_PAIN_DIE1, // deathstate
1809 S_NULL, // xdeathstate
1810 sfx_pedth, // deathsound
1811 8, // speed
1812 31*FRACUNIT, // radius
1813 56*FRACUNIT, // height
1814 400, // mass
1815 0, // damage
1816 sfx_dmact, // activesound
1817 MF_SOLID|MF_SHOOTABLE|MF_FLOAT|MF_NOGRAVITY|MF_COUNTKILL, // flags
1818 S_PAIN_RAISE1 // raisestate
1819 },
1820
1821 { // MT_WOLFSS
1822 84, // doomednum
1823 S_SSWV_STND, // spawnstate
1824 50, // spawnhealth
1825 S_SSWV_RUN1, // seestate
1826 sfx_sssit, // seesound
1827 8, // reactiontime
1828 0, // attacksound
1829 S_SSWV_PAIN, // painstate
1830 170, // painchance
1831 sfx_popain, // painsound
1832 0, // meleestate
1833 S_SSWV_ATK1, // missilestate
1834 S_SSWV_DIE1, // deathstate
1835 S_SSWV_XDIE1, // xdeathstate
1836 sfx_ssdth, // deathsound
1837 8, // speed
1838 20*FRACUNIT, // radius
1839 56*FRACUNIT, // height
1840 100, // mass
1841 0, // damage
1842 sfx_posact, // activesound
1843 MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL, // flags
1844 S_SSWV_RAISE1 // raisestate
1845 },
1846
1847 { // MT_KEEN
1848 72, // doomednum
1849 S_KEENSTND, // spawnstate
1850 100, // spawnhealth
1851 S_NULL, // seestate
1852 sfx_None, // seesound
1853 8, // reactiontime
1854 sfx_None, // attacksound
1855 S_KEENPAIN, // painstate
1856 256, // painchance
1857 sfx_keenpn, // painsound
1858 S_NULL, // meleestate
1859 S_NULL, // missilestate
1860 S_COMMKEEN, // deathstate
1861 S_NULL, // xdeathstate
1862 sfx_keendt, // deathsound
1863 0, // speed
1864 16*FRACUNIT, // radius
1865 72*FRACUNIT, // height
1866 10000000, // mass
1867 0, // damage
1868 sfx_None, // activesound
1869 MF_SOLID|MF_SPAWNCEILING|MF_NOGRAVITY|MF_SHOOTABLE|MF_COUNTKILL, // flags
1870 S_NULL // raisestate
1871 },
1872
1873 { // MT_BOSSBRAIN
1874 88, // doomednum
1875 S_BRAIN, // spawnstate
1876 250, // spawnhealth
1877 S_NULL, // seestate
1878 sfx_None, // seesound
1879 8, // reactiontime
1880 sfx_None, // attacksound
1881 S_BRAIN_PAIN, // painstate
1882 255, // painchance
1883 sfx_bospn, // painsound
1884 S_NULL, // meleestate
1885 S_NULL, // missilestate
1886 S_BRAIN_DIE1, // deathstate
1887 S_NULL, // xdeathstate
1888 sfx_bosdth, // deathsound
1889 0, // speed
1890 16*FRACUNIT, // radius
1891 16*FRACUNIT, // height
1892 10000000, // mass
1893 0, // damage
1894 sfx_None, // activesound
1895 MF_SOLID|MF_SHOOTABLE, // flags
1896 S_NULL // raisestate
1897 },
1898
1899 { // MT_BOSSSPIT
1900 89, // doomednum
1901 S_BRAINEYE, // spawnstate
1902 1000, // spawnhealth
1903 S_BRAINEYESEE, // seestate
1904 sfx_None, // seesound
1905 8, // reactiontime
1906 sfx_None, // attacksound
1907 S_NULL, // painstate
1908 0, // painchance
1909 sfx_None, // painsound
1910 S_NULL, // meleestate
1911 S_NULL, // missilestate
1912 S_NULL, // deathstate
1913 S_NULL, // xdeathstate
1914 sfx_None, // deathsound
1915 0, // speed
1916 20*FRACUNIT, // radius
1917 32*FRACUNIT, // height
1918 100, // mass
1919 0, // damage
1920 sfx_None, // activesound
1921 MF_NOBLOCKMAP|MF_NOSECTOR, // flags
1922 S_NULL // raisestate
1923 },
1924
1925 { // MT_BOSSTARGET
1926 87, // doomednum
1927 S_NULL, // spawnstate
1928 1000, // spawnhealth
1929 S_NULL, // seestate
1930 sfx_None, // seesound
1931 8, // reactiontime
1932 sfx_None, // attacksound
1933 S_NULL, // painstate
1934 0, // painchance
1935 sfx_None, // painsound
1936 S_NULL, // meleestate
1937 S_NULL, // missilestate
1938 S_NULL, // deathstate
1939 S_NULL, // xdeathstate
1940 sfx_None, // deathsound
1941 0, // speed
1942 20*FRACUNIT, // radius
1943 32*FRACUNIT, // height
1944 100, // mass
1945 0, // damage
1946 sfx_None, // activesound
1947 MF_NOBLOCKMAP|MF_NOSECTOR, // flags
1948 S_NULL // raisestate
1949 },
1950
1951 { // MT_SPAWNSHOT
1952 -1, // doomednum
1953 S_SPAWN1, // spawnstate
1954 1000, // spawnhealth
1955 S_NULL, // seestate
1956 sfx_bospit, // seesound
1957 8, // reactiontime
1958 sfx_None, // attacksound
1959 S_NULL, // painstate
1960 0, // painchance
1961 sfx_None, // painsound
1962 S_NULL, // meleestate
1963 S_NULL, // missilestate
1964 S_NULL, // deathstate
1965 S_NULL, // xdeathstate
1966 sfx_firxpl, // deathsound
1967 10*FRACUNIT, // speed
1968 6*FRACUNIT, // radius
1969 32*FRACUNIT, // height
1970 100, // mass
1971 3, // damage
1972 sfx_None, // activesound
1973 MF_NOBLOCKMAP|MF_MISSILE|MF_DROPOFF|MF_NOGRAVITY|MF_NOCLIP, // flags
1974 S_NULL // raisestate
1975 },
1976
1977 { // MT_SPAWNFIRE
1978 -1, // doomednum
1979 S_SPAWNFIRE1, // spawnstate
1980 1000, // spawnhealth
1981 S_NULL, // seestate
1982 sfx_None, // seesound
1983 8, // reactiontime
1984 sfx_None, // attacksound
1985 S_NULL, // painstate
1986 0, // painchance
1987 sfx_None, // painsound
1988 S_NULL, // meleestate
1989 S_NULL, // missilestate
1990 S_NULL, // deathstate
1991 S_NULL, // xdeathstate
1992 sfx_None, // deathsound
1993 0, // speed
1994 20*FRACUNIT, // radius
1995 16*FRACUNIT, // height
1996 100, // mass
1997 0, // damage
1998 sfx_None, // activesound
1999 MF_NOBLOCKMAP|MF_NOGRAVITY|MF_TRANSLUCENT, // flags // phares
2000 S_NULL // raisestate
2001 },
2002
2003 { // MT_BARREL
2004 2035, // doomednum
2005 S_BAR1, // spawnstate
2006 20, // spawnhealth
2007 S_NULL, // seestate
2008 sfx_None, // seesound
2009 8, // reactiontime
2010 sfx_None, // attacksound
2011 S_NULL, // painstate
2012 0, // painchance
2013 sfx_None, // painsound
2014 S_NULL, // meleestate
2015 S_NULL, // missilestate
2016 S_BEXP, // deathstate
2017 S_NULL, // xdeathstate
2018 sfx_barexp, // deathsound
2019 0, // speed
2020 10*FRACUNIT, // radius
2021 42*FRACUNIT, // height
2022 100, // mass
2023 0, // damage
2024 sfx_None, // activesound
2025 MF_SOLID|MF_SHOOTABLE|MF_NOBLOOD, // flags
2026 S_NULL // raisestate
2027 },
2028
2029 { // MT_TROOPSHOT
2030 -1, // doomednum
2031 S_TBALL1, // spawnstate
2032 1000, // spawnhealth
2033 S_NULL, // seestate
2034 sfx_firsht, // seesound
2035 8, // reactiontime
2036 sfx_None, // attacksound
2037 S_NULL, // painstate
2038 0, // painchance
2039 sfx_None, // painsound
2040 S_NULL, // meleestate
2041 S_NULL, // missilestate
2042 S_TBALLX1, // deathstate
2043 S_NULL, // xdeathstate
2044 sfx_firxpl, // deathsound
2045 10*FRACUNIT, // speed
2046 6*FRACUNIT, // radius
2047 8*FRACUNIT, // height
2048 100, // mass
2049 3, // damage
2050 sfx_None, // activesound
2051 MF_NOBLOCKMAP|MF_MISSILE|MF_DROPOFF|MF_NOGRAVITY|MF_TRANSLUCENT, // flags // phares
2052 S_NULL // raisestate
2053 },
2054
2055 { // MT_HEADSHOT
2056 -1, // doomednum
2057 S_RBALL1, // spawnstate
2058 1000, // spawnhealth
2059 S_NULL, // seestate
2060 sfx_firsht, // seesound
2061 8, // reactiontime
2062 sfx_None, // attacksound
2063 S_NULL, // painstate
2064 0, // painchance
2065 sfx_None, // painsound
2066 S_NULL, // meleestate
2067 S_NULL, // missilestate
2068 S_RBALLX1, // deathstate
2069 S_NULL, // xdeathstate
2070 sfx_firxpl, // deathsound
2071 10*FRACUNIT, // speed
2072 6*FRACUNIT, // radius
2073 8*FRACUNIT, // height
2074 100, // mass
2075 5, // damage
2076 sfx_None, // activesound
2077 MF_NOBLOCKMAP|MF_MISSILE|MF_DROPOFF|MF_NOGRAVITY|MF_TRANSLUCENT, // flags // phares, // flags
2078 S_NULL // raisestate
2079 },
2080
2081 { // MT_ROCKET
2082 -1, // doomednum
2083 S_ROCKET, // spawnstate
2084 1000, // spawnhealth
2085 S_NULL, // seestate
2086 sfx_rlaunc, // seesound
2087 8, // reactiontime
2088 sfx_None, // attacksound
2089 S_NULL, // painstate
2090 0, // painchance
2091 sfx_None, // painsound
2092 S_NULL, // meleestate
2093 S_NULL, // missilestate
2094 S_EXPLODE1, // deathstate
2095 S_NULL, // xdeathstate
2096 sfx_barexp, // deathsound
2097 20*FRACUNIT, // speed
2098 11*FRACUNIT, // radius
2099 8*FRACUNIT, // height
2100 100, // mass
2101 20, // damage
2102 sfx_None, // activesound
2103 MF_NOBLOCKMAP|MF_MISSILE|MF_DROPOFF|MF_NOGRAVITY, // flags
2104 S_NULL // raisestate
2105 },
2106
2107 { // MT_PLASMA
2108 -1, // doomednum
2109 S_PLASBALL, // spawnstate
2110 1000, // spawnhealth
2111 S_NULL, // seestate
2112 sfx_plasma, // seesound
2113 8, // reactiontime
2114 sfx_None, // attacksound
2115 S_NULL, // painstate
2116 0, // painchance
2117 sfx_None, // painsound
2118 S_NULL, // meleestate
2119 S_NULL, // missilestate
2120 S_PLASEXP, // deathstate
2121 S_NULL, // xdeathstate
2122 sfx_firxpl, // deathsound
2123 25*FRACUNIT, // speed
2124 13*FRACUNIT, // radius
2125 8*FRACUNIT, // height
2126 100, // mass
2127 5, // damage
2128 sfx_None, // activesound
2129 MF_NOBLOCKMAP|MF_MISSILE|MF_DROPOFF|MF_NOGRAVITY|MF_TRANSLUCENT, // flags // phares
2130 S_NULL // raisestate
2131 },
2132
2133 { // MT_BFG
2134 -1, // doomednum
2135 S_BFGSHOT, // spawnstate
2136 1000, // spawnhealth
2137 S_NULL, // seestate
2138 0, // seesound
2139 8, // reactiontime
2140 sfx_None, // attacksound
2141 S_NULL, // painstate
2142 0, // painchance
2143 sfx_None, // painsound
2144 S_NULL, // meleestate
2145 S_NULL, // missilestate
2146 S_BFGLAND, // deathstate
2147 S_NULL, // xdeathstate
2148 sfx_rxplod, // deathsound
2149 25*FRACUNIT, // speed
2150 13*FRACUNIT, // radius
2151 8*FRACUNIT, // height
2152 100, // mass
2153 100, // damage
2154 sfx_None, // activesound
2155 MF_NOBLOCKMAP|MF_MISSILE|MF_DROPOFF|MF_NOGRAVITY|MF_TRANSLUCENT, // flags // phares
2156 S_NULL // raisestate
2157 },
2158
2159 { // MT_ARACHPLAZ
2160 -1, // doomednum
2161 S_ARACH_PLAZ, // spawnstate
2162 1000, // spawnhealth
2163 S_NULL, // seestate
2164 sfx_plasma, // seesound
2165 8, // reactiontime
2166 sfx_None, // attacksound
2167 S_NULL, // painstate
2168 0, // painchance
2169 sfx_None, // painsound
2170 S_NULL, // meleestate
2171 S_NULL, // missilestate
2172 S_ARACH_PLEX, // deathstate
2173 S_NULL, // xdeathstate
2174 sfx_firxpl, // deathsound
2175 25*FRACUNIT, // speed
2176 13*FRACUNIT, // radius
2177 8*FRACUNIT, // height
2178 100, // mass
2179 5, // damage
2180 sfx_None, // activesound
2181 MF_NOBLOCKMAP|MF_MISSILE|MF_DROPOFF|MF_NOGRAVITY|MF_TRANSLUCENT, // flags // phares
2182 S_NULL // raisestate
2183 },
2184
2185 { // MT_PUFF
2186 -1, // doomednum
2187 S_PUFF1, // spawnstate
2188 1000, // spawnhealth
2189 S_NULL, // seestate
2190 sfx_None, // seesound
2191 8, // reactiontime
2192 sfx_None, // attacksound
2193 S_NULL, // painstate
2194 0, // painchance
2195 sfx_None, // painsound
2196 S_NULL, // meleestate
2197 S_NULL, // missilestate
2198 S_NULL, // deathstate
2199 S_NULL, // xdeathstate
2200 sfx_None, // deathsound
2201 0, // speed
2202 20*FRACUNIT, // radius
2203 16*FRACUNIT, // height
2204 100, // mass
2205 0, // damage
2206 sfx_None, // activesound
2207 MF_NOBLOCKMAP|MF_NOGRAVITY|MF_TRANSLUCENT, // flags // phares
2208 S_NULL // raisestate
2209 },
2210
2211 { // MT_BLOOD
2212 -1, // doomednum
2213 S_BLOOD1, // spawnstate
2214 1000, // spawnhealth
2215 S_NULL, // seestate
2216 sfx_None, // seesound
2217 8, // reactiontime
2218 sfx_None, // attacksound
2219 S_NULL, // painstate
2220 0, // painchance
2221 sfx_None, // painsound
2222 S_NULL, // meleestate
2223 S_NULL, // missilestate
2224 S_NULL, // deathstate
2225 S_NULL, // xdeathstate
2226 sfx_None, // deathsound
2227 0, // speed
2228 20*FRACUNIT, // radius
2229 16*FRACUNIT, // height
2230 100, // mass
2231 0, // damage
2232 sfx_None, // activesound
2233 MF_NOBLOCKMAP, // flags
2234 S_NULL // raisestate
2235 },
2236
2237 { // MT_TFOG
2238 -1, // doomednum
2239 S_TFOG, // spawnstate
2240 1000, // spawnhealth
2241 S_NULL, // seestate
2242 sfx_None, // seesound
2243 8, // reactiontime
2244 sfx_None, // attacksound
2245 S_NULL, // painstate
2246 0, // painchance
2247 sfx_None, // painsound
2248 S_NULL, // meleestate
2249 S_NULL, // missilestate
2250 S_NULL, // deathstate
2251 S_NULL, // xdeathstate
2252 sfx_None, // deathsound
2253 0, // speed
2254 20*FRACUNIT, // radius
2255 16*FRACUNIT, // height
2256 100, // mass
2257 0, // damage
2258 sfx_None, // activesound
2259 MF_NOBLOCKMAP|MF_NOGRAVITY|MF_TRANSLUCENT, // flags // phares
2260 S_NULL // raisestate
2261 },
2262
2263 { // MT_IFOG
2264 -1, // doomednum
2265 S_IFOG, // spawnstate
2266 1000, // spawnhealth
2267 S_NULL, // seestate
2268 sfx_None, // seesound
2269 8, // reactiontime
2270 sfx_None, // attacksound
2271 S_NULL, // painstate
2272 0, // painchance
2273 sfx_None, // painsound
2274 S_NULL, // meleestate
2275 S_NULL, // missilestate
2276 S_NULL, // deathstate
2277 S_NULL, // xdeathstate
2278 sfx_None, // deathsound
2279 0, // speed
2280 20*FRACUNIT, // radius
2281 16*FRACUNIT, // height
2282 100, // mass
2283 0, // damage
2284 sfx_None, // activesound
2285 MF_NOBLOCKMAP|MF_NOGRAVITY|MF_TRANSLUCENT, // flags // phares
2286 S_NULL // raisestate
2287 },
2288
2289 { // MT_TELEPORTMAN
2290 14, // doomednum
2291 S_NULL, // spawnstate
2292 1000, // spawnhealth
2293 S_NULL, // seestate
2294 sfx_None, // seesound
2295 8, // reactiontime
2296 sfx_None, // attacksound
2297 S_NULL, // painstate
2298 0, // painchance
2299 sfx_None, // painsound
2300 S_NULL, // meleestate
2301 S_NULL, // missilestate
2302 S_NULL, // deathstate
2303 S_NULL, // xdeathstate
2304 sfx_None, // deathsound
2305 0, // speed
2306 20*FRACUNIT, // radius
2307 16*FRACUNIT, // height
2308 100, // mass
2309 0, // damage
2310 sfx_None, // activesound
2311 MF_NOBLOCKMAP|MF_NOSECTOR, // flags
2312 S_NULL // raisestate
2313 },
2314
2315 { // MT_EXTRABFG
2316 -1, // doomednum
2317 S_BFGEXP, // spawnstate
2318 1000, // spawnhealth
2319 S_NULL, // seestate
2320 sfx_None, // seesound
2321 8, // reactiontime
2322 sfx_None, // attacksound
2323 S_NULL, // painstate
2324 0, // painchance
2325 sfx_None, // painsound
2326 S_NULL, // meleestate
2327 S_NULL, // missilestate
2328 S_NULL, // deathstate
2329 S_NULL, // xdeathstate
2330 sfx_None, // deathsound
2331 0, // speed
2332 20*FRACUNIT, // radius
2333 16*FRACUNIT, // height
2334 100, // mass
2335 0, // damage
2336 sfx_None, // activesound
2337 MF_NOBLOCKMAP|MF_NOGRAVITY, // flags
2338 S_NULL // raisestate
2339 },
2340
2341 { // MT_MISC0
2342 2018, // doomednum
2343 S_ARM1, // spawnstate
2344 1000, // spawnhealth
2345 S_NULL, // seestate
2346 sfx_None, // seesound
2347 8, // reactiontime
2348 sfx_None, // attacksound
2349 S_NULL, // painstate
2350 0, // painchance
2351 sfx_None, // painsound
2352 S_NULL, // meleestate
2353 S_NULL, // missilestate
2354 S_NULL, // deathstate
2355 S_NULL, // xdeathstate
2356 sfx_None, // deathsound
2357 0, // speed
2358 20*FRACUNIT, // radius
2359 16*FRACUNIT, // height
2360 100, // mass
2361 0, // damage
2362 sfx_None, // activesound
2363 MF_SPECIAL, // flags
2364 S_NULL // raisestate
2365 },
2366
2367 { // MT_MISC1
2368 2019, // doomednum
2369 S_ARM2, // spawnstate
2370 1000, // spawnhealth
2371 S_NULL, // seestate
2372 sfx_None, // seesound
2373 8, // reactiontime
2374 sfx_None, // attacksound
2375 S_NULL, // painstate
2376 0, // painchance
2377 sfx_None, // painsound
2378 S_NULL, // meleestate
2379 S_NULL, // missilestate
2380 S_NULL, // deathstate
2381 S_NULL, // xdeathstate
2382 sfx_None, // deathsound
2383 0, // speed
2384 20*FRACUNIT, // radius
2385 16*FRACUNIT, // height
2386 100, // mass
2387 0, // damage
2388 sfx_None, // activesound
2389 MF_SPECIAL, // flags
2390 S_NULL // raisestate
2391 },
2392
2393 { // MT_MISC2
2394 2014, // doomednum
2395 S_BON1, // spawnstate
2396 1000, // spawnhealth
2397 S_NULL, // seestate
2398 sfx_None, // seesound
2399 8, // reactiontime
2400 sfx_None, // attacksound
2401 S_NULL, // painstate
2402 0, // painchance
2403 sfx_None, // painsound
2404 S_NULL, // meleestate
2405 S_NULL, // missilestate
2406 S_NULL, // deathstate
2407 S_NULL, // xdeathstate
2408 sfx_None, // deathsound
2409 0, // speed
2410 20*FRACUNIT, // radius
2411 16*FRACUNIT, // height
2412 100, // mass
2413 0, // damage
2414 sfx_None, // activesound
2415 MF_SPECIAL|MF_COUNTITEM, // flags
2416 S_NULL // raisestate
2417 },
2418
2419 { // MT_MISC3
2420 2015, // doomednum
2421 S_BON2, // spawnstate
2422 1000, // spawnhealth
2423 S_NULL, // seestate
2424 sfx_None, // seesound
2425 8, // reactiontime
2426 sfx_None, // attacksound
2427 S_NULL, // painstate
2428 0, // painchance
2429 sfx_None, // painsound
2430 S_NULL, // meleestate
2431 S_NULL, // missilestate
2432 S_NULL, // deathstate
2433 S_NULL, // xdeathstate
2434 sfx_None, // deathsound
2435 0, // speed
2436 20*FRACUNIT, // radius
2437 16*FRACUNIT, // height
2438 100, // mass
2439 0, // damage
2440 sfx_None, // activesound
2441 MF_SPECIAL|MF_COUNTITEM, // flags
2442 S_NULL // raisestate
2443 },
2444
2445 { // MT_MISC4
2446 5, // doomednum
2447 S_BKEY, // spawnstate
2448 1000, // spawnhealth
2449 S_NULL, // seestate
2450 sfx_None, // seesound
2451 8, // reactiontime
2452 sfx_None, // attacksound
2453 S_NULL, // painstate
2454 0, // painchance
2455 sfx_None, // painsound
2456 S_NULL, // meleestate
2457 S_NULL, // missilestate
2458 S_NULL, // deathstate
2459 S_NULL, // xdeathstate
2460 sfx_None, // deathsound
2461 0, // speed
2462 20*FRACUNIT, // radius
2463 16*FRACUNIT, // height
2464 100, // mass
2465 0, // damage
2466 sfx_None, // activesound
2467 MF_SPECIAL|MF_NOTDMATCH, // flags
2468 S_NULL // raisestate
2469 },
2470
2471 { // MT_MISC5
2472 13, // doomednum
2473 S_RKEY, // spawnstate
2474 1000, // spawnhealth
2475 S_NULL, // seestate
2476 sfx_None, // seesound
2477 8, // reactiontime
2478 sfx_None, // attacksound
2479 S_NULL, // painstate
2480 0, // painchance
2481 sfx_None, // painsound
2482 S_NULL, // meleestate
2483 S_NULL, // missilestate
2484 S_NULL, // deathstate
2485 S_NULL, // xdeathstate
2486 sfx_None, // deathsound
2487 0, // speed
2488 20*FRACUNIT, // radius
2489 16*FRACUNIT, // height
2490 100, // mass
2491 0, // damage
2492 sfx_None, // activesound
2493 MF_SPECIAL|MF_NOTDMATCH, // flags
2494 S_NULL // raisestate
2495 },
2496
2497 { // MT_MISC6
2498 6, // doomednum
2499 S_YKEY, // spawnstate
2500 1000, // spawnhealth
2501 S_NULL, // seestate
2502 sfx_None, // seesound
2503 8, // reactiontime
2504 sfx_None, // attacksound
2505 S_NULL, // painstate
2506 0, // painchance
2507 sfx_None, // painsound
2508 S_NULL, // meleestate
2509 S_NULL, // missilestate
2510 S_NULL, // deathstate
2511 S_NULL, // xdeathstate
2512 sfx_None, // deathsound
2513 0, // speed
2514 20*FRACUNIT, // radius
2515 16*FRACUNIT, // height
2516 100, // mass
2517 0, // damage
2518 sfx_None, // activesound
2519 MF_SPECIAL|MF_NOTDMATCH, // flags
2520 S_NULL // raisestate
2521 },
2522
2523 { // MT_MISC7
2524 39, // doomednum
2525 S_YSKULL, // spawnstate
2526 1000, // spawnhealth
2527 S_NULL, // seestate
2528 sfx_None, // seesound
2529 8, // reactiontime
2530 sfx_None, // attacksound
2531 S_NULL, // painstate
2532 0, // painchance
2533 sfx_None, // painsound
2534 S_NULL, // meleestate
2535 S_NULL, // missilestate
2536 S_NULL, // deathstate
2537 S_NULL, // xdeathstate
2538 sfx_None, // deathsound
2539 0, // speed
2540 20*FRACUNIT, // radius
2541 16*FRACUNIT, // height
2542 100, // mass
2543 0, // damage
2544 sfx_None, // activesound
2545 MF_SPECIAL|MF_NOTDMATCH, // flags
2546 S_NULL // raisestate
2547 },
2548
2549 { // MT_MISC8
2550 38, // doomednum
2551 S_RSKULL, // spawnstate
2552 1000, // spawnhealth
2553 S_NULL, // seestate
2554 sfx_None, // seesound
2555 8, // reactiontime
2556 sfx_None, // attacksound
2557 S_NULL, // painstate
2558 0, // painchance
2559 sfx_None, // painsound
2560 S_NULL, // meleestate
2561 S_NULL, // missilestate
2562 S_NULL, // deathstate
2563 S_NULL, // xdeathstate
2564 sfx_None, // deathsound
2565 0, // speed
2566 20*FRACUNIT, // radius
2567 16*FRACUNIT, // height
2568 100, // mass
2569 0, // damage
2570 sfx_None, // activesound
2571 MF_SPECIAL|MF_NOTDMATCH, // flags
2572 S_NULL // raisestate
2573 },
2574
2575 { // MT_MISC9
2576 40, // doomednum
2577 S_BSKULL, // spawnstate
2578 1000, // spawnhealth
2579 S_NULL, // seestate
2580 sfx_None, // seesound
2581 8, // reactiontime
2582 sfx_None, // attacksound
2583 S_NULL, // painstate
2584 0, // painchance
2585 sfx_None, // painsound
2586 S_NULL, // meleestate
2587 S_NULL, // missilestate
2588 S_NULL, // deathstate
2589 S_NULL, // xdeathstate
2590 sfx_None, // deathsound
2591 0, // speed
2592 20*FRACUNIT, // radius
2593 16*FRACUNIT, // height
2594 100, // mass
2595 0, // damage
2596 sfx_None, // activesound
2597 MF_SPECIAL|MF_NOTDMATCH, // flags
2598 S_NULL // raisestate
2599 },
2600
2601 { // MT_MISC10
2602 2011, // doomednum
2603 S_STIM, // spawnstate
2604 1000, // spawnhealth
2605 S_NULL, // seestate
2606 sfx_None, // seesound
2607 8, // reactiontime
2608 sfx_None, // attacksound
2609 S_NULL, // painstate
2610 0, // painchance
2611 sfx_None, // painsound
2612 S_NULL, // meleestate
2613 S_NULL, // missilestate
2614 S_NULL, // deathstate
2615 S_NULL, // xdeathstate
2616 sfx_None, // deathsound
2617 0, // speed
2618 20*FRACUNIT, // radius
2619 16*FRACUNIT, // height
2620 100, // mass
2621 0, // damage
2622 sfx_None, // activesound
2623 MF_SPECIAL, // flags
2624 S_NULL // raisestate
2625 },
2626
2627 { // MT_MISC11
2628 2012, // doomednum
2629 S_MEDI, // spawnstate
2630 1000, // spawnhealth
2631 S_NULL, // seestate
2632 sfx_None, // seesound
2633 8, // reactiontime
2634 sfx_None, // attacksound
2635 S_NULL, // painstate
2636 0, // painchance
2637 sfx_None, // painsound
2638 S_NULL, // meleestate
2639 S_NULL, // missilestate
2640 S_NULL, // deathstate
2641 S_NULL, // xdeathstate
2642 sfx_None, // deathsound
2643 0, // speed
2644 20*FRACUNIT, // radius
2645 16*FRACUNIT, // height
2646 100, // mass
2647 0, // damage
2648 sfx_None, // activesound
2649 MF_SPECIAL, // flags
2650 S_NULL // raisestate
2651 },
2652
2653 { // MT_MISC12
2654 2013, // doomednum
2655 S_SOUL, // spawnstate
2656 1000, // spawnhealth
2657 S_NULL, // seestate
2658 sfx_None, // seesound
2659 8, // reactiontime
2660 sfx_None, // attacksound
2661 S_NULL, // painstate
2662 0, // painchance
2663 sfx_None, // painsound
2664 S_NULL, // meleestate
2665 S_NULL, // missilestate
2666 S_NULL, // deathstate
2667 S_NULL, // xdeathstate
2668 sfx_None, // deathsound
2669 0, // speed
2670 20*FRACUNIT, // radius
2671 16*FRACUNIT, // height
2672 100, // mass
2673 0, // damage
2674 sfx_None, // activesound
2675 MF_SPECIAL|MF_COUNTITEM|MF_TRANSLUCENT, // flags // killough 2/21/98
2676 S_NULL // raisestate
2677 },
2678
2679 { // MT_INV
2680 2022, // doomednum
2681 S_PINV, // spawnstate
2682 1000, // spawnhealth
2683 S_NULL, // seestate
2684 sfx_None, // seesound
2685 8, // reactiontime
2686 sfx_None, // attacksound
2687 S_NULL, // painstate
2688 0, // painchance
2689 sfx_None, // painsound
2690 S_NULL, // meleestate
2691 S_NULL, // missilestate
2692 S_NULL, // deathstate
2693 S_NULL, // xdeathstate
2694 sfx_None, // deathsound
2695 0, // speed
2696 20*FRACUNIT, // radius
2697 16*FRACUNIT, // height
2698 100, // mass
2699 0, // damage
2700 sfx_None, // activesound
2701 MF_SPECIAL|MF_COUNTITEM|MF_TRANSLUCENT, // flags // killough 2/21/98
2702 S_NULL // raisestate
2703 },
2704
2705 { // MT_MISC13
2706 2023, // doomednum
2707 S_PSTR, // spawnstate
2708 1000, // spawnhealth
2709 S_NULL, // seestate
2710 sfx_None, // seesound
2711 8, // reactiontime
2712 sfx_None, // attacksound
2713 S_NULL, // painstate
2714 0, // painchance
2715 sfx_None, // painsound
2716 S_NULL, // meleestate
2717 S_NULL, // missilestate
2718 S_NULL, // deathstate
2719 S_NULL, // xdeathstate
2720 sfx_None, // deathsound
2721 0, // speed
2722 20*FRACUNIT, // radius
2723 16*FRACUNIT, // height
2724 100, // mass
2725 0, // damage
2726 sfx_None, // activesound
2727 MF_SPECIAL|MF_COUNTITEM, // flags
2728 S_NULL // raisestate
2729 },
2730
2731 { // MT_INS
2732 2024, // doomednum
2733 S_PINS, // spawnstate
2734 1000, // spawnhealth
2735 S_NULL, // seestate
2736 sfx_None, // seesound
2737 8, // reactiontime
2738 sfx_None, // attacksound
2739 S_NULL, // painstate
2740 0, // painchance
2741 sfx_None, // painsound
2742 S_NULL, // meleestate
2743 S_NULL, // missilestate
2744 S_NULL, // deathstate
2745 S_NULL, // xdeathstate
2746 sfx_None, // deathsound
2747 0, // speed
2748 20*FRACUNIT, // radius
2749 16*FRACUNIT, // height
2750 100, // mass
2751 0, // damage
2752 sfx_None, // activesound
2753 MF_SPECIAL|MF_COUNTITEM|MF_TRANSLUCENT, // flags // killough 2/21/98
2754 S_NULL // raisestate
2755 },
2756
2757 { // MT_MISC14
2758 2025, // doomednum
2759 S_SUIT, // spawnstate
2760 1000, // spawnhealth
2761 S_NULL, // seestate
2762 sfx_None, // seesound
2763 8, // reactiontime
2764 sfx_None, // attacksound
2765 S_NULL, // painstate
2766 0, // painchance
2767 sfx_None, // painsound
2768 S_NULL, // meleestate
2769 S_NULL, // missilestate
2770 S_NULL, // deathstate
2771 S_NULL, // xdeathstate
2772 sfx_None, // deathsound
2773 0, // speed
2774 20*FRACUNIT, // radius
2775 16*FRACUNIT, // height
2776 100, // mass
2777 0, // damage
2778 sfx_None, // activesound
2779 MF_SPECIAL, // flags
2780 S_NULL // raisestate
2781 },
2782
2783 { // MT_MISC15
2784 2026, // doomednum
2785 S_PMAP, // spawnstate
2786 1000, // spawnhealth
2787 S_NULL, // seestate
2788 sfx_None, // seesound
2789 8, // reactiontime
2790 sfx_None, // attacksound
2791 S_NULL, // painstate
2792 0, // painchance
2793 sfx_None, // painsound
2794 S_NULL, // meleestate
2795 S_NULL, // missilestate
2796 S_NULL, // deathstate
2797 S_NULL, // xdeathstate
2798 sfx_None, // deathsound
2799 0, // speed
2800 20*FRACUNIT, // radius
2801 16*FRACUNIT, // height
2802 100, // mass
2803 0, // damage
2804 sfx_None, // activesound
2805 MF_SPECIAL|MF_COUNTITEM, // flags
2806 S_NULL // raisestate
2807 },
2808
2809 { // MT_MISC16
2810 2045, // doomednum
2811 S_PVIS, // spawnstate
2812 1000, // spawnhealth
2813 S_NULL, // seestate
2814 sfx_None, // seesound
2815 8, // reactiontime
2816 sfx_None, // attacksound
2817 S_NULL, // painstate
2818 0, // painchance
2819 sfx_None, // painsound
2820 S_NULL, // meleestate
2821 S_NULL, // missilestate
2822 S_NULL, // deathstate
2823 S_NULL, // xdeathstate
2824 sfx_None, // deathsound
2825 0, // speed
2826 20*FRACUNIT, // radius
2827 16*FRACUNIT, // height
2828 100, // mass
2829 0, // damage
2830 sfx_None, // activesound
2831 MF_SPECIAL|MF_COUNTITEM, // flags
2832 S_NULL // raisestate
2833 },
2834
2835 { // MT_MEGA
2836 83, // doomednum
2837 S_MEGA, // spawnstate
2838 1000, // spawnhealth
2839 S_NULL, // seestate
2840 sfx_None, // seesound
2841 8, // reactiontime
2842 sfx_None, // attacksound
2843 S_NULL, // painstate
2844 0, // painchance
2845 sfx_None, // painsound
2846 S_NULL, // meleestate
2847 S_NULL, // missilestate
2848 S_NULL, // deathstate
2849 S_NULL, // xdeathstate
2850 sfx_None, // deathsound
2851 0, // speed
2852 20*FRACUNIT, // radius
2853 16*FRACUNIT, // height
2854 100, // mass
2855 0, // damage
2856 sfx_None, // activesound
2857 MF_SPECIAL|MF_COUNTITEM|MF_TRANSLUCENT, // flags // killough 2/21/98
2858 S_NULL // raisestate
2859 },
2860
2861 { // MT_CLIP
2862 2007, // doomednum
2863 S_CLIP, // spawnstate
2864 1000, // spawnhealth
2865 S_NULL, // seestate
2866 sfx_None, // seesound
2867 8, // reactiontime
2868 sfx_None, // attacksound
2869 S_NULL, // painstate
2870 0, // painchance
2871 sfx_None, // painsound
2872 S_NULL, // meleestate
2873 S_NULL, // missilestate
2874 S_NULL, // deathstate
2875 S_NULL, // xdeathstate
2876 sfx_None, // deathsound
2877 0, // speed
2878 20*FRACUNIT, // radius
2879 16*FRACUNIT, // height
2880 100, // mass
2881 0, // damage
2882 sfx_None, // activesound
2883 MF_SPECIAL, // flags
2884 S_NULL // raisestate
2885 },
2886
2887 { // MT_MISC17
2888 2048, // doomednum
2889 S_AMMO, // spawnstate
2890 1000, // spawnhealth
2891 S_NULL, // seestate
2892 sfx_None, // seesound
2893 8, // reactiontime
2894 sfx_None, // attacksound
2895 S_NULL, // painstate
2896 0, // painchance
2897 sfx_None, // painsound
2898 S_NULL, // meleestate
2899 S_NULL, // missilestate
2900 S_NULL, // deathstate
2901 S_NULL, // xdeathstate
2902 sfx_None, // deathsound
2903 0, // speed
2904 20*FRACUNIT, // radius
2905 16*FRACUNIT, // height
2906 100, // mass
2907 0, // damage
2908 sfx_None, // activesound
2909 MF_SPECIAL, // flags
2910 S_NULL // raisestate
2911 },
2912
2913 { // MT_MISC18
2914 2010, // doomednum
2915 S_ROCK, // spawnstate
2916 1000, // spawnhealth
2917 S_NULL, // seestate
2918 sfx_None, // seesound
2919 8, // reactiontime
2920 sfx_None, // attacksound
2921 S_NULL, // painstate
2922 0, // painchance
2923 sfx_None, // painsound
2924 S_NULL, // meleestate
2925 S_NULL, // missilestate
2926 S_NULL, // deathstate
2927 S_NULL, // xdeathstate
2928 sfx_None, // deathsound
2929 0, // speed
2930 20*FRACUNIT, // radius
2931 16*FRACUNIT, // height
2932 100, // mass
2933 0, // damage
2934 sfx_None, // activesound
2935 MF_SPECIAL, // flags
2936 S_NULL // raisestate
2937 },
2938
2939 { // MT_MISC19
2940 2046, // doomednum
2941 S_BROK, // spawnstate
2942 1000, // spawnhealth
2943 S_NULL, // seestate
2944 sfx_None, // seesound
2945 8, // reactiontime
2946 sfx_None, // attacksound
2947 S_NULL, // painstate
2948 0, // painchance
2949 sfx_None, // painsound
2950 S_NULL, // meleestate
2951 S_NULL, // missilestate
2952 S_NULL, // deathstate
2953 S_NULL, // xdeathstate
2954 sfx_None, // deathsound
2955 0, // speed
2956 20*FRACUNIT, // radius
2957 16*FRACUNIT, // height
2958 100, // mass
2959 0, // damage
2960 sfx_None, // activesound
2961 MF_SPECIAL, // flags
2962 S_NULL // raisestate
2963 },
2964
2965 { // MT_MISC20
2966 2047, // doomednum
2967 S_CELL, // spawnstate
2968 1000, // spawnhealth
2969 S_NULL, // seestate
2970 sfx_None, // seesound
2971 8, // reactiontime
2972 sfx_None, // attacksound
2973 S_NULL, // painstate
2974 0, // painchance
2975 sfx_None, // painsound
2976 S_NULL, // meleestate
2977 S_NULL, // missilestate
2978 S_NULL, // deathstate
2979 S_NULL, // xdeathstate
2980 sfx_None, // deathsound
2981 0, // speed
2982 20*FRACUNIT, // radius
2983 16*FRACUNIT, // height
2984 100, // mass
2985 0, // damage
2986 sfx_None, // activesound
2987 MF_SPECIAL, // flags
2988 S_NULL // raisestate
2989 },
2990
2991 { // MT_MISC21
2992 17, // doomednum
2993 S_CELP, // spawnstate
2994 1000, // spawnhealth
2995 S_NULL, // seestate
2996 sfx_None, // seesound
2997 8, // reactiontime
2998 sfx_None, // attacksound
2999 S_NULL, // painstate
3000 0, // painchance
3001 sfx_None, // painsound
3002 S_NULL, // meleestate
3003 S_NULL, // missilestate
3004 S_NULL, // deathstate
3005 S_NULL, // xdeathstate
3006 sfx_None, // deathsound
3007 0, // speed
3008 20*FRACUNIT, // radius
3009 16*FRACUNIT, // height
3010 100, // mass
3011 0, // damage
3012 sfx_None, // activesound
3013 MF_SPECIAL, // flags
3014 S_NULL // raisestate
3015 },
3016
3017 { // MT_MISC22
3018 2008, // doomednum
3019 S_SHEL, // spawnstate
3020 1000, // spawnhealth
3021 S_NULL, // seestate
3022 sfx_None, // seesound
3023 8, // reactiontime
3024 sfx_None, // attacksound
3025 S_NULL, // painstate
3026 0, // painchance
3027 sfx_None, // painsound
3028 S_NULL, // meleestate
3029 S_NULL, // missilestate
3030 S_NULL, // deathstate
3031 S_NULL, // xdeathstate
3032 sfx_None, // deathsound
3033 0, // speed
3034 20*FRACUNIT, // radius
3035 16*FRACUNIT, // height
3036 100, // mass
3037 0, // damage
3038 sfx_None, // activesound
3039 MF_SPECIAL, // flags
3040 S_NULL // raisestate
3041 },
3042
3043 { // MT_MISC23
3044 2049, // doomednum
3045 S_SBOX, // spawnstate
3046 1000, // spawnhealth
3047 S_NULL, // seestate
3048 sfx_None, // seesound
3049 8, // reactiontime
3050 sfx_None, // attacksound
3051 S_NULL, // painstate
3052 0, // painchance
3053 sfx_None, // painsound
3054 S_NULL, // meleestate
3055 S_NULL, // missilestate
3056 S_NULL, // deathstate
3057 S_NULL, // xdeathstate
3058 sfx_None, // deathsound
3059 0, // speed
3060 20*FRACUNIT, // radius
3061 16*FRACUNIT, // height
3062 100, // mass
3063 0, // damage
3064 sfx_None, // activesound
3065 MF_SPECIAL, // flags
3066 S_NULL // raisestate
3067 },
3068
3069 { // MT_MISC24
3070 8, // doomednum
3071 S_BPAK, // spawnstate
3072 1000, // spawnhealth
3073 S_NULL, // seestate
3074 sfx_None, // seesound
3075 8, // reactiontime
3076 sfx_None, // attacksound
3077 S_NULL, // painstate
3078 0, // painchance
3079 sfx_None, // painsound
3080 S_NULL, // meleestate
3081 S_NULL, // missilestate
3082 S_NULL, // deathstate
3083 S_NULL, // xdeathstate
3084 sfx_None, // deathsound
3085 0, // speed
3086 20*FRACUNIT, // radius
3087 16*FRACUNIT, // height
3088 100, // mass
3089 0, // damage
3090 sfx_None, // activesound
3091 MF_SPECIAL, // flags
3092 S_NULL // raisestate
3093 },
3094
3095 { // MT_MISC25
3096 2006, // doomednum
3097 S_BFUG, // spawnstate
3098 1000, // spawnhealth
3099 S_NULL, // seestate
3100 sfx_None, // seesound
3101 8, // reactiontime
3102 sfx_None, // attacksound
3103 S_NULL, // painstate
3104 0, // painchance
3105 sfx_None, // painsound
3106 S_NULL, // meleestate
3107 S_NULL, // missilestate
3108 S_NULL, // deathstate
3109 S_NULL, // xdeathstate
3110 sfx_None, // deathsound
3111 0, // speed
3112 20*FRACUNIT, // radius
3113 16*FRACUNIT, // height
3114 100, // mass
3115 0, // damage
3116 sfx_None, // activesound
3117 MF_SPECIAL, // flags
3118 S_NULL // raisestate
3119 },
3120
3121 { // MT_CHAINGUN
3122 2002, // doomednum
3123 S_MGUN, // spawnstate
3124 1000, // spawnhealth
3125 S_NULL, // seestate
3126 sfx_None, // seesound
3127 8, // reactiontime
3128 sfx_None, // attacksound
3129 S_NULL, // painstate
3130 0, // painchance
3131 sfx_None, // painsound
3132 S_NULL, // meleestate
3133 S_NULL, // missilestate
3134 S_NULL, // deathstate
3135 S_NULL, // xdeathstate
3136 sfx_None, // deathsound
3137 0, // speed
3138 20*FRACUNIT, // radius
3139 16*FRACUNIT, // height
3140 100, // mass
3141 0, // damage
3142 sfx_None, // activesound
3143 MF_SPECIAL, // flags
3144 S_NULL // raisestate
3145 },
3146
3147 { // MT_MISC26
3148 2005, // doomednum
3149 S_CSAW, // spawnstate
3150 1000, // spawnhealth
3151 S_NULL, // seestate
3152 sfx_None, // seesound
3153 8, // reactiontime
3154 sfx_None, // attacksound
3155 S_NULL, // painstate
3156 0, // painchance
3157 sfx_None, // painsound
3158 S_NULL, // meleestate
3159 S_NULL, // missilestate
3160 S_NULL, // deathstate
3161 S_NULL, // xdeathstate
3162 sfx_None, // deathsound
3163 0, // speed
3164 20*FRACUNIT, // radius
3165 16*FRACUNIT, // height
3166 100, // mass
3167 0, // damage
3168 sfx_None, // activesound
3169 MF_SPECIAL, // flags
3170 S_NULL // raisestate
3171 },
3172
3173 { // MT_MISC27
3174 2003, // doomednum
3175 S_LAUN, // spawnstate
3176 1000, // spawnhealth
3177 S_NULL, // seestate
3178 sfx_None, // seesound
3179 8, // reactiontime
3180 sfx_None, // attacksound
3181 S_NULL, // painstate
3182 0, // painchance
3183 sfx_None, // painsound
3184 S_NULL, // meleestate
3185 S_NULL, // missilestate
3186 S_NULL, // deathstate
3187 S_NULL, // xdeathstate
3188 sfx_None, // deathsound
3189 0, // speed
3190 20*FRACUNIT, // radius
3191 16*FRACUNIT, // height
3192 100, // mass
3193 0, // damage
3194 sfx_None, // activesound
3195 MF_SPECIAL, // flags
3196 S_NULL // raisestate
3197 },
3198
3199 { // MT_MISC28
3200 2004, // doomednum
3201 S_PLAS, // spawnstate
3202 1000, // spawnhealth
3203 S_NULL, // seestate
3204 sfx_None, // seesound
3205 8, // reactiontime
3206 sfx_None, // attacksound
3207 S_NULL, // painstate
3208 0, // painchance
3209 sfx_None, // painsound
3210 S_NULL, // meleestate
3211 S_NULL, // missilestate
3212 S_NULL, // deathstate
3213 S_NULL, // xdeathstate
3214 sfx_None, // deathsound
3215 0, // speed
3216 20*FRACUNIT, // radius
3217 16*FRACUNIT, // height
3218 100, // mass
3219 0, // damage
3220 sfx_None, // activesound
3221 MF_SPECIAL, // flags
3222 S_NULL // raisestate
3223 },
3224
3225 { // MT_SHOTGUN
3226 2001, // doomednum
3227 S_SHOT, // spawnstate
3228 1000, // spawnhealth
3229 S_NULL, // seestate
3230 sfx_None, // seesound
3231 8, // reactiontime
3232 sfx_None, // attacksound
3233 S_NULL, // painstate
3234 0, // painchance
3235 sfx_None, // painsound
3236 S_NULL, // meleestate
3237 S_NULL, // missilestate
3238 S_NULL, // deathstate
3239 S_NULL, // xdeathstate
3240 sfx_None, // deathsound
3241 0, // speed
3242 20*FRACUNIT, // radius
3243 16*FRACUNIT, // height
3244 100, // mass
3245 0, // damage
3246 sfx_None, // activesound
3247 MF_SPECIAL, // flags
3248 S_NULL // raisestate
3249 },
3250
3251 { // MT_SUPERSHOTGUN
3252 82, // doomednum
3253 S_SHOT2, // spawnstate
3254 1000, // spawnhealth
3255 S_NULL, // seestate
3256 sfx_None, // seesound
3257 8, // reactiontime
3258 sfx_None, // attacksound
3259 S_NULL, // painstate
3260 0, // painchance
3261 sfx_None, // painsound
3262 S_NULL, // meleestate
3263 S_NULL, // missilestate
3264 S_NULL, // deathstate
3265 S_NULL, // xdeathstate
3266 sfx_None, // deathsound
3267 0, // speed
3268 20*FRACUNIT, // radius
3269 16*FRACUNIT, // height
3270 100, // mass
3271 0, // damage
3272 sfx_None, // activesound
3273 MF_SPECIAL, // flags
3274 S_NULL // raisestate
3275 },
3276
3277 { // MT_MISC29
3278 85, // doomednum
3279 S_TECHLAMP, // spawnstate
3280 1000, // spawnhealth
3281 S_NULL, // seestate
3282 sfx_None, // seesound
3283 8, // reactiontime
3284 sfx_None, // attacksound
3285 S_NULL, // painstate
3286 0, // painchance
3287 sfx_None, // painsound
3288 S_NULL, // meleestate
3289 S_NULL, // missilestate
3290 S_NULL, // deathstate
3291 S_NULL, // xdeathstate
3292 sfx_None, // deathsound
3293 0, // speed
3294 16*FRACUNIT, // radius
3295 16*FRACUNIT, // height
3296 100, // mass
3297 0, // damage
3298 sfx_None, // activesound
3299 MF_SOLID, // flags
3300 S_NULL // raisestate
3301 },
3302
3303 { // MT_MISC30
3304 86, // doomednum
3305 S_TECH2LAMP, // spawnstate
3306 1000, // spawnhealth
3307 S_NULL, // seestate
3308 sfx_None, // seesound
3309 8, // reactiontime
3310 sfx_None, // attacksound
3311 S_NULL, // painstate
3312 0, // painchance
3313 sfx_None, // painsound
3314 S_NULL, // meleestate
3315 S_NULL, // missilestate
3316 S_NULL, // deathstate
3317 S_NULL, // xdeathstate
3318 sfx_None, // deathsound
3319 0, // speed
3320 16*FRACUNIT, // radius
3321 16*FRACUNIT, // height
3322 100, // mass
3323 0, // damage
3324 sfx_None, // activesound
3325 MF_SOLID, // flags
3326 S_NULL // raisestate
3327 },
3328
3329 { // MT_MISC31
3330 2028, // doomednum
3331 S_COLU, // spawnstate
3332 1000, // spawnhealth
3333 S_NULL, // seestate
3334 sfx_None, // seesound
3335 8, // reactiontime
3336 sfx_None, // attacksound
3337 S_NULL, // painstate
3338 0, // painchance
3339 sfx_None, // painsound
3340 S_NULL, // meleestate
3341 S_NULL, // missilestate
3342 S_NULL, // deathstate
3343 S_NULL, // xdeathstate
3344 sfx_None, // deathsound
3345 0, // speed
3346 16*FRACUNIT, // radius
3347 16*FRACUNIT, // height
3348 100, // mass
3349 0, // damage
3350 sfx_None, // activesound
3351 MF_SOLID, // flags
3352 S_NULL // raisestate
3353 },
3354
3355 { // MT_MISC32
3356 30, // doomednum
3357 S_TALLGRNCOL, // spawnstate
3358 1000, // spawnhealth
3359 S_NULL, // seestate
3360 sfx_None, // seesound
3361 8, // reactiontime
3362 sfx_None, // attacksound
3363 S_NULL, // painstate
3364 0, // painchance
3365 sfx_None, // painsound
3366 S_NULL, // meleestate
3367 S_NULL, // missilestate
3368 S_NULL, // deathstate
3369 S_NULL, // xdeathstate
3370 sfx_None, // deathsound
3371 0, // speed
3372 16*FRACUNIT, // radius
3373 16*FRACUNIT, // height
3374 100, // mass
3375 0, // damage
3376 sfx_None, // activesound
3377 MF_SOLID, // flags
3378 S_NULL // raisestate
3379 },
3380
3381 { // MT_MISC33
3382 31, // doomednum
3383 S_SHRTGRNCOL, // spawnstate
3384 1000, // spawnhealth
3385 S_NULL, // seestate
3386 sfx_None, // seesound
3387 8, // reactiontime
3388 sfx_None, // attacksound
3389 S_NULL, // painstate
3390 0, // painchance
3391 sfx_None, // painsound
3392 S_NULL, // meleestate
3393 S_NULL, // missilestate
3394 S_NULL, // deathstate
3395 S_NULL, // xdeathstate
3396 sfx_None, // deathsound
3397 0, // speed
3398 16*FRACUNIT, // radius
3399 16*FRACUNIT, // height
3400 100, // mass
3401 0, // damage
3402 sfx_None, // activesound
3403 MF_SOLID, // flags
3404 S_NULL // raisestate
3405 },
3406
3407 { // MT_MISC34
3408 32, // doomednum
3409 S_TALLREDCOL, // spawnstate
3410 1000, // spawnhealth
3411 S_NULL, // seestate
3412 sfx_None, // seesound
3413 8, // reactiontime
3414 sfx_None, // attacksound
3415 S_NULL, // painstate
3416 0, // painchance
3417 sfx_None, // painsound
3418 S_NULL, // meleestate
3419 S_NULL, // missilestate
3420 S_NULL, // deathstate
3421 S_NULL, // xdeathstate
3422 sfx_None, // deathsound
3423 0, // speed
3424 16*FRACUNIT, // radius
3425 16*FRACUNIT, // height
3426 100, // mass
3427 0, // damage
3428 sfx_None, // activesound
3429 MF_SOLID, // flags
3430 S_NULL // raisestate
3431 },
3432
3433 { // MT_MISC35
3434 33, // doomednum
3435 S_SHRTREDCOL, // spawnstate
3436 1000, // spawnhealth
3437 S_NULL, // seestate
3438 sfx_None, // seesound
3439 8, // reactiontime
3440 sfx_None, // attacksound
3441 S_NULL, // painstate
3442 0, // painchance
3443 sfx_None, // painsound
3444 S_NULL, // meleestate
3445 S_NULL, // missilestate
3446 S_NULL, // deathstate
3447 S_NULL, // xdeathstate
3448 sfx_None, // deathsound
3449 0, // speed
3450 16*FRACUNIT, // radius
3451 16*FRACUNIT, // height
3452 100, // mass
3453 0, // damage
3454 sfx_None, // activesound
3455 MF_SOLID, // flags
3456 S_NULL // raisestate
3457 },
3458
3459 { // MT_MISC36
3460 37, // doomednum
3461 S_SKULLCOL, // spawnstate
3462 1000, // spawnhealth
3463 S_NULL, // seestate
3464 sfx_None, // seesound
3465 8, // reactiontime
3466 sfx_None, // attacksound
3467 S_NULL, // painstate
3468 0, // painchance
3469 sfx_None, // painsound
3470 S_NULL, // meleestate
3471 S_NULL, // missilestate
3472 S_NULL, // deathstate
3473 S_NULL, // xdeathstate
3474 sfx_None, // deathsound
3475 0, // speed
3476 16*FRACUNIT, // radius
3477 16*FRACUNIT, // height
3478 100, // mass
3479 0, // damage
3480 sfx_None, // activesound
3481 MF_SOLID, // flags
3482 S_NULL // raisestate
3483 },
3484
3485 { // MT_MISC37
3486 36, // doomednum
3487 S_HEARTCOL, // spawnstate
3488 1000, // spawnhealth
3489 S_NULL, // seestate
3490 sfx_None, // seesound
3491 8, // reactiontime
3492 sfx_None, // attacksound
3493 S_NULL, // painstate
3494 0, // painchance
3495 sfx_None, // painsound
3496 S_NULL, // meleestate
3497 S_NULL, // missilestate
3498 S_NULL, // deathstate
3499 S_NULL, // xdeathstate
3500 sfx_None, // deathsound
3501 0, // speed
3502 16*FRACUNIT, // radius
3503 16*FRACUNIT, // height
3504 100, // mass
3505 0, // damage
3506 sfx_None, // activesound
3507 MF_SOLID, // flags
3508 S_NULL // raisestate
3509 },
3510
3511 { // MT_MISC38
3512 41, // doomednum
3513 S_EVILEYE, // spawnstate
3514 1000, // spawnhealth
3515 S_NULL, // seestate
3516 sfx_None, // seesound
3517 8, // reactiontime
3518 sfx_None, // attacksound
3519 S_NULL, // painstate
3520 0, // painchance
3521 sfx_None, // painsound
3522 S_NULL, // meleestate
3523 S_NULL, // missilestate
3524 S_NULL, // deathstate
3525 S_NULL, // xdeathstate
3526 sfx_None, // deathsound
3527 0, // speed
3528 16*FRACUNIT, // radius
3529 16*FRACUNIT, // height
3530 100, // mass
3531 0, // damage
3532 sfx_None, // activesound
3533 MF_SOLID, // flags
3534 S_NULL // raisestate
3535 },
3536
3537 { // MT_MISC39
3538 42, // doomednum
3539 S_FLOATSKULL, // spawnstate
3540 1000, // spawnhealth
3541 S_NULL, // seestate
3542 sfx_None, // seesound
3543 8, // reactiontime
3544 sfx_None, // attacksound
3545 S_NULL, // painstate
3546 0, // painchance
3547 sfx_None, // painsound
3548 S_NULL, // meleestate
3549 S_NULL, // missilestate
3550 S_NULL, // deathstate
3551 S_NULL, // xdeathstate
3552 sfx_None, // deathsound
3553 0, // speed
3554 16*FRACUNIT, // radius
3555 16*FRACUNIT, // height
3556 100, // mass
3557 0, // damage
3558 sfx_None, // activesound
3559 MF_SOLID, // flags
3560 S_NULL // raisestate
3561 },
3562
3563 { // MT_MISC40
3564 43, // doomednum
3565 S_TORCHTREE, // spawnstate
3566 1000, // spawnhealth
3567 S_NULL, // seestate
3568 sfx_None, // seesound
3569 8, // reactiontime
3570 sfx_None, // attacksound
3571 S_NULL, // painstate
3572 0, // painchance
3573 sfx_None, // painsound
3574 S_NULL, // meleestate
3575 S_NULL, // missilestate
3576 S_NULL, // deathstate
3577 S_NULL, // xdeathstate
3578 sfx_None, // deathsound
3579 0, // speed
3580 16*FRACUNIT, // radius
3581 16*FRACUNIT, // height
3582 100, // mass
3583 0, // damage
3584 sfx_None, // activesound
3585 MF_SOLID, // flags
3586 S_NULL // raisestate
3587 },
3588
3589 { // MT_MISC41
3590 44, // doomednum
3591 S_BLUETORCH, // spawnstate
3592 1000, // spawnhealth
3593 S_NULL, // seestate
3594 sfx_None, // seesound
3595 8, // reactiontime
3596 sfx_None, // attacksound
3597 S_NULL, // painstate
3598 0, // painchance
3599 sfx_None, // painsound
3600 S_NULL, // meleestate
3601 S_NULL, // missilestate
3602 S_NULL, // deathstate
3603 S_NULL, // xdeathstate
3604 sfx_None, // deathsound
3605 0, // speed
3606 16*FRACUNIT, // radius
3607 16*FRACUNIT, // height
3608 100, // mass
3609 0, // damage
3610 sfx_None, // activesound
3611 MF_SOLID, // flags
3612 S_NULL // raisestate
3613 },
3614
3615 { // MT_MISC42
3616 45, // doomednum
3617 S_GREENTORCH, // spawnstate
3618 1000, // spawnhealth
3619 S_NULL, // seestate
3620 sfx_None, // seesound
3621 8, // reactiontime
3622 sfx_None, // attacksound
3623 S_NULL, // painstate
3624 0, // painchance
3625 sfx_None, // painsound
3626 S_NULL, // meleestate
3627 S_NULL, // missilestate
3628 S_NULL, // deathstate
3629 S_NULL, // xdeathstate
3630 sfx_None, // deathsound
3631 0, // speed
3632 16*FRACUNIT, // radius
3633 16*FRACUNIT, // height
3634 100, // mass
3635 0, // damage
3636 sfx_None, // activesound
3637 MF_SOLID, // flags
3638 S_NULL // raisestate
3639 },
3640
3641 { // MT_MISC43
3642 46, // doomednum
3643 S_REDTORCH, // spawnstate
3644 1000, // spawnhealth
3645 S_NULL, // seestate
3646 sfx_None, // seesound
3647 8, // reactiontime
3648 sfx_None, // attacksound
3649 S_NULL, // painstate
3650 0, // painchance
3651 sfx_None, // painsound
3652 S_NULL, // meleestate
3653 S_NULL, // missilestate
3654 S_NULL, // deathstate
3655 S_NULL, // xdeathstate
3656 sfx_None, // deathsound
3657 0, // speed
3658 16*FRACUNIT, // radius
3659 16*FRACUNIT, // height
3660 100, // mass
3661 0, // damage
3662 sfx_None, // activesound
3663 MF_SOLID, // flags
3664 S_NULL // raisestate
3665 },
3666
3667 { // MT_MISC44
3668 55, // doomednum
3669 S_BTORCHSHRT, // spawnstate
3670 1000, // spawnhealth
3671 S_NULL, // seestate
3672 sfx_None, // seesound
3673 8, // reactiontime
3674 sfx_None, // attacksound
3675 S_NULL, // painstate
3676 0, // painchance
3677 sfx_None, // painsound
3678 S_NULL, // meleestate
3679 S_NULL, // missilestate
3680 S_NULL, // deathstate
3681 S_NULL, // xdeathstate
3682 sfx_None, // deathsound
3683 0, // speed
3684 16*FRACUNIT, // radius
3685 16*FRACUNIT, // height
3686 100, // mass
3687 0, // damage
3688 sfx_None, // activesound
3689 MF_SOLID, // flags
3690 S_NULL // raisestate
3691 },
3692
3693 { // MT_MISC45
3694 56, // doomednum
3695 S_GTORCHSHRT, // spawnstate
3696 1000, // spawnhealth
3697 S_NULL, // seestate
3698 sfx_None, // seesound
3699 8, // reactiontime
3700 sfx_None, // attacksound
3701 S_NULL, // painstate
3702 0, // painchance
3703 sfx_None, // painsound
3704 S_NULL, // meleestate
3705 S_NULL, // missilestate
3706 S_NULL, // deathstate
3707 S_NULL, // xdeathstate
3708 sfx_None, // deathsound
3709 0, // speed
3710 16*FRACUNIT, // radius
3711 16*FRACUNIT, // height
3712 100, // mass
3713 0, // damage
3714 sfx_None, // activesound
3715 MF_SOLID, // flags
3716 S_NULL // raisestate
3717 },
3718
3719 { // MT_MISC46
3720 57, // doomednum
3721 S_RTORCHSHRT, // spawnstate
3722 1000, // spawnhealth
3723 S_NULL, // seestate
3724 sfx_None, // seesound
3725 8, // reactiontime
3726 sfx_None, // attacksound
3727 S_NULL, // painstate
3728 0, // painchance
3729 sfx_None, // painsound
3730 S_NULL, // meleestate
3731 S_NULL, // missilestate
3732 S_NULL, // deathstate
3733 S_NULL, // xdeathstate
3734 sfx_None, // deathsound
3735 0, // speed
3736 16*FRACUNIT, // radius
3737 16*FRACUNIT, // height
3738 100, // mass
3739 0, // damage
3740 sfx_None, // activesound
3741 MF_SOLID, // flags
3742 S_NULL // raisestate
3743 },
3744
3745 { // MT_MISC47
3746 47, // doomednum
3747 S_STALAGTITE, // spawnstate
3748 1000, // spawnhealth
3749 S_NULL, // seestate
3750 sfx_None, // seesound
3751 8, // reactiontime
3752 sfx_None, // attacksound
3753 S_NULL, // painstate
3754 0, // painchance
3755 sfx_None, // painsound
3756 S_NULL, // meleestate
3757 S_NULL, // missilestate
3758 S_NULL, // deathstate
3759 S_NULL, // xdeathstate
3760 sfx_None, // deathsound
3761 0, // speed
3762 16*FRACUNIT, // radius
3763 16*FRACUNIT, // height
3764 100, // mass
3765 0, // damage
3766 sfx_None, // activesound
3767 MF_SOLID, // flags
3768 S_NULL // raisestate
3769 },
3770
3771 { // MT_MISC48
3772 48, // doomednum
3773 S_TECHPILLAR, // spawnstate
3774 1000, // spawnhealth
3775 S_NULL, // seestate
3776 sfx_None, // seesound
3777 8, // reactiontime
3778 sfx_None, // attacksound
3779 S_NULL, // painstate
3780 0, // painchance
3781 sfx_None, // painsound
3782 S_NULL, // meleestate
3783 S_NULL, // missilestate
3784 S_NULL, // deathstate
3785 S_NULL, // xdeathstate
3786 sfx_None, // deathsound
3787 0, // speed
3788 16*FRACUNIT, // radius
3789 16*FRACUNIT, // height
3790 100, // mass
3791 0, // damage
3792 sfx_None, // activesound
3793 MF_SOLID, // flags
3794 S_NULL // raisestate
3795 },
3796
3797 { // MT_MISC49
3798 34, // doomednum
3799 S_CANDLESTIK, // spawnstate
3800 1000, // spawnhealth
3801 S_NULL, // seestate
3802 sfx_None, // seesound
3803 8, // reactiontime
3804 sfx_None, // attacksound
3805 S_NULL, // painstate
3806 0, // painchance
3807 sfx_None, // painsound
3808 S_NULL, // meleestate
3809 S_NULL, // missilestate
3810 S_NULL, // deathstate
3811 S_NULL, // xdeathstate
3812 sfx_None, // deathsound
3813 0, // speed
3814 20*FRACUNIT, // radius
3815 16*FRACUNIT, // height
3816 100, // mass
3817 0, // damage
3818 sfx_None, // activesound
3819 0, // flags
3820 S_NULL // raisestate
3821 },
3822
3823 { // MT_MISC50
3824 35, // doomednum
3825 S_CANDELABRA, // spawnstate
3826 1000, // spawnhealth
3827 S_NULL, // seestate
3828 sfx_None, // seesound
3829 8, // reactiontime
3830 sfx_None, // attacksound
3831 S_NULL, // painstate
3832 0, // painchance
3833 sfx_None, // painsound
3834 S_NULL, // meleestate
3835 S_NULL, // missilestate
3836 S_NULL, // deathstate
3837 S_NULL, // xdeathstate
3838 sfx_None, // deathsound
3839 0, // speed
3840 16*FRACUNIT, // radius
3841 16*FRACUNIT, // height
3842 100, // mass
3843 0, // damage
3844 sfx_None, // activesound
3845 MF_SOLID, // flags
3846 S_NULL // raisestate
3847 },
3848
3849 { // MT_MISC51
3850 49, // doomednum
3851 S_BLOODYTWITCH, // spawnstate
3852 1000, // spawnhealth
3853 S_NULL, // seestate
3854 sfx_None, // seesound
3855 8, // reactiontime
3856 sfx_None, // attacksound
3857 S_NULL, // painstate
3858 0, // painchance
3859 sfx_None, // painsound
3860 S_NULL, // meleestate
3861 S_NULL, // missilestate
3862 S_NULL, // deathstate
3863 S_NULL, // xdeathstate
3864 sfx_None, // deathsound
3865 0, // speed
3866 16*FRACUNIT, // radius
3867 68*FRACUNIT, // height
3868 100, // mass
3869 0, // damage
3870 sfx_None, // activesound
3871 MF_SOLID|MF_SPAWNCEILING|MF_NOGRAVITY, // flags
3872 S_NULL // raisestate
3873 },
3874
3875 { // MT_MISC52
3876 50, // doomednum
3877 S_MEAT2, // spawnstate
3878 1000, // spawnhealth
3879 S_NULL, // seestate
3880 sfx_None, // seesound
3881 8, // reactiontime
3882 sfx_None, // attacksound
3883 S_NULL, // painstate
3884 0, // painchance
3885 sfx_None, // painsound
3886 S_NULL, // meleestate
3887 S_NULL, // missilestate
3888 S_NULL, // deathstate
3889 S_NULL, // xdeathstate
3890 sfx_None, // deathsound
3891 0, // speed
3892 16*FRACUNIT, // radius
3893 84*FRACUNIT, // height
3894 100, // mass
3895 0, // damage
3896 sfx_None, // activesound
3897 MF_SOLID|MF_SPAWNCEILING|MF_NOGRAVITY, // flags
3898 S_NULL // raisestate
3899 },
3900
3901 { // MT_MISC53
3902 51, // doomednum
3903 S_MEAT3, // spawnstate
3904 1000, // spawnhealth
3905 S_NULL, // seestate
3906 sfx_None, // seesound
3907 8, // reactiontime
3908 sfx_None, // attacksound
3909 S_NULL, // painstate
3910 0, // painchance
3911 sfx_None, // painsound
3912 S_NULL, // meleestate
3913 S_NULL, // missilestate
3914 S_NULL, // deathstate
3915 S_NULL, // xdeathstate
3916 sfx_None, // deathsound
3917 0, // speed
3918 16*FRACUNIT, // radius
3919 84*FRACUNIT, // height
3920 100, // mass
3921 0, // damage
3922 sfx_None, // activesound
3923 MF_SOLID|MF_SPAWNCEILING|MF_NOGRAVITY, // flags
3924 S_NULL // raisestate
3925 },
3926
3927 { // MT_MISC54
3928 52, // doomednum
3929 S_MEAT4, // spawnstate
3930 1000, // spawnhealth
3931 S_NULL, // seestate
3932 sfx_None, // seesound
3933 8, // reactiontime
3934 sfx_None, // attacksound
3935 S_NULL, // painstate
3936 0, // painchance
3937 sfx_None, // painsound
3938 S_NULL, // meleestate
3939 S_NULL, // missilestate
3940 S_NULL, // deathstate
3941 S_NULL, // xdeathstate
3942 sfx_None, // deathsound
3943 0, // speed
3944 16*FRACUNIT, // radius
3945 68*FRACUNIT, // height
3946 100, // mass
3947 0, // damage
3948 sfx_None, // activesound
3949 MF_SOLID|MF_SPAWNCEILING|MF_NOGRAVITY, // flags
3950 S_NULL // raisestate
3951 },
3952
3953 { // MT_MISC55
3954 53, // doomednum
3955 S_MEAT5, // spawnstate
3956 1000, // spawnhealth
3957 S_NULL, // seestate
3958 sfx_None, // seesound
3959 8, // reactiontime
3960 sfx_None, // attacksound
3961 S_NULL, // painstate
3962 0, // painchance
3963 sfx_None, // painsound
3964 S_NULL, // meleestate
3965 S_NULL, // missilestate
3966 S_NULL, // deathstate
3967 S_NULL, // xdeathstate
3968 sfx_None, // deathsound
3969 0, // speed
3970 16*FRACUNIT, // radius
3971 52*FRACUNIT, // height
3972 100, // mass
3973 0, // damage
3974 sfx_None, // activesound
3975 MF_SOLID|MF_SPAWNCEILING|MF_NOGRAVITY, // flags
3976 S_NULL // raisestate
3977 },
3978
3979 { // MT_MISC56
3980 59, // doomednum
3981 S_MEAT2, // spawnstate
3982 1000, // spawnhealth
3983 S_NULL, // seestate
3984 sfx_None, // seesound
3985 8, // reactiontime
3986 sfx_None, // attacksound
3987 S_NULL, // painstate
3988 0, // painchance
3989 sfx_None, // painsound
3990 S_NULL, // meleestate
3991 S_NULL, // missilestate
3992 S_NULL, // deathstate
3993 S_NULL, // xdeathstate
3994 sfx_None, // deathsound
3995 0, // speed
3996 20*FRACUNIT, // radius
3997 84*FRACUNIT, // height
3998 100, // mass
3999 0, // damage
4000 sfx_None, // activesound
4001 MF_SPAWNCEILING|MF_NOGRAVITY, // flags
4002 S_NULL // raisestate
4003 },
4004
4005 { // MT_MISC57
4006 60, // doomednum
4007 S_MEAT4, // spawnstate
4008 1000, // spawnhealth
4009 S_NULL, // seestate
4010 sfx_None, // seesound
4011 8, // reactiontime
4012 sfx_None, // attacksound
4013 S_NULL, // painstate
4014 0, // painchance
4015 sfx_None, // painsound
4016 S_NULL, // meleestate
4017 S_NULL, // missilestate
4018 S_NULL, // deathstate
4019 S_NULL, // xdeathstate
4020 sfx_None, // deathsound
4021 0, // speed
4022 20*FRACUNIT, // radius
4023 68*FRACUNIT, // height
4024 100, // mass
4025 0, // damage
4026 sfx_None, // activesound
4027 MF_SPAWNCEILING|MF_NOGRAVITY, // flags
4028 S_NULL // raisestate
4029 },
4030
4031 { // MT_MISC58
4032 61, // doomednum
4033 S_MEAT3, // spawnstate
4034 1000, // spawnhealth
4035 S_NULL, // seestate
4036 sfx_None, // seesound
4037 8, // reactiontime
4038 sfx_None, // attacksound
4039 S_NULL, // painstate
4040 0, // painchance
4041 sfx_None, // painsound
4042 S_NULL, // meleestate
4043 S_NULL, // missilestate
4044 S_NULL, // deathstate
4045 S_NULL, // xdeathstate
4046 sfx_None, // deathsound
4047 0, // speed
4048 20*FRACUNIT, // radius
4049 52*FRACUNIT, // height
4050 100, // mass
4051 0, // damage
4052 sfx_None, // activesound
4053 MF_SPAWNCEILING|MF_NOGRAVITY, // flags
4054 S_NULL // raisestate
4055 },
4056
4057 { // MT_MISC59
4058 62, // doomednum
4059 S_MEAT5, // spawnstate
4060 1000, // spawnhealth
4061 S_NULL, // seestate
4062 sfx_None, // seesound
4063 8, // reactiontime
4064 sfx_None, // attacksound
4065 S_NULL, // painstate
4066 0, // painchance
4067 sfx_None, // painsound
4068 S_NULL, // meleestate
4069 S_NULL, // missilestate
4070 S_NULL, // deathstate
4071 S_NULL, // xdeathstate
4072 sfx_None, // deathsound
4073 0, // speed
4074 20*FRACUNIT, // radius
4075 52*FRACUNIT, // height
4076 100, // mass
4077 0, // damage
4078 sfx_None, // activesound
4079 MF_SPAWNCEILING|MF_NOGRAVITY, // flags
4080 S_NULL // raisestate
4081 },
4082
4083 { // MT_MISC60
4084 63, // doomednum
4085 S_BLOODYTWITCH, // spawnstate
4086 1000, // spawnhealth
4087 S_NULL, // seestate
4088 sfx_None, // seesound
4089 8, // reactiontime
4090 sfx_None, // attacksound
4091 S_NULL, // painstate
4092 0, // painchance
4093 sfx_None, // painsound
4094 S_NULL, // meleestate
4095 S_NULL, // missilestate
4096 S_NULL, // deathstate
4097 S_NULL, // xdeathstate
4098 sfx_None, // deathsound
4099 0, // speed
4100 20*FRACUNIT, // radius
4101 68*FRACUNIT, // height
4102 100, // mass
4103 0, // damage
4104 sfx_None, // activesound
4105 MF_SPAWNCEILING|MF_NOGRAVITY, // flags
4106 S_NULL // raisestate
4107 },
4108
4109 { // MT_MISC61
4110 22, // doomednum
4111 S_HEAD_DIE6, // spawnstate
4112 1000, // spawnhealth
4113 S_NULL, // seestate
4114 sfx_None, // seesound
4115 8, // reactiontime
4116 sfx_None, // attacksound
4117 S_NULL, // painstate
4118 0, // painchance
4119 sfx_None, // painsound
4120 S_NULL, // meleestate
4121 S_NULL, // missilestate
4122 S_NULL, // deathstate
4123 S_NULL, // xdeathstate
4124 sfx_None, // deathsound
4125 0, // speed
4126 20*FRACUNIT, // radius
4127 16*FRACUNIT, // height
4128 100, // mass
4129 0, // damage
4130 sfx_None, // activesound
4131 0, // flags
4132 S_NULL // raisestate
4133 },
4134
4135 { // MT_MISC62
4136 15, // doomednum
4137 S_PLAY_DIE7, // spawnstate
4138 1000, // spawnhealth
4139 S_NULL, // seestate
4140 sfx_None, // seesound
4141 8, // reactiontime
4142 sfx_None, // attacksound
4143 S_NULL, // painstate
4144 0, // painchance
4145 sfx_None, // painsound
4146 S_NULL, // meleestate
4147 S_NULL, // missilestate
4148 S_NULL, // deathstate
4149 S_NULL, // xdeathstate
4150 sfx_None, // deathsound
4151 0, // speed
4152 20*FRACUNIT, // radius
4153 16*FRACUNIT, // height
4154 100, // mass
4155 0, // damage
4156 sfx_None, // activesound
4157 0, // flags
4158 S_NULL // raisestate
4159 },
4160
4161 { // MT_MISC63
4162 18, // doomednum
4163 S_POSS_DIE5, // spawnstate
4164 1000, // spawnhealth
4165 S_NULL, // seestate
4166 sfx_None, // seesound
4167 8, // reactiontime
4168 sfx_None, // attacksound
4169 S_NULL, // painstate
4170 0, // painchance
4171 sfx_None, // painsound
4172 S_NULL, // meleestate
4173 S_NULL, // missilestate
4174 S_NULL, // deathstate
4175 S_NULL, // xdeathstate
4176 sfx_None, // deathsound
4177 0, // speed
4178 20*FRACUNIT, // radius
4179 16*FRACUNIT, // height
4180 100, // mass
4181 0, // damage
4182 sfx_None, // activesound
4183 0, // flags
4184 S_NULL // raisestate
4185 },
4186
4187 { // MT_MISC64
4188 21, // doomednum
4189 S_SARG_DIE6, // spawnstate
4190 1000, // spawnhealth
4191 S_NULL, // seestate
4192 sfx_None, // seesound
4193 8, // reactiontime
4194 sfx_None, // attacksound
4195 S_NULL, // painstate
4196 0, // painchance
4197 sfx_None, // painsound
4198 S_NULL, // meleestate
4199 S_NULL, // missilestate
4200 S_NULL, // deathstate
4201 S_NULL, // xdeathstate
4202 sfx_None, // deathsound
4203 0, // speed
4204 20*FRACUNIT, // radius
4205 16*FRACUNIT, // height
4206 100, // mass
4207 0, // damage
4208 sfx_None, // activesound
4209 0, // flags
4210 S_NULL // raisestate
4211 },
4212
4213 { // MT_MISC65
4214 23, // doomednum
4215 S_SKULL_DIE6, // spawnstate
4216 1000, // spawnhealth
4217 S_NULL, // seestate
4218 sfx_None, // seesound
4219 8, // reactiontime
4220 sfx_None, // attacksound
4221 S_NULL, // painstate
4222 0, // painchance
4223 sfx_None, // painsound
4224 S_NULL, // meleestate
4225 S_NULL, // missilestate
4226 S_NULL, // deathstate
4227 S_NULL, // xdeathstate
4228 sfx_None, // deathsound
4229 0, // speed
4230 20*FRACUNIT, // radius
4231 16*FRACUNIT, // height
4232 100, // mass
4233 0, // damage
4234 sfx_None, // activesound
4235 0, // flags
4236 S_NULL // raisestate
4237 },
4238
4239 { // MT_MISC66
4240 20, // doomednum
4241 S_TROO_DIE5, // spawnstate
4242 1000, // spawnhealth
4243 S_NULL, // seestate
4244 sfx_None, // seesound
4245 8, // reactiontime
4246 sfx_None, // attacksound
4247 S_NULL, // painstate
4248 0, // painchance
4249 sfx_None, // painsound
4250 S_NULL, // meleestate
4251 S_NULL, // missilestate
4252 S_NULL, // deathstate
4253 S_NULL, // xdeathstate
4254 sfx_None, // deathsound
4255 0, // speed
4256 20*FRACUNIT, // radius
4257 16*FRACUNIT, // height
4258 100, // mass
4259 0, // damage
4260 sfx_None, // activesound
4261 0, // flags
4262 S_NULL // raisestate
4263 },
4264
4265 { // MT_MISC67
4266 19, // doomednum
4267 S_SPOS_DIE5, // spawnstate
4268 1000, // spawnhealth
4269 S_NULL, // seestate
4270 sfx_None, // seesound
4271 8, // reactiontime
4272 sfx_None, // attacksound
4273 S_NULL, // painstate
4274 0, // painchance
4275 sfx_None, // painsound
4276 S_NULL, // meleestate
4277 S_NULL, // missilestate
4278 S_NULL, // deathstate
4279 S_NULL, // xdeathstate
4280 sfx_None, // deathsound
4281 0, // speed
4282 20*FRACUNIT, // radius
4283 16*FRACUNIT, // height
4284 100, // mass
4285 0, // damage
4286 sfx_None, // activesound
4287 0, // flags
4288 S_NULL // raisestate
4289 },
4290
4291 { // MT_MISC68
4292 10, // doomednum
4293 S_PLAY_XDIE9, // spawnstate
4294 1000, // spawnhealth
4295 S_NULL, // seestate
4296 sfx_None, // seesound
4297 8, // reactiontime
4298 sfx_None, // attacksound
4299 S_NULL, // painstate
4300 0, // painchance
4301 sfx_None, // painsound
4302 S_NULL, // meleestate
4303 S_NULL, // missilestate
4304 S_NULL, // deathstate
4305 S_NULL, // xdeathstate
4306 sfx_None, // deathsound
4307 0, // speed
4308 20*FRACUNIT, // radius
4309 16*FRACUNIT, // height
4310 100, // mass
4311 0, // damage
4312 sfx_None, // activesound
4313 0, // flags
4314 S_NULL // raisestate
4315 },
4316
4317 { // MT_MISC69
4318 12, // doomednum
4319 S_PLAY_XDIE9, // spawnstate
4320 1000, // spawnhealth
4321 S_NULL, // seestate
4322 sfx_None, // seesound
4323 8, // reactiontime
4324 sfx_None, // attacksound
4325 S_NULL, // painstate
4326 0, // painchance
4327 sfx_None, // painsound
4328 S_NULL, // meleestate
4329 S_NULL, // missilestate
4330 S_NULL, // deathstate
4331 S_NULL, // xdeathstate
4332 sfx_None, // deathsound
4333 0, // speed
4334 20*FRACUNIT, // radius
4335 16*FRACUNIT, // height
4336 100, // mass
4337 0, // damage
4338 sfx_None, // activesound
4339 0, // flags
4340 S_NULL // raisestate
4341 },
4342
4343 { // MT_MISC70
4344 28, // doomednum
4345 S_HEADSONSTICK, // spawnstate
4346 1000, // spawnhealth
4347 S_NULL, // seestate
4348 sfx_None, // seesound
4349 8, // reactiontime
4350 sfx_None, // attacksound
4351 S_NULL, // painstate
4352 0, // painchance
4353 sfx_None, // painsound
4354 S_NULL, // meleestate
4355 S_NULL, // missilestate
4356 S_NULL, // deathstate
4357 S_NULL, // xdeathstate
4358 sfx_None, // deathsound
4359 0, // speed
4360 16*FRACUNIT, // radius
4361 16*FRACUNIT, // height
4362 100, // mass
4363 0, // damage
4364 sfx_None, // activesound
4365 MF_SOLID, // flags
4366 S_NULL // raisestate
4367 },
4368
4369 { // MT_MISC71
4370 24, // doomednum
4371 S_GIBS, // spawnstate
4372 1000, // spawnhealth
4373 S_NULL, // seestate
4374 sfx_None, // seesound
4375 8, // reactiontime
4376 sfx_None, // attacksound
4377 S_NULL, // painstate
4378 0, // painchance
4379 sfx_None, // painsound
4380 S_NULL, // meleestate
4381 S_NULL, // missilestate
4382 S_NULL, // deathstate
4383 S_NULL, // xdeathstate
4384 sfx_None, // deathsound
4385 0, // speed
4386 20*FRACUNIT, // radius
4387 16*FRACUNIT, // height
4388 100, // mass
4389 0, // damage
4390 sfx_None, // activesound
4391 0, // flags
4392 S_NULL // raisestate
4393 },
4394
4395 { // MT_MISC72
4396 27, // doomednum
4397 S_HEADONASTICK, // spawnstate
4398 1000, // spawnhealth
4399 S_NULL, // seestate
4400 sfx_None, // seesound
4401 8, // reactiontime
4402 sfx_None, // attacksound
4403 S_NULL, // painstate
4404 0, // painchance
4405 sfx_None, // painsound
4406 S_NULL, // meleestate
4407 S_NULL, // missilestate
4408 S_NULL, // deathstate
4409 S_NULL, // xdeathstate
4410 sfx_None, // deathsound
4411 0, // speed
4412 16*FRACUNIT, // radius
4413 16*FRACUNIT, // height
4414 100, // mass
4415 0, // damage
4416 sfx_None, // activesound
4417 MF_SOLID, // flags
4418 S_NULL // raisestate
4419 },
4420
4421 { // MT_MISC73
4422 29, // doomednum
4423 S_HEADCANDLES, // spawnstate
4424 1000, // spawnhealth
4425 S_NULL, // seestate
4426 sfx_None, // seesound
4427 8, // reactiontime
4428 sfx_None, // attacksound
4429 S_NULL, // painstate
4430 0, // painchance
4431 sfx_None, // painsound
4432 S_NULL, // meleestate
4433 S_NULL, // missilestate
4434 S_NULL, // deathstate
4435 S_NULL, // xdeathstate
4436 sfx_None, // deathsound
4437 0, // speed
4438 16*FRACUNIT, // radius
4439 16*FRACUNIT, // height
4440 100, // mass
4441 0, // damage
4442 sfx_None, // activesound
4443 MF_SOLID, // flags
4444 S_NULL // raisestate
4445 },
4446
4447 { // MT_MISC74
4448 25, // doomednum
4449 S_DEADSTICK, // spawnstate
4450 1000, // spawnhealth
4451 S_NULL, // seestate
4452 sfx_None, // seesound
4453 8, // reactiontime
4454 sfx_None, // attacksound
4455 S_NULL, // painstate
4456 0, // painchance
4457 sfx_None, // painsound
4458 S_NULL, // meleestate
4459 S_NULL, // missilestate
4460 S_NULL, // deathstate
4461 S_NULL, // xdeathstate
4462 sfx_None, // deathsound
4463 0, // speed
4464 16*FRACUNIT, // radius
4465 16*FRACUNIT, // height
4466 100, // mass
4467 0, // damage
4468 sfx_None, // activesound
4469 MF_SOLID, // flags
4470 S_NULL // raisestate
4471 },
4472
4473 { // MT_MISC75
4474 26, // doomednum
4475 S_LIVESTICK, // spawnstate
4476 1000, // spawnhealth
4477 S_NULL, // seestate
4478 sfx_None, // seesound
4479 8, // reactiontime
4480 sfx_None, // attacksound
4481 S_NULL, // painstate
4482 0, // painchance
4483 sfx_None, // painsound
4484 S_NULL, // meleestate
4485 S_NULL, // missilestate
4486 S_NULL, // deathstate
4487 S_NULL, // xdeathstate
4488 sfx_None, // deathsound
4489 0, // speed
4490 16*FRACUNIT, // radius
4491 16*FRACUNIT, // height
4492 100, // mass
4493 0, // damage
4494 sfx_None, // activesound
4495 MF_SOLID, // flags
4496 S_NULL // raisestate
4497 },
4498
4499 { // MT_MISC76
4500 54, // doomednum
4501 S_BIGTREE, // spawnstate
4502 1000, // spawnhealth
4503 S_NULL, // seestate
4504 sfx_None, // seesound
4505 8, // reactiontime
4506 sfx_None, // attacksound
4507 S_NULL, // painstate
4508 0, // painchance
4509 sfx_None, // painsound
4510 S_NULL, // meleestate
4511 S_NULL, // missilestate
4512 S_NULL, // deathstate
4513 S_NULL, // xdeathstate
4514 sfx_None, // deathsound
4515 0, // speed
4516 32*FRACUNIT, // radius
4517 16*FRACUNIT, // height
4518 100, // mass
4519 0, // damage
4520 sfx_None, // activesound
4521 MF_SOLID, // flags
4522 S_NULL // raisestate
4523 },
4524
4525 { // MT_MISC77
4526 70, // doomednum
4527 S_BBAR1, // spawnstate
4528 1000, // spawnhealth
4529 S_NULL, // seestate
4530 sfx_None, // seesound
4531 8, // reactiontime
4532 sfx_None, // attacksound
4533 S_NULL, // painstate
4534 0, // painchance
4535 sfx_None, // painsound
4536 S_NULL, // meleestate
4537 S_NULL, // missilestate
4538 S_NULL, // deathstate
4539 S_NULL, // xdeathstate
4540 sfx_None, // deathsound
4541 0, // speed
4542 16*FRACUNIT, // radius
4543 16*FRACUNIT, // height
4544 100, // mass
4545 0, // damage
4546 sfx_None, // activesound
4547 MF_SOLID, // flags
4548 S_NULL // raisestate
4549 },
4550
4551 { // MT_MISC78
4552 73, // doomednum
4553 S_HANGNOGUTS, // spawnstate
4554 1000, // spawnhealth
4555 S_NULL, // seestate
4556 sfx_None, // seesound
4557 8, // reactiontime
4558 sfx_None, // attacksound
4559 S_NULL, // painstate
4560 0, // painchance
4561 sfx_None, // painsound
4562 S_NULL, // meleestate
4563 S_NULL, // missilestate
4564 S_NULL, // deathstate
4565 S_NULL, // xdeathstate
4566 sfx_None, // deathsound
4567 0, // speed
4568 16*FRACUNIT, // radius
4569 88*FRACUNIT, // height
4570 100, // mass
4571 0, // damage
4572 sfx_None, // activesound
4573 MF_SOLID|MF_SPAWNCEILING|MF_NOGRAVITY, // flags
4574 S_NULL // raisestate
4575 },
4576
4577 { // MT_MISC79
4578 74, // doomednum
4579 S_HANGBNOBRAIN, // spawnstate
4580 1000, // spawnhealth
4581 S_NULL, // seestate
4582 sfx_None, // seesound
4583 8, // reactiontime
4584 sfx_None, // attacksound
4585 S_NULL, // painstate
4586 0, // painchance
4587 sfx_None, // painsound
4588 S_NULL, // meleestate
4589 S_NULL, // missilestate
4590 S_NULL, // deathstate
4591 S_NULL, // xdeathstate
4592 sfx_None, // deathsound
4593 0, // speed
4594 16*FRACUNIT, // radius
4595 88*FRACUNIT, // height
4596 100, // mass
4597 0, // damage
4598 sfx_None, // activesound
4599 MF_SOLID|MF_SPAWNCEILING|MF_NOGRAVITY, // flags
4600 S_NULL // raisestate
4601 },
4602
4603 { // MT_MISC80
4604 75, // doomednum
4605 S_HANGTLOOKDN, // spawnstate
4606 1000, // spawnhealth
4607 S_NULL, // seestate
4608 sfx_None, // seesound
4609 8, // reactiontime
4610 sfx_None, // attacksound
4611 S_NULL, // painstate
4612 0, // painchance
4613 sfx_None, // painsound
4614 S_NULL, // meleestate
4615 S_NULL, // missilestate
4616 S_NULL, // deathstate
4617 S_NULL, // xdeathstate
4618 sfx_None, // deathsound
4619 0, // speed
4620 16*FRACUNIT, // radius
4621 64*FRACUNIT, // height
4622 100, // mass
4623 0, // damage
4624 sfx_None, // activesound
4625 MF_SOLID|MF_SPAWNCEILING|MF_NOGRAVITY, // flags
4626 S_NULL // raisestate
4627 },
4628
4629 { // MT_MISC81
4630 76, // doomednum
4631 S_HANGTSKULL, // spawnstate
4632 1000, // spawnhealth
4633 S_NULL, // seestate
4634 sfx_None, // seesound
4635 8, // reactiontime
4636 sfx_None, // attacksound
4637 S_NULL, // painstate
4638 0, // painchance
4639 sfx_None, // painsound
4640 S_NULL, // meleestate
4641 S_NULL, // missilestate
4642 S_NULL, // deathstate
4643 S_NULL, // xdeathstate
4644 sfx_None, // deathsound
4645 0, // speed
4646 16*FRACUNIT, // radius
4647 64*FRACUNIT, // height
4648 100, // mass
4649 0, // damage
4650 sfx_None, // activesound
4651 MF_SOLID|MF_SPAWNCEILING|MF_NOGRAVITY, // flags
4652 S_NULL // raisestate
4653 },
4654
4655 { // MT_MISC82
4656 77, // doomednum
4657 S_HANGTLOOKUP, // spawnstate
4658 1000, // spawnhealth
4659 S_NULL, // seestate
4660 sfx_None, // seesound
4661 8, // reactiontime
4662 sfx_None, // attacksound
4663 S_NULL, // painstate
4664 0, // painchance
4665 sfx_None, // painsound
4666 S_NULL, // meleestate
4667 S_NULL, // missilestate
4668 S_NULL, // deathstate
4669 S_NULL, // xdeathstate
4670 sfx_None, // deathsound
4671 0, // speed
4672 16*FRACUNIT, // radius
4673 64*FRACUNIT, // height
4674 100, // mass
4675 0, // damage
4676 sfx_None, // activesound
4677 MF_SOLID|MF_SPAWNCEILING|MF_NOGRAVITY, // flags
4678 S_NULL // raisestate
4679 },
4680
4681 { // MT_MISC83
4682 78, // doomednum
4683 S_HANGTNOBRAIN, // spawnstate
4684 1000, // spawnhealth
4685 S_NULL, // seestate
4686 sfx_None, // seesound
4687 8, // reactiontime
4688 sfx_None, // attacksound
4689 S_NULL, // painstate
4690 0, // painchance
4691 sfx_None, // painsound
4692 S_NULL, // meleestate
4693 S_NULL, // missilestate
4694 S_NULL, // deathstate
4695 S_NULL, // xdeathstate
4696 sfx_None, // deathsound
4697 0, // speed
4698 16*FRACUNIT, // radius
4699 64*FRACUNIT, // height
4700 100, // mass
4701 0, // damage
4702 sfx_None, // activesound
4703 MF_SOLID|MF_SPAWNCEILING|MF_NOGRAVITY, // flags
4704 S_NULL // raisestate
4705 },
4706
4707 { // MT_MISC84
4708 79, // doomednum
4709 S_COLONGIBS, // spawnstate
4710 1000, // spawnhealth
4711 S_NULL, // seestate
4712 sfx_None, // seesound
4713 8, // reactiontime
4714 sfx_None, // attacksound
4715 S_NULL, // painstate
4716 0, // painchance
4717 sfx_None, // painsound
4718 S_NULL, // meleestate
4719 S_NULL, // missilestate
4720 S_NULL, // deathstate
4721 S_NULL, // xdeathstate
4722 sfx_None, // deathsound
4723 0, // speed
4724 20*FRACUNIT, // radius
4725 16*FRACUNIT, // height
4726 100, // mass
4727 0, // damage
4728 sfx_None, // activesound
4729 MF_NOBLOCKMAP, // flags
4730 S_NULL // raisestate
4731 },
4732
4733 { // MT_MISC85
4734 80, // doomednum
4735 S_SMALLPOOL, // spawnstate
4736 1000, // spawnhealth
4737 S_NULL, // seestate
4738 sfx_None, // seesound
4739 8, // reactiontime
4740 sfx_None, // attacksound
4741 S_NULL, // painstate
4742 0, // painchance
4743 sfx_None, // painsound
4744 S_NULL, // meleestate
4745 S_NULL, // missilestate
4746 S_NULL, // deathstate
4747 S_NULL, // xdeathstate
4748 sfx_None, // deathsound
4749 0, // speed
4750 20*FRACUNIT, // radius
4751 16*FRACUNIT, // height
4752 100, // mass
4753 0, // damage
4754 sfx_None, // activesound
4755 MF_NOBLOCKMAP, // flags
4756 S_NULL // raisestate
4757 },
4758
4759 { // MT_MISC86
4760 81, // doomednum
4761 S_BRAINSTEM, // spawnstate
4762 1000, // spawnhealth
4763 S_NULL, // seestate
4764 sfx_None, // seesound
4765 8, // reactiontime
4766 sfx_None, // attacksound
4767 S_NULL, // painstate
4768 0, // painchance
4769 sfx_None, // painsound
4770 S_NULL, // meleestate
4771 S_NULL, // missilestate
4772 S_NULL, // deathstate
4773 S_NULL, // xdeathstate
4774 sfx_None, // deathsound
4775 0, // speed
4776 20*FRACUNIT, // radius
4777 16*FRACUNIT, // height
4778 100, // mass
4779 0, // damage
4780 sfx_None, // activesound
4781 MF_NOBLOCKMAP, // flags
4782 S_NULL // raisestate
4783 },
4784
4785 // For use with wind and current effects
4786 { // MT_PUSH // phares
4787 5001, // doomednum // | //jff 5/11/98 deconflict
4788 S_TNT1, // spawnstate // V // with DOSDoom
4789 1000, // spawnhealth
4790 S_NULL, // seestate
4791 sfx_None, // seesound
4792 8, // reactiontime
4793 sfx_None, // attacksound
4794 S_NULL, // painstate
4795 0, // painchance
4796 sfx_None, // painsound
4797 S_NULL, // meleestate
4798 S_NULL, // missilestate
4799 S_NULL, // deathstate
4800 S_NULL, // xdeathstate
4801 sfx_None, // deathsound
4802 0, // speed
4803 8, // radius
4804 8, // height
4805 10, // mass
4806 0, // damage
4807 sfx_None, // activesound
4808 MF_NOBLOCKMAP, // flags
4809 S_NULL // raisestate
4810 },
4811
4812 // For use with wind and current effects
4813 { // MT_PULL
4814 5002, // doomednum //jff 5/11/98 deconflict
4815 S_TNT1, // spawnstate // with DOSDoom
4816 1000, // spawnhealth
4817 S_NULL, // seestate
4818 sfx_None, // seesound
4819 8, // reactiontime
4820 sfx_None, // attacksound
4821 S_NULL, // painstate
4822 0, // painchance
4823 sfx_None, // painsound
4824 S_NULL, // meleestate
4825 S_NULL, // missilestate
4826 S_NULL, // deathstate
4827 S_NULL, // xdeathstate
4828 sfx_None, // deathsound
4829 0, // speed
4830 8, // radius
4831 8, // height
4832 10, // mass
4833 0, // damage
4834 sfx_None, // activesound
4835 MF_NOBLOCKMAP, // flags
4836 S_NULL // raisestate
4837 },
4838#ifdef DOGS
4839 // Marine's best friend :) // killough 7/19/98
4840 { // MT_DOGS
4841 888, // doomednum
4842 S_DOGS_STND, // spawnstate
4843 500, // spawnhealth
4844 S_DOGS_RUN1, // seestate
4845 sfx_dgsit, // seesound
4846 8, // reactiontime
4847 sfx_dgatk, // attacksound
4848 S_DOGS_PAIN, // painstate
4849 180, // painchance
4850 sfx_dgpain, // painsound
4851 S_DOGS_ATK1, // meleestate
4852 0, // missilestate
4853 S_DOGS_DIE1, // deathstate
4854 S_NULL, // xdeathstate
4855 sfx_dgdth, // deathsound
4856 10, // speed
4857 12*FRACUNIT, // radius
4858 28*FRACUNIT, // height
4859 100, // mass
4860 0, // damage
4861 sfx_dgact, // activesound
4862 MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL, // flags
4863 S_DOGS_RAISE1 // raisestate
4864 },
4865#endif
4866 //proff 11/22/98: Andy Baker's stealth monsters (next 12)
4867
4868#define STEALTH_EDNUM_BASE 4050
4869
4870 { // MT_STEALTHBABY (ARACHNOTRON)
4871 STEALTH_EDNUM_BASE, // doomednum
4872 S_BSPI_STND, // spawnstate
4873 500, // spawnhealth
4874 S_BSPI_SIGHT, // seestate
4875 sfx_bspsit, // seesound
4876 8, // reactiontime
4877 0, // attacksound
4878 S_BSPI_PAIN, // painstate
4879 128, // painchance
4880 sfx_dmpain, // painsound
4881 0, // meleestate
4882 S_BSPI_ATK1, // missilestate
4883 S_BSPI_DIE1, // deathstate
4884 S_NULL, // xdeathstate
4885 sfx_bspdth, // deathsound
4886 12, // speed
4887 64*FRACUNIT, // radius
4888 64*FRACUNIT, // height
4889 600, // mass
4890 0, // damage
4891 sfx_bspact, // activesound
4892 MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL|MF_STEALTH, // flags
4893 S_BSPI_RAISE1 // raisestate
4894 },
4895
4896 { // MT_STEALTHVILE
4897 STEALTH_EDNUM_BASE+1, // doomednum
4898 S_VILE_STND, // spawnstate
4899 700, // spawnhealth
4900 S_VILE_RUN1, // seestate
4901 sfx_vilsit, // seesound
4902 8, // reactiontime
4903 0, // attacksound
4904 S_VILE_PAIN, // painstate
4905 10, // painchance
4906 sfx_vipain, // painsound
4907 0, // meleestate
4908 S_VILE_ATK1, // missilestate
4909 S_VILE_DIE1, // deathstate
4910 S_NULL, // xdeathstate
4911 sfx_vildth, // deathsound
4912 15, // speed
4913 20*FRACUNIT, // radius
4914 56*FRACUNIT, // height
4915 500, // mass
4916 0, // damage
4917 sfx_vilact, // activesound
4918 MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL|MF_STEALTH, // flags
4919 S_NULL // raisestate
4920 },
4921
4922 { // MT_STEALTHBRUISER (BARONOFHELL)
4923 STEALTH_EDNUM_BASE+2, // doomednum
4924 S_BOSS_STND, // spawnstate
4925 1000, // spawnhealth
4926 S_BOSS_RUN1, // seestate
4927 sfx_brssit, // seesound
4928 8, // reactiontime
4929 0, // attacksound
4930 S_BOSS_PAIN, // painstate
4931 50, // painchance
4932 sfx_dmpain, // painsound
4933 S_BOSS_ATK1, // meleestate
4934 S_BOSS_ATK1, // missilestate
4935 S_BOSS_DIE1, // deathstate
4936 S_NULL, // xdeathstate
4937 sfx_brsdth, // deathsound
4938 8, // speed
4939 24*FRACUNIT, // radius
4940 64*FRACUNIT, // height
4941 1000, // mass
4942 0, // damage
4943 sfx_dmact, // activesound
4944 MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL|MF_STEALTH, // flags
4945 S_BOSS_RAISE1 // raisestate
4946 },
4947
4948 { // MT_STEALTHHEAD (CACODEMON)
4949 STEALTH_EDNUM_BASE+3, // doomednum
4950 S_HEAD_STND, // spawnstate
4951 400, // spawnhealth
4952 S_HEAD_RUN1, // seestate
4953 sfx_cacsit, // seesound
4954 8, // reactiontime
4955 0, // attacksound
4956 S_HEAD_PAIN, // painstate
4957 128, // painchance
4958 sfx_dmpain, // painsound
4959 0, // meleestate
4960 S_HEAD_ATK1, // missilestate
4961 S_HEAD_DIE1, // deathstate
4962 S_NULL, // xdeathstate
4963 sfx_cacdth, // deathsound
4964 8, // speed
4965 31*FRACUNIT, // radius
4966 56*FRACUNIT, // height
4967 400, // mass
4968 0, // damage
4969 sfx_dmact, // activesound
4970 MF_SOLID|MF_SHOOTABLE|MF_FLOAT|MF_NOGRAVITY|MF_COUNTKILL|MF_STEALTH, // flags
4971 S_HEAD_RAISE1 // raisestate
4972 },
4973
4974 { // MT_STEALTHCHAINGUY (CHAINGUNNER)
4975 STEALTH_EDNUM_BASE+4, // doomednum
4976 S_CPOS_STND, // spawnstate
4977 70, // spawnhealth
4978 S_CPOS_RUN1, // seestate
4979 sfx_posit2, // seesound
4980 8, // reactiontime
4981 0, // attacksound
4982 S_CPOS_PAIN, // painstate
4983 170, // painchance
4984 sfx_popain, // painsound
4985 0, // meleestate
4986 S_CPOS_ATK1, // missilestate
4987 S_CPOS_DIE1, // deathstate
4988 S_CPOS_XDIE1, // xdeathstate
4989 sfx_podth2, // deathsound
4990 8, // speed
4991 20*FRACUNIT, // radius
4992 56*FRACUNIT, // height
4993 100, // mass
4994 0, // damage
4995 sfx_posact, // activesound
4996 MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL|MF_STEALTH, // flags
4997 S_CPOS_RAISE1 // raisestate
4998 },
4999
5000 { // MT_STEALTHSERGEANT (DEMON)
5001 STEALTH_EDNUM_BASE+5, // doomednum
5002 S_SARG_STND, // spawnstate
5003 150, // spawnhealth
5004 S_SARG_RUN1, // seestate
5005 sfx_sgtsit, // seesound
5006 8, // reactiontime
5007 sfx_sgtatk, // attacksound
5008 S_SARG_PAIN, // painstate
5009 180, // painchance
5010 sfx_dmpain, // painsound
5011 S_SARG_ATK1, // meleestate
5012 0, // missilestate
5013 S_SARG_DIE1, // deathstate
5014 S_NULL, // xdeathstate
5015 sfx_sgtdth, // deathsound
5016 10, // speed
5017 30*FRACUNIT, // radius
5018 56*FRACUNIT, // height
5019 400, // mass
5020 0, // damage
5021 sfx_dmact, // activesound
5022 MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL|MF_STEALTH, // flags
5023 S_SARG_RAISE1 // raisestate
5024 },
5025
5026 { // MT_STEALTHKNIGHT
5027 STEALTH_EDNUM_BASE+6, // doomednum
5028 S_BOS2_STND, // spawnstate
5029 500, // spawnhealth
5030 S_BOS2_RUN1, // seestate
5031 sfx_kntsit, // seesound
5032 8, // reactiontime
5033 0, // attacksound
5034 S_BOS2_PAIN, // painstate
5035 50, // painchance
5036 sfx_dmpain, // painsound
5037 S_BOS2_ATK1, // meleestate
5038 S_BOS2_ATK1, // missilestate
5039 S_BOS2_DIE1, // deathstate
5040 S_NULL, // xdeathstate
5041 sfx_kntdth, // deathsound
5042 8, // speed
5043 24*FRACUNIT, // radius
5044 64*FRACUNIT, // height
5045 1000, // mass
5046 0, // damage
5047 sfx_dmact, // activesound
5048 MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL|MF_STEALTH, // flags
5049 S_BOS2_RAISE1 // raisestate
5050 },
5051
5052 { // MT_STEALTHTROOP (IMP)
5053 STEALTH_EDNUM_BASE+7, // doomednum
5054 S_TROO_STND, // spawnstate
5055 60, // spawnhealth
5056 S_TROO_RUN1, // seestate
5057 sfx_bgsit1, // seesound
5058 8, // reactiontime
5059 0, // attacksound
5060 S_TROO_PAIN, // painstate
5061 200, // painchance
5062 sfx_popain, // painsound
5063 S_TROO_ATK1, // meleestate
5064 S_TROO_ATK1, // missilestate
5065 S_TROO_DIE1, // deathstate
5066 S_TROO_XDIE1, // xdeathstate
5067 sfx_bgdth1, // deathsound
5068 8, // speed
5069 20*FRACUNIT, // radius
5070 56*FRACUNIT, // height
5071 100, // mass
5072 0, // damage
5073 sfx_bgact, // activesound
5074 MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL|MF_STEALTH, // flags
5075 S_TROO_RAISE1 // raisestate
5076 },
5077
5078 { // MT_STEALTHFATSO
5079 STEALTH_EDNUM_BASE+8, // doomednum
5080 S_FATT_STND, // spawnstate
5081 600, // spawnhealth
5082 S_FATT_RUN1, // seestate
5083 sfx_mansit, // seesound
5084 8, // reactiontime
5085 0, // attacksound
5086 S_FATT_PAIN, // painstate
5087 80, // painchance
5088 sfx_mnpain, // painsound
5089 0, // meleestate
5090 S_FATT_ATK1, // missilestate
5091 S_FATT_DIE1, // deathstate
5092 S_NULL, // xdeathstate
5093 sfx_mandth, // deathsound
5094 8, // speed
5095 48*FRACUNIT, // radius
5096 64*FRACUNIT, // height
5097 1000, // mass
5098 0, // damage
5099 sfx_posact, // activesound
5100 MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL|MF_STEALTH, // flags
5101 S_FATT_RAISE1 // raisestate
5102 },
5103
5104 { // MT_STEALTHUNDEAD
5105 STEALTH_EDNUM_BASE+9, // doomednum
5106 S_SKEL_STND, // spawnstate
5107 300, // spawnhealth
5108 S_SKEL_RUN1, // seestate
5109 sfx_skesit, // seesound
5110 8, // reactiontime
5111 0, // attacksound
5112 S_SKEL_PAIN, // painstate
5113 100, // painchance
5114 sfx_popain, // painsound
5115 S_SKEL_FIST1, // meleestate
5116 S_SKEL_MISS1, // missilestate
5117 S_SKEL_DIE1, // deathstate
5118 S_NULL, // xdeathstate
5119 sfx_skedth, // deathsound
5120 10, // speed
5121 20*FRACUNIT, // radius
5122 56*FRACUNIT, // height
5123 500, // mass
5124 0, // damage
5125 sfx_skeact, // activesound
5126 MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL|MF_STEALTH, // flags
5127 S_SKEL_RAISE1 // raisestate
5128 },
5129
5130 { // MT_STEALTHSHOTGUY
5131 STEALTH_EDNUM_BASE+10, // doomednum
5132 S_SPOS_STND, // spawnstate
5133 30, // spawnhealth
5134 S_SPOS_RUN1, // seestate
5135 sfx_posit2, // seesound
5136 8, // reactiontime
5137 0, // attacksound
5138 S_SPOS_PAIN, // painstate
5139 170, // painchance
5140 sfx_popain, // painsound
5141 0, // meleestate
5142 S_SPOS_ATK1, // missilestate
5143 S_SPOS_DIE1, // deathstate
5144 S_SPOS_XDIE1, // xdeathstate
5145 sfx_podth2, // deathsound
5146 8, // speed
5147 20*FRACUNIT, // radius
5148 56*FRACUNIT, // height
5149 100, // mass
5150 0, // damage
5151 sfx_posact, // activesound
5152 MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL|MF_STEALTH, // flags
5153 S_SPOS_RAISE1 // raisestate
5154 },
5155
5156 { // MT_STEALTHPOSSESSED
5157 STEALTH_EDNUM_BASE+11, // doomednum
5158 S_POSS_STND, // spawnstate
5159 20, // spawnhealth
5160 S_POSS_RUN1, // seestate
5161 sfx_posit1, // seesound
5162 8, // reactiontime
5163 sfx_pistol, // attacksound
5164 S_POSS_PAIN, // painstate
5165 200, // painchance
5166 sfx_popain, // painsound
5167 0, // meleestate
5168 S_POSS_ATK1, // missilestate
5169 S_POSS_DIE1, // deathstate
5170 S_POSS_XDIE1, // xdeathstate
5171 sfx_podth1, // deathsound
5172 8, // speed
5173 20*FRACUNIT, // radius
5174 56*FRACUNIT, // height
5175 100, // mass
5176 0, // damage
5177 sfx_posact, // activesound
5178 MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL|MF_STEALTH, // flags
5179 S_POSS_RAISE1 // raisestate
5180 }
5181
5182#undef STEALTH_EDNUM_BASE
5183
5184 };
5185
diff --git a/apps/plugins/doom/info.h b/apps/plugins/doom/info.h
new file mode 100644
index 0000000000..d6c20f0d5d
--- /dev/null
+++ b/apps/plugins/doom/info.h
@@ -0,0 +1,1454 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION:
28 * Thing frame/state LUT,
29 * generated by multigen utilitiy.
30 * This one is the original DOOM version, preserved.
31 *
32 *-----------------------------------------------------------------------------*/
33
34#ifndef __INFO__
35#define __INFO__
36
37// Needed for action function pointer handling.
38#include "d_think.h"
39#include "doomtype.h"
40
41/********************************************************************
42 * Sprite name enumeration - must match info.c *
43 ********************************************************************/
44typedef enum
45{
46 SPR_TROO,
47 SPR_SHTG,
48 SPR_PUNG,
49 SPR_PISG,
50 SPR_PISF,
51 SPR_SHTF,
52 SPR_SHT2,
53 SPR_CHGG,
54 SPR_CHGF,
55 SPR_MISG,
56 SPR_MISF,
57 SPR_SAWG,
58 SPR_PLSG,
59 SPR_PLSF,
60 SPR_BFGG,
61 SPR_BFGF,
62 SPR_BLUD,
63 SPR_PUFF,
64 SPR_BAL1,
65 SPR_BAL2,
66 SPR_PLSS,
67 SPR_PLSE,
68 SPR_MISL,
69 SPR_BFS1,
70 SPR_BFE1,
71 SPR_BFE2,
72 SPR_TFOG,
73 SPR_IFOG,
74 SPR_PLAY,
75 SPR_POSS,
76 SPR_SPOS,
77 SPR_VILE,
78 SPR_FIRE,
79 SPR_FATB,
80 SPR_FBXP,
81 SPR_SKEL,
82 SPR_MANF,
83 SPR_FATT,
84 SPR_CPOS,
85 SPR_SARG,
86 SPR_HEAD,
87 SPR_BAL7,
88 SPR_BOSS,
89 SPR_BOS2,
90 SPR_SKUL,
91 SPR_SPID,
92 SPR_BSPI,
93 SPR_APLS,
94 SPR_APBX,
95 SPR_CYBR,
96 SPR_PAIN,
97 SPR_SSWV,
98 SPR_KEEN,
99 SPR_BBRN,
100 SPR_BOSF,
101 SPR_ARM1,
102 SPR_ARM2,
103 SPR_BAR1,
104 SPR_BEXP,
105 SPR_FCAN,
106 SPR_BON1,
107 SPR_BON2,
108 SPR_BKEY,
109 SPR_RKEY,
110 SPR_YKEY,
111 SPR_BSKU,
112 SPR_RSKU,
113 SPR_YSKU,
114 SPR_STIM,
115 SPR_MEDI,
116 SPR_SOUL,
117 SPR_PINV,
118 SPR_PSTR,
119 SPR_PINS,
120 SPR_MEGA,
121 SPR_SUIT,
122 SPR_PMAP,
123 SPR_PVIS,
124 SPR_CLIP,
125 SPR_AMMO,
126 SPR_ROCK,
127 SPR_BROK,
128 SPR_CELL,
129 SPR_CELP,
130 SPR_SHEL,
131 SPR_SBOX,
132 SPR_BPAK,
133 SPR_BFUG,
134 SPR_MGUN,
135 SPR_CSAW,
136 SPR_LAUN,
137 SPR_PLAS,
138 SPR_SHOT,
139 SPR_SGN2,
140 SPR_COLU,
141 SPR_SMT2,
142 SPR_GOR1,
143 SPR_POL2,
144 SPR_POL5,
145 SPR_POL4,
146 SPR_POL3,
147 SPR_POL1,
148 SPR_POL6,
149 SPR_GOR2,
150 SPR_GOR3,
151 SPR_GOR4,
152 SPR_GOR5,
153 SPR_SMIT,
154 SPR_COL1,
155 SPR_COL2,
156 SPR_COL3,
157 SPR_COL4,
158 SPR_CAND,
159 SPR_CBRA,
160 SPR_COL6,
161 SPR_TRE1,
162 SPR_TRE2,
163 SPR_ELEC,
164 SPR_CEYE,
165 SPR_FSKU,
166 SPR_COL5,
167 SPR_TBLU,
168 SPR_TGRN,
169 SPR_TRED,
170 SPR_SMBT,
171 SPR_SMGT,
172 SPR_SMRT,
173 SPR_HDB1,
174 SPR_HDB2,
175 SPR_HDB3,
176 SPR_HDB4,
177 SPR_HDB5,
178 SPR_HDB6,
179 SPR_POB1,
180 SPR_POB2,
181 SPR_BRS1,
182 SPR_TLMP,
183 SPR_TLP2,
184 SPR_TNT1, /* add invisible sprite phares 3/8/98 */
185
186#ifdef DOGS
187 SPR_DOGS, /* killough 7/19/98: Marine's best friend :) */
188#endif
189 NUMSPRITES
190
191} spritenum_t;
192
193/********************************************************************
194 * States (frames) enumeration -- must match info.c *
195 ********************************************************************/
196
197typedef enum
198{
199 S_NULL,
200 S_LIGHTDONE,
201 S_PUNCH,
202 S_PUNCHDOWN,
203 S_PUNCHUP,
204 S_PUNCH1,
205 S_PUNCH2,
206 S_PUNCH3,
207 S_PUNCH4,
208 S_PUNCH5,
209 S_PISTOL,
210 S_PISTOLDOWN,
211 S_PISTOLUP,
212 S_PISTOL1,
213 S_PISTOL2,
214 S_PISTOL3,
215 S_PISTOL4,
216 S_PISTOLFLASH,
217 S_SGUN,
218 S_SGUNDOWN,
219 S_SGUNUP,
220 S_SGUN1,
221 S_SGUN2,
222 S_SGUN3,
223 S_SGUN4,
224 S_SGUN5,
225 S_SGUN6,
226 S_SGUN7,
227 S_SGUN8,
228 S_SGUN9,
229 S_SGUNFLASH1,
230 S_SGUNFLASH2,
231 S_DSGUN,
232 S_DSGUNDOWN,
233 S_DSGUNUP,
234 S_DSGUN1,
235 S_DSGUN2,
236 S_DSGUN3,
237 S_DSGUN4,
238 S_DSGUN5,
239 S_DSGUN6,
240 S_DSGUN7,
241 S_DSGUN8,
242 S_DSGUN9,
243 S_DSGUN10,
244 S_DSNR1,
245 S_DSNR2,
246 S_DSGUNFLASH1,
247 S_DSGUNFLASH2,
248 S_CHAIN,
249 S_CHAINDOWN,
250 S_CHAINUP,
251 S_CHAIN1,
252 S_CHAIN2,
253 S_CHAIN3,
254 S_CHAINFLASH1,
255 S_CHAINFLASH2,
256 S_MISSILE,
257 S_MISSILEDOWN,
258 S_MISSILEUP,
259 S_MISSILE1,
260 S_MISSILE2,
261 S_MISSILE3,
262 S_MISSILEFLASH1,
263 S_MISSILEFLASH2,
264 S_MISSILEFLASH3,
265 S_MISSILEFLASH4,
266 S_SAW,
267 S_SAWB,
268 S_SAWDOWN,
269 S_SAWUP,
270 S_SAW1,
271 S_SAW2,
272 S_SAW3,
273 S_PLASMA,
274 S_PLASMADOWN,
275 S_PLASMAUP,
276 S_PLASMA1,
277 S_PLASMA2,
278 S_PLASMAFLASH1,
279 S_PLASMAFLASH2,
280 S_BFG,
281 S_BFGDOWN,
282 S_BFGUP,
283 S_BFG1,
284 S_BFG2,
285 S_BFG3,
286 S_BFG4,
287 S_BFGFLASH1,
288 S_BFGFLASH2,
289 S_BLOOD1,
290 S_BLOOD2,
291 S_BLOOD3,
292 S_PUFF1,
293 S_PUFF2,
294 S_PUFF3,
295 S_PUFF4,
296 S_TBALL1,
297 S_TBALL2,
298 S_TBALLX1,
299 S_TBALLX2,
300 S_TBALLX3,
301 S_RBALL1,
302 S_RBALL2,
303 S_RBALLX1,
304 S_RBALLX2,
305 S_RBALLX3,
306 S_PLASBALL,
307 S_PLASBALL2,
308 S_PLASEXP,
309 S_PLASEXP2,
310 S_PLASEXP3,
311 S_PLASEXP4,
312 S_PLASEXP5,
313 S_ROCKET,
314 S_BFGSHOT,
315 S_BFGSHOT2,
316 S_BFGLAND,
317 S_BFGLAND2,
318 S_BFGLAND3,
319 S_BFGLAND4,
320 S_BFGLAND5,
321 S_BFGLAND6,
322 S_BFGEXP,
323 S_BFGEXP2,
324 S_BFGEXP3,
325 S_BFGEXP4,
326 S_EXPLODE1,
327 S_EXPLODE2,
328 S_EXPLODE3,
329 S_TFOG,
330 S_TFOG01,
331 S_TFOG02,
332 S_TFOG2,
333 S_TFOG3,
334 S_TFOG4,
335 S_TFOG5,
336 S_TFOG6,
337 S_TFOG7,
338 S_TFOG8,
339 S_TFOG9,
340 S_TFOG10,
341 S_IFOG,
342 S_IFOG01,
343 S_IFOG02,
344 S_IFOG2,
345 S_IFOG3,
346 S_IFOG4,
347 S_IFOG5,
348 S_PLAY,
349 S_PLAY_RUN1,
350 S_PLAY_RUN2,
351 S_PLAY_RUN3,
352 S_PLAY_RUN4,
353 S_PLAY_ATK1,
354 S_PLAY_ATK2,
355 S_PLAY_PAIN,
356 S_PLAY_PAIN2,
357 S_PLAY_DIE1,
358 S_PLAY_DIE2,
359 S_PLAY_DIE3,
360 S_PLAY_DIE4,
361 S_PLAY_DIE5,
362 S_PLAY_DIE6,
363 S_PLAY_DIE7,
364 S_PLAY_XDIE1,
365 S_PLAY_XDIE2,
366 S_PLAY_XDIE3,
367 S_PLAY_XDIE4,
368 S_PLAY_XDIE5,
369 S_PLAY_XDIE6,
370 S_PLAY_XDIE7,
371 S_PLAY_XDIE8,
372 S_PLAY_XDIE9,
373 S_POSS_STND,
374 S_POSS_STND2,
375 S_POSS_RUN1,
376 S_POSS_RUN2,
377 S_POSS_RUN3,
378 S_POSS_RUN4,
379 S_POSS_RUN5,
380 S_POSS_RUN6,
381 S_POSS_RUN7,
382 S_POSS_RUN8,
383 S_POSS_ATK1,
384 S_POSS_ATK2,
385 S_POSS_ATK3,
386 S_POSS_PAIN,
387 S_POSS_PAIN2,
388 S_POSS_DIE1,
389 S_POSS_DIE2,
390 S_POSS_DIE3,
391 S_POSS_DIE4,
392 S_POSS_DIE5,
393 S_POSS_XDIE1,
394 S_POSS_XDIE2,
395 S_POSS_XDIE3,
396 S_POSS_XDIE4,
397 S_POSS_XDIE5,
398 S_POSS_XDIE6,
399 S_POSS_XDIE7,
400 S_POSS_XDIE8,
401 S_POSS_XDIE9,
402 S_POSS_RAISE1,
403 S_POSS_RAISE2,
404 S_POSS_RAISE3,
405 S_POSS_RAISE4,
406 S_SPOS_STND,
407 S_SPOS_STND2,
408 S_SPOS_RUN1,
409 S_SPOS_RUN2,
410 S_SPOS_RUN3,
411 S_SPOS_RUN4,
412 S_SPOS_RUN5,
413 S_SPOS_RUN6,
414 S_SPOS_RUN7,
415 S_SPOS_RUN8,
416 S_SPOS_ATK1,
417 S_SPOS_ATK2,
418 S_SPOS_ATK3,
419 S_SPOS_PAIN,
420 S_SPOS_PAIN2,
421 S_SPOS_DIE1,
422 S_SPOS_DIE2,
423 S_SPOS_DIE3,
424 S_SPOS_DIE4,
425 S_SPOS_DIE5,
426 S_SPOS_XDIE1,
427 S_SPOS_XDIE2,
428 S_SPOS_XDIE3,
429 S_SPOS_XDIE4,
430 S_SPOS_XDIE5,
431 S_SPOS_XDIE6,
432 S_SPOS_XDIE7,
433 S_SPOS_XDIE8,
434 S_SPOS_XDIE9,
435 S_SPOS_RAISE1,
436 S_SPOS_RAISE2,
437 S_SPOS_RAISE3,
438 S_SPOS_RAISE4,
439 S_SPOS_RAISE5,
440 S_VILE_STND,
441 S_VILE_STND2,
442 S_VILE_RUN1,
443 S_VILE_RUN2,
444 S_VILE_RUN3,
445 S_VILE_RUN4,
446 S_VILE_RUN5,
447 S_VILE_RUN6,
448 S_VILE_RUN7,
449 S_VILE_RUN8,
450 S_VILE_RUN9,
451 S_VILE_RUN10,
452 S_VILE_RUN11,
453 S_VILE_RUN12,
454 S_VILE_ATK1,
455 S_VILE_ATK2,
456 S_VILE_ATK3,
457 S_VILE_ATK4,
458 S_VILE_ATK5,
459 S_VILE_ATK6,
460 S_VILE_ATK7,
461 S_VILE_ATK8,
462 S_VILE_ATK9,
463 S_VILE_ATK10,
464 S_VILE_ATK11,
465 S_VILE_HEAL1,
466 S_VILE_HEAL2,
467 S_VILE_HEAL3,
468 S_VILE_PAIN,
469 S_VILE_PAIN2,
470 S_VILE_DIE1,
471 S_VILE_DIE2,
472 S_VILE_DIE3,
473 S_VILE_DIE4,
474 S_VILE_DIE5,
475 S_VILE_DIE6,
476 S_VILE_DIE7,
477 S_VILE_DIE8,
478 S_VILE_DIE9,
479 S_VILE_DIE10,
480 S_FIRE1,
481 S_FIRE2,
482 S_FIRE3,
483 S_FIRE4,
484 S_FIRE5,
485 S_FIRE6,
486 S_FIRE7,
487 S_FIRE8,
488 S_FIRE9,
489 S_FIRE10,
490 S_FIRE11,
491 S_FIRE12,
492 S_FIRE13,
493 S_FIRE14,
494 S_FIRE15,
495 S_FIRE16,
496 S_FIRE17,
497 S_FIRE18,
498 S_FIRE19,
499 S_FIRE20,
500 S_FIRE21,
501 S_FIRE22,
502 S_FIRE23,
503 S_FIRE24,
504 S_FIRE25,
505 S_FIRE26,
506 S_FIRE27,
507 S_FIRE28,
508 S_FIRE29,
509 S_FIRE30,
510 S_SMOKE1,
511 S_SMOKE2,
512 S_SMOKE3,
513 S_SMOKE4,
514 S_SMOKE5,
515 S_TRACER,
516 S_TRACER2,
517 S_TRACEEXP1,
518 S_TRACEEXP2,
519 S_TRACEEXP3,
520 S_SKEL_STND,
521 S_SKEL_STND2,
522 S_SKEL_RUN1,
523 S_SKEL_RUN2,
524 S_SKEL_RUN3,
525 S_SKEL_RUN4,
526 S_SKEL_RUN5,
527 S_SKEL_RUN6,
528 S_SKEL_RUN7,
529 S_SKEL_RUN8,
530 S_SKEL_RUN9,
531 S_SKEL_RUN10,
532 S_SKEL_RUN11,
533 S_SKEL_RUN12,
534 S_SKEL_FIST1,
535 S_SKEL_FIST2,
536 S_SKEL_FIST3,
537 S_SKEL_FIST4,
538 S_SKEL_MISS1,
539 S_SKEL_MISS2,
540 S_SKEL_MISS3,
541 S_SKEL_MISS4,
542 S_SKEL_PAIN,
543 S_SKEL_PAIN2,
544 S_SKEL_DIE1,
545 S_SKEL_DIE2,
546 S_SKEL_DIE3,
547 S_SKEL_DIE4,
548 S_SKEL_DIE5,
549 S_SKEL_DIE6,
550 S_SKEL_RAISE1,
551 S_SKEL_RAISE2,
552 S_SKEL_RAISE3,
553 S_SKEL_RAISE4,
554 S_SKEL_RAISE5,
555 S_SKEL_RAISE6,
556 S_FATSHOT1,
557 S_FATSHOT2,
558 S_FATSHOTX1,
559 S_FATSHOTX2,
560 S_FATSHOTX3,
561 S_FATT_STND,
562 S_FATT_STND2,
563 S_FATT_RUN1,
564 S_FATT_RUN2,
565 S_FATT_RUN3,
566 S_FATT_RUN4,
567 S_FATT_RUN5,
568 S_FATT_RUN6,
569 S_FATT_RUN7,
570 S_FATT_RUN8,
571 S_FATT_RUN9,
572 S_FATT_RUN10,
573 S_FATT_RUN11,
574 S_FATT_RUN12,
575 S_FATT_ATK1,
576 S_FATT_ATK2,
577 S_FATT_ATK3,
578 S_FATT_ATK4,
579 S_FATT_ATK5,
580 S_FATT_ATK6,
581 S_FATT_ATK7,
582 S_FATT_ATK8,
583 S_FATT_ATK9,
584 S_FATT_ATK10,
585 S_FATT_PAIN,
586 S_FATT_PAIN2,
587 S_FATT_DIE1,
588 S_FATT_DIE2,
589 S_FATT_DIE3,
590 S_FATT_DIE4,
591 S_FATT_DIE5,
592 S_FATT_DIE6,
593 S_FATT_DIE7,
594 S_FATT_DIE8,
595 S_FATT_DIE9,
596 S_FATT_DIE10,
597 S_FATT_RAISE1,
598 S_FATT_RAISE2,
599 S_FATT_RAISE3,
600 S_FATT_RAISE4,
601 S_FATT_RAISE5,
602 S_FATT_RAISE6,
603 S_FATT_RAISE7,
604 S_FATT_RAISE8,
605 S_CPOS_STND,
606 S_CPOS_STND2,
607 S_CPOS_RUN1,
608 S_CPOS_RUN2,
609 S_CPOS_RUN3,
610 S_CPOS_RUN4,
611 S_CPOS_RUN5,
612 S_CPOS_RUN6,
613 S_CPOS_RUN7,
614 S_CPOS_RUN8,
615 S_CPOS_ATK1,
616 S_CPOS_ATK2,
617 S_CPOS_ATK3,
618 S_CPOS_ATK4,
619 S_CPOS_PAIN,
620 S_CPOS_PAIN2,
621 S_CPOS_DIE1,
622 S_CPOS_DIE2,
623 S_CPOS_DIE3,
624 S_CPOS_DIE4,
625 S_CPOS_DIE5,
626 S_CPOS_DIE6,
627 S_CPOS_DIE7,
628 S_CPOS_XDIE1,
629 S_CPOS_XDIE2,
630 S_CPOS_XDIE3,
631 S_CPOS_XDIE4,
632 S_CPOS_XDIE5,
633 S_CPOS_XDIE6,
634 S_CPOS_RAISE1,
635 S_CPOS_RAISE2,
636 S_CPOS_RAISE3,
637 S_CPOS_RAISE4,
638 S_CPOS_RAISE5,
639 S_CPOS_RAISE6,
640 S_CPOS_RAISE7,
641 S_TROO_STND,
642 S_TROO_STND2,
643 S_TROO_RUN1,
644 S_TROO_RUN2,
645 S_TROO_RUN3,
646 S_TROO_RUN4,
647 S_TROO_RUN5,
648 S_TROO_RUN6,
649 S_TROO_RUN7,
650 S_TROO_RUN8,
651 S_TROO_ATK1,
652 S_TROO_ATK2,
653 S_TROO_ATK3,
654 S_TROO_PAIN,
655 S_TROO_PAIN2,
656 S_TROO_DIE1,
657 S_TROO_DIE2,
658 S_TROO_DIE3,
659 S_TROO_DIE4,
660 S_TROO_DIE5,
661 S_TROO_XDIE1,
662 S_TROO_XDIE2,
663 S_TROO_XDIE3,
664 S_TROO_XDIE4,
665 S_TROO_XDIE5,
666 S_TROO_XDIE6,
667 S_TROO_XDIE7,
668 S_TROO_XDIE8,
669 S_TROO_RAISE1,
670 S_TROO_RAISE2,
671 S_TROO_RAISE3,
672 S_TROO_RAISE4,
673 S_TROO_RAISE5,
674 S_SARG_STND,
675 S_SARG_STND2,
676 S_SARG_RUN1,
677 S_SARG_RUN2,
678 S_SARG_RUN3,
679 S_SARG_RUN4,
680 S_SARG_RUN5,
681 S_SARG_RUN6,
682 S_SARG_RUN7,
683 S_SARG_RUN8,
684 S_SARG_ATK1,
685 S_SARG_ATK2,
686 S_SARG_ATK3,
687 S_SARG_PAIN,
688 S_SARG_PAIN2,
689 S_SARG_DIE1,
690 S_SARG_DIE2,
691 S_SARG_DIE3,
692 S_SARG_DIE4,
693 S_SARG_DIE5,
694 S_SARG_DIE6,
695 S_SARG_RAISE1,
696 S_SARG_RAISE2,
697 S_SARG_RAISE3,
698 S_SARG_RAISE4,
699 S_SARG_RAISE5,
700 S_SARG_RAISE6,
701 S_HEAD_STND,
702 S_HEAD_RUN1,
703 S_HEAD_ATK1,
704 S_HEAD_ATK2,
705 S_HEAD_ATK3,
706 S_HEAD_PAIN,
707 S_HEAD_PAIN2,
708 S_HEAD_PAIN3,
709 S_HEAD_DIE1,
710 S_HEAD_DIE2,
711 S_HEAD_DIE3,
712 S_HEAD_DIE4,
713 S_HEAD_DIE5,
714 S_HEAD_DIE6,
715 S_HEAD_RAISE1,
716 S_HEAD_RAISE2,
717 S_HEAD_RAISE3,
718 S_HEAD_RAISE4,
719 S_HEAD_RAISE5,
720 S_HEAD_RAISE6,
721 S_BRBALL1,
722 S_BRBALL2,
723 S_BRBALLX1,
724 S_BRBALLX2,
725 S_BRBALLX3,
726 S_BOSS_STND,
727 S_BOSS_STND2,
728 S_BOSS_RUN1,
729 S_BOSS_RUN2,
730 S_BOSS_RUN3,
731 S_BOSS_RUN4,
732 S_BOSS_RUN5,
733 S_BOSS_RUN6,
734 S_BOSS_RUN7,
735 S_BOSS_RUN8,
736 S_BOSS_ATK1,
737 S_BOSS_ATK2,
738 S_BOSS_ATK3,
739 S_BOSS_PAIN,
740 S_BOSS_PAIN2,
741 S_BOSS_DIE1,
742 S_BOSS_DIE2,
743 S_BOSS_DIE3,
744 S_BOSS_DIE4,
745 S_BOSS_DIE5,
746 S_BOSS_DIE6,
747 S_BOSS_DIE7,
748 S_BOSS_RAISE1,
749 S_BOSS_RAISE2,
750 S_BOSS_RAISE3,
751 S_BOSS_RAISE4,
752 S_BOSS_RAISE5,
753 S_BOSS_RAISE6,
754 S_BOSS_RAISE7,
755 S_BOS2_STND,
756 S_BOS2_STND2,
757 S_BOS2_RUN1,
758 S_BOS2_RUN2,
759 S_BOS2_RUN3,
760 S_BOS2_RUN4,
761 S_BOS2_RUN5,
762 S_BOS2_RUN6,
763 S_BOS2_RUN7,
764 S_BOS2_RUN8,
765 S_BOS2_ATK1,
766 S_BOS2_ATK2,
767 S_BOS2_ATK3,
768 S_BOS2_PAIN,
769 S_BOS2_PAIN2,
770 S_BOS2_DIE1,
771 S_BOS2_DIE2,
772 S_BOS2_DIE3,
773 S_BOS2_DIE4,
774 S_BOS2_DIE5,
775 S_BOS2_DIE6,
776 S_BOS2_DIE7,
777 S_BOS2_RAISE1,
778 S_BOS2_RAISE2,
779 S_BOS2_RAISE3,
780 S_BOS2_RAISE4,
781 S_BOS2_RAISE5,
782 S_BOS2_RAISE6,
783 S_BOS2_RAISE7,
784 S_SKULL_STND,
785 S_SKULL_STND2,
786 S_SKULL_RUN1,
787 S_SKULL_RUN2,
788 S_SKULL_ATK1,
789 S_SKULL_ATK2,
790 S_SKULL_ATK3,
791 S_SKULL_ATK4,
792 S_SKULL_PAIN,
793 S_SKULL_PAIN2,
794 S_SKULL_DIE1,
795 S_SKULL_DIE2,
796 S_SKULL_DIE3,
797 S_SKULL_DIE4,
798 S_SKULL_DIE5,
799 S_SKULL_DIE6,
800 S_SPID_STND,
801 S_SPID_STND2,
802 S_SPID_RUN1,
803 S_SPID_RUN2,
804 S_SPID_RUN3,
805 S_SPID_RUN4,
806 S_SPID_RUN5,
807 S_SPID_RUN6,
808 S_SPID_RUN7,
809 S_SPID_RUN8,
810 S_SPID_RUN9,
811 S_SPID_RUN10,
812 S_SPID_RUN11,
813 S_SPID_RUN12,
814 S_SPID_ATK1,
815 S_SPID_ATK2,
816 S_SPID_ATK3,
817 S_SPID_ATK4,
818 S_SPID_PAIN,
819 S_SPID_PAIN2,
820 S_SPID_DIE1,
821 S_SPID_DIE2,
822 S_SPID_DIE3,
823 S_SPID_DIE4,
824 S_SPID_DIE5,
825 S_SPID_DIE6,
826 S_SPID_DIE7,
827 S_SPID_DIE8,
828 S_SPID_DIE9,
829 S_SPID_DIE10,
830 S_SPID_DIE11,
831 S_BSPI_STND,
832 S_BSPI_STND2,
833 S_BSPI_SIGHT,
834 S_BSPI_RUN1,
835 S_BSPI_RUN2,
836 S_BSPI_RUN3,
837 S_BSPI_RUN4,
838 S_BSPI_RUN5,
839 S_BSPI_RUN6,
840 S_BSPI_RUN7,
841 S_BSPI_RUN8,
842 S_BSPI_RUN9,
843 S_BSPI_RUN10,
844 S_BSPI_RUN11,
845 S_BSPI_RUN12,
846 S_BSPI_ATK1,
847 S_BSPI_ATK2,
848 S_BSPI_ATK3,
849 S_BSPI_ATK4,
850 S_BSPI_PAIN,
851 S_BSPI_PAIN2,
852 S_BSPI_DIE1,
853 S_BSPI_DIE2,
854 S_BSPI_DIE3,
855 S_BSPI_DIE4,
856 S_BSPI_DIE5,
857 S_BSPI_DIE6,
858 S_BSPI_DIE7,
859 S_BSPI_RAISE1,
860 S_BSPI_RAISE2,
861 S_BSPI_RAISE3,
862 S_BSPI_RAISE4,
863 S_BSPI_RAISE5,
864 S_BSPI_RAISE6,
865 S_BSPI_RAISE7,
866 S_ARACH_PLAZ,
867 S_ARACH_PLAZ2,
868 S_ARACH_PLEX,
869 S_ARACH_PLEX2,
870 S_ARACH_PLEX3,
871 S_ARACH_PLEX4,
872 S_ARACH_PLEX5,
873 S_CYBER_STND,
874 S_CYBER_STND2,
875 S_CYBER_RUN1,
876 S_CYBER_RUN2,
877 S_CYBER_RUN3,
878 S_CYBER_RUN4,
879 S_CYBER_RUN5,
880 S_CYBER_RUN6,
881 S_CYBER_RUN7,
882 S_CYBER_RUN8,
883 S_CYBER_ATK1,
884 S_CYBER_ATK2,
885 S_CYBER_ATK3,
886 S_CYBER_ATK4,
887 S_CYBER_ATK5,
888 S_CYBER_ATK6,
889 S_CYBER_PAIN,
890 S_CYBER_DIE1,
891 S_CYBER_DIE2,
892 S_CYBER_DIE3,
893 S_CYBER_DIE4,
894 S_CYBER_DIE5,
895 S_CYBER_DIE6,
896 S_CYBER_DIE7,
897 S_CYBER_DIE8,
898 S_CYBER_DIE9,
899 S_CYBER_DIE10,
900 S_PAIN_STND,
901 S_PAIN_RUN1,
902 S_PAIN_RUN2,
903 S_PAIN_RUN3,
904 S_PAIN_RUN4,
905 S_PAIN_RUN5,
906 S_PAIN_RUN6,
907 S_PAIN_ATK1,
908 S_PAIN_ATK2,
909 S_PAIN_ATK3,
910 S_PAIN_ATK4,
911 S_PAIN_PAIN,
912 S_PAIN_PAIN2,
913 S_PAIN_DIE1,
914 S_PAIN_DIE2,
915 S_PAIN_DIE3,
916 S_PAIN_DIE4,
917 S_PAIN_DIE5,
918 S_PAIN_DIE6,
919 S_PAIN_RAISE1,
920 S_PAIN_RAISE2,
921 S_PAIN_RAISE3,
922 S_PAIN_RAISE4,
923 S_PAIN_RAISE5,
924 S_PAIN_RAISE6,
925 S_SSWV_STND,
926 S_SSWV_STND2,
927 S_SSWV_RUN1,
928 S_SSWV_RUN2,
929 S_SSWV_RUN3,
930 S_SSWV_RUN4,
931 S_SSWV_RUN5,
932 S_SSWV_RUN6,
933 S_SSWV_RUN7,
934 S_SSWV_RUN8,
935 S_SSWV_ATK1,
936 S_SSWV_ATK2,
937 S_SSWV_ATK3,
938 S_SSWV_ATK4,
939 S_SSWV_ATK5,
940 S_SSWV_ATK6,
941 S_SSWV_PAIN,
942 S_SSWV_PAIN2,
943 S_SSWV_DIE1,
944 S_SSWV_DIE2,
945 S_SSWV_DIE3,
946 S_SSWV_DIE4,
947 S_SSWV_DIE5,
948 S_SSWV_XDIE1,
949 S_SSWV_XDIE2,
950 S_SSWV_XDIE3,
951 S_SSWV_XDIE4,
952 S_SSWV_XDIE5,
953 S_SSWV_XDIE6,
954 S_SSWV_XDIE7,
955 S_SSWV_XDIE8,
956 S_SSWV_XDIE9,
957 S_SSWV_RAISE1,
958 S_SSWV_RAISE2,
959 S_SSWV_RAISE3,
960 S_SSWV_RAISE4,
961 S_SSWV_RAISE5,
962 S_KEENSTND,
963 S_COMMKEEN,
964 S_COMMKEEN2,
965 S_COMMKEEN3,
966 S_COMMKEEN4,
967 S_COMMKEEN5,
968 S_COMMKEEN6,
969 S_COMMKEEN7,
970 S_COMMKEEN8,
971 S_COMMKEEN9,
972 S_COMMKEEN10,
973 S_COMMKEEN11,
974 S_COMMKEEN12,
975 S_KEENPAIN,
976 S_KEENPAIN2,
977 S_BRAIN,
978 S_BRAIN_PAIN,
979 S_BRAIN_DIE1,
980 S_BRAIN_DIE2,
981 S_BRAIN_DIE3,
982 S_BRAIN_DIE4,
983 S_BRAINEYE,
984 S_BRAINEYESEE,
985 S_BRAINEYE1,
986 S_SPAWN1,
987 S_SPAWN2,
988 S_SPAWN3,
989 S_SPAWN4,
990 S_SPAWNFIRE1,
991 S_SPAWNFIRE2,
992 S_SPAWNFIRE3,
993 S_SPAWNFIRE4,
994 S_SPAWNFIRE5,
995 S_SPAWNFIRE6,
996 S_SPAWNFIRE7,
997 S_SPAWNFIRE8,
998 S_BRAINEXPLODE1,
999 S_BRAINEXPLODE2,
1000 S_BRAINEXPLODE3,
1001 S_ARM1,
1002 S_ARM1A,
1003 S_ARM2,
1004 S_ARM2A,
1005 S_BAR1,
1006 S_BAR2,
1007 S_BEXP,
1008 S_BEXP2,
1009 S_BEXP3,
1010 S_BEXP4,
1011 S_BEXP5,
1012 S_BBAR1,
1013 S_BBAR2,
1014 S_BBAR3,
1015 S_BON1,
1016 S_BON1A,
1017 S_BON1B,
1018 S_BON1C,
1019 S_BON1D,
1020 S_BON1E,
1021 S_BON2,
1022 S_BON2A,
1023 S_BON2B,
1024 S_BON2C,
1025 S_BON2D,
1026 S_BON2E,
1027 S_BKEY,
1028 S_BKEY2,
1029 S_RKEY,
1030 S_RKEY2,
1031 S_YKEY,
1032 S_YKEY2,
1033 S_BSKULL,
1034 S_BSKULL2,
1035 S_RSKULL,
1036 S_RSKULL2,
1037 S_YSKULL,
1038 S_YSKULL2,
1039 S_STIM,
1040 S_MEDI,
1041 S_SOUL,
1042 S_SOUL2,
1043 S_SOUL3,
1044 S_SOUL4,
1045 S_SOUL5,
1046 S_SOUL6,
1047 S_PINV,
1048 S_PINV2,
1049 S_PINV3,
1050 S_PINV4,
1051 S_PSTR,
1052 S_PINS,
1053 S_PINS2,
1054 S_PINS3,
1055 S_PINS4,
1056 S_MEGA,
1057 S_MEGA2,
1058 S_MEGA3,
1059 S_MEGA4,
1060 S_SUIT,
1061 S_PMAP,
1062 S_PMAP2,
1063 S_PMAP3,
1064 S_PMAP4,
1065 S_PMAP5,
1066 S_PMAP6,
1067 S_PVIS,
1068 S_PVIS2,
1069 S_CLIP,
1070 S_AMMO,
1071 S_ROCK,
1072 S_BROK,
1073 S_CELL,
1074 S_CELP,
1075 S_SHEL,
1076 S_SBOX,
1077 S_BPAK,
1078 S_BFUG,
1079 S_MGUN,
1080 S_CSAW,
1081 S_LAUN,
1082 S_PLAS,
1083 S_SHOT,
1084 S_SHOT2,
1085 S_COLU,
1086 S_STALAG,
1087 S_BLOODYTWITCH,
1088 S_BLOODYTWITCH2,
1089 S_BLOODYTWITCH3,
1090 S_BLOODYTWITCH4,
1091 S_DEADTORSO,
1092 S_DEADBOTTOM,
1093 S_HEADSONSTICK,
1094 S_GIBS,
1095 S_HEADONASTICK,
1096 S_HEADCANDLES,
1097 S_HEADCANDLES2,
1098 S_DEADSTICK,
1099 S_LIVESTICK,
1100 S_LIVESTICK2,
1101 S_MEAT2,
1102 S_MEAT3,
1103 S_MEAT4,
1104 S_MEAT5,
1105 S_STALAGTITE,
1106 S_TALLGRNCOL,
1107 S_SHRTGRNCOL,
1108 S_TALLREDCOL,
1109 S_SHRTREDCOL,
1110 S_CANDLESTIK,
1111 S_CANDELABRA,
1112 S_SKULLCOL,
1113 S_TORCHTREE,
1114 S_BIGTREE,
1115 S_TECHPILLAR,
1116 S_EVILEYE,
1117 S_EVILEYE2,
1118 S_EVILEYE3,
1119 S_EVILEYE4,
1120 S_FLOATSKULL,
1121 S_FLOATSKULL2,
1122 S_FLOATSKULL3,
1123 S_HEARTCOL,
1124 S_HEARTCOL2,
1125 S_BLUETORCH,
1126 S_BLUETORCH2,
1127 S_BLUETORCH3,
1128 S_BLUETORCH4,
1129 S_GREENTORCH,
1130 S_GREENTORCH2,
1131 S_GREENTORCH3,
1132 S_GREENTORCH4,
1133 S_REDTORCH,
1134 S_REDTORCH2,
1135 S_REDTORCH3,
1136 S_REDTORCH4,
1137 S_BTORCHSHRT,
1138 S_BTORCHSHRT2,
1139 S_BTORCHSHRT3,
1140 S_BTORCHSHRT4,
1141 S_GTORCHSHRT,
1142 S_GTORCHSHRT2,
1143 S_GTORCHSHRT3,
1144 S_GTORCHSHRT4,
1145 S_RTORCHSHRT,
1146 S_RTORCHSHRT2,
1147 S_RTORCHSHRT3,
1148 S_RTORCHSHRT4,
1149 S_HANGNOGUTS,
1150 S_HANGBNOBRAIN,
1151 S_HANGTLOOKDN,
1152 S_HANGTSKULL,
1153 S_HANGTLOOKUP,
1154 S_HANGTNOBRAIN,
1155 S_COLONGIBS,
1156 S_SMALLPOOL,
1157 S_BRAINSTEM,
1158 S_TECHLAMP,
1159 S_TECHLAMP2,
1160 S_TECHLAMP3,
1161 S_TECHLAMP4,
1162 S_TECH2LAMP,
1163 S_TECH2LAMP2,
1164 S_TECH2LAMP3,
1165 S_TECH2LAMP4,
1166 S_TNT1, /* add state for invisible sprite phares 3/8/98 */
1167
1168 S_GRENADE, /* killough 8/9/98: grenade launcher */
1169 S_DETONATE, /* killough 8/9/98: detonation of objects */
1170 S_DETONATE2,
1171 S_DETONATE3,
1172
1173#ifdef DOGS
1174 S_DOGS_STND, /* killough 7/19/98: Marine's best friend :) */
1175 S_DOGS_STND2,
1176 S_DOGS_RUN1,
1177 S_DOGS_RUN2,
1178 S_DOGS_RUN3,
1179 S_DOGS_RUN4,
1180 S_DOGS_RUN5,
1181 S_DOGS_RUN6,
1182 S_DOGS_RUN7,
1183 S_DOGS_RUN8,
1184 S_DOGS_ATK1,
1185 S_DOGS_ATK2,
1186 S_DOGS_ATK3,
1187 S_DOGS_PAIN,
1188 S_DOGS_PAIN2,
1189 S_DOGS_DIE1,
1190 S_DOGS_DIE2,
1191 S_DOGS_DIE3,
1192 S_DOGS_DIE4,
1193 S_DOGS_DIE5,
1194 S_DOGS_DIE6,
1195 S_DOGS_RAISE1,
1196 S_DOGS_RAISE2,
1197 S_DOGS_RAISE3,
1198 S_DOGS_RAISE4,
1199 S_DOGS_RAISE5,
1200 S_DOGS_RAISE6,
1201#endif
1202
1203 S_MUSHROOM, /* killough 10/98: mushroom explosion effect */
1204
1205 NUMSTATES /* Counter of how many there are */
1206
1207} statenum_t;
1208
1209/********************************************************************
1210 * Definition of the state (frames) structure *
1211 ********************************************************************/
1212
1213typedef struct
1214{
1215 spritenum_t sprite; /* sprite number to show */
1216 long frame; /* which frame/subframe of the sprite is shown */
1217 long tics; /* number of gametics this frame should last */
1218 actionf_t action; /* code pointer to function for action if any */
1219 statenum_t nextstate; /* linked list pointer to next state or zero */
1220 long misc1, misc2; /* apparently never used in DOOM */
1221} state_t;
1222
1223/* these are in info.c */
1224extern state_t states[NUMSTATES];
1225extern const char *sprnames[NUMSPRITES+1]; /* 1/17/98 killough - CPhipps - const */
1226
1227/********************************************************************
1228 * Thing enumeration -- must match info.c *
1229 ********************************************************************
1230 * Note that many of these are generically named for the ornamentals
1231 */
1232
1233typedef enum {
1234 MT_PLAYER,
1235 MT_POSSESSED,
1236 MT_SHOTGUY,
1237 MT_VILE,
1238 MT_FIRE,
1239 MT_UNDEAD,
1240 MT_TRACER,
1241 MT_SMOKE,
1242 MT_FATSO,
1243 MT_FATSHOT,
1244 MT_CHAINGUY,
1245 MT_TROOP,
1246 MT_SERGEANT,
1247 MT_SHADOWS,
1248 MT_HEAD,
1249 MT_BRUISER,
1250 MT_BRUISERSHOT,
1251 MT_KNIGHT,
1252 MT_SKULL,
1253 MT_SPIDER,
1254 MT_BABY,
1255 MT_CYBORG,
1256 MT_PAIN,
1257 MT_WOLFSS,
1258 MT_KEEN,
1259 MT_BOSSBRAIN,
1260 MT_BOSSSPIT,
1261 MT_BOSSTARGET,
1262 MT_SPAWNSHOT,
1263 MT_SPAWNFIRE,
1264 MT_BARREL,
1265 MT_TROOPSHOT,
1266 MT_HEADSHOT,
1267 MT_ROCKET,
1268 MT_PLASMA,
1269 MT_BFG,
1270 MT_ARACHPLAZ,
1271 MT_PUFF,
1272 MT_BLOOD,
1273 MT_TFOG,
1274 MT_IFOG,
1275 MT_TELEPORTMAN,
1276 MT_EXTRABFG,
1277 MT_MISC0,
1278 MT_MISC1,
1279 MT_MISC2,
1280 MT_MISC3,
1281 MT_MISC4,
1282 MT_MISC5,
1283 MT_MISC6,
1284 MT_MISC7,
1285 MT_MISC8,
1286 MT_MISC9,
1287 MT_MISC10,
1288 MT_MISC11,
1289 MT_MISC12,
1290 MT_INV,
1291 MT_MISC13,
1292 MT_INS,
1293 MT_MISC14,
1294 MT_MISC15,
1295 MT_MISC16,
1296 MT_MEGA,
1297 MT_CLIP,
1298 MT_MISC17,
1299 MT_MISC18,
1300 MT_MISC19,
1301 MT_MISC20,
1302 MT_MISC21,
1303 MT_MISC22,
1304 MT_MISC23,
1305 MT_MISC24,
1306 MT_MISC25,
1307 MT_CHAINGUN,
1308 MT_MISC26,
1309 MT_MISC27,
1310 MT_MISC28,
1311 MT_SHOTGUN,
1312 MT_SUPERSHOTGUN,
1313 MT_MISC29,
1314 MT_MISC30,
1315 MT_MISC31,
1316 MT_MISC32,
1317 MT_MISC33,
1318 MT_MISC34,
1319 MT_MISC35,
1320 MT_MISC36,
1321 MT_MISC37,
1322 MT_MISC38,
1323 MT_MISC39,
1324 MT_MISC40,
1325 MT_MISC41,
1326 MT_MISC42,
1327 MT_MISC43,
1328 MT_MISC44,
1329 MT_MISC45,
1330 MT_MISC46,
1331 MT_MISC47,
1332 MT_MISC48,
1333 MT_MISC49,
1334 MT_MISC50,
1335 MT_MISC51,
1336 MT_MISC52,
1337 MT_MISC53,
1338 MT_MISC54,
1339 MT_MISC55,
1340 MT_MISC56,
1341 MT_MISC57,
1342 MT_MISC58,
1343 MT_MISC59,
1344 MT_MISC60,
1345 MT_MISC61,
1346 MT_MISC62,
1347 MT_MISC63,
1348 MT_MISC64,
1349 MT_MISC65,
1350 MT_MISC66,
1351 MT_MISC67,
1352 MT_MISC68,
1353 MT_MISC69,
1354 MT_MISC70,
1355 MT_MISC71,
1356 MT_MISC72,
1357 MT_MISC73,
1358 MT_MISC74,
1359 MT_MISC75,
1360 MT_MISC76,
1361 MT_MISC77,
1362 MT_MISC78,
1363 MT_MISC79,
1364 MT_MISC80,
1365 MT_MISC81,
1366 MT_MISC82,
1367 MT_MISC83,
1368 MT_MISC84,
1369 MT_MISC85,
1370 MT_MISC86,
1371 MT_PUSH, /* controls push source - phares */
1372 MT_PULL, /* controls pull source - phares 3/20/98 */
1373
1374#ifdef DOGS
1375 MT_DOGS, /* killough 7/19/98: Marine's best friend */
1376#endif
1377
1378 /* proff 11/22/98: Andy Baker's stealth monsters (next 12)
1379 * cph - moved below the MBF stuff, no need to displace them */
1380 MT_STEALTHBABY,
1381 MT_STEALTHVILE,
1382 MT_STEALTHBRUISER,
1383 MT_STEALTHHEAD,
1384 MT_STEALTHCHAINGUY,
1385 MT_STEALTHSERGEANT,
1386 MT_STEALTHKNIGHT,
1387 MT_STEALTHIMP,
1388 MT_STEALTHFATSO,
1389 MT_STEALTHUNDEAD,
1390 MT_STEALTHSHOTGUY,
1391 MT_STEALTHZOMBIE,
1392 NUMMOBJTYPES
1393
1394} mobjtype_t;
1395
1396/********************************************************************
1397 * Definition of the Thing structure
1398 ********************************************************************/
1399/* Note that these are only indices to the state, sound, etc. arrays
1400 * and not actual pointers. Most can be set to zero if the action or
1401 * sound doesn't apply (like lamps generally don't attack or whistle).
1402 */
1403
1404typedef struct
1405{
1406 int doomednum; /* Thing number used in id's editor, and now
1407 probably by every other editor too */
1408 int spawnstate; /* The state (frame) index when this Thing is
1409 first created */
1410 int spawnhealth; /* The initial hit points for this Thing */
1411 int seestate; /* The state when it sees you or wakes up */
1412 int seesound; /* The sound it makes when waking */
1413 int reactiontime; /* How many tics it waits after it wakes up
1414 before it will start to attack, in normal
1415 skills (halved for nightmare) */
1416 int attacksound; /* The sound it makes when it attacks */
1417 int painstate; /* The state to indicate pain */
1418 int painchance; /* A number that is checked against a random
1419 number 0-255 to see if the Thing is supposed
1420 to go to its painstate or not. Note this
1421 has absolutely nothing to do with the chance
1422 it will get hurt, just the chance of it
1423 reacting visibly. */
1424 int painsound; /* The sound it emits when it feels pain */
1425 int meleestate; /* Melee==close attack */
1426 int missilestate; /* What states to use when it's in the air, if
1427 in fact it is ever used as a missile */
1428 int deathstate; /* What state begins the death sequence */
1429 int xdeathstate; /* What state begins the horrible death sequence
1430 like when a rocket takes out a trooper */
1431 int deathsound; /* The death sound. See also A_Scream() in
1432 p_enemy.c for some tweaking that goes on
1433 for certain monsters */
1434 int speed; /* How fast it moves. Too fast and it can miss
1435 collision logic. */
1436 int radius; /* An often incorrect radius */
1437 int height; /* An often incorrect height, used only to see
1438 if a monster can enter a sector */
1439 int mass; /* How much an impact will move it. Cacodemons
1440 seem to retreat when shot because they have
1441 very little mass and are moved by impact */
1442 int damage; /* If this is a missile, how much does it hurt? */
1443 int activesound; /* What sound it makes wandering around, once
1444 in a while. Chance is 3/256 it will. */
1445 uint_64_t flags; /* Bit masks for lots of things. See p_mobj.h */
1446 int raisestate; /* The first state for an Archvile or respawn
1447 resurrection. Zero means it won't come
1448 back to life. */
1449} mobjinfo_t;
1450
1451/* See p_mobj_h for addition more technical info */
1452extern mobjinfo_t mobjinfo[NUMMOBJTYPES];
1453
1454#endif
diff --git a/apps/plugins/doom/m_argv.c b/apps/plugins/doom/m_argv.c
new file mode 100644
index 0000000000..253fb01aba
--- /dev/null
+++ b/apps/plugins/doom/m_argv.c
@@ -0,0 +1,53 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION:
28 * Some argument handling.
29 *
30 *-----------------------------------------------------------------------------*/
31
32#include "rockmacros.h"
33#include "m_argv.h"
34
35int myargc;
36char** myargv;
37
38//
39// M_CheckParm
40// Checks for the given parameter
41// in the program's command line arguments.
42// Returns the argument number (1 to argc-1)
43// or 0 if not present
44//
45
46int M_CheckParm(const char *check)
47{
48 signed int i = myargc;
49 while (--i>0)
50 if (!strcasecmp(check, myargv[i]))
51 return i;
52 return 0;
53}
diff --git a/apps/plugins/doom/m_argv.h b/apps/plugins/doom/m_argv.h
new file mode 100644
index 0000000000..61e7a27069
--- /dev/null
+++ b/apps/plugins/doom/m_argv.h
@@ -0,0 +1,45 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION:
28 * Argument handling.
29 *
30 *-----------------------------------------------------------------------------*/
31
32
33#ifndef __M_ARGV__
34#define __M_ARGV__
35
36//
37// MISC
38//
39extern int myargc;
40extern char** myargv;
41
42/* Returns the position of the given parameter in the arg list (0 if not found). */
43int M_CheckParm(const char *check);
44
45#endif
diff --git a/apps/plugins/doom/m_bbox.c b/apps/plugins/doom/m_bbox.c
new file mode 100644
index 0000000000..916ed7a401
--- /dev/null
+++ b/apps/plugins/doom/m_bbox.c
@@ -0,0 +1,58 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION:
28 * Main loop menu stuff.
29 * Random number LUT.
30 * Default Config File.
31 * PCX Screenshots.
32 *
33 *-----------------------------------------------------------------------------*/
34
35#ifdef __GNUG__
36#pragma implementation "m_bbox.h"
37#endif
38#include "m_bbox.h"
39
40#include "rockmacros.h"
41
42void M_ClearBox (fixed_t *box)
43{
44 box[BOXTOP] = box[BOXRIGHT] = MININT;
45 box[BOXBOTTOM] = box[BOXLEFT] = MAXINT;
46}
47
48void M_AddToBox(fixed_t* box,fixed_t x,fixed_t y)
49{
50 if (x<box[BOXLEFT])
51 box[BOXLEFT] = x;
52 else if (x>box[BOXRIGHT])
53 box[BOXRIGHT] = x;
54 if (y<box[BOXBOTTOM])
55 box[BOXBOTTOM] = y;
56 else if (y>box[BOXTOP])
57 box[BOXTOP] = y;
58}
diff --git a/apps/plugins/doom/m_bbox.h b/apps/plugins/doom/m_bbox.h
new file mode 100644
index 0000000000..32202ec543
--- /dev/null
+++ b/apps/plugins/doom/m_bbox.h
@@ -0,0 +1,54 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION:
28 * Simple bounding box datatype and functions.
29 *
30 *-----------------------------------------------------------------------------*/
31
32
33#ifndef __M_BBOX__
34#define __M_BBOX__
35
36#include <limits.h>
37#include "m_fixed.h"
38
39/* Bounding box coordinate storage. */
40enum
41{
42 BOXTOP,
43 BOXBOTTOM,
44 BOXLEFT,
45 BOXRIGHT
46}; /* bbox coordinates */
47
48/* Bounding box functions. */
49
50void M_ClearBox(fixed_t* box);
51
52void M_AddToBox(fixed_t* box,fixed_t x,fixed_t y);
53
54#endif
diff --git a/apps/plugins/doom/m_cheat.c b/apps/plugins/doom/m_cheat.c
new file mode 100644
index 0000000000..afd68e960d
--- /dev/null
+++ b/apps/plugins/doom/m_cheat.c
@@ -0,0 +1,104 @@
1// Emacs style mode select -*- C++ -*-
2//-----------------------------------------------------------------------------
3//
4// $Id$
5//
6// Copyright (C) 1993-1996 by id Software, Inc.
7//
8// This program is free software; you can redistribute it and/or
9// modify it under the terms of the GNU General Public License
10// as published by the Free Software Foundation; either version 2
11// of the License, or (at your option) any later version.
12//
13// This program is distributed in the hope that it will be useful,
14// but WITHOUT ANY WARRANTY; without even the implied warranty of
15// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16// GNU General Public License for more details.
17//
18// $Log$
19// Revision 1.1 2006/03/28 15:44:01 dave
20// Patch #2969 - Doom! Currently only working on the H300.
21//
22//
23// DESCRIPTION:
24// Cheat sequence checking.
25//
26//-----------------------------------------------------------------------------
27
28#include "m_cheat.h"
29
30//
31// CHEAT SEQUENCE PACKAGE
32//
33
34static int firsttime = 1;
35static unsigned char cheat_xlate_table[20];
36
37
38//
39// Called in st_stuff module, which handles the input.
40// Returns a 1 if the cheat was successful, 0 if failed.
41//
42int
43cht_CheckCheat
44( cheatseq_t* cht,
45 char key )
46{
47 int i;
48 int rc = 0;
49
50 if (firsttime)
51 {
52 firsttime = 0;
53 for (i=0;i<256;i++)
54 cheat_xlate_table[i] = SCRAMBLE(i);
55 }
56
57 if (!cht->p)
58 cht->p = cht->sequence; // initialize if first time
59
60 if (*cht->p == 0)
61 *(cht->p++) = key;
62 else if
63 (cheat_xlate_table[(unsigned char)key] == *cht->p)
64 cht->p++;
65 else
66 cht->p = cht->sequence;
67
68 if (*cht->p == 1)
69 cht->p++;
70 else if (*cht->p == 0xff) // end of sequence character
71 {
72 cht->p = cht->sequence;
73 rc = 1;
74 }
75
76 return rc;
77}
78
79void
80cht_GetParam
81( cheatseq_t* cht,
82 char* buffer )
83{
84
85 unsigned char *p, c;
86
87 p = cht->sequence;
88 while (*(p++) != 1)
89 ;
90
91 do
92 {
93 c = *p;
94 *(buffer++) = c;
95 *(p++) = 0;
96 }
97 while (c && *p!=0xff );
98
99 if (*p==0xff)
100 *buffer = 0;
101
102}
103
104
diff --git a/apps/plugins/doom/m_cheat.h b/apps/plugins/doom/m_cheat.h
new file mode 100644
index 0000000000..dfa916ffdb
--- /dev/null
+++ b/apps/plugins/doom/m_cheat.h
@@ -0,0 +1,63 @@
1// Emacs style mode select -*- C++ -*-
2//-----------------------------------------------------------------------------
3//
4// $Id$
5//
6// Copyright (C) 1993-1996 by id Software, Inc.
7//
8// This program is free software; you can redistribute it and/or
9// modify it under the terms of the GNU General Public License
10// as published by the Free Software Foundation; either version 2
11// of the License, or (at your option) any later version.
12//
13// This program is distributed in the hope that it will be useful,
14// but WITHOUT ANY WARRANTY; without even the implied warranty of
15// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16// GNU General Public License for more details.
17//
18// DESCRIPTION:
19// Cheat code checking.
20//
21//-----------------------------------------------------------------------------
22
23
24#ifndef __M_CHEAT__
25#define __M_CHEAT__
26
27//
28// CHEAT SEQUENCE PACKAGE
29//
30
31#define SCRAMBLE(a) \
32((((a)&1)<<7) + (((a)&2)<<5) + ((a)&4) + (((a)&8)<<1) \
33 + (((a)&16)>>1) + ((a)&32) + (((a)&64)>>5) + (((a)&128)>>7))
34
35typedef struct
36{
37 unsigned char* sequence;
38 unsigned char* p;
39
40}
41cheatseq_t;
42
43int
44cht_CheckCheat
45( cheatseq_t* cht,
46 char key );
47
48
49void
50cht_GetParam
51( cheatseq_t* cht,
52 char* buffer );
53
54
55#endif
56//-----------------------------------------------------------------------------
57//
58// $Log$
59// Revision 1.1 2006/03/28 15:44:01 dave
60// Patch #2969 - Doom! Currently only working on the H300.
61//
62//
63//-----------------------------------------------------------------------------
diff --git a/apps/plugins/doom/m_fixed.h b/apps/plugins/doom/m_fixed.h
new file mode 100644
index 0000000000..3c922e8f50
--- /dev/null
+++ b/apps/plugins/doom/m_fixed.h
@@ -0,0 +1,94 @@
1// Emacs style mode select -*- C++ -*-
2//-----------------------------------------------------------------------------
3//
4// $Id$
5//
6// Copyright (C) 1993-1996 by id Software, Inc.
7//
8// This program is free software; you can redistribute it and/or
9// modify it under the terms of the GNU General Public License
10// as published by the Free Software Foundation; either version 2
11// of the License, or (at your option) any later version.
12//
13// This program is distributed in the hope that it will be useful,
14// but WITHOUT ANY WARRANTY; without even the implied warranty of
15// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16// GNU General Public License for more details.
17//
18// DESCRIPTION:
19// Fixed point arithemtics, implementation.
20//
21//-----------------------------------------------------------------------------
22
23
24#ifndef __M_FIXED__
25#define __M_FIXED__
26
27
28#ifdef __GNUG__
29#pragma interface
30#endif
31
32#include "doomtype.h"
33#include "rockmacros.h"
34
35//
36// Fixed point, 32bit as 16.16.
37//
38#define FRACBITS 16
39#define FRACUNIT (1<<FRACBITS)
40
41#define D_abs(x) ({fixed_t _t = (x), _s = _t >> (8*sizeof _t-1); (_t^_s)-_s;})
42
43typedef int fixed_t;
44
45inline static int FixedMul( int a, int b )
46{
47#if defined(CPU_COLDFIRE) && !defined(SIMULATOR)
48 // Code contributed by Thom Johansen
49 register int result;
50 asm volatile (
51 "mac.l %[x],%[y],%%acc0 \n" /* multiply */
52 "move.l %[y],%%d2 \n"
53 "mulu.l %[x],%%d2 \n" /* get lower half, avoid emac stall */
54 "movclr.l %%acc0,%[result] \n" /* get higher half */
55 "moveq.l #15,%%d1 \n"
56 "asl.l %%d1,%[result] \n" /* hi <<= 15, plus one free */
57 "moveq.l #16,%%d1 \n"
58 "lsr.l %%d1,%%d2 \n" /* (unsigned)lo >>= 16 */
59 "or.l %%d2 ,%[result] \n" /* combine result */
60 : /* outputs */
61 [result]"=&d"(result)
62 : /* inputs */
63 [x] "d" (a),
64 [y] "d" (b)
65 : /* clobbers */
66 "d1", "d2"
67 );
68 return result;
69#else
70 return (fixed_t)((long long) a*b >> FRACBITS);
71#endif
72}
73
74inline static fixed_t FixedDiv( fixed_t a, fixed_t b )
75{
76 return (D_abs(a)>>14) >= D_abs(b) ? ((a^b)>>31) ^ MAXINT :
77 (fixed_t)(((long long) a << FRACBITS) / b);
78}
79
80/* CPhipps -
81 * FixedMod - returns a % b, guaranteeing 0<=a<b
82 * (notice that the C standard for % does not guarantee this)
83 */
84
85inline static fixed_t FixedMod(fixed_t a, fixed_t b)
86{
87 if (b & (b-1)) {
88 fixed_t r = a % b;
89 return ((r<0) ? r+b : r);
90 } else
91 return (a & (b-1));
92}
93
94#endif
diff --git a/apps/plugins/doom/m_menu.c b/apps/plugins/doom/m_menu.c
new file mode 100644
index 0000000000..34f3e22ce2
--- /dev/null
+++ b/apps/plugins/doom/m_menu.c
@@ -0,0 +1,1848 @@
1// Emacs style mode select -*- C++ -*-
2//-----------------------------------------------------------------------------
3//
4// $Id$
5//
6// Copyright (C) 1993-1996 by id Software, Inc.
7//
8// This program is free software; you can redistribute it and/or
9// modify it under the terms of the GNU General Public License
10// as published by the Free Software Foundation; either version 2
11// of the License, or (at your option) any later version.
12//
13// This program is distributed in the hope that it will be useful,
14// but WITHOUT ANY WARRANTY; without even the implied warranty of
15// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16// GNU General Public License for more details.
17//
18// $Log$
19// Revision 1.1 2006/03/28 15:44:01 dave
20// Patch #2969 - Doom! Currently only working on the H300.
21//
22//
23// DESCRIPTION:
24// DOOM selection menu, options, episode etc.
25// Sliders and icons. Kinda widget stuff.
26//
27//-----------------------------------------------------------------------------
28
29#include "doomdef.h"
30#include "dstrings.h"
31
32#include "d_main.h"
33
34#include "i_system.h"
35#include "i_video.h"
36#include "z_zone.h"
37#include "v_video.h"
38#include "w_wad.h"
39
40#include "r_main.h"
41
42#include "hu_stuff.h"
43
44#include "g_game.h"
45
46#include "m_argv.h"
47#include "m_swap.h"
48#include "s_sound.h"
49
50#include "doomstat.h"
51
52// Data.
53#include "sounds.h"
54
55#include "m_menu.h"
56#include "rockmacros.h"
57
58
59extern patchnum_t hu_font[HU_FONTSIZE];
60extern boolean message_dontfuckwithme;
61
62extern boolean chat_on; // in heads-up code
63
64//
65// defaulted values
66//
67int mouseSensitivity; // has default
68
69// Show messages has default, 0 = off, 1 = on
70int showMessages;
71
72// Blocky mode, has default, 0 = high, 1 = normal
73int screenblocks; // has default
74
75// temp for screenblocks (0-9)
76int screenSize;
77
78// -1 = no quicksave slot picked!
79int quickSaveSlot;
80
81// 1 = message to be printed
82int messageToPrint;
83// ...and here is the message string!
84char* messageString;
85
86// message x & y
87int messx;
88int messy;
89int messageLastMenuActive;
90
91// timed message = no input from user
92boolean messageNeedsInput;
93
94void (*messageRoutine)(int response);
95
96#define SAVESTRINGSIZE 24
97
98char gammamsg[5][26] =
99 {
100 GAMMALVL0,
101 GAMMALVL1,
102 GAMMALVL2,
103 GAMMALVL3,
104 GAMMALVL4
105 };
106
107// we are going to be entering a savegame string
108int saveStringEnter;
109int saveSlot; // which slot to save in
110int saveCharIndex; // which char we're editing
111// old save description before edit
112char saveOldString[SAVESTRINGSIZE];
113
114boolean inhelpscreens;
115boolean menuactive;
116
117#define SKULLXOFF -32
118#define LINEHEIGHT 16
119
120extern boolean sendpause;
121char savegamestrings[10][SAVESTRINGSIZE];
122
123char endstring[170];
124
125
126//
127// MENU TYPEDEFS
128//
129typedef struct
130{
131 // 0 = no cursor here, 1 = ok, 2 = arrows ok
132 short status;
133
134 char name[10];
135
136 // choice = menu item #.
137 // if status = 2,
138 // choice=0:leftarrow,1:rightarrow
139 void (*routine)(int choice);
140
141 // hotkey in menu
142 char alphaKey;
143}
144menuitem_t;
145
146
147
148typedef struct menu_s
149{
150 short numitems; // # of menu items
151 struct menu_s* prevMenu; // previous menu
152 menuitem_t* menuitems; // menu items
153 void (*routine)(void); // draw routine ROCKBOX
154 short x;
155 short y; // x,y of menu
156 short lastOn; // last item user was on in menu
157}
158menu_t;
159
160short itemOn; // menu item skull is on
161short skullAnimCounter; // skull animation counter
162short whichSkull; // which skull to draw
163int systemvol;
164
165// graphic name of skulls
166// warning: initializer-string for array of chars is too long
167char skullName[2][/*8*/9] = {"M_SKULL1","M_SKULL2"};
168
169// current menudef
170menu_t* currentMenu;
171
172//
173// PROTOTYPES
174//
175void M_NewGame(int choice);
176void M_Episode(int choice);
177void M_ChooseSkill(int choice);
178void M_LoadGame(int choice);
179void M_SaveGame(int choice);
180void M_Options(int choice);
181void M_EndGame(int choice);
182void M_ReadThis(int choice);
183void M_ReadThis2(int choice);
184void M_QuitDOOM(int choice);
185
186void M_ChangeMessages(int choice);
187void M_ChangeSensitivity(int choice);
188void M_SfxVol(int choice);
189void M_MusicVol(int choice);
190void M_SystemVol(int choice);
191void M_SizeDisplay(int choice);
192void M_StartGame(int choice);
193void M_Sound(int choice);
194
195void M_FinishReadThis(int choice);
196void M_LoadSelect(int choice);
197void M_SaveSelect(int choice);
198void M_ReadSaveStrings(void);
199void M_QuickSave(void);
200void M_QuickLoad(void);
201
202void M_DrawMainMenu(void);
203void M_DrawReadThis1(void);
204void M_DrawReadThis2(void);
205void M_DrawNewGame(void);
206void M_DrawEpisode(void);
207void M_DrawOptions(void);
208void M_DrawSound(void);
209void M_DrawLoad(void);
210void M_DrawSave(void);
211
212void M_DrawSaveLoadBorder(int x,int y);
213void M_SetupNextMenu(menu_t *menudef);
214void M_DrawThermo(int x,int y,int thermWidth,int thermDot);
215void M_DrawEmptyCell(menu_t *menu,int item);
216void M_DrawSelCell(menu_t *menu,int item);
217void M_WriteText(int x, int y, char *string);
218int M_StringWidth(const char* string);
219int M_StringHeight(const char* string);
220void M_StartControlPanel(void);
221void M_StartMessage(char *string,void *routine,boolean input);
222void M_StopMessage(void);
223void M_ClearMenus (void);
224
225
226
227
228//
229// DOOM MENU
230//
231enum
232{
233 newgame = 0,
234 options,
235 loadgame,
236 savegame,
237 readthis,
238 quitdoom,
239 main_end
240} main_e;
241
242menuitem_t MainMenu[]=
243 {
244 {1,"M_NGAME",M_NewGame,'n'},
245 {1,"M_OPTION",M_Options,'o'},
246 {1,"M_LOADG",M_LoadGame,'l'},
247 {1,"M_SAVEG",M_SaveGame,'s'},
248 // Another hickup with Special edition.
249 {1,"M_RDTHIS",M_ReadThis,'r'},
250 {1,"M_QUITG",M_QuitDOOM,'q'}
251 };
252
253menu_t MainDef =
254 {
255 main_end,
256 NULL,
257 MainMenu,
258 M_DrawMainMenu,
259 97,64,
260 0
261 };
262
263
264//
265// EPISODE SELECT
266//
267enum
268{
269 ep1,
270 ep2,
271 ep3,
272 ep4,
273 ep_end
274} episodes_e;
275
276menuitem_t EpisodeMenu[]=
277 {
278 {1,"M_EPI1", M_Episode,'k'},
279 {1,"M_EPI2", M_Episode,'t'},
280 {1,"M_EPI3", M_Episode,'i'},
281 {1,"M_EPI4", M_Episode,'t'}
282 };
283
284menu_t EpiDef =
285 {
286 ep_end, // # of menu items
287 &MainDef, // previous menu
288 EpisodeMenu, // menuitem_t ->
289 M_DrawEpisode, // drawing routine ->
290 48,63, // x,y
291 ep1 // lastOn
292 };
293
294//
295// NEW GAME
296//
297enum
298{
299 killthings,
300 toorough,
301 hurtme,
302 violence,
303 nightmare,
304 newg_end
305} newgame_e;
306
307menuitem_t NewGameMenu[]=
308 {
309 {1,"M_JKILL", M_ChooseSkill, 'i'},
310 {1,"M_ROUGH", M_ChooseSkill, 'h'},
311 {1,"M_HURT", M_ChooseSkill, 'h'},
312 {1,"M_ULTRA", M_ChooseSkill, 'u'},
313 {1,"M_NMARE", M_ChooseSkill, 'n'}
314 };
315
316menu_t NewDef =
317 {
318 newg_end, // # of menu items
319 &EpiDef, // previous menu
320 NewGameMenu, // menuitem_t ->
321 M_DrawNewGame, // drawing routine ->
322 48,63, // x,y
323 hurtme // lastOn
324 };
325
326
327
328//
329// OPTIONS MENU
330//
331enum
332{
333 endgame,
334 messages,
335 scrnsize,
336 option_empty1,
337 gamasens,
338 option_empty2,
339 soundvol,
340 opt_end
341} options_e;
342
343menuitem_t OptionsMenu[]=
344 {
345 {1,"M_ENDGAM", M_EndGame,'e'},
346 {1,"M_MESSG", M_ChangeMessages,'m'},
347 {2,"M_SCRNSZ", M_SizeDisplay,'s'},
348 {-1,"",0,0},
349 {2,"M_MSENS", M_ChangeSensitivity,'m'},
350 {-1,"",0,0},
351 {1,"M_SVOL", M_Sound,'s'}
352 };
353
354menu_t OptionsDef =
355 {
356 opt_end,
357 &MainDef,
358 OptionsMenu,
359 M_DrawOptions,
360 60,37,
361 0
362 };
363
364//
365// Read This! MENU 1 & 2
366//
367enum
368{
369 rdthsempty1,
370 read1_end
371} read_e;
372
373menuitem_t ReadMenu1[] =
374 {
375 {1,"",M_ReadThis2,0}
376 };
377
378menu_t ReadDef1 =
379 {
380 read1_end,
381 &MainDef,
382 ReadMenu1,
383 M_DrawReadThis1,
384 280,185,
385 0
386 };
387
388enum
389{
390 rdthsempty2,
391 read2_end
392} read_e2;
393
394menuitem_t ReadMenu2[]=
395 {
396 {1,"",M_FinishReadThis,0}
397 };
398
399menu_t ReadDef2 =
400 {
401 read2_end,
402 &ReadDef1,
403 ReadMenu2,
404 M_DrawReadThis2,
405 330,175,
406 0
407 };
408
409//
410// SOUND VOLUME MENU
411//
412enum
413{
414 sfx_vol,
415 sfx_empty1,
416 music_vol,
417 sfx_empty2,
418 system_vol,
419 sfx_empty3,
420 sound_end
421} sound_e;
422
423menuitem_t SoundMenu[]=
424 {
425 {2,"M_SFXVOL",M_SfxVol,'s'},
426 {-1,"",0,0}, //ROCKBOX
427 {2,"M_MUSVOL",M_MusicVol,'m'},
428 {-1,"",0,0}, //ROCKBOX
429 {2,"M_MUSVOL",M_SystemVol,'z'},
430 {-1,"",0,0} //ROCKBOX
431 };
432
433menu_t SoundDef =
434 {
435 sound_end,
436 &OptionsDef,
437 SoundMenu,
438 M_DrawSound,
439 80,64,
440 0
441 };
442
443//
444// LOAD GAME MENU
445//
446enum
447{
448 load1,
449 load2,
450 load3,
451 load4,
452 load5,
453 load6,
454 load_end
455} load_e;
456
457menuitem_t LoadMenu[]=
458 {
459 {1,"", M_LoadSelect,'1'},
460 {1,"", M_LoadSelect,'2'},
461 {1,"", M_LoadSelect,'3'},
462 {1,"", M_LoadSelect,'4'},
463 {1,"", M_LoadSelect,'5'},
464 {1,"", M_LoadSelect,'6'}
465 };
466
467menu_t LoadDef =
468 {
469 load_end,
470 &MainDef,
471 LoadMenu,
472 M_DrawLoad,
473 80,54,
474 0
475 };
476
477//
478// SAVE GAME MENU
479//
480menuitem_t SaveMenu[]=
481 {
482 {1,"", M_SaveSelect,'1'},
483 {1,"", M_SaveSelect,'2'},
484 {1,"", M_SaveSelect,'3'},
485 {1,"", M_SaveSelect,'4'},
486 {1,"", M_SaveSelect,'5'},
487 {1,"", M_SaveSelect,'6'}
488 };
489
490menu_t SaveDef =
491 {
492 load_end,
493 &MainDef,
494 SaveMenu,
495 M_DrawSave,
496 80,54,
497 0
498 };
499
500
501//
502// M_ReadSaveStrings
503// read the strings from the savegame files
504//
505void M_ReadSaveStrings(void)
506{
507 int handle;
508 int count;
509 int i;
510 char name[256];
511
512 for (i = 0;i < load_end;i++)
513 {
514 if (M_CheckParm("-cdrom"))
515 snprintf(name,sizeof(name),"c:\\doomdata\\"SAVEGAMENAME"%d.dsg",i);
516 else
517 snprintf(name,sizeof(name),SAVEGAMENAME"%d.dsg",i);
518
519 handle = open (name, O_RDONLY | 0);
520 if (handle == -1)
521 {
522 strcpy(&savegamestrings[i][0],EMPTYSTRING);
523 LoadMenu[i].status = 0;
524 continue;
525 }
526 count = read (handle, &savegamestrings[i], SAVESTRINGSIZE);
527 close (handle);
528 LoadMenu[i].status = 1;
529 }
530}
531
532#define LOADGRAPHIC_Y 8
533//
534// M_LoadGame & Cie.
535//
536void M_DrawLoad(void)
537{
538 int i;
539
540 V_DrawNamePatch(72 ,LOADGRAPHIC_Y, 0, "M_LOADG", CR_DEFAULT, VPT_STRETCH);
541 for (i = 0;i < load_end; i++)
542 {
543 M_DrawSaveLoadBorder(LoadDef.x,LoadDef.y+LINEHEIGHT*i);
544 M_WriteText(LoadDef.x,LoadDef.y+LINEHEIGHT*i,savegamestrings[i]);
545 }
546}
547
548
549
550//
551// Draw border for the savegame description
552//
553void M_DrawSaveLoadBorder(int x,int y)
554{
555 int i;
556
557 V_DrawNamePatch(x-8, y+7, 0, "M_LSLEFT", CR_DEFAULT, VPT_STRETCH);
558 for (i = 0;i < 24;i++)
559 {
560 V_DrawNamePatch(x, y+7, 0, "M_LSCNTR", CR_DEFAULT, VPT_STRETCH);
561 x += 8;
562 }
563 V_DrawNamePatch(x, y+7, 0, "M_LSRGHT", CR_DEFAULT, VPT_STRETCH);
564}
565
566
567
568//
569// User wants to load this game
570//
571void M_LoadSelect(int choice)
572{
573 char name[256];
574
575 if (M_CheckParm("-cdrom"))
576 snprintf(name,sizeof(name),"c:\\doomdata\\"SAVEGAMENAME"%d.dsg",choice);
577 else
578 snprintf(name,sizeof(name),SAVEGAMENAME"%d.dsg",choice);
579 G_LoadGame (choice, false);
580 M_ClearMenus ();
581}
582
583//
584// Selected from DOOM menu
585//
586void M_LoadGame (int choice)
587{
588 (void)choice;
589 if (netgame)
590 {
591 M_StartMessage(LOADNET,NULL,false);
592 return;
593 }
594
595 M_SetupNextMenu(&LoadDef);
596 M_ReadSaveStrings();
597}
598
599
600//
601// M_SaveGame & Cie.
602//
603void M_DrawSave(void)
604{
605 int i;
606
607 V_DrawNamePatch(72, LOADGRAPHIC_Y, 0, "M_SAVEG", CR_DEFAULT, VPT_STRETCH);
608 for (i = 0;i < load_end; i++)
609 {
610 M_DrawSaveLoadBorder(LoadDef.x,LoadDef.y+LINEHEIGHT*i);
611 M_WriteText(LoadDef.x,LoadDef.y+LINEHEIGHT*i,savegamestrings[i]);
612 }
613
614 if (saveStringEnter)
615 {
616 i = M_StringWidth(savegamestrings[saveSlot]);
617 M_WriteText(LoadDef.x + i,LoadDef.y+LINEHEIGHT*saveSlot,"_");
618 }
619}
620
621//
622// M_Responder calls this when user is finished
623//
624void M_DoSave(int slot)
625{
626 G_SaveGame (slot,savegamestrings[slot]);
627 M_ClearMenus ();
628
629 // PICK QUICKSAVE SLOT YET?
630 if (quickSaveSlot == -2)
631 quickSaveSlot = slot;
632}
633
634//
635// User wants to save. Start string input for M_Responder
636//
637void M_SaveSelect(int choice)
638{
639 // we are going to be intercepting all chars
640 saveStringEnter = 1;
641
642 saveSlot = choice;
643 snprintf(savegamestrings[choice], sizeof(savegamestrings[choice]), "Mysave%d", choice);
644// strcpy(saveOldString,savegamestrings[choice]);
645 if (!strcmp(savegamestrings[choice],EMPTYSTRING))
646 savegamestrings[choice][0] = 0;
647 saveCharIndex = strlen(savegamestrings[choice]);
648}
649
650//
651// Selected from DOOM menu
652//
653void M_SaveGame (int choice)
654{
655 (void)choice;
656 if (!usergame)
657 {
658 M_StartMessage(SAVEDEAD,NULL,false);
659 return;
660 }
661
662 if (gamestate != GS_LEVEL)
663 return;
664
665 M_SetupNextMenu(&SaveDef);
666 M_ReadSaveStrings();
667}
668
669
670
671//
672// M_QuickSave
673//
674char tempstring[80];
675
676void M_QuickSaveResponse(int ch)
677{
678 if (ch == 'y')
679 {
680 M_DoSave(quickSaveSlot);
681
682 S_StartSound(NULL,sfx_swtchx);
683
684 }
685}
686
687void M_QuickSave(void)
688{
689 if (!usergame)
690 {
691 S_StartSound(NULL,sfx_oof);
692 return;
693 }
694
695 if (gamestate != GS_LEVEL)
696 return;
697
698 if (quickSaveSlot < 0)
699 {
700 M_StartControlPanel();
701 M_ReadSaveStrings();
702 M_SetupNextMenu(&SaveDef);
703 quickSaveSlot = -2; // means to pick a slot now
704 return;
705 }
706 snprintf(tempstring,sizeof(tempstring),QSPROMPT,savegamestrings[quickSaveSlot]);
707 M_StartMessage(tempstring,M_QuickSaveResponse,true);
708}
709
710
711
712//
713// M_QuickLoad
714//
715void M_QuickLoadResponse(int ch)
716{
717 if (ch == 'y')
718 {
719 M_LoadSelect(quickSaveSlot);
720 S_StartSound(NULL,sfx_swtchx);
721 }
722}
723
724
725void M_QuickLoad(void)
726{
727 if (netgame)
728 {
729 M_StartMessage(QLOADNET,NULL,false);
730 return;
731 }
732
733 if (quickSaveSlot < 0)
734 {
735 M_StartMessage(QSAVESPOT,NULL,false);
736 return;
737 }
738 snprintf(tempstring, sizeof(tempstring), QLPROMPT,savegamestrings[quickSaveSlot]);
739 M_StartMessage(tempstring,M_QuickLoadResponse,true);
740}
741
742
743
744
745//
746// Read This Menus
747// Had a "quick hack to fix romero bug"
748//
749void M_DrawReadThis1(void)
750{
751 inhelpscreens = true;
752 switch ( gamemode )
753 {
754 case commercial:
755 V_DrawNamePatch(0, 0, 0, "HELP", CR_DEFAULT, VPT_STRETCH);
756 break;
757 case shareware:
758 case registered:
759 case retail:
760 V_DrawNamePatch(0, 0, 0, "HELP1", CR_DEFAULT, VPT_STRETCH);
761 break;
762 default:
763 break;
764 }
765 return;
766}
767
768
769
770//
771// Read This Menus - optional second page.
772//
773void M_DrawReadThis2(void)
774{
775 inhelpscreens = true;
776 switch ( gamemode )
777 {
778 case retail:
779 case commercial:
780 // This hack keeps us from having to change menus.
781 V_DrawNamePatch(0, 0, 0, "CREDIT", CR_DEFAULT, VPT_STRETCH);
782 break;
783 case shareware:
784 case registered:
785 V_DrawNamePatch(0, 0, 0, "HELP2", CR_DEFAULT, VPT_STRETCH);
786 break;
787 default:
788 break;
789 }
790 return;
791}
792
793
794//
795// Change Sfx & Music volumes
796//
797void M_DrawSound(void)
798{
799 int sysmax=(rb->sound_max(SOUND_VOLUME)-rb->sound_min(SOUND_VOLUME));
800 V_DrawNamePatch(60, 38, 0, "M_SVOL", CR_DEFAULT, VPT_STRETCH);
801
802 M_DrawThermo(SoundDef.x,SoundDef.y+LINEHEIGHT*(sfx_vol+1),
803 16,snd_SfxVolume);
804
805 M_DrawThermo(SoundDef.x,SoundDef.y+LINEHEIGHT*(music_vol+1),
806 16,snd_MusicVolume);
807
808 M_DrawThermo(SoundDef.x,SoundDef.y+LINEHEIGHT*(system_vol+1),
809 16,(sysmax+systemvol)/5);
810}
811
812void M_Sound(int choice)
813{
814 (void) choice;
815 M_SetupNextMenu(&SoundDef);
816}
817
818void M_SfxVol(int choice)
819{
820 switch(choice)
821 {
822 case 0:
823 if (snd_SfxVolume)
824 snd_SfxVolume--;
825 break;
826 case 1:
827 if (snd_SfxVolume < 15)
828 snd_SfxVolume++;
829 break;
830 }
831
832 S_SetSfxVolume(snd_SfxVolume /* *8 */);
833}
834
835void M_MusicVol(int choice)
836{
837 switch(choice)
838 {
839 case 0:
840 if (snd_MusicVolume)
841 snd_MusicVolume--;
842 break;
843 case 1:
844 if (snd_MusicVolume < 15)
845 snd_MusicVolume++;
846 break;
847 }
848
849 S_SetMusicVolume(snd_MusicVolume /* *8 */);
850}
851
852void M_SystemVol(int choice)
853{
854 switch(choice)
855 {
856 case 0:
857 if (systemvol-5>rb->sound_min(SOUND_VOLUME))
858 {
859 systemvol-=5;
860 rb->sound_set(SOUND_VOLUME, systemvol);
861 rb->global_settings->volume = systemvol;
862 }
863 break;
864 case 1:
865 if (systemvol+5<rb->sound_max(SOUND_VOLUME))
866 {
867 systemvol+=5;
868 rb->sound_set(SOUND_VOLUME, systemvol);
869 rb->global_settings->volume = systemvol;
870 }
871 break;
872 }
873}
874
875//
876// M_DrawMainMenu
877//
878void M_DrawMainMenu(void)
879{
880 V_DrawNamePatch(94, 2, 0, "M_DOOM", CR_DEFAULT, VPT_STRETCH);
881}
882
883
884
885
886//
887// M_NewGame
888//
889void M_DrawNewGame(void)
890{
891 // CPhipps - patch drawing updated
892 V_DrawNamePatch(96, 14, 0, "M_NEWG", CR_DEFAULT, VPT_STRETCH);
893 V_DrawNamePatch(54, 38, 0, "M_SKILL",CR_DEFAULT, VPT_STRETCH);
894}
895
896void M_NewGame(int choice)
897{
898 (void) choice;
899 if (netgame && !demoplayback)
900 {
901 M_StartMessage(NEWGAME,NULL,false);
902 return;
903 }
904
905 if ( gamemode == commercial )
906 M_SetupNextMenu(&NewDef);
907 else
908 M_SetupNextMenu(&EpiDef);
909}
910
911
912//
913// M_Episode
914//
915int epi;
916
917void M_DrawEpisode(void)
918{
919 // CPhipps - patch drawing updated
920 V_DrawNamePatch(54, 38, 0, "M_EPISOD", CR_DEFAULT, VPT_STRETCH);
921}
922
923void M_VerifyNightmare(int ch)
924{
925 if (ch != KEY_ENTER)
926 return;
927
928 G_DeferedInitNew(nightmare,epi+1,1);
929 M_ClearMenus ();
930}
931
932void M_ChooseSkill(int choice)
933{
934 if (choice == nightmare)
935 {
936 M_StartMessage(NIGHTMARE,M_VerifyNightmare,true);
937 return;
938 }
939
940 //jff 3/24/98 remember last skill selected
941 // killough 10/98 moved to here
942 defaultskill = choice+1;
943
944 G_DeferedInitNew(choice,epi+1,1);
945 M_ClearMenus ();
946}
947
948void M_Episode(int choice)
949{
950 if ( (gamemode == shareware)
951 && choice)
952 {
953 M_StartMessage(SWSTRING,NULL,false);
954 M_SetupNextMenu(&ReadDef1);
955 return;
956 }
957
958 // Yet another hack...
959 if ( (gamemode == registered)
960 && (choice > 2))
961 {
962 /* Digita */
963 // fprintf( stderr,
964 // "M_Episode: 4th episode requires UltimateDOOM\n");
965 choice = 0;
966 }
967
968 epi = choice;
969 M_SetupNextMenu(&NewDef);
970}
971
972
973
974//
975// M_Options
976//
977char detailNames[2][9] = {"M_GDHIGH","M_GDLOW"};
978char msgNames[2][9] = {"M_MSGOFF","M_MSGON"};
979
980
981void M_DrawOptions(void)
982{
983 // CPhipps - patch drawing updated
984 V_DrawNamePatch(108, 15, 0, "M_OPTTTL", CR_DEFAULT, VPT_STRETCH);
985
986 V_DrawNamePatch(OptionsDef.x + 120, OptionsDef.y+LINEHEIGHT*messages, 0,
987 msgNames[showMessages], CR_DEFAULT, VPT_STRETCH);
988
989 M_DrawThermo(OptionsDef.x,OptionsDef.y+LINEHEIGHT*(gamasens+1),
990 4,usegamma);
991
992 M_DrawThermo(OptionsDef.x,OptionsDef.y+LINEHEIGHT*(scrnsize+1),
993 9,screenSize);
994}
995
996void M_Options(int choice)
997{
998 (void)choice;
999 M_SetupNextMenu(&OptionsDef);
1000}
1001
1002
1003
1004//
1005// Toggle messages on/off
1006//
1007void M_ChangeMessages(int choice)
1008{
1009 // warning: unused parameter `int choice'
1010 choice = 0;
1011 showMessages = 1 - showMessages;
1012
1013 if (!showMessages)
1014 players[consoleplayer].message = MSGOFF;
1015 else
1016 players[consoleplayer].message = MSGON ;
1017
1018 message_dontfuckwithme = true;
1019}
1020
1021
1022//
1023// M_EndGame
1024//
1025void M_EndGameResponse(int ch)
1026{
1027 if (ch != KEY_ENTER)
1028 return;
1029
1030 // killough 5/26/98: make endgame quit if recording or playing back demo
1031 if (demorecording || singledemo)
1032 G_CheckDemoStatus();
1033
1034 currentMenu->lastOn = itemOn;
1035 M_ClearMenus ();
1036 D_StartTitle ();
1037}
1038
1039void M_EndGame(int choice)
1040{
1041 choice = 0;
1042 if (!usergame)
1043 {
1044 S_StartSound(NULL,sfx_oof);
1045 return;
1046 }
1047
1048 if (netgame)
1049 {
1050 M_StartMessage(NETEND,NULL,false);
1051 return;
1052 }
1053
1054 M_StartMessage(ENDGAME,M_EndGameResponse,true);
1055}
1056
1057
1058
1059
1060//
1061// M_ReadThis
1062//
1063void M_ReadThis(int choice)
1064{
1065 choice = 0;
1066 M_SetupNextMenu(&ReadDef1);
1067}
1068
1069void M_ReadThis2(int choice)
1070{
1071 choice = 0;
1072 M_SetupNextMenu(&ReadDef2);
1073}
1074
1075void M_FinishReadThis(int choice)
1076{
1077 choice = 0;
1078 M_SetupNextMenu(&MainDef);
1079}
1080
1081
1082
1083
1084//
1085// M_QuitDOOM
1086//
1087int quitsounds[8] =
1088 {
1089 sfx_pldeth,
1090 sfx_dmpain,
1091 sfx_popain,
1092 sfx_slop,
1093 sfx_telept,
1094 sfx_posit1,
1095 sfx_posit3,
1096 sfx_sgtatk
1097 };
1098
1099int quitsounds2[8] =
1100 {
1101 sfx_vilact,
1102 sfx_getpow,
1103 sfx_boscub,
1104 sfx_slop,
1105 sfx_skeswg,
1106 sfx_kntdth,
1107 sfx_bspact,
1108 sfx_sgtatk
1109 };
1110
1111
1112
1113void M_QuitResponse(int ch)
1114{
1115 if (ch != KEY_ENTER)
1116 return;
1117 if (!netgame)
1118 {
1119 if (gamemode == commercial)
1120 S_StartSound(NULL,quitsounds2[(gametic>>2)&7]);
1121 else
1122 S_StartSound(NULL,quitsounds[(gametic>>2)&7]);
1123 I_WaitVBL(105);
1124 }
1125 I_Quit ();
1126}
1127
1128
1129
1130
1131void M_QuitDOOM(int choice)
1132{
1133 (void)choice;
1134 // We pick index 0 which is language sensitive,
1135 // or one at random, between 1 and maximum number.
1136 if (language != english )
1137 snprintf(endstring,sizeof(endstring),"%s\n\n"DOSY, endmsg[0] );
1138 else
1139 snprintf(endstring,sizeof(endstring),"%s\n\n%s", endmsg[gametic%(NUM_QUITMESSAGES-1)+1], DOSY);
1140
1141 M_StartMessage(endstring,M_QuitResponse,true);
1142}
1143
1144
1145
1146
1147void M_ChangeSensitivity(int choice)
1148{
1149 switch(choice)
1150 {
1151 case 0:
1152 if (usegamma)
1153 usegamma--;
1154 break;
1155 case 1:
1156 if (usegamma < 4)
1157 usegamma++;
1158 break;
1159 }
1160 V_SetPalette (0);
1161}
1162
1163void M_SizeDisplay(int choice)
1164{
1165 switch(choice)
1166 {
1167 case 0:
1168 if (screenSize > 0)
1169 {
1170 screenblocks--;
1171 screenSize--;
1172 }
1173 break;
1174 case 1:
1175 if (screenSize < 8)
1176 {
1177 screenblocks++;
1178 screenSize++;
1179 }
1180 break;
1181 }
1182
1183
1184 R_SetViewSize (screenblocks);
1185}
1186
1187
1188
1189
1190//
1191// Menu Functions
1192//
1193void
1194M_DrawThermo
1195( int x,
1196 int y,
1197 int thermWidth,
1198 int thermDot )
1199{
1200 int xx;
1201 int i;
1202
1203 xx = x;
1204 V_DrawNamePatch(xx, y, 0, "M_THERML", CR_DEFAULT, VPT_STRETCH);
1205 xx += 8;
1206 for (i=0;i<thermWidth;i++)
1207 {
1208 V_DrawNamePatch(xx, y, 0, "M_THERMM", CR_DEFAULT, VPT_STRETCH);
1209 xx += 8;
1210 }
1211 V_DrawNamePatch(xx, y, 0, "M_THERMR", CR_DEFAULT, VPT_STRETCH);
1212 V_DrawNamePatch((x+8)+thermDot*8,y,0,"M_THERMO",CR_DEFAULT,VPT_STRETCH);
1213}
1214
1215
1216
1217void
1218M_DrawEmptyCell
1219( menu_t* menu,
1220 int item )
1221{
1222 // CPhipps - patch drawing updated
1223 V_DrawNamePatch(menu->x - 10, menu->y+item*LINEHEIGHT - 1, 0,
1224 "M_CELL1", CR_DEFAULT, VPT_STRETCH);
1225}
1226
1227void
1228M_DrawSelCell
1229( menu_t* menu,
1230 int item )
1231{
1232 // CPhipps - patch drawing updated
1233 V_DrawNamePatch(menu->x - 10, menu->y+item*LINEHEIGHT - 1, 0,
1234 "M_CELL2", CR_DEFAULT, VPT_STRETCH);
1235}
1236
1237
1238void
1239M_StartMessage
1240( char* string,
1241 void* routine,
1242 boolean input )
1243{
1244 messageLastMenuActive = menuactive;
1245 messageToPrint = 1;
1246 messageString = string;
1247 messageRoutine = routine;
1248 messageNeedsInput = input;
1249 menuactive = true;
1250 return;
1251}
1252
1253
1254
1255void M_StopMessage(void)
1256{
1257 menuactive = messageLastMenuActive;
1258 messageToPrint = 0;
1259}
1260
1261
1262
1263//
1264// Find string width from hu_font chars
1265//
1266int M_StringWidth(const char* string)
1267{
1268 int i, c, w = 0;
1269 for (i = 0;(size_t)i < strlen(string);i++)
1270 w += (c = toupper(string[i]) - HU_FONTSTART) < 0 || c >= HU_FONTSIZE ?
1271 4 : SHORT(hu_font[c].width);
1272 return w;
1273}
1274
1275//
1276// Find string height from hu_font chars
1277//
1278
1279int M_StringHeight(const char* string)
1280{
1281 int i, h, height = h = SHORT(hu_font[0].height);
1282 for (i = 0;string[i];i++) // killough 1/31/98
1283 if (string[i] == '\n')
1284 h += height;
1285 return h;
1286}
1287
1288
1289//
1290// Write a string using the hu_font
1291//
1292void
1293M_WriteText
1294( int x,
1295 int y,
1296 char* string)
1297{
1298 int w;
1299 char* ch;
1300 int c;
1301 int cx;
1302 int cy;
1303
1304
1305 ch = string;
1306 cx = x;
1307 cy = y;
1308
1309 while(1)
1310 {
1311 c = *ch++;
1312 if (!c)
1313 break;
1314 if (c == '\n')
1315 {
1316 cx = x;
1317 cy += 12;
1318 continue;
1319 }
1320
1321 c = toupper(c) - HU_FONTSTART;
1322 if (c < 0 || c>= HU_FONTSIZE)
1323 {
1324 cx += 4;
1325 continue;
1326 }
1327
1328 w = SHORT (hu_font[c].width);
1329 if (cx+w > SCREENWIDTH)
1330 break;
1331 // proff/nicolas 09/20/98 -- changed for hi-res
1332 // CPhipps - patch drawing updated
1333 V_DrawNumPatch(cx, cy, 0, hu_font[c].lumpnum, CR_DEFAULT, VPT_STRETCH);
1334 cx+=w;
1335 }
1336}
1337
1338
1339
1340//
1341// CONTROL PANEL
1342//
1343
1344//
1345// M_Responder
1346//
1347boolean M_Responder (event_t* ev)
1348{
1349 int ch;
1350 int i;
1351// static int joywait = 0;
1352// static int mousewait = 0;
1353// static int mousey = 0;
1354// static int lasty = 0;
1355// static int mousex = 0;
1356// static int lastx = 0;
1357
1358 ch = -1;
1359
1360 // Process joystick input
1361
1362/* if (ev->type == ev_joystick && joywait < I_GetTime())
1363 {
1364 if (ev->data3 == -1)
1365 {
1366 ch = KEY_UPARROW;
1367 joywait = I_GetTime() + 5;
1368 }
1369 else if (ev->data3 == 1)
1370 {
1371 ch = KEY_DOWNARROW;
1372 joywait = I_GetTime() + 5;
1373 }
1374
1375 if (ev->data2 == -1)
1376 {
1377 ch = KEY_LEFTARROW;
1378 joywait = I_GetTime() + 2;
1379 }
1380 else if (ev->data2 == 1)
1381 {
1382 ch = KEY_RIGHTARROW;
1383 joywait = I_GetTime() + 2;
1384 }
1385
1386 if (ev->data1&1)
1387 {
1388 ch = KEY_ENTER;
1389 joywait = I_GetTime() + 5;
1390 }
1391 if (ev->data1&2)
1392 {
1393 ch = KEY_BACKSPACE;
1394 joywait = I_GetTime() + 5;
1395 }
1396 }
1397 else
1398 {
1399 // Process mouse input
1400 if (ev->type == ev_mouse && mousewait < I_GetTime())
1401 {
1402 mousey += ev->data3;
1403 if (mousey < lasty-30)
1404 {
1405 ch = KEY_DOWNARROW;
1406 mousewait = I_GetTime() + 5;
1407 mousey = lasty -= 30;
1408 }
1409 else if (mousey > lasty+30)
1410 {
1411 ch = KEY_UPARROW;
1412 mousewait = I_GetTime() + 5;
1413 mousey = lasty += 30;
1414 }
1415
1416 mousex += ev->data2;
1417 if (mousex < lastx-30)
1418 {
1419 ch = KEY_LEFTARROW;
1420 mousewait = I_GetTime() + 5;
1421 mousex = lastx -= 30;
1422 }
1423 else if (mousex > lastx+30)
1424 {
1425 ch = KEY_RIGHTARROW;
1426 mousewait = I_GetTime() + 5;
1427 mousex = lastx += 30;
1428 }
1429
1430 if (ev->data1&1)
1431 {
1432 ch = KEY_ENTER;
1433 mousewait = I_GetTime() + 15;
1434 }
1435
1436 if (ev->data1&2)
1437 {
1438 ch = KEY_BACKSPACE;
1439 mousewait = I_GetTime() + 15;
1440 }
1441 }
1442 else */if (ev->type == ev_keydown)
1443 {
1444 ch = ev->data1;
1445 }
1446// }
1447
1448 if (ch == -1)
1449 return false;
1450
1451
1452 // Save Game string input
1453 if (saveStringEnter)
1454 {
1455 switch(ch)
1456 {
1457 case KEY_BACKSPACE:
1458 if (saveCharIndex > 0)
1459 {
1460 saveCharIndex--;
1461 savegamestrings[saveSlot][saveCharIndex] = 0;
1462 }
1463 break;
1464
1465 case KEY_ESCAPE:
1466 saveStringEnter = 0;
1467 strcpy(&savegamestrings[saveSlot][0],saveOldString);
1468 break;
1469
1470 case KEY_ENTER:
1471 saveStringEnter = 0;
1472 if (savegamestrings[saveSlot][0])
1473 M_DoSave(saveSlot);
1474 break;
1475
1476 default:
1477 ch = toupper(ch);
1478 if (ch != 32)
1479 if (ch-HU_FONTSTART < 0 || ch-HU_FONTSTART >= HU_FONTSIZE)
1480 break;
1481 if (ch >= 32 && ch <= 127 &&
1482 saveCharIndex < SAVESTRINGSIZE-1 &&
1483 M_StringWidth(savegamestrings[saveSlot]) <
1484 (SAVESTRINGSIZE-2)*8)
1485 {
1486 savegamestrings[saveSlot][saveCharIndex++] = ch;
1487 savegamestrings[saveSlot][saveCharIndex] = 0;
1488 }
1489 break;
1490 }
1491 return true;
1492 }
1493
1494 // Take care of any messages that need input
1495 if (messageToPrint)
1496 {
1497 if (messageNeedsInput == true &&
1498 !(ch == ' ' || ch == 'n' || ch == KEY_ENTER || ch == KEY_ESCAPE))
1499 return false;
1500
1501 menuactive = messageLastMenuActive;
1502 messageToPrint = 0;
1503 if (messageRoutine)
1504 messageRoutine(ch);
1505
1506 menuactive = false;
1507 S_StartSound(NULL,sfx_swtchx);
1508 return true;
1509 }
1510/*
1511 if (ch == KEY_F1) // devparm &&
1512 {
1513 G_ScreenShot ();
1514 return true;
1515 }
1516*/
1517 // F-Keys
1518 if (!menuactive)
1519 switch(ch)
1520 {
1521 case KEY_MINUS: // Screen size down
1522 if ((automapmode & am_active) || chat_on)
1523 return false;
1524 M_SizeDisplay(0);
1525 S_StartSound(NULL,sfx_stnmov);
1526 return true;
1527
1528 case KEY_EQUALS: // Screen size up
1529 if ((automapmode & am_active) || chat_on)
1530 return false;
1531 M_SizeDisplay(1);
1532 S_StartSound(NULL,sfx_stnmov);
1533 return true;
1534/*
1535 case KEY_F1: // Help key
1536 M_StartControlPanel ();
1537
1538 if ( gamemode == retail )
1539 currentMenu = &ReadDef2;
1540 else
1541 currentMenu = &ReadDef1;
1542
1543 itemOn = 0;
1544 S_StartSound(NULL,sfx_swtchn);
1545 return true;
1546
1547 case KEY_F6: // Quicksave
1548 S_StartSound(NULL,sfx_swtchn);
1549 M_QuickSave();
1550 return true;
1551
1552 case KEY_F9: // Quickload
1553 S_StartSound(NULL,sfx_swtchn);
1554 M_QuickLoad();
1555 return true;
1556*/
1557 }
1558
1559
1560 // Pop-up menu?
1561 if (!menuactive)
1562 {
1563 if (ch == KEY_ESCAPE)
1564 {
1565 M_StartControlPanel ();
1566 S_StartSound(NULL,sfx_swtchn);
1567 return true;
1568 }
1569 return false;
1570 }
1571
1572
1573 // Keys usable within menu
1574 switch (ch)
1575 {
1576 case KEY_DOWNARROW:
1577 do
1578 {
1579 if (itemOn+1 > currentMenu->numitems-1)
1580 itemOn = 0;
1581 else
1582 itemOn++;
1583 S_StartSound(NULL,sfx_pstop);
1584 }
1585 while(currentMenu->menuitems[itemOn].status==-1);
1586 return true;
1587
1588 case KEY_UPARROW:
1589 do
1590 {
1591 if (!itemOn)
1592 itemOn = currentMenu->numitems-1;
1593 else
1594 itemOn--;
1595 S_StartSound(NULL,sfx_pstop);
1596 }
1597 while(currentMenu->menuitems[itemOn].status==-1);
1598 return true;
1599
1600 case KEY_LEFTARROW:
1601 if (currentMenu->menuitems[itemOn].routine &&
1602 currentMenu->menuitems[itemOn].status == 2)
1603 {
1604 S_StartSound(NULL,sfx_stnmov);
1605 currentMenu->menuitems[itemOn].routine(0);
1606 }
1607 return true;
1608
1609 case KEY_RIGHTARROW:
1610 if (currentMenu->menuitems[itemOn].routine &&
1611 currentMenu->menuitems[itemOn].status == 2)
1612 {
1613 S_StartSound(NULL,sfx_stnmov);
1614 currentMenu->menuitems[itemOn].routine(1);
1615 }
1616 return true;
1617
1618 case KEY_ENTER:
1619 if (currentMenu->menuitems[itemOn].routine &&
1620 currentMenu->menuitems[itemOn].status)
1621 {
1622 currentMenu->lastOn = itemOn;
1623 if (currentMenu->menuitems[itemOn].status == 2)
1624 {
1625 currentMenu->menuitems[itemOn].routine(1); // right arrow
1626 S_StartSound(NULL,sfx_stnmov);
1627 }
1628 else
1629 {
1630 currentMenu->menuitems[itemOn].routine(itemOn);
1631 S_StartSound(NULL,sfx_pistol);
1632 }
1633 }
1634 return true;
1635
1636 case KEY_ESCAPE:
1637 currentMenu->lastOn = itemOn;
1638 M_ClearMenus ();
1639 S_StartSound(NULL,sfx_swtchx);
1640 return true;
1641
1642 case KEY_BACKSPACE:
1643 currentMenu->lastOn = itemOn;
1644 if (currentMenu->prevMenu)
1645 {
1646 currentMenu = currentMenu->prevMenu;
1647 itemOn = currentMenu->lastOn;
1648 S_StartSound(NULL,sfx_swtchn);
1649 }
1650 return true;
1651
1652 default:
1653 for (i = itemOn+1;i < currentMenu->numitems;i++)
1654 if (currentMenu->menuitems[i].alphaKey == ch)
1655 {
1656 itemOn = i;
1657 S_StartSound(NULL,sfx_pstop);
1658 return true;
1659 }
1660 for (i = 0;i <= itemOn;i++)
1661 if (currentMenu->menuitems[i].alphaKey == ch)
1662 {
1663 itemOn = i;
1664 S_StartSound(NULL,sfx_pstop);
1665 return true;
1666 }
1667 break;
1668
1669 }
1670
1671 return false;
1672}
1673
1674
1675
1676//
1677// M_StartControlPanel
1678//
1679void M_StartControlPanel (void)
1680{
1681 // intro might call this repeatedly
1682 if (menuactive)
1683 return;
1684
1685 menuactive = 1;
1686 currentMenu = &MainDef; // JDC
1687 itemOn = currentMenu->lastOn; // JDC
1688}
1689
1690
1691//
1692// M_Drawer
1693// Called after the view has been rendered,
1694// but before it has been blitted.
1695//
1696void M_Drawer (void)
1697{
1698 static short x;
1699 static short y;
1700 unsigned short i;
1701 short max;
1702 char string[40];
1703 int start;
1704
1705 inhelpscreens = false;
1706
1707
1708 // Horiz. & Vertically center string and print it.
1709 if (messageToPrint)
1710 {
1711 start = 0;
1712 y = 100 - M_StringHeight(messageString)/2;
1713 while(*(messageString+start))
1714 {
1715 for (i = 0;i < strlen(messageString+start);i++)
1716 if (*(messageString+start+i) == '\n')
1717 {
1718 memset(string,0,40);
1719 strncpy(string,messageString+start,i);
1720 start += i+1;
1721 break;
1722 }
1723 if (i == strlen(messageString+start))
1724 {
1725 strcpy(string,messageString+start);
1726 start += i;
1727 }
1728
1729 x = 160 - M_StringWidth(string)/2;
1730 M_WriteText(x,y,string);
1731 y += SHORT(hu_font[0].height);
1732 }
1733 return;
1734 }
1735
1736 if (!menuactive)
1737 return;
1738
1739 if (currentMenu->routine)
1740 currentMenu->routine(); // call Draw routine
1741
1742 // DRAW MENU
1743 x = currentMenu->x;
1744 y = currentMenu->y;
1745 max = currentMenu->numitems;
1746
1747 for (i=0;i<max;i++)
1748 {
1749 if (currentMenu->menuitems[i].name[0])
1750 V_DrawNamePatch(x,y,0,currentMenu->menuitems[i].name,
1751 CR_DEFAULT, VPT_STRETCH);
1752 y += LINEHEIGHT;
1753 }
1754
1755 // DRAW SKULL
1756 // CPhipps - patch drawing updated
1757 V_DrawNamePatch(x + SKULLXOFF, currentMenu->y - 5 + itemOn*LINEHEIGHT,0,
1758 skullName[whichSkull], CR_DEFAULT, VPT_STRETCH);
1759
1760}
1761
1762
1763//
1764// M_ClearMenus
1765//
1766void M_ClearMenus (void)
1767{
1768 menuactive = 0;
1769 // if (!netgame && usergame && paused)
1770 // sendpause = true;
1771}
1772
1773
1774
1775
1776//
1777// M_SetupNextMenu
1778//
1779void M_SetupNextMenu(menu_t *menudef)
1780{
1781 currentMenu = menudef;
1782 itemOn = currentMenu->lastOn;
1783}
1784
1785
1786//
1787// M_Ticker
1788//
1789void M_Ticker (void)
1790{
1791 if (--skullAnimCounter <= 0)
1792 {
1793 whichSkull ^= 1;
1794 skullAnimCounter = 8;
1795 }
1796}
1797
1798
1799//
1800// M_Init
1801//
1802void M_Init (void)
1803{
1804 currentMenu = &MainDef;
1805 menuactive = 0;
1806 itemOn = currentMenu->lastOn;
1807 whichSkull = 0;
1808 skullAnimCounter = 10;
1809 screenSize = screenblocks - 3;
1810 messageToPrint = 0;
1811 messageString = NULL;
1812 messageLastMenuActive = menuactive;
1813 quickSaveSlot = -1;
1814
1815 // Here we could catch other version dependencies,
1816 // like HELP1/2, and four episodes.
1817
1818
1819 switch ( gamemode )
1820 {
1821 case commercial:
1822 // This is used because DOOM 2 had only one HELP
1823 // page. I use CREDIT as second page now, but
1824 // kept this hack for educational purposes.
1825 MainMenu[readthis] = MainMenu[quitdoom];
1826 MainDef.numitems--;
1827 MainDef.y += 8;
1828 NewDef.prevMenu = &MainDef;
1829 ReadDef1.routine = M_DrawReadThis1;
1830 ReadDef1.x = 330;
1831 ReadDef1.y = 165;
1832 ReadMenu1[0].routine = M_FinishReadThis;
1833 break;
1834 case shareware:
1835 // Episode 2 and 3 are handled,
1836 // branching to an ad screen.
1837 case registered:
1838 // We need to remove the fourth episode.
1839 EpiDef.numitems--;
1840 break;
1841 case retail:
1842 // We are fine.
1843 default:
1844 break;
1845 }
1846
1847}
1848
diff --git a/apps/plugins/doom/m_menu.h b/apps/plugins/doom/m_menu.h
new file mode 100644
index 0000000000..8444b72a5f
--- /dev/null
+++ b/apps/plugins/doom/m_menu.h
@@ -0,0 +1,121 @@
1// Emacs style mode select -*- C++ -*-
2//-----------------------------------------------------------------------------
3//
4// $Id$
5//
6// Copyright (C) 1993-1996 by id Software, Inc.
7//
8// This program is free software; you can redistribute it and/or
9// modify it under the terms of the GNU General Public License
10// as published by the Free Software Foundation; either version 2
11// of the License, or (at your option) any later version.
12//
13// This program is distributed in the hope that it will be useful,
14// but WITHOUT ANY WARRANTY; without even the implied warranty of
15// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16// GNU General Public License for more details.
17//
18// DESCRIPTION:
19// Menu widget stuff, episode selection and such.
20//
21//-----------------------------------------------------------------------------
22
23
24#ifndef __M_MENU__
25#define __M_MENU__
26
27
28
29#include "d_event.h"
30
31//
32// MENUS
33//
34// Called by main loop,
35// saves config file and calls I_Quit when user exits.
36// Even when the menu is not displayed,
37// this can resize the view and change game parameters.
38// Does all the real work of the menu interaction.
39boolean M_Responder (event_t *ev);
40
41
42// Called by main loop,
43// only used for menu (skull cursor) animation.
44void M_Ticker (void);
45
46// Called by main loop,
47// draws the menus directly into the screen buffer.
48void M_Drawer (void);
49
50// Called by D_DoomMain,
51// loads the config file.
52void M_Init (void);
53
54// Called by intro code to force menu up upon a keypress,
55// does nothing if menu is already up.
56void M_StartControlPanel (void);
57
58/****************************
59 *
60 * The setup_group enum is used to show which 'groups' keys fall into so
61 * that you can bind a key differently in each 'group'.
62 */
63
64typedef enum {
65 m_null, // Has no meaning; not applicable
66 m_scrn, // A key can not be assigned to more than one action
67 m_map, // in the same group. A key can be assigned to one
68 m_menu, // action in one group, and another action in another.
69} setup_group;
70
71/****************************
72 *
73 * phares 4/17/98:
74 * State definition for each item.
75 * This is the definition of the structure for each setup item. Not all
76 * fields are used by all items.
77 *
78 * A setup screen is defined by an array of these items specific to
79 * that screen.
80 *
81 * killough 11/98:
82 *
83 * Restructured to allow simpler table entries,
84 * and to Xref with defaults[] array in m_misc.c.
85 * Moved from m_menu.c to m_menu.h so that m_misc.c can use it.
86 */
87
88typedef struct setup_menu_s
89{
90 const char *m_text; /* text to display */
91 int m_flags; /* phares 4/17/98: flag bits S_* (defined above) */
92 setup_group m_group; /* Group */
93 short m_x; /* screen x position (left is 0) */
94 short m_y; /* screen y position (top is 0) */
95
96 union /* killough 11/98: The first field is a union of several types */
97 {
98 const void *var; /* generic variable */
99 int *m_key; /* key value, or 0 if not shown */
100 const char *name; /* name */
101 struct default_s *def; /* default[] table entry */
102 struct setup_menu_s *menu; /* next or prev menu */
103 } var;
104
105 int *m_mouse; /* mouse button value, or 0 if not shown */
106 int *m_joy; /* joystick button value, or 0 if not shown */
107 void (*action)(void); /* killough 10/98: function to call after changing */
108} setup_menu_t;
109
110
111
112
113#endif
114//-----------------------------------------------------------------------------
115//
116// $Log$
117// Revision 1.1 2006/03/28 15:44:01 dave
118// Patch #2969 - Doom! Currently only working on the H300.
119//
120//
121//-----------------------------------------------------------------------------
diff --git a/apps/plugins/doom/m_misc.c b/apps/plugins/doom/m_misc.c
new file mode 100644
index 0000000000..2cde2102e6
--- /dev/null
+++ b/apps/plugins/doom/m_misc.c
@@ -0,0 +1,1077 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION:
28 * Main loop menu stuff.
29 * Default Config File.
30 * PCX Screenshots.
31 *
32 *-----------------------------------------------------------------------------*/
33
34#include "doomstat.h"
35#include "m_argv.h"
36#include "g_game.h"
37#include "m_menu.h"
38#include "am_map.h"
39#include "w_wad.h"
40#include "i_sound.h"
41#include "i_video.h"
42#include "v_video.h"
43#include "hu_stuff.h"
44#include "st_stuff.h"
45#include "dstrings.h"
46#include "m_misc.h"
47#include "s_sound.h"
48#include "sounds.h"
49#include "i_system.h"
50#include "d_main.h"
51#include "m_swap.h"
52#include "p_pspr.h"
53
54#include "rockmacros.h"
55
56//
57// M_DrawText
58// Returns the final X coordinate
59// HU_Init must have been called to init the font
60//
61extern patchnum_t hu_font[HU_FONTSIZE];
62
63int M_DrawText(int x,int y,boolean direct,char* string)
64{
65 (void)direct;
66 int c;
67 int w;
68
69 while (*string) {
70 c = toupper(*string) - HU_FONTSTART;
71 string++;
72 if (c < 0 || c> HU_FONTSIZE) {
73 x += 4;
74 continue;
75 }
76
77 w = SHORT (hu_font[c].width);
78 if (x+w > SCREENWIDTH)
79 break;
80
81 // proff/nicolas 09/20/98 -- changed for hi-res
82 // CPhipps - patch drawing updated, reformatted
83 V_DrawNumPatch(x, y, 0, hu_font[c].lumpnum, CR_DEFAULT, VPT_STRETCH);
84 x+=w;
85 }
86
87 return x;
88}
89
90//
91// M_WriteFile
92//
93
94boolean M_WriteFile(char const* name,void* source,int length)
95{
96 int handle;
97 int count;
98
99 handle = open ( name, O_WRONLY | O_CREAT | O_TRUNC);
100
101 if (handle == -1)
102 return false;
103
104 count = write (handle, source, length);
105 close (handle);
106
107 if (count < length) {
108// unlink(name); // CPhipps - no corrupt data files around, they only confuse people.
109 return false;
110 }
111
112 return true;
113}
114
115
116//
117// M_ReadFile
118//
119
120int M_ReadFile(char const* name,byte** buffer)
121{
122 int handle, count, length;
123 // struct stat fileinfo;
124 byte *buf;
125
126 handle = open (name, O_RDONLY);
127 if ((handle < 0))
128 I_Error ("M_ReadFile: Couldn't read file %s", name);
129
130 length = filesize(handle);
131 buf = Z_Malloc (length, PU_STATIC, NULL);
132 count = read (handle, buf, length);
133 close (handle);
134
135 if (count < length)
136 I_Error ("M_ReadFile: Couldn't read file %s", name);
137
138 *buffer = buf;
139 return length;
140}
141
142//
143// DEFAULTS
144//
145
146int usemouse;
147boolean precache = true; /* if true, load all graphics at start */
148
149extern int mousebfire;
150extern int mousebstrafe;
151extern int mousebforward;
152
153extern int viewwidth;
154extern int viewheight;
155extern int fake_contrast;
156extern int mouseSensitivity_horiz,mouseSensitivity_vert; // killough
157
158extern int realtic_clock_rate; // killough 4/13/98: adjustable timer
159extern int tran_filter_pct; // killough 2/21/98
160
161extern int screenblocks;
162extern int showMessages;
163
164#ifndef DJGPP
165const char* musserver_filename;
166const char* sndserver_filename;
167const char* snd_device;
168int mus_pause_opt; // 0 = kill music, 1 = pause, 2 = continue
169#endif
170
171extern const char* chat_macros[];
172
173extern int endoom_mode;
174int X_opt;
175
176extern const char* S_music_files[]; // cournia
177
178/* cph - Some MBF stuff parked here for now
179 * killough 10/98
180 */
181int map_point_coordinates;
182
183default_t defaults[] =
184 {
185 {"Misc settings",{NULL, NULL},{0, NULL},UL,UL,def_none,ss_none, 0, 0},
186 {"default_compatibility_level",{(void *)&default_compatibility_level, NULL},
187 {-1, NULL},-1,MAX_COMPATIBILITY_LEVEL-1,
188 def_int,ss_none, 0, 0}, // compatibility level" - CPhipps
189// {"realtic_clock_rate",{&realtic_clock_rate, NULL},{100, NULL},0,UL,
190// def_int,ss_none, 0, 0}, // percentage of normal speed (35 fps) realtic clock runs at
191 {"max_player_corpse", {&bodyquesize, NULL}, {32, NULL},-1,UL, // killough 2/8/98
192 def_int,ss_none, 0, 0}, // number of dead bodies in view supported (-1 = no limit)
193 {"flashing_hom",{&flashing_hom, NULL},{0, NULL},0,1,
194 def_bool,ss_none, 0, 0}, // killough 10/98 - enable flashing HOM indicator
195 {"demo_insurance",{&default_demo_insurance, NULL},{2, NULL},0,2, // killough 3/31/98
196 def_int,ss_none, 0, 0}, // 1=take special steps ensuring demo sync, 2=only during recordings
197// {"endoom_mode", {&endoom_mode, NULL},{5, NULL},0,7, // CPhipps - endoom flags
198// def_hex, ss_none, 0, 0}, // 0, +1 for colours, +2 for non-ascii chars, +4 for skip-last-line
199 {"level_precache",{(void*)&precache, NULL},{1, NULL},0,1,
200 def_bool,ss_none, 0, 0}, // precache level data?
201
202 {"Files",{NULL, NULL},{0, NULL},UL,UL,def_none,ss_none, 0, 0},
203 /* cph - MBF-like wad/deh/bex autoload code
204 * POSIX targets need to get lumps from prboom.wad */
205// {"wadfile_1",{NULL,&wad_files[0]},{0,
206#ifdef ALL_IN_ONE
207// ""
208#else
209// "prboom.wad"
210#endif
211// },UL,UL,def_str,ss_none, 0, 0},
212// {"wadfile_2",{NULL,&wad_files[1]},{0,""},UL,UL,def_str,ss_none, 0, 0},
213// {"dehfile_1",{NULL,&deh_files[0]},{0,""},UL,UL,def_str,ss_none, 0, 0},
214// {"dehfile_2",{NULL,&deh_files[1]},{0,""},UL,UL,def_str,ss_none, 0, 0},
215
216 {"Game settings",{NULL, NULL},{0, NULL},UL,UL,def_none,ss_none, 0, 0},
217 {"default_skill",{&defaultskill, NULL},{3, NULL},1,5, // jff 3/24/98 allow default skill setting
218 def_int,ss_none, 0, 0}, // selects default skill 1=TYTD 2=NTR 3=HMP 4=UV 5=NM
219 {"weapon_recoil",{&default_weapon_recoil, NULL},{0, NULL},0,1,
220 def_bool,ss_weap, &weapon_recoil, 0},
221 /* killough 10/98 - toggle between SG/SSG and Fist/Chainsaw */
222 {"doom_weapon_toggles",{&doom_weapon_toggles, NULL}, {1, NULL}, 0, 1,
223 def_bool, ss_weap , 0, 0},
224 {"player_bobbing",{&default_player_bobbing, NULL},{1, NULL},0,1, // phares 2/25/98
225 def_bool,ss_weap, &player_bobbing, 0},
226 {"monsters_remember",{&default_monsters_remember, NULL},{1, NULL},0,1, // killough 3/1/98
227 def_bool,ss_enem, &monsters_remember, 0},
228 /* MBF AI enhancement options */
229 {"monster_infighting",{&default_monster_infighting, NULL}, {1, NULL}, 0, 1,
230 def_bool, ss_enem, &monster_infighting, 0},
231 {"monster_backing",{&default_monster_backing, NULL}, {0, NULL}, 0, 1,
232 def_bool, ss_enem, &monster_backing, 0},
233 {"monster_avoid_hazards",{&default_monster_avoid_hazards, NULL}, {1, NULL}, 0, 1,
234 def_bool, ss_enem, &monster_avoid_hazards, 0},
235 {"monkeys",{&default_monkeys, NULL}, {0, NULL}, 0, 1,
236 def_bool, ss_enem, &monkeys, 0},
237 {"monster_friction",{&default_monster_friction, NULL}, {1, NULL}, 0, 1,
238 def_bool, ss_enem, &monster_friction, 0},
239 {"help_friends",{&default_help_friends, NULL}, {1, NULL}, 0, 1,
240 def_bool, ss_enem, &help_friends, 0},
241#ifdef DOGS
242 {"player_helpers",{&default_dogs, NULL}, {0, NULL}, 0, 3,
243 def_bool, ss_enem , 0, 0},
244 {"friend_distance",{&default_distfriend, NULL}, {128, NULL}, 0, 999,
245 def_int, ss_enem, &distfriend, 0},
246 {"dog_jumping",{&default_dog_jumping, NULL}, {1, NULL}, 0, 1,
247 def_bool, ss_enem, &dog_jumping, 0},
248#endif
249 /* End of MBF AI extras */
250 {"sts_always_red",{&sts_always_red, NULL},{1, NULL},0,1, // no color changes on status bar
251 def_bool,ss_stat, 0, 0},
252 {"sts_pct_always_gray",{&sts_pct_always_gray, NULL},{0, NULL},0,1, // 2/23/98 chg default
253 def_bool,ss_stat, 0, 0}, // makes percent signs on status bar always gray
254 {"sts_traditional_keys",{&sts_traditional_keys, NULL},{0, NULL},0,1, // killough 2/28/98
255 def_bool,ss_stat,0,0}, // disables doubled card and skull key display on status bar
256// {"traditional_menu",{&traditional_menu, NULL},{1, NULL},0,1,
257// def_bool,ss_none, 0, 0}, // force use of Doom's main menu ordering // killough 4/17/98
258 {"show_messages",{&showMessages, NULL},{1, NULL},0,1,
259 def_bool,ss_none,0,0}, // enables message display
260 {"autorun",{&autorun, NULL},{0, NULL},0,1, // killough 3/6/98: preserve autorun across games
261 def_bool,ss_none,0,0},
262
263 {"Compatibility settings",{NULL, NULL},{0, NULL},UL,UL,def_none,ss_none, 0, 0},
264 {"comp_zombie",{&default_comp[comp_zombie], NULL},{0, NULL},0,1,def_bool,ss_comp,&comp[comp_zombie], 0},
265 {"comp_infcheat",{&default_comp[comp_infcheat], NULL},{0, NULL},0,1,def_bool,ss_comp,&comp[comp_infcheat], 0},
266 {"comp_stairs",{&default_comp[comp_stairs], NULL},{0, NULL},0,1,def_bool,ss_comp,&comp[comp_stairs], 0},
267 {"comp_telefrag",{&default_comp[comp_telefrag], NULL},{0, NULL},0,1,def_bool,ss_comp,&comp[comp_telefrag], 0},
268 {"comp_dropoff",{&default_comp[comp_dropoff], NULL},{0, NULL},0,1,def_bool,ss_comp,&comp[comp_dropoff], 0},
269 {"comp_falloff",{&default_comp[comp_falloff], NULL},{0, NULL},0,1,def_bool,ss_comp,&comp[comp_falloff], 0},
270 {"comp_staylift",{&default_comp[comp_staylift], NULL},{0, NULL},0,1,def_bool,ss_comp,&comp[comp_staylift], 0},
271 {"comp_doorstuck",{&default_comp[comp_doorstuck], NULL},{0, NULL},0,1,def_bool,ss_comp,&comp[comp_doorstuck], 0},
272 {"comp_pursuit",{&default_comp[comp_pursuit], NULL},{0, NULL},0,1,def_bool,ss_comp,&comp[comp_pursuit], 0},
273 {"comp_vile",{&default_comp[comp_vile], NULL},{0, NULL},0,1,def_bool,ss_comp,&comp[comp_vile], 0},
274 {"comp_pain",{&default_comp[comp_pain], NULL},{0, NULL},0,1,def_bool,ss_comp,&comp[comp_pain], 0},
275 {"comp_skull",{&default_comp[comp_skull], NULL},{0, NULL},0,1,def_bool,ss_comp,&comp[comp_skull], 0},
276 {"comp_blazing",{&default_comp[comp_blazing], NULL},{0, NULL},0,1,def_bool,ss_comp,&comp[comp_blazing], 0},
277 {"comp_doorlight",{&default_comp[comp_doorlight], NULL},{0, NULL},0,1,def_bool,ss_comp,&comp[comp_doorlight], 0},
278 {"comp_god",{&default_comp[comp_god], NULL},{0, NULL},0,1,def_bool,ss_comp,&comp[comp_god], 0},
279 {"comp_skymap",{&default_comp[comp_skymap], NULL},{0, NULL},0,1,def_bool,ss_comp,&comp[comp_skymap], 0},
280 {"comp_floors",{&default_comp[comp_floors], NULL},{0, NULL},0,1,def_bool,ss_comp,&comp[comp_floors], 0},
281 {"comp_model",{&default_comp[comp_model], NULL},{0, NULL},0,1,def_bool,ss_comp,&comp[comp_model], 0},
282 {"comp_zerotags",{&default_comp[comp_zerotags], NULL},{0, NULL},0,1,def_bool,ss_comp,&comp[comp_zerotags], 0},
283 {"comp_moveblock",{&default_comp[comp_moveblock], NULL},{0, NULL},0,1,def_bool,ss_comp,&comp[comp_moveblock], 0},
284 {"comp_sound",{&default_comp[comp_sound], NULL},{0, NULL},0,1,def_bool,ss_comp,&comp[comp_sound], 0},
285
286 {"Sound settings",{NULL, NULL},{0, NULL},UL,UL,def_none,ss_none, 0, 0},
287// {"sound_card",{&snd_card, NULL},{-1, NULL},-1,7, // jff 1/18/98 allow Allegro drivers
288// def_int,ss_none, 0, 0}, // select sounds driver (DOS), -1 is autodetect, 0 is none; in Linux, non-zero enables sound
289// {"music_card",{&mus_card, NULL},{-1, NULL},-1,9, // to be set, -1 = autodetect
290// def_int,ss_none, 0, 0}, // select music driver (DOS), -1 is autodetect, 0 is none"; in Linux, non-zero enables music
291 {"pitched_sounds",{&pitched_sounds, NULL},{0, NULL},0,1, // killough 2/21/98
292 def_bool,ss_none, 0, 0}, // enables variable pitch in sound effects (from id's original code)
293// {"samplerate",{&snd_samplerate, NULL},{22050, NULL},11025,48000, def_int,ss_none, 0, 0},
294 {"sfx_volume",{&snd_SfxVolume, NULL},{8, NULL},0,15, def_int,ss_none, 0, 0},
295 {"music_volume",{&snd_MusicVolume, NULL},{8, NULL},0,15, def_int,ss_none, 0, 0},
296 {"mus_pause_opt",{&mus_pause_opt, NULL},{2, NULL},0,2, // CPhipps - music pausing
297 def_int, ss_none, 0, 0}, // 0 = kill music when paused, 1 = pause music, 2 = let music continue
298 {"sounddev", {NULL,&snd_device}, {0,"/dev/dsp"},UL,UL,
299 def_str,ss_none, 0, 0}, // sound output device (UNIX)
300 {"snd_channels",{&default_numChannels, NULL},{4, NULL},1,32,
301 def_int,ss_none, 0, 0}, // number of audio events simultaneously // killough
302
303 {"Video settings",{NULL, NULL},{0, NULL},UL,UL,def_none,ss_none, 0, 0},
304 // CPhipps - default screensize for targets that support high-res
305 /* {"screen_width",{&desired_screenwidth, NULL},{320, NULL}, 320, 1600,
306 def_int,ss_none, 0, 0},
307 {"screen_height",{&desired_screenheight, NULL},{200, NULL},200,1200,
308 def_int,ss_none, 0, 0},*/
309 {"fake_contrast",{&fake_contrast, NULL},{1, NULL},0,1,
310 def_bool,ss_none, 0, 0}, /* cph - allow crappy fake contrast to be disabled */
311// {"use_fullscreen",{&use_fullscreen, NULL},{1, NULL},0,1, /* proff 21/05/2000 */
312// def_bool,ss_none, 0, 0},
313// {"use_doublebuffer",{&use_doublebuffer, NULL},{1, NULL},0,1, // proff 2001-7-4
314// def_bool,ss_none, 0, 0}, // enable doublebuffer to avoid display tearing (fullscreen)
315 {"translucency",{&default_translucency, NULL},{1, NULL},0,1, // phares
316 def_bool,ss_none, 0, 0}, // enables translucency
317 {"tran_filter_pct",{&tran_filter_pct, NULL},{66, NULL},0,100, // killough 2/21/98
318 def_int,ss_none, 0, 0}, // set percentage of foreground/background translucency mix
319 {"screenblocks",{&screenblocks, NULL},{9, NULL},3,11,
320 def_int,ss_none, 0, 0},
321 {"usegamma",{&usegamma, NULL},{1, NULL},0,4, //jff 3/6/98 fix erroneous upper limit in range
322 def_int,ss_none, 0, 0}, // gamma correction level // killough 1/18/98
323 {"X_options",{&X_opt, NULL},{0, NULL},0,3, // CPhipps - misc X options
324 def_hex,ss_none, 0, 0}, // X options, see l_video_x.c
325
326 {"Mouse settings",{NULL, NULL},{0, NULL},UL,UL,def_none,ss_none, 0, 0},
327 {"use_mouse",{&usemouse, NULL},{1, NULL},0,1,
328 def_bool,ss_none, 0, 0}, // enables use of mouse with DOOM
329 //jff 4/3/98 allow unlimited sensitivity
330// {"mouse_sensitivity_horiz",{&mouseSensitivity_horiz, NULL},{10, NULL},0,UL,
331// def_int,ss_none, 0, 0}, /* adjust horizontal (x) mouse sensitivity killough/mead */
332 //jff 4/3/98 allow unlimited sensitivity
333// {"mouse_sensitivity_vert",{&mouseSensitivity_vert, NULL},{10, NULL},0,UL,
334// def_int,ss_none, 0, 0}, /* adjust vertical (y) mouse sensitivity killough/mead */
335 //jff 3/8/98 allow -1 in mouse bindings to disable mouse function
336 {"mouseb_fire",{&mousebfire, NULL},{0, NULL},-1,MAX_MOUSEB,
337 def_int,ss_keys, 0, 0}, // mouse button number to use for fire
338 {"mouseb_strafe",{&mousebstrafe, NULL},{1, NULL},-1,MAX_MOUSEB,
339 def_int,ss_keys, 0, 0}, // mouse button number to use for strafing
340 {"mouseb_forward",{&mousebforward, NULL},{2, NULL},-1,MAX_MOUSEB,
341 def_int,ss_keys, 0, 0}, // mouse button number to use for forward motion
342 //jff 3/8/98 end of lower range change for -1 allowed in mouse binding
343
344 // For key bindings, the values stored in the key_* variables // phares
345 // are the internal Doom Codes. The values stored in the default.cfg
346 // file are the keyboard codes.
347 // CPhipps - now they're the doom codes, so default.cfg can be portable
348
349 {"Key bindings",{NULL, NULL},{0, NULL},UL,UL,def_none,ss_none, 0, 0},
350 {"key_right", {&key_right, NULL}, {KEY_RIGHTARROW, NULL},
351 0,MAX_KEY,def_key,ss_keys, 0, 0}, // key to turn right
352 {"key_left", {&key_left, NULL}, {KEY_LEFTARROW, NULL} ,
353 0,MAX_KEY,def_key,ss_keys, 0, 0}, // key to turn left
354 {"key_up", {&key_up, NULL}, {KEY_RCTRL, NULL} ,
355 0,MAX_KEY,def_key,ss_keys, 0, 0}, // key to move forward
356 {"key_down", {&key_down, NULL}, {KEY_DOWNARROW, NULL},
357 0,MAX_KEY,def_key,ss_keys, 0, 0}, // key to move backward
358/* {"key_menu_right", {&key_menu_right, NULL}, {KEY_RIGHTARROW, NULL},// phares 3/7/98
359 0,MAX_KEY,def_key,ss_keys, 0, 0}, // key to move right in a menu // |
360 {"key_menu_left", {&key_menu_left, NULL}, {KEY_LEFTARROW} ,// V
361 0,MAX_KEY,def_key,ss_keys, NULL}, // key to move left in a menu
362 {"key_menu_up", {&key_menu_up, NULL}, {KEY_UPARROW,NULL} ,
363 0,MAX_KEY,def_key,ss_keys, 0, 0}, // key to move up in a menu
364 {"key_menu_down", {&key_menu_down, NULL}, {KEY_DOWNARROW, NULL} ,
365 0,MAX_KEY,def_key,ss_keys, 0, 0}, // key to move down in a menu
366 {"key_menu_backspace",{&key_menu_backspace, NULL},{KEY_BACKSPACE, NULL} ,
367 0,MAX_KEY,def_key,ss_keys, 0, 0}, // delete key in a menu
368 {"key_menu_escape", {&key_menu_escape, NULL}, {KEY_ESCAPE, NULL} ,
369 0,MAX_KEY,def_key,ss_keys, 0, 0}, // key to leave a menu , // phares 3/7/98
370 {"key_menu_enter", {&key_menu_enter, NULL}, {KEY_ENTER, NULL} ,
371 0,MAX_KEY,def_key,ss_keys, 0, 0}, // key to select from menu
372*/
373 {"key_strafeleft", {&key_strafeleft, NULL}, {',', NULL},
374 0,MAX_KEY,def_key,ss_keys, 0, 0}, // key to strafe left
375 {"key_straferight", {&key_straferight, NULL}, {'.', NULL},
376 0,MAX_KEY,def_key,ss_keys, 0, 0}, // key to strafe right
377
378 {"key_fire", {&key_fire, NULL}, {' ', NULL} ,
379 0,MAX_KEY,def_key,ss_keys, 0, 0}, // duh
380 {"key_use", {&key_use, NULL}, {KEY_DOWNARROW, NULL},
381 0,MAX_KEY,def_key,ss_keys, 0, 0}, // key to open a door, use a switch
382 {"key_strafe", {&key_strafe, NULL}, {'w', NULL} ,
383 0,MAX_KEY,def_key,ss_keys, 0, 0}, // key to use with arrows to strafe
384 {"key_speed", {&key_speed, NULL}, {KEY_RSHIFT, NULL} ,
385 0,MAX_KEY,def_key,ss_keys, 0, 0}, // key to run
386
387 {"key_savegame", {&key_savegame, NULL}, {KEY_F2, NULL},
388 0,MAX_KEY,def_key,ss_keys, 0, 0}, // key to save current game
389 {"key_loadgame", {&key_loadgame, NULL}, {KEY_F3, NULL},
390 0,MAX_KEY,def_key,ss_keys, 0, 0}, // key to restore from saved games
391 {"key_soundvolume", {&key_soundvolume, NULL}, {KEY_F4, NULL},
392 0,MAX_KEY,def_key,ss_keys, 0, 0}, // key to bring up sound controls
393 {"key_hud", {&key_hud, NULL}, {KEY_F5, NULL},
394 0,MAX_KEY,def_key,ss_keys, 0, 0}, // key to adjust HUD
395 {"key_quicksave", {&key_quicksave, NULL}, {KEY_F6, NULL},
396 0,MAX_KEY,def_key,ss_keys, 0, 0}, // key to to quicksave
397 {"key_endgame", {&key_endgame, NULL}, {KEY_F7, NULL},
398 0,MAX_KEY,def_key,ss_keys, 0, 0}, // key to end the game
399 {"key_messages", {&key_messages, NULL}, {KEY_F8, NULL},
400 0,MAX_KEY,def_key,ss_keys, 0, 0}, // key to toggle message enable
401 {"key_quickload", {&key_quickload, NULL}, {KEY_F9, NULL},
402 0,MAX_KEY,def_key,ss_keys, 0, 0}, // key to load from quicksave
403 {"key_quit", {&key_quit, NULL}, {KEY_F10, NULL},
404 0,MAX_KEY,def_key,ss_keys, 0, 0}, // key to quit game
405 {"key_gamma", {&key_gamma, NULL}, {KEY_F11, NULL},
406 0,MAX_KEY,def_key,ss_keys, 0, 0}, // key to adjust gamma correction
407 {"key_spy", {&key_spy, NULL}, {KEY_F12, NULL},
408 0,MAX_KEY,def_key,ss_keys, 0, 0}, // key to view from another coop player's view
409 {"key_pause", {&key_pause, NULL}, {KEY_PAUSE, NULL},
410 0,MAX_KEY,def_key,ss_keys, 0, 0}, // key to pause the game
411 {"key_autorun", {&key_autorun, NULL}, {KEY_CAPSLOCK, NULL},
412 0,MAX_KEY,def_key,ss_keys, 0, 0}, // key to toggle always run mode
413 {"key_chat", {&key_chat, NULL}, {'t', NULL},
414 0,MAX_KEY,def_key,ss_keys, 0, 0}, // key to enter a chat message
415 {"key_backspace", {&key_backspace, NULL}, {KEY_BACKSPACE, NULL},
416 0,MAX_KEY,def_key,ss_keys, 0, 0}, // backspace key
417 {"key_enter", {&key_enter, NULL}, {KEY_ENTER, NULL},
418 0,MAX_KEY,def_key,ss_keys, 0, 0}, // key to select from menu or see last message
419 {"key_map", {&key_map, NULL}, {KEY_TAB, NULL},
420 0,MAX_KEY,def_key,ss_keys, 0, 0}, // key to toggle automap display
421 {"key_map_right", {&key_map_right, NULL}, {KEY_RIGHTARROW, NULL},// phares 3/7/98
422 0,MAX_KEY,def_key,ss_keys, 0, 0}, // key to shift automap right // |
423 {"key_map_left", {&key_map_left, NULL}, {KEY_LEFTARROW, NULL},// V
424 0,MAX_KEY,def_key,ss_keys, 0, 0}, // key to shift automap left
425 {"key_map_up", {&key_map_up, NULL}, {KEY_UPARROW, NULL},
426 0,MAX_KEY,def_key,ss_keys, 0, 0}, // key to shift automap up
427 {"key_map_down", {&key_map_down, NULL}, {KEY_DOWNARROW, NULL},
428 0,MAX_KEY,def_key,ss_keys, 0, 0}, // key to shift automap down
429 {"key_map_zoomin", {&key_map_zoomin, NULL}, {'=', NULL},
430 0,MAX_KEY,def_key,ss_keys, 0, 0}, // key to enlarge automap
431 {"key_map_zoomout", {&key_map_zoomout, NULL}, {'-', NULL},
432 0,MAX_KEY,def_key,ss_keys, 0, 0}, // key to reduce automap
433 {"key_map_gobig", {&key_map_gobig, NULL}, {'0', NULL},
434 0,MAX_KEY,def_key,ss_keys, 0, 0}, // key to get max zoom for automap
435 {"key_map_follow", {&key_map_follow, NULL}, {'f', NULL},
436 0,MAX_KEY,def_key,ss_keys, 0, 0}, // key to toggle follow mode
437 {"key_map_mark", {&key_map_mark, NULL}, {'m', NULL},
438 0,MAX_KEY,def_key,ss_keys, 0, 0}, // key to drop a marker on automap
439 {"key_map_clear", {&key_map_clear, NULL}, {'c', NULL},
440 0,MAX_KEY,def_key,ss_keys, 0, 0}, // key to clear all markers on automap
441 {"key_map_grid", {&key_map_grid, NULL}, {'g', NULL},
442 0,MAX_KEY,def_key,ss_keys, 0, 0}, // key to toggle grid display over automap
443 {"key_map_rotate", {&key_map_rotate, NULL}, {'r', NULL},
444 0,MAX_KEY,def_key,ss_keys, 0, 0}, // key to toggle rotating the automap to match the player's orientation
445 {"key_map_overlay", {&key_map_overlay, NULL}, {'o', NULL},
446 0,MAX_KEY,def_key,ss_keys, 0, 0}, // key to toggle overlaying the automap on the rendered display
447 {"key_reverse", {&key_reverse, NULL}, {'/', NULL},
448 0,MAX_KEY,def_key,ss_keys, 0, 0}, // key to spin 180 instantly
449 {"key_zoomin", {&key_zoomin, NULL}, {'=', NULL},
450 0,MAX_KEY,def_key,ss_keys, 0, 0}, // key to enlarge display
451 {"key_zoomout", {&key_zoomout, NULL}, {'-', NULL},
452 0,MAX_KEY,def_key,ss_keys, 0, 0}, // key to reduce display
453 {"key_chatplayer1", {&destination_keys[0], NULL}, {'g', NULL},
454 0,MAX_KEY,def_key,ss_keys, 0, 0}, // key to chat with player 1
455 // killough 11/98: fix 'i'/'b' reversal
456 {"key_chatplayer2", {&destination_keys[1], NULL}, {'i', NULL},
457 0,MAX_KEY,def_key,ss_keys, 0, 0}, // key to chat with player 2
458 {"key_chatplayer3", {&destination_keys[2], NULL}, {'b', NULL},
459 0,MAX_KEY,def_key,ss_keys, 0, 0}, // key to chat with player 3
460 {"key_chatplayer4", {&destination_keys[3], NULL}, {'r', NULL},
461 0,MAX_KEY,def_key,ss_keys, 0, 0}, // key to chat with player 4
462 {"key_weapon",{&key_weapon, NULL}, {KEY_UPARROW, NULL},
463 0,MAX_KEY,def_key,ss_keys, 0, 0}, // key to toggle between two most preferred weapons with ammo
464 {"key_weapontoggle",{&key_weapontoggle, NULL}, {'0', NULL},
465 0,MAX_KEY,def_key,ss_keys, 0, 0}, // key to toggle between two most preferred weapons with ammo
466 {"key_weapon1", {&key_weapon1, NULL}, {'1', NULL},
467 0,MAX_KEY,def_key,ss_keys, 0, 0}, // key to switch to weapon 1 (fist/chainsaw)
468 {"key_weapon2", {&key_weapon2, NULL}, {'2', NULL},
469 0,MAX_KEY,def_key,ss_keys, 0, 0}, // key to switch to weapon 2 (pistol)
470 {"key_weapon3", {&key_weapon3, NULL}, {'3', NULL},
471 0,MAX_KEY,def_key,ss_keys, 0, 0}, // key to switch to weapon 3 (supershotgun/shotgun)
472 {"key_weapon4", {&key_weapon4, NULL}, {'4', NULL},
473 0,MAX_KEY,def_key,ss_keys, 0, 0}, // key to switch to weapon 4 (chaingun)
474 {"key_weapon5", {&key_weapon5, NULL}, {'5', NULL},
475 0,MAX_KEY,def_key,ss_keys, 0, 0}, // key to switch to weapon 5 (rocket launcher)
476 {"key_weapon6", {&key_weapon6, NULL}, {'6', NULL},
477 0,MAX_KEY,def_key,ss_keys, 0, 0}, // key to switch to weapon 6 (plasma rifle)
478 {"key_weapon7", {&key_weapon7, NULL}, {'7', NULL},
479 0,MAX_KEY,def_key,ss_keys, 0, 0}, // key to switch to weapon 7 (bfg9000) // ^
480 {"key_weapon8", {&key_weapon8, NULL}, {'8', NULL},
481 0,MAX_KEY,def_key,ss_keys, 0, 0}, // key to switch to weapon 8 (chainsaw) // |
482 {"key_weapon9", {&key_weapon9, NULL}, {'9', NULL},
483 0,MAX_KEY,def_key,ss_keys, 0, 0}, // key to switch to weapon 9 (supershotgun) // phares
484
485 // killough 2/22/98: screenshot key
486 {"key_screenshot", {&key_screenshot, NULL}, {'*', NULL},
487 0,MAX_KEY,def_key,ss_keys, 0, 0}, // key to take a screenshot
488
489 /* {"Joystick settings",{NULL, NULL},{0, NULL},UL,UL,def_none,ss_none, 0, 0},
490 {"use_joystick",{&usejoystick, NULL},{0, NULL},0,2,
491 def_int,ss_none, 0, 0}, // number of joystick to use (0 for none)
492 {"joy_left",{&joyleft, NULL},{0, NULL}, UL,UL,def_int,ss_none, 0, 0},
493 {"joy_right",{&joyright, NULL},{0, NULL},UL,UL,def_int,ss_none, 0, 0},
494 {"joy_up", {&joyup, NULL}, {0, NULL}, UL,UL,def_int,ss_none, 0, 0},
495 {"joy_down",{&joydown, NULL},{0, NULL}, UL,UL,def_int,ss_none, 0, 0},
496 {"joyb_fire",{&joybfire, NULL},{0, NULL},0,UL,
497 def_int,ss_keys, 0, 0}, // joystick button number to use for fire
498 {"joyb_strafe",{&joybstrafe, NULL},{1, NULL},0,UL,
499 def_int,ss_keys, 0, 0}, // joystick button number to use for strafing
500 {"joyb_speed",{&joybspeed, NULL},{2, NULL},0,UL,
501 def_int,ss_keys, 0, 0}, // joystick button number to use for running
502 {"joyb_use",{&joybuse, NULL},{3, NULL},0,UL,
503 def_int,ss_keys, 0, 0}, // joystick button number to use for use/open
504*/
505 {"Chat macros",{NULL, NULL},{0, NULL},UL,UL,def_none,ss_none, 0, 0},
506 {"chatmacro0", {0,&chat_macros[0]}, {0,HUSTR_CHATMACRO0},UL,UL,
507 def_str,ss_chat, 0, 0}, // chat string associated with 0 key
508 {"chatmacro1", {0,&chat_macros[1]}, {0,HUSTR_CHATMACRO1},UL,UL,
509 def_str,ss_chat, 0, 0}, // chat string associated with 1 key
510 {"chatmacro2", {0,&chat_macros[2]}, {0,HUSTR_CHATMACRO2},UL,UL,
511 def_str,ss_chat, 0, 0}, // chat string associated with 2 key
512 {"chatmacro3", {0,&chat_macros[3]}, {0,HUSTR_CHATMACRO3},UL,UL,
513 def_str,ss_chat, 0, 0}, // chat string associated with 3 key
514 {"chatmacro4", {0,&chat_macros[4]}, {0,HUSTR_CHATMACRO4},UL,UL,
515 def_str,ss_chat, 0, 0}, // chat string associated with 4 key
516 {"chatmacro5", {0,&chat_macros[5]}, {0,HUSTR_CHATMACRO5},UL,UL,
517 def_str,ss_chat, 0, 0}, // chat string associated with 5 key
518 {"chatmacro6", {0,&chat_macros[6]}, {0,HUSTR_CHATMACRO6},UL,UL,
519 def_str,ss_chat, 0, 0}, // chat string associated with 6 key
520 {"chatmacro7", {0,&chat_macros[7]}, {0,HUSTR_CHATMACRO7},UL,UL,
521 def_str,ss_chat, 0, 0}, // chat string associated with 7 key
522 {"chatmacro8", {0,&chat_macros[8]}, {0,HUSTR_CHATMACRO8},UL,UL,
523 def_str,ss_chat, 0, 0}, // chat string associated with 8 key
524 {"chatmacro9", {0,&chat_macros[9]}, {0,HUSTR_CHATMACRO9},UL,UL,
525 def_str,ss_chat, 0, 0}, // chat string associated with 9 key
526
527 {"Automap settings",{NULL, NULL},{0, NULL},UL,UL,def_none,ss_none, 0, 0},
528 //jff 1/7/98 defaults for automap colors
529 //jff 4/3/98 remove -1 in lower range, 0 now disables new map features
530 {"mapcolor_back", {&mapcolor_back, NULL}, {247, NULL},0,255, // black //jff 4/6/98 new black
531 def_colour,ss_auto, 0, 0}, // color used as background for automap
532 {"mapcolor_grid", {&mapcolor_grid, NULL}, {104, NULL},0,255, // dk gray
533 def_colour,ss_auto, 0, 0}, // color used for automap grid lines
534 {"mapcolor_wall", {&mapcolor_wall, NULL}, {23, NULL},0,255, // red-brown
535 def_colour,ss_auto, 0, 0}, // color used for one side walls on automap
536 {"mapcolor_fchg", {&mapcolor_fchg, NULL}, {55, NULL},0,255, // lt brown
537 def_colour,ss_auto, 0, 0}, // color used for lines floor height changes across
538 {"mapcolor_cchg", {&mapcolor_cchg, NULL}, {215, NULL},0,255, // orange
539 def_colour,ss_auto, 0, 0}, // color used for lines ceiling height changes across
540 {"mapcolor_clsd", {&mapcolor_clsd, NULL}, {208, NULL},0,255, // white
541 def_colour,ss_auto, 0, 0}, // color used for lines denoting closed doors, objects
542 {"mapcolor_rkey", {&mapcolor_rkey, NULL}, {175, NULL},0,255, // red
543 def_colour,ss_auto, 0, 0}, // color used for red key sprites
544 {"mapcolor_bkey", {&mapcolor_bkey, NULL}, {204, NULL},0,255, // blue
545 def_colour,ss_auto, 0, 0}, // color used for blue key sprites
546 {"mapcolor_ykey", {&mapcolor_ykey, NULL}, {231, NULL},0,255, // yellow
547 def_colour,ss_auto, 0, 0}, // color used for yellow key sprites
548 {"mapcolor_rdor", {&mapcolor_rdor, NULL}, {175, NULL},0,255, // red
549 def_colour,ss_auto, 0, 0}, // color used for closed red doors
550 {"mapcolor_bdor", {&mapcolor_bdor, NULL}, {204, NULL},0,255, // blue
551 def_colour,ss_auto, 0, 0}, // color used for closed blue doors
552 {"mapcolor_ydor", {&mapcolor_ydor, NULL}, {231, NULL},0,255, // yellow
553 def_colour,ss_auto, 0, 0}, // color used for closed yellow doors
554 {"mapcolor_tele", {&mapcolor_tele, NULL}, {119, NULL},0,255, // dk green
555 def_colour,ss_auto, 0, 0}, // color used for teleporter lines
556 {"mapcolor_secr", {&mapcolor_secr, NULL}, {252, NULL},0,255, // purple
557 def_colour,ss_auto, 0, 0}, // color used for lines around secret sectors
558 {"mapcolor_exit", {&mapcolor_exit, NULL}, {0, NULL},0,255, // none
559 def_colour,ss_auto, 0, 0}, // color used for exit lines
560 {"mapcolor_unsn", {&mapcolor_unsn, NULL}, {104, NULL},0,255, // dk gray
561 def_colour,ss_auto, 0, 0}, // color used for lines not seen without computer map
562 {"mapcolor_flat", {&mapcolor_flat, NULL}, {88, NULL},0,255, // lt gray
563 def_colour,ss_auto, 0, 0}, // color used for lines with no height changes
564 {"mapcolor_sprt", {&mapcolor_sprt, NULL}, {112, NULL},0,255, // green
565 def_colour,ss_auto, 0, 0}, // color used as things
566 {"mapcolor_item", {&mapcolor_item, NULL}, {231, NULL},0,255, // yellow
567 def_colour,ss_auto, 0, 0}, // color used for counted items
568 {"mapcolor_hair", {&mapcolor_hair, NULL}, {208, NULL},0,255, // white
569 def_colour,ss_auto, 0, 0}, // color used for dot crosshair denoting center of map
570 {"mapcolor_sngl", {&mapcolor_sngl, NULL}, {208, NULL},0,255, // white
571 def_colour,ss_auto, 0, 0}, // color used for the single player arrow
572/* {"mapcolor_me", {&mapcolor_me, NULL}, {112, NULL},0,255, // green
573 def_colour,ss_auto, 0, 0}, // your (player) colour*/
574 {"mapcolor_frnd", {&mapcolor_frnd, NULL}, {112, NULL},0,255,
575 def_colour,ss_auto, 0, 0},
576 //jff 3/9/98 add option to not show secrets til after found
577 {"map_secret_after", {&map_secret_after, NULL}, {0, NULL},0,1, // show secret after gotten
578 def_bool,ss_auto, 0, 0}, // prevents showing secret sectors till after entered
579 {"map_point_coord", {&map_point_coordinates, NULL}, {0, NULL},0,1,
580 def_bool,ss_auto, 0, 0},
581 //jff 1/7/98 end additions for automap
582 {"automapmode", {(void*)&automapmode, NULL}, {0, NULL}, 0, 31, // CPhipps - remember automap mode
583 def_hex,ss_none, 0, 0}, // automap mode
584
585 {"Heads-up display settings",{NULL, NULL},{0, NULL},UL,UL,def_none,ss_none, 0, 0},
586 //jff 2/16/98 defaults for color ranges in hud and status
587 {"hudcolor_titl", {&hudcolor_titl, NULL}, {5, NULL},0,9, // gold range
588 def_int,ss_auto, 0, 0}, // color range used for automap level title
589 {"hudcolor_xyco", {&hudcolor_xyco, NULL}, {3, NULL},0,9, // green range
590 def_int,ss_auto, 0, 0}, // color range used for automap coordinates
591 {"hudcolor_mesg", {&hudcolor_mesg, NULL}, {6, NULL},0,9, // red range
592 def_int,ss_mess, 0, 0}, // color range used for messages during play
593 {"hudcolor_chat", {&hudcolor_chat, NULL}, {5, NULL},0,9, // gold range
594 def_int,ss_mess, 0, 0}, // color range used for chat messages and entry
595 {"hudcolor_list", {&hudcolor_list, NULL}, {5, NULL},0,9, // gold range //jff 2/26/98
596 def_int,ss_mess, 0, 0}, // color range used for message review
597 {"hud_msg_lines", {&hud_msg_lines, NULL}, {1, NULL},1,16, // 1 line scrolling window
598 def_int,ss_mess, 0, 0}, // number of messages in review display (1=disable)
599 {"hud_list_bgon", {&hud_list_bgon, NULL}, {0, NULL},0,1, // solid window bg ena //jff 2/26/98
600 def_bool,ss_mess, 0, 0}, // enables background window behind message review
601 {"hud_distributed",{&hud_distributed, NULL},{0, NULL},0,1, // hud broken up into 3 displays //jff 3/4/98
602 def_bool,ss_none, 0, 0}, // splits HUD into three 2 line displays
603
604 {"health_red", {&health_red, NULL}, {25, NULL},0,200, // below is red
605 def_int,ss_stat, 0, 0}, // amount of health for red to yellow transition
606 {"health_yellow", {&health_yellow, NULL}, {50, NULL},0,200, // below is yellow
607 def_int,ss_stat, 0, 0}, // amount of health for yellow to green transition
608 {"health_green", {&health_green, NULL}, {100, NULL},0,200,// below is green, above blue
609 def_int,ss_stat, 0, 0}, // amount of health for green to blue transition
610 {"armor_red", {&armor_red, NULL}, {25, NULL},0,200, // below is red
611 def_int,ss_stat, 0, 0}, // amount of armor for red to yellow transition
612 {"armor_yellow", {&armor_yellow, NULL}, {50, NULL},0,200, // below is yellow
613 def_int,ss_stat, 0, 0}, // amount of armor for yellow to green transition
614 {"armor_green", {&armor_green, NULL}, {100, NULL},0,200,// below is green, above blue
615 def_int,ss_stat, 0, 0}, // amount of armor for green to blue transition
616 {"ammo_red", {&ammo_red, NULL}, {25, NULL},0,100, // below 25% is red
617 def_int,ss_stat, 0, 0}, // percent of ammo for red to yellow transition
618 {"ammo_yellow", {&ammo_yellow, NULL}, {50, NULL},0,100, // below 50% is yellow, above green
619 def_int,ss_stat, 0, 0}, // percent of ammo for yellow to green transition
620
621 //jff 2/16/98 HUD and status feature controls
622 {"hud_active", {&hud_active, NULL}, {1, NULL},0,2, // 0=off, 1=small, 2=full
623 def_int,ss_none, 0, 0}, // 0 for HUD off, 1 for HUD small, 2 for full HUD
624 //jff 2/23/98
625 {"hud_displayed", {&hud_displayed, NULL}, {0, NULL},0,1, // whether hud is displayed
626 def_bool,ss_none, 0, 0}, // enables display of HUD
627 {"hud_nosecrets", {&hud_nosecrets, NULL}, {0, NULL},0,1, // no secrets/items/kills HUD line
628 def_bool,ss_stat, 0, 0}, // disables display of kills/items/secrets on HUD
629
630 {"Weapon preferences",{NULL, NULL},{0, NULL},UL,UL,def_none,ss_none, 0, 0},
631 // killough 2/8/98: weapon preferences set by user:
632 {"weapon_choice_1", {&weapon_preferences[0][0], NULL}, {6, NULL}, 0,9,
633 def_int,ss_weap, 0, 0}, // first choice for weapon (best)
634 {"weapon_choice_2", {&weapon_preferences[0][1], NULL}, {9, NULL}, 0,9,
635 def_int,ss_weap, 0, 0}, // second choice for weapon
636 {"weapon_choice_3", {&weapon_preferences[0][2], NULL}, {4, NULL}, 0,9,
637 def_int,ss_weap, 0, 0}, // third choice for weapon
638 {"weapon_choice_4", {&weapon_preferences[0][3], NULL}, {3, NULL}, 0,9,
639 def_int,ss_weap, 0, 0}, // fourth choice for weapon
640 {"weapon_choice_5", {&weapon_preferences[0][4], NULL}, {2, NULL}, 0,9,
641 def_int,ss_weap, 0, 0}, // fifth choice for weapon
642 {"weapon_choice_6", {&weapon_preferences[0][5], NULL}, {8, NULL}, 0,9,
643 def_int,ss_weap, 0, 0}, // sixth choice for weapon
644 {"weapon_choice_7", {&weapon_preferences[0][6], NULL}, {5, NULL}, 0,9,
645 def_int,ss_weap, 0, 0}, // seventh choice for weapon
646 {"weapon_choice_8", {&weapon_preferences[0][7], NULL}, {7, NULL}, 0,9,
647 def_int,ss_weap, 0, 0}, // eighth choice for weapon
648 {"weapon_choice_9", {&weapon_preferences[0][8], NULL}, {1, NULL}, 0,9,
649 def_int,ss_weap, 0, 0}, // ninth choice for weapon (worst)
650
651/* // cournia - support for arbitrary music file (defaults are mp3)
652 {"Music", {NULL, NULL},{0, NULL},UL,UL,def_none,ss_none, 0, 0},
653 {"mus_e1m1", {0,&S_music_files[mus_e1m1]}, {0,"e1m1.mp3"},UL,UL,
654 def_str,ss_none, 0, 0},
655 {"mus_e1m2", {0,&S_music_files[mus_e1m2]}, {0,"e1m2.mp3"},UL,UL,
656 def_str,ss_none, 0, 0},
657 {"mus_e1m3", {0,&S_music_files[mus_e1m3]}, {0,"e1m3.mp3"},UL,UL,
658 def_str,ss_none, 0, 0},
659 {"mus_e1m4", {0,&S_music_files[mus_e1m4]}, {0,"e1m4.mp3"},UL,UL,
660 def_str,ss_none, 0, 0},
661 {"mus_e1m5", {0,&S_music_files[mus_e1m5]}, {0,"e1m5.mp3"},UL,UL,
662 def_str,ss_none, 0, 0},
663 {"mus_e1m6", {0,&S_music_files[mus_e1m6]}, {0,"e1m6.mp3"},UL,UL,
664 def_str,ss_none, 0, 0},
665 {"mus_e1m7", {0,&S_music_files[mus_e1m7]}, {0,"e1m7.mp3"},UL,UL,
666 def_str,ss_none, 0, 0},
667 {"mus_e1m8", {0,&S_music_files[mus_e1m8]}, {0,"e1m8.mp3"},UL,UL,
668 def_str,ss_none, 0, 0},
669 {"mus_e1m9", {0,&S_music_files[mus_e1m9]}, {0,"e1m9.mp3"},UL,UL,
670 def_str,ss_none, 0, 0},
671 {"mus_e2m1", {0,&S_music_files[mus_e2m1]}, {0,"e2m1.mp3"},UL,UL,
672 def_str,ss_none, 0, 0},
673 {"mus_e2m2", {0,&S_music_files[mus_e2m2]}, {0,"e2m2.mp3"},UL,UL,
674 def_str,ss_none, 0, 0},
675 {"mus_e2m3", {0,&S_music_files[mus_e2m3]}, {0,"e2m3.mp3"},UL,UL,
676 def_str,ss_none, 0, 0},
677 {"mus_e2m4", {0,&S_music_files[mus_e2m4]}, {0,"e2m4.mp3"},UL,UL,
678 def_str,ss_none, 0, 0},
679 {"mus_e2m5", {0,&S_music_files[mus_e2m5]}, {0,"e1m7.mp3"},UL,UL,
680 def_str,ss_none, 0, 0},
681 {"mus_e2m6", {0,&S_music_files[mus_e2m6]}, {0,"e2m6.mp3"},UL,UL,
682 def_str,ss_none, 0, 0},
683 {"mus_e2m7", {0,&S_music_files[mus_e2m7]}, {0,"e2m7.mp3"},UL,UL,
684 def_str,ss_none, 0, 0},
685 {"mus_e2m8", {0,&S_music_files[mus_e2m8]}, {0,"e2m8.mp3"},UL,UL,
686 def_str,ss_none, 0, 0},
687 {"mus_e2m9", {0,&S_music_files[mus_e2m9]}, {0,"e3m1.mp3"},UL,UL,
688 def_str,ss_none, 0, 0},
689 {"mus_e3m1", {0,&S_music_files[mus_e3m1]}, {0,"e3m1.mp3"},UL,UL,
690 def_str,ss_none, 0, 0},
691 {"mus_e3m2", {0,&S_music_files[mus_e3m2]}, {0,"e3m2.mp3"},UL,UL,
692 def_str,ss_none, 0, 0},
693 {"mus_e3m3", {0,&S_music_files[mus_e3m3]}, {0,"e3m3.mp3"},UL,UL,
694 def_str,ss_none, 0, 0},
695 {"mus_e3m4", {0,&S_music_files[mus_e3m4]}, {0,"e1m8.mp3"},UL,UL,
696 def_str,ss_none, 0, 0},
697 {"mus_e3m5", {0,&S_music_files[mus_e3m5]}, {0,"e1m7.mp3"},UL,UL,
698 def_str,ss_none, 0, 0},
699 {"mus_e3m6", {0,&S_music_files[mus_e3m6]}, {0,"e1m6.mp3"},UL,UL,
700 def_str,ss_none, 0, 0},
701 {"mus_e3m7", {0,&S_music_files[mus_e3m7]}, {0,"e2m7.mp3"},UL,UL,
702 def_str,ss_none, 0, 0},
703 {"mus_e3m8", {0,&S_music_files[mus_e3m8]}, {0,"e3m8.mp3"},UL,UL,
704 def_str,ss_none, 0, 0},
705 {"mus_e3m9", {0,&S_music_files[mus_e3m9]}, {0,"e1m9.mp3"},UL,UL,
706 def_str,ss_none, 0, 0},
707 {"mus_inter", {0,&S_music_files[mus_inter]}, {0,"e2m3.mp3"},UL,UL,
708 def_str,ss_none, 0, 0},
709 {"mus_intro", {0,&S_music_files[mus_intro]}, {0,"intro.mp3"},UL,UL,
710 def_str,ss_none, 0, 0},
711 {"mus_bunny", {0,&S_music_files[mus_bunny]}, {0,"bunny.mp3"},UL,UL,
712 def_str,ss_none, 0, 0},
713 {"mus_victor", {0,&S_music_files[mus_victor]}, {0,"victor.mp3"},UL,UL,
714 def_str,ss_none, 0, 0},
715 {"mus_introa", {0,&S_music_files[mus_introa]}, {0,"intro.mp3"},UL,UL,
716 def_str,ss_none, 0, 0},
717 {"mus_runnin", {0,&S_music_files[mus_runnin]}, {0,"runnin.mp3"},UL,UL,
718 def_str,ss_none, 0, 0},
719 {"mus_stalks", {0,&S_music_files[mus_stalks]}, {0,"stalks.mp3"},UL,UL,
720 def_str,ss_none, 0, 0},
721 {"mus_countd", {0,&S_music_files[mus_countd]}, {0,"countd.mp3"},UL,UL,
722 def_str,ss_none, 0, 0},
723 {"mus_betwee", {0,&S_music_files[mus_betwee]}, {0,"betwee.mp3"},UL,UL,
724 def_str,ss_none, 0, 0},
725 {"mus_doom", {0,&S_music_files[mus_doom]}, {0,"doom.mp3"},UL,UL,
726 def_str,ss_none, 0, 0},
727 {"mus_the_da", {0,&S_music_files[mus_the_da]}, {0,"the_da.mp3"},UL,UL,
728 def_str,ss_none, 0, 0},
729 {"mus_shawn", {0,&S_music_files[mus_shawn]}, {0,"shawn.mp3"},UL,UL,
730 def_str,ss_none, 0, 0},
731 {"mus_ddtblu", {0,&S_music_files[mus_ddtblu]}, {0,"ddtblu.mp3"},UL,UL,
732 def_str,ss_none, 0, 0},
733 {"mus_in_cit", {0,&S_music_files[mus_in_cit]}, {0,"in_cit.mp3"},UL,UL,
734 def_str,ss_none, 0, 0},
735 {"mus_dead", {0,&S_music_files[mus_dead]}, {0,"dead.mp3"},UL,UL,
736 def_str,ss_none, 0, 0},
737 {"mus_stlks2", {0,&S_music_files[mus_stlks2]}, {0,"stalks.mp3"},UL,UL,
738 def_str,ss_none, 0, 0},
739 {"mus_theda2", {0,&S_music_files[mus_theda2]}, {0,"the_da.mp3"},UL,UL,
740 def_str,ss_none, 0, 0},
741 {"mus_doom2", {0,&S_music_files[mus_doom2]}, {0,"doom.mp3"},UL,UL,
742 def_str,ss_none, 0, 0},
743 {"mus_ddtbl2", {0,&S_music_files[mus_ddtbl2]}, {0,"ddtblu.mp3"},UL,UL,
744 def_str,ss_none, 0, 0},
745 {"mus_runni2", {0,&S_music_files[mus_runni2]}, {0,"runnin.mp3"},UL,UL,
746 def_str,ss_none, 0, 0},
747 {"mus_dead2", {0,&S_music_files[mus_dead2]}, {0,"dead.mp3"},UL,UL,
748 def_str,ss_none, 0, 0},
749 {"mus_stlks3", {0,&S_music_files[mus_stlks3]}, {0,"stalks.mp3"},UL,UL,
750 def_str,ss_none, 0, 0},
751 {"mus_romero", {0,&S_music_files[mus_romero]}, {0,"romero.mp3"},UL,UL,
752 def_str,ss_none, 0, 0},
753 {"mus_shawn2", {0,&S_music_files[mus_shawn2]}, {0,"shawn.mp3"},UL,UL,
754 def_str,ss_none, 0, 0},
755 {"mus_messag", {0,&S_music_files[mus_messag]}, {0,"messag.mp3"},UL,UL,
756 def_str,ss_none, 0, 0},
757 {"mus_count2", {0,&S_music_files[mus_count2]}, {0,"countd.mp3"},UL,UL,
758 def_str,ss_none, 0, 0},
759 {"mus_ddtbl3", {0,&S_music_files[mus_ddtbl3]}, {0,"ddtblu.mp3"},UL,UL,
760 def_str,ss_none, 0, 0},
761 {"mus_ampie", {0,&S_music_files[mus_ampie]}, {0,"ampie.mp3"},UL,UL,
762 def_str,ss_none, 0, 0},
763 {"mus_theda3", {0,&S_music_files[mus_theda3]}, {0,"the_da.mp3"},UL,UL,
764 def_str,ss_none, 0, 0},
765 {"mus_adrian", {0,&S_music_files[mus_adrian]}, {0,"adrian.mp3"},UL,UL,
766 def_str,ss_none, 0, 0},
767 {"mus_messg2", {0,&S_music_files[mus_messg2]}, {0,"messag.mp3"},UL,UL,
768 def_str,ss_none, 0, 0},
769 {"mus_romer2", {0,&S_music_files[mus_romer2]}, {0,"romero.mp3"},UL,UL,
770 def_str,ss_none, 0, 0},
771 {"mus_tense", {0,&S_music_files[mus_tense]}, {0,"tense.mp3"},UL,UL,
772 def_str,ss_none, 0, 0},
773 {"mus_shawn3", {0,&S_music_files[mus_shawn3]}, {0,"shawn.mp3"},UL,UL,
774 def_str,ss_none, 0, 0},
775 {"mus_openin", {0,&S_music_files[mus_openin]}, {0,"openin.mp3"},UL,UL,
776 def_str,ss_none, 0, 0},
777 {"mus_evil", {0,&S_music_files[mus_evil]}, {0,"evil.mp3"},UL,UL,
778 def_str,ss_none, 0, 0},
779 {"mus_ultima", {0,&S_music_files[mus_ultima]}, {0,"ultima.mp3"},UL,UL,
780 def_str,ss_none, 0, 0},
781 {"mus_read_m", {0,&S_music_files[mus_read_m]}, {0,"read_m.mp3"},UL,UL,
782 def_str,ss_none, 0, 0},
783 {"mus_dm2ttl", {0,&S_music_files[mus_dm2ttl]}, {0,"dm2ttl.mp3"},UL,UL,
784 def_str,ss_none, 0, 0},
785 {"mus_dm2int", {0,&S_music_files[mus_dm2int]}, {0,"dm2int.mp3"},UL,UL,
786 def_str,ss_none, 0, 0},
787*/
788 };
789
790int numdefaults;
791//static const char* defaultfile; // CPhipps - static, const
792
793//
794// M_SaveDefaults
795//
796
797void M_SaveDefaults (void)
798{
799 int i,fd;
800
801 fd = open (GAMEBASE"default.dfg", O_WRONLY|O_CREAT|O_TRUNC);
802 if (fd<0)
803 return; // can't write the file, but don't complain
804
805 for (i=0 ; i<numdefaults ; i++)
806 if(defaults[i].location.pi)
807 write(fd,defaults[i].location.pi, sizeof(int));
808
809 close (fd);
810}
811
812/*
813 * M_LookupDefault
814 *
815 * cph - mimic MBF function for now. Yes it's crap.
816 */
817
818struct default_s *M_LookupDefault(const char *name)
819{
820 int i;
821 for (i = 0 ; i < numdefaults ; i++)
822 if ((defaults[i].type != def_none) && !strcmp(name, defaults[i].name))
823 return &defaults[i];
824 I_Error("M_LookupDefault: %s not found",name);
825 return NULL;
826}
827
828//
829// M_LoadDefaults
830//
831
832#define NUMCHATSTRINGS 10 // phares 4/13/98
833
834void M_LoadDefaults (void)
835{
836 int i;
837 int fd;
838 // set everything to base values
839
840 numdefaults = sizeof(defaults)/sizeof(defaults[0]);
841 for (i = 0 ; i < numdefaults ; i++) {
842 if (defaults[i].location.ppsz)
843 *defaults[i].location.ppsz = strdup(defaults[i].defaultvalue.psz);
844 if (defaults[i].location.pi)
845 *defaults[i].location.pi = defaults[i].defaultvalue.i;
846 }
847
848 fd = open (GAMEBASE"default.dfg", O_RDONLY);
849 if (fd<0)
850 return; // don't have anything to read
851
852 for (i=0 ; i<numdefaults ; i++)
853 if(defaults[i].location.pi)
854 read(fd,defaults[i].location.pi, sizeof(int));
855
856 close (fd);
857}
858
859
860//
861// SCREEN SHOTS
862//
863
864// CPhipps - nasty but better than nothing
865static boolean screenshot_write_error;
866
867// jff 3/30/98 types and data structures for BMP output of screenshots
868//
869// killough 5/2/98:
870// Changed type names to avoid conflicts with endianess functions
871
872#define BI_RGB 0L
873
874typedef unsigned long dword_t;
875typedef long long_t;
876typedef unsigned char ubyte_t;
877
878typedef struct tagBITMAPFILEHEADER
879{
880 unsigned short bfType;
881 dword_t bfSize;
882 unsigned short bfReserved1;
883 unsigned short bfReserved2;
884 dword_t bfOffBits;
885} PACKEDATTR BITMAPFILEHEADER;
886
887typedef struct tagBITMAPINFOHEADER
888{
889 dword_t biSize;
890 long_t biWidth;
891 long_t biHeight;
892 unsigned short biPlanes;
893 unsigned short biBitCount;
894 dword_t biCompression;
895 dword_t biSizeImage;
896 long_t biXPelsPerMeter;
897 long_t biYPelsPerMeter;
898 dword_t biClrUsed;
899 dword_t biClrImportant;
900} PACKEDATTR BITMAPINFOHEADER;
901#if 0
902// jff 3/30/98 binary file write with error detection
903// CPhipps - static, const on parameter
904static void SafeWrite(const void *data, size_t size, size_t number, int st)
905{
906 /* if (write(data,size,number,st)<number)
907 screenshot_write_error = true; // CPhipps - made non-fatal*/
908}
909#endif
910//
911// WriteBMPfile
912// jff 3/30/98 Add capability to write a .BMP file (256 color uncompressed)
913//
914
915// CPhipps - static, const on parameters
916static void WriteBMPfile(const char* filename, const byte* data,
917 const int width, const int height, const byte* palette)
918{
919 (void)filename;
920 (void)data;
921 (void)width;
922 (void)height;
923 (void)palette;
924 /* int i,wid;
925 BITMAPFILEHEADER bmfh;
926 BITMAPINFOHEADER bmih;
927 int fhsiz,ihsiz;
928 FILE *st;
929 char zero=0;
930 ubyte_t c;
931
932 fhsiz = sizeof(BITMAPFILEHEADER);
933 ihsiz = sizeof(BITMAPINFOHEADER);
934 wid = 4*((width+3)/4);
935 //jff 4/22/98 add endian macros
936 bmfh.bfType = SHORT(19778);
937 bmfh.bfSize = LONG(fhsiz+ihsiz+256L*4+width*height);
938 bmfh.bfReserved1 = SHORT(0);
939 bmfh.bfReserved2 = SHORT(0);
940 bmfh.bfOffBits = LONG(fhsiz+ihsiz+256L*4);
941
942 bmih.biSize = LONG(ihsiz);
943 bmih.biWidth = LONG(width);
944 bmih.biHeight = LONG(height);
945 bmih.biPlanes = SHORT(1);
946 bmih.biBitCount = SHORT(8);
947 bmih.biCompression = LONG(BI_RGB);
948 bmih.biSizeImage = LONG(wid*height);
949 bmih.biXPelsPerMeter = LONG(0);
950 bmih.biYPelsPerMeter = LONG(0);
951 bmih.biClrUsed = LONG(256);
952 bmih.biClrImportant = LONG(256);
953
954 st = fopen(filename,"wb");
955 if (st!=NULL) {
956 // write the header
957 SafeWrite(&bmfh.bfType,sizeof(bmfh.bfType),1,st);
958 SafeWrite(&bmfh.bfSize,sizeof(bmfh.bfSize),1,st);
959 SafeWrite(&bmfh.bfReserved1,sizeof(bmfh.bfReserved1),1,st);
960 SafeWrite(&bmfh.bfReserved2,sizeof(bmfh.bfReserved2),1,st);
961 SafeWrite(&bmfh.bfOffBits,sizeof(bmfh.bfOffBits),1,st);
962
963 SafeWrite(&bmih.biSize,sizeof(bmih.biSize),1,st);
964 SafeWrite(&bmih.biWidth,sizeof(bmih.biWidth),1,st);
965 SafeWrite(&bmih.biHeight,sizeof(bmih.biHeight),1,st);
966 SafeWrite(&bmih.biPlanes,sizeof(bmih.biPlanes),1,st);
967 SafeWrite(&bmih.biBitCount,sizeof(bmih.biBitCount),1,st);
968 SafeWrite(&bmih.biCompression,sizeof(bmih.biCompression),1,st);
969 SafeWrite(&bmih.biSizeImage,sizeof(bmih.biSizeImage),1,st);
970 SafeWrite(&bmih.biXPelsPerMeter,sizeof(bmih.biXPelsPerMeter),1,st);
971 SafeWrite(&bmih.biYPelsPerMeter,sizeof(bmih.biYPelsPerMeter),1,st);
972 SafeWrite(&bmih.biClrUsed,sizeof(bmih.biClrUsed),1,st);
973 SafeWrite(&bmih.biClrImportant,sizeof(bmih.biClrImportant),1,st);
974
975 // write the palette, in blue-green-red order, gamma corrected
976 for (i=0;i<768;i+=3) {
977 c=gammatable[usegamma][palette[i+2]];
978 SafeWrite(&c,sizeof(char),1,st);
979 c=gammatable[usegamma][palette[i+1]];
980 SafeWrite(&c,sizeof(char),1,st);
981 c=gammatable[usegamma][palette[i+0]];
982 SafeWrite(&c,sizeof(char),1,st);
983 SafeWrite(&zero,sizeof(char),1,st);
984 }
985
986 for (i = 0 ; i < height ; i++)
987 SafeWrite(data+(height-1-i)*width,sizeof(byte),wid,st);
988
989 fclose(st);
990 }*/
991}
992
993//
994// M_ScreenShot
995//
996// Modified by Lee Killough so that any number of shots can be taken,
997// the code is faster, and no annoying "screenshot" message appears.
998
999// CPhipps - modified to use its own buffer for the image
1000// - checks for the case where no file can be created (doesn't occur on POSIX systems, would on DOS)
1001// - track errors better
1002// - split into 2 functions
1003
1004//
1005// M_DoScreenShot
1006// Takes a screenshot into the names file
1007
1008void M_DoScreenShot (const char* fname)
1009{
1010 byte *linear;
1011#ifndef GL_DOOM
1012 const byte *pal;
1013 int pplump = W_GetNumForName("PLAYPAL");
1014#endif
1015
1016 screenshot_write_error = false;
1017
1018#ifdef GL_DOOM
1019 // munge planar buffer to linear
1020 // CPhipps - use a malloc()ed buffer instead of screens[2]
1021 gld_ReadScreen(linear = malloc(SCREENWIDTH * SCREENHEIGHT * 3));
1022
1023 // save the bmp file
1024
1025 WriteTGAfile
1026 (fname, linear, SCREENWIDTH, SCREENHEIGHT);
1027#else
1028 // munge planar buffer to linear
1029 // CPhipps - use a malloc()ed buffer instead of screens[2]
1030 I_ReadScreen(linear = malloc(SCREENWIDTH * SCREENHEIGHT));
1031
1032 // killough 4/18/98: make palette stay around (PU_CACHE could cause crash)
1033 pal = W_CacheLumpNum (pplump);
1034
1035 // save the bmp file
1036
1037 WriteBMPfile
1038 (fname, linear, SCREENWIDTH, SCREENHEIGHT, pal);
1039
1040 // cph - free the palette
1041 W_UnlockLumpNum(pplump);
1042#endif
1043 free(linear);
1044 // 1/18/98 killough: replace "SCREEN SHOT" acknowledgement with sfx
1045
1046 if (screenshot_write_error)
1047 doom_printf("M_ScreenShot: Error writing screenshot");
1048}
1049
1050void M_ScreenShot(void)
1051{
1052 static int shot;
1053 char lbmname[32];
1054 int startshot;
1055
1056 screenshot_write_error = false;
1057
1058 if (fileexists(".")) screenshot_write_error = true;
1059
1060 startshot = shot; // CPhipps - prevent infinite loop
1061
1062 do
1063 snprintf(lbmname,sizeof(lbmname),"DOOM%d.BMP", shot++);
1064 while (!fileexists(lbmname) && (shot != startshot) && (shot < 10000));
1065
1066 if (!fileexists(lbmname)) screenshot_write_error = true;
1067
1068 if (screenshot_write_error) {
1069 doom_printf ("M_ScreenShot: Couldn't create a BMP");
1070 // killough 4/18/98
1071 return;
1072 }
1073
1074 M_DoScreenShot(lbmname); // cph
1075
1076 S_StartSound(NULL,gamemode==commercial ? sfx_radio : sfx_tink);
1077}
diff --git a/apps/plugins/doom/m_misc.h b/apps/plugins/doom/m_misc.h
new file mode 100644
index 0000000000..25eb8540c0
--- /dev/null
+++ b/apps/plugins/doom/m_misc.h
@@ -0,0 +1,112 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION:
28 * External non-system-specific stuff, like storing config settings,
29 * simple file handling, and saving screnshots.
30 *
31 *-----------------------------------------------------------------------------*/
32
33
34#ifndef __M_MISC__
35#define __M_MISC__
36
37
38#include "doomtype.h"
39//
40// MISC
41//
42
43boolean M_WriteFile (char const* name,void* source,int length);
44
45int M_ReadFile (char const* name,byte** buffer);
46
47void M_ScreenShot (void);
48void M_DoScreenShot (const char*); // cph
49
50void M_LoadDefaults (void);
51
52void M_SaveDefaults (void);
53
54
55int M_DrawText (int x,int y,boolean direct,char* string);
56
57struct default_s *M_LookupDefault(const char *name); /* killough 11/98 */
58
59// phares 4/21/98:
60// Moved from m_misc.c so m_menu.c could see it.
61
62// CPhipps - struct to hold a value in a config file
63// Cannot be a union, as it must be initialised
64typedef struct default_s
65{
66 const char* name;
67 /* cph -
68 * The location struct holds the pointer to the variable holding the
69 * setting. For int's we do nothing special.
70 * For strings, the string is actually stored on our heap with Z_Strdup()
71 * BUT we don't want the rest of the program to be able to modify them,
72 * so we declare it const. It's not really const though, and m_misc.c and
73 * m_menu.c cast it back when they need to change it. Possibly this is
74 * more trouble than it's worth.
75 */
76 struct {
77 int* pi;
78 const char** ppsz;
79 } location;
80 struct {
81 int i;
82 const char* psz;
83 } defaultvalue; // CPhipps - default value
84 // Limits (for an int)
85 int minvalue; // jff 3/3/98 minimum allowed value
86 int maxvalue; // jff 3/3/98 maximum allowed value
87 enum {
88 def_none, // Dummy entry
89 def_str, // A string
90 def_int, // Integer
91 def_hex, // Integer (write in hex)
92 def_bool = def_int, // Boolean
93 def_key = def_hex, // Key code (byte)
94 def_mouseb = def_int,// Mouse button
95 def_colour = def_hex // Colour (256 colour palette entry)
96 } type; // CPhipps - type of entry
97 int setupscreen; // phares 4/19/98: setup screen where this appears
98 int *current; /* cph - MBF-like pointer to current value */
99 // cph - removed the help strings from the config file
100 // const char* help; // jff 3/3/98 description of parameter
101 // CPhipps - remove unused "lousy hack" code
102 struct setup_menu_s *setup_menu; /* Xref to setup menu item, if any */
103} default_t;
104
105#define IS_STRING(dv) ((dv).type == def_str)
106// CPhipps - What is the max. key code that X will send us?
107#define MAX_KEY 65536
108#define MAX_MOUSEB 2
109
110#define UL (-123456789) /* magic number for no min or max for parameter */
111
112#endif
diff --git a/apps/plugins/doom/m_random.c b/apps/plugins/doom/m_random.c
new file mode 100644
index 0000000000..2c43aaf54c
--- /dev/null
+++ b/apps/plugins/doom/m_random.c
@@ -0,0 +1,136 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION:
28 * Random number LUT.
29 *
30 * 1/19/98 killough: Rewrote random number generator for better randomness,
31 * while at the same time maintaining demo sync and backward compatibility.
32 *
33 * 2/16/98 killough: Made each RNG local to each control-equivalent block,
34 * to reduce the chances of demo sync problems.
35 *
36 *-----------------------------------------------------------------------------*/
37
38
39#include "doomstat.h"
40#include "m_random.h"
41
42//
43// M_Random
44// Returns a 0-255 number
45//
46static const unsigned char rndtable[256] = { // 1/19/98 killough -- made const
47 0, 8, 109, 220, 222, 241, 149, 107, 75, 248, 254, 140, 16, 66 ,
48 74, 21, 211, 47, 80, 242, 154, 27, 205, 128, 161, 89, 77, 36 ,
49 95, 110, 85, 48, 212, 140, 211, 249, 22, 79, 200, 50, 28, 188 ,
50 52, 140, 202, 120, 68, 145, 62, 70, 184, 190, 91, 197, 152, 224 ,
51 149, 104, 25, 178, 252, 182, 202, 182, 141, 197, 4, 81, 181, 242 ,
52 145, 42, 39, 227, 156, 198, 225, 193, 219, 93, 122, 175, 249, 0 ,
53 175, 143, 70, 239, 46, 246, 163, 53, 163, 109, 168, 135, 2, 235 ,
54 25, 92, 20, 145, 138, 77, 69, 166, 78, 176, 173, 212, 166, 113 ,
55 94, 161, 41, 50, 239, 49, 111, 164, 70, 60, 2, 37, 171, 75 ,
56 136, 156, 11, 56, 42, 146, 138, 229, 73, 146, 77, 61, 98, 196 ,
57 135, 106, 63, 197, 195, 86, 96, 203, 113, 101, 170, 247, 181, 113 ,
58 80, 250, 108, 7, 255, 237, 129, 226, 79, 107, 112, 166, 103, 241 ,
59 24, 223, 239, 120, 198, 58, 60, 82, 128, 3, 184, 66, 143, 224 ,
60 145, 224, 81, 206, 163, 45, 63, 90, 168, 114, 59, 33, 159, 95 ,
61 28, 139, 123, 98, 125, 196, 15, 70, 194, 253, 54, 14, 109, 226 ,
62 71, 17, 161, 93, 186, 87, 244, 138, 20, 52, 123, 251, 26, 36 ,
63 17, 46, 52, 231, 232, 76, 31, 221, 84, 37, 216, 165, 212, 106 ,
64 197, 242, 98, 43, 39, 175, 254, 145, 190, 84, 118, 222, 187, 136 ,
65 120, 163, 236, 249
66 };
67
68rng_t rng; // the random number state
69
70unsigned long rngseed = 1993; // killough 3/26/98: The seed
71
72int P_Random(pr_class_t pr_class)
73{
74 // killough 2/16/98: We always update both sets of random number
75 // generators, to ensure repeatability if the demo_compatibility
76 // flag is changed while the program is running. Changing the
77 // demo_compatibility flag does not change the sequences generated,
78 // only which one is selected from.
79 //
80 // All of this RNG stuff is tricky as far as demo sync goes --
81 // it's like playing with explosives :) Lee
82
83 int compat = pr_class == pr_misc ?
84 (rng.prndindex = (rng.prndindex + 1) & 255) :
85 (rng. rndindex = (rng. rndindex + 1) & 255) ;
86
87 unsigned long boom;
88
89 // killough 3/31/98:
90 // If demo sync insurance is not requested, use
91 // much more unstable method by putting everything
92 // except pr_misc into pr_all_in_one
93
94 if (pr_class != pr_misc && !demo_insurance) // killough 3/31/98
95 pr_class = pr_all_in_one;
96
97 boom = rng.seed[pr_class];
98
99 // killough 3/26/98: add pr_class*2 to addend
100
101 rng.seed[pr_class] = boom * 1664525ul + 221297ul + pr_class*2;
102
103 if (demo_compatibility)
104 return rndtable[compat];
105
106 boom >>= 20;
107
108 /* killough 3/30/98: use gametic-levelstarttic to shuffle RNG
109 * killough 3/31/98: but only if demo insurance requested,
110 * since it's unnecessary for random shuffling otherwise
111 * killough 9/29/98: but use basetic now instead of levelstarttic
112 * cph - DEMOSYNC - this change makes MBF demos work,
113 * but does it break Boom ones?
114 */
115
116 if (demo_insurance)
117 boom += (gametic-basetic)*7;
118
119 return boom & 255;
120}
121
122// Initialize all the seeds
123//
124// This initialization method is critical to maintaining demo sync.
125// Each seed is initialized according to its class, so if new classes
126// are added they must be added to end of pr_class_t list. killough
127//
128
129void M_ClearRandom (void)
130{
131 int i;
132 unsigned long seed = rngseed*2+1; // add 3/26/98: add rngseed
133 for (i=0; i<NUMPRCLASS; i++) // go through each pr_class and set
134 rng.seed[i] = seed *= 69069ul; // each starting seed differently
135 rng.prndindex = rng.rndindex = 0; // clear two compatibility indices
136}
diff --git a/apps/plugins/doom/m_random.h b/apps/plugins/doom/m_random.h
new file mode 100644
index 0000000000..67c1a3ba4b
--- /dev/null
+++ b/apps/plugins/doom/m_random.h
@@ -0,0 +1,148 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION:
28 * Functions to return random numbers.
29 *
30 *-----------------------------------------------------------------------------*/
31
32
33#ifndef __M_RANDOM__
34#define __M_RANDOM__
35
36#include "doomtype.h"
37
38// killough 1/19/98: rewritten to use to use a better random number generator
39// in the new engine, although the old one is available for compatibility.
40
41// killough 2/16/98:
42//
43// Make every random number generator local to each control-equivalent block.
44// Critical for demo sync. Changing the order of this list breaks all previous
45// versions' demos. The random number generators are made local to reduce the
46// chances of sync problems. In Doom, if a single random number generator call
47// was off, it would mess up all random number generators. This reduces the
48// chances of it happening by making each RNG local to a control flow block.
49//
50// Notes to developers: if you want to reduce your demo sync hassles, follow
51// this rule: for each call to P_Random you add, add a new class to the enum
52// type below for each block of code which calls P_Random. If two calls to
53// P_Random are not in "control-equivalent blocks", i.e. there are any cases
54// where one is executed, and the other is not, put them in separate classes.
55//
56// Keep all current entries in this list the same, and in the order
57// indicated by the #'s, because they're critical for preserving demo
58// sync. Do not remove entries simply because they become unused later.
59
60typedef enum {
61 pr_skullfly, // #1
62 pr_damage, // #2
63 pr_crush, // #3
64 pr_genlift, // #4
65 pr_killtics, // #5
66 pr_damagemobj, // #6
67 pr_painchance, // #7
68 pr_lights, // #8
69 pr_explode, // #9
70 pr_respawn, // #10
71 pr_lastlook, // #11
72 pr_spawnthing, // #12
73 pr_spawnpuff, // #13
74 pr_spawnblood, // #14
75 pr_missile, // #15
76 pr_shadow, // #16
77 pr_plats, // #17
78 pr_punch, // #18
79 pr_punchangle, // #19
80 pr_saw, // #20
81 pr_plasma, // #21
82 pr_gunshot, // #22
83 pr_misfire, // #23
84 pr_shotgun, // #24
85 pr_bfg, // #25
86 pr_slimehurt, // #26
87 pr_dmspawn, // #27
88 pr_missrange, // #28
89 pr_trywalk, // #29
90 pr_newchase, // #30
91 pr_newchasedir, // #31
92 pr_see, // #32
93 pr_facetarget, // #33
94 pr_posattack, // #34
95 pr_sposattack, // #35
96 pr_cposattack, // #36
97 pr_spidrefire, // #37
98 pr_troopattack, // #38
99 pr_sargattack, // #39
100 pr_headattack, // #40
101 pr_bruisattack, // #41
102 pr_tracer, // #42
103 pr_skelfist, // #43
104 pr_scream, // #44
105 pr_brainscream, // #45
106 pr_cposrefire, // #46
107 pr_brainexp, // #47
108 pr_spawnfly, // #48
109 pr_misc, // #49
110 pr_all_in_one, // #50
111 /* CPhipps - new entries from MBF, mostly unused for now */
112 pr_opendoor, // #51
113 pr_targetsearch, // #52
114 pr_friends, // #53
115 pr_threshold, // #54
116 pr_skiptarget, // #55
117 pr_enemystrafe, // #56
118 pr_avoidcrush, // #57
119 pr_stayonlift, // #58
120 pr_helpfriend, // #59
121 pr_dropoff, // #60
122 pr_randomjump, // #61
123 pr_defect, // #62 // Start new entries -- add new entries below
124
125 // End of new entries
126 NUMPRCLASS // MUST be last item in list
127} pr_class_t;
128
129// The random number generator's state.
130typedef struct {
131 unsigned long seed[NUMPRCLASS]; // Each block's random seed
132 int rndindex, prndindex; // For compatibility support
133} rng_t;
134
135extern rng_t rng; // The rng's state
136
137extern unsigned long rngseed; // The starting seed (not part of state)
138
139// Returns a number from 0 to 255,
140#define M_Random() P_Random(pr_misc)
141
142// As M_Random, but used by the play simulation.
143int P_Random(pr_class_t);
144
145// Fix randoms for demos.
146void M_ClearRandom(void);
147
148#endif
diff --git a/apps/plugins/doom/m_swap.h b/apps/plugins/doom/m_swap.h
new file mode 100644
index 0000000000..fdf2b92a15
--- /dev/null
+++ b/apps/plugins/doom/m_swap.h
@@ -0,0 +1,104 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION:
28 * Endianess handling, swapping 16bit and 32bit.
29 *
30 *-----------------------------------------------------------------------------*/
31
32
33#ifndef __M_SWAP__
34#define __M_SWAP__
35
36#ifdef __GNUG__
37#pragma interface
38#endif
39
40/* Endianess handling. */
41
42/* cph - First the macros to do the actual byte swapping */
43
44/* leban
45 * rather than continue the confusing tradition of redefining the
46 * stardard macro, we now present the doom_ntoh and doom_hton macros....
47 * might as well use the xdoom macros.
48 */
49
50#ifndef doom_swap_l
51#define doom_swap_l(x) \
52 ((long int)((((unsigned long int)(x) & 0x000000ffU) << 24) | \
53 (((unsigned long int)(x) & 0x0000ff00U) << 8) | \
54 (((unsigned long int)(x) & 0x00ff0000U) >> 8) | \
55 (((unsigned long int)(x) & 0xff000000U) >> 24)))
56#endif
57
58#ifndef doom_swap_s
59#define doom_swap_s(x) \
60 ((short int)((((unsigned short int)(x) & 0x00ff) << 8) | \
61 (((unsigned short int)(x) & 0xff00) >> 8)))
62#endif
63
64/* Macros are named doom_XtoYT, where
65 * X is thing to convert from, Y is thing to convert to, chosen from
66 * n for network, h for host (i.e our machine's), w for WAD (Doom data files)
67 * and T is the type, l or s for long or short
68 *
69 * CPhipps - all WADs and network packets will be little endian for now
70 * Use separate macros so network could be converted to big-endian later.
71 */
72
73#ifdef __BIG_ENDIAN__
74
75#define doom_wtohl(x) doom_swap_l(x)
76#define doom_htowl(x) doom_swap_l(x)
77#define doom_wtohs(x) doom_swap_s(x)
78#define doom_htows(x) doom_swap_s(x)
79
80#define doom_ntohl(x) doom_swap_l(x)
81#define doom_htonl(x) doom_swap_l(x)
82#define doom_ntohs(x) doom_swap_s(x)
83#define doom_htons(x) doom_swap_s(x)
84
85#else
86
87#define doom_wtohl(x) (long int)(x)
88#define doom_htowl(x) (long int)(x)
89#define doom_wtohs(x) (short int)(x)
90#define doom_htows(x) (short int)(x)
91
92#define doom_ntohl(x) (long int)(x)
93#define doom_htonl(x) (long int)(x)
94#define doom_ntohs(x) (short int)(x)
95#define doom_htons(x) (short int)(x)
96
97#endif
98
99/* CPhipps - Boom's old LONG and SHORT endianness macros are for WAD stuff */
100
101#define LONG(x) doom_wtohl(x)
102#define SHORT(x) doom_htows(x)
103
104#endif
diff --git a/apps/plugins/doom/p_ceilng.c b/apps/plugins/doom/p_ceilng.c
new file mode 100644
index 0000000000..db5a701b1a
--- /dev/null
+++ b/apps/plugins/doom/p_ceilng.c
@@ -0,0 +1,468 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION:
28 * Ceiling aninmation (lowering, crushing, raising)
29 *
30 *-----------------------------------------------------------------------------*/
31
32#include "doomstat.h"
33#include "r_main.h"
34#include "p_spec.h"
35#include "p_tick.h"
36#include "s_sound.h"
37#include "sounds.h"
38#include "z_zone.h"
39#include "doomdef.h"
40#define PU_LEVSPEC 51 // a special thinker in a level
41#include "rockmacros.h"
42
43// the list of ceilings moving currently, including crushers
44ceilinglist_t *activeceilings;
45
46/////////////////////////////////////////////////////////////////
47//
48// Ceiling action routine and linedef type handler
49//
50/////////////////////////////////////////////////////////////////
51
52//
53// T_MoveCeiling
54//
55// Action routine that moves ceilings. Called once per tick.
56//
57// Passed a ceiling_t structure that contains all the info about the move.
58// see P_SPEC.H for fields. No return.
59//
60// jff 02/08/98 all cases with labels beginning with gen added to support
61// generalized line type behaviors.
62//
63void T_MoveCeiling (ceiling_t* ceiling)
64{
65 result_e res;
66
67 switch(ceiling->direction)
68 {
69 case 0:
70 // If ceiling in stasis, do nothing
71 break;
72
73 case 1:
74 // Ceiling is moving up
75 res = T_MovePlane
76 (
77 ceiling->sector,
78 ceiling->speed,
79 ceiling->topheight,
80 false,
81 1,
82 ceiling->direction
83 );
84
85 // if not a silent crusher, make moving sound
86 if (!(leveltime&7))
87 {
88 switch(ceiling->type)
89 {
90 case silentCrushAndRaise:
91 case genSilentCrusher:
92 break;
93 default:
94 S_StartSound((mobj_t *)&ceiling->sector->soundorg,sfx_stnmov);
95 break;
96 }
97 }
98
99 // handle reaching destination height
100 if (res == pastdest)
101 {
102 switch(ceiling->type)
103 {
104 // plain movers are just removed
105 case raiseToHighest:
106 case genCeiling:
107 P_RemoveActiveCeiling(ceiling);
108 break;
109
110 // movers with texture change, change the texture then get removed
111 case genCeilingChgT:
112 case genCeilingChg0:
113 ceiling->sector->special = ceiling->newspecial;
114 //jff 3/14/98 transfer old special field as well
115 ceiling->sector->oldspecial = ceiling->oldspecial;
116 case genCeilingChg:
117 ceiling->sector->ceilingpic = ceiling->texture;
118 P_RemoveActiveCeiling(ceiling);
119 break;
120
121 // crushers reverse direction at the top
122 case silentCrushAndRaise:
123 S_StartSound((mobj_t *)&ceiling->sector->soundorg,sfx_pstop);
124 case genSilentCrusher:
125 case genCrusher:
126 case fastCrushAndRaise:
127 case crushAndRaise:
128 ceiling->direction = -1;
129 break;
130
131 default:
132 break;
133 }
134 }
135 break;
136
137 case -1:
138 // Ceiling moving down
139 res = T_MovePlane
140 (
141 ceiling->sector,
142 ceiling->speed,
143 ceiling->bottomheight,
144 ceiling->crush,
145 1,
146 ceiling->direction
147 );
148
149 // if not silent crusher type make moving sound
150 if (!(leveltime&7))
151 {
152 switch(ceiling->type)
153 {
154 case silentCrushAndRaise:
155 case genSilentCrusher:
156 break;
157 default:
158 S_StartSound((mobj_t *)&ceiling->sector->soundorg,sfx_stnmov);
159 }
160 }
161
162 // handle reaching destination height
163 if (res == pastdest)
164 {
165 switch(ceiling->type)
166 {
167 // 02/09/98 jff change slow crushers' speed back to normal
168 // start back up
169 case genSilentCrusher:
170 case genCrusher:
171 if (ceiling->oldspeed<CEILSPEED*3)
172 ceiling->speed = ceiling->oldspeed;
173 ceiling->direction = 1; //jff 2/22/98 make it go back up!
174 break;
175
176 // make platform stop at bottom of all crusher strokes
177 // except generalized ones, reset speed, start back up
178 case silentCrushAndRaise:
179 S_StartSound((mobj_t *)&ceiling->sector->soundorg,sfx_pstop);
180 case crushAndRaise:
181 ceiling->speed = CEILSPEED;
182 case fastCrushAndRaise:
183 ceiling->direction = 1;
184 break;
185
186 // in the case of ceiling mover/changer, change the texture
187 // then remove the active ceiling
188 case genCeilingChgT:
189 case genCeilingChg0:
190 ceiling->sector->special = ceiling->newspecial;
191 //jff add to fix bug in special transfers from changes
192 ceiling->sector->oldspecial = ceiling->oldspecial;
193 case genCeilingChg:
194 ceiling->sector->ceilingpic = ceiling->texture;
195 P_RemoveActiveCeiling(ceiling);
196 break;
197
198 // all other case, just remove the active ceiling
199 case lowerAndCrush:
200 case lowerToFloor:
201 case lowerToLowest:
202 case lowerToMaxFloor:
203 case genCeiling:
204 P_RemoveActiveCeiling(ceiling);
205 break;
206
207 default:
208 break;
209 }
210 }
211 else // ( res != pastdest )
212 {
213 // handle the crusher encountering an obstacle
214 if (res == crushed)
215 {
216 switch(ceiling->type)
217 {
218 //jff 02/08/98 slow down slow crushers on obstacle
219 case genCrusher:
220 case genSilentCrusher:
221 if (ceiling->oldspeed < CEILSPEED*3)
222 ceiling->speed = CEILSPEED / 8;
223 break;
224 case silentCrushAndRaise:
225 case crushAndRaise:
226 case lowerAndCrush:
227 ceiling->speed = CEILSPEED / 8;
228 break;
229
230 default:
231 break;
232 }
233 }
234 }
235 break;
236 }
237}
238
239
240//
241// EV_DoCeiling
242//
243// Move a ceiling up/down or start a crusher
244//
245// Passed the linedef activating the function and the type of function desired
246// returns true if a thinker started
247//
248int EV_DoCeiling
249( line_t* line,
250 ceiling_e type )
251{
252 int secnum;
253 int rtn;
254 sector_t* sec;
255 ceiling_t* ceiling;
256
257 secnum = -1;
258 rtn = 0;
259
260 // Reactivate in-stasis ceilings...for certain types.
261 // This restarts a crusher after it has been stopped
262 switch(type)
263 {
264 case fastCrushAndRaise:
265 case silentCrushAndRaise:
266 case crushAndRaise:
267 //jff 4/5/98 return if activated
268 rtn = P_ActivateInStasisCeiling(line);
269 default:
270 break;
271 }
272
273 // affects all sectors with the same tag as the linedef
274 while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0)
275 {
276 sec = &sectors[secnum];
277
278 // if ceiling already moving, don't start a second function on it
279 if (P_SectorActive(ceiling_special,sec)) //jff 2/22/98
280 continue;
281
282 // create a new ceiling thinker
283 rtn = 1;
284 ceiling = Z_Malloc (sizeof(*ceiling), PU_LEVSPEC, 0);
285 P_AddThinker (&ceiling->thinker);
286 sec->ceilingdata = ceiling; //jff 2/22/98
287 ceiling->thinker.function = T_MoveCeiling;
288 ceiling->sector = sec;
289 ceiling->crush = false;
290
291 // setup ceiling structure according to type of function
292 switch(type)
293 {
294 case fastCrushAndRaise:
295 ceiling->crush = true;
296 ceiling->topheight = sec->ceilingheight;
297 ceiling->bottomheight = sec->floorheight + (8*FRACUNIT);
298 ceiling->direction = -1;
299 ceiling->speed = CEILSPEED * 2;
300 break;
301
302 case silentCrushAndRaise:
303 case crushAndRaise:
304 ceiling->crush = true;
305 ceiling->topheight = sec->ceilingheight;
306 case lowerAndCrush:
307 case lowerToFloor:
308 ceiling->bottomheight = sec->floorheight;
309 if (type != lowerToFloor)
310 ceiling->bottomheight += 8*FRACUNIT;
311 ceiling->direction = -1;
312 ceiling->speed = CEILSPEED;
313 break;
314
315 case raiseToHighest:
316 ceiling->topheight = P_FindHighestCeilingSurrounding(sec);
317 ceiling->direction = 1;
318 ceiling->speed = CEILSPEED;
319 break;
320
321 case lowerToLowest:
322 ceiling->bottomheight = P_FindLowestCeilingSurrounding(sec);
323 ceiling->direction = -1;
324 ceiling->speed = CEILSPEED;
325 break;
326
327 case lowerToMaxFloor:
328 ceiling->bottomheight = P_FindHighestFloorSurrounding(sec);
329 ceiling->direction = -1;
330 ceiling->speed = CEILSPEED;
331 break;
332
333 default:
334 break;
335 }
336
337 // add the ceiling to the active list
338 ceiling->tag = sec->tag;
339 ceiling->type = type;
340 P_AddActiveCeiling(ceiling);
341 }
342 return rtn;
343}
344
345//////////////////////////////////////////////////////////////////////
346//
347// Active ceiling list primitives
348//
349/////////////////////////////////////////////////////////////////////
350
351// jff 2/22/98 - modified Lee's plat code to work for ceilings
352//
353// The following were all rewritten by Lee Killough
354// to use the new structure which places no limits
355// on active ceilings. It also avoids spending as much
356// time searching for active ceilings. Previously a
357// fixed-size array was used, with NULL indicating
358// empty entries, while now a doubly-linked list
359// is used.
360
361//
362// P_ActivateInStasisCeiling()
363//
364// Reactivates all stopped crushers with the right tag
365//
366// Passed the line reactivating the crusher
367// Returns true if a ceiling reactivated
368//
369//jff 4/5/98 return if activated
370int P_ActivateInStasisCeiling(line_t *line)
371{
372 ceilinglist_t *cl;
373 int rtn=0;
374
375 for (cl=activeceilings; cl; cl=cl->next)
376 {
377 ceiling_t *ceiling = cl->ceiling;
378 if (ceiling->tag == line->tag && ceiling->direction == 0)
379 {
380 ceiling->direction = ceiling->olddirection;
381 ceiling->thinker.function = T_MoveCeiling;
382 //jff 4/5/98 return if activated
383 rtn=1;
384 }
385 }
386 return rtn;
387}
388
389//
390// EV_CeilingCrushStop()
391//
392// Stops all active ceilings with the right tag
393//
394// Passed the linedef stopping the ceilings
395// Returns true if a ceiling put in stasis
396//
397int EV_CeilingCrushStop(line_t* line)
398{
399 int rtn=0;
400
401 ceilinglist_t *cl;
402 for (cl=activeceilings; cl; cl=cl->next)
403 {
404 ceiling_t *ceiling = cl->ceiling;
405 if (ceiling->direction != 0 && ceiling->tag == line->tag)
406 {
407 ceiling->olddirection = ceiling->direction;
408 ceiling->direction = 0;
409 ceiling->thinker.function = NULL;
410 rtn=1;
411 }
412 }
413 return rtn;
414}
415
416//
417// P_AddActiveCeiling()
418//
419// Adds a ceiling to the head of the list of active ceilings
420//
421// Passed the ceiling motion structure
422// Returns nothing
423//
424void P_AddActiveCeiling(ceiling_t* ceiling)
425{
426 ceilinglist_t *list = malloc(sizeof *list);
427 list->ceiling = ceiling;
428 ceiling->list = list;
429 if ((list->next = activeceilings))
430 list->next->prev = &list->next;
431 list->prev = &activeceilings;
432 activeceilings = list;
433}
434
435//
436// P_RemoveActiveCeiling()
437//
438// Removes a ceiling from the list of active ceilings
439//
440// Passed the ceiling motion structure
441// Returns nothing
442//
443void P_RemoveActiveCeiling(ceiling_t* ceiling)
444{
445 ceilinglist_t *list = ceiling->list;
446 ceiling->sector->ceilingdata = NULL; //jff 2/22/98
447 P_RemoveThinker(&ceiling->thinker);
448 if ((*list->prev = list->next))
449 list->next->prev = list->prev;
450 free(list);
451}
452
453//
454// P_RemoveAllActiveCeilings()
455//
456// Removes all ceilings from the active ceiling list
457//
458// Passed nothing, returns nothing
459//
460void P_RemoveAllActiveCeilings(void)
461{
462 while (activeceilings)
463 {
464 ceilinglist_t *next = activeceilings->next;
465 free(activeceilings);
466 activeceilings = next;
467 }
468}
diff --git a/apps/plugins/doom/p_doors.c b/apps/plugins/doom/p_doors.c
new file mode 100644
index 0000000000..9d8f28cd7a
--- /dev/null
+++ b/apps/plugins/doom/p_doors.c
@@ -0,0 +1,672 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION:
28 * Door animation code (opening/closing)
29 *
30 *-----------------------------------------------------------------------------*/
31
32#include "doomstat.h"
33#include "p_spec.h"
34#include "p_tick.h"
35#include "s_sound.h"
36#include "sounds.h"
37#include "r_main.h"
38#include "dstrings.h"
39//#include "d_deh.h" // Ty 03/27/98 - externalized
40
41#include "rockmacros.h"
42
43///////////////////////////////////////////////////////////////
44//
45// Door action routines, called once per tick
46//
47///////////////////////////////////////////////////////////////
48
49//
50// T_VerticalDoor
51//
52// Passed a door structure containing all info about the door.
53// See P_SPEC.H for fields.
54// Returns nothing.
55//
56// jff 02/08/98 all cases with labels beginning with gen added to support
57// generalized line type behaviors.
58
59void T_VerticalDoor (vldoor_t* door)
60{
61 result_e res;
62
63 // Is the door waiting, going up, or going down?
64 switch(door->direction)
65 {
66 case 0:
67 // Door is waiting
68 if (!--door->topcountdown) // downcount and check
69 {
70 switch(door->type)
71 {
72 case blazeRaise:
73 case genBlazeRaise:
74 door->direction = -1; // time to go back down
75 S_StartSound((mobj_t *)&door->sector->soundorg,sfx_bdcls);
76 break;
77
78 case normal:
79 case genRaise:
80 door->direction = -1; // time to go back down
81 S_StartSound((mobj_t *)&door->sector->soundorg,sfx_dorcls);
82 break;
83
84 case close30ThenOpen:
85 case genCdO:
86 door->direction = 1; // time to go back up
87 S_StartSound((mobj_t *)&door->sector->soundorg,sfx_doropn);
88 break;
89
90 case genBlazeCdO:
91 door->direction = 1; // time to go back up
92 S_StartSound((mobj_t *)&door->sector->soundorg,sfx_bdopn);
93 break;
94
95 default:
96 break;
97 }
98 }
99 break;
100
101 case 2:
102 // Special case for sector type door that opens in 5 mins
103 if (!--door->topcountdown) // 5 minutes up?
104 {
105 switch(door->type)
106 {
107 case raiseIn5Mins:
108 door->direction = 1; // time to raise then
109 door->type = normal; // door acts just like normal 1 DR door now
110 S_StartSound((mobj_t *)&door->sector->soundorg,sfx_doropn);
111 break;
112
113 default:
114 break;
115 }
116 }
117 break;
118
119 case -1:
120 // Door is moving down
121 res = T_MovePlane
122 (
123 door->sector,
124 door->speed,
125 door->sector->floorheight,
126 false,
127 1,
128 door->direction
129 );
130
131 /* killough 10/98: implement gradual lighting effects */
132 if (door->lighttag && door->topheight - door->sector->floorheight)
133 EV_LightTurnOnPartway(door->line,
134 FixedDiv(door->sector->ceilingheight -
135 door->sector->floorheight,
136 door->topheight -
137 door->sector->floorheight));
138
139 // handle door reaching bottom
140 if (res == pastdest)
141 {
142 switch(door->type)
143 {
144 // regular open and close doors are all done, remove them
145 case blazeRaise:
146 case blazeClose:
147 case genBlazeRaise:
148 case genBlazeClose:
149 door->sector->ceilingdata = NULL; //jff 2/22/98
150 P_RemoveThinker (&door->thinker); // unlink and free
151 // killough 4/15/98: remove double-closing sound of blazing doors
152 if (comp[comp_blazing])
153 S_StartSound((mobj_t *)&door->sector->soundorg,sfx_bdcls);
154 break;
155
156 case normal:
157 case p_close:
158 case genRaise:
159 case genClose:
160 door->sector->ceilingdata = NULL; //jff 2/22/98
161 P_RemoveThinker (&door->thinker); // unlink and free
162 break;
163
164 // close then open doors start waiting
165 case close30ThenOpen:
166 door->direction = 0;
167 door->topcountdown = TICRATE*30;
168 break;
169
170 case genCdO:
171 case genBlazeCdO:
172 door->direction = 0;
173 door->topcountdown = door->topwait; // jff 5/8/98 insert delay
174 break;
175
176 default:
177 break;
178 }
179 }
180 /* jff 1/31/98 turn lighting off in tagged sectors of manual doors
181 * killough 10/98: replaced with gradual lighting code
182 */
183 else if (res == crushed) // handle door meeting obstruction on way down
184 {
185 switch(door->type)
186 {
187 case genClose:
188 case genBlazeClose:
189 case blazeClose:
190 case p_close: // Close types do not bounce, merely wait
191 break;
192
193 case blazeRaise:
194 case genBlazeRaise:
195 door->direction = 1;
196 if (!comp[comp_blazing]) {
197 S_StartSound((mobj_t *)&door->sector->soundorg,sfx_bdopn);
198 break;
199 }
200
201 default: // other types bounce off the obstruction
202 door->direction = 1;
203 S_StartSound((mobj_t *)&door->sector->soundorg,sfx_doropn);
204 break;
205 }
206 }
207 break;
208
209 case 1:
210 // Door is moving up
211 res = T_MovePlane
212 (
213 door->sector,
214 door->speed,
215 door->topheight,
216 false,
217 1,
218 door->direction
219 );
220
221 /* killough 10/98: implement gradual lighting effects */
222 if (door->lighttag && door->topheight - door->sector->floorheight)
223 EV_LightTurnOnPartway(door->line,
224 FixedDiv(door->sector->ceilingheight -
225 door->sector->floorheight,
226 door->topheight -
227 door->sector->floorheight));
228
229 // handle door reaching the top
230 if (res == pastdest)
231 {
232 switch(door->type)
233 {
234 case blazeRaise: // regular open/close doors start waiting
235 case normal:
236 case genRaise:
237 case genBlazeRaise:
238 door->direction = 0; // wait at top with delay
239 door->topcountdown = door->topwait;
240 break;
241
242 case close30ThenOpen: // close and close/open doors are done
243 case blazeOpen:
244 case p_open:
245 case genBlazeOpen:
246 case genOpen:
247 case genCdO:
248 case genBlazeCdO:
249 door->sector->ceilingdata = NULL; //jff 2/22/98
250 P_RemoveThinker (&door->thinker); // unlink and free
251 break;
252
253 default:
254 break;
255 }
256
257 /* jff 1/31/98 turn lighting on in tagged sectors of manual doors
258 * killough 10/98: replaced with gradual lighting code */
259 }
260 break;
261 }
262}
263
264///////////////////////////////////////////////////////////////
265//
266// Door linedef handlers
267//
268///////////////////////////////////////////////////////////////
269
270//
271// EV_DoLockedDoor
272//
273// Handle opening a tagged locked door
274//
275// Passed the line activating the door, the type of door,
276// and the thing that activated the line
277// Returns true if a thinker created
278//
279int EV_DoLockedDoor
280( line_t* line,
281 vldoor_e type,
282 mobj_t* thing )
283{
284 player_t* p;
285
286 // only players can open locked doors
287 p = thing->player;
288 if (!p)
289 return 0;
290
291 // check type of linedef, and if key is possessed to open it
292 switch(line->special)
293 {
294 case 99: // Blue Lock
295 case 133:
296 if (!p->cards[it_bluecard] && !p->cards[it_blueskull])
297 {
298 p->message = PD_BLUEO; // Ty 03/27/98 - externalized
299 S_StartSound(p->mo,sfx_oof); // killough 3/20/98
300 return 0;
301 }
302 break;
303
304 case 134: // Red Lock
305 case 135:
306 if (!p->cards[it_redcard] && !p->cards[it_redskull])
307 {
308 p->message = PD_REDO; // Ty 03/27/98 - externalized
309 S_StartSound(p->mo,sfx_oof); // killough 3/20/98
310 return 0;
311 }
312 break;
313
314 case 136: // Yellow Lock
315 case 137:
316 if (!p->cards[it_yellowcard] && !p->cards[it_yellowskull])
317 {
318 p->message = PD_YELLOWO; // Ty 03/27/98 - externalized
319 S_StartSound(p->mo,sfx_oof); // killough 3/20/98
320 return 0;
321 }
322 break;
323 }
324
325 // got the key, so open the door
326 return EV_DoDoor(line,type);
327}
328
329
330//
331// EV_DoDoor
332//
333// Handle opening a tagged door
334//
335// Passed the line activating the door and the type of door
336// Returns true if a thinker created
337//
338int EV_DoDoor
339( line_t* line,
340 vldoor_e type )
341{
342 int secnum,rtn;
343 sector_t* sec;
344 vldoor_t* door;
345
346 secnum = -1;
347 rtn = 0;
348
349 // open all doors with the same tag as the activating line
350 while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0)
351 {
352 sec = &sectors[secnum];
353 // if the ceiling already moving, don't start the door action
354 if (P_SectorActive(ceiling_special,sec)) //jff 2/22/98
355 continue;
356
357 // new door thinker
358 rtn = 1;
359 door = Z_Malloc (sizeof(*door), PU_LEVSPEC, 0);
360 P_AddThinker (&door->thinker);
361 sec->ceilingdata = door; //jff 2/22/98
362
363 door->thinker.function = T_VerticalDoor;
364 door->sector = sec;
365 door->type = type;
366 door->topwait = VDOORWAIT;
367 door->speed = VDOORSPEED;
368 door->line = line; // jff 1/31/98 remember line that triggered us
369 door->lighttag = 0; /* killough 10/98: no light effects with tagged doors */
370
371 // setup door parameters according to type of door
372 switch(type)
373 {
374 case blazeClose:
375 door->topheight = P_FindLowestCeilingSurrounding(sec);
376 door->topheight -= 4*FRACUNIT;
377 door->direction = -1;
378 door->speed = VDOORSPEED * 4;
379 S_StartSound((mobj_t *)&door->sector->soundorg,sfx_bdcls);
380 break;
381
382 case p_close:
383 door->topheight = P_FindLowestCeilingSurrounding(sec);
384 door->topheight -= 4*FRACUNIT;
385 door->direction = -1;
386 S_StartSound((mobj_t *)&door->sector->soundorg,sfx_dorcls);
387 break;
388
389 case close30ThenOpen:
390 door->topheight = sec->ceilingheight;
391 door->direction = -1;
392 S_StartSound((mobj_t *)&door->sector->soundorg,sfx_dorcls);
393 break;
394
395 case blazeRaise:
396 case blazeOpen:
397 door->direction = 1;
398 door->topheight = P_FindLowestCeilingSurrounding(sec);
399 door->topheight -= 4*FRACUNIT;
400 door->speed = VDOORSPEED * 4;
401 if (door->topheight != sec->ceilingheight)
402 S_StartSound((mobj_t *)&door->sector->soundorg,sfx_bdopn);
403 break;
404
405 case normal:
406 case p_open:
407 door->direction = 1;
408 door->topheight = P_FindLowestCeilingSurrounding(sec);
409 door->topheight -= 4*FRACUNIT;
410 if (door->topheight != sec->ceilingheight)
411 S_StartSound((mobj_t *)&door->sector->soundorg,sfx_doropn);
412 break;
413
414 default:
415 break;
416 }
417 }
418 return rtn;
419}
420
421
422//
423// EV_VerticalDoor
424//
425// Handle opening a door manually, no tag value
426//
427// Passed the line activating the door and the thing activating it
428// Returns true if a thinker created
429//
430// jff 2/12/98 added int return value, fixed all returns
431//
432int EV_VerticalDoor
433( line_t* line,
434 mobj_t* thing )
435{
436 player_t* player;
437 int secnum;
438 sector_t* sec;
439 vldoor_t* door;
440
441 // Check for locks
442 player = thing->player;
443
444 switch(line->special)
445 {
446 case 26: // Blue Lock
447 case 32:
448 if ( !player )
449 return 0;
450 if (!player->cards[it_bluecard] && !player->cards[it_blueskull])
451 {
452 player->message = PD_BLUEK; // Ty 03/27/98 - externalized
453 S_StartSound(player->mo,sfx_oof); // killough 3/20/98
454 return 0;
455 }
456 break;
457
458 case 27: // Yellow Lock
459 case 34:
460 if ( !player )
461 return 0;
462 if (!player->cards[it_yellowcard] && !player->cards[it_yellowskull])
463 {
464 player->message = PD_YELLOWK; // Ty 03/27/98 - externalized
465 S_StartSound(player->mo,sfx_oof); // killough 3/20/98
466 return 0;
467 }
468 break;
469
470 case 28: // Red Lock
471 case 33:
472 if ( !player )
473 return 0;
474 if (!player->cards[it_redcard] && !player->cards[it_redskull])
475 {
476 player->message = PD_REDK; // Ty 03/27/98 - externalized
477 S_StartSound(player->mo,sfx_oof); // killough 3/20/98
478 return 0;
479 }
480 break;
481
482 default:
483 break;
484 }
485
486 // if the wrong side of door is pushed, give oof sound
487 if (line->sidenum[1]==-1) // killough
488 {
489 S_StartSound(player->mo,sfx_oof); // killough 3/20/98
490 return 0;
491 }
492
493 // get the sector on the second side of activating linedef
494 sec = sides[line->sidenum[1]].sector;
495 secnum = sec-sectors;
496
497 /* if door already has a thinker, use it
498 * cph 2001/04/05 -
499 * Ok, this is a disaster area. We're assuming that sec->ceilingdata
500 * is a vldoor_t! What if this door is controlled by both DR lines
501 * and by switches? I don't know how to fix that.
502 * Secondly, original Doom didn't distinguish floor/lighting/ceiling
503 * actions, so we need to do the same in demo compatibility mode.
504 */
505 door = sec->ceilingdata;
506 if (demo_compatibility) {
507 if (!door) door = sec->floordata;
508 if (!door) door = sec->lightingdata;
509 }
510 if (door)
511 {
512 switch(line->special)
513 {
514 case 1: // only for "raise" doors, not "open"s
515 case 26:
516 case 27:
517 case 28:
518 case 117:
519 if (door->direction == -1)
520 door->direction = 1; // go back up
521 else
522 {
523 if (!thing->player)
524 return 0; // JDC: bad guys never close doors
525
526 door->direction = -1; // start going down immediately
527 }
528 return 1;
529 }
530 }
531
532 // emit proper sound
533 switch(line->special)
534 {
535 case 117: // blazing door raise
536 case 118: // blazing door open
537 S_StartSound((mobj_t *)&sec->soundorg,sfx_bdopn);
538 break;
539
540 case 1: // normal door sound
541 case 31:
542 S_StartSound((mobj_t *)&sec->soundorg,sfx_doropn);
543 break;
544
545 default: // locked door sound
546 S_StartSound((mobj_t *)&sec->soundorg,sfx_doropn);
547 break;
548 }
549
550 // new door thinker
551 door = Z_Malloc (sizeof(*door), PU_LEVSPEC, 0);
552 P_AddThinker (&door->thinker);
553 sec->ceilingdata = door; //jff 2/22/98
554 door->thinker.function = T_VerticalDoor;
555 door->sector = sec;
556 door->direction = 1;
557 door->speed = VDOORSPEED;
558 door->topwait = VDOORWAIT;
559 door->line = line; // jff 1/31/98 remember line that triggered us
560
561 /* killough 10/98: use gradual lighting changes if nonzero tag given */
562 door->lighttag = comp[comp_doorlight] ? 0 : line->tag;
563
564 // set the type of door from the activating linedef type
565 switch(line->special)
566 {
567 case 1:
568 case 26:
569 case 27:
570 case 28:
571 door->type = normal;
572 break;
573
574 case 31:
575 case 32:
576 case 33:
577 case 34:
578 door->type = p_open;
579 line->special = 0;
580 break;
581
582 case 117: // blazing door raise
583 door->type = blazeRaise;
584 door->speed = VDOORSPEED*4;
585 break;
586 case 118: // blazing door open
587 door->type = blazeOpen;
588 line->special = 0;
589 door->speed = VDOORSPEED*4;
590 break;
591
592 default:
593 door->lighttag = 0; // killough 10/98
594 break;
595 }
596
597 // find the top and bottom of the movement range
598 door->topheight = P_FindLowestCeilingSurrounding(sec);
599 door->topheight -= 4*FRACUNIT;
600 return 1;
601}
602
603
604///////////////////////////////////////////////////////////////
605//
606// Sector type door spawners
607//
608///////////////////////////////////////////////////////////////
609
610//
611// P_SpawnDoorCloseIn30()
612//
613// Spawn a door that closes after 30 seconds (called at level init)
614//
615// Passed the sector of the door, whose type specified the door action
616// Returns nothing
617//
618void P_SpawnDoorCloseIn30 (sector_t* sec)
619{
620 vldoor_t* door;
621
622 door = Z_Malloc ( sizeof(*door), PU_LEVSPEC, 0);
623
624 P_AddThinker (&door->thinker);
625
626 sec->ceilingdata = door; //jff 2/22/98
627 sec->special = 0;
628
629 door->thinker.function = T_VerticalDoor;
630 door->sector = sec;
631 door->direction = 0;
632 door->type = normal;
633 door->speed = VDOORSPEED;
634 door->topcountdown = 30 * 35;
635 door->line = NULL; // jff 1/31/98 remember line that triggered us
636 door->lighttag = 0; /* killough 10/98: no lighting changes */
637}
638
639//
640// P_SpawnDoorRaiseIn5Mins()
641//
642// Spawn a door that opens after 5 minutes (called at level init)
643//
644// Passed the sector of the door, whose type specified the door action
645// Returns nothing
646//
647void P_SpawnDoorRaiseIn5Mins
648( sector_t* sec,
649 int secnum )
650{
651 (void)secnum;
652 vldoor_t* door;
653
654 door = Z_Malloc ( sizeof(*door), PU_LEVSPEC, 0);
655
656 P_AddThinker (&door->thinker);
657
658 sec->ceilingdata = door; //jff 2/22/98
659 sec->special = 0;
660
661 door->thinker.function = T_VerticalDoor;
662 door->sector = sec;
663 door->direction = 2;
664 door->type = raiseIn5Mins;
665 door->speed = VDOORSPEED;
666 door->topheight = P_FindLowestCeilingSurrounding(sec);
667 door->topheight -= 4*FRACUNIT;
668 door->topwait = VDOORWAIT;
669 door->topcountdown = 5 * 60 * 35;
670 door->line = NULL; // jff 1/31/98 remember line that triggered us
671 door->lighttag = 0; /* killough 10/98: no lighting changes */
672}
diff --git a/apps/plugins/doom/p_enemy.c b/apps/plugins/doom/p_enemy.c
new file mode 100644
index 0000000000..b1f40bc5b8
--- /dev/null
+++ b/apps/plugins/doom/p_enemy.c
@@ -0,0 +1,2623 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION:
28 * Enemy thinking, AI.
29 * Action Pointer Functions
30 * that are associated with states/frames.
31 *
32 *-----------------------------------------------------------------------------*/
33
34#include "doomstat.h"
35#include "m_random.h"
36#include "r_main.h"
37#include "p_maputl.h"
38#include "p_map.h"
39#include "p_setup.h"
40#include "p_spec.h"
41#include "s_sound.h"
42#include "sounds.h"
43#include "p_inter.h"
44#include "g_game.h"
45#include "p_enemy.h"
46#include "p_tick.h"
47#include "m_bbox.h"
48
49#include "rockmacros.h"
50
51static mobj_t *current_actor;
52
53typedef enum {
54 DI_EAST,
55 DI_NORTHEAST,
56 DI_NORTH,
57 DI_NORTHWEST,
58 DI_WEST,
59 DI_SOUTHWEST,
60 DI_SOUTH,
61 DI_SOUTHEAST,
62 DI_NODIR,
63 NUMDIRS
64} dirtype_t;
65
66void A_Fall(mobj_t *actor);
67void A_FaceTarget(mobj_t *actor);
68static void P_NewChaseDir(mobj_t *actor);
69void P_ZBumpCheck(mobj_t *); // phares
70
71//
72// ENEMY THINKING
73// Enemies are allways spawned
74// with targetplayer = -1, threshold = 0
75// Most monsters are spawned unaware of all players,
76// but some can be made preaware
77//
78
79//
80// Called by P_NoiseAlert.
81// Recursively traverse adjacent sectors,
82// sound blocking lines cut off traversal.
83//
84// killough 5/5/98: reformatted, cleaned up
85
86static void P_RecursiveSound(sector_t *sec, int soundblocks,
87 mobj_t *soundtarget)
88{
89 int i;
90
91 // wake up all monsters in this sector
92 if (sec->validcount == validcount && sec->soundtraversed <= soundblocks+1)
93 return; // already flooded
94
95 sec->validcount = validcount;
96 sec->soundtraversed = soundblocks+1;
97 P_SetTarget(&sec->soundtarget, soundtarget);
98
99 for (i=0; i<sec->linecount; i++)
100 {
101 sector_t *other;
102 line_t *check = sec->lines[i];
103
104 if (!(check->flags & ML_TWOSIDED))
105 continue;
106
107 P_LineOpening(check);
108
109 if (openrange <= 0)
110 continue; // closed door
111
112 other=sides[check->sidenum[sides[check->sidenum[0]].sector==sec]].sector;
113
114 if (!(check->flags & ML_SOUNDBLOCK))
115 P_RecursiveSound(other, soundblocks, soundtarget);
116 else
117 if (!soundblocks)
118 P_RecursiveSound(other, 1, soundtarget);
119 }
120}
121
122//
123// P_NoiseAlert
124// If a monster yells at a player,
125// it will alert other monsters to the player.
126//
127void P_NoiseAlert(mobj_t *target, mobj_t *emitter)
128{
129 validcount++;
130 P_RecursiveSound(emitter->subsector->sector, 0, target);
131}
132
133//
134// P_CheckMeleeRange
135//
136
137static boolean P_CheckMeleeRange(mobj_t *actor)
138{
139 mobj_t *pl = actor->target;
140
141 return // killough 7/18/98: friendly monsters don't attack other friends
142 pl && !(actor->flags & pl->flags & MF_FRIEND) &&
143 (P_AproxDistance(pl->x-actor->x, pl->y-actor->y) <
144 MELEERANGE - 20*FRACUNIT + pl->info->radius) &&
145 P_CheckSight(actor, actor->target);
146}
147
148//
149// P_HitFriend()
150//
151// killough 12/98
152// This function tries to prevent shooting at friends
153
154static boolean P_HitFriend(mobj_t *actor)
155{
156 return actor->flags & MF_FRIEND && actor->target &&
157 (P_AimLineAttack(actor,
158 R_PointToAngle2(actor->x, actor->y,
159 actor->target->x, actor->target->y),
160 P_AproxDistance(actor->x-actor->target->x,
161 actor->y-actor->target->y), 0),
162 linetarget) && linetarget != actor->target &&
163 !((linetarget->flags ^ actor->flags) & MF_FRIEND);
164}
165
166//
167// P_CheckMissileRange
168//
169boolean P_CheckMissileRange(mobj_t *actor)
170{
171 fixed_t dist;
172
173 if (!P_CheckSight(actor, actor->target))
174 return false;
175
176 if (actor->flags & MF_JUSTHIT)
177 { // the target just hit the enemy, so fight back!
178 actor->flags &= ~MF_JUSTHIT;
179
180 /* killough 7/18/98: no friendly fire at corpses
181 * killough 11/98: prevent too much infighting among friends
182 * cph - yikes, talk about fitting everything on one line... */
183
184 return
185 !(actor->flags & MF_FRIEND) ||
186 (actor->target->health > 0 &&
187 (!(actor->target->flags & MF_FRIEND) ||
188 (actor->target->player ?
189 monster_infighting || P_Random(pr_defect) >128 :
190 !(actor->target->flags & MF_JUSTHIT) && P_Random(pr_defect) >128)));
191 }
192
193 /* killough 7/18/98: friendly monsters don't attack other friendly
194 * monsters or players (except when attacked, and then only once)
195 */
196 if (actor->flags & actor->target->flags & MF_FRIEND)
197 return false;
198
199 if (actor->reactiontime)
200 return false; // do not attack yet
201
202 // OPTIMIZE: get this from a global checksight
203 dist = P_AproxDistance ( actor->x-actor->target->x,
204 actor->y-actor->target->y) - 64*FRACUNIT;
205
206 if (!actor->info->meleestate)
207 dist -= 128*FRACUNIT; // no melee attack, so fire more
208
209 dist >>= FRACBITS;
210
211 if (actor->type == MT_VILE)
212 if (dist > 14*64)
213 return false; // too far away
214
215
216 if (actor->type == MT_UNDEAD)
217 {
218 if (dist < 196)
219 return false; // close for fist attack
220 dist >>= 1;
221 }
222
223 if (actor->type == MT_CYBORG ||
224 actor->type == MT_SPIDER ||
225 actor->type == MT_SKULL)
226 dist >>= 1;
227
228 if (dist > 200)
229 dist = 200;
230
231 if (actor->type == MT_CYBORG && dist > 160)
232 dist = 160;
233
234 if (P_Random(pr_missrange) < dist)
235 return false;
236
237 if (P_HitFriend(actor))
238 return false;
239
240 return true;
241}
242
243/*
244 * P_IsOnLift
245 *
246 * killough 9/9/98:
247 *
248 * Returns true if the object is on a lift. Used for AI,
249 * since it may indicate the need for crowded conditions,
250 * or that a monster should stay on the lift for a while
251 * while it goes up or down.
252 */
253
254static boolean P_IsOnLift(const mobj_t *actor)
255{
256 const sector_t *sec = actor->subsector->sector;
257 line_t line;
258 int l;
259
260 // Short-circuit: it's on a lift which is active.
261 if (sec->floordata && ((thinker_t *) sec->floordata)->function==T_PlatRaise)
262 return true;
263
264 // Check to see if it's in a sector which can be activated as a lift.
265 if ((line.tag = sec->tag))
266 for (l = -1; (l = P_FindLineFromLineTag(&line, l)) >= 0;)
267 switch (lines[l].special)
268 {
269case 10: case 14: case 15: case 20: case 21: case 22:
270case 47: case 53: case 62: case 66: case 67: case 68:
271case 87: case 88: case 95: case 120: case 121: case 122:
272case 123: case 143: case 162: case 163: case 181: case 182:
273case 144: case 148: case 149: case 211: case 227: case 228:
274case 231: case 232: case 235: case 236:
275 return true;
276 }
277
278 return false;
279}
280
281/*
282 * P_IsUnderDamage
283 *
284 * killough 9/9/98:
285 *
286 * Returns nonzero if the object is under damage based on
287 * their current position. Returns 1 if the damage is moderate,
288 * -1 if it is serious. Used for AI.
289 */
290
291static int P_IsUnderDamage(mobj_t *actor)
292{
293 const struct msecnode_s *seclist;
294 const ceiling_t *cl; // Crushing ceiling
295 int dir = 0;
296 for (seclist=actor->touching_sectorlist; seclist; seclist=seclist->m_tnext)
297 if ((cl = seclist->m_sector->ceilingdata) &&
298 cl->thinker.function == T_MoveCeiling)
299 dir |= cl->direction;
300 return dir;
301}
302
303//
304// P_Move
305// Move in the current direction,
306// returns false if the move is blocked.
307//
308
309static fixed_t xspeed[8] = {FRACUNIT,47000,0,-47000,-FRACUNIT,-47000,0,47000};
310static fixed_t yspeed[8] = {0,47000,FRACUNIT,47000,0,-47000,-FRACUNIT,-47000};
311
312// 1/11/98 killough: Limit removed on special lines crossed
313extern line_t **spechit; // New code -- killough
314extern int numspechit;
315
316static boolean P_Move(mobj_t *actor, boolean dropoff) /* killough 9/12/98 */
317{
318 fixed_t tryx, tryy, deltax, deltay, origx, origy;
319 boolean try_ok;
320 int movefactor = ORIG_FRICTION_FACTOR; // killough 10/98
321 int friction = ORIG_FRICTION;
322 int speed;
323
324 if (actor->movedir == DI_NODIR)
325 return false;
326
327#ifdef RANGECHECK
328 if ((unsigned)actor->movedir >= 8)
329 I_Error ("P_Move: Weird actor->movedir!");
330#endif
331
332 // killough 10/98: make monsters get affected by ice and sludge too:
333
334 if (monster_friction)
335 movefactor = P_GetMoveFactor(actor, &friction);
336
337 speed = actor->info->speed;
338
339 if (friction < ORIG_FRICTION && // sludge
340 !(speed = ((ORIG_FRICTION_FACTOR - (ORIG_FRICTION_FACTOR-movefactor)/2)
341 * speed) / ORIG_FRICTION_FACTOR))
342 speed = 1; // always give the monster a little bit of speed
343
344 tryx = (origx = actor->x) + (deltax = speed * xspeed[actor->movedir]);
345 tryy = (origy = actor->y) + (deltay = speed * yspeed[actor->movedir]);
346
347 try_ok = P_TryMove(actor, tryx, tryy, dropoff);
348
349 // killough 10/98:
350 // Let normal momentum carry them, instead of steptoeing them across ice.
351
352 if (try_ok && friction > ORIG_FRICTION)
353 {
354 actor->x = origx;
355 actor->y = origy;
356 movefactor *= FRACUNIT / ORIG_FRICTION_FACTOR / 4;
357 actor->momx += FixedMul(deltax, movefactor);
358 actor->momy += FixedMul(deltay, movefactor);
359 }
360
361 if (!try_ok)
362 { // open any specials
363 int good;
364
365 if (actor->flags & MF_FLOAT && floatok)
366 {
367 if (actor->z < tmfloorz) // must adjust height
368 actor->z += FLOATSPEED;
369 else
370 actor->z -= FLOATSPEED;
371
372 actor->flags |= MF_INFLOAT;
373
374 return true;
375 }
376
377 if (!numspechit)
378 return false;
379
380 actor->movedir = DI_NODIR;
381
382 /* if the special is not a door that can be opened, return false
383 *
384 * killough 8/9/98: this is what caused monsters to get stuck in
385 * doortracks, because it thought that the monster freed itself
386 * by opening a door, even if it was moving towards the doortrack,
387 * and not the door itself.
388 *
389 * killough 9/9/98: If a line blocking the monster is activated,
390 * return true 90% of the time. If a line blocking the monster is
391 * not activated, but some other line is, return false 90% of the
392 * time. A bit of randomness is needed to ensure it's free from
393 * lockups, but for most cases, it returns the correct result.
394 *
395 * Do NOT simply return false 1/4th of the time (causes monsters to
396 * back out when they shouldn't, and creates secondary stickiness).
397 */
398
399 for (good = false; numspechit--; )
400 if (P_UseSpecialLine(actor, spechit[numspechit], 0))
401 good |= spechit[numspechit] == blockline ? 1 : 2;
402
403 /* cph - compatibility maze here
404 * Boom v2.01 and orig. Doom return "good"
405 * Boom v2.02 and LxDoom return good && (P_Random(pr_trywalk)&3)
406 * MBF plays even more games
407 */
408 if (!good || comp[comp_doorstuck]) return good;
409 if (!mbf_features)
410 return (P_Random(pr_trywalk)&3); /* jff 8/13/98 */
411 else /* finally, MBF code */
412 return ((P_Random(pr_opendoor) >= 230) ^ (good & 1));
413 }
414 else
415 actor->flags &= ~MF_INFLOAT;
416
417 /* killough 11/98: fall more slowly, under gravity, if felldown==true */
418 if (!(actor->flags & MF_FLOAT) &&
419 (!felldown || !mbf_features))
420 actor->z = actor->floorz;
421
422 return true;
423}
424
425/*
426 * P_SmartMove
427 *
428 * killough 9/12/98: Same as P_Move, except smarter
429 */
430
431static boolean P_SmartMove(mobj_t *actor)
432{
433 mobj_t *target = actor->target;
434 int on_lift, dropoff = false, under_damage;
435
436 /* killough 9/12/98: Stay on a lift if target is on one */
437 on_lift = !comp[comp_staylift]
438 && target && target->health > 0
439 && target->subsector->sector->tag==actor->subsector->sector->tag &&
440 P_IsOnLift(actor);
441
442 under_damage = monster_avoid_hazards && P_IsUnderDamage(actor);
443
444 // killough 10/98: allow dogs to drop off of taller ledges sometimes.
445 // dropoff==1 means always allow it, dropoff==2 means only up to 128 high,
446 // and only if the target is immediately on the other side of the line.
447
448#ifdef DOGS
449 if (actor->type == MT_DOGS && target && dog_jumping &&
450 !((target->flags ^ actor->flags) & MF_FRIEND) &&
451 P_AproxDistance(actor->x - target->x,
452 actor->y - target->y) < FRACUNIT*144 &&
453 P_Random(pr_dropoff) < 235)
454 dropoff = 2;
455#endif
456
457 if (!P_Move(actor, dropoff))
458 return false;
459
460 // killough 9/9/98: avoid crushing ceilings or other damaging areas
461 if (
462 (on_lift && P_Random(pr_stayonlift) < 230 && // Stay on lift
463 !P_IsOnLift(actor))
464 ||
465 (monster_avoid_hazards && !under_damage && // Get away from damage
466 (under_damage = P_IsUnderDamage(actor)) &&
467 (under_damage < 0 || P_Random(pr_avoidcrush) < 200))
468 )
469 actor->movedir = DI_NODIR; // avoid the area (most of the time anyway)
470
471 return true;
472}
473
474//
475// TryWalk
476// Attempts to move actor on
477// in its current (ob->moveangle) direction.
478// If blocked by either a wall or an actor
479// returns FALSE
480// If move is either clear or blocked only by a door,
481// returns TRUE and sets...
482// If a door is in the way,
483// an OpenDoor call is made to start it opening.
484//
485
486boolean P_TryWalk(mobj_t *actor)
487{
488 if (!P_SmartMove(actor))
489 return false;
490 actor->movecount = P_Random(pr_trywalk)&15;
491 return true;
492}
493
494//
495// P_DoNewChaseDir
496//
497// killough 9/8/98:
498//
499// Most of P_NewChaseDir(), except for what
500// determines the new direction to take
501//
502
503static void P_DoNewChaseDir(mobj_t *actor, fixed_t deltax, fixed_t deltay)
504{
505 dirtype_t xdir, ydir, tdir;
506 dirtype_t olddir = actor->movedir;
507 dirtype_t turnaround = olddir;
508
509 if (turnaround != DI_NODIR) // find reverse direction
510 turnaround ^= 4;
511
512 xdir =
513 deltax > 10*FRACUNIT ? DI_EAST :
514 deltax < -10*FRACUNIT ? DI_WEST : DI_NODIR;
515
516 ydir =
517 deltay < -10*FRACUNIT ? DI_SOUTH :
518 deltay > 10*FRACUNIT ? DI_NORTH : DI_NODIR;
519
520 // try direct route
521 if (xdir != DI_NODIR && ydir != DI_NODIR && turnaround !=
522 (actor->movedir = deltay < 0 ? deltax > 0 ? DI_SOUTHEAST : DI_SOUTHWEST :
523 deltax > 0 ? DI_NORTHEAST : DI_NORTHWEST) && P_TryWalk(actor))
524 return;
525
526 // try other directions
527 if (P_Random(pr_newchase) > 200 || abs(deltay)>abs(deltax))
528 tdir = xdir, xdir = ydir, ydir = tdir;
529
530 if ((xdir == turnaround ? xdir = DI_NODIR : xdir) != DI_NODIR &&
531 (actor->movedir = xdir, P_TryWalk(actor)))
532 return; // either moved forward or attacked
533
534 if ((ydir == turnaround ? ydir = DI_NODIR : ydir) != DI_NODIR &&
535 (actor->movedir = ydir, P_TryWalk(actor)))
536 return;
537
538 // there is no direct path to the player, so pick another direction.
539 if (olddir != DI_NODIR && (actor->movedir = olddir, P_TryWalk(actor)))
540 return;
541
542 // randomly determine direction of search
543 if (P_Random(pr_newchasedir) & 1)
544 {
545 for (tdir = DI_EAST; tdir <= DI_SOUTHEAST; tdir++)
546 if (tdir != turnaround && (actor->movedir = tdir, P_TryWalk(actor)))
547 return;
548 }
549 else
550 for (tdir = DI_SOUTHEAST; tdir != (unsigned)(DI_EAST-1); tdir--)
551 if (tdir != turnaround && (actor->movedir = tdir, P_TryWalk(actor)))
552 return;
553
554 if ((actor->movedir = turnaround) != DI_NODIR && !P_TryWalk(actor))
555 actor->movedir = DI_NODIR;
556}
557
558//
559// killough 11/98:
560//
561// Monsters try to move away from tall dropoffs.
562//
563// In Doom, they were never allowed to hang over dropoffs,
564// and would remain stuck if involuntarily forced over one.
565// This logic, combined with p_map.c (P_TryMove), allows
566// monsters to free themselves without making them tend to
567// hang over dropoffs.
568
569static fixed_t dropoff_deltax, dropoff_deltay, floorz;
570
571static boolean PIT_AvoidDropoff(line_t *line)
572{
573 if (line->backsector && // Ignore one-sided linedefs
574 tmbbox[BOXRIGHT] > line->bbox[BOXLEFT] &&
575 tmbbox[BOXLEFT] < line->bbox[BOXRIGHT] &&
576 tmbbox[BOXTOP] > line->bbox[BOXBOTTOM] && // Linedef must be contacted
577 tmbbox[BOXBOTTOM] < line->bbox[BOXTOP] &&
578 P_BoxOnLineSide(tmbbox, line) == -1)
579 {
580 fixed_t front = line->frontsector->floorheight;
581 fixed_t back = line->backsector->floorheight;
582 angle_t angle;
583
584 // The monster must contact one of the two floors,
585 // and the other must be a tall dropoff (more than 24).
586
587 if (back == floorz && front < floorz - FRACUNIT*24)
588 angle = R_PointToAngle2(0,0,line->dx,line->dy); // front side dropoff
589 else
590 if (front == floorz && back < floorz - FRACUNIT*24)
591 angle = R_PointToAngle2(line->dx,line->dy,0,0); // back side dropoff
592 else
593 return true;
594
595 // Move away from dropoff at a standard speed.
596 // Multiple contacted linedefs are cumulative (e.g. hanging over corner)
597 dropoff_deltax -= finesine[angle >> ANGLETOFINESHIFT]*32;
598 dropoff_deltay += finecosine[angle >> ANGLETOFINESHIFT]*32;
599 }
600 return true;
601}
602
603//
604// Driver for above
605//
606
607static fixed_t P_AvoidDropoff(mobj_t *actor)
608{
609 int yh=((tmbbox[BOXTOP] = actor->y+actor->radius)-bmaporgy)>>MAPBLOCKSHIFT;
610 int yl=((tmbbox[BOXBOTTOM]= actor->y-actor->radius)-bmaporgy)>>MAPBLOCKSHIFT;
611 int xh=((tmbbox[BOXRIGHT] = actor->x+actor->radius)-bmaporgx)>>MAPBLOCKSHIFT;
612 int xl=((tmbbox[BOXLEFT] = actor->x-actor->radius)-bmaporgx)>>MAPBLOCKSHIFT;
613 int bx, by;
614
615 floorz = actor->z; // remember floor height
616
617 dropoff_deltax = dropoff_deltay = 0;
618
619 // check lines
620
621 validcount++;
622 for (bx=xl ; bx<=xh ; bx++)
623 for (by=yl ; by<=yh ; by++)
624 P_BlockLinesIterator(bx, by, PIT_AvoidDropoff); // all contacted lines
625
626 return dropoff_deltax | dropoff_deltay; // Non-zero if movement prescribed
627}
628
629//
630// P_NewChaseDir
631//
632// killough 9/8/98: Split into two functions
633//
634
635static void P_NewChaseDir(mobj_t *actor)
636{
637 mobj_t *target = actor->target;
638 fixed_t deltax = target->x - actor->x;
639 fixed_t deltay = target->y - actor->y;
640
641 // killough 8/8/98: sometimes move away from target, keeping distance
642 //
643 // 1) Stay a certain distance away from a friend, to avoid being in their way
644 // 2) Take advantage over an enemy without missiles, by keeping distance
645
646 actor->strafecount = 0;
647
648 if (mbf_features) {
649 if (actor->floorz - actor->dropoffz > FRACUNIT*24 &&
650 actor->z <= actor->floorz &&
651 !(actor->flags & (MF_DROPOFF|MF_FLOAT)) &&
652 !comp[comp_dropoff] &&
653 P_AvoidDropoff(actor)) /* Move away from dropoff */
654 {
655 P_DoNewChaseDir(actor, dropoff_deltax, dropoff_deltay);
656
657 // If moving away from dropoff, set movecount to 1 so that
658 // small steps are taken to get monster away from dropoff.
659
660 actor->movecount = 1;
661 return;
662 }
663 else
664 {
665 fixed_t dist = P_AproxDistance(deltax, deltay);
666
667 // Move away from friends when too close, except
668 // in certain situations (e.g. a crowded lift)
669
670 if (actor->flags & target->flags & MF_FRIEND &&
671 distfriend << FRACBITS > dist &&
672 !P_IsOnLift(target) && !P_IsUnderDamage(actor))
673 {
674 deltax = -deltax, deltay = -deltay;
675 } else
676 if (target->health > 0 && (actor->flags ^ target->flags) & MF_FRIEND)
677 { // Live enemy target
678 if (monster_backing &&
679 actor->info->missilestate && actor->type != MT_SKULL &&
680 ((!target->info->missilestate && dist < MELEERANGE*2) ||
681 (target->player && dist < MELEERANGE*3 &&
682 (target->player->readyweapon == wp_fist ||
683 target->player->readyweapon == wp_chainsaw))))
684 { // Back away from melee attacker
685 actor->strafecount = P_Random(pr_enemystrafe) & 15;
686 deltax = -deltax, deltay = -deltay;
687 }
688 }
689 }
690 }
691
692 P_DoNewChaseDir(actor, deltax, deltay);
693
694 // If strafing, set movecount to strafecount so that old Doom
695 // logic still works the same, except in the strafing part
696
697 if (actor->strafecount)
698 actor->movecount = actor->strafecount;
699}
700
701//
702// P_IsVisible
703//
704// killough 9/9/98: whether a target is visible to a monster
705//
706
707static boolean P_IsVisible(mobj_t *actor, mobj_t *mo, boolean allaround)
708{
709 if (!allaround)
710 {
711 angle_t an = R_PointToAngle2(actor->x, actor->y,
712 mo->x, mo->y) - actor->angle;
713 if (an > ANG90 && an < ANG270 &&
714 P_AproxDistance(mo->x-actor->x, mo->y-actor->y) > MELEERANGE)
715 return false;
716 }
717 return P_CheckSight(actor, mo);
718}
719
720//
721// PIT_FindTarget
722//
723// killough 9/5/98
724//
725// Finds monster targets for other monsters
726//
727
728static int current_allaround;
729
730static boolean PIT_FindTarget(mobj_t *mo)
731{
732 mobj_t *actor = current_actor;
733
734 if (!((mo->flags ^ actor->flags) & MF_FRIEND && // Invalid target
735 mo->health > 0 && (mo->flags & MF_COUNTKILL || mo->type == MT_SKULL)))
736 return true;
737
738 // If the monster is already engaged in a one-on-one attack
739 // with a healthy friend, don't attack around 60% the time
740 {
741 const mobj_t *targ = mo->target;
742 if (targ && targ->target == mo &&
743 P_Random(pr_skiptarget) > 100 &&
744 (targ->flags ^ mo->flags) & MF_FRIEND &&
745 targ->health*2 >= targ->info->spawnhealth)
746 return true;
747 }
748
749 if (!P_IsVisible(actor, mo, current_allaround))
750 return true;
751
752 P_SetTarget(&actor->lastenemy, actor->target); // Remember previous target
753 P_SetTarget(&actor->target, mo); // Found target
754
755 // Move the selected monster to the end of its associated
756 // list, so that it gets searched last next time.
757
758 {
759 thinker_t *cap = &thinkerclasscap[mo->flags & MF_FRIEND ?
760 th_friends : th_enemies];
761 (mo->thinker.cprev->cnext = mo->thinker.cnext)->cprev = mo->thinker.cprev;
762 (mo->thinker.cprev = cap->cprev)->cnext = &mo->thinker;
763 (mo->thinker.cnext = cap)->cprev = &mo->thinker;
764 }
765
766 return false;
767}
768
769//
770// P_LookForPlayers
771// If allaround is false, only look 180 degrees in front.
772// Returns true if a player is targeted.
773//
774
775static boolean P_LookForPlayers(mobj_t *actor, boolean allaround)
776{
777 player_t *player;
778 int stop, stopc, c;
779
780 if (actor->flags & MF_FRIEND)
781 { // killough 9/9/98: friendly monsters go about players differently
782 int anyone;
783
784#if 0
785 if (!allaround) // If you want friendly monsters not to awaken unprovoked
786 return false;
787#endif
788
789 // Go back to a player, no matter whether it's visible or not
790 for (anyone=0; anyone<=1; anyone++)
791 for (c=0; c<MAXPLAYERS; c++)
792 if (playeringame[c] && players[c].playerstate==PST_LIVE &&
793 (anyone || P_IsVisible(actor, players[c].mo, allaround)))
794 {
795 P_SetTarget(&actor->target, players[c].mo);
796
797 // killough 12/98:
798 // get out of refiring loop, to avoid hitting player accidentally
799
800 if (actor->info->missilestate)
801 {
802 P_SetMobjState(actor, actor->info->seestate);
803 actor->flags &= ~MF_JUSTHIT;
804 }
805
806 return true;
807 }
808
809 return false;
810 }
811
812 // Change mask of 3 to (MAXPLAYERS-1) -- killough 2/15/98:
813 stop = (actor->lastlook-1)&(MAXPLAYERS-1);
814
815 c = 0;
816
817 stopc = !mbf_features &&
818 !demo_compatibility && monsters_remember ?
819 MAXPLAYERS : 2; // killough 9/9/98
820
821 for (;; actor->lastlook = (actor->lastlook+1)&(MAXPLAYERS-1))
822 {
823 if (!playeringame[actor->lastlook])
824 continue;
825
826 // killough 2/15/98, 9/9/98:
827 if (c++ == stopc || actor->lastlook == stop) // done looking
828 return false;
829
830 player = &players[actor->lastlook];
831
832 if (player->health <= 0)
833 continue; // dead
834
835 if (!P_IsVisible(actor, player->mo, allaround))
836 continue;
837
838 P_SetTarget(&actor->target, player->mo);
839
840 /* killough 9/9/98: give monsters a threshold towards getting players
841 * (we don't want it to be too easy for a player with dogs :)
842 */
843 if (!comp[comp_pursuit])
844 actor->threshold = 60;
845
846 return true;
847 }
848}
849
850//
851// Friendly monsters, by Lee Killough 7/18/98
852//
853// Friendly monsters go after other monsters first, but
854// also return to owner if they cannot find any targets.
855// A marine's best friend :) killough 7/18/98, 9/98
856//
857
858static boolean P_LookForMonsters(mobj_t *actor, boolean allaround)
859{
860 thinker_t *cap, *th;
861
862 if (demo_compatibility)
863 return false;
864
865 if (actor->lastenemy && actor->lastenemy->health > 0 && monsters_remember &&
866 !(actor->lastenemy->flags & actor->flags & MF_FRIEND)) // not friends
867 {
868 P_SetTarget(&actor->target, actor->lastenemy);
869 P_SetTarget(&actor->lastenemy, NULL);
870 return true;
871 }
872
873 /* Old demos do not support monster-seeking bots */
874 if (!mbf_features)
875 return false;
876
877 // Search the threaded list corresponding to this object's potential targets
878 cap = &thinkerclasscap[actor->flags & MF_FRIEND ? th_enemies : th_friends];
879
880 // Search for new enemy
881
882 if (cap->cnext != cap) // Empty list? bail out early
883 {
884 int x = (actor->x - bmaporgx)>>MAPBLOCKSHIFT;
885 int y = (actor->y - bmaporgy)>>MAPBLOCKSHIFT;
886 int d;
887
888 current_actor = actor;
889 current_allaround = allaround;
890
891 // Search first in the immediate vicinity.
892
893 if (!P_BlockThingsIterator(x, y, PIT_FindTarget))
894 return true;
895
896 for (d=1; d<5; d++)
897 {
898 int i = 1 - d;
899 do
900 if (!P_BlockThingsIterator(x+i, y-d, PIT_FindTarget) ||
901 !P_BlockThingsIterator(x+i, y+d, PIT_FindTarget))
902 return true;
903 while (++i < d);
904 do
905 if (!P_BlockThingsIterator(x-d, y+i, PIT_FindTarget) ||
906 !P_BlockThingsIterator(x+d, y+i, PIT_FindTarget))
907 return true;
908 while (--i + d >= 0);
909 }
910
911 { // Random number of monsters, to prevent patterns from forming
912 int n = (P_Random(pr_friends) & 31) + 15;
913
914 for (th = cap->cnext; th != cap; th = th->cnext)
915 if (--n < 0)
916 {
917 // Only a subset of the monsters were searched. Move all of
918 // the ones which were searched so far, to the end of the list.
919
920 (cap->cnext->cprev = cap->cprev)->cnext = cap->cnext;
921 (cap->cprev = th->cprev)->cnext = cap;
922 (th->cprev = cap)->cnext = th;
923 break;
924 }
925 else
926 if (!PIT_FindTarget((mobj_t *) th)) // If target sighted
927 return true;
928 }
929 }
930
931 return false; // No monster found
932}
933
934//
935// P_LookForTargets
936//
937// killough 9/5/98: look for targets to go after, depending on kind of monster
938//
939
940static boolean P_LookForTargets(mobj_t *actor, int allaround)
941{
942 return actor->flags & MF_FRIEND ?
943 P_LookForMonsters(actor, allaround) || P_LookForPlayers (actor, allaround):
944 P_LookForPlayers (actor, allaround) || P_LookForMonsters(actor, allaround);
945}
946
947//
948// P_HelpFriend
949//
950// killough 9/8/98: Help friends in danger of dying
951//
952
953static boolean P_HelpFriend(mobj_t *actor)
954{
955 thinker_t *cap, *th;
956
957 // If less than 33% health, self-preservation rules
958 if (actor->health*3 < actor->info->spawnhealth)
959 return false;
960
961 current_actor = actor;
962 current_allaround = true;
963
964 // Possibly help a friend under 50% health
965 cap = &thinkerclasscap[actor->flags & MF_FRIEND ? th_friends : th_enemies];
966
967 for (th = cap->cnext; th != cap; th = th->cnext)
968 if (((mobj_t *) th)->health*2 >= ((mobj_t *) th)->info->spawnhealth)
969 {
970 if (P_Random(pr_helpfriend) < 180)
971 break;
972 }
973 else
974 if (((mobj_t *) th)->flags & MF_JUSTHIT &&
975 ((mobj_t *) th)->target &&
976 ((mobj_t *) th)->target != actor->target &&
977 !PIT_FindTarget(((mobj_t *) th)->target))
978 {
979 // Ignore any attacking monsters, while searching for friend
980 actor->threshold = BASETHRESHOLD;
981 return true;
982 }
983
984 return false;
985}
986
987//
988// A_KeenDie
989// DOOM II special, map 32.
990// Uses special tag 666.
991//
992void A_KeenDie(mobj_t* mo)
993{
994 thinker_t *th;
995 line_t junk;
996
997 A_Fall(mo);
998
999 // scan the remaining thinkers to see if all Keens are dead
1000
1001 for (th = thinkercap.next ; th != &thinkercap ; th=th->next)
1002 if (th->function == P_MobjThinker)
1003 {
1004 mobj_t *mo2 = (mobj_t *) th;
1005 if (mo2 != mo && mo2->type == mo->type && mo2->health > 0)
1006 return; // other Keen not dead
1007 }
1008
1009 junk.tag = 666;
1010 EV_DoDoor(&junk,p_open);
1011}
1012
1013
1014//
1015// ACTION ROUTINES
1016//
1017
1018//
1019// A_Look
1020// Stay in state until a player is sighted.
1021//
1022
1023void A_Look(mobj_t *actor)
1024{
1025 mobj_t *targ = actor->subsector->sector->soundtarget;
1026 actor->threshold = 0; // any shot will wake up
1027
1028 /* killough 7/18/98:
1029 * Friendly monsters go after other monsters first, but
1030 * also return to player, without attacking them, if they
1031 * cannot find any targets. A marine's best friend :)
1032 */
1033 actor->pursuecount = 0;
1034
1035 if (!(actor->flags & MF_FRIEND && P_LookForTargets(actor, false)) &&
1036 !((targ = actor->subsector->sector->soundtarget) &&
1037 targ->flags & MF_SHOOTABLE &&
1038 (P_SetTarget(&actor->target, targ),
1039 !(actor->flags & MF_AMBUSH) || P_CheckSight(actor, targ))) &&
1040 (actor->flags & MF_FRIEND || !P_LookForTargets(actor, false)))
1041 return;
1042
1043 // go into chase state
1044
1045 if (actor->info->seesound)
1046 {
1047 int sound;
1048 switch (actor->info->seesound)
1049 {
1050 case sfx_posit1:
1051 case sfx_posit2:
1052 case sfx_posit3:
1053 sound = sfx_posit1+P_Random(pr_see)%3;
1054 break;
1055
1056 case sfx_bgsit1:
1057 case sfx_bgsit2:
1058 sound = sfx_bgsit1+P_Random(pr_see)%2;
1059 break;
1060
1061 default:
1062 sound = actor->info->seesound;
1063 break;
1064 }
1065 if (actor->type==MT_SPIDER || actor->type == MT_CYBORG)
1066 S_StartSound(NULL, sound); // full volume
1067 else
1068 S_StartSound(actor, sound);
1069 }
1070 P_SetMobjState(actor, actor->info->seestate);
1071}
1072
1073//
1074// A_KeepChasing
1075//
1076// killough 10/98:
1077// Allows monsters to continue movement while attacking
1078//
1079
1080void A_KeepChasing(mobj_t *actor)
1081{
1082 if (actor->movecount)
1083 {
1084 actor->movecount--;
1085 if (actor->strafecount)
1086 actor->strafecount--;
1087 P_SmartMove(actor);
1088 }
1089}
1090
1091//
1092// A_Chase
1093// Actor has a melee attack,
1094// so it tries to close as fast as possible
1095//
1096
1097void A_Chase(mobj_t *actor)
1098{
1099 if (actor->reactiontime)
1100 actor->reactiontime--;
1101
1102 if (actor->threshold) { /* modify target threshold */
1103 if (!actor->target || actor->target->health <= 0)
1104 actor->threshold = 0;
1105 else
1106 actor->threshold--;
1107 }
1108
1109 /* turn towards movement direction if not there yet
1110 * killough 9/7/98: keep facing towards target if strafing or backing out
1111 */
1112
1113 if (actor->strafecount)
1114 A_FaceTarget(actor);
1115 else if (actor->movedir < 8)
1116 {
1117 int delta = (actor->angle &= (7<<29)) - (actor->movedir << 29);
1118 if (delta > 0)
1119 actor->angle -= ANG90/2;
1120 else
1121 if (delta < 0)
1122 actor->angle += ANG90/2;
1123 }
1124
1125 if (!actor->target || !(actor->target->flags&MF_SHOOTABLE))
1126 {
1127 if (!P_LookForTargets(actor,true)) // look for a new target
1128 P_SetMobjState(actor, actor->info->spawnstate); // no new target
1129 return;
1130 }
1131
1132 // do not attack twice in a row
1133 if (actor->flags & MF_JUSTATTACKED)
1134 {
1135 actor->flags &= ~MF_JUSTATTACKED;
1136 if (gameskill != sk_nightmare && !fastparm)
1137 P_NewChaseDir(actor);
1138 return;
1139 }
1140
1141 // check for melee attack
1142 if (actor->info->meleestate && P_CheckMeleeRange(actor))
1143 {
1144 if (actor->info->attacksound)
1145 S_StartSound(actor, actor->info->attacksound);
1146 P_SetMobjState(actor, actor->info->meleestate);
1147 /* killough 8/98: remember an attack
1148 * cph - DEMOSYNC? */
1149 if (!actor->info->missilestate)
1150 actor->flags |= MF_JUSTHIT;
1151 return;
1152 }
1153
1154 // check for missile attack
1155 if (actor->info->missilestate)
1156 if (!(gameskill < sk_nightmare && !fastparm && actor->movecount))
1157 if (P_CheckMissileRange(actor))
1158 {
1159 P_SetMobjState(actor, actor->info->missilestate);
1160 actor->flags |= MF_JUSTATTACKED;
1161 return;
1162 }
1163
1164 if (!actor->threshold) {
1165 if (!mbf_features)
1166 { /* killough 9/9/98: for backward demo compatibility */
1167 if (netgame && !P_CheckSight(actor, actor->target) &&
1168 P_LookForPlayers(actor, true))
1169 return;
1170 }
1171 /* killough 7/18/98, 9/9/98: new monster AI */
1172 else if (help_friends && P_HelpFriend(actor))
1173 return; /* killough 9/8/98: Help friends in need */
1174 /* Look for new targets if current one is bad or is out of view */
1175 else if (actor->pursuecount)
1176 actor->pursuecount--;
1177 else {
1178 /* Our pursuit time has expired. We're going to think about
1179 * changing targets */
1180 actor->pursuecount = BASETHRESHOLD;
1181
1182 /* Unless (we have a live target
1183 * and it's not friendly
1184 * and we can see it)
1185 * try to find a new one; return if sucessful */
1186
1187 if (!(actor->target && actor->target->health > 0 &&
1188 ((comp[comp_pursuit] && !netgame) ||
1189 (((actor->target->flags ^ actor->flags) & MF_FRIEND ||
1190 (!(actor->flags & MF_FRIEND) && monster_infighting)) &&
1191 P_CheckSight(actor, actor->target))))
1192 && P_LookForTargets(actor, true))
1193 return;
1194
1195 /* (Current target was good, or no new target was found.)
1196 *
1197 * If monster is a missile-less friend, give up pursuit and
1198 * return to player, if no attacks have occurred recently.
1199 */
1200
1201 if (!actor->info->missilestate && actor->flags & MF_FRIEND) {
1202 if (actor->flags & MF_JUSTHIT) /* if recent action, */
1203 actor->flags &= ~MF_JUSTHIT; /* keep fighting */
1204 else if (P_LookForPlayers(actor, true)) /* else return to player */
1205 return;
1206 }
1207 }
1208 }
1209
1210 if (actor->strafecount)
1211 actor->strafecount--;
1212
1213 // chase towards player
1214 if (--actor->movecount<0 || !P_SmartMove(actor))
1215 P_NewChaseDir(actor);
1216
1217 // make active sound
1218 if (actor->info->activesound && P_Random(pr_see)<3)
1219 S_StartSound(actor, actor->info->activesound);
1220}
1221
1222//
1223// A_FaceTarget
1224//
1225void A_FaceTarget(mobj_t *actor)
1226{
1227 if (!actor->target)
1228 return;
1229 actor->flags &= ~MF_AMBUSH;
1230 actor->angle = R_PointToAngle2(actor->x, actor->y,
1231 actor->target->x, actor->target->y);
1232 if (actor->target->flags & MF_SHADOW)
1233 { // killough 5/5/98: remove dependence on order of evaluation:
1234 int t = P_Random(pr_facetarget);
1235 actor->angle += (t-P_Random(pr_facetarget))<<21;
1236 }
1237}
1238
1239//
1240// A_PosAttack
1241//
1242
1243void A_PosAttack(mobj_t *actor)
1244{
1245 int angle, damage, slope, t;
1246
1247 if (!actor->target)
1248 return;
1249 A_FaceTarget(actor);
1250 angle = actor->angle;
1251 slope = P_AimLineAttack(actor, angle, MISSILERANGE, 0); /* killough 8/2/98 */
1252 S_StartSound(actor, sfx_pistol);
1253
1254 // killough 5/5/98: remove dependence on order of evaluation:
1255 t = P_Random(pr_posattack);
1256 angle += (t - P_Random(pr_posattack))<<20;
1257 damage = (P_Random(pr_posattack)%5 + 1)*3;
1258 P_LineAttack(actor, angle, MISSILERANGE, slope, damage);
1259}
1260
1261void A_SPosAttack(mobj_t* actor)
1262{
1263 int i, bangle, slope;
1264
1265 if (!actor->target)
1266 return;
1267 S_StartSound(actor, sfx_shotgn);
1268 A_FaceTarget(actor);
1269 bangle = actor->angle;
1270 slope = P_AimLineAttack(actor, bangle, MISSILERANGE, 0); /* killough 8/2/98 */
1271 for (i=0; i<3; i++)
1272 { // killough 5/5/98: remove dependence on order of evaluation:
1273 int t = P_Random(pr_sposattack);
1274 int angle = bangle + ((t - P_Random(pr_sposattack))<<20);
1275 int damage = ((P_Random(pr_sposattack)%5)+1)*3;
1276 P_LineAttack(actor, angle, MISSILERANGE, slope, damage);
1277 }
1278}
1279
1280void A_CPosAttack(mobj_t *actor)
1281{
1282 int angle, bangle, damage, slope, t;
1283
1284 if (!actor->target)
1285 return;
1286 S_StartSound(actor, sfx_shotgn);
1287 A_FaceTarget(actor);
1288 bangle = actor->angle;
1289 slope = P_AimLineAttack(actor, bangle, MISSILERANGE, 0); /* killough 8/2/98 */
1290
1291 // killough 5/5/98: remove dependence on order of evaluation:
1292 t = P_Random(pr_cposattack);
1293 angle = bangle + ((t - P_Random(pr_cposattack))<<20);
1294 damage = ((P_Random(pr_cposattack)%5)+1)*3;
1295 P_LineAttack(actor, angle, MISSILERANGE, slope, damage);
1296}
1297
1298void A_CPosRefire(mobj_t *actor)
1299{
1300 // keep firing unless target got out of sight
1301 A_FaceTarget(actor);
1302
1303 /* killough 12/98: Stop firing if a friend has gotten in the way */
1304 if (P_HitFriend(actor))
1305 goto stop;
1306
1307 /* killough 11/98: prevent refiring on friends continuously */
1308 if (P_Random(pr_cposrefire) < 40) {
1309 if (actor->target && actor->flags & actor->target->flags & MF_FRIEND)
1310 goto stop;
1311 else
1312 return;
1313 }
1314
1315 if (!actor->target || actor->target->health <= 0
1316 || !P_CheckSight(actor, actor->target))
1317stop: P_SetMobjState(actor, actor->info->seestate);
1318}
1319
1320void A_SpidRefire(mobj_t* actor)
1321{
1322 // keep firing unless target got out of sight
1323 A_FaceTarget(actor);
1324
1325 /* killough 12/98: Stop firing if a friend has gotten in the way */
1326 if (P_HitFriend(actor))
1327 goto stop;
1328
1329 if (P_Random(pr_spidrefire) < 10)
1330 return;
1331
1332 // killough 11/98: prevent refiring on friends continuously
1333 if (!actor->target || actor->target->health <= 0
1334 || actor->flags & actor->target->flags & MF_FRIEND
1335 || !P_CheckSight(actor, actor->target))
1336stop: P_SetMobjState(actor, actor->info->seestate);
1337}
1338
1339void A_BspiAttack(mobj_t *actor)
1340{
1341 if (!actor->target)
1342 return;
1343 A_FaceTarget(actor);
1344 P_SpawnMissile(actor, actor->target, MT_ARACHPLAZ); // launch a missile
1345}
1346
1347//
1348// A_TroopAttack
1349//
1350
1351void A_TroopAttack(mobj_t *actor)
1352{
1353 if (!actor->target)
1354 return;
1355 A_FaceTarget(actor);
1356 if (P_CheckMeleeRange(actor))
1357 {
1358 int damage;
1359 S_StartSound(actor, sfx_claw);
1360 damage = (P_Random(pr_troopattack)%8+1)*3;
1361 P_DamageMobj(actor->target, actor, actor, damage);
1362 return;
1363 }
1364 P_SpawnMissile(actor, actor->target, MT_TROOPSHOT); // launch a missile
1365}
1366
1367void A_SargAttack(mobj_t *actor)
1368{
1369 if (!actor->target)
1370 return;
1371 A_FaceTarget(actor);
1372 if (P_CheckMeleeRange(actor))
1373 {
1374 int damage = ((P_Random(pr_sargattack)%10)+1)*4;
1375 P_DamageMobj(actor->target, actor, actor, damage);
1376 }
1377}
1378
1379void A_HeadAttack(mobj_t *actor)
1380{
1381 if (!actor->target)
1382 return;
1383 A_FaceTarget (actor);
1384 if (P_CheckMeleeRange(actor))
1385 {
1386 int damage = (P_Random(pr_headattack)%6+1)*10;
1387 P_DamageMobj(actor->target, actor, actor, damage);
1388 return;
1389 }
1390 P_SpawnMissile(actor, actor->target, MT_HEADSHOT); // launch a missile
1391}
1392
1393void A_CyberAttack(mobj_t *actor)
1394{
1395 if (!actor->target)
1396 return;
1397 A_FaceTarget(actor);
1398 P_SpawnMissile(actor, actor->target, MT_ROCKET);
1399}
1400
1401void A_BruisAttack(mobj_t *actor)
1402{
1403 if (!actor->target)
1404 return;
1405 if (P_CheckMeleeRange(actor))
1406 {
1407 int damage;
1408 S_StartSound(actor, sfx_claw);
1409 damage = (P_Random(pr_bruisattack)%8+1)*10;
1410 P_DamageMobj(actor->target, actor, actor, damage);
1411 return;
1412 }
1413 P_SpawnMissile(actor, actor->target, MT_BRUISERSHOT); // launch a missile
1414}
1415
1416//
1417// A_SkelMissile
1418//
1419
1420void A_SkelMissile(mobj_t *actor)
1421{
1422 mobj_t *mo;
1423
1424 if (!actor->target)
1425 return;
1426
1427 A_FaceTarget (actor);
1428 actor->z += 16*FRACUNIT; // so missile spawns higher
1429 mo = P_SpawnMissile (actor, actor->target, MT_TRACER);
1430 actor->z -= 16*FRACUNIT; // back to normal
1431
1432 mo->x += mo->momx;
1433 mo->y += mo->momy;
1434 P_SetTarget(&mo->tracer, actor->target);
1435}
1436
1437int TRACEANGLE = 0xc000000;
1438
1439void A_Tracer(mobj_t *actor)
1440{
1441 angle_t exact;
1442 fixed_t dist;
1443 fixed_t slope;
1444 mobj_t *dest;
1445 mobj_t *th;
1446
1447 /* killough 1/18/98: this is why some missiles do not have smoke
1448 * and some do. Also, internal demos start at random gametics, thus
1449 * the bug in which revenants cause internal demos to go out of sync.
1450 *
1451 * killough 3/6/98: fix revenant internal demo bug by subtracting
1452 * levelstarttic from gametic.
1453 *
1454 * killough 9/29/98: use new "basetic" so that demos stay in sync
1455 * during pauses and menu activations, while retaining old demo sync.
1456 *
1457 * leveltime would have been better to use to start with in Doom, but
1458 * since old demos were recorded using gametic, we must stick with it,
1459 * and improvise around it (using leveltime causes desync across levels).
1460 */
1461
1462 if ((gametic-basetic) & 3)
1463 return;
1464
1465 // spawn a puff of smoke behind the rocket
1466 P_SpawnPuff(actor->x, actor->y, actor->z);
1467
1468 th = P_SpawnMobj (actor->x-actor->momx,
1469 actor->y-actor->momy,
1470 actor->z, MT_SMOKE);
1471
1472 th->momz = FRACUNIT;
1473 th->tics -= P_Random(pr_tracer) & 3;
1474 if (th->tics < 1)
1475 th->tics = 1;
1476
1477 // adjust direction
1478 dest = actor->tracer;
1479
1480 if (!dest || dest->health <= 0)
1481 return;
1482
1483 // change angle
1484 exact = R_PointToAngle2(actor->x, actor->y, dest->x, dest->y);
1485
1486 if (exact != actor->angle) {
1487 if (exact - actor->angle > 0x80000000)
1488 {
1489 actor->angle -= TRACEANGLE;
1490 if (exact - actor->angle < 0x80000000)
1491 actor->angle = exact;
1492 }
1493 else
1494 {
1495 actor->angle += TRACEANGLE;
1496 if (exact - actor->angle > 0x80000000)
1497 actor->angle = exact;
1498 }
1499 }
1500
1501 exact = actor->angle>>ANGLETOFINESHIFT;
1502 actor->momx = FixedMul(actor->info->speed, finecosine[exact]);
1503 actor->momy = FixedMul(actor->info->speed, finesine[exact]);
1504
1505 // change slope
1506 dist = P_AproxDistance(dest->x - actor->x, dest->y - actor->y);
1507
1508 dist = dist / actor->info->speed;
1509
1510 if (dist < 1)
1511 dist = 1;
1512
1513 slope = (dest->z+40*FRACUNIT - actor->z) / dist;
1514
1515 if (slope < actor->momz)
1516 actor->momz -= FRACUNIT/8;
1517 else
1518 actor->momz += FRACUNIT/8;
1519}
1520
1521void A_SkelWhoosh(mobj_t *actor)
1522{
1523 if (!actor->target)
1524 return;
1525 A_FaceTarget(actor);
1526 S_StartSound(actor,sfx_skeswg);
1527}
1528
1529void A_SkelFist(mobj_t *actor)
1530{
1531 if (!actor->target)
1532 return;
1533 A_FaceTarget(actor);
1534 if (P_CheckMeleeRange(actor))
1535 {
1536 int damage = ((P_Random(pr_skelfist)%10)+1)*6;
1537 S_StartSound(actor, sfx_skepch);
1538 P_DamageMobj(actor->target, actor, actor, damage);
1539 }
1540}
1541
1542//
1543// PIT_VileCheck
1544// Detect a corpse that could be raised.
1545//
1546
1547mobj_t* corpsehit;
1548mobj_t* vileobj;
1549fixed_t viletryx;
1550fixed_t viletryy;
1551
1552boolean PIT_VileCheck(mobj_t *thing)
1553{
1554 int maxdist;
1555 boolean check;
1556
1557 if (!(thing->flags & MF_CORPSE) )
1558 return true; // not a monster
1559
1560 if (thing->tics != -1)
1561 return true; // not lying still yet
1562
1563 if (thing->info->raisestate == S_NULL)
1564 return true; // monster doesn't have a raise state
1565
1566 maxdist = thing->info->radius + mobjinfo[MT_VILE].radius;
1567
1568 if (D_abs(thing->x-viletryx) > maxdist || D_abs(thing->y-viletryy) > maxdist)
1569 return true; // not actually touching
1570
1571 // Check to see if the radius and height are zero. If they are // phares
1572 // then this is a crushed monster that has been turned into a // |
1573 // gib. One of the options may be to ignore this guy. // V
1574
1575 // Option 1: the original, buggy method, -> ghost (compatibility)
1576 // Option 2: ressurect the monster, but not as a ghost
1577 // Option 3: ignore the gib
1578
1579 // if (Option3) // ^
1580 // if ((thing->height == 0) && (thing->radius == 0)) // |
1581 // return true; // phares
1582
1583 corpsehit = thing;
1584 corpsehit->momx = corpsehit->momy = 0;
1585 if (comp[comp_vile]) // phares
1586 { // |
1587 corpsehit->height <<= 2; // V
1588 check = P_CheckPosition(corpsehit,corpsehit->x,corpsehit->y);
1589 corpsehit->height >>= 2;
1590 }
1591 else
1592 {
1593 int height,radius;
1594
1595 height = corpsehit->height; // save temporarily
1596 radius = corpsehit->radius; // save temporarily
1597 corpsehit->height = corpsehit->info->height;
1598 corpsehit->radius = corpsehit->info->radius;
1599 corpsehit->flags |= MF_SOLID;
1600 check = P_CheckPosition(corpsehit,corpsehit->x,corpsehit->y);
1601 corpsehit->height = height; // restore
1602 corpsehit->radius = radius; // restore // ^
1603 corpsehit->flags &= ~MF_SOLID;
1604 } // |
1605 // phares
1606 if (!check)
1607 return true; // doesn't fit here
1608 return false; // got one, so stop checking
1609}
1610
1611//
1612// A_VileChase
1613// Check for ressurecting a body
1614//
1615
1616void A_VileChase(mobj_t* actor)
1617{
1618 int xl, xh;
1619 int yl, yh;
1620 int bx, by;
1621
1622 if (actor->movedir != DI_NODIR)
1623 {
1624 // check for corpses to raise
1625 viletryx =
1626 actor->x + actor->info->speed*xspeed[actor->movedir];
1627 viletryy =
1628 actor->y + actor->info->speed*yspeed[actor->movedir];
1629
1630 xl = (viletryx - bmaporgx - MAXRADIUS*2)>>MAPBLOCKSHIFT;
1631 xh = (viletryx - bmaporgx + MAXRADIUS*2)>>MAPBLOCKSHIFT;
1632 yl = (viletryy - bmaporgy - MAXRADIUS*2)>>MAPBLOCKSHIFT;
1633 yh = (viletryy - bmaporgy + MAXRADIUS*2)>>MAPBLOCKSHIFT;
1634
1635 vileobj = actor;
1636 for (bx=xl ; bx<=xh ; bx++)
1637 {
1638 for (by=yl ; by<=yh ; by++)
1639 {
1640 // Call PIT_VileCheck to check
1641 // whether object is a corpse
1642 // that canbe raised.
1643 if (!P_BlockThingsIterator(bx,by,PIT_VileCheck))
1644 {
1645 mobjinfo_t *info;
1646
1647 // got one!
1648 mobj_t* temp = actor->target;
1649 actor->target = corpsehit;
1650 A_FaceTarget(actor);
1651 actor->target = temp;
1652
1653 P_SetMobjState(actor, S_VILE_HEAL1);
1654 S_StartSound(corpsehit, sfx_slop);
1655 info = corpsehit->info;
1656
1657 P_SetMobjState(corpsehit,info->raisestate);
1658
1659 if (comp[comp_vile]) // phares
1660 corpsehit->height <<= 2; // |
1661 else // V
1662 {
1663 corpsehit->height = info->height; // fix Ghost bug
1664 corpsehit->radius = info->radius; // fix Ghost bug
1665 } // phares
1666
1667 /* killough 7/18/98:
1668 * friendliness is transferred from AV to raised corpse
1669 */
1670 corpsehit->flags =
1671 (info->flags & ~MF_FRIEND) | (actor->flags & MF_FRIEND);
1672
1673 if (!((corpsehit->flags ^ MF_COUNTKILL) & (MF_FRIEND | MF_COUNTKILL)))
1674 totallive++;
1675
1676 corpsehit->health = info->spawnhealth;
1677 P_SetTarget(&corpsehit->target, NULL); // killough 11/98
1678
1679 if (mbf_features)
1680 { /* kilough 9/9/98 */
1681 P_SetTarget(&corpsehit->lastenemy, NULL);
1682 corpsehit->flags &= ~MF_JUSTHIT;
1683 }
1684
1685 /* killough 8/29/98: add to appropriate thread */
1686 P_UpdateThinker(&corpsehit->thinker);
1687
1688 return;
1689 }
1690 }
1691 }
1692 }
1693 A_Chase(actor); // Return to normal attack.
1694}
1695
1696//
1697// A_VileStart
1698//
1699
1700void A_VileStart(mobj_t *actor)
1701{
1702 S_StartSound(actor, sfx_vilatk);
1703}
1704
1705//
1706// A_Fire
1707// Keep fire in front of player unless out of sight
1708//
1709
1710void A_Fire(mobj_t *actor);
1711
1712void A_StartFire(mobj_t *actor)
1713{
1714 S_StartSound(actor,sfx_flamst);
1715 A_Fire(actor);
1716}
1717
1718void A_FireCrackle(mobj_t* actor)
1719{
1720 S_StartSound(actor,sfx_flame);
1721 A_Fire(actor);
1722}
1723
1724void A_Fire(mobj_t *actor)
1725{
1726 unsigned an;
1727 mobj_t *dest = actor->tracer;
1728
1729 if (!dest)
1730 return;
1731
1732 // don't move it if the vile lost sight
1733 if (!P_CheckSight(actor->target, dest) )
1734 return;
1735
1736 an = dest->angle >> ANGLETOFINESHIFT;
1737
1738 P_UnsetThingPosition(actor);
1739 actor->x = dest->x + FixedMul(24*FRACUNIT, finecosine[an]);
1740 actor->y = dest->y + FixedMul(24*FRACUNIT, finesine[an]);
1741 actor->z = dest->z;
1742 P_SetThingPosition(actor);
1743}
1744
1745//
1746// A_VileTarget
1747// Spawn the hellfire
1748//
1749
1750void A_VileTarget(mobj_t *actor)
1751{
1752 mobj_t *fog;
1753
1754 if (!actor->target)
1755 return;
1756
1757 A_FaceTarget(actor);
1758
1759 // killough 12/98: fix Vile fog coordinates // CPhipps - compatibility optioned
1760 fog = P_SpawnMobj(actor->target->x,
1761 (compatibility_level < lxdoom_1_compatibility) ? actor->target->x : actor->target->y,
1762 actor->target->z,MT_FIRE);
1763
1764 P_SetTarget(&actor->tracer, fog);
1765 P_SetTarget(&fog->target, actor);
1766 P_SetTarget(&fog->tracer, actor->target);
1767 A_Fire(fog);
1768}
1769
1770//
1771// A_VileAttack
1772//
1773
1774void A_VileAttack(mobj_t *actor)
1775{
1776 mobj_t *fire;
1777 int an;
1778
1779 if (!actor->target)
1780 return;
1781
1782 A_FaceTarget(actor);
1783
1784 if (!P_CheckSight(actor, actor->target))
1785 return;
1786
1787 S_StartSound(actor, sfx_barexp);
1788 P_DamageMobj(actor->target, actor, actor, 20);
1789 actor->target->momz = 1000*FRACUNIT/actor->target->info->mass;
1790
1791 an = actor->angle >> ANGLETOFINESHIFT;
1792
1793 fire = actor->tracer;
1794
1795 if (!fire)
1796 return;
1797
1798 // move the fire between the vile and the player
1799 fire->x = actor->target->x - FixedMul (24*FRACUNIT, finecosine[an]);
1800 fire->y = actor->target->y - FixedMul (24*FRACUNIT, finesine[an]);
1801 P_RadiusAttack(fire, actor, 70);
1802}
1803
1804//
1805// Mancubus attack,
1806// firing three missiles (bruisers)
1807// in three different directions?
1808// Doesn't look like it.
1809//
1810
1811#define FATSPREAD (ANG90/8)
1812
1813void A_FatRaise(mobj_t *actor)
1814{
1815 A_FaceTarget(actor);
1816 S_StartSound(actor, sfx_manatk);
1817}
1818
1819void A_FatAttack1(mobj_t *actor)
1820{
1821 mobj_t *mo;
1822 int an;
1823
1824 A_FaceTarget(actor);
1825
1826 // Change direction to ...
1827 actor->angle += FATSPREAD;
1828
1829 P_SpawnMissile(actor, actor->target, MT_FATSHOT);
1830
1831 mo = P_SpawnMissile (actor, actor->target, MT_FATSHOT);
1832 mo->angle += FATSPREAD;
1833 an = mo->angle >> ANGLETOFINESHIFT;
1834 mo->momx = FixedMul(mo->info->speed, finecosine[an]);
1835 mo->momy = FixedMul(mo->info->speed, finesine[an]);
1836}
1837
1838void A_FatAttack2(mobj_t *actor)
1839{
1840 mobj_t *mo;
1841 int an;
1842
1843 A_FaceTarget(actor);
1844 // Now here choose opposite deviation.
1845 actor->angle -= FATSPREAD;
1846 P_SpawnMissile(actor, actor->target, MT_FATSHOT);
1847
1848 mo = P_SpawnMissile(actor, actor->target, MT_FATSHOT);
1849 mo->angle -= FATSPREAD*2;
1850 an = mo->angle >> ANGLETOFINESHIFT;
1851 mo->momx = FixedMul(mo->info->speed, finecosine[an]);
1852 mo->momy = FixedMul(mo->info->speed, finesine[an]);
1853}
1854
1855void A_FatAttack3(mobj_t *actor)
1856{
1857 mobj_t *mo;
1858 int an;
1859
1860 A_FaceTarget(actor);
1861
1862 mo = P_SpawnMissile(actor, actor->target, MT_FATSHOT);
1863 mo->angle -= FATSPREAD/2;
1864 an = mo->angle >> ANGLETOFINESHIFT;
1865 mo->momx = FixedMul(mo->info->speed, finecosine[an]);
1866 mo->momy = FixedMul(mo->info->speed, finesine[an]);
1867
1868 mo = P_SpawnMissile(actor, actor->target, MT_FATSHOT);
1869 mo->angle += FATSPREAD/2;
1870 an = mo->angle >> ANGLETOFINESHIFT;
1871 mo->momx = FixedMul(mo->info->speed, finecosine[an]);
1872 mo->momy = FixedMul(mo->info->speed, finesine[an]);
1873}
1874
1875
1876//
1877// SkullAttack
1878// Fly at the player like a missile.
1879//
1880#define SKULLSPEED (20*FRACUNIT)
1881
1882void A_SkullAttack(mobj_t *actor)
1883{
1884 mobj_t *dest;
1885 angle_t an;
1886 int dist;
1887
1888 if (!actor->target)
1889 return;
1890
1891 dest = actor->target;
1892 actor->flags |= MF_SKULLFLY;
1893
1894 S_StartSound(actor, actor->info->attacksound);
1895 A_FaceTarget(actor);
1896 an = actor->angle >> ANGLETOFINESHIFT;
1897 actor->momx = FixedMul(SKULLSPEED, finecosine[an]);
1898 actor->momy = FixedMul(SKULLSPEED, finesine[an]);
1899 dist = P_AproxDistance(dest->x - actor->x, dest->y - actor->y);
1900 dist = dist / SKULLSPEED;
1901
1902 if (dist < 1)
1903 dist = 1;
1904 actor->momz = (dest->z+(dest->height>>1) - actor->z) / dist;
1905}
1906
1907//
1908// A_PainShootSkull
1909// Spawn a lost soul and launch it at the target
1910//
1911
1912void A_PainShootSkull(mobj_t *actor, angle_t angle)
1913{
1914 fixed_t x,y,z;
1915 mobj_t *newmobj;
1916 angle_t an;
1917 int prestep;
1918
1919 // The original code checked for 20 skulls on the level, // phares
1920 // and wouldn't spit another one if there were. If not in // phares
1921 // compatibility mode, we remove the limit. // phares
1922 // phares
1923 if (comp[comp_pain]) /* killough 10/98: compatibility-optioned */
1924 {
1925 // count total number of skulls currently on the level
1926 int count = 0;
1927 thinker_t *currentthinker;
1928 for (currentthinker = thinkercap.next;
1929 currentthinker != &thinkercap;
1930 currentthinker = currentthinker->next)
1931 if ((currentthinker->function == P_MobjThinker)
1932 && ((mobj_t *)currentthinker)->type == MT_SKULL)
1933 count++;
1934 if (count > 20) // phares
1935 return; // phares
1936 }
1937
1938 // okay, there's room for another one
1939
1940 an = angle >> ANGLETOFINESHIFT;
1941
1942 prestep = 4*FRACUNIT + 3*(actor->info->radius + mobjinfo[MT_SKULL].radius)/2;
1943
1944 x = actor->x + FixedMul(prestep, finecosine[an]);
1945 y = actor->y + FixedMul(prestep, finesine[an]);
1946 z = actor->z + 8*FRACUNIT;
1947
1948 if (comp[comp_skull]) /* killough 10/98: compatibility-optioned */
1949 newmobj = P_SpawnMobj(x, y, z, MT_SKULL); // phares
1950 else // V
1951 {
1952 // Check whether the Lost Soul is being fired through a 1-sided
1953 // wall or an impassible line, or a "monsters can't cross" line.
1954 // If it is, then we don't allow the spawn. This is a bug fix, but
1955 // it should be considered an enhancement, since it may disturb
1956 // existing demos, so don't do it in compatibility mode.
1957
1958 if (Check_Sides(actor,x,y))
1959 return;
1960
1961 newmobj = P_SpawnMobj(x, y, z, MT_SKULL);
1962
1963 // Check to see if the new Lost Soul's z value is above the
1964 // ceiling of its new sector, or below the floor. If so, kill it.
1965
1966 if ((newmobj->z >
1967 (newmobj->subsector->sector->ceilingheight - newmobj->height)) ||
1968 (newmobj->z < newmobj->subsector->sector->floorheight))
1969 {
1970 // kill it immediately
1971 P_DamageMobj(newmobj,actor,actor,10000);
1972 return; // ^
1973 } // |
1974 } // phares
1975
1976 /* killough 7/20/98: PEs shoot lost souls with the same friendliness */
1977 newmobj->flags = (newmobj->flags & ~MF_FRIEND) | (actor->flags & MF_FRIEND);
1978
1979 /* killough 8/29/98: add to appropriate thread */
1980 P_UpdateThinker(&newmobj->thinker);
1981
1982 // Check for movements.
1983 // killough 3/15/98: don't jump over dropoffs:
1984
1985 if (!P_TryMove(newmobj, newmobj->x, newmobj->y, false))
1986 {
1987 // kill it immediately
1988 P_DamageMobj(newmobj, actor, actor, 10000);
1989 return;
1990 }
1991
1992 P_SetTarget(&newmobj->target, actor->target);
1993 A_SkullAttack(newmobj);
1994}
1995
1996//
1997// A_PainAttack
1998// Spawn a lost soul and launch it at the target
1999//
2000
2001void A_PainAttack(mobj_t *actor)
2002{
2003 if (!actor->target)
2004 return;
2005 A_FaceTarget(actor);
2006 A_PainShootSkull(actor, actor->angle);
2007}
2008
2009void A_PainDie(mobj_t *actor)
2010{
2011 A_Fall(actor);
2012 A_PainShootSkull(actor, actor->angle+ANG90);
2013 A_PainShootSkull(actor, actor->angle+ANG180);
2014 A_PainShootSkull(actor, actor->angle+ANG270);
2015}
2016
2017void A_Scream(mobj_t *actor)
2018{
2019 int sound;
2020
2021 switch (actor->info->deathsound)
2022 {
2023 case 0:
2024 return;
2025
2026 case sfx_podth1:
2027 case sfx_podth2:
2028 case sfx_podth3:
2029 sound = sfx_podth1 + P_Random(pr_scream)%3;
2030 break;
2031
2032 case sfx_bgdth1:
2033 case sfx_bgdth2:
2034 sound = sfx_bgdth1 + P_Random(pr_scream)%2;
2035 break;
2036
2037 default:
2038 sound = actor->info->deathsound;
2039 break;
2040 }
2041
2042 // Check for bosses.
2043 if (actor->type==MT_SPIDER || actor->type == MT_CYBORG)
2044 S_StartSound(NULL, sound); // full volume
2045 else
2046 S_StartSound(actor, sound);
2047}
2048
2049void A_XScream(mobj_t *actor)
2050{
2051 S_StartSound(actor, sfx_slop);
2052}
2053
2054void A_Pain(mobj_t *actor)
2055{
2056 if (actor->info->painsound)
2057 S_StartSound(actor, actor->info->painsound);
2058}
2059
2060void A_Fall(mobj_t *actor)
2061{
2062 // actor is on ground, it can be walked over
2063 actor->flags &= ~MF_SOLID;
2064}
2065
2066//
2067// A_Explode
2068//
2069void A_Explode(mobj_t *thingy)
2070{
2071 P_RadiusAttack( thingy, thingy->target, 128 );
2072}
2073
2074//
2075// A_BossDeath
2076// Possibly trigger special effects
2077// if on first boss level
2078//
2079
2080void A_BossDeath(mobj_t *mo)
2081{
2082 thinker_t *th;
2083 line_t junk;
2084 int i;
2085
2086 if (gamemode == commercial)
2087 {
2088 if (gamemap != 7)
2089 return;
2090
2091 if ((mo->type != MT_FATSO)
2092 && (mo->type != MT_BABY))
2093 return;
2094 }
2095 else
2096 {
2097 switch(gameepisode)
2098 {
2099 case 1:
2100 if (gamemap != 8)
2101 return;
2102
2103 if (mo->type != MT_BRUISER)
2104 return;
2105 break;
2106
2107 case 2:
2108 if (gamemap != 8)
2109 return;
2110
2111 if (mo->type != MT_CYBORG)
2112 return;
2113 break;
2114
2115 case 3:
2116 if (gamemap != 8)
2117 return;
2118
2119 if (mo->type != MT_SPIDER)
2120 return;
2121
2122 break;
2123
2124 case 4:
2125 switch(gamemap)
2126 {
2127 case 6:
2128 if (mo->type != MT_CYBORG)
2129 return;
2130 break;
2131
2132 case 8:
2133 if (mo->type != MT_SPIDER)
2134 return;
2135 break;
2136
2137 default:
2138 return;
2139 break;
2140 }
2141 break;
2142
2143 default:
2144 if (gamemap != 8)
2145 return;
2146 break;
2147 }
2148
2149 }
2150
2151 // make sure there is a player alive for victory
2152 for (i=0; i<MAXPLAYERS; i++)
2153 if (playeringame[i] && players[i].health > 0)
2154 break;
2155
2156 if (i==MAXPLAYERS)
2157 return; // no one left alive, so do not end game
2158
2159 // scan the remaining thinkers to see
2160 // if all bosses are dead
2161 for (th = thinkercap.next ; th != &thinkercap ; th=th->next)
2162 if (th->function == P_MobjThinker)
2163 {
2164 mobj_t *mo2 = (mobj_t *) th;
2165 if (mo2 != mo && mo2->type == mo->type && mo2->health > 0)
2166 return; // other boss not dead
2167 }
2168
2169 // victory!
2170 if ( gamemode == commercial)
2171 {
2172 if (gamemap == 7)
2173 {
2174 if (mo->type == MT_FATSO)
2175 {
2176 junk.tag = 666;
2177 EV_DoFloor(&junk,lowerFloorToLowest);
2178 return;
2179 }
2180
2181 if (mo->type == MT_BABY)
2182 {
2183 junk.tag = 667;
2184 EV_DoFloor(&junk,raiseToTexture);
2185 return;
2186 }
2187 }
2188 }
2189 else
2190 {
2191 switch(gameepisode)
2192 {
2193 case 1:
2194 junk.tag = 666;
2195 EV_DoFloor(&junk, lowerFloorToLowest);
2196 return;
2197 break;
2198
2199 case 4:
2200 switch(gamemap)
2201 {
2202 case 6:
2203 junk.tag = 666;
2204 EV_DoDoor(&junk, blazeOpen);
2205 return;
2206 break;
2207
2208 case 8:
2209 junk.tag = 666;
2210 EV_DoFloor(&junk, lowerFloorToLowest);
2211 return;
2212 break;
2213 }
2214 }
2215 }
2216 G_ExitLevel();
2217}
2218
2219
2220void A_Hoof (mobj_t* mo)
2221{
2222 S_StartSound(mo, sfx_hoof);
2223 A_Chase(mo);
2224}
2225
2226void A_Metal(mobj_t *mo)
2227{
2228 S_StartSound(mo, sfx_metal);
2229 A_Chase(mo);
2230}
2231
2232void A_BabyMetal(mobj_t *mo)
2233{
2234 S_StartSound(mo, sfx_bspwlk);
2235 A_Chase(mo);
2236}
2237
2238void A_OpenShotgun2(player_t *player, pspdef_t *psp)
2239{
2240 (void)psp;
2241 S_StartSound(player->mo, sfx_dbopn);
2242}
2243
2244void A_LoadShotgun2(player_t *player, pspdef_t *psp)
2245{
2246 (void)psp;
2247 S_StartSound(player->mo, sfx_dbload);
2248}
2249
2250void A_ReFire(player_t *player, pspdef_t *psp);
2251
2252void A_CloseShotgun2(player_t *player, pspdef_t *psp)
2253{
2254 S_StartSound(player->mo, sfx_dbcls);
2255 A_ReFire(player,psp);
2256}
2257
2258// killough 2/7/98: Remove limit on icon landings:
2259mobj_t **braintargets;
2260int numbraintargets_alloc;
2261int numbraintargets;
2262
2263struct brain_s brain; // killough 3/26/98: global state of boss brain
2264
2265// killough 3/26/98: initialize icon landings at level startup,
2266// rather than at boss wakeup, to prevent savegame-related crashes
2267
2268void P_SpawnBrainTargets(void) // killough 3/26/98: renamed old function
2269{
2270 thinker_t *thinker;
2271
2272 // find all the target spots
2273 numbraintargets = 0;
2274 brain.targeton = 0;
2275 brain.easy = 0; // killough 3/26/98: always init easy to 0
2276
2277 for (thinker = thinkercap.next ;
2278 thinker != &thinkercap ;
2279 thinker = thinker->next)
2280 if (thinker->function == P_MobjThinker)
2281 {
2282 mobj_t *m = (mobj_t *) thinker;
2283
2284 if (m->type == MT_BOSSTARGET )
2285 { // killough 2/7/98: remove limit on icon landings:
2286 if (numbraintargets >= numbraintargets_alloc)
2287 braintargets = realloc(braintargets,
2288 (numbraintargets_alloc = numbraintargets_alloc ?
2289 numbraintargets_alloc*2 : 32) *sizeof *braintargets);
2290 braintargets[numbraintargets++] = m;
2291 }
2292 }
2293}
2294
2295void A_BrainAwake(mobj_t *mo)
2296{
2297 (void)mo;
2298 S_StartSound(NULL,sfx_bossit); // killough 3/26/98: only generates sound now
2299}
2300
2301void A_BrainPain(mobj_t *mo)
2302{
2303 (void)mo;
2304 S_StartSound(NULL,sfx_bospn);
2305}
2306
2307void A_BrainScream(mobj_t *mo)
2308{
2309 int x;
2310 for (x=mo->x - 196*FRACUNIT ; x< mo->x + 320*FRACUNIT ; x+= FRACUNIT*8)
2311 {
2312 int y = mo->y - 320*FRACUNIT;
2313 int z = 128 + P_Random(pr_brainscream)*2*FRACUNIT;
2314 mobj_t *th = P_SpawnMobj (x,y,z, MT_ROCKET);
2315 th->momz = P_Random(pr_brainscream)*512;
2316 P_SetMobjState(th, S_BRAINEXPLODE1);
2317 th->tics -= P_Random(pr_brainscream)&7;
2318 if (th->tics < 1)
2319 th->tics = 1;
2320 }
2321 S_StartSound(NULL,sfx_bosdth);
2322}
2323
2324void A_BrainExplode(mobj_t *mo)
2325{ // killough 5/5/98: remove dependence on order of evaluation:
2326 (void)mo;
2327 int t = P_Random(pr_brainexp);
2328 int x = mo->x + (t - P_Random(pr_brainexp))*2048;
2329 int y = mo->y;
2330 int z = 128 + P_Random(pr_brainexp)*2*FRACUNIT;
2331 mobj_t *th = P_SpawnMobj(x,y,z, MT_ROCKET);
2332 th->momz = P_Random(pr_brainexp)*512;
2333 P_SetMobjState(th, S_BRAINEXPLODE1);
2334 th->tics -= P_Random(pr_brainexp)&7;
2335 if (th->tics < 1)
2336 th->tics = 1;
2337}
2338
2339void A_BrainDie(mobj_t *mo)
2340{
2341 (void)mo;
2342 G_ExitLevel();
2343}
2344
2345void A_BrainSpit(mobj_t *mo)
2346{
2347 mobj_t *targ, *newmobj;
2348
2349 if (!numbraintargets) // killough 4/1/98: ignore if no targets
2350 return;
2351
2352 brain.easy ^= 1; // killough 3/26/98: use brain struct
2353 if (gameskill <= sk_easy && !brain.easy)
2354 return;
2355
2356 // shoot a cube at current target
2357 targ = braintargets[brain.targeton++]; // killough 3/26/98:
2358 brain.targeton %= numbraintargets; // Use brain struct for targets
2359
2360 // spawn brain missile
2361 newmobj = P_SpawnMissile(mo, targ, MT_SPAWNSHOT);
2362 P_SetTarget(&newmobj->target, targ);
2363 newmobj->reactiontime = (short)(((targ->y-mo->y)/newmobj->momy)/newmobj->state->tics);
2364
2365 // killough 7/18/98: brain friendliness is transferred
2366 newmobj->flags = (newmobj->flags & ~MF_FRIEND) | (mo->flags & MF_FRIEND);
2367
2368 // killough 8/29/98: add to appropriate thread
2369 P_UpdateThinker(&newmobj->thinker);
2370
2371 S_StartSound(NULL, sfx_bospit);
2372}
2373
2374void A_SpawnFly(mobj_t *mo);
2375
2376// travelling cube sound
2377void A_SpawnSound(mobj_t *mo)
2378{
2379 S_StartSound(mo,sfx_boscub);
2380 A_SpawnFly(mo);
2381}
2382
2383void A_SpawnFly(mobj_t *mo)
2384{
2385 mobj_t *newmobj;
2386 mobj_t *fog;
2387 mobj_t *targ;
2388 int r;
2389 mobjtype_t type;
2390
2391 if (--mo->reactiontime)
2392 return; // still flying
2393
2394 targ = mo->target;
2395
2396 // First spawn teleport fog.
2397 fog = P_SpawnMobj(targ->x, targ->y, targ->z, MT_SPAWNFIRE);
2398 S_StartSound(fog, sfx_telept);
2399
2400 // Randomly select monster to spawn.
2401 r = P_Random(pr_spawnfly);
2402
2403 // Probability distribution (kind of :), decreasing likelihood.
2404 if ( r<50 )
2405 type = MT_TROOP;
2406 else if (r<90)
2407 type = MT_SERGEANT;
2408 else if (r<120)
2409 type = MT_SHADOWS;
2410 else if (r<130)
2411 type = MT_PAIN;
2412 else if (r<160)
2413 type = MT_HEAD;
2414 else if (r<162)
2415 type = MT_VILE;
2416 else if (r<172)
2417 type = MT_UNDEAD;
2418 else if (r<192)
2419 type = MT_BABY;
2420 else if (r<222)
2421 type = MT_FATSO;
2422 else if (r<246)
2423 type = MT_KNIGHT;
2424 else
2425 type = MT_BRUISER;
2426
2427 newmobj = P_SpawnMobj(targ->x, targ->y, targ->z, type);
2428
2429 /* killough 7/18/98: brain friendliness is transferred */
2430 newmobj->flags = (newmobj->flags & ~MF_FRIEND) | (mo->flags & MF_FRIEND);
2431
2432 /* killough 8/29/98: add to appropriate thread */
2433 P_UpdateThinker(&newmobj->thinker);
2434
2435 if (P_LookForTargets(newmobj,true)) /* killough 9/4/98 */
2436 P_SetMobjState(newmobj, newmobj->info->seestate);
2437
2438 // telefrag anything in this spot
2439 P_TeleportMove(newmobj, newmobj->x, newmobj->y, true); /* killough 8/9/98 */
2440
2441 // remove self (i.e., cube).
2442 P_RemoveMobj(mo);
2443}
2444
2445void A_PlayerScream(mobj_t *mo)
2446{
2447 int sound = sfx_pldeth; // Default death sound.
2448 if (gamemode != shareware && mo->health < -50)
2449 sound = sfx_pdiehi; // IF THE PLAYER DIES LESS THAN -50% WITHOUT GIBBING
2450 S_StartSound(mo, sound);
2451}
2452
2453/* cph - MBF-added codepointer functions */
2454
2455// killough 11/98: kill an object
2456void A_Die(mobj_t *actor)
2457{
2458 P_DamageMobj(actor, NULL, NULL, actor->health);
2459}
2460
2461//
2462// A_Detonate
2463// killough 8/9/98: same as A_Explode, except that the damage is variable
2464//
2465
2466void A_Detonate(mobj_t *mo)
2467{
2468 P_RadiusAttack(mo, mo->target, mo->info->damage);
2469}
2470
2471//
2472// killough 9/98: a mushroom explosion effect, sorta :)
2473// Original idea: Linguica
2474//
2475
2476void A_Mushroom(mobj_t *actor)
2477{
2478 int i, j, n = actor->info->damage;
2479
2480 A_Explode(actor); // First make normal explosion
2481
2482 // Now launch mushroom cloud
2483 for (i = -n; i <= n; i += 8)
2484 for (j = -n; j <= n; j += 8)
2485 {
2486 mobj_t target = *actor, *mo;
2487 target.x += i << FRACBITS; // Aim in many directions from source
2488 target.y += j << FRACBITS;
2489 target.z += P_AproxDistance(i,j) << (FRACBITS+2); // Aim up fairly high
2490 mo = P_SpawnMissile(actor, &target, MT_FATSHOT); // Launch fireball
2491 mo->momx >>= 1;
2492 mo->momy >>= 1; // Slow it down a bit
2493 mo->momz >>= 1;
2494 mo->flags &= ~MF_NOGRAVITY; // Make debris fall under gravity
2495 }
2496}
2497
2498//
2499// killough 11/98
2500//
2501// The following were inspired by Len Pitre
2502//
2503// A small set of highly-sought-after code pointers
2504//
2505
2506void A_Spawn(mobj_t *mo)
2507{
2508 if (mo->state->misc1)
2509 {
2510 /* mobj_t *newmobj = */
2511 P_SpawnMobj(mo->x, mo->y, (mo->state->misc2 << FRACBITS) + mo->z,
2512 mo->state->misc1 - 1);
2513 /* CPhipps - no friendlyness (yet)
2514 newmobj->flags = (newmobj->flags & ~MF_FRIEND) | (mo->flags & MF_FRIEND);
2515 */
2516 }
2517}
2518
2519void A_Turn(mobj_t *mo)
2520{
2521 mo->angle += (unsigned int)(((uint_64_t) mo->state->misc1 << 32) / 360);
2522}
2523
2524void A_Face(mobj_t *mo)
2525{
2526 mo->angle = (unsigned int)(((uint_64_t) mo->state->misc1 << 32) / 360);
2527}
2528
2529void A_Scratch(mobj_t *mo)
2530{
2531 mo->target && (A_FaceTarget(mo), P_CheckMeleeRange(mo)) ?
2532 mo->state->misc2 ? S_StartSound(mo, mo->state->misc2) : (void) 0,
2533 P_DamageMobj(mo->target, mo, mo, mo->state->misc1) : (void) 0;
2534}
2535
2536void A_PlaySound(mobj_t *mo)
2537{
2538 S_StartSound(mo->state->misc2 ? NULL : mo, mo->state->misc1);
2539}
2540
2541void A_RandomJump(mobj_t *mo)
2542{
2543 if (P_Random(pr_randomjump) < mo->state->misc2)
2544 P_SetMobjState(mo, mo->state->misc1);
2545}
2546
2547//
2548// This allows linedef effects to be activated inside deh frames.
2549//
2550
2551void A_LineEffect(mobj_t *mo)
2552{
2553 static line_t junk;
2554 player_t player;
2555 player_t *oldplayer;
2556 junk = *lines;
2557 oldplayer = mo->player;
2558 mo->player = &player;
2559 player.health = 100;
2560 junk.special = (short)mo->state->misc1;
2561 if (!junk.special)
2562 return;
2563 junk.tag = (short)mo->state->misc2;
2564 if (!P_UseSpecialLine(mo, &junk, 0))
2565 P_CrossSpecialLine(&junk, 0, mo);
2566 mo->state->misc1 = junk.special;
2567 mo->player = oldplayer;
2568}
2569
2570/***** Start of new functions for Andy Baker's stealth monsters ******/
2571
2572void P_BecomeVisible(mobj_t* actor)
2573{
2574 actor->invisible = false;
2575 actor->flags &= ~MF_TRANSLUCBITS;
2576};
2577
2578void P_IncreaseVisibility(mobj_t* actor)
2579{
2580 if (actor->invisible) {
2581 actor->invisible = false;
2582 actor->flags |= MF_TRANSLUC25;
2583 } else switch (actor->flags & MF_TRANSLUCBITS) {
2584 case MF_TRANSLUC25:
2585 actor->flags &= ~MF_TRANSLUCBITS;
2586 actor->flags |= MF_TRANSLUC50;
2587 break;
2588 case MF_TRANSLUC50:
2589 actor->flags &= ~MF_TRANSLUCBITS;
2590 actor->flags |= MF_TRANSLUC25;
2591 actor->flags |= MF_TRANSLUC50;
2592 break;
2593 case MF_TRANSLUC75:
2594 actor->flags &= ~MF_TRANSLUCBITS;
2595 break;
2596 }
2597}
2598
2599void P_DecreaseVisibility(mobj_t* actor)
2600{
2601 if (actor->invisible)
2602 return; // already invisible
2603
2604 switch (actor->flags & MF_TRANSLUCBITS) {
2605 case 0:
2606 actor->flags &= ~MF_TRANSLUCBITS;
2607 actor->flags |= MF_TRANSLUC75;
2608 break;
2609 case MF_TRANSLUC75:
2610 actor->flags &= ~MF_TRANSLUCBITS;
2611 actor->flags |= MF_TRANSLUC50;
2612 break;
2613 case MF_TRANSLUC50:
2614 actor->flags &= ~MF_TRANSLUCBITS;
2615 actor->flags |= MF_TRANSLUC25;
2616 break;
2617 case MF_TRANSLUC25:
2618 actor->flags &= ~MF_TRANSLUCBITS;
2619 actor->invisible = true;
2620 }
2621}
2622/***** End of new functions for Andy Baker's stealth monsters ******/
2623
diff --git a/apps/plugins/doom/p_enemy.h b/apps/plugins/doom/p_enemy.h
new file mode 100644
index 0000000000..edf59af6ef
--- /dev/null
+++ b/apps/plugins/doom/p_enemy.h
@@ -0,0 +1,50 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION:
28 * Enemy thinking, AI.
29 * Action Pointer Functions
30 * that are associated with states/frames.
31 *
32 *-----------------------------------------------------------------------------*/
33
34#ifndef __P_ENEMY__
35#define __P_ENEMY__
36
37#include "p_mobj.h"
38
39void P_NoiseAlert (mobj_t *target, mobj_t *emmiter);
40void P_SpawnBrainTargets(void); /* killough 3/26/98: spawn icon landings */
41/* proff 11/22/98: Andy Baker's stealth monsters */
42void P_BecomeVisible (mobj_t *actor);
43void P_IncreaseVisibility (mobj_t *actor);
44void P_DecreaseVisibility (mobj_t *actor);
45
46extern struct brain_s { /* killough 3/26/98: global state of boss brain */
47 int easy, targeton;
48 } brain;
49
50#endif // __P_ENEMY__
diff --git a/apps/plugins/doom/p_floor.c b/apps/plugins/doom/p_floor.c
new file mode 100644
index 0000000000..bbcf2bc358
--- /dev/null
+++ b/apps/plugins/doom/p_floor.c
@@ -0,0 +1,1035 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION:
28 * General plane mover and floor mover action routines
29 * Floor motion, pure changer types, raising stairs. donuts, elevators
30 *
31 *-----------------------------------------------------------------------------*/
32
33#include "doomstat.h"
34#include "r_main.h"
35#include "p_map.h"
36#include "p_spec.h"
37#include "p_tick.h"
38#include "s_sound.h"
39#include "sounds.h"
40
41#include "rockmacros.h"
42
43///////////////////////////////////////////////////////////////////////
44//
45// Plane (floor or ceiling), Floor motion and Elevator action routines
46//
47///////////////////////////////////////////////////////////////////////
48
49//
50// T_MovePlane()
51//
52// Move a plane (floor or ceiling) and check for crushing. Called
53// every tick by all actions that move floors or ceilings.
54//
55// Passed the sector to move a plane in, the speed to move it at,
56// the dest height it is to achieve, whether it crushes obstacles,
57// whether it moves a floor or ceiling, and the direction up or down
58// to move.
59//
60// Returns a result_e:
61// ok - plane moved normally, has not achieved destination yet
62// pastdest - plane moved normally and is now at destination height
63// crushed - plane encountered an obstacle, is holding until removed
64//
65result_e T_MovePlane
66( sector_t* sector,
67 fixed_t speed,
68 fixed_t dest,
69 boolean crush,
70 int floorOrCeiling,
71 int direction )
72{
73 boolean flag;
74 fixed_t lastpos;
75 fixed_t destheight; //jff 02/04/98 used to keep floors/ceilings
76 // from moving thru each other
77
78 switch(floorOrCeiling)
79 {
80 case 0:
81 // Moving a floor
82 switch(direction)
83 {
84 case -1:
85 // Moving a floor down
86 if (sector->floorheight - speed < dest)
87 {
88 lastpos = sector->floorheight;
89 sector->floorheight = dest;
90 flag = P_CheckSector(sector,crush); //jff 3/19/98 use faster chk
91 if (flag == true)
92 {
93 sector->floorheight =lastpos;
94 P_CheckSector(sector,crush); //jff 3/19/98 use faster chk
95 }
96 return pastdest;
97 }
98 else
99 {
100 lastpos = sector->floorheight;
101 sector->floorheight -= speed;
102 flag = P_CheckSector(sector,crush); //jff 3/19/98 use faster chk
103 /* cph - make more compatible with original Doom, by
104 * reintroducing this code. This means floors can't lower
105 * if objects are stuck in the ceiling */
106 if ((flag == true) && comp[comp_floors]) {
107 sector->floorheight = lastpos;
108 P_ChangeSector(sector,crush);
109 return crushed;
110 }
111 }
112 break;
113
114 case 1:
115 // Moving a floor up
116 // jff 02/04/98 keep floor from moving thru ceilings
117 // jff 2/22/98 weaken check to demo_compatibility
118 destheight = (comp[comp_floors] || dest<sector->ceilingheight)?
119 dest : sector->ceilingheight;
120 if (sector->floorheight + speed > destheight)
121 {
122 lastpos = sector->floorheight;
123 sector->floorheight = destheight;
124 flag = P_CheckSector(sector,crush); //jff 3/19/98 use faster chk
125 if (flag == true)
126 {
127 sector->floorheight = lastpos;
128 P_CheckSector(sector,crush); //jff 3/19/98 use faster chk
129 }
130 return pastdest;
131 }
132 else
133 {
134 // crushing is possible
135 lastpos = sector->floorheight;
136 sector->floorheight += speed;
137 flag = P_CheckSector(sector,crush); //jff 3/19/98 use faster chk
138 if (flag == true)
139 {
140 /* jff 1/25/98 fix floor crusher */
141 if (comp[comp_floors]) {
142 if (crush == true)
143 return crushed;
144 }
145 sector->floorheight = lastpos;
146 P_CheckSector(sector,crush); //jff 3/19/98 use faster chk
147 return crushed;
148 }
149 }
150 break;
151 }
152 break;
153
154 case 1:
155 // moving a ceiling
156 switch(direction)
157 {
158 case -1:
159 // moving a ceiling down
160 // jff 02/04/98 keep ceiling from moving thru floors
161 // jff 2/22/98 weaken check to demo_compatibility
162 destheight = (comp[comp_floors] || dest>sector->floorheight)?
163 dest : sector->floorheight;
164 if (sector->ceilingheight - speed < destheight)
165 {
166 lastpos = sector->ceilingheight;
167 sector->ceilingheight = destheight;
168 flag = P_CheckSector(sector,crush); //jff 3/19/98 use faster chk
169
170 if (flag == true)
171 {
172 sector->ceilingheight = lastpos;
173 P_CheckSector(sector,crush); //jff 3/19/98 use faster chk
174 }
175 return pastdest;
176 }
177 else
178 {
179 // crushing is possible
180 lastpos = sector->ceilingheight;
181 sector->ceilingheight -= speed;
182 flag = P_CheckSector(sector,crush); //jff 3/19/98 use faster chk
183
184 if (flag == true)
185 {
186 if (crush == true)
187 return crushed;
188 sector->ceilingheight = lastpos;
189 P_CheckSector(sector,crush); //jff 3/19/98 use faster chk
190 return crushed;
191 }
192 }
193 break;
194
195 case 1:
196 // moving a ceiling up
197 if (sector->ceilingheight + speed > dest)
198 {
199 lastpos = sector->ceilingheight;
200 sector->ceilingheight = dest;
201 flag = P_CheckSector(sector,crush); //jff 3/19/98 use faster chk
202 if (flag == true)
203 {
204 sector->ceilingheight = lastpos;
205 P_CheckSector(sector,crush); //jff 3/19/98 use faster chk
206 }
207 return pastdest;
208 }
209 else
210 {
211 lastpos = sector->ceilingheight;
212 sector->ceilingheight += speed;
213 flag = P_CheckSector(sector,crush); //jff 3/19/98 use faster chk
214 }
215 break;
216 }
217 break;
218 }
219 return ok;
220}
221
222//
223// T_MoveFloor()
224//
225// Move a floor to it's destination (up or down).
226// Called once per tick for each moving floor.
227//
228// Passed a floormove_t structure that contains all pertinent info about the
229// move. See P_SPEC.H for fields.
230// No return.
231//
232// jff 02/08/98 all cases with labels beginning with gen added to support
233// generalized line type behaviors.
234void T_MoveFloor(floormove_t* floor)
235{
236 result_e res;
237
238 res = T_MovePlane // move the floor
239 (
240 floor->sector,
241 floor->speed,
242 floor->floordestheight,
243 floor->crush,
244 0,
245 floor->direction
246 );
247
248 if (!(leveltime&7)) // make the floormove sound
249 S_StartSound((mobj_t *)&floor->sector->soundorg, sfx_stnmov);
250
251 if (res == pastdest) // if destination height is reached
252 {
253 if (floor->direction == 1) // going up
254 {
255 switch(floor->type) // handle texture/type changes
256 {
257 case donutRaise:
258 floor->sector->special = floor->newspecial;
259 floor->sector->floorpic = floor->texture;
260 break;
261 case genFloorChgT:
262 case genFloorChg0:
263 floor->sector->special = floor->newspecial;
264 //jff add to fix bug in special transfers from changes
265 floor->sector->oldspecial = floor->oldspecial;
266 //fall thru
267 case genFloorChg:
268 floor->sector->floorpic = floor->texture;
269 break;
270 default:
271 break;
272 }
273 }
274 else if (floor->direction == -1) // going down
275 {
276 switch(floor->type) // handle texture/type changes
277 {
278 case lowerAndChange:
279 floor->sector->special = floor->newspecial;
280 //jff add to fix bug in special transfers from changes
281 floor->sector->oldspecial = floor->oldspecial;
282 floor->sector->floorpic = floor->texture;
283 break;
284 case genFloorChgT:
285 case genFloorChg0:
286 floor->sector->special = floor->newspecial;
287 //jff add to fix bug in special transfers from changes
288 floor->sector->oldspecial = floor->oldspecial;
289 //fall thru
290 case genFloorChg:
291 floor->sector->floorpic = floor->texture;
292 break;
293 default:
294 break;
295 }
296 }
297
298 floor->sector->floordata = NULL; //jff 2/22/98
299 P_RemoveThinker(&floor->thinker);//remove this floor from list of movers
300
301 //jff 2/26/98 implement stair retrigger lockout while still building
302 // note this only applies to the retriggerable generalized stairs
303
304 if (floor->sector->stairlock==-2) // if this sector is stairlocked
305 {
306 sector_t *sec = floor->sector;
307 sec->stairlock=-1; // thinker done, promote lock to -1
308
309 while (sec->prevsec!=-1 && sectors[sec->prevsec].stairlock!=-2)
310 sec = &sectors[sec->prevsec]; // search for a non-done thinker
311 if (sec->prevsec==-1) // if all thinkers previous are done
312 {
313 sec = floor->sector; // search forward
314 while (sec->nextsec!=-1 && sectors[sec->nextsec].stairlock!=-2)
315 sec = &sectors[sec->nextsec];
316 if (sec->nextsec==-1) // if all thinkers ahead are done too
317 {
318 while (sec->prevsec!=-1) // clear all locks
319 {
320 sec->stairlock = 0;
321 sec = &sectors[sec->prevsec];
322 }
323 sec->stairlock = 0;
324 }
325 }
326 }
327
328 // make floor stop sound
329 S_StartSound((mobj_t *)&floor->sector->soundorg, sfx_pstop);
330 }
331}
332
333//
334// T_MoveElevator()
335//
336// Move an elevator to it's destination (up or down)
337// Called once per tick for each moving floor.
338//
339// Passed an elevator_t structure that contains all pertinent info about the
340// move. See P_SPEC.H for fields.
341// No return.
342//
343// jff 02/22/98 added to support parallel floor/ceiling motion
344//
345void T_MoveElevator(elevator_t* elevator)
346{
347 result_e res;
348
349 if (elevator->direction<0) // moving down
350 {
351 res = T_MovePlane //jff 4/7/98 reverse order of ceiling/floor
352 (
353 elevator->sector,
354 elevator->speed,
355 elevator->ceilingdestheight,
356 0,
357 1, // move floor
358 elevator->direction
359 );
360 if (res==ok || res==pastdest) // jff 4/7/98 don't move ceil if blocked
361 T_MovePlane
362 (
363 elevator->sector,
364 elevator->speed,
365 elevator->floordestheight,
366 0,
367 0, // move ceiling
368 elevator->direction
369 );
370 }
371 else // up
372 {
373 res = T_MovePlane //jff 4/7/98 reverse order of ceiling/floor
374 (
375 elevator->sector,
376 elevator->speed,
377 elevator->floordestheight,
378 0,
379 0, // move ceiling
380 elevator->direction
381 );
382 if (res==ok || res==pastdest) // jff 4/7/98 don't move floor if blocked
383 T_MovePlane
384 (
385 elevator->sector,
386 elevator->speed,
387 elevator->ceilingdestheight,
388 0,
389 1, // move floor
390 elevator->direction
391 );
392 }
393
394 // make floor move sound
395 if (!(leveltime&7))
396 S_StartSound((mobj_t *)&elevator->sector->soundorg, sfx_stnmov);
397
398 if (res == pastdest) // if destination height acheived
399 {
400 elevator->sector->floordata = NULL; //jff 2/22/98
401 elevator->sector->ceilingdata = NULL; //jff 2/22/98
402 P_RemoveThinker(&elevator->thinker); // remove elevator from actives
403
404 // make floor stop sound
405 S_StartSound((mobj_t *)&elevator->sector->soundorg, sfx_pstop);
406 }
407}
408
409///////////////////////////////////////////////////////////////////////
410//
411// Floor motion linedef handlers
412//
413///////////////////////////////////////////////////////////////////////
414
415//
416// EV_DoFloor()
417//
418// Handle regular and extended floor types
419//
420// Passed the line that activated the floor and the type of floor motion
421// Returns true if a thinker was created.
422//
423int EV_DoFloor
424( line_t* line,
425 floor_e floortype )
426{
427 int secnum;
428 int rtn;
429 int i;
430 sector_t* sec;
431 floormove_t* floor;
432
433 secnum = -1;
434 rtn = 0;
435 // move all floors with the same tag as the linedef
436 while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0)
437 {
438 sec = &sectors[secnum];
439
440 // Don't start a second thinker on the same floor
441 if (P_SectorActive(floor_special,sec)) //jff 2/23/98
442 continue;
443
444 // new floor thinker
445 rtn = 1;
446 floor = Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0);
447 P_AddThinker (&floor->thinker);
448 sec->floordata = floor; //jff 2/22/98
449 floor->thinker.function = T_MoveFloor;
450 floor->type = floortype;
451 floor->crush = false;
452
453 // setup the thinker according to the linedef type
454 switch(floortype)
455 {
456 case lowerFloor:
457 floor->direction = -1;
458 floor->sector = sec;
459 floor->speed = FLOORSPEED;
460 floor->floordestheight = P_FindHighestFloorSurrounding(sec);
461 break;
462
463 //jff 02/03/30 support lowering floor by 24 absolute
464 case lowerFloor24:
465 floor->direction = -1;
466 floor->sector = sec;
467 floor->speed = FLOORSPEED;
468 floor->floordestheight = floor->sector->floorheight + 24 * FRACUNIT;
469 break;
470
471 //jff 02/03/30 support lowering floor by 32 absolute (fast)
472 case lowerFloor32Turbo:
473 floor->direction = -1;
474 floor->sector = sec;
475 floor->speed = FLOORSPEED*4;
476 floor->floordestheight = floor->sector->floorheight + 32 * FRACUNIT;
477 break;
478
479 case lowerFloorToLowest:
480 floor->direction = -1;
481 floor->sector = sec;
482 floor->speed = FLOORSPEED;
483 floor->floordestheight = P_FindLowestFloorSurrounding(sec);
484 break;
485
486 //jff 02/03/30 support lowering floor to next lowest floor
487 case lowerFloorToNearest:
488 floor->direction = -1;
489 floor->sector = sec;
490 floor->speed = FLOORSPEED;
491 floor->floordestheight =
492 P_FindNextLowestFloor(sec,floor->sector->floorheight);
493 break;
494
495 case turboLower:
496 floor->direction = -1;
497 floor->sector = sec;
498 floor->speed = FLOORSPEED * 4;
499 floor->floordestheight = P_FindHighestFloorSurrounding(sec);
500 if (floor->floordestheight != sec->floorheight)
501 floor->floordestheight += 8*FRACUNIT;
502 break;
503
504 case raiseFloorCrush:
505 floor->crush = true;
506 case raiseFloor:
507 floor->direction = 1;
508 floor->sector = sec;
509 floor->speed = FLOORSPEED;
510 floor->floordestheight = P_FindLowestCeilingSurrounding(sec);
511 if (floor->floordestheight > sec->ceilingheight)
512 floor->floordestheight = sec->ceilingheight;
513 floor->floordestheight -= (8*FRACUNIT)*(floortype == raiseFloorCrush);
514 break;
515
516 case raiseFloorTurbo:
517 floor->direction = 1;
518 floor->sector = sec;
519 floor->speed = FLOORSPEED*4;
520 floor->floordestheight = P_FindNextHighestFloor(sec,sec->floorheight);
521 break;
522
523 case raiseFloorToNearest:
524 floor->direction = 1;
525 floor->sector = sec;
526 floor->speed = FLOORSPEED;
527 floor->floordestheight = P_FindNextHighestFloor(sec,sec->floorheight);
528 break;
529
530 case raiseFloor24:
531 floor->direction = 1;
532 floor->sector = sec;
533 floor->speed = FLOORSPEED;
534 floor->floordestheight = floor->sector->floorheight + 24 * FRACUNIT;
535 break;
536
537 // jff 2/03/30 support straight raise by 32 (fast)
538 case raiseFloor32Turbo:
539 floor->direction = 1;
540 floor->sector = sec;
541 floor->speed = FLOORSPEED*4;
542 floor->floordestheight = floor->sector->floorheight + 32 * FRACUNIT;
543 break;
544
545 case raiseFloor512:
546 floor->direction = 1;
547 floor->sector = sec;
548 floor->speed = FLOORSPEED;
549 floor->floordestheight = floor->sector->floorheight + 512 * FRACUNIT;
550 break;
551
552 case raiseFloor24AndChange:
553 floor->direction = 1;
554 floor->sector = sec;
555 floor->speed = FLOORSPEED;
556 floor->floordestheight = floor->sector->floorheight + 24 * FRACUNIT;
557 sec->floorpic = line->frontsector->floorpic;
558 sec->special = line->frontsector->special;
559 //jff 3/14/98 transfer both old and new special
560 sec->oldspecial = line->frontsector->oldspecial;
561 break;
562
563 case raiseToTexture:
564 {
565 int minsize = INT_MAX;
566 side_t* side;
567
568 /* jff 3/13/98 no ovf */
569 if (!comp[comp_model]) minsize = 32000<<FRACBITS;
570 floor->direction = 1;
571 floor->sector = sec;
572 floor->speed = FLOORSPEED;
573 for (i = 0; i < sec->linecount; i++)
574 {
575 if (twoSided (secnum, i) )
576 {
577 side = getSide(secnum,i,0);
578 // jff 8/14/98 don't scan texture 0, its not real
579 if (side->bottomtexture > 0 ||
580 (comp[comp_model] && !side->bottomtexture))
581 if (textureheight[side->bottomtexture] < minsize)
582 minsize = textureheight[side->bottomtexture];
583 side = getSide(secnum,i,1);
584 // jff 8/14/98 don't scan texture 0, its not real
585 if (side->bottomtexture > 0 ||
586 (comp[comp_model] && !side->bottomtexture))
587 if (textureheight[side->bottomtexture] < minsize)
588 minsize = textureheight[side->bottomtexture];
589 }
590 }
591 if (comp[comp_model])
592 floor->floordestheight = floor->sector->floorheight + minsize;
593 else
594 {
595 floor->floordestheight =
596 (floor->sector->floorheight>>FRACBITS) + (minsize>>FRACBITS);
597 if (floor->floordestheight>32000)
598 floor->floordestheight = 32000; //jff 3/13/98 do not
599 floor->floordestheight<<=FRACBITS; // allow height overflow
600 }
601 }
602 break;
603
604 case lowerAndChange:
605 floor->direction = -1;
606 floor->sector = sec;
607 floor->speed = FLOORSPEED;
608 floor->floordestheight = P_FindLowestFloorSurrounding(sec);
609 floor->texture = sec->floorpic;
610
611 // jff 1/24/98 make sure floor->newspecial gets initialized
612 // in case no surrounding sector is at floordestheight
613 // --> should not affect compatibility <--
614 floor->newspecial = sec->special;
615 //jff 3/14/98 transfer both old and new special
616 floor->oldspecial = sec->oldspecial;
617
618 //jff 5/23/98 use model subroutine to unify fixes and handling
619 sec = P_FindModelFloorSector(floor->floordestheight,sec-sectors);
620 if (sec)
621 {
622 floor->texture = sec->floorpic;
623 floor->newspecial = sec->special;
624 //jff 3/14/98 transfer both old and new special
625 floor->oldspecial = sec->oldspecial;
626 }
627 break;
628 default:
629 break;
630 }
631 }
632 return rtn;
633}
634
635//
636// EV_DoChange()
637//
638// Handle pure change types. These change floor texture and sector type
639// by trigger or numeric model without moving the floor.
640//
641// The linedef causing the change and the type of change is passed
642// Returns true if any sector changes
643//
644// jff 3/15/98 added to better support generalized sector types
645//
646int EV_DoChange
647( line_t* line,
648 change_e changetype )
649{
650 int secnum;
651 int rtn;
652 sector_t* sec;
653 sector_t* secm;
654
655 secnum = -1;
656 rtn = 0;
657 // change all sectors with the same tag as the linedef
658 while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0)
659 {
660 sec = &sectors[secnum];
661
662 rtn = 1;
663
664 // handle trigger or numeric change type
665 switch(changetype)
666 {
667 case trigChangeOnly:
668 sec->floorpic = line->frontsector->floorpic;
669 sec->special = line->frontsector->special;
670 sec->oldspecial = line->frontsector->oldspecial;
671 break;
672 case numChangeOnly:
673 secm = P_FindModelFloorSector(sec->floorheight,secnum);
674 if (secm) // if no model, no change
675 {
676 sec->floorpic = secm->floorpic;
677 sec->special = secm->special;
678 sec->oldspecial = secm->oldspecial;
679 }
680 break;
681 default:
682 break;
683 }
684 }
685 return rtn;
686}
687
688/*
689 * EV_BuildStairs()
690 *
691 * Handles staircase building. A sequence of sectors chosen by algorithm
692 * rise at a speed indicated to a height that increases by the stepsize
693 * each step.
694 *
695 * Passed the linedef triggering the stairs and the type of stair rise
696 * Returns true if any thinkers are created
697 *
698 * cph 2001/09/21 - compatibility nightmares again
699 * There are three different ways this function has, during its history, stepped
700 * through all the stairs to be triggered by the single switch
701 * - original Doom used a linear P_FindSectorFromLineTag, but failed to preserve
702 * the index of the previous sector found, so instead it would restart its
703 * linear search from the last sector of the previous staircase
704 * - MBF/PrBoom with comp_stairs fail to emulate this, because their
705 * P_FindSectorFromLineTag is a chained hash table implementation. Instead they
706 * start following the hash chain from the last sector of the previous
707 * staircase, which will (probably) have the wrong tag, so they miss any further
708 * stairs
709 * - Boom fixed the bug, and MBF/PrBoom without comp_stairs work right
710 */
711static inline int P_FindSectorFromLineTagWithLowerBound
712(line_t* l, int start, int min)
713{
714 /* Emulate original Doom's linear lower-bounded P_FindSectorFromLineTag
715 * as needed */
716 do {
717 start = P_FindSectorFromLineTag(l,start);
718 } while (start >= 0 && start <= min);
719 return start;
720}
721
722int EV_BuildStairs
723( line_t* line,
724 stair_e type )
725{
726 /* cph 2001/09/22 - cleaned up this function to save my sanity. A separate
727 * outer loop index makes the logic much cleared, and local variables moved
728 * into the inner blocks helps too */
729 int ssec = -1;
730 int minssec = -1;
731 int rtn = 0;
732
733 // start a stair at each sector tagged the same as the linedef
734 while ((ssec = P_FindSectorFromLineTagWithLowerBound(line,ssec,minssec)) >= 0)
735 {
736 int secnum = ssec;
737 sector_t* sec = &sectors[secnum];
738
739 // don't start a stair if the first step's floor is already moving
740 if (!P_SectorActive(floor_special,sec)) { //jff 2/22/98
741 floormove_t* floor;
742 int texture, height;
743 fixed_t stairsize;
744 fixed_t speed;
745 int ok;
746
747 // create new floor thinker for first step
748 rtn = 1;
749 floor = Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0);
750 P_AddThinker (&floor->thinker);
751 sec->floordata = floor;
752 floor->thinker.function = T_MoveFloor;
753 floor->direction = 1;
754 floor->sector = sec;
755 floor->type = buildStair; //jff 3/31/98 do not leave uninited
756
757 // set up the speed and stepsize according to the stairs type
758 switch(type)
759 {
760 default: // killough -- prevent compiler warning
761 case build8:
762 speed = FLOORSPEED/4;
763 stairsize = 8*FRACUNIT;
764 if (!demo_compatibility)
765 floor->crush = false; //jff 2/27/98 fix uninitialized crush field
766 break;
767 case turbo16:
768 speed = FLOORSPEED*4;
769 stairsize = 16*FRACUNIT;
770 if (!demo_compatibility)
771 floor->crush = true; //jff 2/27/98 fix uninitialized crush field
772 break;
773 }
774 floor->speed = speed;
775 height = sec->floorheight + stairsize;
776 floor->floordestheight = height;
777
778 texture = sec->floorpic;
779
780 // Find next sector to raise
781 // 1. Find 2-sided line with same sector side[0] (lowest numbered)
782 // 2. Other side is the next sector to raise
783 // 3. Unless already moving, or different texture, then stop building
784 do
785 {
786 int i;
787 ok = 0;
788
789 for (i = 0;i < sec->linecount;i++)
790 {
791 sector_t* tsec = (sec->lines[i])->frontsector;
792 int newsecnum;
793 if ( !((sec->lines[i])->flags & ML_TWOSIDED) )
794 continue;
795
796 newsecnum = tsec-sectors;
797
798 if (secnum != newsecnum)
799 continue;
800
801 tsec = (sec->lines[i])->backsector;
802 if (!tsec) continue; //jff 5/7/98 if no backside, continue
803 newsecnum = tsec - sectors;
804
805 // if sector's floor is different texture, look for another
806 if (tsec->floorpic != texture)
807 continue;
808
809 /* jff 6/19/98 prevent double stepsize
810 * killough 10/98: intentionally left this way [MBF comment]
811 * cph 2001/02/06: stair bug fix should be controlled by comp_stairs,
812 * except if we're emulating MBF which perversly reverted the fix
813 */
814 if (comp[comp_stairs] || (compatibility_level == mbf_compatibility))
815 height += stairsize; // jff 6/28/98 change demo compatibility
816
817 // if sector's floor already moving, look for another
818 if (P_SectorActive(floor_special,tsec)) //jff 2/22/98
819 continue;
820
821 /* cph - see comment above - do this iff we didn't do so above */
822 if (!comp[comp_stairs] && (compatibility_level != mbf_compatibility))
823 height += stairsize;
824
825 sec = tsec;
826 secnum = newsecnum;
827
828 // create and initialize a thinker for the next step
829 floor = Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0);
830 P_AddThinker (&floor->thinker);
831
832 sec->floordata = floor; //jff 2/22/98
833 floor->thinker.function = T_MoveFloor;
834 floor->direction = 1;
835 floor->sector = sec;
836 floor->speed = speed;
837 floor->floordestheight = height;
838 floor->type = buildStair; //jff 3/31/98 do not leave uninited
839 //jff 2/27/98 fix uninitialized crush field
840 if (!demo_compatibility)
841 floor->crush = type==build8? false : true;
842 ok = 1;
843 break;
844 }
845 } while(ok); // continue until no next step is found
846
847 }
848 /* killough 10/98: compatibility option */
849 if (comp[comp_stairs]) {
850 /* cph 2001/09/22 - emulate buggy MBF comp_stairs for demos, with logic
851 * reversed since we now have a separate outer loop index.
852 * DEMOSYNC - what about boom_compatibility_compatibility?
853 */
854 if ((compatibility_level >= mbf_compatibility) && (compatibility_level <
855 prboom_3_compatibility)) ssec = secnum; /* Trash outer loop index */
856 else {
857 /* cph 2001/09/22 - now the correct comp_stairs - Doom used a linear
858 * search from the last secnum, so we set that as a minimum value and do
859 * a fresh tag search
860 */
861 ssec = -1; minssec = secnum;
862 }
863 }
864 }
865 return rtn;
866}
867
868//
869// EV_DoDonut()
870//
871// Handle donut function: lower pillar, raise surrounding pool, both to height,
872// texture and type of the sector surrounding the pool.
873//
874// Passed the linedef that triggered the donut
875// Returns whether a thinker was created
876//
877int EV_DoDonut(line_t* line)
878{
879 sector_t* s1;
880 sector_t* s2;
881 sector_t* s3;
882 int secnum;
883 int rtn;
884 int i;
885 floormove_t* floor;
886
887 secnum = -1;
888 rtn = 0;
889 // do function on all sectors with same tag as linedef
890 while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0)
891 {
892 s1 = &sectors[secnum]; // s1 is pillar's sector
893
894 // do not start the donut if the pillar is already moving
895 if (P_SectorActive(floor_special,s1)) //jff 2/22/98
896 continue;
897
898 s2 = getNextSector(s1->lines[0],s1); // s2 is pool's sector
899 if (!s2) continue; // note lowest numbered line around
900 // pillar must be two-sided
901
902 /* do not start the donut if the pool is already moving
903 * cph - DEMOSYNC - was !compatibility */
904 if (!comp[comp_floors] && P_SectorActive(floor_special,s2))
905 continue; //jff 5/7/98
906
907 // find a two sided line around the pool whose other side isn't the pillar
908 for (i = 0;i < s2->linecount;i++)
909 {
910 //jff 3/29/98 use true two-sidedness, not the flag
911 // killough 4/5/98: changed demo_compatibility to compatibility
912 if (comp[comp_model])
913 {
914 if ((!s2->lines[i]->flags & ML_TWOSIDED) ||
915 (s2->lines[i]->backsector == s1))
916 continue;
917 }
918 else if (!s2->lines[i]->backsector || s2->lines[i]->backsector == s1)
919 continue;
920
921 rtn = 1; //jff 1/26/98 no donut action - no switch change on return
922
923 s3 = s2->lines[i]->backsector; // s3 is model sector for changes
924
925 // Spawn rising slime
926 floor = Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0);
927 P_AddThinker (&floor->thinker);
928 s2->floordata = floor; //jff 2/22/98
929 floor->thinker.function = T_MoveFloor;
930 floor->type = donutRaise;
931 floor->crush = false;
932 floor->direction = 1;
933 floor->sector = s2;
934 floor->speed = FLOORSPEED / 2;
935 floor->texture = s3->floorpic;
936 floor->newspecial = 0;
937 floor->floordestheight = s3->floorheight;
938
939 // Spawn lowering donut-hole pillar
940 floor = Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0);
941 P_AddThinker (&floor->thinker);
942 s1->floordata = floor; //jff 2/22/98
943 floor->thinker.function = T_MoveFloor;
944 floor->type = lowerFloor;
945 floor->crush = false;
946 floor->direction = -1;
947 floor->sector = s1;
948 floor->speed = FLOORSPEED / 2;
949 floor->floordestheight = s3->floorheight;
950 break;
951 }
952 }
953 return rtn;
954}
955
956//
957// EV_DoElevator
958//
959// Handle elevator linedef types
960//
961// Passed the linedef that triggered the elevator and the elevator action
962//
963// jff 2/22/98 new type to move floor and ceiling in parallel
964//
965int EV_DoElevator
966( line_t* line,
967 elevator_e elevtype )
968{
969 int secnum;
970 int rtn;
971 sector_t* sec;
972 elevator_t* elevator;
973
974 secnum = -1;
975 rtn = 0;
976 // act on all sectors with the same tag as the triggering linedef
977 while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0)
978 {
979 sec = &sectors[secnum];
980
981 // If either floor or ceiling is already activated, skip it
982 if (sec->floordata || sec->ceilingdata) //jff 2/22/98
983 continue;
984
985 // create and initialize new elevator thinker
986 rtn = 1;
987 elevator = Z_Malloc (sizeof(*elevator), PU_LEVSPEC, 0);
988 P_AddThinker (&elevator->thinker);
989 sec->floordata = elevator; //jff 2/22/98
990 sec->ceilingdata = elevator; //jff 2/22/98
991 elevator->thinker.function = T_MoveElevator;
992 elevator->type = elevtype;
993
994 // set up the fields according to the type of elevator action
995 switch(elevtype)
996 {
997 // elevator down to next floor
998 case elevateDown:
999 elevator->direction = -1;
1000 elevator->sector = sec;
1001 elevator->speed = ELEVATORSPEED;
1002 elevator->floordestheight =
1003 P_FindNextLowestFloor(sec,sec->floorheight);
1004 elevator->ceilingdestheight =
1005 elevator->floordestheight + sec->ceilingheight - sec->floorheight;
1006 break;
1007
1008 // elevator up to next floor
1009 case elevateUp:
1010 elevator->direction = 1;
1011 elevator->sector = sec;
1012 elevator->speed = ELEVATORSPEED;
1013 elevator->floordestheight =
1014 P_FindNextHighestFloor(sec,sec->floorheight);
1015 elevator->ceilingdestheight =
1016 elevator->floordestheight + sec->ceilingheight - sec->floorheight;
1017 break;
1018
1019 // elevator to floor height of activating switch's front sector
1020 case elevateCurrent:
1021 elevator->sector = sec;
1022 elevator->speed = ELEVATORSPEED;
1023 elevator->floordestheight = line->frontsector->floorheight;
1024 elevator->ceilingdestheight =
1025 elevator->floordestheight + sec->ceilingheight - sec->floorheight;
1026 elevator->direction =
1027 elevator->floordestheight>sec->floorheight? 1 : -1;
1028 break;
1029
1030 default:
1031 break;
1032 }
1033 }
1034 return rtn;
1035}
diff --git a/apps/plugins/doom/p_genlin.c b/apps/plugins/doom/p_genlin.c
new file mode 100644
index 0000000000..a521210c64
--- /dev/null
+++ b/apps/plugins/doom/p_genlin.c
@@ -0,0 +1,1154 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION:
28 * Generalized linedef type handlers
29 * Floors, Ceilings, Doors, Locked Doors, Lifts, Stairs, Crushers
30 *
31 *-----------------------------------------------------------------------------*/
32
33#include "doomstat.h" //jff 6/19/98 for demo_compatibility
34#include "r_main.h"
35#include "p_spec.h"
36#include "p_tick.h"
37#include "m_random.h"
38#include "s_sound.h"
39#include "sounds.h"
40
41//////////////////////////////////////////////////////////
42//
43// Generalized Linedef Type handlers
44//
45//////////////////////////////////////////////////////////
46
47//
48// EV_DoGenFloor()
49//
50// Handle generalized floor types
51//
52// Passed the line activating the generalized floor function
53// Returns true if a thinker is created
54//
55// jff 02/04/98 Added this routine (and file) to handle generalized
56// floor movers using bit fields in the line special type.
57//
58int EV_DoGenFloor
59( line_t* line )
60{
61 int secnum;
62 int rtn;
63 boolean manual;
64 sector_t* sec;
65 floormove_t* floor;
66 unsigned value = (unsigned)line->special - GenFloorBase;
67
68 // parse the bit fields in the line's special type
69
70 int Crsh = (value & FloorCrush) >> FloorCrushShift;
71 int ChgT = (value & FloorChange) >> FloorChangeShift;
72 int Targ = (value & FloorTarget) >> FloorTargetShift;
73 int Dirn = (value & FloorDirection) >> FloorDirectionShift;
74 int ChgM = (value & FloorModel) >> FloorModelShift;
75 int Sped = (value & FloorSpeed) >> FloorSpeedShift;
76 int Trig = (value & TriggerType) >> TriggerTypeShift;
77
78 rtn = 0;
79
80 // check if a manual trigger, if so do just the sector on the backside
81 manual = false;
82 if (Trig==PushOnce || Trig==PushMany)
83 {
84 if (!(sec = line->backsector))
85 return rtn;
86 secnum = sec-sectors;
87 manual = true;
88 goto manual_floor;
89 }
90
91 secnum = -1;
92 // if not manual do all sectors tagged the same as the line
93 while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0)
94 {
95 sec = &sectors[secnum];
96
97manual_floor:
98 // Do not start another function if floor already moving
99 if (P_SectorActive(floor_special,sec))
100 {
101 if (!manual)
102 continue;
103 else
104 return rtn;
105 }
106
107 // new floor thinker
108 rtn = 1;
109 floor = Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0);
110 P_AddThinker (&floor->thinker);
111 sec->floordata = floor;
112 floor->thinker.function = T_MoveFloor;
113 floor->crush = Crsh;
114 floor->direction = Dirn? 1 : -1;
115 floor->sector = sec;
116 floor->texture = sec->floorpic;
117 floor->newspecial = sec->special;
118 //jff 3/14/98 transfer old special field too
119 floor->oldspecial = sec->oldspecial;
120 floor->type = genFloor;
121
122 // set the speed of motion
123 switch (Sped)
124 {
125 case SpeedSlow:
126 floor->speed = FLOORSPEED;
127 break;
128 case SpeedNormal:
129 floor->speed = FLOORSPEED*2;
130 break;
131 case SpeedFast:
132 floor->speed = FLOORSPEED*4;
133 break;
134 case SpeedTurbo:
135 floor->speed = FLOORSPEED*8;
136 break;
137 default:
138 break;
139 }
140
141 // set the destination height
142 switch(Targ)
143 {
144 case FtoHnF:
145 floor->floordestheight = P_FindHighestFloorSurrounding(sec);
146 break;
147 case FtoLnF:
148 floor->floordestheight = P_FindLowestFloorSurrounding(sec);
149 break;
150 case FtoNnF:
151 floor->floordestheight = Dirn?
152 P_FindNextHighestFloor(sec,sec->floorheight) :
153 P_FindNextLowestFloor(sec,sec->floorheight);
154 break;
155 case FtoLnC:
156 floor->floordestheight = P_FindLowestCeilingSurrounding(sec);
157 break;
158 case FtoC:
159 floor->floordestheight = sec->ceilingheight;
160 break;
161 case FbyST:
162 floor->floordestheight = (floor->sector->floorheight>>FRACBITS) +
163 floor->direction * (P_FindShortestTextureAround(secnum)>>FRACBITS);
164 if (floor->floordestheight>32000) //jff 3/13/98 prevent overflow
165 floor->floordestheight=32000; // wraparound in floor height
166 if (floor->floordestheight<-32000)
167 floor->floordestheight=-32000;
168 floor->floordestheight<<=FRACBITS;
169 break;
170 case Fby24:
171 floor->floordestheight = floor->sector->floorheight +
172 floor->direction * 24*FRACUNIT;
173 break;
174 case Fby32:
175 floor->floordestheight = floor->sector->floorheight +
176 floor->direction * 32*FRACUNIT;
177 break;
178 default:
179 break;
180 }
181
182 // set texture/type change properties
183 if (ChgT) // if a texture change is indicated
184 {
185 if (ChgM) // if a numeric model change
186 {
187 sector_t *sec;
188
189 //jff 5/23/98 find model with ceiling at target height if target
190 //is a ceiling type
191 sec = (Targ==FtoLnC || Targ==FtoC)?
192 P_FindModelCeilingSector(floor->floordestheight,secnum) :
193 P_FindModelFloorSector(floor->floordestheight,secnum);
194 if (sec)
195 {
196 floor->texture = sec->floorpic;
197 switch(ChgT)
198 {
199 case FChgZero: // zero type
200 floor->newspecial = 0;
201 //jff 3/14/98 change old field too
202 floor->oldspecial = 0;
203 floor->type = genFloorChg0;
204 break;
205 case FChgTyp: // copy type
206 floor->newspecial = sec->special;
207 //jff 3/14/98 change old field too
208 floor->oldspecial = sec->oldspecial;
209 floor->type = genFloorChgT;
210 break;
211 case FChgTxt: // leave type be
212 floor->type = genFloorChg;
213 break;
214 default:
215 break;
216 }
217 }
218 }
219 else // else if a trigger model change
220 {
221 floor->texture = line->frontsector->floorpic;
222 switch (ChgT)
223 {
224 case FChgZero: // zero type
225 floor->newspecial = 0;
226 //jff 3/14/98 change old field too
227 floor->oldspecial = 0;
228 floor->type = genFloorChg0;
229 break;
230 case FChgTyp: // copy type
231 floor->newspecial = line->frontsector->special;
232 //jff 3/14/98 change old field too
233 floor->oldspecial = line->frontsector->oldspecial;
234 floor->type = genFloorChgT;
235 break;
236 case FChgTxt: // leave type be
237 floor->type = genFloorChg;
238 default:
239 break;
240 }
241 }
242 }
243 if (manual) return rtn;
244 }
245 return rtn;
246}
247
248
249//
250// EV_DoGenCeiling()
251//
252// Handle generalized ceiling types
253//
254// Passed the linedef activating the ceiling function
255// Returns true if a thinker created
256//
257// jff 02/04/98 Added this routine (and file) to handle generalized
258// floor movers using bit fields in the line special type.
259//
260int EV_DoGenCeiling
261( line_t* line )
262{
263 int secnum;
264 int rtn;
265 boolean manual;
266 fixed_t targheight;
267 sector_t* sec;
268 ceiling_t* ceiling;
269 unsigned value = (unsigned)line->special - GenCeilingBase;
270
271 // parse the bit fields in the line's special type
272
273 int Crsh = (value & CeilingCrush) >> CeilingCrushShift;
274 int ChgT = (value & CeilingChange) >> CeilingChangeShift;
275 int Targ = (value & CeilingTarget) >> CeilingTargetShift;
276 int Dirn = (value & CeilingDirection) >> CeilingDirectionShift;
277 int ChgM = (value & CeilingModel) >> CeilingModelShift;
278 int Sped = (value & CeilingSpeed) >> CeilingSpeedShift;
279 int Trig = (value & TriggerType) >> TriggerTypeShift;
280
281 rtn = 0;
282
283 // check if a manual trigger, if so do just the sector on the backside
284 manual = false;
285 if (Trig==PushOnce || Trig==PushMany)
286 {
287 if (!(sec = line->backsector))
288 return rtn;
289 secnum = sec-sectors;
290 manual = true;
291 goto manual_ceiling;
292 }
293
294 secnum = -1;
295 // if not manual do all sectors tagged the same as the line
296 while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0)
297 {
298 sec = &sectors[secnum];
299
300manual_ceiling:
301 // Do not start another function if ceiling already moving
302 if (P_SectorActive(ceiling_special,sec)) //jff 2/22/98
303 {
304 if (!manual)
305 continue;
306 else
307 return rtn;
308 }
309
310 // new ceiling thinker
311 rtn = 1;
312 ceiling = Z_Malloc (sizeof(*ceiling), PU_LEVSPEC, 0);
313 P_AddThinker (&ceiling->thinker);
314 sec->ceilingdata = ceiling; //jff 2/22/98
315 ceiling->thinker.function = T_MoveCeiling;
316 ceiling->crush = Crsh;
317 ceiling->direction = Dirn? 1 : -1;
318 ceiling->sector = sec;
319 ceiling->texture = sec->ceilingpic;
320 ceiling->newspecial = sec->special;
321 //jff 3/14/98 change old field too
322 ceiling->oldspecial = sec->oldspecial;
323 ceiling->tag = sec->tag;
324 ceiling->type = genCeiling;
325
326 // set speed of motion
327 switch (Sped)
328 {
329 case SpeedSlow:
330 ceiling->speed = CEILSPEED;
331 break;
332 case SpeedNormal:
333 ceiling->speed = CEILSPEED*2;
334 break;
335 case SpeedFast:
336 ceiling->speed = CEILSPEED*4;
337 break;
338 case SpeedTurbo:
339 ceiling->speed = CEILSPEED*8;
340 break;
341 default:
342 break;
343 }
344
345 // set destination target height
346 targheight = sec->ceilingheight;
347 switch(Targ)
348 {
349 case CtoHnC:
350 targheight = P_FindHighestCeilingSurrounding(sec);
351 break;
352 case CtoLnC:
353 targheight = P_FindLowestCeilingSurrounding(sec);
354 break;
355 case CtoNnC:
356 targheight = Dirn?
357 P_FindNextHighestCeiling(sec,sec->ceilingheight) :
358 P_FindNextLowestCeiling(sec,sec->ceilingheight);
359 break;
360 case CtoHnF:
361 targheight = P_FindHighestFloorSurrounding(sec);
362 break;
363 case CtoF:
364 targheight = sec->floorheight;
365 break;
366 case CbyST:
367 targheight = (ceiling->sector->ceilingheight>>FRACBITS) +
368 ceiling->direction * (P_FindShortestUpperAround(secnum)>>FRACBITS);
369 if (targheight>32000) //jff 3/13/98 prevent overflow
370 targheight=32000; // wraparound in ceiling height
371 if (targheight<-32000)
372 targheight=-32000;
373 targheight<<=FRACBITS;
374 break;
375 case Cby24:
376 targheight = ceiling->sector->ceilingheight +
377 ceiling->direction * 24*FRACUNIT;
378 break;
379 case Cby32:
380 targheight = ceiling->sector->ceilingheight +
381 ceiling->direction * 32*FRACUNIT;
382 break;
383 default:
384 break;
385 }
386 if (Dirn) ceiling->topheight = targheight;
387 else ceiling->bottomheight = targheight;
388
389 // set texture/type change properties
390 if (ChgT) // if a texture change is indicated
391 {
392 if (ChgM) // if a numeric model change
393 {
394 sector_t *sec;
395
396 //jff 5/23/98 find model with floor at target height if target
397 //is a floor type
398 sec = (Targ==CtoHnF || Targ==CtoF)?
399 P_FindModelFloorSector(targheight,secnum) :
400 P_FindModelCeilingSector(targheight,secnum);
401 if (sec)
402 {
403 ceiling->texture = sec->ceilingpic;
404 switch (ChgT)
405 {
406 case CChgZero: // type is zeroed
407 ceiling->newspecial = 0;
408 //jff 3/14/98 change old field too
409 ceiling->oldspecial = 0;
410 ceiling->type = genCeilingChg0;
411 break;
412 case CChgTyp: // type is copied
413 ceiling->newspecial = sec->special;
414 //jff 3/14/98 change old field too
415 ceiling->oldspecial = sec->oldspecial;
416 ceiling->type = genCeilingChgT;
417 break;
418 case CChgTxt: // type is left alone
419 ceiling->type = genCeilingChg;
420 break;
421 default:
422 break;
423 }
424 }
425 }
426 else // else if a trigger model change
427 {
428 ceiling->texture = line->frontsector->ceilingpic;
429 switch (ChgT)
430 {
431 case CChgZero: // type is zeroed
432 ceiling->newspecial = 0;
433 //jff 3/14/98 change old field too
434 ceiling->oldspecial = 0;
435 ceiling->type = genCeilingChg0;
436 break;
437 case CChgTyp: // type is copied
438 ceiling->newspecial = line->frontsector->special;
439 //jff 3/14/98 change old field too
440 ceiling->oldspecial = line->frontsector->oldspecial;
441 ceiling->type = genCeilingChgT;
442 break;
443 case CChgTxt: // type is left alone
444 ceiling->type = genCeilingChg;
445 break;
446 default:
447 break;
448 }
449 }
450 }
451 P_AddActiveCeiling(ceiling); // add this ceiling to the active list
452 if (manual) return rtn;
453 }
454 return rtn;
455}
456
457//
458// EV_DoGenLift()
459//
460// Handle generalized lift types
461//
462// Passed the linedef activating the lift
463// Returns true if a thinker is created
464//
465int EV_DoGenLift
466( line_t* line )
467{
468 plat_t* plat;
469 int secnum;
470 int rtn;
471 boolean manual;
472 sector_t* sec;
473 unsigned value = (unsigned)line->special - GenLiftBase;
474
475 // parse the bit fields in the line's special type
476
477 int Targ = (value & LiftTarget) >> LiftTargetShift;
478 int Dely = (value & LiftDelay) >> LiftDelayShift;
479 int Sped = (value & LiftSpeed) >> LiftSpeedShift;
480 int Trig = (value & TriggerType) >> TriggerTypeShift;
481
482 secnum = -1;
483 rtn = 0;
484
485 // Activate all <type> plats that are in_stasis
486
487 if (Targ==LnF2HnF)
488 P_ActivateInStasis(line->tag);
489
490 // check if a manual trigger, if so do just the sector on the backside
491 manual = false;
492 if (Trig==PushOnce || Trig==PushMany)
493 {
494 if (!(sec = line->backsector))
495 return rtn;
496 secnum = sec-sectors;
497 manual = true;
498 goto manual_lift;
499 }
500
501 // if not manual do all sectors tagged the same as the line
502 while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0)
503 {
504 sec = &sectors[secnum];
505
506manual_lift:
507 // Do not start another function if floor already moving
508 if (P_SectorActive(floor_special,sec))
509 {
510 if (!manual)
511 continue;
512 else
513 return rtn;
514 }
515
516 // Setup the plat thinker
517 rtn = 1;
518 plat = Z_Malloc( sizeof(*plat), PU_LEVSPEC, 0);
519 P_AddThinker(&plat->thinker);
520
521 plat->sector = sec;
522 plat->sector->floordata = plat;
523 plat->thinker.function = T_PlatRaise;
524 plat->crush = false;
525 plat->tag = line->tag;
526
527 plat->type = genLift;
528 plat->high = sec->floorheight;
529 plat->status = down;
530
531 // setup the target destination height
532 switch(Targ)
533 {
534 case F2LnF:
535 plat->low = P_FindLowestFloorSurrounding(sec);
536 if (plat->low > sec->floorheight)
537 plat->low = sec->floorheight;
538 break;
539 case F2NnF:
540 plat->low = P_FindNextLowestFloor(sec,sec->floorheight);
541 break;
542 case F2LnC:
543 plat->low = P_FindLowestCeilingSurrounding(sec);
544 if (plat->low > sec->floorheight)
545 plat->low = sec->floorheight;
546 break;
547 case LnF2HnF:
548 plat->type = genPerpetual;
549 plat->low = P_FindLowestFloorSurrounding(sec);
550 if (plat->low > sec->floorheight)
551 plat->low = sec->floorheight;
552 plat->high = P_FindHighestFloorSurrounding(sec);
553 if (plat->high < sec->floorheight)
554 plat->high = sec->floorheight;
555 plat->status = P_Random(pr_genlift)&1;
556 break;
557 default:
558 break;
559 }
560
561 // setup the speed of motion
562 switch(Sped)
563 {
564 case SpeedSlow:
565 plat->speed = PLATSPEED * 2;
566 break;
567 case SpeedNormal:
568 plat->speed = PLATSPEED * 4;
569 break;
570 case SpeedFast:
571 plat->speed = PLATSPEED * 8;
572 break;
573 case SpeedTurbo:
574 plat->speed = PLATSPEED * 16;
575 break;
576 default:
577 break;
578 }
579
580 // setup the delay time before the floor returns
581 switch(Dely)
582 {
583 case 0:
584 plat->wait = 1*35;
585 break;
586 case 1:
587 plat->wait = PLATWAIT*35;
588 break;
589 case 2:
590 plat->wait = 5*35;
591 break;
592 case 3:
593 plat->wait = 10*35;
594 break;
595 }
596
597 S_StartSound((mobj_t *)&sec->soundorg,sfx_pstart);
598 P_AddActivePlat(plat); // add this plat to the list of active plats
599
600 if (manual)
601 return rtn;
602 }
603 return rtn;
604}
605
606//
607// EV_DoGenStairs()
608//
609// Handle generalized stair building
610//
611// Passed the linedef activating the stairs
612// Returns true if a thinker is created
613//
614int EV_DoGenStairs
615( line_t* line )
616{
617 int secnum;
618 int osecnum; //jff 3/4/98 preserve loop index
619 int height;
620 int i;
621 int newsecnum;
622 int texture;
623 int ok;
624 int rtn;
625 boolean manual;
626
627 sector_t* sec;
628 sector_t* tsec;
629
630 floormove_t* floor;
631
632 fixed_t stairsize;
633 fixed_t speed;
634
635 unsigned value = (unsigned)line->special - GenStairsBase;
636
637 // parse the bit fields in the line's special type
638
639 int Igno = (value & StairIgnore) >> StairIgnoreShift;
640 int Dirn = (value & StairDirection) >> StairDirectionShift;
641 int Step = (value & StairStep) >> StairStepShift;
642 int Sped = (value & StairSpeed) >> StairSpeedShift;
643 int Trig = (value & TriggerType) >> TriggerTypeShift;
644
645 rtn = 0;
646
647 // check if a manual trigger, if so do just the sector on the backside
648 manual = false;
649 if (Trig==PushOnce || Trig==PushMany)
650 {
651 if (!(sec = line->backsector))
652 return rtn;
653 secnum = sec-sectors;
654 manual = true;
655 goto manual_stair;
656 }
657
658 secnum = -1;
659 // if not manual do all sectors tagged the same as the line
660 while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0)
661 {
662 sec = &sectors[secnum];
663
664manual_stair:
665 //Do not start another function if floor already moving
666 //jff 2/26/98 add special lockout condition to wait for entire
667 //staircase to build before retriggering
668 if (P_SectorActive(floor_special,sec) || sec->stairlock)
669 {
670 if (!manual)
671 continue;
672 else
673 return rtn;
674 }
675
676 // new floor thinker
677 rtn = 1;
678 floor = Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0);
679 P_AddThinker (&floor->thinker);
680 sec->floordata = floor;
681 floor->thinker.function = T_MoveFloor;
682 floor->direction = Dirn? 1 : -1;
683 floor->sector = sec;
684
685 // setup speed of stair building
686 switch(Sped)
687 {
688 default:
689 case SpeedSlow:
690 floor->speed = FLOORSPEED/4;
691 break;
692 case SpeedNormal:
693 floor->speed = FLOORSPEED/2;
694 break;
695 case SpeedFast:
696 floor->speed = FLOORSPEED*2;
697 break;
698 case SpeedTurbo:
699 floor->speed = FLOORSPEED*4;
700 break;
701 }
702
703 // setup stepsize for stairs
704 switch(Step)
705 {
706 default:
707 case 0:
708 stairsize = 4*FRACUNIT;
709 break;
710 case 1:
711 stairsize = 8*FRACUNIT;
712 break;
713 case 2:
714 stairsize = 16*FRACUNIT;
715 break;
716 case 3:
717 stairsize = 24*FRACUNIT;
718 break;
719 }
720
721 speed = floor->speed;
722 height = sec->floorheight + floor->direction * stairsize;
723 floor->floordestheight = height;
724 texture = sec->floorpic;
725 floor->crush = false;
726 floor->type = genBuildStair; // jff 3/31/98 do not leave uninited
727
728 sec->stairlock = -2; // jff 2/26/98 set up lock on current sector
729 sec->nextsec = -1;
730 sec->prevsec = -1;
731
732 osecnum = secnum; //jff 3/4/98 preserve loop index
733 // Find next sector to raise
734 // 1. Find 2-sided line with same sector side[0]
735 // 2. Other side is the next sector to raise
736 do
737 {
738 ok = 0;
739 for (i = 0;i < sec->linecount;i++)
740 {
741 if ( !((sec->lines[i])->backsector) )
742 continue;
743
744 tsec = (sec->lines[i])->frontsector;
745 newsecnum = tsec-sectors;
746
747 if (secnum != newsecnum)
748 continue;
749
750 tsec = (sec->lines[i])->backsector;
751 newsecnum = tsec - sectors;
752
753 if (!Igno && tsec->floorpic != texture)
754 continue;
755
756 /* jff 6/19/98 prevent double stepsize */
757 if (compatibility_level < boom_202_compatibility)
758 height += floor->direction * stairsize;
759
760 //jff 2/26/98 special lockout condition for retriggering
761 if (P_SectorActive(floor_special,tsec) || tsec->stairlock)
762 continue;
763
764 /* jff 6/19/98 increase height AFTER continue */
765 if (compatibility_level >= boom_202_compatibility)
766 height += floor->direction * stairsize;
767
768 // jff 2/26/98
769 // link the stair chain in both directions
770 // lock the stair sector until building complete
771 sec->nextsec = newsecnum; // link step to next
772 tsec->prevsec = secnum; // link next back
773 tsec->nextsec = -1; // set next forward link as end
774 tsec->stairlock = -2; // lock the step
775
776 sec = tsec;
777 secnum = newsecnum;
778 floor = Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0);
779
780 P_AddThinker (&floor->thinker);
781
782 sec->floordata = floor;
783 floor->thinker.function = T_MoveFloor;
784 floor->direction = Dirn? 1 : -1;
785 floor->sector = sec;
786 floor->speed = speed;
787 floor->floordestheight = height;
788 floor->crush = false;
789 floor->type = genBuildStair; // jff 3/31/98 do not leave uninited
790
791 ok = 1;
792 break;
793 }
794 } while(ok);
795 if (manual)
796 return rtn;
797 secnum = osecnum; //jff 3/4/98 restore old loop index
798 }
799 // retriggerable generalized stairs build up or down alternately
800 if (rtn)
801 line->special ^= StairDirection; // alternate dir on succ activations
802 return rtn;
803}
804
805//
806// EV_DoGenCrusher()
807//
808// Handle generalized crusher types
809//
810// Passed the linedef activating the crusher
811// Returns true if a thinker created
812//
813int EV_DoGenCrusher
814( line_t* line )
815{
816 int secnum;
817 int rtn;
818 boolean manual;
819 sector_t* sec;
820 ceiling_t* ceiling;
821 unsigned value = (unsigned)line->special - GenCrusherBase;
822
823 // parse the bit fields in the line's special type
824
825 int Slnt = (value & CrusherSilent) >> CrusherSilentShift;
826 int Sped = (value & CrusherSpeed) >> CrusherSpeedShift;
827 int Trig = (value & TriggerType) >> TriggerTypeShift;
828
829 //jff 2/22/98 Reactivate in-stasis ceilings...for certain types.
830 //jff 4/5/98 return if activated
831 rtn = P_ActivateInStasisCeiling(line);
832
833 // check if a manual trigger, if so do just the sector on the backside
834 manual = false;
835 if (Trig==PushOnce || Trig==PushMany)
836 {
837 if (!(sec = line->backsector))
838 return rtn;
839 secnum = sec-sectors;
840 manual = true;
841 goto manual_crusher;
842 }
843
844 secnum = -1;
845 // if not manual do all sectors tagged the same as the line
846 while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0)
847 {
848 sec = &sectors[secnum];
849
850manual_crusher:
851 // Do not start another function if ceiling already moving
852 if (P_SectorActive(ceiling_special,sec)) //jff 2/22/98
853 {
854 if (!manual)
855 continue;
856 else
857 return rtn;
858 }
859
860 // new ceiling thinker
861 rtn = 1;
862 ceiling = Z_Malloc (sizeof(*ceiling), PU_LEVSPEC, 0);
863 P_AddThinker (&ceiling->thinker);
864 sec->ceilingdata = ceiling; //jff 2/22/98
865 ceiling->thinker.function = T_MoveCeiling;
866 ceiling->crush = true;
867 ceiling->direction = -1;
868 ceiling->sector = sec;
869 ceiling->texture = sec->ceilingpic;
870 ceiling->newspecial = sec->special;
871 ceiling->tag = sec->tag;
872 ceiling->type = Slnt? genSilentCrusher : genCrusher;
873 ceiling->topheight = sec->ceilingheight;
874 ceiling->bottomheight = sec->floorheight + (8*FRACUNIT);
875
876 // setup ceiling motion speed
877 switch (Sped)
878 {
879 case SpeedSlow:
880 ceiling->speed = CEILSPEED;
881 break;
882 case SpeedNormal:
883 ceiling->speed = CEILSPEED*2;
884 break;
885 case SpeedFast:
886 ceiling->speed = CEILSPEED*4;
887 break;
888 case SpeedTurbo:
889 ceiling->speed = CEILSPEED*8;
890 break;
891 default:
892 break;
893 }
894 ceiling->oldspeed=ceiling->speed;
895
896 P_AddActiveCeiling(ceiling); // add to list of active ceilings
897 if (manual) return rtn;
898 }
899 return rtn;
900}
901
902//
903// EV_DoGenLockedDoor()
904//
905// Handle generalized locked door types
906//
907// Passed the linedef activating the generalized locked door
908// Returns true if a thinker created
909//
910int EV_DoGenLockedDoor
911( line_t* line )
912{
913 int secnum,rtn;
914 sector_t* sec;
915 vldoor_t* door;
916 boolean manual;
917 unsigned value = (unsigned)line->special - GenLockedBase;
918
919 // parse the bit fields in the line's special type
920
921 int Kind = (value & LockedKind) >> LockedKindShift;
922 int Sped = (value & LockedSpeed) >> LockedSpeedShift;
923 int Trig = (value & TriggerType) >> TriggerTypeShift;
924
925 rtn = 0;
926
927 // check if a manual trigger, if so do just the sector on the backside
928 manual = false;
929 if (Trig==PushOnce || Trig==PushMany)
930 {
931 if (!(sec = line->backsector))
932 return rtn;
933 secnum = sec-sectors;
934 manual = true;
935 goto manual_locked;
936 }
937
938 secnum = -1;
939 rtn = 0;
940
941 // if not manual do all sectors tagged the same as the line
942 while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0)
943 {
944 sec = &sectors[secnum];
945manual_locked:
946 // Do not start another function if ceiling already moving
947 if (P_SectorActive(ceiling_special,sec)) //jff 2/22/98
948 {
949 if (!manual)
950 continue;
951 else
952 return rtn;
953 }
954
955 // new door thinker
956 rtn = 1;
957 door = Z_Malloc (sizeof(*door), PU_LEVSPEC, 0);
958 P_AddThinker (&door->thinker);
959 sec->ceilingdata = door; //jff 2/22/98
960
961 door->thinker.function = T_VerticalDoor;
962 door->sector = sec;
963 door->topwait = VDOORWAIT;
964 door->line = line;
965 door->topheight = P_FindLowestCeilingSurrounding(sec);
966 door->topheight -= 4*FRACUNIT;
967 door->direction = 1;
968
969 /* killough 10/98: implement gradual lighting */
970 door->lighttag = !comp[comp_doorlight] &&
971 (line->special&6) == 6 &&
972 line->special > GenLockedBase ? line->tag : 0;
973
974 // setup speed of door motion
975 switch(Sped)
976 {
977 default:
978 case SpeedSlow:
979 door->type = Kind? genOpen : genRaise;
980 door->speed = VDOORSPEED;
981 break;
982 case SpeedNormal:
983 door->type = Kind? genOpen : genRaise;
984 door->speed = VDOORSPEED*2;
985 break;
986 case SpeedFast:
987 door->type = Kind? genBlazeOpen : genBlazeRaise;
988 door->speed = VDOORSPEED*4;
989 break;
990 case SpeedTurbo:
991 door->type = Kind? genBlazeOpen : genBlazeRaise;
992 door->speed = VDOORSPEED*8;
993
994 break;
995 }
996
997 // killough 4/15/98: fix generalized door opening sounds
998 // (previously they always had the blazing door close sound)
999
1000 S_StartSound((mobj_t *)&door->sector->soundorg, // killough 4/15/98
1001 door->speed >= VDOORSPEED*4 ? sfx_bdopn : sfx_doropn);
1002
1003 if (manual)
1004 return rtn;
1005 }
1006 return rtn;
1007}
1008
1009//
1010// EV_DoGenDoor()
1011//
1012// Handle generalized door types
1013//
1014// Passed the linedef activating the generalized door
1015// Returns true if a thinker created
1016//
1017int EV_DoGenDoor
1018( line_t* line )
1019{
1020 int secnum,rtn;
1021 sector_t* sec;
1022 boolean manual;
1023 vldoor_t* door;
1024 unsigned value = (unsigned)line->special - GenDoorBase;
1025
1026 // parse the bit fields in the line's special type
1027
1028 int Dely = (value & DoorDelay) >> DoorDelayShift;
1029 int Kind = (value & DoorKind) >> DoorKindShift;
1030 int Sped = (value & DoorSpeed) >> DoorSpeedShift;
1031 int Trig = (value & TriggerType) >> TriggerTypeShift;
1032
1033 rtn = 0;
1034
1035 // check if a manual trigger, if so do just the sector on the backside
1036 manual = false;
1037 if (Trig==PushOnce || Trig==PushMany)
1038 {
1039 if (!(sec = line->backsector))
1040 return rtn;
1041 secnum = sec-sectors;
1042 manual = true;
1043 goto manual_door;
1044 }
1045
1046
1047 secnum = -1;
1048 rtn = 0;
1049
1050 // if not manual do all sectors tagged the same as the line
1051 while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0)
1052 {
1053 sec = &sectors[secnum];
1054manual_door:
1055 // Do not start another function if ceiling already moving
1056 if (P_SectorActive(ceiling_special,sec)) //jff 2/22/98
1057 {
1058 if (!manual)
1059 continue;
1060 else
1061 return rtn;
1062 }
1063
1064 // new door thinker
1065 rtn = 1;
1066 door = Z_Malloc (sizeof(*door), PU_LEVSPEC, 0);
1067 P_AddThinker (&door->thinker);
1068 sec->ceilingdata = door; //jff 2/22/98
1069
1070 door->thinker.function = T_VerticalDoor;
1071 door->sector = sec;
1072 // setup delay for door remaining open/closed
1073 switch(Dely)
1074 {
1075 default:
1076 case 0:
1077 door->topwait = 35;
1078 break;
1079 case 1:
1080 door->topwait = VDOORWAIT;
1081 break;
1082 case 2:
1083 door->topwait = 2*VDOORWAIT;
1084 break;
1085 case 3:
1086 door->topwait = 7*VDOORWAIT;
1087 break;
1088 }
1089
1090 // setup speed of door motion
1091 switch(Sped)
1092 {
1093 default:
1094 case SpeedSlow:
1095 door->speed = VDOORSPEED;
1096 break;
1097 case SpeedNormal:
1098 door->speed = VDOORSPEED*2;
1099 break;
1100 case SpeedFast:
1101 door->speed = VDOORSPEED*4;
1102 break;
1103 case SpeedTurbo:
1104 door->speed = VDOORSPEED*8;
1105 break;
1106 }
1107 door->line = line; // jff 1/31/98 remember line that triggered us
1108
1109 /* killough 10/98: implement gradual lighting */
1110 door->lighttag = !comp[comp_doorlight] &&
1111 (line->special&6) == 6 &&
1112 line->special > GenLockedBase ? line->tag : 0;
1113
1114 // set kind of door, whether it opens then close, opens, closes etc.
1115 // assign target heights accordingly
1116 switch(Kind)
1117 {
1118 case OdCDoor:
1119 door->direction = 1;
1120 door->topheight = P_FindLowestCeilingSurrounding(sec);
1121 door->topheight -= 4*FRACUNIT;
1122 if (door->topheight != sec->ceilingheight)
1123 S_StartSound((mobj_t *)&door->sector->soundorg,Sped>=SpeedFast || comp[comp_sound] ? sfx_bdopn : sfx_doropn);
1124 door->type = Sped>=SpeedFast? genBlazeRaise : genRaise;
1125 break;
1126 case ODoor:
1127 door->direction = 1;
1128 door->topheight = P_FindLowestCeilingSurrounding(sec);
1129 door->topheight -= 4*FRACUNIT;
1130 if (door->topheight != sec->ceilingheight)
1131 S_StartSound((mobj_t *)&door->sector->soundorg,Sped>=SpeedFast || comp[comp_sound] ? sfx_bdopn : sfx_doropn);
1132 door->type = Sped>=SpeedFast? genBlazeOpen : genOpen;
1133 break;
1134 case CdODoor:
1135 door->topheight = sec->ceilingheight;
1136 door->direction = -1;
1137 S_StartSound((mobj_t *)&door->sector->soundorg,Sped>=SpeedFast && !comp[comp_sound] ? sfx_bdcls : sfx_dorcls);
1138 door->type = Sped>=SpeedFast? genBlazeCdO : genCdO;
1139 break;
1140 case CDoor:
1141 door->topheight = P_FindLowestCeilingSurrounding(sec);
1142 door->topheight -= 4*FRACUNIT;
1143 door->direction = -1;
1144 S_StartSound((mobj_t *)&door->sector->soundorg,Sped>=SpeedFast && !comp[comp_sound] ? sfx_bdcls : sfx_dorcls);
1145 door->type = Sped>=SpeedFast? genBlazeClose : genClose;
1146 break;
1147 default:
1148 break;
1149 }
1150 if (manual)
1151 return rtn;
1152 }
1153 return rtn;
1154}
diff --git a/apps/plugins/doom/p_inter.c b/apps/plugins/doom/p_inter.c
new file mode 100644
index 0000000000..f4a0f80c8f
--- /dev/null
+++ b/apps/plugins/doom/p_inter.c
@@ -0,0 +1,904 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION:
28 * Handling interactions (i.e., collisions).
29 *
30 *-----------------------------------------------------------------------------*/
31
32#include "doomstat.h"
33#include "dstrings.h"
34#include "m_random.h"
35#include "am_map.h"
36#include "r_main.h"
37#include "s_sound.h"
38#include "sounds.h"
39//#include "d_deh.h" // Ty 03/22/98 - externalized strings
40#include "p_tick.h"
41#include "i_system.h"
42#include "p_inter.h"
43#include "p_enemy.h"
44
45#ifdef __GNUG__
46#pragma implementation "p_inter.h"
47#endif
48#include "p_inter.h"
49
50#define BONUSADD 6
51
52// Ty 03/07/98 - add deh externals
53// Maximums and such were hardcoded values. Need to externalize those for
54// dehacked support (and future flexibility). Most var names came from the key
55// strings used in dehacked.
56
57int initial_health = 100;
58int initial_bullets = 50;
59int maxhealth = 100; // was MAXHEALTH as a #define, used only in this module
60int max_armor = 200;
61int green_armor_class = 1; // these are involved with armortype below
62int blue_armor_class = 2;
63int max_soul = 200;
64int soul_health = 100;
65int mega_health = 200;
66int god_health = 100; // these are used in cheats (see st_stuff.c)
67int idfa_armor = 200;
68int idfa_armor_class = 2;
69// not actually used due to pairing of cheat_k and cheat_fa
70int idkfa_armor = 200;
71int idkfa_armor_class = 2;
72
73int bfgcells = 40; // used in p_pspr.c
74// Ty 03/07/98 - end deh externals
75
76// a weapon is found with two clip loads,
77// a big item has five clip loads
78int maxammo[NUMAMMO] = {200, 50, 300, 50};
79int clipammo[NUMAMMO] = { 10, 4, 20, 1};
80
81//
82// GET STUFF
83//
84
85//
86// P_GiveAmmo
87// Num is the number of clip loads,
88// not the individual count (0= 1/2 clip).
89// Returns false if the ammo can't be picked up at all
90//
91
92boolean P_GiveAmmo(player_t *player, ammotype_t ammo, int num)
93{
94 int oldammo;
95
96 if (ammo == am_noammo)
97 return false;
98
99#ifdef RANGECHECK
100 if (ammo < 0 || ammo > NUMAMMO)
101 I_Error ("P_GiveAmmo: bad type %i", ammo);
102#endif
103
104 if ( player->ammo[ammo] == player->maxammo[ammo] )
105 return false;
106
107 if (num)
108 num *= clipammo[ammo];
109 else
110 num = clipammo[ammo]/2;
111
112 // give double ammo in trainer mode, you'll need in nightmare
113 if (gameskill == sk_baby || gameskill == sk_nightmare)
114 num <<= 1;
115
116 oldammo = player->ammo[ammo];
117 player->ammo[ammo] += num;
118
119 if (player->ammo[ammo] > player->maxammo[ammo])
120 player->ammo[ammo] = player->maxammo[ammo];
121
122 // If non zero ammo, don't change up weapons, player was lower on purpose.
123 if (oldammo)
124 return true;
125
126 // We were down to zero, so select a new weapon.
127 // Preferences are not user selectable.
128
129 switch (ammo)
130 {
131 case am_clip:
132 if (player->readyweapon == wp_fist) {
133 if (player->weaponowned[wp_chaingun])
134 player->pendingweapon = wp_chaingun;
135 else
136 player->pendingweapon = wp_pistol;
137 }
138 break;
139
140 case am_shell:
141 if (player->readyweapon == wp_fist || player->readyweapon == wp_pistol)
142 if (player->weaponowned[wp_shotgun])
143 player->pendingweapon = wp_shotgun;
144 break;
145
146 case am_cell:
147 if (player->readyweapon == wp_fist || player->readyweapon == wp_pistol)
148 if (player->weaponowned[wp_plasma])
149 player->pendingweapon = wp_plasma;
150 break;
151
152 case am_misl:
153 if (player->readyweapon == wp_fist)
154 if (player->weaponowned[wp_missile])
155 player->pendingweapon = wp_missile;
156 default:
157 break;
158 }
159 return true;
160}
161
162//
163// P_GiveWeapon
164// The weapon name may have a MF_DROPPED flag ored in.
165//
166
167boolean P_GiveWeapon(player_t *player, weapontype_t weapon, boolean dropped)
168{
169 boolean gaveammo;
170 boolean gaveweapon;
171
172 if (netgame && deathmatch!=2 && !dropped)
173 {
174 // leave placed weapons forever on net games
175 if (player->weaponowned[weapon])
176 return false;
177
178 player->bonuscount += BONUSADD;
179 player->weaponowned[weapon] = true;
180
181 P_GiveAmmo(player, weaponinfo[weapon].ammo, deathmatch ? 5 : 2);
182
183 player->pendingweapon = weapon;
184 /* cph 20028/10 - for old-school DM addicts, allow old behavior
185 * where only consoleplayer's pickup sounds are heard */
186 if (!comp[comp_sound] || player == &players[consoleplayer])
187 S_StartSound (player->mo, sfx_wpnup|PICKUP_SOUND); // killough 4/25/98
188 return false;
189 }
190
191 if (weaponinfo[weapon].ammo != am_noammo)
192 {
193 // give one clip with a dropped weapon,
194 // two clips with a found weapon
195 gaveammo = P_GiveAmmo (player, weaponinfo[weapon].ammo, dropped ? 1 : 2);
196 }
197 else
198 gaveammo = false;
199
200 if (player->weaponowned[weapon])
201 gaveweapon = false;
202 else
203 {
204 gaveweapon = true;
205 player->weaponowned[weapon] = true;
206 player->pendingweapon = weapon;
207 }
208 return gaveweapon || gaveammo;
209}
210
211//
212// P_GiveBody
213// Returns false if the body isn't needed at all
214//
215
216boolean P_GiveBody(player_t *player, int num)
217{
218 if (player->health >= maxhealth)
219 return false; // Ty 03/09/98 externalized MAXHEALTH to maxhealth
220 player->health += num;
221 if (player->health > maxhealth)
222 player->health = maxhealth;
223 player->mo->health = player->health;
224 return true;
225}
226
227//
228// P_GiveArmor
229// Returns false if the armor is worse
230// than the current armor.
231//
232
233boolean P_GiveArmor(player_t *player, int armortype)
234{
235 int hits = armortype*100;
236 if (player->armorpoints >= hits)
237 return false; // don't pick up
238 player->armortype = armortype;
239 player->armorpoints = hits;
240 return true;
241}
242
243//
244// P_GiveCard
245//
246
247void P_GiveCard(player_t *player, card_t card)
248{
249 if (player->cards[card])
250 return;
251 player->bonuscount = BONUSADD;
252 player->cards[card] = 1;
253}
254
255//
256// P_GivePower
257//
258// Rewritten by Lee Killough
259//
260
261boolean P_GivePower(player_t *player, int power)
262{
263 static const int tics[NUMPOWERS] = {
264 INVULNTICS, 1 /* strength */, INVISTICS,
265 IRONTICS, 1 /* allmap */, INFRATICS,
266 };
267
268 switch (power)
269 {
270 case pw_invisibility:
271 player->mo->flags |= MF_SHADOW;
272 break;
273 case pw_allmap:
274 if (player->powers[pw_allmap])
275 return false;
276 break;
277 case pw_strength:
278 P_GiveBody(player,100);
279 break;
280 }
281
282 // Unless player has infinite duration cheat, set duration (killough)
283
284 if (player->powers[power] >= 0)
285 player->powers[power] = tics[power];
286 return true;
287}
288
289//
290// P_TouchSpecialThing
291//
292
293void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher)
294{
295 player_t *player;
296 int i;
297 int sound;
298 fixed_t delta = special->z - toucher->z;
299
300 if (delta > toucher->height || delta < -8*FRACUNIT)
301 return; // out of reach
302
303 sound = sfx_itemup;
304 player = toucher->player;
305
306 // Dead thing touching.
307 // Can happen with a sliding player corpse.
308 if (toucher->health <= 0)
309 return;
310
311 // Identify by sprite.
312 switch (special->sprite)
313 {
314 // armor
315 case SPR_ARM1:
316 if (!P_GiveArmor (player, green_armor_class))
317 return;
318 player->message = GOTARMOR; // Ty 03/22/98 - externalized
319 break;
320
321 case SPR_ARM2:
322 if (!P_GiveArmor (player, blue_armor_class))
323 return;
324 player->message = GOTMEGA; // Ty 03/22/98 - externalized
325 break;
326
327 // bonus items
328 case SPR_BON1:
329 player->health++; // can go over 100%
330 if (player->health > (maxhealth * 2))
331 player->health = (maxhealth * 2);
332 player->mo->health = player->health;
333 player->message = GOTHTHBONUS; // Ty 03/22/98 - externalized
334 break;
335
336 case SPR_BON2:
337 player->armorpoints++; // can go over 100%
338 if (player->armorpoints > max_armor)
339 player->armorpoints = max_armor;
340 if (!player->armortype)
341 player->armortype = green_armor_class;
342 player->message = GOTARMBONUS; // Ty 03/22/98 - externalized
343 break;
344
345 case SPR_SOUL:
346 player->health += soul_health;
347 if (player->health > max_soul)
348 player->health = max_soul;
349 player->mo->health = player->health;
350 player->message = GOTSUPER; // Ty 03/22/98 - externalized
351 sound = sfx_getpow;
352 break;
353
354 case SPR_MEGA:
355 if (gamemode != commercial)
356 return;
357 player->health = mega_health;
358 player->mo->health = player->health;
359 P_GiveArmor (player,blue_armor_class);
360 player->message = GOTMSPHERE; // Ty 03/22/98 - externalized
361 sound = sfx_getpow;
362 break;
363
364 // cards
365 // leave cards for everyone
366 case SPR_BKEY:
367 if (!player->cards[it_bluecard])
368 player->message = GOTBLUECARD; // Ty 03/22/98 - externalized
369 P_GiveCard (player, it_bluecard);
370 if (!netgame)
371 break;
372 return;
373
374 case SPR_YKEY:
375 if (!player->cards[it_yellowcard])
376 player->message = GOTYELWCARD; // Ty 03/22/98 - externalized
377 P_GiveCard (player, it_yellowcard);
378 if (!netgame)
379 break;
380 return;
381
382 case SPR_RKEY:
383 if (!player->cards[it_redcard])
384 player->message = GOTREDCARD; // Ty 03/22/98 - externalized
385 P_GiveCard (player, it_redcard);
386 if (!netgame)
387 break;
388 return;
389
390 case SPR_BSKU:
391 if (!player->cards[it_blueskull])
392 player->message = GOTBLUESKUL; // Ty 03/22/98 - externalized
393 P_GiveCard (player, it_blueskull);
394 if (!netgame)
395 break;
396 return;
397
398 case SPR_YSKU:
399 if (!player->cards[it_yellowskull])
400 player->message = GOTYELWSKUL; // Ty 03/22/98 - externalized
401 P_GiveCard (player, it_yellowskull);
402 if (!netgame)
403 break;
404 return;
405
406 case SPR_RSKU:
407 if (!player->cards[it_redskull])
408 player->message = GOTREDSKULL; // Ty 03/22/98 - externalized
409 P_GiveCard (player, it_redskull);
410 if (!netgame)
411 break;
412 return;
413
414 // medikits, heals
415 case SPR_STIM:
416 if (!P_GiveBody (player, 10))
417 return;
418 player->message = GOTSTIM; // Ty 03/22/98 - externalized
419 break;
420
421 case SPR_MEDI:
422 if (!P_GiveBody (player, 25))
423 return;
424
425 if (player->health < 50) // cph - 25 + the 25 just added, thanks to Quasar for reporting this bug
426 player->message = GOTMEDINEED; // Ty 03/22/98 - externalized
427 else
428 player->message = GOTMEDIKIT; // Ty 03/22/98 - externalized
429 break;
430
431
432 // power ups
433 case SPR_PINV:
434 if (!P_GivePower (player, pw_invulnerability))
435 return;
436 player->message = GOTINVUL; // Ty 03/22/98 - externalized
437 sound = sfx_getpow;
438 break;
439
440 case SPR_PSTR:
441 if (!P_GivePower (player, pw_strength))
442 return;
443 player->message = GOTBERSERK; // Ty 03/22/98 - externalized
444 if (player->readyweapon != wp_fist)
445 player->pendingweapon = wp_fist;
446 sound = sfx_getpow;
447 break;
448
449 case SPR_PINS:
450 if (!P_GivePower (player, pw_invisibility))
451 return;
452 player->message = GOTINVIS; // Ty 03/22/98 - externalized
453 sound = sfx_getpow;
454 break;
455
456 case SPR_SUIT:
457 if (!P_GivePower (player, pw_ironfeet))
458 return;
459 player->message = GOTSUIT; // Ty 03/22/98 - externalized
460 sound = sfx_getpow;
461 break;
462
463 case SPR_PMAP:
464 if (!P_GivePower (player, pw_allmap))
465 return;
466 player->message = GOTMAP; // Ty 03/22/98 - externalized
467 sound = sfx_getpow;
468 break;
469
470 case SPR_PVIS:
471 if (!P_GivePower (player, pw_infrared))
472 return;
473 player->message = GOTVISOR; // Ty 03/22/98 - externalized
474 sound = sfx_getpow;
475 break;
476
477 // ammo
478 case SPR_CLIP:
479 if (special->flags & MF_DROPPED)
480 {
481 if (!P_GiveAmmo (player,am_clip,0))
482 return;
483 }
484 else
485 {
486 if (!P_GiveAmmo (player,am_clip,1))
487 return;
488 }
489 player->message = GOTCLIP; // Ty 03/22/98 - externalized
490 break;
491
492 case SPR_AMMO:
493 if (!P_GiveAmmo (player, am_clip,5))
494 return;
495 player->message = GOTCLIPBOX; // Ty 03/22/98 - externalized
496 break;
497
498 case SPR_ROCK:
499 if (!P_GiveAmmo (player, am_misl,1))
500 return;
501 player->message = GOTROCKET; // Ty 03/22/98 - externalized
502 break;
503
504 case SPR_BROK:
505 if (!P_GiveAmmo (player, am_misl,5))
506 return;
507 player->message = GOTROCKBOX; // Ty 03/22/98 - externalized
508 break;
509
510 case SPR_CELL:
511 if (!P_GiveAmmo (player, am_cell,1))
512 return;
513 player->message = GOTCELL; // Ty 03/22/98 - externalized
514 break;
515
516 case SPR_CELP:
517 if (!P_GiveAmmo (player, am_cell,5))
518 return;
519 player->message = GOTCELLBOX; // Ty 03/22/98 - externalized
520 break;
521
522 case SPR_SHEL:
523 if (!P_GiveAmmo (player, am_shell,1))
524 return;
525 player->message = GOTSHELLS; // Ty 03/22/98 - externalized
526 break;
527
528 case SPR_SBOX:
529 if (!P_GiveAmmo (player, am_shell,5))
530 return;
531 player->message = GOTSHELLBOX; // Ty 03/22/98 - externalized
532 break;
533
534 case SPR_BPAK:
535 if (!player->backpack)
536 {
537 for (i=0 ; i<NUMAMMO ; i++)
538 player->maxammo[i] *= 2;
539 player->backpack = true;
540 }
541 for (i=0 ; i<NUMAMMO ; i++)
542 P_GiveAmmo (player, i, 1);
543 player->message = GOTBACKPACK; // Ty 03/22/98 - externalized
544 break;
545
546 // weapons
547 case SPR_BFUG:
548 if (!P_GiveWeapon (player, wp_bfg, false) )
549 return;
550 player->message = GOTBFG9000; // Ty 03/22/98 - externalized
551 sound = sfx_wpnup;
552 break;
553
554 case SPR_MGUN:
555 if (!P_GiveWeapon (player, wp_chaingun, (special->flags&MF_DROPPED)!=0) )
556 return;
557 player->message = GOTCHAINGUN; // Ty 03/22/98 - externalized
558 sound = sfx_wpnup;
559 break;
560
561 case SPR_CSAW:
562 if (!P_GiveWeapon (player, wp_chainsaw, false) )
563 return;
564 player->message = GOTCHAINSAW; // Ty 03/22/98 - externalized
565 sound = sfx_wpnup;
566 break;
567
568 case SPR_LAUN:
569 if (!P_GiveWeapon (player, wp_missile, false) )
570 return;
571 player->message = GOTLAUNCHER; // Ty 03/22/98 - externalized
572 sound = sfx_wpnup;
573 break;
574
575 case SPR_PLAS:
576 if (!P_GiveWeapon (player, wp_plasma, false) )
577 return;
578 player->message = GOTPLASMA; // Ty 03/22/98 - externalized
579 sound = sfx_wpnup;
580 break;
581
582 case SPR_SHOT:
583 if (!P_GiveWeapon (player, wp_shotgun, (special->flags&MF_DROPPED)!=0 ) )
584 return;
585 player->message = GOTSHOTGUN; // Ty 03/22/98 - externalized
586 sound = sfx_wpnup;
587 break;
588
589 case SPR_SGN2:
590 if (!P_GiveWeapon(player, wp_supershotgun, (special->flags&MF_DROPPED)!=0))
591 return;
592 player->message = GOTSHOTGUN2; // Ty 03/22/98 - externalized
593 sound = sfx_wpnup;
594 break;
595
596 default:
597 I_Error ("P_SpecialThing: Unknown gettable thing");
598 }
599
600 if (special->flags & MF_COUNTITEM)
601 player->itemcount++;
602 P_RemoveMobj (special);
603 player->bonuscount += BONUSADD;
604
605 /* cph 20028/10 - for old-school DM addicts, allow old behavior
606 * where only consoleplayer's pickup sounds are heard */
607 if (!comp[comp_sound] || player == &players[consoleplayer])
608 S_StartSound (player->mo, sound | PICKUP_SOUND); // killough 4/25/98
609}
610
611//
612// KillMobj
613//
614// killough 11/98: make static
615static void P_KillMobj(mobj_t *source, mobj_t *target)
616{
617 mobjtype_t item;
618 mobj_t *mo;
619
620 target->flags &= ~(MF_SHOOTABLE|MF_FLOAT|MF_SKULLFLY);
621
622 if (target->type != MT_SKULL)
623 target->flags &= ~MF_NOGRAVITY;
624
625 target->flags |= MF_CORPSE|MF_DROPOFF;
626 target->height >>= 2;
627
628 if (!((target->flags ^ MF_COUNTKILL) & (MF_FRIEND | MF_COUNTKILL)))
629 totallive--;
630
631 if (source && source->player)
632 {
633 // count for intermission
634 if (target->flags & MF_COUNTKILL)
635 source->player->killcount++;
636 if (target->player)
637 source->player->frags[target->player-players]++;
638 }
639 else
640 if (target->flags & MF_COUNTKILL) { /* Add to kills tally */
641 if ((compatibility_level < lxdoom_1_compatibility) || !netgame) {
642 if (!netgame)
643 // count all monster deaths,
644 // even those caused by other monsters
645 players[0].killcount++;
646 } else
647 if (!deathmatch) {
648 // try and find a player to give the kill to, otherwise give the
649 // kill to a random player. this fixes the missing monsters bug
650 // in coop - rain
651 // CPhipps - not a bug as such, but certainly an inconsistency.
652 if (target->lastenemy && target->lastenemy->health > 0
653 && target->lastenemy->player) // Fighting a player
654 target->lastenemy->player->killcount++;
655 else {
656 // cph - randomely choose a player in the game to be credited
657 // and do it uniformly between the active players
658 unsigned int activeplayers = 0, player, i;
659
660 for (player = 0; player<MAXPLAYERS; player++)
661 if (playeringame[player])
662 activeplayers++;
663
664 if (activeplayers) {
665 player = P_Random(pr_friends) % activeplayers;
666
667 for (i=0; i<MAXPLAYERS; i++)
668 if (playeringame[i])
669 if (!player--)
670 players[i].killcount++;
671 }
672 }
673 }
674 }
675
676 if (target->player)
677 {
678 // count environment kills against you
679 if (!source)
680 target->player->frags[target->player-players]++;
681
682 target->flags &= ~MF_SOLID;
683 target->player->playerstate = PST_DEAD;
684 P_DropWeapon (target->player);
685
686 if (target->player == &players[consoleplayer] && (automapmode & am_active))
687 AM_Stop(); // don't die in auto map; switch view prior to dying
688 }
689
690 if (target->health < -target->info->spawnhealth && target->info->xdeathstate)
691 P_SetMobjState (target, target->info->xdeathstate);
692 else
693 P_SetMobjState (target, target->info->deathstate);
694
695 target->tics -= P_Random(pr_killtics)&3;
696
697 if (target->tics < 1)
698 target->tics = 1;
699
700 // Drop stuff.
701 // This determines the kind of object spawned
702 // during the death frame of a thing.
703
704 switch (target->type)
705 {
706 case MT_WOLFSS:
707 case MT_POSSESSED:
708 item = MT_CLIP;
709 break;
710
711 case MT_SHOTGUY:
712 item = MT_SHOTGUN;
713 break;
714
715 case MT_CHAINGUY:
716 item = MT_CHAINGUN;
717 break;
718
719 default:
720 return;
721 }
722
723 mo = P_SpawnMobj (target->x,target->y,ONFLOORZ, item);
724 mo->flags |= MF_DROPPED; // special versions of items
725}
726
727//
728// P_DamageMobj
729// Damages both enemies and players
730// "inflictor" is the thing that caused the damage
731// creature or missile, can be NULL (slime, etc)
732// "source" is the thing to target after taking damage
733// creature or NULL
734// Source and inflictor are the same for melee attacks.
735// Source can be NULL for slime, barrel explosions
736// and other environmental stuff.
737//
738
739void P_DamageMobj(mobj_t *target,mobj_t *inflictor, mobj_t *source, int damage)
740{
741 player_t *player;
742 boolean justhit; /* killough 11/98 */
743
744 /* killough 8/31/98: allow bouncers to take damage */
745 if (!(target->flags & (MF_SHOOTABLE | MF_BOUNCES)))
746 return; // shouldn't happen...
747
748 if (target->health <= 0)
749 return;
750
751 /* proff 11/22/98: Andy Baker's Stealth monsters */
752 if (target->flags & MF_STEALTH)
753 P_BecomeVisible(target);
754
755 if (target->flags & MF_SKULLFLY)
756 target->momx = target->momy = target->momz = 0;
757
758 player = target->player;
759 if (player && gameskill == sk_baby)
760 damage >>= 1; // take half damage in trainer mode
761
762 // Some close combat weapons should not
763 // inflict thrust and push the victim out of reach,
764 // thus kick away unless using the chainsaw.
765
766 if (inflictor && !(target->flags & MF_NOCLIP) &&
767 (!source || !source->player ||
768 source->player->readyweapon != wp_chainsaw))
769 {
770 unsigned ang = R_PointToAngle2 (inflictor->x, inflictor->y,
771 target->x, target->y);
772
773 fixed_t thrust = damage*(FRACUNIT>>3)*100/target->info->mass;
774
775 // make fall forwards sometimes
776 if ( damage < 40 && damage > target->health
777 && target->z - inflictor->z > 64*FRACUNIT
778 && P_Random(pr_damagemobj) & 1)
779 {
780 ang += ANG180;
781 thrust *= 4;
782 }
783
784 ang >>= ANGLETOFINESHIFT;
785 target->momx += FixedMul (thrust, finecosine[ang]);
786 target->momy += FixedMul (thrust, finesine[ang]);
787
788 /* killough 11/98: thrust objects hanging off ledges */
789 if (target->intflags & MIF_FALLING && target->gear >= MAXGEAR)
790 target->gear = 0;
791 }
792
793 // player specific
794 if (player)
795 {
796 // end of game hell hack
797 if (target->subsector->sector->special == 11 && damage >= target->health)
798 damage = target->health - 1;
799
800 // Below certain threshold,
801 // ignore damage in GOD mode, or with INVUL power.
802 // killough 3/26/98: make god mode 100% god mode in non-compat mode
803
804 if ((damage < 1000 || (!comp[comp_god] && (player->cheats&CF_GODMODE))) &&
805 (player->cheats&CF_GODMODE || player->powers[pw_invulnerability]))
806 return;
807
808 if (player->armortype)
809 {
810 int saved = player->armortype == 1 ? damage/3 : damage/2;
811 if (player->armorpoints <= saved)
812 {
813 // armor is used up
814 saved = player->armorpoints;
815 player->armortype = 0;
816 }
817 player->armorpoints -= saved;
818 damage -= saved;
819 }
820
821 player->health -= damage; // mirror mobj health here for Dave
822 if (player->health < 0)
823 player->health = 0;
824
825 player->attacker = source;
826 player->damagecount += damage; // add damage after armor / invuln
827
828 if (player->damagecount > 100)
829 player->damagecount = 100; // teleport stomp does 10k points...
830 }
831
832 // do the damage
833 target->health -= damage;
834 if (target->health <= 0)
835 {
836 P_KillMobj (source, target);
837 return;
838 }
839
840 // killough 9/7/98: keep track of targets so that friends can help friends
841 if (mbf_features)
842 {
843 /* If target is a player, set player's target to source,
844 * so that a friend can tell who's hurting a player
845 */
846 if (player)
847 P_SetTarget(&target->target, source);
848
849 /* killough 9/8/98:
850 * If target's health is less than 50%, move it to the front of its list.
851 * This will slightly increase the chances that enemies will choose to
852 * "finish it off", but its main purpose is to alert friends of danger.
853 */
854 if (target->health*2 < target->info->spawnhealth)
855 {
856 thinker_t *cap = &thinkerclasscap[target->flags & MF_FRIEND ?
857 th_friends : th_enemies];
858 (target->thinker.cprev->cnext = target->thinker.cnext)->cprev =
859 target->thinker.cprev;
860 (target->thinker.cnext = cap->cnext)->cprev = &target->thinker;
861 (target->thinker.cprev = cap)->cnext = &target->thinker;
862 }
863 }
864
865 if ((justhit = (P_Random (pr_painchance) < target->info->painchance &&
866 !(target->flags & MF_SKULLFLY)))) //killough 11/98: see below
867 P_SetMobjState(target, target->info->painstate);
868
869 target->reactiontime = 0; // we're awake now...
870
871 /* killough 9/9/98: cleaned up, made more consistent: */
872
873 if (source && source != target && source->type != MT_VILE &&
874 (!target->threshold || target->type == MT_VILE) &&
875 ((source->flags ^ target->flags) & MF_FRIEND ||
876 monster_infighting ||
877 !mbf_features))
878 {
879 /* if not intent on another player, chase after this one
880 *
881 * killough 2/15/98: remember last enemy, to prevent
882 * sleeping early; 2/21/98: Place priority on players
883 * killough 9/9/98: cleaned up, made more consistent:
884 */
885
886 if (!target->lastenemy || target->lastenemy->health <= 0 ||
887 (!mbf_features ?
888 !target->lastenemy->player :
889 !((target->flags ^ target->lastenemy->flags) & MF_FRIEND) &&
890 target->target != source)) // remember last enemy - killough
891 P_SetTarget(&target->lastenemy, target->target);
892
893 P_SetTarget(&target->target, source); // killough 11/98
894 target->threshold = BASETHRESHOLD;
895 if (target->state == &states[target->info->spawnstate]
896 && target->info->seestate != S_NULL)
897 P_SetMobjState (target, target->info->seestate);
898 }
899
900 /* killough 11/98: Don't attack a friend, unless hit by that friend. */
901 if (justhit && (target->target == source || !target->target ||
902 !(target->flags & target->target->flags & MF_FRIEND)))
903 target->flags |= MF_JUSTHIT; // fight back!
904}
diff --git a/apps/plugins/doom/p_inter.h b/apps/plugins/doom/p_inter.h
new file mode 100644
index 0000000000..669a9585f8
--- /dev/null
+++ b/apps/plugins/doom/p_inter.h
@@ -0,0 +1,77 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION:
28 * Thing events, and dehacked specified numbers controlling them.
29 *
30 *-----------------------------------------------------------------------------*/
31
32#ifndef __P_INTER__
33#define __P_INTER__
34
35#include "d_player.h"
36#include "p_mobj.h"
37
38#ifdef __GNUG__
39#pragma interface
40#endif
41
42/* Ty 03/09/98 Moved to an int in p_inter.c for deh and externalization */
43#define MAXHEALTH 100//maxhealth
44
45/* follow a player exlusively for 3 seconds */
46#define BASETHRESHOLD (100)
47
48boolean P_GivePower(player_t *, int);
49void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher);
50void P_DamageMobj(mobj_t *target,mobj_t *inflictor,mobj_t *source,int damage);
51
52/* killough 5/2/98: moved from d_deh.c, g_game.c, m_misc.c, others: */
53
54extern int god_health; /* Ty 03/09/98 - deh support, see also p_inter.c */
55extern int idfa_armor;
56extern int idfa_armor_class;
57extern int idkfa_armor;
58extern int idkfa_armor_class; /* Ty - end */
59/* Ty 03/13/98 - externalized initial settings for respawned player */
60extern int initial_health;
61extern int initial_bullets;
62extern int maxhealth;
63extern int max_armor;
64extern int green_armor_class;
65extern int blue_armor_class;
66extern int max_soul;
67extern int soul_health;
68extern int mega_health;
69extern int god_health;
70extern int idfa_armor;
71extern int idfa_armor_class;
72extern int idkfa_armor;
73extern int idkfa_armor_class;
74extern int bfgcells;
75extern int maxammo[], clipammo[];
76
77#endif
diff --git a/apps/plugins/doom/p_lights.c b/apps/plugins/doom/p_lights.c
new file mode 100644
index 0000000000..44d151b7b5
--- /dev/null
+++ b/apps/plugins/doom/p_lights.c
@@ -0,0 +1,437 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION:
28 * Action routines for lighting thinkers
29 * Spawn sector based lighting effects.
30 * Handle lighting linedef types
31 *
32 *-----------------------------------------------------------------------------*/
33
34#include "doomstat.h" //jff 5/18/98
35#include "doomdef.h"
36#include "m_random.h"
37#include "r_main.h"
38#include "p_spec.h"
39#include "p_tick.h"
40
41//////////////////////////////////////////////////////////
42//
43// Lighting action routines, called once per tick
44//
45//////////////////////////////////////////////////////////
46
47//
48// T_FireFlicker()
49//
50// Firelight flicker action routine, called once per tick
51//
52// Passed a fireflicker_t structure containing light levels and timing
53// Returns nothing
54//
55void T_FireFlicker (fireflicker_t* flick)
56{
57 int amount;
58
59 if (--flick->count)
60 return;
61
62 amount = (P_Random(pr_lights)&3)*16;
63
64 if (flick->sector->lightlevel - amount < flick->minlight)
65 flick->sector->lightlevel = flick->minlight;
66 else
67 flick->sector->lightlevel = flick->maxlight - amount;
68
69 flick->count = 4;
70}
71
72//
73// T_LightFlash()
74//
75// Broken light flashing action routine, called once per tick
76//
77// Passed a lightflash_t structure containing light levels and timing
78// Returns nothing
79//
80void T_LightFlash (lightflash_t* flash)
81{
82 if (--flash->count)
83 return;
84
85 if (flash->sector->lightlevel == flash->maxlight)
86 {
87 flash-> sector->lightlevel = flash->minlight;
88 flash->count = (P_Random(pr_lights)&flash->mintime)+1;
89 }
90 else
91 {
92 flash-> sector->lightlevel = flash->maxlight;
93 flash->count = (P_Random(pr_lights)&flash->maxtime)+1;
94 }
95
96}
97
98//
99// T_StrobeFlash()
100//
101// Strobe light flashing action routine, called once per tick
102//
103// Passed a strobe_t structure containing light levels and timing
104// Returns nothing
105//
106void T_StrobeFlash (strobe_t* flash)
107{
108 if (--flash->count)
109 return;
110
111 if (flash->sector->lightlevel == flash->minlight)
112 {
113 flash-> sector->lightlevel = flash->maxlight;
114 flash->count = flash->brighttime;
115 }
116 else
117 {
118 flash-> sector->lightlevel = flash->minlight;
119 flash->count =flash->darktime;
120 }
121}
122
123//
124// T_Glow()
125//
126// Glowing light action routine, called once per tick
127//
128// Passed a glow_t structure containing light levels and timing
129// Returns nothing
130//
131
132void T_Glow(glow_t* g)
133{
134 switch(g->direction)
135 {
136 case -1:
137 // light dims
138 g->sector->lightlevel -= GLOWSPEED;
139 if (g->sector->lightlevel <= g->minlight)
140 {
141 g->sector->lightlevel += GLOWSPEED;
142 g->direction = 1;
143 }
144 break;
145
146 case 1:
147 // light brightens
148 g->sector->lightlevel += GLOWSPEED;
149 if (g->sector->lightlevel >= g->maxlight)
150 {
151 g->sector->lightlevel -= GLOWSPEED;
152 g->direction = -1;
153 }
154 break;
155 }
156}
157
158//////////////////////////////////////////////////////////
159//
160// Sector lighting type spawners
161//
162// After the map has been loaded, each sector is scanned
163// for specials that spawn thinkers
164//
165//////////////////////////////////////////////////////////
166
167//
168// P_SpawnFireFlicker()
169//
170// Spawns a fire flicker lighting thinker
171//
172// Passed the sector that spawned the thinker
173// Returns nothing
174//
175void P_SpawnFireFlicker (sector_t* sector)
176{
177 fireflicker_t* flick;
178
179 // Note that we are resetting sector attributes.
180 // Nothing special about it during gameplay.
181 sector->special &= ~31; //jff 3/14/98 clear non-generalized sector type
182
183 flick = Z_Malloc ( sizeof(*flick), PU_LEVSPEC, 0);
184
185 P_AddThinker (&flick->thinker);
186
187 flick->thinker.function = T_FireFlicker;
188 flick->sector = sector;
189 flick->maxlight = sector->lightlevel;
190 flick->minlight = P_FindMinSurroundingLight(sector,sector->lightlevel)+16;
191 flick->count = 4;
192}
193
194//
195// P_SpawnLightFlash()
196//
197// Spawns a broken light flash lighting thinker
198//
199// Passed the sector that spawned the thinker
200// Returns nothing
201//
202void P_SpawnLightFlash (sector_t* sector)
203{
204 lightflash_t* flash;
205
206 // nothing special about it during gameplay
207 sector->special &= ~31; //jff 3/14/98 clear non-generalized sector type
208
209 flash = Z_Malloc ( sizeof(*flash), PU_LEVSPEC, 0);
210
211 P_AddThinker (&flash->thinker);
212
213 flash->thinker.function = T_LightFlash;
214 flash->sector = sector;
215 flash->maxlight = sector->lightlevel;
216
217 flash->minlight = P_FindMinSurroundingLight(sector,sector->lightlevel);
218 flash->maxtime = 64;
219 flash->mintime = 7;
220 flash->count = (P_Random(pr_lights)&flash->maxtime)+1;
221}
222
223//
224// P_SpawnStrobeFlash
225//
226// Spawns a blinking light thinker
227//
228// Passed the sector that spawned the thinker, speed of blinking
229// and whether blinking is to by syncrhonous with other sectors
230//
231// Returns nothing
232//
233void P_SpawnStrobeFlash
234( sector_t* sector,
235 int fastOrSlow,
236 int inSync )
237{
238 strobe_t* flash;
239
240 flash = Z_Malloc ( sizeof(*flash), PU_LEVSPEC, 0);
241
242 P_AddThinker (&flash->thinker);
243
244 flash->sector = sector;
245 flash->darktime = fastOrSlow;
246 flash->brighttime = STROBEBRIGHT;
247 flash->thinker.function = T_StrobeFlash;
248 flash->maxlight = sector->lightlevel;
249 flash->minlight = P_FindMinSurroundingLight(sector, sector->lightlevel);
250
251 if (flash->minlight == flash->maxlight)
252 flash->minlight = 0;
253
254 // nothing special about it during gameplay
255 sector->special &= ~31; //jff 3/14/98 clear non-generalized sector type
256
257 if (!inSync)
258 flash->count = (P_Random(pr_lights)&7)+1;
259 else
260 flash->count = 1;
261}
262
263//
264// P_SpawnGlowingLight()
265//
266// Spawns a glowing light (smooth oscillation from min to max) thinker
267//
268// Passed the sector that spawned the thinker
269// Returns nothing
270//
271void P_SpawnGlowingLight(sector_t* sector)
272{
273 glow_t* g;
274
275 g = Z_Malloc( sizeof(*g), PU_LEVSPEC, 0);
276
277 P_AddThinker(&g->thinker);
278
279 g->sector = sector;
280 g->minlight = P_FindMinSurroundingLight(sector,sector->lightlevel);
281 g->maxlight = sector->lightlevel;
282 g->thinker.function = T_Glow;
283 g->direction = -1;
284
285 sector->special &= ~31; //jff 3/14/98 clear non-generalized sector type
286}
287
288//////////////////////////////////////////////////////////
289//
290// Linedef lighting function handlers
291//
292//////////////////////////////////////////////////////////
293
294//
295// EV_StartLightStrobing()
296//
297// Start strobing lights (usually from a trigger)
298//
299// Passed the line that activated the strobing
300// Returns true
301//
302// jff 2/12/98 added int return value, fixed return
303//
304int EV_StartLightStrobing(line_t* line)
305{
306 int secnum;
307 sector_t* sec;
308
309 secnum = -1;
310 // start lights strobing in all sectors tagged same as line
311 while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0)
312 {
313 sec = &sectors[secnum];
314 // if already doing a lighting function, don't start a second
315 if (P_SectorActive(lighting_special,sec)) //jff 2/22/98
316 continue;
317
318 P_SpawnStrobeFlash (sec,SLOWDARK, 0);
319 }
320 return 1;
321}
322
323//
324// EV_TurnTagLightsOff()
325//
326// Turn line's tagged sector's lights to min adjacent neighbor level
327//
328// Passed the line that activated the lights being turned off
329// Returns true
330//
331// jff 2/12/98 added int return value, fixed return
332//
333int EV_TurnTagLightsOff(line_t* line)
334{
335 int j;
336
337 // search sectors for those with same tag as activating line
338
339 // killough 10/98: replaced inefficient search with fast search
340 for (j = -1; (j = P_FindSectorFromLineTag(line,j)) >= 0;)
341 {
342 sector_t *sector = sectors + j, *tsec;
343 int i, min = sector->lightlevel;
344 // find min neighbor light level
345 for (i = 0;i < sector->linecount; i++)
346 if ((tsec = getNextSector(sector->lines[i], sector)) &&
347 tsec->lightlevel < min)
348 min = tsec->lightlevel;
349 sector->lightlevel = min;
350 }
351 return 1;
352}
353
354//
355// EV_LightTurnOn()
356//
357// Turn sectors tagged to line lights on to specified or max neighbor level
358//
359// Passed the activating line, and a level to set the light to
360// If level passed is 0, the maximum neighbor lighting is used
361// Returns true
362//
363// jff 2/12/98 added int return value, fixed return
364//
365int EV_LightTurnOn(line_t *line, int bright)
366{
367 int i;
368
369 // search all sectors for ones with same tag as activating line
370
371 // killough 10/98: replace inefficient search with fast search
372 for (i = -1; (i = P_FindSectorFromLineTag(line,i)) >= 0;)
373 {
374 sector_t *temp, *sector = sectors+i;
375 int j, tbright = bright; //jff 5/17/98 search for maximum PER sector
376
377 // bright = 0 means to search for highest light level surrounding sector
378
379 if (!bright)
380 for (j = 0;j < sector->linecount; j++)
381 if ((temp = getNextSector(sector->lines[j],sector)) &&
382 temp->lightlevel > tbright)
383 tbright = temp->lightlevel;
384
385 sector->lightlevel = tbright;
386
387 //jff 5/17/98 unless compatibility optioned
388 //then maximum near ANY tagged sector
389 if (comp[comp_model])
390 bright = tbright;
391 }
392 return 1;
393}
394
395/* killough 10/98:
396 *
397 * EV_LightTurnOnPartway()
398 *
399 * Turn sectors tagged to line lights on to specified or max neighbor level
400 *
401 * Passed the activating line, and a light level fraction between 0 and 1.
402 * Sets the light to min on 0, max on 1, and interpolates in-between.
403 * Used for doors with gradual lighting effects.
404 *
405 * Returns true
406 */
407
408int EV_LightTurnOnPartway(line_t *line, fixed_t level)
409{
410 int i;
411
412 if (level < 0) // clip at extremes
413 level = 0;
414 if (level > FRACUNIT)
415 level = FRACUNIT;
416
417 // search all sectors for ones with same tag as activating line
418 for (i = -1; (i = P_FindSectorFromLineTag(line,i)) >= 0;)
419 {
420 sector_t *temp, *sector = sectors+i;
421 int j, bright = 0, min = sector->lightlevel;
422
423 for (j = 0; j < sector->linecount; j++)
424 if ((temp = getNextSector(sector->lines[j],sector)))
425 {
426 if (temp->lightlevel > bright)
427 bright = temp->lightlevel;
428 if (temp->lightlevel < min)
429 min = temp->lightlevel;
430 }
431
432 sector->lightlevel = // Set level in-between extremes
433 (level * bright + (FRACUNIT-level) * min) >> FRACBITS;
434 }
435 return 1;
436}
437
diff --git a/apps/plugins/doom/p_map.c b/apps/plugins/doom/p_map.c
new file mode 100644
index 0000000000..35194dec14
--- /dev/null
+++ b/apps/plugins/doom/p_map.c
@@ -0,0 +1,2207 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION:
28 * Movement, collision handling.
29 * Shooting and aiming.
30 *
31 *-----------------------------------------------------------------------------*/
32
33#include "doomstat.h"
34#include "r_main.h"
35#include "p_mobj.h"
36#include "p_maputl.h"
37#include "p_map.h"
38#include "p_setup.h"
39#include "p_spec.h"
40#include "s_sound.h"
41#include "sounds.h"
42#include "p_inter.h"
43#include "m_random.h"
44#include "m_bbox.h"
45#include "i_system.h"
46#include "rockmacros.h"
47
48static mobj_t *tmthing;
49static fixed_t tmx;
50static fixed_t tmy;
51static int pe_x; // Pain Elemental position for Lost Soul checks // phares
52static int pe_y; // Pain Elemental position for Lost Soul checks // phares
53static int ls_x; // Lost Soul position for Lost Soul checks // phares
54static int ls_y; // Lost Soul position for Lost Soul checks // phares
55
56// If "floatok" true, move would be ok
57// if within "tmfloorz - tmceilingz".
58
59boolean floatok;
60
61/* killough 11/98: if "felldown" true, object was pushed down ledge */
62boolean felldown;
63
64// The tm* items are used to hold information globally, usually for
65// line or object intersection checking
66
67fixed_t tmbbox[4]; // bounding box for line intersection checks
68fixed_t tmfloorz; // floor you'd hit if free to fall
69fixed_t tmceilingz; // ceiling of sector you're in
70fixed_t tmdropoffz; // dropoff on other side of line you're crossing
71
72// keep track of the line that lowers the ceiling,
73// so missiles don't explode against sky hack walls
74
75line_t *ceilingline;
76line_t *blockline; /* killough 8/11/98: blocking linedef */
77line_t *floorline; /* killough 8/1/98: Highest touched floor */
78static int tmunstuck; /* killough 8/1/98: whether to allow unsticking */
79
80// keep track of special lines as they are hit,
81// but don't process them until the move is proven valid
82
83// 1/11/98 killough: removed limit on special lines crossed
84line_t **spechit; // new code -- killough
85static int spechit_max; // killough
86
87int numspechit;
88
89// Temporary holder for thing_sectorlist threads
90msecnode_t* sector_list = NULL; // phares 3/16/98
91
92//
93// TELEPORT MOVE
94//
95
96//
97// PIT_StompThing
98//
99
100static boolean telefrag; /* killough 8/9/98: whether to telefrag at exit */
101
102boolean PIT_StompThing (mobj_t* thing)
103{
104 fixed_t blockdist;
105
106 // phares 9/10/98: moved this self-check to start of routine
107
108 // don't clip against self
109
110 if (thing == tmthing)
111 return true;
112
113 if (!(thing->flags & MF_SHOOTABLE)) // Can't shoot it? Can't stomp it!
114 return true;
115
116 blockdist = thing->radius + tmthing->radius;
117
118 if (D_abs(thing->x - tmx) >= blockdist || D_abs(thing->y - tmy) >= blockdist)
119 return true; // didn't hit it
120
121 // monsters don't stomp things except on boss level
122 if (!telefrag) // killough 8/9/98: make consistent across all levels
123 return false;
124
125 P_DamageMobj (thing, tmthing, tmthing, 10000); // Stomp!
126
127 return true;
128}
129
130
131/*
132 * killough 8/28/98:
133 *
134 * P_GetFriction()
135 *
136 * Returns the friction associated with a particular mobj.
137 */
138
139int P_GetFriction(const mobj_t *mo, int *frictionfactor)
140{
141 int friction = ORIG_FRICTION;
142 int movefactor = ORIG_FRICTION_FACTOR;
143 const msecnode_t *m;
144 const sector_t *sec;
145
146 /* Assign the friction value to objects on the floor, non-floating,
147 * and clipped. Normally the object's friction value is kept at
148 * ORIG_FRICTION and this thinker changes it for icy or muddy floors.
149 *
150 * When the object is straddling sectors with the same
151 * floorheight that have different frictions, use the lowest
152 * friction value (muddy has precedence over icy).
153 */
154
155 if (!(mo->flags & (MF_NOCLIP|MF_NOGRAVITY))
156 && (mbf_features || (mo->player && !compatibility)) &&
157 variable_friction)
158 for (m = mo->touching_sectorlist; m; m = m->m_tnext)
159 if ((sec = m->m_sector)->special & FRICTION_MASK &&
160 (sec->friction < friction || friction == ORIG_FRICTION) &&
161 (mo->z <= sec->floorheight ||
162 (sec->heightsec != -1 &&
163 mo->z <= sectors[sec->heightsec].floorheight &&
164 mbf_features)))
165 friction = sec->friction, movefactor = sec->movefactor;
166
167 if (frictionfactor)
168 *frictionfactor = movefactor;
169
170 return friction;
171}
172
173/* phares 3/19/98
174 * P_GetMoveFactor() returns the value by which the x,y
175 * movements are multiplied to add to player movement.
176 *
177 * killough 8/28/98: rewritten
178 */
179
180int P_GetMoveFactor(const mobj_t *mo, int *frictionp)
181{
182 int movefactor, friction;
183
184 // If the floor is icy or muddy, it's harder to get moving. This is where
185 // the different friction factors are applied to 'trying to move'. In
186 // p_mobj.c, the friction factors are applied as you coast and slow down.
187
188 if ((friction = P_GetFriction(mo, &movefactor)) < ORIG_FRICTION)
189 {
190 // phares 3/11/98: you start off slowly, then increase as
191 // you get better footing
192
193 int momentum = P_AproxDistance(mo->momx,mo->momy);
194
195 if (momentum > MORE_FRICTION_MOMENTUM<<2)
196 movefactor <<= 3;
197 else if (momentum > MORE_FRICTION_MOMENTUM<<1)
198 movefactor <<= 2;
199 else if (momentum > MORE_FRICTION_MOMENTUM)
200 movefactor <<= 1;
201 }
202
203 if (frictionp)
204 *frictionp = friction;
205
206 return movefactor;
207}
208
209//
210// P_TeleportMove
211//
212
213boolean P_TeleportMove (mobj_t* thing,fixed_t x,fixed_t y, boolean boss)
214{
215 int xl;
216 int xh;
217 int yl;
218 int yh;
219 int bx;
220 int by;
221
222 subsector_t* newsubsec;
223
224 /* killough 8/9/98: make telefragging more consistent, preserve compatibility */
225 telefrag = thing->player ||
226 (!comp[comp_telefrag] ? boss : (gamemap==30));
227
228 // kill anything occupying the position
229
230 tmthing = thing;
231
232 tmx = x;
233 tmy = y;
234
235 tmbbox[BOXTOP] = y + tmthing->radius;
236 tmbbox[BOXBOTTOM] = y - tmthing->radius;
237 tmbbox[BOXRIGHT] = x + tmthing->radius;
238 tmbbox[BOXLEFT] = x - tmthing->radius;
239
240 newsubsec = R_PointInSubsector (x,y);
241 ceilingline = NULL;
242
243 // The base floor/ceiling is from the subsector
244 // that contains the point.
245 // Any contacted lines the step closer together
246 // will adjust them.
247
248 tmfloorz = tmdropoffz = newsubsec->sector->floorheight;
249 tmceilingz = newsubsec->sector->ceilingheight;
250
251 validcount++;
252 numspechit = 0;
253
254 // stomp on any things contacted
255
256 xl = (tmbbox[BOXLEFT] - bmaporgx - MAXRADIUS)>>MAPBLOCKSHIFT;
257 xh = (tmbbox[BOXRIGHT] - bmaporgx + MAXRADIUS)>>MAPBLOCKSHIFT;
258 yl = (tmbbox[BOXBOTTOM] - bmaporgy - MAXRADIUS)>>MAPBLOCKSHIFT;
259 yh = (tmbbox[BOXTOP] - bmaporgy + MAXRADIUS)>>MAPBLOCKSHIFT;
260
261 for (bx=xl ; bx<=xh ; bx++)
262 for (by=yl ; by<=yh ; by++)
263 if (!P_BlockThingsIterator(bx,by,PIT_StompThing))
264 return false;
265
266 // the move is ok,
267 // so unlink from the old position & link into the new position
268
269 P_UnsetThingPosition (thing);
270
271 thing->floorz = tmfloorz;
272 thing->ceilingz = tmceilingz;
273 thing->dropoffz = tmdropoffz; // killough 11/98
274
275 thing->x = x;
276 thing->y = y;
277
278 P_SetThingPosition (thing);
279
280 return true;
281}
282
283
284//
285// MOVEMENT ITERATOR FUNCTIONS
286//
287
288// // phares
289// PIT_CrossLine // |
290// Checks to see if a PE->LS trajectory line crosses a blocking // V
291// line. Returns false if it does.
292//
293// tmbbox holds the bounding box of the trajectory. If that box
294// does not touch the bounding box of the line in question,
295// then the trajectory is not blocked. If the PE is on one side
296// of the line and the LS is on the other side, then the
297// trajectory is blocked.
298//
299// Currently this assumes an infinite line, which is not quite
300// correct. A more correct solution would be to check for an
301// intersection of the trajectory and the line, but that takes
302// longer and probably really isn't worth the effort.
303//
304
305static // killough 3/26/98: make static
306boolean PIT_CrossLine (line_t* ld)
307{
308 if (!(ld->flags & ML_TWOSIDED) ||
309 (ld->flags & (ML_BLOCKING|ML_BLOCKMONSTERS)))
310 if (!(tmbbox[BOXLEFT] > ld->bbox[BOXRIGHT] ||
311 tmbbox[BOXRIGHT] < ld->bbox[BOXLEFT] ||
312 tmbbox[BOXTOP] < ld->bbox[BOXBOTTOM] ||
313 tmbbox[BOXBOTTOM] > ld->bbox[BOXTOP]))
314 if (P_PointOnLineSide(pe_x,pe_y,ld) != P_PointOnLineSide(ls_x,ls_y,ld))
315 return(false); // line blocks trajectory // ^
316 return(true); // line doesn't block trajectory // |
317} // phares
318
319
320/* killough 8/1/98: used to test intersection between thing and line
321 * assuming NO movement occurs -- used to avoid sticky situations.
322 */
323
324static int untouched(line_t *ld)
325{
326 fixed_t x, y, tmbbox[4];
327 return
328 (tmbbox[BOXRIGHT] = (x=tmthing->x)+tmthing->radius) <= ld->bbox[BOXLEFT] ||
329 (tmbbox[BOXLEFT] = x-tmthing->radius) >= ld->bbox[BOXRIGHT] ||
330 (tmbbox[BOXTOP] = (y=tmthing->y)+tmthing->radius) <= ld->bbox[BOXBOTTOM] ||
331 (tmbbox[BOXBOTTOM] = y-tmthing->radius) >= ld->bbox[BOXTOP] ||
332 P_BoxOnLineSide(tmbbox, ld) != -1;
333}
334
335//
336// PIT_CheckLine
337// Adjusts tmfloorz and tmceilingz as lines are contacted
338//
339
340static // killough 3/26/98: make static
341boolean PIT_CheckLine (line_t* ld)
342{
343 if (tmbbox[BOXRIGHT] <= ld->bbox[BOXLEFT]
344 || tmbbox[BOXLEFT] >= ld->bbox[BOXRIGHT]
345 || tmbbox[BOXTOP] <= ld->bbox[BOXBOTTOM]
346 || tmbbox[BOXBOTTOM] >= ld->bbox[BOXTOP] )
347 return true; // didn't hit it
348
349 if (P_BoxOnLineSide(tmbbox, ld) != -1)
350 return true; // didn't hit it
351
352 // A line has been hit
353
354 // The moving thing's destination position will cross the given line.
355 // If this should not be allowed, return false.
356 // If the line is special, keep track of it
357 // to process later if the move is proven ok.
358 // NOTE: specials are NOT sorted by order,
359 // so two special lines that are only 8 pixels apart
360 // could be crossed in either order.
361
362 // killough 7/24/98: allow player to move out of 1s wall, to prevent sticking
363 if (!ld->backsector) // one sided line
364 {
365 blockline = ld;
366 return tmunstuck && !untouched(ld) &&
367 FixedMul(tmx-tmthing->x,ld->dy) > FixedMul(tmy-tmthing->y,ld->dx);
368 }
369
370 // killough 8/10/98: allow bouncing objects to pass through as missiles
371 if (!(tmthing->flags & (MF_MISSILE | MF_BOUNCES)))
372 {
373 if (ld->flags & ML_BLOCKING) // explicitly blocking everything
374 return tmunstuck && !untouched(ld); // killough 8/1/98: allow escape
375
376 // killough 8/9/98: monster-blockers don't affect friends
377 if (!(tmthing->flags & MF_FRIEND || tmthing->player)
378 && ld->flags & ML_BLOCKMONSTERS)
379 return false; // block monsters only
380 }
381
382 // set openrange, opentop, openbottom
383 // these define a 'window' from one sector to another across this line
384
385 P_LineOpening (ld);
386
387 // adjust floor & ceiling heights
388
389 if (opentop < tmceilingz)
390 {
391 tmceilingz = opentop;
392 ceilingline = ld;
393 blockline = ld;
394 }
395
396 if (openbottom > tmfloorz)
397 {
398 tmfloorz = openbottom;
399 floorline = ld; // killough 8/1/98: remember floor linedef
400 blockline = ld;
401 }
402
403 if (lowfloor < tmdropoffz)
404 tmdropoffz = lowfloor;
405
406 // if contacted a special line, add it to the list
407
408 if (ld->special)
409 {
410 // 1/11/98 killough: remove limit on lines hit, by array doubling
411 if (numspechit >= spechit_max)
412 {
413 spechit_max = spechit_max ? spechit_max*2 : 8;
414 spechit = realloc(spechit,sizeof *spechit*spechit_max); // killough
415 }
416 spechit[numspechit++] = ld;
417 }
418
419 return true;
420}
421
422//
423// PIT_CheckThing
424//
425
426static boolean PIT_CheckThing(mobj_t *thing) // killough 3/26/98: make static
427{
428 fixed_t blockdist;
429 int damage;
430
431 // killough 11/98: add touchy things
432 if (!(thing->flags & (MF_SOLID|MF_SPECIAL|MF_SHOOTABLE|MF_TOUCHY)))
433 return true;
434
435 blockdist = thing->radius + tmthing->radius;
436
437 if (D_abs(thing->x - tmx) >= blockdist || D_abs(thing->y - tmy) >= blockdist)
438 return true; // didn't hit it
439
440 // killough 11/98:
441 //
442 // This test has less information content (it's almost always false), so it
443 // should not be moved up to first, as it adds more overhead than it removes.
444
445 // don't clip against self
446
447 if (thing == tmthing)
448 return true;
449
450 /* killough 11/98:
451 *
452 * TOUCHY flag, for mines or other objects which die on contact with solids.
453 * If a solid object of a different type comes in contact with a touchy
454 * thing, and the touchy thing is not the sole one moving relative to fixed
455 * surroundings such as walls, then the touchy thing dies immediately.
456 */
457
458 if (thing->flags & MF_TOUCHY && // touchy object
459 tmthing->flags & MF_SOLID && // solid object touches it
460 thing->health > 0 && // touchy object is alive
461 (thing->intflags & MIF_ARMED || // Thing is an armed mine
462 sentient(thing)) && // ... or a sentient thing
463 (thing->type != tmthing->type || // only different species
464 thing->type == MT_PLAYER) && // ... or different players
465 thing->z + thing->height >= tmthing->z && // touches vertically
466 tmthing->z + tmthing->height >= thing->z &&
467 (thing->type ^ MT_PAIN) | // PEs and lost souls
468 (tmthing->type ^ MT_SKULL) && // are considered same
469 (thing->type ^ MT_SKULL) | // (but Barons & Knights
470 (tmthing->type ^ MT_PAIN)) // are intentionally not)
471 {
472 P_DamageMobj(thing, NULL, NULL, thing->health); // kill object
473 return true;
474 }
475
476 // check for skulls slamming into things
477
478 if (tmthing->flags & MF_SKULLFLY)
479 {
480 // A flying skull is smacking something.
481 // Determine damage amount, and the skull comes to a dead stop.
482
483 int damage = ((P_Random(pr_skullfly)%8)+1)*tmthing->info->damage;
484
485 P_DamageMobj (thing, tmthing, tmthing, damage);
486
487 tmthing->flags &= ~MF_SKULLFLY;
488 tmthing->momx = tmthing->momy = tmthing->momz = 0;
489
490 P_SetMobjState (tmthing, tmthing->info->spawnstate);
491
492 return false; // stop moving
493 }
494
495 // missiles can hit other things
496 // killough 8/10/98: bouncing non-solid things can hit other things too
497
498 if (tmthing->flags & MF_MISSILE || (tmthing->flags & MF_BOUNCES &&
499 !(tmthing->flags & MF_SOLID)))
500 {
501 // see if it went over / under
502
503 if (tmthing->z > thing->z + thing->height)
504 return true; // overhead
505
506 if (tmthing->z+tmthing->height < thing->z)
507 return true; // underneath
508
509 if (tmthing->target && (tmthing->target->type == thing->type ||
510 (tmthing->target->type == MT_KNIGHT && thing->type == MT_BRUISER)||
511 (tmthing->target->type == MT_BRUISER && thing->type == MT_KNIGHT)))
512 {
513 if (thing == tmthing->target)
514 return true; // Don't hit same species as originator.
515 else
516 if (thing->type != MT_PLAYER) // Explode, but do no damage.
517 return false; // Let players missile other players.
518 }
519
520 // killough 8/10/98: if moving thing is not a missile, no damage
521 // is inflicted, and momentum is reduced if object hit is solid.
522
523 if (!(tmthing->flags & MF_MISSILE)) {
524 if (!(thing->flags & MF_SOLID)) {
525 return true;
526 } else {
527 tmthing->momx = -tmthing->momx;
528 tmthing->momy = -tmthing->momy;
529 if (!(tmthing->flags & MF_NOGRAVITY))
530 {
531 tmthing->momx >>= 2;
532 tmthing->momy >>= 2;
533 }
534 return false;
535 }
536 }
537
538 if (!(thing->flags & MF_SHOOTABLE))
539 return !(thing->flags & MF_SOLID); // didn't do any damage
540
541 // damage / explode
542
543 damage = ((P_Random(pr_damage)%8)+1)*tmthing->info->damage;
544 P_DamageMobj (thing, tmthing, tmthing->target, damage);
545
546 // don't traverse any more
547 return false;
548 }
549
550 // check for special pickup
551
552 if (thing->flags & MF_SPECIAL)
553 {
554 uint_64_t solid = thing->flags & MF_SOLID;
555 if (tmthing->flags & MF_PICKUP)
556 P_TouchSpecialThing(thing, tmthing); // can remove thing
557 return !solid;
558 }
559
560 // killough 3/16/98: Allow non-solid moving objects to move through solid
561 // ones, by allowing the moving thing (tmthing) to move if it's non-solid,
562 // despite another solid thing being in the way.
563 // killough 4/11/98: Treat no-clipping things as not blocking
564
565 return !((thing->flags & MF_SOLID && !(thing->flags & MF_NOCLIP))
566 && (tmthing->flags & MF_SOLID || demo_compatibility));
567
568 // return !(thing->flags & MF_SOLID); // old code -- killough
569}
570
571// This routine checks for Lost Souls trying to be spawned // phares
572// across 1-sided lines, impassible lines, or "monsters can't // |
573// cross" lines. Draw an imaginary line between the PE // V
574// and the new Lost Soul spawn spot. If that line crosses
575// a 'blocking' line, then disallow the spawn. Only search
576// lines in the blocks of the blockmap where the bounding box
577// of the trajectory line resides. Then check bounding box
578// of the trajectory vs. the bounding box of each blocking
579// line to see if the trajectory and the blocking line cross.
580// Then check the PE and LS to see if they're on different
581// sides of the blocking line. If so, return true, otherwise
582// false.
583
584boolean Check_Sides(mobj_t* actor, int x, int y)
585{
586 int bx,by,xl,xh,yl,yh;
587
588 pe_x = actor->x;
589 pe_y = actor->y;
590 ls_x = x;
591 ls_y = y;
592
593 // Here is the bounding box of the trajectory
594
595 tmbbox[BOXLEFT] = pe_x < x ? pe_x : x;
596 tmbbox[BOXRIGHT] = pe_x > x ? pe_x : x;
597 tmbbox[BOXTOP] = pe_y > y ? pe_y : y;
598 tmbbox[BOXBOTTOM] = pe_y < y ? pe_y : y;
599
600 // Determine which blocks to look in for blocking lines
601
602 xl = (tmbbox[BOXLEFT] - bmaporgx)>>MAPBLOCKSHIFT;
603 xh = (tmbbox[BOXRIGHT] - bmaporgx)>>MAPBLOCKSHIFT;
604 yl = (tmbbox[BOXBOTTOM] - bmaporgy)>>MAPBLOCKSHIFT;
605 yh = (tmbbox[BOXTOP] - bmaporgy)>>MAPBLOCKSHIFT;
606
607 // xl->xh, yl->yh determine the mapblock set to search
608
609 validcount++; // prevents checking same line twice
610 for (bx = xl ; bx <= xh ; bx++)
611 for (by = yl ; by <= yh ; by++)
612 if (!P_BlockLinesIterator(bx,by,PIT_CrossLine))
613 return true; // ^
614 return(false); // |
615} // phares
616
617//
618// MOVEMENT CLIPPING
619//
620
621//
622// P_CheckPosition
623// This is purely informative, nothing is modified
624// (except things picked up).
625//
626// in:
627// a mobj_t (can be valid or invalid)
628// a position to be checked
629// (doesn't need to be related to the mobj_t->x,y)
630//
631// during:
632// special things are touched if MF_PICKUP
633// early out on solid lines?
634//
635// out:
636// newsubsec
637// floorz
638// ceilingz
639// tmdropoffz
640// the lowest point contacted
641// (monsters won't move to a dropoff)
642// speciallines[]
643// numspeciallines
644//
645
646boolean P_CheckPosition (mobj_t* thing,fixed_t x,fixed_t y)
647{
648 int xl;
649 int xh;
650 int yl;
651 int yh;
652 int bx;
653 int by;
654 subsector_t* newsubsec;
655
656 tmthing = thing;
657
658 tmx = x;
659 tmy = y;
660
661 tmbbox[BOXTOP] = y + tmthing->radius;
662 tmbbox[BOXBOTTOM] = y - tmthing->radius;
663 tmbbox[BOXRIGHT] = x + tmthing->radius;
664 tmbbox[BOXLEFT] = x - tmthing->radius;
665
666 newsubsec = R_PointInSubsector (x,y);
667 floorline = blockline = ceilingline = NULL; // killough 8/1/98
668
669 // Whether object can get out of a sticky situation:
670 tmunstuck = thing->player && /* only players */
671 thing->player->mo == thing && /* not voodoo dolls */
672 mbf_features; /* not under old demos */
673
674 // The base floor / ceiling is from the subsector
675 // that contains the point.
676 // Any contacted lines the step closer together
677 // will adjust them.
678
679 tmfloorz = tmdropoffz = newsubsec->sector->floorheight;
680 tmceilingz = newsubsec->sector->ceilingheight;
681 validcount++;
682 numspechit = 0;
683
684 if ( tmthing->flags & MF_NOCLIP )
685 return true;
686
687 // Check things first, possibly picking things up.
688 // The bounding box is extended by MAXRADIUS
689 // because mobj_ts are grouped into mapblocks
690 // based on their origin point, and can overlap
691 // into adjacent blocks by up to MAXRADIUS units.
692
693 xl = (tmbbox[BOXLEFT] - bmaporgx - MAXRADIUS)>>MAPBLOCKSHIFT;
694 xh = (tmbbox[BOXRIGHT] - bmaporgx + MAXRADIUS)>>MAPBLOCKSHIFT;
695 yl = (tmbbox[BOXBOTTOM] - bmaporgy - MAXRADIUS)>>MAPBLOCKSHIFT;
696 yh = (tmbbox[BOXTOP] - bmaporgy + MAXRADIUS)>>MAPBLOCKSHIFT;
697
698
699 for (bx=xl ; bx<=xh ; bx++)
700 for (by=yl ; by<=yh ; by++)
701 if (!P_BlockThingsIterator(bx,by,PIT_CheckThing))
702 return false;
703
704 // check lines
705
706 xl = (tmbbox[BOXLEFT] - bmaporgx)>>MAPBLOCKSHIFT;
707 xh = (tmbbox[BOXRIGHT] - bmaporgx)>>MAPBLOCKSHIFT;
708 yl = (tmbbox[BOXBOTTOM] - bmaporgy)>>MAPBLOCKSHIFT;
709 yh = (tmbbox[BOXTOP] - bmaporgy)>>MAPBLOCKSHIFT;
710
711 for (bx=xl ; bx<=xh ; bx++)
712 for (by=yl ; by<=yh ; by++)
713 if (!P_BlockLinesIterator (bx,by,PIT_CheckLine))
714 return false; // doesn't fit
715
716 return true;
717}
718
719
720//
721// P_TryMove
722// Attempt to move to a new position,
723// crossing special lines unless MF_TELEPORT is set.
724//
725boolean P_TryMove(mobj_t* thing,fixed_t x,fixed_t y,
726 boolean dropoff) // killough 3/15/98: allow dropoff as option
727{
728 fixed_t oldx;
729 fixed_t oldy;
730
731 felldown = floatok = false; // killough 11/98
732
733 if (!P_CheckPosition (thing, x, y))
734 return false; // solid wall or thing
735
736 if ( !(thing->flags & MF_NOCLIP) )
737 {
738 // killough 7/26/98: reformatted slightly
739 // killough 8/1/98: Possibly allow escape if otherwise stuck
740
741 if (tmceilingz - tmfloorz < thing->height || // doesn't fit
742 // mobj must lower to fit
743 (floatok = true, !(thing->flags & MF_TELEPORT) &&
744 tmceilingz - thing->z < thing->height) ||
745 // too big a step up
746 (!(thing->flags & MF_TELEPORT) &&
747 tmfloorz - thing->z > 24*FRACUNIT))
748 return tmunstuck
749 && !(ceilingline && untouched(ceilingline))
750 && !( floorline && untouched( floorline));
751
752 /* killough 3/15/98: Allow certain objects to drop off
753 * killough 7/24/98, 8/1/98:
754 * Prevent monsters from getting stuck hanging off ledges
755 * killough 10/98: Allow dropoffs in controlled circumstances
756 * killough 11/98: Improve symmetry of clipping on stairs
757 */
758
759 if (!(thing->flags & (MF_DROPOFF|MF_FLOAT))) {
760 if (comp[comp_dropoff])
761 {
762 if ((compatibility || !dropoff) && (tmfloorz - tmdropoffz > 24*FRACUNIT))
763 return false; // don't stand over a dropoff
764 }
765 else
766 if (!dropoff || (dropoff==2 && // large jump down (e.g. dogs)
767 (tmfloorz-tmdropoffz > 128*FRACUNIT ||
768 !thing->target || thing->target->z >tmdropoffz)))
769 {
770 if (!monkeys || !mbf_features ?
771 tmfloorz - tmdropoffz > 24*FRACUNIT :
772 thing->floorz - tmfloorz > 24*FRACUNIT ||
773 thing->dropoffz - tmdropoffz > 24*FRACUNIT)
774 return false;
775 }
776 else { /* dropoff allowed -- check for whether it fell more than 24 */
777 felldown = !(thing->flags & MF_NOGRAVITY) &&
778 thing->z - tmfloorz > 24*FRACUNIT;
779 }
780 }
781
782 if (thing->flags & MF_BOUNCES && // killough 8/13/98
783 !(thing->flags & (MF_MISSILE|MF_NOGRAVITY)) &&
784 !sentient(thing) && tmfloorz - thing->z > 16*FRACUNIT)
785 return false; // too big a step up for bouncers under gravity
786
787 // killough 11/98: prevent falling objects from going up too many steps
788 if (thing->intflags & MIF_FALLING && tmfloorz - thing->z >
789 FixedMul(thing->momx,thing->momx)+FixedMul(thing->momy,thing->momy))
790 return false;
791 }
792
793 // the move is ok,
794 // so unlink from the old position and link into the new position
795
796 P_UnsetThingPosition (thing);
797
798 oldx = thing->x;
799 oldy = thing->y;
800 thing->floorz = tmfloorz;
801 thing->ceilingz = tmceilingz;
802 thing->dropoffz = tmdropoffz; // killough 11/98: keep track of dropoffs
803 thing->x = x;
804 thing->y = y;
805
806 P_SetThingPosition (thing);
807
808 // if any special lines were hit, do the effect
809
810 if (! (thing->flags&(MF_TELEPORT|MF_NOCLIP)) )
811 while (numspechit--)
812 if (spechit[numspechit]->special) // see if the line was crossed
813 {
814 int oldside;
815 if ((oldside = P_PointOnLineSide(oldx, oldy, spechit[numspechit])) !=
816 P_PointOnLineSide(thing->x, thing->y, spechit[numspechit]))
817 P_CrossSpecialLine(spechit[numspechit], oldside, thing);
818 }
819
820 return true;
821}
822
823/*
824 * killough 9/12/98:
825 *
826 * Apply "torque" to objects hanging off of ledges, so that they
827 * fall off. It's not really torque, since Doom has no concept of
828 * rotation, but it's a convincing effect which avoids anomalies
829 * such as lifeless objects hanging more than halfway off of ledges,
830 * and allows objects to roll off of the edges of moving lifts, or
831 * to slide up and then back down stairs, or to fall into a ditch.
832 * If more than one linedef is contacted, the effects are cumulative,
833 * so balancing is possible.
834 */
835
836static boolean PIT_ApplyTorque(line_t *ld)
837{
838 if (ld->backsector && // If thing touches two-sided pivot linedef
839 tmbbox[BOXRIGHT] > ld->bbox[BOXLEFT] &&
840 tmbbox[BOXLEFT] < ld->bbox[BOXRIGHT] &&
841 tmbbox[BOXTOP] > ld->bbox[BOXBOTTOM] &&
842 tmbbox[BOXBOTTOM] < ld->bbox[BOXTOP] &&
843 P_BoxOnLineSide(tmbbox, ld) == -1)
844 {
845 mobj_t *mo = tmthing;
846
847 fixed_t dist = // lever arm
848 + (ld->dx >> FRACBITS) * (mo->y >> FRACBITS)
849 - (ld->dy >> FRACBITS) * (mo->x >> FRACBITS)
850 - (ld->dx >> FRACBITS) * (ld->v1->y >> FRACBITS)
851 + (ld->dy >> FRACBITS) * (ld->v1->x >> FRACBITS);
852
853 if (dist < 0 ? // dropoff direction
854 ld->frontsector->floorheight < mo->z &&
855 ld->backsector->floorheight >= mo->z :
856 ld->backsector->floorheight < mo->z &&
857 ld->frontsector->floorheight >= mo->z)
858 {
859 /* At this point, we know that the object straddles a two-sided
860 * linedef, and that the object's center of mass is above-ground.
861 */
862
863 fixed_t x = D_abs(ld->dx), y = D_abs(ld->dy);
864
865 if (y > x)
866 {
867 fixed_t t = x;
868 x = y;
869 y = t;
870 }
871
872 y = finesine[(tantoangle[FixedDiv(y,x)>>DBITS] +
873 ANG90) >> ANGLETOFINESHIFT];
874
875 /* Momentum is proportional to distance between the
876 * object's center of mass and the pivot linedef.
877 *
878 * It is scaled by 2^(OVERDRIVE - gear). When gear is
879 * increased, the momentum gradually decreases to 0 for
880 * the same amount of pseudotorque, so that oscillations
881 * are prevented, yet it has a chance to reach equilibrium.
882 */
883 dist = FixedDiv(FixedMul(dist, (mo->gear < OVERDRIVE) ?
884 y << -(mo->gear - OVERDRIVE) :
885 y >> +(mo->gear - OVERDRIVE)), x);
886
887 /* Apply momentum away from the pivot linedef. */
888
889 x = FixedMul(ld->dy, dist);
890 y = FixedMul(ld->dx, dist);
891
892 /* Avoid moving too fast all of a sudden (step into "overdrive") */
893
894 dist = FixedMul(x,x) + FixedMul(y,y);
895
896 while (dist > FRACUNIT*4 && mo->gear < MAXGEAR)
897 ++mo->gear, x >>= 1, y >>= 1, dist >>= 1;
898
899 mo->momx -= x;
900 mo->momy += y;
901 }
902 }
903 return true;
904}
905
906/*
907 * killough 9/12/98
908 *
909 * Applies "torque" to objects, based on all contacted linedefs
910 */
911
912void P_ApplyTorque(mobj_t *mo)
913{
914 int xl = ((tmbbox[BOXLEFT] =
915 mo->x - mo->radius) - bmaporgx) >> MAPBLOCKSHIFT;
916 int xh = ((tmbbox[BOXRIGHT] =
917 mo->x + mo->radius) - bmaporgx) >> MAPBLOCKSHIFT;
918 int yl = ((tmbbox[BOXBOTTOM] =
919 mo->y - mo->radius) - bmaporgy) >> MAPBLOCKSHIFT;
920 int yh = ((tmbbox[BOXTOP] =
921 mo->y + mo->radius) - bmaporgy) >> MAPBLOCKSHIFT;
922 int bx,by,flags = mo->intflags; //Remember the current state, for gear-change
923
924 tmthing = mo;
925 validcount++; /* prevents checking same line twice */
926
927 for (bx = xl ; bx <= xh ; bx++)
928 for (by = yl ; by <= yh ; by++)
929 P_BlockLinesIterator(bx, by, PIT_ApplyTorque);
930
931 /* If any momentum, mark object as 'falling' using engine-internal flags */
932 if (mo->momx | mo->momy)
933 mo->intflags |= MIF_FALLING;
934 else // Clear the engine-internal flag indicating falling object.
935 mo->intflags &= ~MIF_FALLING;
936
937 /* If the object has been moving, step up the gear.
938 * This helps reach equilibrium and avoid oscillations.
939 *
940 * Doom has no concept of potential energy, much less
941 * of rotation, so we have to creatively simulate these
942 * systems somehow :)
943 */
944
945 if (!((mo->intflags | flags) & MIF_FALLING)) // If not falling for a while,
946 mo->gear = 0; // Reset it to full strength
947 else
948 if (mo->gear < MAXGEAR) // Else if not at max gear,
949 mo->gear++; // move up a gear
950}
951
952//
953// P_ThingHeightClip
954// Takes a valid thing and adjusts the thing->floorz,
955// thing->ceilingz, and possibly thing->z.
956// This is called for all nearby monsters
957// whenever a sector changes height.
958// If the thing doesn't fit,
959// the z will be set to the lowest value
960// and false will be returned.
961//
962
963boolean P_ThingHeightClip (mobj_t* thing)
964{
965 boolean onfloor;
966
967 onfloor = (thing->z == thing->floorz);
968
969 P_CheckPosition (thing, thing->x, thing->y);
970
971 /* what about stranding a monster partially off an edge?
972 * killough 11/98: Answer: see below (upset balance if hanging off ledge)
973 */
974
975 thing->floorz = tmfloorz;
976 thing->ceilingz = tmceilingz;
977 thing->dropoffz = tmdropoffz; /* killough 11/98: remember dropoffs */
978
979 if (onfloor)
980 {
981
982 // walking monsters rise and fall with the floor
983
984 thing->z = thing->floorz;
985
986 /* killough 11/98: Possibly upset balance of objects hanging off ledges */
987 if (thing->intflags & MIF_FALLING && thing->gear >= MAXGEAR)
988 thing->gear = 0;
989 }
990 else
991 {
992
993 // don't adjust a floating monster unless forced to
994
995 if (thing->z+thing->height > thing->ceilingz)
996 thing->z = thing->ceilingz - thing->height;
997 }
998
999 return thing->ceilingz - thing->floorz >= thing->height;
1000}
1001
1002
1003//
1004// SLIDE MOVE
1005// Allows the player to slide along any angled walls.
1006//
1007
1008/* killough 8/2/98: make variables static */
1009static fixed_t bestslidefrac;
1010static fixed_t secondslidefrac;
1011static line_t* bestslideline;
1012static line_t* secondslideline;
1013static mobj_t* slidemo;
1014static fixed_t tmxmove;
1015static fixed_t tmymove;
1016
1017
1018//
1019// P_HitSlideLine
1020// Adjusts the xmove / ymove
1021// so that the next move will slide along the wall.
1022// If the floor is icy, then you can bounce off a wall. // phares
1023//
1024
1025void P_HitSlideLine (line_t* ld)
1026{
1027 int side;
1028 angle_t lineangle;
1029 angle_t moveangle;
1030 angle_t deltaangle;
1031 fixed_t movelen;
1032 fixed_t newlen;
1033 boolean icyfloor; // is floor icy? // phares
1034 // |
1035 // Under icy conditions, if the angle of approach to the wall // V
1036 // is more than 45 degrees, then you'll bounce and lose half
1037 // your momentum. If less than 45 degrees, you'll slide along
1038 // the wall. 45 is arbitrary and is believable.
1039
1040 // Check for the special cases of horz or vert walls.
1041
1042 /* killough 10/98: only bounce if hit hard (prevents wobbling)
1043 * cph - DEMOSYNC - should only affect players in Boom demos? */
1044 icyfloor =
1045 (mbf_features ?
1046 P_AproxDistance(tmxmove, tmymove) > 4*FRACUNIT : !compatibility) &&
1047 variable_friction && // killough 8/28/98: calc friction on demand
1048 slidemo->z <= slidemo->floorz &&
1049 P_GetFriction(slidemo, NULL) > ORIG_FRICTION;
1050
1051 if (ld->slopetype == ST_HORIZONTAL)
1052 {
1053 if (icyfloor && (D_abs(tmymove) > D_abs(tmxmove)))
1054 {
1055 tmxmove /= 2; // absorb half the momentum
1056 tmymove = -tmymove/2;
1057 S_StartSound(slidemo,sfx_oof); // oooff!
1058 }
1059 else
1060 tmymove = 0; // no more movement in the Y direction
1061 return;
1062 }
1063
1064 if (ld->slopetype == ST_VERTICAL)
1065 {
1066 if (icyfloor && (D_abs(tmxmove) > D_abs(tmymove)))
1067 {
1068 tmxmove = -tmxmove/2; // absorb half the momentum
1069 tmymove /= 2;
1070 S_StartSound(slidemo,sfx_oof); // oooff! // ^
1071 } // |
1072 else // phares
1073 tmxmove = 0; // no more movement in the X direction
1074 return;
1075 }
1076
1077 // The wall is angled. Bounce if the angle of approach is // phares
1078 // less than 45 degrees. // phares
1079
1080 side = P_PointOnLineSide (slidemo->x, slidemo->y, ld);
1081
1082 lineangle = R_PointToAngle2 (0,0, ld->dx, ld->dy);
1083 if (side == 1)
1084 lineangle += ANG180;
1085 moveangle = R_PointToAngle2 (0,0, tmxmove, tmymove);
1086
1087 // killough 3/2/98:
1088 // The moveangle+=10 breaks v1.9 demo compatibility in
1089 // some demos, so it needs demo_compatibility switch.
1090
1091 if (!demo_compatibility)
1092 moveangle += 10; // prevents sudden path reversal due to // phares
1093 // rounding error // |
1094 deltaangle = moveangle-lineangle; // V
1095 movelen = P_AproxDistance (tmxmove, tmymove);
1096 if (icyfloor && (deltaangle > ANG45) && (deltaangle < ANG90+ANG45))
1097 {
1098 moveangle = lineangle - deltaangle;
1099 movelen /= 2; // absorb
1100 S_StartSound(slidemo,sfx_oof); // oooff!
1101 moveangle >>= ANGLETOFINESHIFT;
1102 tmxmove = FixedMul (movelen, finecosine[moveangle]);
1103 tmymove = FixedMul (movelen, finesine[moveangle]);
1104 } // ^
1105 else // |
1106 { // phares
1107 if (deltaangle > ANG180)
1108 deltaangle += ANG180;
1109
1110 // I_Error ("SlideLine: ang>ANG180");
1111
1112 lineangle >>= ANGLETOFINESHIFT;
1113 deltaangle >>= ANGLETOFINESHIFT;
1114 newlen = FixedMul (movelen, finecosine[deltaangle]);
1115 tmxmove = FixedMul (newlen, finecosine[lineangle]);
1116 tmymove = FixedMul (newlen, finesine[lineangle]);
1117 } // phares
1118}
1119
1120
1121//
1122// PTR_SlideTraverse
1123//
1124
1125boolean PTR_SlideTraverse (intercept_t* in)
1126{
1127 line_t* li;
1128
1129 if (!in->isaline)
1130 I_Error ("PTR_SlideTraverse: not a line?");
1131
1132 li = in->d.line;
1133
1134 if ( ! (li->flags & ML_TWOSIDED) )
1135 {
1136 if (P_PointOnLineSide (slidemo->x, slidemo->y, li))
1137 return true; // don't hit the back side
1138 goto isblocking;
1139 }
1140
1141 // set openrange, opentop, openbottom.
1142 // These define a 'window' from one sector to another across a line
1143
1144 P_LineOpening (li);
1145
1146 if (openrange < slidemo->height)
1147 goto isblocking; // doesn't fit
1148
1149 if (opentop - slidemo->z < slidemo->height)
1150 goto isblocking; // mobj is too high
1151
1152 if (openbottom - slidemo->z > 24*FRACUNIT )
1153 goto isblocking; // too big a step up
1154
1155 // this line doesn't block movement
1156
1157 return true;
1158
1159 // the line does block movement,
1160 // see if it is closer than best so far
1161
1162isblocking:
1163
1164 if (in->frac < bestslidefrac)
1165 {
1166 secondslidefrac = bestslidefrac;
1167 secondslideline = bestslideline;
1168 bestslidefrac = in->frac;
1169 bestslideline = li;
1170 }
1171
1172 return false; // stop
1173}
1174
1175
1176//
1177// P_SlideMove
1178// The momx / momy move is bad, so try to slide
1179// along a wall.
1180// Find the first line hit, move flush to it,
1181// and slide along it
1182//
1183// This is a kludgy mess.
1184//
1185// killough 11/98: reformatted
1186
1187void P_SlideMove(mobj_t *mo)
1188{
1189 int hitcount = 3;
1190
1191 slidemo = mo; // the object that's sliding
1192
1193 do
1194 {
1195 fixed_t leadx, leady, trailx, traily;
1196
1197 if (!--hitcount)
1198 goto stairstep; // don't loop forever
1199
1200 // trace along the three leading corners
1201
1202 if (mo->momx > 0)
1203 leadx = mo->x + mo->radius, trailx = mo->x - mo->radius;
1204 else
1205 leadx = mo->x - mo->radius, trailx = mo->x + mo->radius;
1206
1207 if (mo->momy > 0)
1208 leady = mo->y + mo->radius, traily = mo->y - mo->radius;
1209 else
1210 leady = mo->y - mo->radius, traily = mo->y + mo->radius;
1211
1212 bestslidefrac = FRACUNIT+1;
1213
1214 P_PathTraverse(leadx, leady, leadx+mo->momx, leady+mo->momy,
1215 PT_ADDLINES, PTR_SlideTraverse);
1216 P_PathTraverse(trailx, leady, trailx+mo->momx, leady+mo->momy,
1217 PT_ADDLINES, PTR_SlideTraverse);
1218 P_PathTraverse(leadx, traily, leadx+mo->momx, traily+mo->momy,
1219 PT_ADDLINES, PTR_SlideTraverse);
1220
1221 // move up to the wall
1222
1223 if (bestslidefrac == FRACUNIT+1)
1224 {
1225 // the move must have hit the middle, so stairstep
1226
1227stairstep:
1228
1229 /* killough 3/15/98: Allow objects to drop off ledges
1230 *
1231 * phares 5/4/98: kill momentum if you can't move at all
1232 * This eliminates player bobbing if pressed against a wall
1233 * while on ice.
1234 *
1235 * killough 10/98: keep buggy code around for old Boom demos
1236 *
1237 * cph 2000/09//23: buggy code was only in Boom v2.01
1238 */
1239
1240 if (!P_TryMove(mo, mo->x, mo->y + mo->momy, true))
1241 if (!P_TryMove(mo, mo->x + mo->momx, mo->y, true))
1242 if (compatibility_level == boom_201_compatibility)
1243 mo->momx = mo->momy = 0;
1244
1245 break;
1246 }
1247
1248 // fudge a bit to make sure it doesn't hit
1249
1250 if ((bestslidefrac -= 0x800) > 0)
1251 {
1252 fixed_t newx = FixedMul(mo->momx, bestslidefrac);
1253 fixed_t newy = FixedMul(mo->momy, bestslidefrac);
1254
1255 // killough 3/15/98: Allow objects to drop off ledges
1256
1257 if (!P_TryMove(mo, mo->x+newx, mo->y+newy, true))
1258 goto stairstep;
1259 }
1260
1261 // Now continue along the wall.
1262 // First calculate remainder.
1263
1264 bestslidefrac = FRACUNIT-(bestslidefrac+0x800);
1265
1266 if (bestslidefrac > FRACUNIT)
1267 bestslidefrac = FRACUNIT;
1268
1269 if (bestslidefrac <= 0)
1270 break;
1271
1272 tmxmove = FixedMul(mo->momx, bestslidefrac);
1273 tmymove = FixedMul(mo->momy, bestslidefrac);
1274
1275 P_HitSlideLine(bestslideline); // clip the moves
1276
1277 mo->momx = tmxmove;
1278 mo->momy = tmymove;
1279
1280 /* killough 10/98: affect the bobbing the same way (but not voodoo dolls)
1281 * cph - DEMOSYNC? */
1282 if (mo->player && mo->player->mo == mo)
1283 {
1284 if (D_abs(mo->player->momx) > D_abs(tmxmove))
1285 mo->player->momx = tmxmove;
1286 if (D_abs(mo->player->momy) > D_abs(tmymove))
1287 mo->player->momy = tmymove;
1288 }
1289 } // killough 3/15/98: Allow objects to drop off ledges:
1290 while (!P_TryMove(mo, mo->x+tmxmove, mo->y+tmymove, true));
1291}
1292
1293//
1294// P_LineAttack
1295//
1296mobj_t* linetarget; // who got hit (or NULL)
1297static mobj_t* shootthing;
1298
1299/* killough 8/2/98: for more intelligent autoaiming */
1300static uint_64_t aim_flags_mask;
1301
1302// Height if not aiming up or down
1303fixed_t shootz;
1304
1305int la_damage;
1306fixed_t attackrange;
1307
1308static fixed_t aimslope;
1309
1310// slopes to top and bottom of target
1311// killough 4/20/98: make static instead of using ones in p_sight.c
1312
1313static fixed_t topslope;
1314static fixed_t bottomslope;
1315
1316
1317//
1318// PTR_AimTraverse
1319// Sets linetaget and aimslope when a target is aimed at.
1320//
1321boolean PTR_AimTraverse (intercept_t* in)
1322{
1323 line_t* li;
1324 mobj_t* th;
1325 fixed_t slope;
1326 fixed_t thingtopslope;
1327 fixed_t thingbottomslope;
1328 fixed_t dist;
1329
1330 if (in->isaline)
1331 {
1332 li = in->d.line;
1333
1334 if ( !(li->flags & ML_TWOSIDED) )
1335 return false; // stop
1336
1337 // Crosses a two sided line.
1338 // A two sided line will restrict
1339 // the possible target ranges.
1340
1341 P_LineOpening (li);
1342
1343 if (openbottom >= opentop)
1344 return false; // stop
1345
1346 dist = FixedMul (attackrange, in->frac);
1347
1348 if (li->frontsector->floorheight != li->backsector->floorheight)
1349 {
1350 slope = FixedDiv (openbottom - shootz , dist);
1351 if (slope > bottomslope)
1352 bottomslope = slope;
1353 }
1354
1355 if (li->frontsector->ceilingheight != li->backsector->ceilingheight)
1356 {
1357 slope = FixedDiv (opentop - shootz , dist);
1358 if (slope < topslope)
1359 topslope = slope;
1360 }
1361
1362 if (topslope <= bottomslope)
1363 return false; // stop
1364
1365 return true; // shot continues
1366 }
1367
1368 // shoot a thing
1369
1370 th = in->d.thing;
1371 if (th == shootthing)
1372 return true; // can't shoot self
1373
1374 if (!(th->flags&MF_SHOOTABLE))
1375 return true; // corpse or something
1376
1377 /* killough 7/19/98, 8/2/98:
1378 * friends don't aim at friends (except players), at least not first
1379 */
1380 if (th->flags & shootthing->flags & aim_flags_mask && !th->player)
1381 return true;
1382
1383 // check angles to see if the thing can be aimed at
1384
1385 dist = FixedMul (attackrange, in->frac);
1386 thingtopslope = FixedDiv (th->z+th->height - shootz , dist);
1387
1388 if (thingtopslope < bottomslope)
1389 return true; // shot over the thing
1390
1391 thingbottomslope = FixedDiv (th->z - shootz, dist);
1392
1393 if (thingbottomslope > topslope)
1394 return true; // shot under the thing
1395
1396 // this thing can be hit!
1397
1398 if (thingtopslope > topslope)
1399 thingtopslope = topslope;
1400
1401 if (thingbottomslope < bottomslope)
1402 thingbottomslope = bottomslope;
1403
1404 aimslope = (thingtopslope+thingbottomslope)/2;
1405 linetarget = th;
1406
1407 return false; // don't go any farther
1408}
1409
1410
1411//
1412// PTR_ShootTraverse
1413//
1414boolean PTR_ShootTraverse (intercept_t* in)
1415{
1416 fixed_t x;
1417 fixed_t y;
1418 fixed_t z;
1419 fixed_t frac;
1420
1421 mobj_t* th;
1422
1423 fixed_t slope;
1424 fixed_t dist;
1425 fixed_t thingtopslope;
1426 fixed_t thingbottomslope;
1427
1428 if (in->isaline)
1429 {
1430 line_t *li = in->d.line;
1431
1432 if (li->special)
1433 P_ShootSpecialLine (shootthing, li);
1434
1435 if (li->flags & ML_TWOSIDED)
1436 { // crosses a two sided (really 2s) line
1437 P_LineOpening (li);
1438 dist = FixedMul(attackrange, in->frac);
1439
1440 // killough 11/98: simplify
1441
1442 if ((li->frontsector->floorheight==li->backsector->floorheight ||
1443 (slope = FixedDiv(openbottom - shootz , dist)) <= aimslope) &&
1444 (li->frontsector->ceilingheight==li->backsector->ceilingheight ||
1445 (slope = FixedDiv (opentop - shootz , dist)) >= aimslope))
1446 return true; // shot continues
1447 }
1448
1449 // hit line
1450 // position a bit closer
1451
1452 frac = in->frac - FixedDiv (4*FRACUNIT,attackrange);
1453 x = trace.x + FixedMul (trace.dx, frac);
1454 y = trace.y + FixedMul (trace.dy, frac);
1455 z = shootz + FixedMul (aimslope, FixedMul(frac, attackrange));
1456
1457 if (li->frontsector->ceilingpic == skyflatnum)
1458 {
1459 // don't shoot the sky!
1460
1461 if (z > li->frontsector->ceilingheight)
1462 return false;
1463
1464 // it's a sky hack wall
1465
1466 if (li->backsector && li->backsector->ceilingpic == skyflatnum)
1467
1468 // fix bullet-eaters -- killough:
1469 // WARNING: Almost all demos will lose sync without this
1470 // demo_compatibility flag check!!! killough 1/18/98
1471 if (demo_compatibility || li->backsector->ceilingheight < z)
1472 return false;
1473 }
1474
1475 // Spawn bullet puffs.
1476
1477 P_SpawnPuff (x,y,z);
1478
1479 // don't go any farther
1480
1481 return false;
1482 }
1483
1484 // shoot a thing
1485
1486 th = in->d.thing;
1487 if (th == shootthing)
1488 return true; // can't shoot self
1489
1490 if (!(th->flags&MF_SHOOTABLE))
1491 return true; // corpse or something
1492
1493 // check angles to see if the thing can be aimed at
1494
1495 dist = FixedMul (attackrange, in->frac);
1496 thingtopslope = FixedDiv (th->z+th->height - shootz , dist);
1497
1498 if (thingtopslope < aimslope)
1499 return true; // shot over the thing
1500
1501 thingbottomslope = FixedDiv (th->z - shootz, dist);
1502
1503 if (thingbottomslope > aimslope)
1504 return true; // shot under the thing
1505
1506 // hit thing
1507 // position a bit closer
1508
1509 frac = in->frac - FixedDiv (10*FRACUNIT,attackrange);
1510
1511 x = trace.x + FixedMul (trace.dx, frac);
1512 y = trace.y + FixedMul (trace.dy, frac);
1513 z = shootz + FixedMul (aimslope, FixedMul(frac, attackrange));
1514
1515 // Spawn bullet puffs or blod spots,
1516 // depending on target type.
1517 if (in->d.thing->flags & MF_NOBLOOD)
1518 P_SpawnPuff (x,y,z);
1519 else
1520 P_SpawnBlood (x,y,z, la_damage);
1521
1522 if (la_damage)
1523 P_DamageMobj (th, shootthing, shootthing, la_damage);
1524
1525 // don't go any farther
1526 return false;
1527}
1528
1529
1530//
1531// P_AimLineAttack
1532//
1533fixed_t P_AimLineAttack(mobj_t* t1,angle_t angle,fixed_t distance, uint_64_t mask)
1534{
1535 fixed_t x2;
1536 fixed_t y2;
1537
1538 angle >>= ANGLETOFINESHIFT;
1539 shootthing = t1;
1540
1541 x2 = t1->x + (distance>>FRACBITS)*finecosine[angle];
1542 y2 = t1->y + (distance>>FRACBITS)*finesine[angle];
1543 shootz = t1->z + (t1->height>>1) + 8*FRACUNIT;
1544
1545 // can't shoot outside view angles
1546
1547 topslope = 100*FRACUNIT/160;
1548 bottomslope = -100*FRACUNIT/160;
1549
1550 attackrange = distance;
1551 linetarget = NULL;
1552
1553 /* killough 8/2/98: prevent friends from aiming at friends */
1554 aim_flags_mask = mask;
1555
1556 P_PathTraverse(t1->x,t1->y,x2,y2,PT_ADDLINES|PT_ADDTHINGS,PTR_AimTraverse);
1557
1558 if (linetarget)
1559 return aimslope;
1560
1561 return 0;
1562}
1563
1564
1565//
1566// P_LineAttack
1567// If damage == 0, it is just a test trace
1568// that will leave linetarget set.
1569//
1570
1571void P_LineAttack
1572(mobj_t* t1,
1573 angle_t angle,
1574 fixed_t distance,
1575 fixed_t slope,
1576 int damage)
1577{
1578 fixed_t x2;
1579 fixed_t y2;
1580
1581 angle >>= ANGLETOFINESHIFT;
1582 shootthing = t1;
1583 la_damage = damage;
1584 x2 = t1->x + (distance>>FRACBITS)*finecosine[angle];
1585 y2 = t1->y + (distance>>FRACBITS)*finesine[angle];
1586 shootz = t1->z + (t1->height>>1) + 8*FRACUNIT;
1587 attackrange = distance;
1588 aimslope = slope;
1589
1590 P_PathTraverse(t1->x,t1->y,x2,y2,PT_ADDLINES|PT_ADDTHINGS,PTR_ShootTraverse);
1591}
1592
1593
1594//
1595// USE LINES
1596//
1597
1598mobj_t* usething;
1599
1600boolean PTR_UseTraverse (intercept_t* in)
1601{
1602 int side;
1603
1604 if (!in->d.line->special)
1605 {
1606 P_LineOpening (in->d.line);
1607 if (openrange <= 0)
1608 {
1609 S_StartSound (usething, sfx_noway);
1610
1611 // can't use through a wall
1612 return false;
1613 }
1614
1615 // not a special line, but keep checking
1616
1617 return true;
1618 }
1619
1620 side = 0;
1621 if (P_PointOnLineSide (usething->x, usething->y, in->d.line) == 1)
1622 side = 1;
1623
1624 // return false; // don't use back side
1625
1626 P_UseSpecialLine (usething, in->d.line, side);
1627
1628 //WAS can't use for than one special line in a row
1629 //jff 3/21/98 NOW multiple use allowed with enabling line flag
1630
1631 return (!demo_compatibility && (in->d.line->flags&ML_PASSUSE))?
1632 true : false;
1633}
1634
1635// Returns false if a "oof" sound should be made because of a blocking
1636// linedef. Makes 2s middles which are impassable, as well as 2s uppers
1637// and lowers which block the player, cause the sound effect when the
1638// player tries to activate them. Specials are excluded, although it is
1639// assumed that all special linedefs within reach have been considered
1640// and rejected already (see P_UseLines).
1641//
1642// by Lee Killough
1643//
1644
1645boolean PTR_NoWayTraverse(intercept_t* in)
1646{
1647 line_t *ld = in->d.line;
1648 // This linedef
1649 return ld->special || !( // Ignore specials
1650 ld->flags & ML_BLOCKING || ( // Always blocking
1651 P_LineOpening(ld), // Find openings
1652 openrange <= 0 || // No opening
1653 openbottom > usething->z+24*FRACUNIT || // Too high it blocks
1654 opentop < usething->z+usething->height // Too low it blocks
1655 )
1656 );
1657}
1658
1659//
1660// P_UseLines
1661// Looks for special lines in front of the player to activate.
1662//
1663void P_UseLines (player_t* player)
1664{
1665 int angle;
1666 fixed_t x1;
1667 fixed_t y1;
1668 fixed_t x2;
1669 fixed_t y2;
1670
1671 usething = player->mo;
1672
1673 angle = player->mo->angle >> ANGLETOFINESHIFT;
1674
1675 x1 = player->mo->x;
1676 y1 = player->mo->y;
1677 x2 = x1 + (USERANGE>>FRACBITS)*finecosine[angle];
1678 y2 = y1 + (USERANGE>>FRACBITS)*finesine[angle];
1679
1680 // old code:
1681 //
1682 // P_PathTraverse ( x1, y1, x2, y2, PT_ADDLINES, PTR_UseTraverse );
1683 //
1684 // This added test makes the "oof" sound work on 2s lines -- killough:
1685
1686 if (P_PathTraverse ( x1, y1, x2, y2, PT_ADDLINES, PTR_UseTraverse ))
1687 if (!comp[comp_sound] && !P_PathTraverse ( x1, y1, x2, y2, PT_ADDLINES, PTR_NoWayTraverse ))
1688 S_StartSound (usething, sfx_noway);
1689}
1690
1691
1692//
1693// RADIUS ATTACK
1694//
1695
1696static mobj_t *bombsource, *bombspot;
1697static int bombdamage;
1698
1699
1700//
1701// PIT_RadiusAttack
1702// "bombsource" is the creature
1703// that caused the explosion at "bombspot".
1704//
1705
1706boolean PIT_RadiusAttack (mobj_t* thing)
1707{
1708 fixed_t dx;
1709 fixed_t dy;
1710 fixed_t dist;
1711
1712 /* killough 8/20/98: allow bouncers to take damage
1713 * (missile bouncers are already excluded with MF_NOBLOCKMAP)
1714 */
1715
1716 if (!(thing->flags & (MF_SHOOTABLE | MF_BOUNCES)))
1717 return true;
1718
1719 // Boss spider and cyborg
1720 // take no damage from concussion.
1721
1722 // killough 8/10/98: allow grenades to hurt anyone, unless
1723 // fired by Cyberdemons, in which case it won't hurt Cybers.
1724
1725 if (bombspot->flags & MF_BOUNCES ?
1726 thing->type == MT_CYBORG && bombsource->type == MT_CYBORG :
1727 thing->type == MT_CYBORG || thing->type == MT_SPIDER)
1728 return true;
1729
1730 dx = D_abs(thing->x - bombspot->x);
1731 dy = D_abs(thing->y - bombspot->y);
1732
1733 dist = dx>dy ? dx : dy;
1734 dist = (dist - thing->radius) >> FRACBITS;
1735
1736 if (dist < 0)
1737 dist = 0;
1738
1739 if (dist >= bombdamage)
1740 return true; // out of range
1741
1742 if ( P_CheckSight (thing, bombspot) )
1743 {
1744 // must be in direct path
1745 P_DamageMobj (thing, bombspot, bombsource, bombdamage - dist);
1746 }
1747
1748 return true;
1749}
1750
1751
1752//
1753// P_RadiusAttack
1754// Source is the creature that caused the explosion at spot.
1755//
1756void P_RadiusAttack(mobj_t* spot,mobj_t* source,int damage)
1757{
1758 int x;
1759 int y;
1760
1761 int xl;
1762 int xh;
1763 int yl;
1764 int yh;
1765
1766 fixed_t dist;
1767
1768 dist = (damage+MAXRADIUS)<<FRACBITS;
1769 yh = (spot->y + dist - bmaporgy)>>MAPBLOCKSHIFT;
1770 yl = (spot->y - dist - bmaporgy)>>MAPBLOCKSHIFT;
1771 xh = (spot->x + dist - bmaporgx)>>MAPBLOCKSHIFT;
1772 xl = (spot->x - dist - bmaporgx)>>MAPBLOCKSHIFT;
1773 bombspot = spot;
1774 bombsource = source;
1775 bombdamage = damage;
1776
1777 for (y=yl ; y<=yh ; y++)
1778 for (x=xl ; x<=xh ; x++)
1779 P_BlockThingsIterator (x, y, PIT_RadiusAttack );
1780}
1781
1782
1783
1784//
1785// SECTOR HEIGHT CHANGING
1786// After modifying a sectors floor or ceiling height,
1787// call this routine to adjust the positions
1788// of all things that touch the sector.
1789//
1790// If anything doesn't fit anymore, true will be returned.
1791// If crunch is true, they will take damage
1792// as they are being crushed.
1793// If Crunch is false, you should set the sector height back
1794// the way it was and call P_ChangeSector again
1795// to undo the changes.
1796//
1797
1798static boolean crushchange, nofit;
1799
1800//
1801// PIT_ChangeSector
1802//
1803
1804boolean PIT_ChangeSector (mobj_t* thing)
1805{
1806 mobj_t* mo;
1807
1808 if (P_ThingHeightClip (thing))
1809 return true; // keep checking
1810
1811 // crunch bodies to giblets
1812
1813 if (thing->health <= 0)
1814 {
1815 P_SetMobjState (thing, S_GIBS);
1816
1817 thing->flags &= ~MF_SOLID;
1818 thing->height = 0;
1819 thing->radius = 0;
1820 return true; // keep checking
1821 }
1822
1823 // crunch dropped items
1824
1825 if (thing->flags & MF_DROPPED)
1826 {
1827 P_RemoveMobj (thing);
1828
1829 // keep checking
1830 return true;
1831 }
1832
1833 /* killough 11/98: kill touchy things immediately */
1834 if (thing->flags & MF_TOUCHY &&
1835 (thing->intflags & MIF_ARMED || sentient(thing)))
1836 {
1837 P_DamageMobj(thing, NULL, NULL, thing->health); // kill object
1838 return true; // keep checking
1839 }
1840
1841 if (! (thing->flags & MF_SHOOTABLE) )
1842 {
1843 // assume it is bloody gibs or something
1844 return true;
1845 }
1846
1847 nofit = true;
1848
1849 if (crushchange && !(leveltime&3)) {
1850 int t;
1851 P_DamageMobj(thing,NULL,NULL,10);
1852
1853 // spray blood in a random direction
1854 mo = P_SpawnMobj (thing->x,
1855 thing->y,
1856 thing->z + thing->height/2, MT_BLOOD);
1857
1858 /* killough 8/10/98: remove dependence on order of evaluation */
1859 t = P_Random(pr_crush);
1860 mo->momx = (t - P_Random (pr_crush))<<12;
1861 t = P_Random(pr_crush);
1862 mo->momy = (t - P_Random (pr_crush))<<12;
1863 }
1864
1865 // keep checking (crush other things)
1866 return true;
1867}
1868
1869
1870//
1871// P_ChangeSector
1872//
1873boolean P_ChangeSector(sector_t* sector,boolean crunch)
1874{
1875 int x;
1876 int y;
1877
1878 nofit = false;
1879 crushchange = crunch;
1880
1881 // ARRGGHHH!!!!
1882 // This is horrendously slow!!!
1883 // killough 3/14/98
1884
1885 // re-check heights for all things near the moving sector
1886
1887 for (x=sector->blockbox[BOXLEFT] ; x<= sector->blockbox[BOXRIGHT] ; x++)
1888 for (y=sector->blockbox[BOXBOTTOM];y<= sector->blockbox[BOXTOP] ; y++)
1889 P_BlockThingsIterator (x, y, PIT_ChangeSector);
1890
1891 return nofit;
1892}
1893
1894//
1895// P_CheckSector
1896// jff 3/19/98 added to just check monsters on the periphery
1897// of a moving sector instead of all in bounding box of the
1898// sector. Both more accurate and faster.
1899//
1900
1901boolean P_CheckSector(sector_t* sector,boolean crunch)
1902{
1903 msecnode_t *n;
1904
1905 if (comp[comp_floors]) /* use the old routine for old demos though */
1906 return P_ChangeSector(sector,crunch);
1907
1908 nofit = false;
1909 crushchange = crunch;
1910
1911 // killough 4/4/98: scan list front-to-back until empty or exhausted,
1912 // restarting from beginning after each thing is processed. Avoids
1913 // crashes, and is sure to examine all things in the sector, and only
1914 // the things which are in the sector, until a steady-state is reached.
1915 // Things can arbitrarily be inserted and removed and it won't mess up.
1916 //
1917 // killough 4/7/98: simplified to avoid using complicated counter
1918
1919 // Mark all things invalid
1920
1921 for (n=sector->touching_thinglist; n; n=n->m_snext)
1922 n->visited = false;
1923
1924 do
1925 for (n=sector->touching_thinglist; n; n=n->m_snext) // go through list
1926 if (!n->visited) // unprocessed thing found
1927 {
1928 n->visited = true; // mark thing as processed
1929 if (!(n->m_thing->flags & MF_NOBLOCKMAP)) //jff 4/7/98 don't do these
1930 PIT_ChangeSector(n->m_thing); // process it
1931 break; // exit and start over
1932 }
1933 while (n); // repeat from scratch until all things left are marked valid
1934
1935 return nofit;
1936}
1937
1938
1939// CPhipps -
1940// Use block memory allocator here
1941
1942#include "z_bmalloc.h"
1943
1944IMPLEMENT_BLOCK_MEMORY_ALLOC_ZONE(secnodezone, sizeof(msecnode_t), PU_LEVEL, 32, "SecNodes");
1945
1946inline static msecnode_t* P_GetSecnode(void)
1947{
1948 return (msecnode_t*)Z_BMalloc(&secnodezone);
1949}
1950
1951// P_PutSecnode() returns a node to the freelist.
1952
1953inline static void P_PutSecnode(msecnode_t* node)
1954{
1955 Z_BFree(&secnodezone, node);
1956}
1957
1958// phares 3/16/98
1959//
1960// P_AddSecnode() searches the current list to see if this sector is
1961// already there. If not, it adds a sector node at the head of the list of
1962// sectors this object appears in. This is called when creating a list of
1963// nodes that will get linked in later. Returns a pointer to the new node.
1964
1965msecnode_t* P_AddSecnode(sector_t* s, mobj_t* thing, msecnode_t* nextnode)
1966{
1967 msecnode_t* node;
1968
1969 node = nextnode;
1970 while (node)
1971 {
1972 if (node->m_sector == s) // Already have a node for this sector?
1973 {
1974 node->m_thing = thing; // Yes. Setting m_thing says 'keep it'.
1975 return(nextnode);
1976 }
1977 node = node->m_tnext;
1978 }
1979
1980 // Couldn't find an existing node for this sector. Add one at the head
1981 // of the list.
1982
1983 node = P_GetSecnode();
1984
1985 // killough 4/4/98, 4/7/98: mark new nodes unvisited.
1986 node->visited = 0;
1987
1988 node->m_sector = s; // sector
1989 node->m_thing = thing; // mobj
1990 node->m_tprev = NULL; // prev node on Thing thread
1991 node->m_tnext = nextnode; // next node on Thing thread
1992 if (nextnode)
1993 nextnode->m_tprev = node; // set back link on Thing
1994
1995 // Add new node at head of sector thread starting at s->touching_thinglist
1996
1997 node->m_sprev = NULL; // prev node on sector thread
1998 node->m_snext = s->touching_thinglist; // next node on sector thread
1999 if (s->touching_thinglist)
2000 node->m_snext->m_sprev = node;
2001 s->touching_thinglist = node;
2002 return(node);
2003}
2004
2005
2006// P_DelSecnode() deletes a sector node from the list of
2007// sectors this object appears in. Returns a pointer to the next node
2008// on the linked list, or NULL.
2009
2010msecnode_t* P_DelSecnode(msecnode_t* node)
2011{
2012 msecnode_t* tp; // prev node on thing thread
2013 msecnode_t* tn; // next node on thing thread
2014 msecnode_t* sp; // prev node on sector thread
2015 msecnode_t* sn; // next node on sector thread
2016
2017 if (node)
2018 {
2019
2020 // Unlink from the Thing thread. The Thing thread begins at
2021 // sector_list and not from mobj_t->touching_sectorlist.
2022
2023 tp = node->m_tprev;
2024 tn = node->m_tnext;
2025 if (tp)
2026 tp->m_tnext = tn;
2027 if (tn)
2028 tn->m_tprev = tp;
2029
2030 // Unlink from the sector thread. This thread begins at
2031 // sector_t->touching_thinglist.
2032
2033 sp = node->m_sprev;
2034 sn = node->m_snext;
2035 if (sp)
2036 sp->m_snext = sn;
2037 else
2038 node->m_sector->touching_thinglist = sn;
2039 if (sn)
2040 sn->m_sprev = sp;
2041
2042 // Return this node to the freelist
2043
2044 P_PutSecnode(node);
2045 return(tn);
2046 }
2047 return(NULL);
2048} // phares 3/13/98
2049
2050// Delete an entire sector list
2051
2052void P_DelSeclist(msecnode_t* node)
2053
2054{
2055 while (node)
2056 node = P_DelSecnode(node);
2057}
2058
2059
2060// phares 3/14/98
2061//
2062// PIT_GetSectors
2063// Locates all the sectors the object is in by looking at the lines that
2064// cross through it. You have already decided that the object is allowed
2065// at this location, so don't bother with checking impassable or
2066// blocking lines.
2067
2068boolean PIT_GetSectors(line_t* ld)
2069{
2070 if (tmbbox[BOXRIGHT] <= ld->bbox[BOXLEFT] ||
2071 tmbbox[BOXLEFT] >= ld->bbox[BOXRIGHT] ||
2072 tmbbox[BOXTOP] <= ld->bbox[BOXBOTTOM] ||
2073 tmbbox[BOXBOTTOM] >= ld->bbox[BOXTOP])
2074 return true;
2075
2076 if (P_BoxOnLineSide(tmbbox, ld) != -1)
2077 return true;
2078
2079 // This line crosses through the object.
2080
2081 // Collect the sector(s) from the line and add to the
2082 // sector_list you're examining. If the Thing ends up being
2083 // allowed to move to this position, then the sector_list
2084 // will be attached to the Thing's mobj_t at touching_sectorlist.
2085
2086 sector_list = P_AddSecnode(ld->frontsector,tmthing,sector_list);
2087
2088 /* Don't assume all lines are 2-sided, since some Things
2089 * like MT_TFOG are allowed regardless of whether their radius takes
2090 * them beyond an impassable linedef.
2091 *
2092 * killough 3/27/98, 4/4/98:
2093 * Use sidedefs instead of 2s flag to determine two-sidedness.
2094 * killough 8/1/98: avoid duplicate if same sector on both sides
2095 * cph - DEMOSYNC? */
2096
2097 if (ld->backsector && ld->backsector != ld->frontsector)
2098 sector_list = P_AddSecnode(ld->backsector, tmthing, sector_list);
2099
2100 return true;
2101}
2102
2103
2104// phares 3/14/98
2105//
2106// P_CreateSecNodeList alters/creates the sector_list that shows what sectors
2107// the object resides in.
2108
2109void P_CreateSecNodeList(mobj_t* thing,fixed_t x,fixed_t y)
2110{
2111 int xl;
2112 int xh;
2113 int yl;
2114 int yh;
2115 int bx;
2116 int by;
2117 msecnode_t* node;
2118 mobj_t* saved_tmthing = tmthing; /* cph - see comment at func end */
2119 fixed_t saved_tmx = tmx, saved_tmy = tmy; /* ditto */
2120
2121 // First, clear out the existing m_thing fields. As each node is
2122 // added or verified as needed, m_thing will be set properly. When
2123 // finished, delete all nodes where m_thing is still NULL. These
2124 // represent the sectors the Thing has vacated.
2125
2126 node = sector_list;
2127 while (node)
2128 {
2129 node->m_thing = NULL;
2130 node = node->m_tnext;
2131 }
2132
2133 tmthing = thing;
2134
2135 tmx = x;
2136 tmy = y;
2137
2138 tmbbox[BOXTOP] = y + tmthing->radius;
2139 tmbbox[BOXBOTTOM] = y - tmthing->radius;
2140 tmbbox[BOXRIGHT] = x + tmthing->radius;
2141 tmbbox[BOXLEFT] = x - tmthing->radius;
2142
2143 validcount++; // used to make sure we only process a line once
2144
2145 xl = (tmbbox[BOXLEFT] - bmaporgx)>>MAPBLOCKSHIFT;
2146 xh = (tmbbox[BOXRIGHT] - bmaporgx)>>MAPBLOCKSHIFT;
2147 yl = (tmbbox[BOXBOTTOM] - bmaporgy)>>MAPBLOCKSHIFT;
2148 yh = (tmbbox[BOXTOP] - bmaporgy)>>MAPBLOCKSHIFT;
2149
2150 for (bx=xl ; bx<=xh ; bx++)
2151 for (by=yl ; by<=yh ; by++)
2152 P_BlockLinesIterator(bx,by,PIT_GetSectors);
2153
2154 // Add the sector of the (x,y) point to sector_list.
2155
2156 sector_list = P_AddSecnode(thing->subsector->sector,thing,sector_list);
2157
2158 // Now delete any nodes that won't be used. These are the ones where
2159 // m_thing is still NULL.
2160
2161 node = sector_list;
2162 while (node)
2163 {
2164 if (node->m_thing == NULL)
2165 {
2166 if (node == sector_list)
2167 sector_list = node->m_tnext;
2168 node = P_DelSecnode(node);
2169 }
2170 else
2171 node = node->m_tnext;
2172 }
2173
2174 /* cph -
2175 * This is the strife we get into for using global variables. tmthing
2176 * is being used by several different functions calling
2177 * P_BlockThingIterator, including functions that can be called *from*
2178 * P_BlockThingIterator. Using a global tmthing is not reentrant.
2179 * OTOH for Boom/MBF demos we have to preserve the buggy behavior.
2180 * Fun. We restore its previous value unless we're in a Boom/MBF demo.
2181 */
2182 if ((compatibility_level < boom_compatibility_compatibility) ||
2183 (compatibility_level >= prboom_3_compatibility))
2184 tmthing = saved_tmthing;
2185 /* And, duh, the same for tmx/y - cph 2002/09/22
2186 * And for tmbbox - cph 2003/08/10 */
2187 if ((compatibility_level < boom_compatibility_compatibility) /* ||
2188 (compatibility_level >= prboom_4_compatibility) */) {
2189 tmx = saved_tmx, tmy = saved_tmy;
2190 if (tmthing) {
2191 tmbbox[BOXTOP] = tmy + tmthing->radius;
2192 tmbbox[BOXBOTTOM] = tmy - tmthing->radius;
2193 tmbbox[BOXRIGHT] = tmx + tmthing->radius;
2194 tmbbox[BOXLEFT] = tmx - tmthing->radius;
2195 }
2196 }
2197}
2198
2199/* cphipps 2004/08/30 -
2200 * Must clear tmthing at tic end, as it might contain a pointer to a removed thinker, or the level might have ended/been ended and we clear the objects it was pointing too. Hopefully we don't need to carry this between tics for sync. */
2201void P_MapStart(void) {
2202 if (tmthing) I_Error("P_MapStart: tmthing set!");
2203}
2204void P_MapEnd(void) {
2205 tmthing = NULL;
2206}
2207
diff --git a/apps/plugins/doom/p_map.h b/apps/plugins/doom/p_map.h
new file mode 100644
index 0000000000..6985cc15c1
--- /dev/null
+++ b/apps/plugins/doom/p_map.h
@@ -0,0 +1,90 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION:
28 * Map functions
29 *
30 *-----------------------------------------------------------------------------*/
31
32#ifndef __P_MAP__
33#define __P_MAP__
34
35#include "r_defs.h"
36#include "d_player.h"
37
38#define USERANGE (64*FRACUNIT)
39#define MELEERANGE (64*FRACUNIT)
40#define MISSILERANGE (32*64*FRACUNIT)
41
42// MAXRADIUS is for precalculated sector block boxes the spider demon
43// is larger, but we do not have any moving sectors nearby
44#define MAXRADIUS (32*FRACUNIT)
45
46// killough 3/15/98: add fourth argument to P_TryMove
47boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean dropoff);
48
49// killough 8/9/98: extra argument for telefragging
50boolean P_TeleportMove(mobj_t *thing, fixed_t x, fixed_t y,boolean boss);
51void P_SlideMove(mobj_t *mo);
52boolean P_CheckSight(mobj_t *t1, mobj_t *t2);
53void P_UseLines(player_t *player);
54
55// killough 8/2/98: add 'mask' argument to prevent friends autoaiming at others
56fixed_t P_AimLineAttack(mobj_t *t1,angle_t angle,fixed_t distance, uint_64_t mask);
57
58void P_LineAttack(mobj_t *t1, angle_t angle, fixed_t distance,
59 fixed_t slope, int damage );
60void P_RadiusAttack(mobj_t *spot, mobj_t *source, int damage);
61boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y);
62
63//jff 3/19/98 P_CheckSector(): new routine to replace P_ChangeSector()
64boolean P_ChangeSector(sector_t* sector,boolean crunch);
65boolean P_CheckSector(sector_t *sector, boolean crunch);
66void P_DelSeclist(msecnode_t*); // phares 3/16/98
67void P_CreateSecNodeList(mobj_t*,fixed_t,fixed_t); // phares 3/14/98
68boolean Check_Sides(mobj_t *, int, int); // phares
69
70int P_GetMoveFactor(const mobj_t *mo, int *friction); // killough 8/28/98
71int P_GetFriction(const mobj_t *mo, int *factor); // killough 8/28/98
72void P_ApplyTorque(mobj_t *mo); // killough 9/12/98
73
74/* cphipps 2004/08/30 */
75void P_MapStart(void);
76void P_MapEnd(void);
77
78// If "floatok" true, move would be ok if within "tmfloorz - tmceilingz".
79extern boolean floatok;
80extern boolean felldown; // killough 11/98: indicates object pushed off ledge
81extern fixed_t tmfloorz;
82extern fixed_t tmceilingz;
83extern line_t *ceilingline;
84extern line_t *floorline; // killough 8/23/98
85extern mobj_t *linetarget; // who got hit (or NULL)
86extern msecnode_t *sector_list; // phares 3/16/98
87extern fixed_t tmbbox[4]; // phares 3/20/98
88extern line_t *blockline; // killough 8/11/98
89
90#endif // __P_MAP__
diff --git a/apps/plugins/doom/p_maputl.c b/apps/plugins/doom/p_maputl.c
new file mode 100644
index 0000000000..a2ef132d11
--- /dev/null
+++ b/apps/plugins/doom/p_maputl.c
@@ -0,0 +1,700 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION:
28 * Movement/collision utility functions,
29 * as used by function in p_map.c.
30 * BLOCKMAP Iterator functions,
31 * and some PIT_* functions to use for iteration.
32 *
33 *-----------------------------------------------------------------------------*/
34
35#include "doomstat.h"
36#include "m_bbox.h"
37#include "r_main.h"
38#include "p_maputl.h"
39#include "p_map.h"
40#include "p_setup.h"
41#include "rockmacros.h"
42//
43// P_AproxDistance
44// Gives an estimation of distance (not exact)
45//
46
47fixed_t CONSTFUNC P_AproxDistance(fixed_t dx, fixed_t dy)
48{
49 dx = D_abs(dx);
50 dy = D_abs(dy);
51 if (dx < dy)
52 return dx+dy-(dx>>1);
53 return dx+dy-(dy>>1);
54}
55
56//
57// P_PointOnLineSide
58// Returns 0 or 1
59//
60// killough 5/3/98: reformatted, cleaned up
61
62int CONSTFUNC P_PointOnLineSide(fixed_t x, fixed_t y, const line_t *line)
63{
64 return
65 !line->dx ? x <= line->v1->x ? line->dy > 0 : line->dy < 0 :
66 !line->dy ? y <= line->v1->y ? line->dx < 0 : line->dx > 0 :
67 FixedMul(y-line->v1->y, line->dx>>FRACBITS) >=
68 FixedMul(line->dy>>FRACBITS, x-line->v1->x);
69}
70
71//
72// P_BoxOnLineSide
73// Considers the line to be infinite
74// Returns side 0 or 1, -1 if box crosses the line.
75//
76// killough 5/3/98: reformatted, cleaned up
77
78int CONSTFUNC P_BoxOnLineSide(const fixed_t *tmbox, const line_t *ld)
79{
80 switch (ld->slopetype)
81 {
82 int p;
83 default: // shut up compiler warnings -- killough
84 case ST_HORIZONTAL:
85 return
86 (tmbox[BOXBOTTOM] > ld->v1->y) == (p = tmbox[BOXTOP] > ld->v1->y) ?
87 p ^ (ld->dx < 0) : -1;
88 case ST_VERTICAL:
89 return
90 (tmbox[BOXLEFT] < ld->v1->x) == (p = tmbox[BOXRIGHT] < ld->v1->x) ?
91 p ^ (ld->dy < 0) : -1;
92 case ST_POSITIVE:
93 return
94 P_PointOnLineSide(tmbox[BOXRIGHT], tmbox[BOXBOTTOM], ld) ==
95 (p = P_PointOnLineSide(tmbox[BOXLEFT], tmbox[BOXTOP], ld)) ? p : -1;
96 case ST_NEGATIVE:
97 return
98 (P_PointOnLineSide(tmbox[BOXLEFT], tmbox[BOXBOTTOM], ld)) ==
99 (p = P_PointOnLineSide(tmbox[BOXRIGHT], tmbox[BOXTOP], ld)) ? p : -1;
100 }
101}
102
103//
104// P_PointOnDivlineSide
105// Returns 0 or 1.
106//
107// killough 5/3/98: reformatted, cleaned up
108
109int CONSTFUNC P_PointOnDivlineSide(fixed_t x, fixed_t y, const divline_t *line)
110{
111 return
112 !line->dx ? x <= line->x ? line->dy > 0 : line->dy < 0 :
113 !line->dy ? y <= line->y ? line->dx < 0 : line->dx > 0 :
114 (line->dy^line->dx^(x -= line->x)^(y -= line->y)) < 0 ? (line->dy^x) < 0 :
115 FixedMul(y>>8, line->dx>>8) >= FixedMul(line->dy>>8, x>>8);
116}
117
118//
119// P_MakeDivline
120//
121
122void P_MakeDivline(const line_t *li, divline_t *dl)
123{
124 dl->x = li->v1->x;
125 dl->y = li->v1->y;
126 dl->dx = li->dx;
127 dl->dy = li->dy;
128}
129
130//
131// P_InterceptVector
132// Returns the fractional intercept point
133// along the first divline.
134// This is only called by the addthings
135// and addlines traversers.
136//
137// killough 5/3/98: reformatted, cleaned up
138
139fixed_t CONSTFUNC P_InterceptVector(const divline_t *v2, const divline_t *v1)
140{
141 fixed_t den = FixedMul(v1->dy>>8, v2->dx) - FixedMul(v1->dx>>8, v2->dy);
142 return den ? FixedDiv((FixedMul((v1->x-v2->x)>>8, v1->dy) +
143 FixedMul((v2->y-v1->y)>>8, v1->dx)), den) : 0;
144}
145
146//
147// P_LineOpening
148// Sets opentop and openbottom to the window
149// through a two sided line.
150// OPTIMIZE: keep this precalculated
151//
152
153fixed_t opentop;
154fixed_t openbottom;
155fixed_t openrange;
156fixed_t lowfloor;
157
158// moved front and back outside P-LineOpening and changed // phares 3/7/98
159// them to these so we can pick up the new friction value
160// in PIT_CheckLine()
161sector_t *openfrontsector; // made global // phares
162sector_t *openbacksector; // made global
163
164void P_LineOpening(const line_t *linedef)
165{
166 if (linedef->sidenum[1] == -1) // single sided line
167 {
168 openrange = 0;
169 return;
170 }
171
172 openfrontsector = linedef->frontsector;
173 openbacksector = linedef->backsector;
174
175 if (openfrontsector->ceilingheight < openbacksector->ceilingheight)
176 opentop = openfrontsector->ceilingheight;
177 else
178 opentop = openbacksector->ceilingheight;
179
180 if (openfrontsector->floorheight > openbacksector->floorheight)
181 {
182 openbottom = openfrontsector->floorheight;
183 lowfloor = openbacksector->floorheight;
184 }
185 else
186 {
187 openbottom = openbacksector->floorheight;
188 lowfloor = openfrontsector->floorheight;
189 }
190 openrange = opentop - openbottom;
191}
192
193//
194// THING POSITION SETTING
195//
196
197//
198// P_UnsetThingPosition
199// Unlinks a thing from block map and sectors.
200// On each position change, BLOCKMAP and other
201// lookups maintaining lists ot things inside
202// these structures need to be updated.
203//
204
205void P_UnsetThingPosition (mobj_t *thing)
206{
207 if (!(thing->flags & MF_NOSECTOR))
208 {
209 /* invisible things don't need to be in sector list
210 * unlink from subsector
211 *
212 * killough 8/11/98: simpler scheme using pointers-to-pointers for prev
213 * pointers, allows head node pointers to be treated like everything else
214 */
215
216 mobj_t **sprev = thing->sprev;
217 mobj_t *snext = thing->snext;
218 if ((*sprev = snext)) // unlink from sector list
219 snext->sprev = sprev;
220
221 // phares 3/14/98
222 //
223 // Save the sector list pointed to by touching_sectorlist.
224 // In P_SetThingPosition, we'll keep any nodes that represent
225 // sectors the Thing still touches. We'll add new ones then, and
226 // delete any nodes for sectors the Thing has vacated. Then we'll
227 // put it back into touching_sectorlist. It's done this way to
228 // avoid a lot of deleting/creating for nodes, when most of the
229 // time you just get back what you deleted anyway.
230 //
231 // If this Thing is being removed entirely, then the calling
232 // routine will clear out the nodes in sector_list.
233
234 sector_list = thing->touching_sectorlist;
235 thing->touching_sectorlist = NULL; //to be restored by P_SetThingPosition
236 }
237
238 if (!(thing->flags & MF_NOBLOCKMAP))
239 {
240 /* inert things don't need to be in blockmap
241 *
242 * killough 8/11/98: simpler scheme using pointers-to-pointers for prev
243 * pointers, allows head node pointers to be treated like everything else
244 *
245 * Also more robust, since it doesn't depend on current position for
246 * unlinking. Old method required computing head node based on position
247 * at time of unlinking, assuming it was the same position as during
248 * linking.
249 */
250
251 mobj_t *bnext, **bprev = thing->bprev;
252 if (bprev && (*bprev = bnext = thing->bnext)) // unlink from block map
253 bnext->bprev = bprev;
254 }
255}
256
257//
258// P_SetThingPosition
259// Links a thing into both a block and a subsector
260// based on it's x y.
261// Sets thing->subsector properly
262//
263// killough 5/3/98: reformatted, cleaned up
264
265void P_SetThingPosition(mobj_t *thing)
266{ // link into subsector
267 subsector_t *ss = thing->subsector = R_PointInSubsector(thing->x, thing->y);
268 if (!(thing->flags & MF_NOSECTOR))
269 {
270 // invisible things don't go into the sector links
271
272 // killough 8/11/98: simpler scheme using pointer-to-pointer prev
273 // pointers, allows head nodes to be treated like everything else
274
275 mobj_t **link = &ss->sector->thinglist;
276 mobj_t *snext = *link;
277 if ((thing->snext = snext))
278 snext->sprev = &thing->snext;
279 thing->sprev = link;
280 *link = thing;
281
282 // phares 3/16/98
283 //
284 // If sector_list isn't NULL, it has a collection of sector
285 // nodes that were just removed from this Thing.
286
287 // Collect the sectors the object will live in by looking at
288 // the existing sector_list and adding new nodes and deleting
289 // obsolete ones.
290
291 // When a node is deleted, its sector links (the links starting
292 // at sector_t->touching_thinglist) are broken. When a node is
293 // added, new sector links are created.
294
295 P_CreateSecNodeList(thing,thing->x,thing->y);
296 thing->touching_sectorlist = sector_list; // Attach to Thing's mobj_t
297 sector_list = NULL; // clear for next time
298 }
299
300 // link into blockmap
301 if (!(thing->flags & MF_NOBLOCKMAP))
302 {
303 // inert things don't need to be in blockmap
304 int blockx = (thing->x - bmaporgx)>>MAPBLOCKSHIFT;
305 int blocky = (thing->y - bmaporgy)>>MAPBLOCKSHIFT;
306 if (blockx>=0 && blockx < bmapwidth && blocky>=0 && blocky < bmapheight)
307 {
308 // killough 8/11/98: simpler scheme using pointer-to-pointer prev
309 // pointers, allows head nodes to be treated like everything else
310
311 mobj_t **link = &blocklinks[blocky*bmapwidth+blockx];
312 mobj_t *bnext = *link;
313 if ((thing->bnext = bnext))
314 bnext->bprev = &thing->bnext;
315 thing->bprev = link;
316 *link = thing;
317 }
318 else // thing is off the map
319 thing->bnext = NULL, thing->bprev = NULL;
320 }
321}
322
323// killough 3/15/98:
324//
325// A fast function for testing intersections between things and linedefs.
326
327boolean CONSTFUNC ThingIsOnLine(const mobj_t *t, const line_t *l)
328{
329 int dx = l->dx >> FRACBITS; // Linedef vector
330 int dy = l->dy >> FRACBITS;
331 int a = (l->v1->x >> FRACBITS) - (t->x >> FRACBITS); // Thing-->v1 vector
332 int b = (l->v1->y >> FRACBITS) - (t->y >> FRACBITS);
333 int r = t->radius >> FRACBITS; // Thing radius
334
335 // First make sure bounding boxes of linedef and thing intersect.
336 // Leads to quick rejection using only shifts and adds/subs/compares.
337
338 if (D_abs(a*2+dx)-D_abs(dx) > r*2 || D_abs(b*2+dy)-D_abs(dy) > r*2)
339 return 0;
340
341 // Next, make sure that at least one thing crosshair intersects linedef's
342 // extension. Requires only 3-4 multiplications, the rest adds/subs/
343 // shifts/xors (writing the steps out this way leads to better codegen).
344
345 a *= dy;
346 b *= dx;
347 a -= b;
348 b = dx + dy;
349 b *= r;
350 if (((a-b)^(a+b)) < 0)
351 return 1;
352 dy -= dx;
353 dy *= r;
354 b = a+dy;
355 a -= dy;
356 return (a^b) < 0;
357}
358
359//
360// BLOCK MAP ITERATORS
361// For each line/thing in the given mapblock,
362// call the passed PIT_* function.
363// If the function returns false,
364// exit with false without checking anything else.
365//
366
367//
368// P_BlockLinesIterator
369// The validcount flags are used to avoid checking lines
370// that are marked in multiple mapblocks,
371// so increment validcount before the first call
372// to P_BlockLinesIterator, then make one or more calls
373// to it.
374//
375// killough 5/3/98: reformatted, cleaned up
376
377boolean P_BlockLinesIterator(int x, int y, boolean func(line_t*))
378{
379 int offset;
380 const long *list; // killough 3/1/98: for removal of blockmap limit
381
382 if (x<0 || y<0 || x>=bmapwidth || y>=bmapheight)
383 return true;
384 offset = y*bmapwidth+x;
385 offset = *(blockmap+offset);
386 list = blockmaplump+offset; // original was reading // phares
387 // delmiting 0 as linedef 0 // phares
388
389 // killough 1/31/98: for compatibility we need to use the old method.
390 // Most demos go out of sync, and maybe other problems happen, if we
391 // don't consider linedef 0. For safety this should be qualified.
392
393 if (!demo_compatibility) // killough 2/22/98: demo_compatibility check
394 list++; // skip 0 starting delimiter // phares
395 for ( ; *list != -1 ; list++) // phares
396 {
397 line_t *ld = &lines[*list];
398 if (ld->validcount == validcount)
399 continue; // line has already been checked
400 ld->validcount = validcount;
401 if (!func(ld))
402 return false;
403 }
404 return true; // everything was checked
405}
406
407//
408// P_BlockThingsIterator
409//
410// killough 5/3/98: reformatted, cleaned up
411
412boolean P_BlockThingsIterator(int x, int y, boolean func(mobj_t*))
413{
414 mobj_t *mobj;
415 if (!(x<0 || y<0 || x>=bmapwidth || y>=bmapheight))
416 for (mobj = blocklinks[y*bmapwidth+x]; mobj; mobj = mobj->bnext)
417 if (!func(mobj))
418 return false;
419 return true;
420}
421
422//
423// INTERCEPT ROUTINES
424//
425
426// 1/11/98 killough: Intercept limit removed
427static intercept_t *intercepts, *intercept_p;
428
429// Check for limit and double size if necessary -- killough
430static void check_intercept(void)
431{
432 static size_t num_intercepts;
433 size_t offset = intercept_p - intercepts;
434 if (offset >= num_intercepts)
435 {
436 num_intercepts = num_intercepts ? num_intercepts*2 : 128;
437 intercepts = realloc(intercepts, sizeof(*intercepts)*num_intercepts);
438 intercept_p = intercepts + offset;
439 }
440}
441
442divline_t trace;
443
444// PIT_AddLineIntercepts.
445// Looks for lines in the given block
446// that intercept the given trace
447// to add to the intercepts list.
448//
449// A line is crossed if its endpoints
450// are on opposite sides of the trace.
451//
452// killough 5/3/98: reformatted, cleaned up
453
454boolean PIT_AddLineIntercepts(line_t *ld)
455{
456 int s1;
457 int s2;
458 fixed_t frac;
459 divline_t dl;
460
461 // avoid precision problems with two routines
462 if (trace.dx > FRACUNIT*16 || trace.dy > FRACUNIT*16 ||
463 trace.dx < -FRACUNIT*16 || trace.dy < -FRACUNIT*16)
464 {
465 s1 = P_PointOnDivlineSide (ld->v1->x, ld->v1->y, &trace);
466 s2 = P_PointOnDivlineSide (ld->v2->x, ld->v2->y, &trace);
467 }
468 else
469 {
470 s1 = P_PointOnLineSide (trace.x, trace.y, ld);
471 s2 = P_PointOnLineSide (trace.x+trace.dx, trace.y+trace.dy, ld);
472 }
473
474 if (s1 == s2)
475 return true; // line isn't crossed
476
477 // hit the line
478 P_MakeDivline(ld, &dl);
479 frac = P_InterceptVector(&trace, &dl);
480
481 if (frac < 0)
482 return true; // behind source
483
484 check_intercept(); // killough
485
486 intercept_p->frac = frac;
487 intercept_p->isaline = true;
488 intercept_p->d.line = ld;
489 intercept_p++;
490
491 return true; // continue
492}
493
494//
495// PIT_AddThingIntercepts
496//
497// killough 5/3/98: reformatted, cleaned up
498
499boolean PIT_AddThingIntercepts(mobj_t *thing)
500{
501 fixed_t x1, y1;
502 fixed_t x2, y2;
503 int s1, s2;
504 divline_t dl;
505 fixed_t frac;
506
507 // check a corner to corner crossection for hit
508 if ((trace.dx ^ trace.dy) > 0)
509 {
510 x1 = thing->x - thing->radius;
511 y1 = thing->y + thing->radius;
512 x2 = thing->x + thing->radius;
513 y2 = thing->y - thing->radius;
514 }
515 else
516 {
517 x1 = thing->x - thing->radius;
518 y1 = thing->y - thing->radius;
519 x2 = thing->x + thing->radius;
520 y2 = thing->y + thing->radius;
521 }
522
523 s1 = P_PointOnDivlineSide (x1, y1, &trace);
524 s2 = P_PointOnDivlineSide (x2, y2, &trace);
525
526 if (s1 == s2)
527 return true; // line isn't crossed
528
529 dl.x = x1;
530 dl.y = y1;
531 dl.dx = x2-x1;
532 dl.dy = y2-y1;
533
534 frac = P_InterceptVector (&trace, &dl);
535
536 if (frac < 0)
537 return true; // behind source
538
539 check_intercept(); // killough
540
541 intercept_p->frac = frac;
542 intercept_p->isaline = false;
543 intercept_p->d.thing = thing;
544 intercept_p++;
545
546 return true; // keep going
547}
548
549//
550// P_TraverseIntercepts
551// Returns true if the traverser function returns true
552// for all lines.
553//
554// killough 5/3/98: reformatted, cleaned up
555
556boolean P_TraverseIntercepts(traverser_t func, fixed_t maxfrac)
557{
558 intercept_t *in = NULL;
559 int count = intercept_p - intercepts;
560 while (count--)
561 {
562 fixed_t dist = INT_MAX;
563 intercept_t *scan;
564 for (scan = intercepts; scan < intercept_p; scan++)
565 if (scan->frac < dist)
566 dist = (in=scan)->frac;
567 if (dist > maxfrac)
568 return true; // checked everything in range
569 if (!func(in))
570 return false; // don't bother going farther
571 in->frac = INT_MAX;
572 }
573 return true; // everything was traversed
574}
575
576//
577// P_PathTraverse
578// Traces a line from x1,y1 to x2,y2,
579// calling the traverser function for each.
580// Returns true if the traverser function returns true
581// for all lines.
582//
583// killough 5/3/98: reformatted, cleaned up
584
585boolean P_PathTraverse(fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2,
586 int flags, boolean trav(intercept_t *))
587{
588 fixed_t xt1, yt1;
589 fixed_t xt2, yt2;
590 fixed_t xstep, ystep;
591 fixed_t partial;
592 fixed_t xintercept, yintercept;
593 int mapx, mapy;
594 int mapxstep, mapystep;
595 int count;
596
597 validcount++;
598 intercept_p = intercepts;
599
600 if (!((x1-bmaporgx)&(MAPBLOCKSIZE-1)))
601 x1 += FRACUNIT; // don't side exactly on a line
602
603 if (!((y1-bmaporgy)&(MAPBLOCKSIZE-1)))
604 y1 += FRACUNIT; // don't side exactly on a line
605
606 trace.x = x1;
607 trace.y = y1;
608 trace.dx = x2 - x1;
609 trace.dy = y2 - y1;
610
611 x1 -= bmaporgx;
612 y1 -= bmaporgy;
613 xt1 = x1>>MAPBLOCKSHIFT;
614 yt1 = y1>>MAPBLOCKSHIFT;
615
616 x2 -= bmaporgx;
617 y2 -= bmaporgy;
618 xt2 = x2>>MAPBLOCKSHIFT;
619 yt2 = y2>>MAPBLOCKSHIFT;
620
621 if (xt2 > xt1)
622 {
623 mapxstep = 1;
624 partial = FRACUNIT - ((x1>>MAPBTOFRAC)&(FRACUNIT-1));
625 ystep = FixedDiv (y2-y1,D_abs(x2-x1));
626 }
627 else
628 if (xt2 < xt1)
629 {
630 mapxstep = -1;
631 partial = (x1>>MAPBTOFRAC)&(FRACUNIT-1);
632 ystep = FixedDiv (y2-y1,D_abs(x2-x1));
633 }
634 else
635 {
636 mapxstep = 0;
637 partial = FRACUNIT;
638 ystep = 256*FRACUNIT;
639 }
640
641 yintercept = (y1>>MAPBTOFRAC) + FixedMul(partial, ystep);
642
643 if (yt2 > yt1)
644 {
645 mapystep = 1;
646 partial = FRACUNIT - ((y1>>MAPBTOFRAC)&(FRACUNIT-1));
647 xstep = FixedDiv (x2-x1,D_abs(y2-y1));
648 }
649 else
650 if (yt2 < yt1)
651 {
652 mapystep = -1;
653 partial = (y1>>MAPBTOFRAC)&(FRACUNIT-1);
654 xstep = FixedDiv (x2-x1,D_abs(y2-y1));
655 }
656 else
657 {
658 mapystep = 0;
659 partial = FRACUNIT;
660 xstep = 256*FRACUNIT;
661 }
662
663 xintercept = (x1>>MAPBTOFRAC) + FixedMul (partial, xstep);
664
665 // Step through map blocks.
666 // Count is present to prevent a round off error
667 // from skipping the break.
668
669 mapx = xt1;
670 mapy = yt1;
671
672 for (count = 0; count < 64; count++)
673 {
674 if (flags & PT_ADDLINES)
675 if (!P_BlockLinesIterator(mapx, mapy,PIT_AddLineIntercepts))
676 return false; // early out
677
678 if (flags & PT_ADDTHINGS)
679 if (!P_BlockThingsIterator(mapx, mapy,PIT_AddThingIntercepts))
680 return false; // early out
681
682 if (mapx == xt2 && mapy == yt2)
683 break;
684
685 if ((yintercept >> FRACBITS) == mapy)
686 {
687 yintercept += ystep;
688 mapx += mapxstep;
689 }
690 else
691 if ((xintercept >> FRACBITS) == mapx)
692 {
693 xintercept += xstep;
694 mapy += mapystep;
695 }
696 }
697
698 // go through the sorted list
699 return P_TraverseIntercepts(trav, FRACUNIT);
700}
diff --git a/apps/plugins/doom/p_maputl.h b/apps/plugins/doom/p_maputl.h
new file mode 100644
index 0000000000..a000bf0edb
--- /dev/null
+++ b/apps/plugins/doom/p_maputl.h
@@ -0,0 +1,91 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION:
28 * Map utility functions
29 *
30 *-----------------------------------------------------------------------------*/
31
32#ifndef __P_MAPUTL__
33#define __P_MAPUTL__
34
35#include "r_defs.h"
36
37/* mapblocks are used to check movement against lines and things */
38#define MAPBLOCKUNITS 128
39#define MAPBLOCKSIZE (MAPBLOCKUNITS*FRACUNIT)
40#define MAPBLOCKSHIFT (FRACBITS+7)
41#define MAPBMASK (MAPBLOCKSIZE-1)
42#define MAPBTOFRAC (MAPBLOCKSHIFT-FRACBITS)
43
44#define PT_ADDLINES 1
45#define PT_ADDTHINGS 2
46#define PT_EARLYOUT 4
47
48typedef struct {
49 fixed_t x;
50 fixed_t y;
51 fixed_t dx;
52 fixed_t dy;
53} divline_t;
54
55typedef struct {
56 fixed_t frac; /* along trace line */
57 boolean isaline;
58 union {
59 mobj_t* thing;
60 line_t* line;
61 } d;
62} intercept_t;
63
64typedef boolean (*traverser_t)(intercept_t *in);
65
66#define CONSTFUNC
67
68fixed_t CONSTFUNC P_AproxDistance (fixed_t dx, fixed_t dy);
69int CONSTFUNC P_PointOnLineSide (fixed_t x, fixed_t y, const line_t *line);
70int CONSTFUNC P_PointOnDivlineSide (fixed_t x, fixed_t y,
71 const divline_t *line);
72int CONSTFUNC P_BoxOnLineSide (const fixed_t *tmbox, const line_t *ld);
73fixed_t CONSTFUNC P_InterceptVector (const divline_t *v2, const divline_t *v1);
74
75void P_MakeDivline (const line_t *li, divline_t *dl);
76void P_LineOpening (const line_t *linedef);
77void P_UnsetThingPosition(mobj_t *thing);
78void P_SetThingPosition(mobj_t *thing);
79boolean P_BlockLinesIterator (int x, int y, boolean func(line_t *));
80boolean P_BlockThingsIterator(int x, int y, boolean func(mobj_t *));
81boolean CONSTFUNC ThingIsOnLine(const mobj_t *t, const line_t *l); /* killough 3/15/98 */
82boolean P_PathTraverse(fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2,
83 int flags, boolean trav(intercept_t *));
84
85extern fixed_t opentop;
86extern fixed_t openbottom;
87extern fixed_t openrange;
88extern fixed_t lowfloor;
89extern divline_t trace;
90
91#endif /* __P_MAPUTL__ */
diff --git a/apps/plugins/doom/p_mobj.c b/apps/plugins/doom/p_mobj.c
new file mode 100644
index 0000000000..3aaaf4510a
--- /dev/null
+++ b/apps/plugins/doom/p_mobj.c
@@ -0,0 +1,1394 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION:
28 * Moving object handling. Spawn functions.
29 *
30 *-----------------------------------------------------------------------------*/
31
32#include "doomdef.h"
33#include "doomstat.h"
34#include "m_random.h"
35#include "r_main.h"
36#include "p_maputl.h"
37#include "p_map.h"
38#include "p_tick.h"
39#include "sounds.h"
40#include "st_stuff.h"
41#include "hu_stuff.h"
42#include "s_sound.h"
43#include "info.h"
44#include "g_game.h"
45#include "p_inter.h"
46#include "rockmacros.h"
47//
48// P_SetMobjState
49// Returns true if the mobj is still present.
50//
51
52statenum_t i IBSS_ATTR; // initial state
53statenum_t seenstate_tab[NUMSTATES] IBSS_ATTR; // fast transition table
54
55boolean P_SetMobjState(mobj_t* mobj,statenum_t state)
56{
57 state_t* st;
58 // killough 4/9/98: remember states seen, to detect cycles:
59 statenum_t *seenstate = seenstate_tab; // pointer to table
60 static int recursion; // detects recursion
61 i = state;
62 boolean ret = true; // return value
63
64 if (recursion++) // if recursion detected,
65 memset(seenstate,0,sizeof(seenstate_tab)); // clear state table
66
67 do
68 {
69 if (state == S_NULL)
70 {
71 mobj->state = (state_t *) S_NULL;
72 P_RemoveMobj (mobj);
73 ret = false;
74 break; // killough 4/9/98
75 }
76
77 st = &states[state];
78 mobj->state = st;
79 mobj->tics = st->tics;
80 mobj->sprite = st->sprite;
81 mobj->frame = st->frame;
82
83 // Modified handling.
84 // Call action functions when the state is set
85
86 if (st->action)
87 st->action(mobj);
88
89 seenstate[state] = 1 + st->nextstate; // killough 4/9/98
90
91 state = st->nextstate;
92 } while (!mobj->tics && !seenstate[state]); // killough 4/9/98
93
94 if (ret && !mobj->tics) // killough 4/9/98: detect state cycles
95 doom_printf("Warning: State Cycle Detected");
96
97 if (!--recursion)
98 for (;(state=seenstate[i]);i=state-1)
99 seenstate[i] = 0; // killough 4/9/98: erase memory of states
100
101 return ret;
102}
103
104
105//
106// P_ExplodeMissile
107//
108
109void P_ExplodeMissile (mobj_t* mo)
110{
111 mo->momx = mo->momy = mo->momz = 0;
112
113 P_SetMobjState (mo, mobjinfo[mo->type].deathstate);
114
115 mo->tics -= P_Random(pr_explode)&3;
116
117 if (mo->tics < 1)
118 mo->tics = 1;
119
120 mo->flags &= ~MF_MISSILE;
121
122 if (mo->info->deathsound)
123 S_StartSound (mo, mo->info->deathsound);
124}
125
126
127//
128// P_XYMovement
129//
130// Attempts to move something if it has momentum.
131//
132
133void P_XYMovement (mobj_t* mo)
134{
135 player_t *player;
136 fixed_t xmove, ymove;
137#if 0
138 fixed_t ptryx;
139 fixed_t ptryy;
140 fixed_t xmove;
141 fixed_t ymove;
142 fixed_t oldx,oldy; // phares 9/10/98: reducing bobbing/momentum on ice
143 // when up against walls
144#endif
145 if (!(mo->momx | mo->momy)) // Any momentum?
146 {
147 if (mo->flags & MF_SKULLFLY)
148 {
149
150 // the skull slammed into something
151
152 mo->flags &= ~MF_SKULLFLY;
153 mo->momz = 0;
154
155 P_SetMobjState (mo, mo->info->spawnstate);
156 }
157 return;
158 }
159
160 player = mo->player;
161
162 if (mo->momx > MAXMOVE)
163 mo->momx = MAXMOVE;
164 else if (mo->momx < -MAXMOVE)
165 mo->momx = -MAXMOVE;
166
167 if (mo->momy > MAXMOVE)
168 mo->momy = MAXMOVE;
169 else if (mo->momy < -MAXMOVE)
170 mo->momy = -MAXMOVE;
171
172 xmove = mo->momx;
173 ymove = mo->momy;
174
175#if 0
176 oldx = mo->x; // phares 9/10/98: new code to reduce bobbing/momentum
177 oldy = mo->y; // when on ice & up against wall. These will be compared
178 // to your x,y values later to see if you were able to move
179#endif
180
181 do
182 {
183 fixed_t ptryx, ptryy;
184 // killough 8/9/98: fix bug in original Doom source:
185 // Large negative displacements were never considered.
186 // This explains the tendency for Mancubus fireballs
187 // to pass through walls.
188 // CPhipps - compatibility optioned
189
190 if (xmove > MAXMOVE/2 || ymove > MAXMOVE/2 ||
191 (!comp[comp_moveblock]
192 && (xmove < -MAXMOVE/2 || ymove < -MAXMOVE/2)))
193 {
194 ptryx = mo->x + xmove/2;
195 ptryy = mo->y + ymove/2;
196 xmove >>= 1;
197 ymove >>= 1;
198 }
199 else
200 {
201 ptryx = mo->x + xmove;
202 ptryy = mo->y + ymove;
203 xmove = ymove = 0;
204 }
205
206 // killough 3/15/98: Allow objects to drop off
207
208 if (!P_TryMove (mo, ptryx, ptryy, true))
209 {
210 // blocked move
211
212 // killough 8/11/98: bouncing off walls
213 // killough 10/98:
214 // Add ability for objects other than players to bounce on ice
215
216 if (!(mo->flags & MF_MISSILE) &&
217 mbf_features &&
218 (mo->flags & MF_BOUNCES ||
219 (!player && blockline &&
220 variable_friction && mo->z <= mo->floorz &&
221 P_GetFriction(mo, NULL) > ORIG_FRICTION)))
222 {
223 if (blockline)
224 {
225 fixed_t r = ((blockline->dx >> FRACBITS) * mo->momx +
226 (blockline->dy >> FRACBITS) * mo->momy) /
227 ((blockline->dx >> FRACBITS)*(blockline->dx >> FRACBITS)+
228 (blockline->dy >> FRACBITS)*(blockline->dy >> FRACBITS));
229 fixed_t x = FixedMul(r, blockline->dx);
230 fixed_t y = FixedMul(r, blockline->dy);
231
232 // reflect momentum away from wall
233
234 mo->momx = x*2 - mo->momx;
235 mo->momy = y*2 - mo->momy;
236
237 // if under gravity, slow down in
238 // direction perpendicular to wall.
239
240 if (!(mo->flags & MF_NOGRAVITY))
241 {
242 mo->momx = (mo->momx + x)/2;
243 mo->momy = (mo->momy + y)/2;
244 }
245 }
246 else
247 mo->momx = mo->momy = 0;
248 }
249 else
250 if (player) // try to slide along it
251 P_SlideMove (mo);
252 else
253 if (mo->flags & MF_MISSILE)
254 {
255 // explode a missile
256
257 if (ceilingline &&
258 ceilingline->backsector &&
259 ceilingline->backsector->ceilingpic == skyflatnum)
260 if (demo_compatibility || // killough
261 mo->z > ceilingline->backsector->ceilingheight)
262 {
263 // Hack to prevent missiles exploding
264 // against the sky.
265 // Does not handle sky floors.
266
267 P_RemoveMobj (mo);
268 return;
269 }
270 P_ExplodeMissile (mo);
271 }
272 else // whatever else it is, it is now standing still in (x,y)
273 mo->momx = mo->momy = 0;
274 }
275 } while (xmove || ymove);
276
277 // slow down
278
279#if 0 /* killough 10/98: this is unused code (except maybe in .deh files?) */
280 if (player && player->cheats & CF_NOMOMENTUM)
281 {
282 // debug option for no sliding at all
283 mo->momx = mo->momy = 0;
284 player->momx = player->momy = 0; /* killough 10/98 */
285 return;
286 }
287#endif
288
289 /* no friction for missiles or skulls ever, no friction when airborne */
290 if (mo->flags & (MF_MISSILE | MF_SKULLFLY) || mo->z > mo->floorz)
291 return;
292
293 /* killough 8/11/98: add bouncers
294 * killough 9/15/98: add objects falling off ledges
295 * killough 11/98: only include bouncers hanging off ledges
296 */
297 if (((mo->flags & MF_BOUNCES && mo->z > mo->dropoffz) ||
298 mo->flags & MF_CORPSE || mo->intflags & MIF_FALLING) &&
299 (mo->momx > FRACUNIT/4 || mo->momx < -FRACUNIT/4 ||
300 mo->momy > FRACUNIT/4 || mo->momy < -FRACUNIT/4) &&
301 mo->floorz != mo->subsector->sector->floorheight)
302 return; // do not stop sliding if halfway off a step with some momentum
303
304 // killough 11/98:
305 // Stop voodoo dolls that have come to rest, despite any
306 // moving corresponding player, except in old demos:
307
308 if (mo->momx > -STOPSPEED && mo->momx < STOPSPEED &&
309 mo->momy > -STOPSPEED && mo->momy < STOPSPEED &&
310 (!player || !(player->cmd.forwardmove | player->cmd.sidemove) ||
311 (player->mo != mo && compatibility_level >= lxdoom_1_compatibility)))
312 {
313 // if in a walking frame, stop moving
314
315 // killough 10/98:
316 // Don't affect main player when voodoo dolls stop, except in old demos:
317
318 if (player && (unsigned)(player->mo->state - states - S_PLAY_RUN1) < 4
319 && (player->mo == mo || compatibility_level >= lxdoom_1_compatibility))
320 P_SetMobjState(player->mo, S_PLAY);
321
322 mo->momx = mo->momy = 0;
323
324 /* killough 10/98: kill any bobbing momentum too (except in voodoo dolls)
325 * cph - DEMOSYNC - needs compatibility check?
326 */
327 if (player && player->mo == mo)
328 player->momx = player->momy = 0;
329 }
330 else
331 {
332 /* phares 3/17/98
333 *
334 * Friction will have been adjusted by friction thinkers for
335 * icy or muddy floors. Otherwise it was never touched and
336 * remained set at ORIG_FRICTION
337 *
338 * killough 8/28/98: removed inefficient thinker algorithm,
339 * instead using touching_sectorlist in P_GetFriction() to
340 * determine friction (and thus only when it is needed).
341 *
342 * killough 10/98: changed to work with new bobbing method.
343 * Reducing player momentum is no longer needed to reduce
344 * bobbing, so ice works much better now.
345 *
346 * cph - DEMOSYNC - need old code for Boom demos?
347 */
348
349 fixed_t friction = P_GetFriction(mo, NULL);
350
351 mo->momx = FixedMul(mo->momx, friction);
352 mo->momy = FixedMul(mo->momy, friction);
353
354 /* killough 10/98: Always decrease player bobbing by ORIG_FRICTION.
355 * This prevents problems with bobbing on ice, where it was not being
356 * reduced fast enough, leading to all sorts of kludges being developed.
357 */
358
359 if (player && player->mo == mo) /* Not voodoo dolls */
360 {
361 player->momx = FixedMul(player->momx, ORIG_FRICTION);
362 player->momy = FixedMul(player->momy, ORIG_FRICTION);
363 }
364
365 }
366}
367
368
369//
370// P_ZMovement
371//
372// Attempt vertical movement.
373
374static void P_ZMovement (mobj_t* mo)
375{
376 /* killough 7/11/98:
377 * BFG fireballs bounced on floors and ceilings in Pre-Beta Doom
378 * killough 8/9/98: added support for non-missile objects bouncing
379 * (e.g. grenade, mine, pipebomb)
380 */
381
382 if (mo->flags & MF_BOUNCES && mo->momz) {
383 mo->z += mo->momz;
384 if (mo->z <= mo->floorz) { /* bounce off floors */
385 mo->z = mo->floorz;
386 if (mo->momz < 0) {
387 mo->momz = -mo->momz;
388 if (!(mo->flags & MF_NOGRAVITY)) { /* bounce back with decay */
389 mo->momz = mo->flags & MF_FLOAT ? // floaters fall slowly
390 mo->flags & MF_DROPOFF ? // DROPOFF indicates rate
391 FixedMul(mo->momz, (fixed_t)(FRACUNIT*.85)) :
392 FixedMul(mo->momz, (fixed_t)(FRACUNIT*.70)) :
393 FixedMul(mo->momz, (fixed_t)(FRACUNIT*.45)) ;
394
395 /* Bring it to rest below a certain speed */
396 if (abs(mo->momz) <= mo->info->mass*(GRAVITY*4/256))
397 mo->momz = 0;
398 }
399
400 /* killough 11/98: touchy objects explode on impact */
401 if (mo->flags & MF_TOUCHY && mo->intflags & MIF_ARMED
402 && mo->health > 0)
403 P_DamageMobj(mo, NULL, NULL, mo->health);
404 else if (mo->flags & MF_FLOAT && sentient(mo))
405 goto floater;
406 return;
407 }
408} else if (mo->z >= mo->ceilingz - mo->height) {
409 /* bounce off ceilings */
410 mo->z = mo->ceilingz - mo->height;
411 if (mo->momz > 0) {
412 if (mo->subsector->sector->ceilingpic != skyflatnum)
413 mo->momz = -mo->momz; /* always bounce off non-sky ceiling */
414 else if (mo->flags & MF_MISSILE)
415 P_RemoveMobj(mo); /* missiles don't bounce off skies */
416 else if (mo->flags & MF_NOGRAVITY)
417 mo->momz = -mo->momz; // bounce unless under gravity
418
419 if (mo->flags & MF_FLOAT && sentient(mo))
420 goto floater;
421
422 return;
423 }
424 } else {
425 if (!(mo->flags & MF_NOGRAVITY)) /* free-fall under gravity */
426 mo->momz -= mo->info->mass*(GRAVITY/256);
427
428 if (mo->flags & MF_FLOAT && sentient(mo)) goto floater;
429 return;
430 }
431
432 /* came to a stop */
433 mo->momz = 0;
434
435 if (mo->flags & MF_MISSILE) {
436 if (ceilingline &&
437 ceilingline->backsector &&
438 ceilingline->backsector->ceilingpic == skyflatnum &&
439 mo->z > ceilingline->backsector->ceilingheight)
440 P_RemoveMobj(mo); /* don't explode on skies */
441 else
442 P_ExplodeMissile(mo);
443 }
444
445 if (mo->flags & MF_FLOAT && sentient(mo)) goto floater;
446 return;
447 }
448
449 /* killough 8/9/98: end bouncing object code */
450
451 // check for smooth step up
452
453 if (mo->player &&
454 mo->player->mo == mo && // killough 5/12/98: exclude voodoo dolls
455 mo->z < mo->floorz)
456 {
457 mo->player->viewheight -= mo->floorz-mo->z;
458 mo->player->deltaviewheight = (VIEWHEIGHT - mo->player->viewheight)>>3;
459 }
460
461 // adjust altitude
462
463 mo->z += mo->momz;
464
465floater:
466 if ((mo->flags & MF_FLOAT) && mo->target)
467
468 // float down towards target if too close
469
470 if (!((mo->flags ^ MF_FLOAT) & (MF_FLOAT | MF_SKULLFLY | MF_INFLOAT)) &&
471 mo->target) /* killough 11/98: simplify */
472 {
473 fixed_t delta;
474 if (P_AproxDistance(mo->x - mo->target->x, mo->y - mo->target->y) <
475 abs(delta = mo->target->z + (mo->height>>1) - mo->z)*3)
476 mo->z += delta < 0 ? -FLOATSPEED : FLOATSPEED;
477 }
478
479 // clip movement
480
481 if (mo->z <= mo->floorz)
482 {
483 // hit the floor
484
485 /* Note (id):
486 * somebody left this after the setting momz to 0,
487 * kinda useless there.
488 * cph - This was the a bug in the linuxdoom-1.10 source which
489 * caused it not to sync Doom 2 v1.9 demos. Someone
490 * added the above comment and moved up the following code. So
491 * demos would desync in close lost soul fights.
492 * Note that this only applies to original Doom 1 or Doom2 demos -
493 * Final Doom and Ultimate Doom. So we test demo_compatibility *and*
494 * gamemission. (Note we assume that Doom1 is always Ult Doom, which
495 * seems to hold for most published demos.)
496 */
497 int correct_lost_soul_bounce = !demo_compatibility || (gamemission != doom2);
498
499 if (correct_lost_soul_bounce && mo->flags & MF_SKULLFLY)
500 mo->momz = -mo->momz; // the skull slammed into something
501
502 if (mo->momz < 0)
503 {
504 /* killough 11/98: touchy objects explode on impact */
505 if (mo->flags & MF_TOUCHY && mo->intflags & MIF_ARMED && mo->health > 0)
506 P_DamageMobj(mo, NULL, NULL, mo->health);
507 else
508 if (mo->player && /* killough 5/12/98: exclude voodoo dolls */
509 mo->player->mo == mo && mo->momz < -GRAVITY*8)
510 {
511 // Squat down.
512 // Decrease viewheight for a moment
513 // after hitting the ground (hard),
514 // and utter appropriate sound.
515
516 mo->player->deltaviewheight = mo->momz>>3;
517 if (mo->health) /* cph - prevent "oof" when dead */
518 S_StartSound (mo, sfx_oof);
519 }
520 mo->momz = 0;
521 }
522 mo->z = mo->floorz;
523
524 /* cph 2001/05/26 -
525 * See lost soul bouncing comment above. We need this here for bug
526 * compatibility with original Doom2 v1.9 - if a soul is charging and
527 * hit by a raising floor this incorrectly reverses its Y momentum.
528 */
529 if (!correct_lost_soul_bounce && mo->flags & MF_SKULLFLY)
530 mo->momz = -mo->momz; // the skull slammed into something
531
532 if ( (mo->flags & MF_MISSILE) && !(mo->flags & MF_NOCLIP) )
533 {
534 P_ExplodeMissile (mo);
535 return;
536 }
537 }
538 else // still above the floor // phares
539 if (!(mo->flags & MF_NOGRAVITY))
540 {
541 if (!mo->momz)
542 mo->momz = -GRAVITY;
543 mo->momz -= GRAVITY;
544 }
545
546 if (mo->z + mo->height > mo->ceilingz)
547 {
548
549 // hit the ceiling
550
551 if (mo->momz > 0)
552 mo->momz = 0;
553
554 mo->z = mo->ceilingz - mo->height;
555
556 if (mo->flags & MF_SKULLFLY)
557 mo->momz = -mo->momz; // the skull slammed into something
558
559 if ( (mo->flags & MF_MISSILE) && !(mo->flags & MF_NOCLIP) )
560 {
561 P_ExplodeMissile (mo);
562 return;
563 }
564 }
565}
566
567//
568// P_NightmareRespawn
569//
570
571void P_NightmareRespawn(mobj_t* mobj)
572{
573 fixed_t x;
574 fixed_t y;
575 fixed_t z;
576 subsector_t* ss;
577 mobj_t* mo;
578 mapthing_t* mthing;
579
580 x = mobj->spawnpoint.x << FRACBITS;
581 y = mobj->spawnpoint.y << FRACBITS;
582
583 /* haleyjd: stupid nightmare respawning bug fix
584 *
585 * 08/09/00: compatibility added, time to ramble :)
586 * This fixes the notorious nightmare respawning bug that causes monsters
587 * that didn't spawn at level startup to respawn at the point (0,0)
588 * regardless of that point's nature. SMMU and Eternity need this for
589 * script-spawned things like Halif Swordsmythe, as well.
590 *
591 * cph - copied from eternity, except comp_respawnfix becomes comp_respawn
592 * and the logic is reversed (i.e. like the rest of comp_ it *disables*
593 * the fix)
594 */
595 if(!comp[comp_respawn] && !x && !y)
596 {
597 // spawnpoint was zeroed out, so use point of death instead
598 x = mobj->x;
599 y = mobj->y;
600 }
601
602 // something is occupying its position?
603
604 if (!P_CheckPosition (mobj, x, y) )
605 return; // no respwan
606
607 // spawn a teleport fog at old spot
608 // because of removal of the body?
609
610 mo = P_SpawnMobj (mobj->x,
611 mobj->y,
612 mobj->subsector->sector->floorheight,
613 MT_TFOG);
614
615 // initiate teleport sound
616
617 S_StartSound (mo, sfx_telept);
618
619 // spawn a teleport fog at the new spot
620
621 ss = R_PointInSubsector (x,y);
622
623 mo = P_SpawnMobj (x, y, ss->sector->floorheight , MT_TFOG);
624
625 S_StartSound (mo, sfx_telept);
626
627 // spawn the new monster
628
629 mthing = &mobj->spawnpoint;
630 if (mobj->info->flags & MF_SPAWNCEILING)
631 z = ONCEILINGZ;
632 else
633 z = ONFLOORZ;
634
635 // inherit attributes from deceased one
636
637 mo = P_SpawnMobj (x,y,z, mobj->type);
638 mo->spawnpoint = mobj->spawnpoint;
639 mo->angle = ANG45 * (mthing->angle/45);
640
641 if (mthing->options & MTF_AMBUSH)
642 mo->flags |= MF_AMBUSH;
643
644 /* killough 11/98: transfer friendliness from deceased */
645 mo->flags = (mo->flags & ~MF_FRIEND) | (mobj->flags & MF_FRIEND);
646
647 mo->reactiontime = 18;
648
649 // remove the old monster,
650
651 P_RemoveMobj (mobj);
652}
653
654
655//
656// P_MobjThinker
657//
658
659void P_MobjThinker (mobj_t* mobj)
660{
661 // killough 11/98:
662 // removed old code which looked at target references
663 // (we use pointer reference counting now)
664
665 // momentum movement
666 if (mobj->momx | mobj->momy || mobj->flags & MF_SKULLFLY)
667 {
668 P_XYMovement(mobj);
669 if (mobj->thinker.function != P_MobjThinker) // cph - Must've been removed
670 return; // killough - mobj was removed
671 }
672
673 if (mobj->z != mobj->floorz || mobj->momz)
674 {
675 P_ZMovement(mobj);
676 if (mobj->thinker.function != P_MobjThinker) // cph - Must've been removed
677 return; // killough - mobj was removed
678 }
679 else
680 if (!(mobj->momx | mobj->momy) && !sentient(mobj))
681 { // non-sentient objects at rest
682 mobj->intflags |= MIF_ARMED; // arm a mine which has come to rest
683
684 // killough 9/12/98: objects fall off ledges if they are hanging off
685 // slightly push off of ledge if hanging more than halfway off
686
687 if (mobj->z > mobj->dropoffz && // Only objects contacting dropoff
688 !(mobj->flags & MF_NOGRAVITY) && // Only objects which fall
689 !comp[comp_falloff]) // Not in old demos
690 P_ApplyTorque(mobj); // Apply torque
691 else
692 mobj->intflags &= ~MIF_FALLING, mobj->gear = 0; // Reset torque
693 }
694
695 // cycle through states,
696 // calling action functions at transitions
697
698 if (mobj->tics != -1)
699 {
700 mobj->tics--;
701
702 // you can cycle through multiple states in a tic
703
704 if (!mobj->tics)
705 if (!P_SetMobjState (mobj, mobj->state->nextstate) )
706 return; // freed itself
707 }
708 else
709 {
710
711 // check for nightmare respawn
712
713 if (! (mobj->flags & MF_COUNTKILL) )
714 return;
715
716 if (!respawnmonsters)
717 return;
718
719 mobj->movecount++;
720
721 if (mobj->movecount < 12*35)
722 return;
723
724 if (leveltime & 31)
725 return;
726
727 if (P_Random (pr_respawn) > 4)
728 return;
729
730 P_NightmareRespawn (mobj);
731 }
732
733}
734
735
736//
737// P_SpawnMobj
738//
739mobj_t* P_SpawnMobj(fixed_t x,fixed_t y,fixed_t z,mobjtype_t type)
740{
741 mobj_t* mobj;
742 state_t* st;
743 mobjinfo_t* info;
744
745 mobj = Z_Malloc (sizeof(*mobj), PU_LEVEL, NULL);
746 memset (mobj, 0, sizeof (*mobj));
747 info = &mobjinfo[type];
748 mobj->type = type;
749 mobj->info = info;
750 mobj->x = x;
751 mobj->y = y;
752 mobj->radius = info->radius;
753 mobj->height = info->height; // phares
754 mobj->flags = info->flags;
755
756 /* killough 8/23/98: no friends, bouncers, or touchy things in old demos */
757 if (!mbf_features)
758 mobj->flags &= ~(MF_BOUNCES | MF_FRIEND | MF_TOUCHY);
759 else
760 if (type == MT_PLAYER) // Except in old demos, players
761 mobj->flags |= MF_FRIEND; // are always friends.
762
763 mobj->health = info->spawnhealth;
764
765 if (gameskill != sk_nightmare)
766 mobj->reactiontime = info->reactiontime;
767
768 mobj->lastlook = P_Random (pr_lastlook) % MAXPLAYERS;
769
770 // do not set the state with P_SetMobjState,
771 // because action routines can not be called yet
772
773 st = &states[info->spawnstate];
774
775 mobj->state = st;
776 mobj->tics = st->tics;
777 mobj->sprite = st->sprite;
778 mobj->frame = st->frame;
779 mobj->touching_sectorlist = NULL; // NULL head of sector list // phares 3/13/98
780
781 // set subsector and/or block links
782
783 P_SetThingPosition (mobj);
784
785 mobj->dropoffz = /* killough 11/98: for tracking dropoffs */
786 mobj->floorz = mobj->subsector->sector->floorheight;
787 mobj->ceilingz = mobj->subsector->sector->ceilingheight;
788
789 mobj->z = z == ONFLOORZ ? mobj->floorz : z == ONCEILINGZ ?
790 mobj->ceilingz - mobj->height : z;
791
792 mobj->thinker.function = P_MobjThinker;
793 mobj->above_thing = 0; // phares
794 mobj->below_thing = 0; // phares
795
796 mobj->target = mobj->tracer = mobj->lastenemy = NULL;
797 P_AddThinker (&mobj->thinker);
798 if (!((mobj->flags ^ MF_COUNTKILL) & (MF_FRIEND | MF_COUNTKILL)))
799 totallive++;
800 return mobj;
801}
802
803
804mapthing_t itemrespawnque[ITEMQUESIZE];
805int itemrespawntime[ITEMQUESIZE];
806int iquehead;
807int iquetail;
808
809
810//
811// P_RemoveMobj
812//
813
814void P_RemoveMobj (mobj_t* mobj)
815{
816 if ((mobj->flags & MF_SPECIAL)
817 && !(mobj->flags & MF_DROPPED)
818 && (mobj->type != MT_INV)
819 && (mobj->type != MT_INS))
820 {
821 itemrespawnque[iquehead] = mobj->spawnpoint;
822 itemrespawntime[iquehead] = leveltime;
823 iquehead = (iquehead+1)&(ITEMQUESIZE-1);
824
825 // lose one off the end?
826
827 if (iquehead == iquetail)
828 iquetail = (iquetail+1)&(ITEMQUESIZE-1);
829 }
830
831 // unlink from sector and block lists
832
833 P_UnsetThingPosition (mobj);
834
835 // Delete all nodes on the current sector_list phares 3/16/98
836
837 if (sector_list)
838 {
839 P_DelSeclist(sector_list);
840 sector_list = NULL;
841 }
842
843 // stop any playing sound
844
845 S_StopSound (mobj);
846
847 // killough 11/98:
848 //
849 // Remove any references to other mobjs.
850 //
851 // Older demos might depend on the fields being left alone, however,
852 // if multiple thinkers reference each other indirectly before the
853 // end of the current tic.
854 // CPhipps - only leave dead references in old demos; I hope lxdoom_1 level
855 // demos are rare and don't rely on this. I hope.
856
857 if ((compatibility_level >= lxdoom_1_compatibility) ||
858 (!demorecording && !demoplayback)) {
859 P_SetTarget(&mobj->target, NULL);
860 P_SetTarget(&mobj->tracer, NULL);
861 P_SetTarget(&mobj->lastenemy, NULL);
862 }
863 // free block
864
865 // P_RemoveThinker ((thinker_t*)mobj);
866 P_RemoveThinker (&mobj->thinker);
867}
868
869
870/*
871 * P_FindDoomedNum
872 *
873 * Finds a mobj type with a matching doomednum
874 *
875 * killough 8/24/98: rewrote to use hashing
876 */
877
878int P_FindDoomedNum(unsigned type)
879{
880 static struct { int first, next; } *hash;
881 register int i;
882
883 if (!hash)
884 {
885 hash = Z_Malloc(sizeof (*hash) * NUMMOBJTYPES, PU_CACHE, (void*)(void*) &hash);
886 for (i=0; i<NUMMOBJTYPES; i++)
887 hash[i].first = NUMMOBJTYPES;
888 for (i=0; i<NUMMOBJTYPES; i++)
889 if (mobjinfo[i].doomednum != -1)
890 {
891 unsigned h = (unsigned) mobjinfo[i].doomednum % NUMMOBJTYPES;
892 hash[i].next = hash[h].first;
893 hash[h].first = i;
894 }
895 }
896
897 i = hash[type % NUMMOBJTYPES].first;
898 while ((i < NUMMOBJTYPES) && ((unsigned)mobjinfo[i].doomednum != type))
899 i = hash[i].next;
900 return i;
901}
902
903//
904// P_RespawnSpecials
905//
906
907void P_RespawnSpecials (void)
908{
909 fixed_t x;
910 fixed_t y;
911 fixed_t z;
912 subsector_t* ss;
913 mobj_t* mo;
914 mapthing_t* mthing;
915 int i;
916
917 // only respawn items in deathmatch
918
919 if (deathmatch != 2)
920 return;
921
922 // nothing left to respawn?
923
924 if (iquehead == iquetail)
925 return;
926
927 // wait at least 30 seconds
928
929 if (leveltime - itemrespawntime[iquetail] < 30*35)
930 return;
931
932 mthing = &itemrespawnque[iquetail];
933
934 x = mthing->x << FRACBITS;
935 y = mthing->y << FRACBITS;
936
937 // spawn a teleport fog at the new spot
938
939 ss = R_PointInSubsector (x,y);
940 mo = P_SpawnMobj (x, y, ss->sector->floorheight , MT_IFOG);
941 S_StartSound (mo, sfx_itmbk);
942
943 // find which type to spawn
944
945 /* killough 8/23/98: use table for faster lookup */
946 i = P_FindDoomedNum(mthing->type);
947
948 // spawn it
949
950 if (mobjinfo[i].flags & MF_SPAWNCEILING)
951 z = ONCEILINGZ;
952 else
953 z = ONFLOORZ;
954
955 mo = P_SpawnMobj (x,y,z, i);
956 mo->spawnpoint = *mthing;
957 mo->angle = ANG45 * (mthing->angle/45);
958
959 // pull it from the queue
960
961 iquetail = (iquetail+1)&(ITEMQUESIZE-1);
962}
963
964//
965// P_SpawnPlayer
966// Called when a player is spawned on the level.
967// Most of the player structure stays unchanged
968// between levels.
969//
970
971extern byte playernumtotrans[MAXPLAYERS];
972
973void P_SpawnPlayer (mapthing_t* mthing)
974{
975 player_t* p;
976 fixed_t x;
977 fixed_t y;
978 fixed_t z;
979 mobj_t* mobj;
980 int i;
981
982 // not playing?
983
984 if (!playeringame[mthing->type-1])
985 return;
986
987 p = &players[mthing->type-1];
988
989 if (p->playerstate == PST_REBORN)
990 G_PlayerReborn (mthing->type-1);
991
992 x = mthing->x << FRACBITS;
993 y = mthing->y << FRACBITS;
994 z = ONFLOORZ;
995 mobj = P_SpawnMobj (x,y,z, MT_PLAYER);
996
997 // set color translations for player sprites
998
999 if (mthing->type > 0)
1000 mobj->flags |= playernumtotrans[mthing->type-1]<<MF_TRANSSHIFT;
1001
1002 mobj->angle = ANG45 * (mthing->angle/45);
1003 mobj->player = p;
1004 mobj->health = p->health;
1005
1006 p->mo = mobj;
1007 p->playerstate = PST_LIVE;
1008 p->refire = 0;
1009 p->message = NULL;
1010 p->damagecount = 0;
1011 p->bonuscount = 0;
1012 p->extralight = 0;
1013 p->fixedcolormap = 0;
1014 p->viewheight = VIEWHEIGHT;
1015
1016 p->momx = p->momy = 0; // killough 10/98: initialize bobbing to 0.
1017
1018 // setup gun psprite
1019
1020 P_SetupPsprites (p);
1021
1022 // give all cards in death match mode
1023
1024 if (deathmatch)
1025 for (i = 0 ; i < NUMCARDS ; i++)
1026 p->cards[i] = true;
1027
1028 if (mthing->type-1 == consoleplayer)
1029 {
1030 ST_Start(); // wake up the status bar
1031 HU_Start(); // wake up the heads up text
1032 }
1033}
1034
1035
1036//
1037// P_SpawnMapThing
1038// The fields of the mapthing should
1039// already be in host byte order.
1040//
1041
1042void P_SpawnMapThing (mapthing_t* mthing)
1043{
1044 int i;
1045 //int bit;
1046 mobj_t* mobj;
1047 fixed_t x;
1048 fixed_t y;
1049 fixed_t z;
1050
1051 // killough 2/26/98: Ignore type-0 things as NOPs
1052 // phares 5/14/98: Ignore Player 5-8 starts (for now)
1053
1054 switch(mthing->type)
1055 {
1056 case 0:
1057 case DEN_PLAYER5:
1058 case DEN_PLAYER6:
1059 case DEN_PLAYER7:
1060 case DEN_PLAYER8:
1061 return;
1062 }
1063
1064 // killough 11/98: clear flags unused by Doom
1065 //
1066 // We clear the flags unused in Doom if we see flag mask 256 set, since
1067 // it is reserved to be 0 under the new scheme. A 1 in this reserved bit
1068 // indicates it's a Doom wad made by a Doom editor which puts 1's in
1069 // bits that weren't used in Doom (such as HellMaker wads). So we should
1070 // then simply ignore all upper bits.
1071
1072 if (demo_compatibility ||
1073 (compatibility_level >= lxdoom_1_compatibility &&
1074 mthing->options & MTF_RESERVED)) {
1075 if (!demo_compatibility) // cph - Add warning about bad thing flags
1076 printf("P_SpawnMapThing: correcting bad flags (%u) (thing type %d)\n",
1077 mthing->options, mthing->type);
1078 mthing->options &= MTF_EASY|MTF_NORMAL|MTF_HARD|MTF_AMBUSH|MTF_NOTSINGLE;
1079 }
1080
1081 // count deathmatch start positions
1082
1083 // doom2.exe has at most 10 deathmatch starts
1084 if (mthing->type == 11 && (!compatibility || deathmatch_p-deathmatchstarts < 10))
1085 {
1086 // 1/11/98 killough -- new code removes limit on deathmatch starts:
1087
1088 size_t offset = deathmatch_p - deathmatchstarts;
1089
1090 if (offset >= num_deathmatchstarts)
1091 {
1092 num_deathmatchstarts = num_deathmatchstarts ?
1093 num_deathmatchstarts*2 : 16;
1094 deathmatchstarts = realloc(deathmatchstarts,
1095 num_deathmatchstarts *
1096 sizeof(*deathmatchstarts));
1097 deathmatch_p = deathmatchstarts + offset;
1098 }
1099 memcpy(deathmatch_p++, mthing, sizeof(*mthing));
1100 return;
1101 }
1102
1103 // check for players specially
1104
1105 if (mthing->type <= 4 && mthing->type > 0) // killough 2/26/98 -- fix crashes
1106 {
1107#ifdef DOGS
1108 // killough 7/19/98: Marine's best friend :)
1109 if (!netgame && mthing->type > 1 && mthing->type <= dogs+1 &&
1110 !players[mthing->type-1].secretcount)
1111 { // use secretcount to avoid multiple dogs in case of multiple starts
1112 players[mthing->type-1].secretcount = 1;
1113
1114 // killough 10/98: force it to be a friend
1115 mthing->options |= MTF_FRIEND;
1116 i = MT_DOGS;
1117 goto spawnit;
1118 }
1119#endif
1120
1121
1122 // save spots for respawning in network games
1123
1124 playerstarts[mthing->type-1] = *mthing;
1125 if (!deathmatch)
1126 P_SpawnPlayer (mthing);
1127 return;
1128 }
1129
1130 // check for apropriate skill level
1131
1132 /* jff "not single" thing flag */
1133 if (!netgame && mthing->options & MTF_NOTSINGLE)
1134 return;
1135
1136 //jff 3/30/98 implement "not deathmatch" thing flag
1137
1138 if (netgame && deathmatch && mthing->options & MTF_NOTDM)
1139 return;
1140
1141 //jff 3/30/98 implement "not cooperative" thing flag
1142
1143 if (netgame && !deathmatch && mthing->options & MTF_NOTCOOP)
1144 return;
1145
1146 // killough 11/98: simplify
1147 if (gameskill == sk_baby || gameskill == sk_easy ?
1148 !(mthing->options & MTF_EASY) :
1149 gameskill == sk_hard || gameskill == sk_nightmare ?
1150 !(mthing->options & MTF_HARD) : !(mthing->options & MTF_NORMAL))
1151 return;
1152
1153 // find which type to spawn
1154
1155 // killough 8/23/98: use table for faster lookup
1156 i = P_FindDoomedNum(mthing->type);
1157
1158 // phares 5/16/98:
1159 // Do not abort because of an unknown thing. Ignore it, but post a
1160 // warning message for the player.
1161
1162 if (i == NUMMOBJTYPES)
1163 {
1164 doom_printf("Unknown Thing type %i at (%i, %i)",mthing->type,mthing->x,mthing->y);
1165 return;
1166 }
1167
1168 // don't spawn keycards and players in deathmatch
1169
1170 if (deathmatch && mobjinfo[i].flags & MF_NOTDMATCH)
1171 return;
1172
1173 // don't spawn any monsters if -nomonsters
1174
1175 if (nomonsters && (i == MT_SKULL || (mobjinfo[i].flags & MF_COUNTKILL)))
1176 return;
1177
1178 // spawn it
1179#ifdef DOGS
1180spawnit:
1181#endif
1182
1183 x = mthing->x << FRACBITS;
1184 y = mthing->y << FRACBITS;
1185
1186 if (mobjinfo[i].flags & MF_SPAWNCEILING)
1187 z = ONCEILINGZ;
1188 else
1189 z = ONFLOORZ;
1190
1191 mobj = P_SpawnMobj (x,y,z, i);
1192 mobj->spawnpoint = *mthing;
1193
1194 if (mobj->tics > 0)
1195 mobj->tics = 1 + (P_Random (pr_spawnthing) % mobj->tics);
1196
1197 if (!(mobj->flags & MF_FRIEND) &&
1198 mthing->options & MTF_FRIEND &&
1199 mbf_features)
1200 {
1201 mobj->flags |= MF_FRIEND; // killough 10/98:
1202 P_UpdateThinker(&mobj->thinker); // transfer friendliness flag
1203 }
1204
1205 /* killough 7/20/98: exclude friends */
1206 if (!((mobj->flags ^ MF_COUNTKILL) & (MF_FRIEND | MF_COUNTKILL)))
1207 totalkills++;
1208
1209 if (mobj->flags & MF_COUNTITEM)
1210 totalitems++;
1211
1212 mobj->angle = ANG45 * (mthing->angle/45);
1213 if (mthing->options & MTF_AMBUSH)
1214 mobj->flags |= MF_AMBUSH;
1215}
1216
1217
1218//
1219// GAME SPAWN FUNCTIONS
1220//
1221
1222//
1223// P_SpawnPuff
1224//
1225
1226extern fixed_t attackrange;
1227
1228void P_SpawnPuff(fixed_t x,fixed_t y,fixed_t z)
1229{
1230 mobj_t* th;
1231 // killough 5/5/98: remove dependence on order of evaluation:
1232 int t = P_Random(pr_spawnpuff);
1233 z += (t - P_Random(pr_spawnpuff))<<10;
1234
1235 th = P_SpawnMobj (x,y,z, MT_PUFF);
1236 th->momz = FRACUNIT;
1237 th->tics -= P_Random(pr_spawnpuff)&3;
1238
1239 if (th->tics < 1)
1240 th->tics = 1;
1241
1242 // don't make punches spark on the wall
1243
1244 if (attackrange == MELEERANGE)
1245 P_SetMobjState (th, S_PUFF3);
1246}
1247
1248
1249//
1250// P_SpawnBlood
1251//
1252void P_SpawnBlood(fixed_t x,fixed_t y,fixed_t z,int damage)
1253{
1254 mobj_t* th;
1255 // killough 5/5/98: remove dependence on order of evaluation:
1256 int t = P_Random(pr_spawnblood);
1257 z += (t - P_Random(pr_spawnblood))<<10;
1258 th = P_SpawnMobj(x,y,z, MT_BLOOD);
1259 th->momz = FRACUNIT*2;
1260 th->tics -= P_Random(pr_spawnblood)&3;
1261
1262 if (th->tics < 1)
1263 th->tics = 1;
1264
1265 if (damage <= 12 && damage >= 9)
1266 P_SetMobjState (th,S_BLOOD2);
1267 else if (damage < 9)
1268 P_SetMobjState (th,S_BLOOD3);
1269}
1270
1271
1272//
1273// P_CheckMissileSpawn
1274// Moves the missile forward a bit
1275// and possibly explodes it right there.
1276//
1277
1278void P_CheckMissileSpawn (mobj_t* th)
1279{
1280 th->tics -= P_Random(pr_missile)&3;
1281 if (th->tics < 1)
1282 th->tics = 1;
1283
1284 // move a little forward so an angle can
1285 // be computed if it immediately explodes
1286
1287 th->x += (th->momx>>1);
1288 th->y += (th->momy>>1);
1289 th->z += (th->momz>>1);
1290
1291 // killough 8/12/98: for non-missile objects (e.g. grenades)
1292 if (!(th->flags & MF_MISSILE) && mbf_features)
1293 return;
1294
1295 // killough 3/15/98: no dropoff (really = don't care for missiles)
1296
1297 if (!P_TryMove (th, th->x, th->y, false))
1298 P_ExplodeMissile (th);
1299}
1300
1301
1302//
1303// P_SpawnMissile
1304//
1305
1306mobj_t* P_SpawnMissile(mobj_t* source,mobj_t* dest,mobjtype_t type)
1307{
1308 mobj_t* th;
1309 angle_t an;
1310 int dist;
1311
1312 th = P_SpawnMobj (source->x,source->y,source->z + 4*8*FRACUNIT,type);
1313
1314 if (th->info->seesound)
1315 S_StartSound (th, th->info->seesound);
1316
1317 P_SetTarget(&th->target, source); // where it came from
1318 an = R_PointToAngle2 (source->x, source->y, dest->x, dest->y);
1319
1320 // fuzzy player
1321
1322 if (dest->flags & MF_SHADOW)
1323 { // killough 5/5/98: remove dependence on order of evaluation:
1324 int t = P_Random(pr_shadow);
1325 an += (t - P_Random(pr_shadow))<<20;
1326 }
1327
1328 th->angle = an;
1329 an >>= ANGLETOFINESHIFT;
1330 th->momx = FixedMul (th->info->speed, finecosine[an]);
1331 th->momy = FixedMul (th->info->speed, finesine[an]);
1332
1333 dist = P_AproxDistance (dest->x - source->x, dest->y - source->y);
1334 dist = dist / th->info->speed;
1335
1336 if (dist < 1)
1337 dist = 1;
1338
1339 th->momz = (dest->z - source->z) / dist;
1340 P_CheckMissileSpawn (th);
1341
1342 return th;
1343}
1344
1345
1346//
1347// P_SpawnPlayerMissile
1348// Tries to aim at a nearby monster
1349//
1350
1351void P_SpawnPlayerMissile(mobj_t* source,mobjtype_t type)
1352{
1353 mobj_t *th;
1354 fixed_t x, y, z, slope = 0;
1355
1356 // see which target is to be aimed at
1357
1358 angle_t an = source->angle;
1359
1360 // killough 7/19/98: autoaiming was not in original beta
1361 {
1362 // killough 8/2/98: prefer autoaiming at enemies
1363 uint_64_t mask = mbf_features ? MF_FRIEND : 0;
1364
1365 do
1366 {
1367 slope = P_AimLineAttack(source, an, 16*64*FRACUNIT, mask);
1368 if (!linetarget)
1369 slope = P_AimLineAttack(source, an += 1<<26, 16*64*FRACUNIT, mask);
1370 if (!linetarget)
1371 slope = P_AimLineAttack(source, an -= 2<<26, 16*64*FRACUNIT, mask);
1372 if (!linetarget)
1373 an = source->angle, slope = 0;
1374 }
1375 while (mask && (mask=0, !linetarget)); // killough 8/2/98
1376 }
1377
1378 x = source->x;
1379 y = source->y;
1380 z = source->z + 4*8*FRACUNIT;
1381
1382 th = P_SpawnMobj (x,y,z, type);
1383
1384 if (th->info->seesound)
1385 S_StartSound (th, th->info->seesound);
1386
1387 P_SetTarget(&th->target, source);
1388 th->angle = an;
1389 th->momx = FixedMul(th->info->speed,finecosine[an>>ANGLETOFINESHIFT]);
1390 th->momy = FixedMul(th->info->speed,finesine[an>>ANGLETOFINESHIFT]);
1391 th->momz = FixedMul(th->info->speed,slope);
1392
1393 P_CheckMissileSpawn(th);
1394}
diff --git a/apps/plugins/doom/p_mobj.h b/apps/plugins/doom/p_mobj.h
new file mode 100644
index 0000000000..bdd863afd9
--- /dev/null
+++ b/apps/plugins/doom/p_mobj.h
@@ -0,0 +1,409 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION:
28 * Map Objects, MObj, definition and handling.
29 *
30 *-----------------------------------------------------------------------------*/
31
32#ifndef __P_MOBJ__
33#define __P_MOBJ__
34
35// Basics.
36#include "tables.h"
37#include "m_fixed.h"
38
39// We need the thinker_t stuff.
40#include "d_think.h"
41
42// We need the WAD data structure for Map things,
43// from the THINGS lump.
44#include "doomdata.h"
45
46// States are tied to finite states are
47// tied to animation frames.
48// Needs precompiled tables/data structures.
49#include "info.h"
50
51//
52// NOTES: mobj_t
53//
54// mobj_ts are used to tell the refresh where to draw an image,
55// tell the world simulation when objects are contacted,
56// and tell the sound driver how to position a sound.
57//
58// The refresh uses the next and prev links to follow
59// lists of things in sectors as they are being drawn.
60// The sprite, frame, and angle elements determine which patch_t
61// is used to draw the sprite if it is visible.
62// The sprite and frame values are allmost allways set
63// from state_t structures.
64// The statescr.exe utility generates the states.h and states.c
65// files that contain the sprite/frame numbers from the
66// statescr.txt source file.
67// The xyz origin point represents a point at the bottom middle
68// of the sprite (between the feet of a biped).
69// This is the default origin position for patch_ts grabbed
70// with lumpy.exe.
71// A walking creature will have its z equal to the floor
72// it is standing on.
73//
74// The sound code uses the x,y, and subsector fields
75// to do stereo positioning of any sound effited by the mobj_t.
76//
77// The play simulation uses the blocklinks, x,y,z, radius, height
78// to determine when mobj_ts are touching each other,
79// touching lines in the map, or hit by trace lines (gunshots,
80// lines of sight, etc).
81// The mobj_t->flags element has various bit flags
82// used by the simulation.
83//
84// Every mobj_t is linked into a single sector
85// based on its origin coordinates.
86// The subsector_t is found with R_PointInSubsector(x,y),
87// and the sector_t can be found with subsector->sector.
88// The sector links are only used by the rendering code,
89// the play simulation does not care about them at all.
90//
91// Any mobj_t that needs to be acted upon by something else
92// in the play world (block movement, be shot, etc) will also
93// need to be linked into the blockmap.
94// If the thing has the MF_NOBLOCK flag set, it will not use
95// the block links. It can still interact with other things,
96// but only as the instigator (missiles will run into other
97// things, but nothing can run into a missile).
98// Each block in the grid is 128*128 units, and knows about
99// every line_t that it contains a piece of, and every
100// interactable mobj_t that has its origin contained.
101//
102// A valid mobj_t is a mobj_t that has the proper subsector_t
103// filled in for its xy coordinates and is linked into the
104// sector from which the subsector was made, or has the
105// MF_NOSECTOR flag set (the subsector_t needs to be valid
106// even if MF_NOSECTOR is set), and is linked into a blockmap
107// block or has the MF_NOBLOCKMAP flag set.
108// Links should only be modified by the P_[Un]SetThingPosition()
109// functions.
110// Do not change the MF_NO? flags while a thing is valid.
111//
112// Any questions?
113//
114
115//
116// Misc. mobj flags
117//
118
119// Call P_SpecialThing when touched.
120#define MF_SPECIAL (uint_64_t)(0x0000000000000001LL)
121// Blocks.
122#define MF_SOLID (uint_64_t)(0x0000000000000002LL)
123// Can be hit.
124#define MF_SHOOTABLE (uint_64_t)(0x0000000000000004LL)
125// Don't use the sector links (invisible but touchable).
126#define MF_NOSECTOR (uint_64_t)(0x0000000000000008LL)
127// Don't use the blocklinks (inert but displayable)
128#define MF_NOBLOCKMAP (uint_64_t)(0x0000000000000010LL)
129
130// Not to be activated by sound, deaf monster.
131#define MF_AMBUSH (uint_64_t)(0x0000000000000020LL)
132// Will try to attack right back.
133#define MF_JUSTHIT (uint_64_t)(0x0000000000000040LL)
134// Will take at least one step before attacking.
135#define MF_JUSTATTACKED (uint_64_t)(0x0000000000000080LL)
136// On level spawning (initial position),
137// hang from ceiling instead of stand on floor.
138#define MF_SPAWNCEILING (uint_64_t)(0x0000000000000100LL)
139// Don't apply gravity (every tic),
140// that is, object will float, keeping current height
141// or changing it actively.
142#define MF_NOGRAVITY (uint_64_t)(0x0000000000000200LL)
143
144// Movement flags.
145// This allows jumps from high places.
146#define MF_DROPOFF (uint_64_t)(0x0000000000000400LL)
147// For players, will pick up items.
148#define MF_PICKUP (uint_64_t)(0x0000000000000800LL)
149// Player cheat. ???
150#define MF_NOCLIP (uint_64_t)(0x0000000000001000LL)
151// Player: keep info about sliding along walls.
152#define MF_SLIDE (uint_64_t)(0x0000000000002000LL)
153// Allow moves to any height, no gravity.
154// For active floaters, e.g. cacodemons, pain elementals.
155#define MF_FLOAT (uint_64_t)(0x0000000000004000LL)
156// Don't cross lines
157// ??? or look at heights on teleport.
158#define MF_TELEPORT (uint_64_t)(0x0000000000008000LL)
159// Don't hit same species, explode on block.
160// Player missiles as well as fireballs of various kinds.
161#define MF_MISSILE (uint_64_t)(0x0000000000010000LL)
162// Dropped by a demon, not level spawned.
163// E.g. ammo clips dropped by dying former humans.
164#define MF_DROPPED (uint_64_t)(0x0000000000020000LL)
165// Use fuzzy draw (shadow demons or spectres),
166// temporary player invisibility powerup.
167#define MF_SHADOW (uint_64_t)(0x0000000000040000LL)
168// Flag: don't bleed when shot (use puff),
169// barrels and shootable furniture shall not bleed.
170#define MF_NOBLOOD (uint_64_t)(0x0000000000080000LL)
171// Don't stop moving halfway off a step,
172// that is, have dead bodies slide down all the way.
173#define MF_CORPSE (uint_64_t)(0x0000000000100000LL)
174// Floating to a height for a move, ???
175// don't auto float to target's height.
176#define MF_INFLOAT (uint_64_t)(0x0000000000200000LL)
177
178// On kill, count this enemy object
179// towards intermission kill total.
180// Happy gathering.
181#define MF_COUNTKILL (uint_64_t)(0x0000000000400000LL)
182
183// On picking up, count this item object
184// towards intermission item total.
185#define MF_COUNTITEM (uint_64_t)(0x0000000000800000LL)
186
187// Special handling: skull in flight.
188// Neither a cacodemon nor a missile.
189#define MF_SKULLFLY (uint_64_t)(0x0000000001000000LL)
190
191// Don't spawn this object
192// in death match mode (e.g. key cards).
193#define MF_NOTDMATCH (uint_64_t)(0x0000000002000000LL)
194
195// Player sprites in multiplayer modes are modified
196// using an internal color lookup table for re-indexing.
197// If 0x4 0x8 or 0xc,
198// use a translation table for player colormaps
199#define MF_TRANSLATION (uint_64_t)(0x000000000c000000LL)
200#define MF_TRANSLATION1 (uint_64_t)(0x0000000004000000LL)
201#define MF_TRANSLATION2 (uint_64_t)(0x0000000008000000LL)
202// Hmm ???.
203#define MF_TRANSSHIFT 26
204
205// proff 11/19/98: Andy Baker's stealth monsters - unused yet
206//Stealth Mode - Creatures that dissappear and reappear.
207
208#define MF_STEALTH (uint_64_t)(0x0000000010000000LL)
209
210// proff 11/19/98: 3 (4 counting opaque) levels of translucency
211// not very good to set the next one in this enum, should be seperate
212#define MF_TRANSLUCBITS (uint_64_t)(0x0000000060000000LL)
213#define MF_TRANSLUC25 (uint_64_t)(0x0000000020000000LL)
214#define MF_TRANSLUC50 (uint_64_t)(0x0000000040000000LL)
215#define MF_TRANSLUC75 (uint_64_t)(0x0000000060000000LL)
216
217// Translucent sprite? // phares
218#define MF_TRANSLUCENT (uint_64_t)(0x0000000040000000LL)
219
220// these are greater than an int. That's why the flags below are now uint_64_t
221#define MF_TOUCHY (uint_64_t)(0x0000000100000000LL)
222#define MF_BOUNCES (uint_64_t)(0x0000000200000000LL)
223#define MF_FRIEND (uint_64_t)(0x0000000400000000LL)
224
225// killough 9/15/98: Same, but internal flags, not intended for .deh
226// (some degree of opaqueness is good, to avoid compatibility woes)
227
228enum {
229 MIF_FALLING = 1, // Object is falling
230 MIF_ARMED = 2, // Object is armed (for MF_TOUCHY objects)
231};
232
233// Map Object definition.
234//
235// killough 2/20/98:
236//
237// WARNING: Special steps must be taken in p_saveg.c if C pointers are added to
238// this mobj_s struct, or else savegames will crash when loaded. See p_saveg.c.
239// Do not add "struct mobj_s *fooptr" without adding code to p_saveg.c to
240// convert the pointers to ordinals and back for savegames. This was the whole
241// reason behind monsters going to sleep when loading savegames (the "target"
242// pointer was simply nullified after loading, to prevent Doom from crashing),
243// and the whole reason behind loadgames crashing on savegames of AV attacks.
244//
245
246// killough 9/8/98: changed some fields to shorts,
247// for better memory usage (if only for cache).
248
249typedef struct mobj_s
250{
251 // List: thinker links.
252 thinker_t thinker;
253
254 // Info for drawing: position.
255 fixed_t x;
256 fixed_t y;
257 fixed_t z;
258
259 // More list: links in sector (if needed)
260 struct mobj_s* snext;
261 struct mobj_s** sprev; // killough 8/10/98: change to ptr-to-ptr
262
263 //More drawing info: to determine current sprite.
264 angle_t angle; // orientation
265 spritenum_t sprite; // used to find patch_t and flip value
266 int frame; // might be ORed with FF_FULLBRIGHT
267
268 // Interaction info, by BLOCKMAP.
269 // Links in blocks (if needed).
270 struct mobj_s* bnext;
271 struct mobj_s** bprev; // killough 8/11/98: change to ptr-to-ptr
272
273 struct subsector_s* subsector;
274
275 // The closest interval over all contacted Sectors.
276 fixed_t floorz;
277 fixed_t ceilingz;
278
279 // killough 11/98: the lowest floor over all contacted Sectors.
280 fixed_t dropoffz;
281
282 // For movement checking.
283 fixed_t radius;
284 fixed_t height;
285
286 // Momentums, used to update position.
287 fixed_t momx;
288 fixed_t momy;
289 fixed_t momz;
290
291 // If == validcount, already checked.
292 int validcount;
293
294 mobjtype_t type;
295 mobjinfo_t* info; // &mobjinfo[mobj->type]
296
297 int tics; // state tic counter
298 state_t* state;
299 uint_64_t flags;
300 int intflags; // killough 9/15/98: internal flags
301 int health;
302
303 // Movement direction, movement generation (zig-zagging).
304 short movedir; // 0-7
305 short movecount; // when 0, select a new dir
306 short strafecount; // killough 9/8/98: monster strafing
307
308 // Thing being chased/attacked (or NULL),
309 // also the originator for missiles.
310 struct mobj_s* target;
311
312 // Reaction time: if non 0, don't attack yet.
313 // Used by player to freeze a bit after teleporting.
314 short reactiontime;
315
316 // If >0, the current target will be chased no
317 // matter what (even if shot by another object)
318 short threshold;
319
320 // killough 9/9/98: How long a monster pursues a target.
321 short pursuecount;
322
323 short gear; // killough 11/98: used in torque simulation
324
325 // Additional info record for player avatars only.
326 // Only valid if type == MT_PLAYER
327 struct player_s* player;
328
329 // Player number last looked for.
330 short lastlook;
331
332 // For nightmare respawn.
333 mapthing_t spawnpoint;
334
335 // Thing being chased/attacked for tracers.
336 struct mobj_s* tracer;
337
338 //proff 11/22/98: Andy Baker's stealth monsters
339 boolean invisible;
340
341 // new field: last known enemy -- killough 2/15/98
342 struct mobj_s* lastenemy;
343
344 // Are we above a Thing? above_thing points to the Thing // phares
345 // if so, otherwise it's zero. // |
346 // V
347 struct mobj_s* above_thing;
348
349 // Are we below a Thing? below_thing points to the Thing
350 // if so, otherwise it's zero.
351 // ^
352 struct mobj_s* below_thing; // |
353 // phares
354
355 // killough 8/2/98: friction properties part of sectors,
356 // not objects -- removed friction properties from here
357
358 // a linked list of sectors where this object appears
359 struct msecnode_s* touching_sectorlist; // phares 3/14/98
360
361 // SEE WARNING ABOVE ABOUT POINTER FIELDS!!!
362} mobj_t;
363
364// External declarations (fomerly in p_local.h) -- killough 5/2/98
365
366#define VIEWHEIGHT (41*FRACUNIT)
367#define PLAYERRADIUS (16*FRACUNIT)
368
369#define GRAVITY FRACUNIT
370#define MAXMOVE (30*FRACUNIT)
371
372#define ONFLOORZ INT_MIN
373#define ONCEILINGZ INT_MAX
374
375// Time interval for item respawning.
376#define ITEMQUESIZE 128
377
378#define FLOATSPEED (FRACUNIT*4)
379#define STOPSPEED (FRACUNIT/16)
380
381// killough 11/98:
382// For torque simulation:
383
384#define OVERDRIVE 6
385#define MAXGEAR (OVERDRIVE+16)
386
387// killough 11/98:
388// Whether an object is "sentient" or not. Used for environmental influences.
389#define sentient(mobj) ((mobj)->health > 0 && (mobj)->info->seestate)
390
391extern mapthing_t itemrespawnque[];
392extern int itemrespawntime[];
393extern int iquehead;
394extern int iquetail;
395
396void P_RespawnSpecials(void);
397mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type);
398void P_RemoveMobj(mobj_t *th);
399boolean P_SetMobjState(mobj_t *mobj, statenum_t state);
400void P_MobjThinker(mobj_t *mobj);
401void P_SpawnPuff(fixed_t x, fixed_t y, fixed_t z);
402void P_SpawnBlood(fixed_t x, fixed_t y, fixed_t z, int damage);
403mobj_t *P_SpawnMissile(mobj_t *source, mobj_t *dest, mobjtype_t type);
404void P_SpawnPlayerMissile(mobj_t *source, mobjtype_t type);
405void P_SpawnMapThing (mapthing_t* mthing);
406void P_CheckMissileSpawn(mobj_t*); // killough 8/2/98
407void P_ExplodeMissile(mobj_t*); // killough
408#endif
409
diff --git a/apps/plugins/doom/p_plats.c b/apps/plugins/doom/p_plats.c
new file mode 100644
index 0000000000..4a5c28bb88
--- /dev/null
+++ b/apps/plugins/doom/p_plats.c
@@ -0,0 +1,434 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION:
28 * Plats (i.e. elevator platforms) code, raising/lowering.
29 *
30 *-----------------------------------------------------------------------------*/
31
32#include "doomstat.h"
33#include "m_random.h"
34#include "r_main.h"
35#include "p_spec.h"
36#include "p_tick.h"
37#include "s_sound.h"
38#include "sounds.h"
39#include "rockmacros.h"
40platlist_t *activeplats; // killough 2/14/98: made global again
41
42//
43// T_PlatRaise()
44//
45// Action routine to move a plat up and down
46//
47// Passed a plat structure containing all pertinent information about the move
48// No return
49//
50// jff 02/08/98 all cases with labels beginning with gen added to support
51// generalized line type behaviors.
52
53void T_PlatRaise(plat_t* plat)
54{
55 result_e res;
56
57 // handle plat moving, up, down, waiting, or in stasis,
58 switch(plat->status)
59 {
60 case up: // plat moving up
61 res = T_MovePlane(plat->sector,plat->speed,plat->high,plat->crush,0,1);
62
63 // if a pure raise type, make the plat moving sound
64 if (plat->type == raiseAndChange
65 || plat->type == raiseToNearestAndChange)
66 {
67 if (!(leveltime&7))
68 S_StartSound((mobj_t *)&plat->sector->soundorg, sfx_stnmov);
69 }
70
71 // if encountered an obstacle, and not a crush type, reverse direction
72 if (res == crushed && (!plat->crush))
73 {
74 plat->count = plat->wait;
75 plat->status = down;
76 S_StartSound((mobj_t *)&plat->sector->soundorg, sfx_pstart);
77 }
78 else // else handle reaching end of up stroke
79 {
80 if (res == pastdest) // end of stroke
81 {
82 // if not an instant toggle type, wait, make plat stop sound
83 if (plat->type!=toggleUpDn)
84 {
85 plat->count = plat->wait;
86 plat->status = waiting;
87 S_StartSound((mobj_t *)&plat->sector->soundorg, sfx_pstop);
88 }
89 else // else go into stasis awaiting next toggle activation
90 {
91 plat->oldstatus = plat->status;//jff 3/14/98 after action wait
92 plat->status = in_stasis; //for reactivation of toggle
93 }
94
95 // lift types and pure raise types are done at end of up stroke
96 // only the perpetual type waits then goes back up
97 switch(plat->type)
98 {
99 case blazeDWUS:
100 case downWaitUpStay:
101 case raiseAndChange:
102 case raiseToNearestAndChange:
103 case genLift:
104 P_RemoveActivePlat(plat); // killough
105 default:
106 break;
107 }
108 }
109 }
110 break;
111
112 case down: // plat moving down
113 res = T_MovePlane(plat->sector,plat->speed,plat->low,false,0,-1);
114
115 // handle reaching end of down stroke
116 if (res == pastdest)
117 {
118 // if not an instant toggle, start waiting, make plat stop sound
119 if (plat->type!=toggleUpDn) //jff 3/14/98 toggle up down
120 { // is silent, instant, no waiting
121 plat->count = plat->wait;
122 plat->status = waiting;
123 S_StartSound((mobj_t *)&plat->sector->soundorg,sfx_pstop);
124 }
125 else // instant toggles go into stasis awaiting next activation
126 {
127 plat->oldstatus = plat->status;//jff 3/14/98 after action wait
128 plat->status = in_stasis; //for reactivation of toggle
129 }
130
131 //jff 1/26/98 remove the plat if it bounced so it can be tried again
132 //only affects plats that raise and bounce
133 //killough 1/31/98: relax compatibility to demo_compatibility
134
135 // remove the plat if its a pure raise type
136 if (!comp[comp_floors])
137 {
138 switch(plat->type)
139 {
140 case raiseAndChange:
141 case raiseToNearestAndChange:
142 P_RemoveActivePlat(plat);
143 default:
144 break;
145 }
146 }
147 }
148 break;
149
150 case waiting: // plat is waiting
151 if (!--plat->count) // downcount and check for delay elapsed
152 {
153 if (plat->sector->floorheight == plat->low)
154 plat->status = up; // if at bottom, start up
155 else
156 plat->status = down; // if at top, start down
157
158 // make plat start sound
159 S_StartSound((mobj_t *)&plat->sector->soundorg,sfx_pstart);
160 }
161 break; //jff 1/27/98 don't pickup code added later to in_stasis
162
163 case in_stasis: // do nothing if in stasis
164 break;
165 }
166}
167
168
169//
170// EV_DoPlat
171//
172// Handle Plat linedef types
173//
174// Passed the linedef that activated the plat, the type of plat action,
175// and for some plat types, an amount to raise
176// Returns true if a thinker is started, or restarted from stasis
177//
178int EV_DoPlat
179( line_t* line,
180 plattype_e type,
181 int amount )
182{
183 plat_t* plat;
184 int secnum;
185 int rtn;
186 sector_t* sec;
187
188 secnum = -1;
189 rtn = 0;
190
191
192 // Activate all <type> plats that are in_stasis
193 switch(type)
194 {
195 case perpetualRaise:
196 P_ActivateInStasis(line->tag);
197 break;
198
199 case toggleUpDn:
200 P_ActivateInStasis(line->tag);
201 rtn=1;
202 break;
203
204 default:
205 break;
206 }
207
208 // act on all sectors tagged the same as the activating linedef
209 while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0)
210 {
211 sec = &sectors[secnum];
212
213 // don't start a second floor function if already moving
214 if (P_SectorActive(floor_special,sec)) //jff 2/23/98 multiple thinkers
215 continue;
216
217 // Create a thinker
218 rtn = 1;
219 plat = Z_Malloc( sizeof(*plat), PU_LEVSPEC, 0);
220 P_AddThinker(&plat->thinker);
221
222 plat->type = type;
223 plat->sector = sec;
224 plat->sector->floordata = plat; //jff 2/23/98 multiple thinkers
225 plat->thinker.function = T_PlatRaise;
226 plat->crush = false;
227 plat->tag = line->tag;
228
229 //jff 1/26/98 Avoid raise plat bouncing a head off a ceiling and then
230 //going down forever -- default low to plat height when triggered
231 plat->low = sec->floorheight;
232
233 // set up plat according to type
234 switch(type)
235 {
236 case raiseToNearestAndChange:
237 plat->speed = PLATSPEED/2;
238 sec->floorpic = sides[line->sidenum[0]].sector->floorpic;
239 plat->high = P_FindNextHighestFloor(sec,sec->floorheight);
240 plat->wait = 0;
241 plat->status = up;
242 sec->special = 0;
243 //jff 3/14/98 clear old field as well
244 sec->oldspecial = 0;
245
246 S_StartSound((mobj_t *)&sec->soundorg,sfx_stnmov);
247 break;
248
249 case raiseAndChange:
250 plat->speed = PLATSPEED/2;
251 sec->floorpic = sides[line->sidenum[0]].sector->floorpic;
252 plat->high = sec->floorheight + amount*FRACUNIT;
253 plat->wait = 0;
254 plat->status = up;
255
256 S_StartSound((mobj_t *)&sec->soundorg,sfx_stnmov);
257 break;
258
259 case downWaitUpStay:
260 plat->speed = PLATSPEED * 4;
261 plat->low = P_FindLowestFloorSurrounding(sec);
262
263 if (plat->low > sec->floorheight)
264 plat->low = sec->floorheight;
265
266 plat->high = sec->floorheight;
267 plat->wait = 35*PLATWAIT;
268 plat->status = down;
269 S_StartSound((mobj_t *)&sec->soundorg,sfx_pstart);
270 break;
271
272 case blazeDWUS:
273 plat->speed = PLATSPEED * 8;
274 plat->low = P_FindLowestFloorSurrounding(sec);
275
276 if (plat->low > sec->floorheight)
277 plat->low = sec->floorheight;
278
279 plat->high = sec->floorheight;
280 plat->wait = 35*PLATWAIT;
281 plat->status = down;
282 S_StartSound((mobj_t *)&sec->soundorg,sfx_pstart);
283 break;
284
285 case perpetualRaise:
286 plat->speed = PLATSPEED;
287 plat->low = P_FindLowestFloorSurrounding(sec);
288
289 if (plat->low > sec->floorheight)
290 plat->low = sec->floorheight;
291
292 plat->high = P_FindHighestFloorSurrounding(sec);
293
294 if (plat->high < sec->floorheight)
295 plat->high = sec->floorheight;
296
297 plat->wait = 35*PLATWAIT;
298 plat->status = P_Random(pr_plats)&1;
299
300 S_StartSound((mobj_t *)&sec->soundorg,sfx_pstart);
301 break;
302
303 case toggleUpDn: //jff 3/14/98 add new type to support instant toggle
304 plat->speed = PLATSPEED; //not used
305 plat->wait = 35*PLATWAIT; //not used
306 plat->crush = true; //jff 3/14/98 crush anything in the way
307
308 // set up toggling between ceiling, floor inclusive
309 plat->low = sec->ceilingheight;
310 plat->high = sec->floorheight;
311 plat->status = down;
312 break;
313
314 default:
315 break;
316 }
317 P_AddActivePlat(plat); // add plat to list of active plats
318 }
319 return rtn;
320}
321
322// The following were all rewritten by Lee Killough
323// to use the new structure which places no limits
324// on active plats. It also avoids spending as much
325// time searching for active plats. Previously a
326// fixed-size array was used, with NULL indicating
327// empty entries, while now a doubly-linked list
328// is used.
329
330//
331// P_ActivateInStasis()
332//
333// Activate a plat that has been put in stasis
334// (stopped perpetual floor, instant floor/ceil toggle)
335//
336// Passed the tag of the plat that should be reactivated
337// Returns nothing
338//
339void P_ActivateInStasis(int tag)
340{
341 platlist_t *pl;
342 for (pl=activeplats; pl; pl=pl->next) // search the active plats
343 {
344 plat_t *plat = pl->plat; // for one in stasis with right tag
345 if (plat->tag == tag && plat->status == in_stasis)
346 {
347 if (plat->type==toggleUpDn) //jff 3/14/98 reactivate toggle type
348 plat->status = plat->oldstatus==up? down : up;
349 else
350 plat->status = plat->oldstatus;
351 plat->thinker.function = T_PlatRaise;
352 }
353 }
354}
355
356//
357// EV_StopPlat()
358//
359// Handler for "stop perpetual floor" linedef type
360//
361// Passed the linedef that stopped the plat
362// Returns true if a plat was put in stasis
363//
364// jff 2/12/98 added int return value, fixed return
365//
366int EV_StopPlat(line_t* line)
367{
368 platlist_t *pl;
369 for (pl=activeplats; pl; pl=pl->next) // search the active plats
370 {
371 plat_t *plat = pl->plat; // for one with the tag not in stasis
372 if (plat->status != in_stasis && plat->tag == line->tag)
373 {
374 plat->oldstatus = plat->status; // put it in stasis
375 plat->status = in_stasis;
376 plat->thinker.function = NULL;
377 }
378 }
379 return 1;
380}
381
382//
383// P_AddActivePlat()
384//
385// Add a plat to the head of the active plat list
386//
387// Passed a pointer to the plat to add
388// Returns nothing
389//
390void P_AddActivePlat(plat_t* plat)
391{
392 platlist_t *list = malloc(sizeof *list);
393 list->plat = plat;
394 plat->list = list;
395 if ((list->next = activeplats))
396 list->next->prev = &list->next;
397 list->prev = &activeplats;
398 activeplats = list;
399}
400
401//
402// P_RemoveActivePlat()
403//
404// Remove a plat from the active plat list
405//
406// Passed a pointer to the plat to remove
407// Returns nothing
408//
409void P_RemoveActivePlat(plat_t* plat)
410{
411 platlist_t *list = plat->list;
412 plat->sector->floordata = NULL; //jff 2/23/98 multiple thinkers
413 P_RemoveThinker(&plat->thinker);
414 if ((*list->prev = list->next))
415 list->next->prev = list->prev;
416 free(list);
417}
418
419//
420// P_RemoveAllActivePlats()
421//
422// Remove all plats from the active plat list
423//
424// Passed nothing, returns nothing
425//
426void P_RemoveAllActivePlats(void)
427{
428 while (activeplats)
429 {
430 platlist_t *next = activeplats->next;
431 free(activeplats);
432 activeplats = next;
433 }
434}
diff --git a/apps/plugins/doom/p_pspr.c b/apps/plugins/doom/p_pspr.c
new file mode 100644
index 0000000000..9ef9e73978
--- /dev/null
+++ b/apps/plugins/doom/p_pspr.c
@@ -0,0 +1,853 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION:
28 * Weapon sprite animation, weapon objects.
29 * Action functions for weapons.
30 *
31 *-----------------------------------------------------------------------------*/
32
33#include "doomstat.h"
34#include "r_main.h"
35#include "p_map.h"
36#include "p_inter.h"
37#include "p_pspr.h"
38#include "p_enemy.h"
39#include "m_random.h"
40#include "s_sound.h"
41#include "sounds.h"
42#include "d_event.h"
43#include "rockmacros.h"
44#define LOWERSPEED (FRACUNIT*6)
45#define RAISESPEED (FRACUNIT*6)
46#define WEAPONBOTTOM (FRACUNIT*128)
47#define WEAPONTOP (FRACUNIT*32)
48
49// plasma cells for a bfg attack
50#define BFGCELLS 40
51//#define BFGCELLS bfgcells /* Ty 03/09/98 externalized in p_inter.c */
52
53extern void P_Thrust(player_t *, angle_t, fixed_t);
54
55// The following array holds the recoil values // phares
56
57static const int recoil_values[] = { // phares
58 10, // wp_fist
59 10, // wp_pistol
60 30, // wp_shotgun
61 10, // wp_chaingun
62 100,// wp_missile
63 20, // wp_plasma
64 100,// wp_bfg
65 0, // wp_chainsaw
66 80 // wp_supershotgun
67 };
68
69//
70// P_SetPsprite
71//
72
73static void P_SetPsprite(player_t *player, int position, statenum_t stnum)
74{
75 pspdef_t *psp = &player->psprites[position];
76
77 do
78 {
79 state_t *state;
80
81 if (!stnum)
82 {
83 // object removed itself
84 psp->state = NULL;
85 break;
86 }
87
88 state = &states[stnum];
89 psp->state = state;
90 psp->tics = state->tics; // could be 0
91
92 if (state->misc1)
93 {
94 // coordinate set
95 psp->sx = state->misc1 << FRACBITS;
96 psp->sy = state->misc2 << FRACBITS;
97 }
98
99 // Call action routine.
100 // Modified handling.
101 if (state->action)
102 {
103 state->action(player, psp);
104 if (!psp->state)
105 break;
106 }
107 stnum = psp->state->nextstate;
108 }
109 while (!psp->tics); // an initial state of 0 could cycle through
110}
111
112//
113// P_BringUpWeapon
114// Starts bringing the pending weapon up
115// from the bottom of the screen.
116// Uses player
117//
118
119static void P_BringUpWeapon(player_t *player)
120{
121 statenum_t newstate;
122
123 if (player->pendingweapon == wp_nochange)
124 player->pendingweapon = player->readyweapon;
125
126 if (player->pendingweapon == wp_chainsaw)
127 S_StartSound (player->mo, sfx_sawup);
128
129 newstate = weaponinfo[player->pendingweapon].upstate;
130
131 player->pendingweapon = wp_nochange;
132 // killough 12/98: prevent pistol from starting visibly at bottom of screen:
133 player->psprites[ps_weapon].sy =
134 mbf_features ? WEAPONBOTTOM+FRACUNIT*2 : WEAPONBOTTOM;
135
136 P_SetPsprite(player, ps_weapon, newstate);
137}
138
139// The first set is where the weapon preferences from // killough,
140// default.cfg are stored. These values represent the keys used // phares
141// in DOOM2 to bring up the weapon, i.e. 6 = plasma gun. These // |
142// are NOT the wp_* constants. // V
143
144int weapon_preferences[2][NUMWEAPONS+1] = {
145 {6, 9, 4, 3, 2, 8, 5, 7, 1, 0}, // !compatibility preferences
146 {6, 9, 4, 3, 2, 8, 5, 7, 1, 0}, // compatibility preferences
147 };
148
149// P_SwitchWeapon checks current ammo levels and gives you the
150// most preferred weapon with ammo. It will not pick the currently
151// raised weapon. When called from P_CheckAmmo this won't matter,
152// because the raised weapon has no ammo anyway. When called from
153// G_BuildTiccmd you want to toggle to a different weapon regardless.
154
155int P_SwitchWeapon(player_t *player)
156{
157 int *prefer = weapon_preferences[demo_compatibility!=0]; // killough 3/22/98
158 int currentweapon = player->readyweapon;
159 int newweapon = currentweapon;
160 int i = NUMWEAPONS+1; // killough 5/2/98
161
162 // killough 2/8/98: follow preferences and fix BFG/SSG bugs
163
164 do
165 switch (*prefer++)
166 {
167 case 1:
168 if (!player->powers[pw_strength]) // allow chainsaw override
169 break;
170 case 0:
171 newweapon = wp_fist;
172 break;
173 case 2:
174 if (player->ammo[am_clip])
175 newweapon = wp_pistol;
176 break;
177 case 3:
178 if (player->weaponowned[wp_shotgun] && player->ammo[am_shell])
179 newweapon = wp_shotgun;
180 break;
181 case 4:
182 if (player->weaponowned[wp_chaingun] && player->ammo[am_clip])
183 newweapon = wp_chaingun;
184 break;
185 case 5:
186 if (player->weaponowned[wp_missile] && player->ammo[am_misl])
187 newweapon = wp_missile;
188 break;
189 case 6:
190 if (player->weaponowned[wp_plasma] && player->ammo[am_cell] &&
191 gamemode != shareware)
192 newweapon = wp_plasma;
193 break;
194 case 7:
195 if (player->weaponowned[wp_bfg] && gamemode != shareware &&
196 player->ammo[am_cell] >= (demo_compatibility ? 41 : 40))
197 newweapon = wp_bfg;
198 break;
199 case 8:
200 if (player->weaponowned[wp_chainsaw])
201 newweapon = wp_chainsaw;
202 break;
203 case 9:
204 if (player->weaponowned[wp_supershotgun] && gamemode == commercial &&
205 player->ammo[am_shell] >= (demo_compatibility ? 3 : 2))
206 newweapon = wp_supershotgun;
207 break;
208 }
209 while (newweapon==currentweapon && --i); // killough 5/2/98
210 return newweapon;
211}
212
213// killough 5/2/98: whether consoleplayer prefers weapon w1 over weapon w2.
214int P_WeaponPreferred(int w1, int w2)
215{
216 return
217 (weapon_preferences[0][0] != ++w2 && (weapon_preferences[0][0] == ++w1 ||
218 (weapon_preferences[0][1] != w2 && (weapon_preferences[0][1] == w1 ||
219 (weapon_preferences[0][2] != w2 && (weapon_preferences[0][2] == w1 ||
220 (weapon_preferences[0][3] != w2 && (weapon_preferences[0][3] == w1 ||
221 (weapon_preferences[0][4] != w2 && (weapon_preferences[0][4] == w1 ||
222 (weapon_preferences[0][5] != w2 && (weapon_preferences[0][5] == w1 ||
223 (weapon_preferences[0][6] != w2 && (weapon_preferences[0][6] == w1 ||
224 (weapon_preferences[0][7] != w2 && (weapon_preferences[0][7] == w1
225 ))))))))))))))));
226}
227
228//
229// P_CheckAmmo
230// Returns true if there is enough ammo to shoot.
231// If not, selects the next weapon to use.
232// (only in demo_compatibility mode -- killough 3/22/98)
233//
234
235boolean P_CheckAmmo(player_t *player)
236{
237 ammotype_t ammo = weaponinfo[player->readyweapon].ammo;
238 int count = 1; // Regular
239
240 if (player->readyweapon == wp_bfg) // Minimal amount for one shot varies.
241 count = BFGCELLS;
242 else
243 if (player->readyweapon == wp_supershotgun) // Double barrel.
244 count = 2;
245
246 // Some do not need ammunition anyway.
247 // Return if current ammunition sufficient.
248
249 if (ammo == am_noammo || player->ammo[ammo] >= count)
250 return true;
251
252 // Out of ammo, pick a weapon to change to.
253 //
254 // killough 3/22/98: for old demos we do the switch here and now;
255 // for Boom games we cannot do this, and have different player
256 // preferences across demos or networks, so we have to use the
257 // G_BuildTiccmd() interface instead of making the switch here.
258
259 if (demo_compatibility)
260 {
261 player->pendingweapon = P_SwitchWeapon(player); // phares
262 // Now set appropriate weapon overlay.
263 P_SetPsprite(player,ps_weapon,weaponinfo[player->readyweapon].downstate);
264 }
265
266 return false;
267}
268
269//
270// P_FireWeapon.
271//
272
273int lastshottic; // killough 3/22/98
274
275static void P_FireWeapon(player_t *player)
276{
277 statenum_t newstate;
278
279 if (!P_CheckAmmo(player))
280 return;
281
282 P_SetMobjState(player->mo, S_PLAY_ATK1);
283 newstate = weaponinfo[player->readyweapon].atkstate;
284 P_SetPsprite(player, ps_weapon, newstate);
285 P_NoiseAlert(player->mo, player->mo);
286 lastshottic = gametic; // killough 3/22/98
287}
288
289//
290// P_DropWeapon
291// Player died, so put the weapon away.
292//
293
294void P_DropWeapon(player_t *player)
295{
296 P_SetPsprite(player, ps_weapon, weaponinfo[player->readyweapon].downstate);
297}
298
299//
300// A_WeaponReady
301// The player can fire the weapon
302// or change to another weapon at this time.
303// Follows after getting weapon up,
304// or after previous attack/fire sequence.
305//
306
307void A_WeaponReady(player_t *player, pspdef_t *psp)
308{
309 // get out of attack state
310 if (player->mo->state == &states[S_PLAY_ATK1]
311 || player->mo->state == &states[S_PLAY_ATK2] )
312 P_SetMobjState(player->mo, S_PLAY);
313
314 if (player->readyweapon == wp_chainsaw && psp->state == &states[S_SAW])
315 S_StartSound(player->mo, sfx_sawidl);
316
317 // check for change
318 // if player is dead, put the weapon away
319
320 if (player->pendingweapon != wp_nochange || !player->health)
321 {
322 // change weapon (pending weapon should already be validated)
323 statenum_t newstate = weaponinfo[player->readyweapon].downstate;
324 P_SetPsprite(player, ps_weapon, newstate);
325 return;
326 }
327
328 // check for fire
329 // the missile launcher and bfg do not auto fire
330
331 if (player->cmd.buttons & BT_ATTACK)
332 {
333 if (!player->attackdown || (player->readyweapon != wp_missile &&
334 player->readyweapon != wp_bfg))
335 {
336 player->attackdown = true;
337 P_FireWeapon(player);
338 return;
339 }
340 }
341 else
342 player->attackdown = false;
343
344 // bob the weapon based on movement speed
345 {
346 int angle = (128*leveltime) & FINEMASK;
347 psp->sx = FRACUNIT + FixedMul(player->bob, finecosine[angle]);
348 angle &= FINEANGLES/2-1;
349 psp->sy = WEAPONTOP + FixedMul(player->bob, finesine[angle]);
350 }
351}
352
353//
354// A_ReFire
355// The player can re-fire the weapon
356// without lowering it entirely.
357//
358
359void A_ReFire(player_t *player, pspdef_t *psp)
360{
361 (void)psp;
362 // check for fire
363 // (if a weaponchange is pending, let it go through instead)
364
365 if ( (player->cmd.buttons & BT_ATTACK)
366 && player->pendingweapon == wp_nochange && player->health)
367 {
368 player->refire++;
369 P_FireWeapon(player);
370 }
371 else
372 {
373 player->refire = 0;
374 P_CheckAmmo(player);
375 }
376}
377
378void A_CheckReload(player_t *player, pspdef_t *psp)
379{
380 (void)psp;
381 P_CheckAmmo(player);
382}
383
384//
385// A_Lower
386// Lowers current weapon,
387// and changes weapon at bottom.
388//
389
390void A_Lower(player_t *player, pspdef_t *psp)
391{
392 psp->sy += LOWERSPEED;
393
394 // Is already down.
395 if (psp->sy < WEAPONBOTTOM)
396 return;
397
398 // Player is dead.
399 if (player->playerstate == PST_DEAD)
400 {
401 psp->sy = WEAPONBOTTOM;
402 return; // don't bring weapon back up
403 }
404
405 // The old weapon has been lowered off the screen,
406 // so change the weapon and start raising it
407
408 if (!player->health)
409 { // Player is dead, so keep the weapon off screen.
410 P_SetPsprite(player, ps_weapon, S_NULL);
411 return;
412 }
413
414 player->readyweapon = player->pendingweapon;
415
416 P_BringUpWeapon(player);
417}
418
419//
420// A_Raise
421//
422
423void A_Raise(player_t *player, pspdef_t *psp)
424{
425 statenum_t newstate;
426
427 psp->sy -= RAISESPEED;
428
429 if (psp->sy > WEAPONTOP)
430 return;
431
432 psp->sy = WEAPONTOP;
433
434 // The weapon has been raised all the way,
435 // so change to the ready state.
436
437 newstate = weaponinfo[player->readyweapon].readystate;
438
439 P_SetPsprite(player, ps_weapon, newstate);
440}
441
442
443// Weapons now recoil, amount depending on the weapon. // phares
444// // |
445// The P_SetPsprite call in each of the weapon firing routines // V
446// was moved here so the recoil could be synched with the
447// muzzle flash, rather than the pressing of the trigger.
448// The BFG delay caused this to be necessary.
449
450static void A_FireSomething(player_t* player,int adder)
451{
452 P_SetPsprite(player, ps_flash,
453 weaponinfo[player->readyweapon].flashstate+adder);
454
455 // killough 3/27/98: prevent recoil in no-clipping mode
456 if (!(player->mo->flags & MF_NOCLIP))
457 if (!compatibility && weapon_recoil)
458 P_Thrust(player,
459 ANG180+player->mo->angle, // ^
460 2048*recoil_values[player->readyweapon]); // |
461} // phares
462
463//
464// A_GunFlash
465//
466
467void A_GunFlash(player_t *player, pspdef_t *psp)
468{
469 (void)psp;
470 P_SetMobjState(player->mo, S_PLAY_ATK2);
471
472 A_FireSomething(player,0); // phares
473}
474
475//
476// WEAPON ATTACKS
477//
478
479//
480// A_Punch
481//
482
483void A_Punch(player_t *player, pspdef_t *psp)
484{
485 (void)psp;
486 angle_t angle;
487 int t, slope, damage = (P_Random(pr_punch)%10+1)<<1;
488
489 if (player->powers[pw_strength])
490 damage *= 10;
491
492 angle = player->mo->angle;
493
494 // killough 5/5/98: remove dependence on order of evaluation:
495 t = P_Random(pr_punchangle);
496 angle += (t - P_Random(pr_punchangle))<<18;
497
498 /* killough 8/2/98: make autoaiming prefer enemies */
499 if (!mbf_features ||
500 (slope = P_AimLineAttack(player->mo, angle, MELEERANGE, MF_FRIEND),
501 !linetarget))
502 slope = P_AimLineAttack(player->mo, angle, MELEERANGE, 0);
503
504 P_LineAttack(player->mo, angle, MELEERANGE, slope, damage);
505
506 if (!linetarget)
507 return;
508
509 S_StartSound(player->mo, sfx_punch);
510
511 // turn to face target
512
513 player->mo->angle = R_PointToAngle2(player->mo->x, player->mo->y,
514 linetarget->x, linetarget->y);
515}
516
517//
518// A_Saw
519//
520
521void A_Saw(player_t *player, pspdef_t *psp)
522{
523 (void)psp;
524 int slope, damage = 2*(P_Random(pr_saw)%10+1);
525 angle_t angle = player->mo->angle;
526 // killough 5/5/98: remove dependence on order of evaluation:
527 int t = P_Random(pr_saw);
528 angle += (t - P_Random(pr_saw))<<18;
529
530 /* Use meleerange + 1 so that the puff doesn't skip the flash
531 * killough 8/2/98: make autoaiming prefer enemies */
532 if (!mbf_features ||
533 (slope = P_AimLineAttack(player->mo, angle, MELEERANGE+1, MF_FRIEND),
534 !linetarget))
535 slope = P_AimLineAttack(player->mo, angle, MELEERANGE+1, 0);
536
537 P_LineAttack(player->mo, angle, MELEERANGE+1, slope, damage);
538
539 if (!linetarget)
540 {
541 S_StartSound(player->mo, sfx_sawful);
542 return;
543 }
544
545 S_StartSound(player->mo, sfx_sawhit);
546
547 // turn to face target
548 angle = R_PointToAngle2(player->mo->x, player->mo->y,
549 linetarget->x, linetarget->y);
550
551 if (angle - player->mo->angle > ANG180) {
552 if (angle - player->mo->angle < (unsigned)(-ANG90/20))
553 player->mo->angle = angle + ANG90/21;
554 else
555 player->mo->angle -= ANG90/20;
556 } else {
557 if (angle - player->mo->angle > ANG90/20)
558 player->mo->angle = angle - ANG90/21;
559 else
560 player->mo->angle += ANG90/20;
561 }
562
563 player->mo->flags |= MF_JUSTATTACKED;
564}
565
566//
567// A_FireMissile
568//
569
570void A_FireMissile(player_t *player, pspdef_t *psp)
571{
572 (void)psp;
573 player->ammo[weaponinfo[player->readyweapon].ammo]--;
574 P_SpawnPlayerMissile(player->mo, MT_ROCKET);
575}
576
577//
578// A_FireBFG
579//
580
581void A_FireBFG(player_t *player, pspdef_t *psp)
582{
583 (void)psp;
584 player->ammo[weaponinfo[player->readyweapon].ammo] -= BFGCELLS;
585 P_SpawnPlayerMissile(player->mo, MT_BFG);
586}
587
588/*
589 * A_FireOldBFG
590 *
591 * This function emulates Doom's Pre-Beta BFG
592 * By Lee Killough 6/6/98, 7/11/98, 7/19/98, 8/20/98
593 *
594 * This code may not be used in other mods without appropriate credit given.
595 * Code leeches will be telefragged.
596 */
597
598void A_FireOldBFG(player_t *player, pspdef_t *psp)
599{
600 (void)psp;
601 (void)player;
602}
603
604//
605// A_FirePlasma
606//
607
608void A_FirePlasma(player_t *player, pspdef_t *psp)
609{
610 (void)psp;
611 player->ammo[weaponinfo[player->readyweapon].ammo]--;
612
613 A_FireSomething(player,P_Random(pr_plasma)&1); // phares
614 P_SpawnPlayerMissile(player->mo, MT_PLASMA);
615}
616
617//
618// P_BulletSlope
619// Sets a slope so a near miss is at aproximately
620// the height of the intended target
621//
622
623static fixed_t bulletslope;
624
625static void P_BulletSlope(mobj_t *mo)
626{
627 angle_t an = mo->angle; // see which target is to be aimed at
628
629 /* killough 8/2/98: make autoaiming prefer enemies */
630 uint_64_t mask = mbf_features ? MF_FRIEND : 0;
631
632 do
633 {
634 bulletslope = P_AimLineAttack(mo, an, 16*64*FRACUNIT, mask);
635 if (!linetarget)
636 bulletslope = P_AimLineAttack(mo, an += 1<<26, 16*64*FRACUNIT, mask);
637 if (!linetarget)
638 bulletslope = P_AimLineAttack(mo, an -= 2<<26, 16*64*FRACUNIT, mask);
639 }
640 while (mask && (mask=0, !linetarget)); /* killough 8/2/98 */
641}
642
643//
644// P_GunShot
645//
646
647void P_GunShot(mobj_t *mo, boolean accurate)
648{
649 int damage = 5*(P_Random(pr_gunshot)%3+1);
650 angle_t angle = mo->angle;
651
652 if (!accurate)
653 { // killough 5/5/98: remove dependence on order of evaluation:
654 int t = P_Random(pr_misfire);
655 angle += (t - P_Random(pr_misfire))<<18;
656 }
657
658 P_LineAttack(mo, angle, MISSILERANGE, bulletslope, damage);
659}
660
661//
662// A_FirePistol
663//
664
665void A_FirePistol(player_t *player, pspdef_t *psp)
666{
667 (void)psp;
668 S_StartSound(player->mo, sfx_pistol);
669
670 P_SetMobjState(player->mo, S_PLAY_ATK2);
671 player->ammo[weaponinfo[player->readyweapon].ammo]--;
672
673 A_FireSomething(player,0); // phares
674 P_BulletSlope(player->mo);
675 P_GunShot(player->mo, !player->refire);
676}
677
678//
679// A_FireShotgun
680//
681
682void A_FireShotgun(player_t *player, pspdef_t *psp)
683{
684 (void)psp;
685 int i;
686
687 S_StartSound(player->mo, sfx_shotgn);
688 P_SetMobjState(player->mo, S_PLAY_ATK2);
689
690 player->ammo[weaponinfo[player->readyweapon].ammo]--;
691
692 A_FireSomething(player,0); // phares
693
694 P_BulletSlope(player->mo);
695
696 for (i=0; i<7; i++)
697 P_GunShot(player->mo, false);
698}
699
700//
701// A_FireShotgun2
702//
703
704void A_FireShotgun2(player_t *player, pspdef_t *psp)
705{
706 (void)psp;
707 int i;
708
709 S_StartSound(player->mo, sfx_dshtgn);
710 P_SetMobjState(player->mo, S_PLAY_ATK2);
711 player->ammo[weaponinfo[player->readyweapon].ammo] -= 2;
712
713 A_FireSomething(player,0); // phares
714
715 P_BulletSlope(player->mo);
716
717 for (i=0; i<20; i++)
718 {
719 int damage = 5*(P_Random(pr_shotgun)%3+1);
720 angle_t angle = player->mo->angle;
721 // killough 5/5/98: remove dependence on order of evaluation:
722 int t = P_Random(pr_shotgun);
723 angle += (t - P_Random(pr_shotgun))<<19;
724 t = P_Random(pr_shotgun);
725 P_LineAttack(player->mo, angle, MISSILERANGE, bulletslope +
726 ((t - P_Random(pr_shotgun))<<5), damage);
727 }
728}
729
730//
731// A_FireCGun
732//
733
734void A_FireCGun(player_t *player, pspdef_t *psp)
735{
736 if (player->ammo[weaponinfo[player->readyweapon].ammo] || comp[comp_sound])
737 S_StartSound(player->mo, sfx_pistol);
738
739 if (!player->ammo[weaponinfo[player->readyweapon].ammo])
740 return;
741
742 P_SetMobjState(player->mo, S_PLAY_ATK2);
743 player->ammo[weaponinfo[player->readyweapon].ammo]--;
744
745 A_FireSomething(player,psp->state - &states[S_CHAIN1]); // phares
746
747 P_BulletSlope(player->mo);
748
749 P_GunShot(player->mo, !player->refire);
750}
751
752void A_Light0(player_t *player, pspdef_t *psp)
753{
754 (void)psp;
755 player->extralight = 0;
756}
757
758void A_Light1 (player_t *player, pspdef_t *psp)
759{
760 (void)psp;
761 player->extralight = 1;
762}
763
764void A_Light2 (player_t *player, pspdef_t *psp)
765{
766 (void)psp;
767 player->extralight = 2;
768}
769
770//
771// A_BFGSpray
772// Spawn a BFG explosion on every monster in view
773//
774
775void A_BFGSpray(mobj_t *mo)
776{
777 int i;
778
779 for (i=0 ; i<40 ; i++) // offset angles from its attack angle
780 {
781 int j, damage;
782 angle_t an = mo->angle - ANG90/2 + ANG90/40*i;
783
784 // mo->target is the originator (player) of the missile
785
786 // killough 8/2/98: make autoaiming prefer enemies
787 if (!mbf_features ||
788 (P_AimLineAttack(mo->target, an, 16*64*FRACUNIT, MF_FRIEND),
789 !linetarget))
790 P_AimLineAttack(mo->target, an, 16*64*FRACUNIT, 0);
791
792 if (!linetarget)
793 continue;
794
795 P_SpawnMobj(linetarget->x, linetarget->y,
796 linetarget->z + (linetarget->height>>2), MT_EXTRABFG);
797
798 for (damage=j=0; j<15; j++)
799 damage += (P_Random(pr_bfg)&7) + 1;
800
801 P_DamageMobj(linetarget, mo->target, mo->target, damage);
802 }
803}
804
805//
806// A_BFGsound
807//
808
809void A_BFGsound(player_t *player, pspdef_t *psp)
810{
811 (void)psp;
812 S_StartSound(player->mo, sfx_bfg);
813}
814
815//
816// P_SetupPsprites
817// Called at start of level for each player.
818//
819
820void P_SetupPsprites(player_t *player)
821{
822 int i;
823
824 // remove all psprites
825 for (i=0; i<NUMPSPRITES; i++)
826 player->psprites[i].state = NULL;
827
828 // spawn the gun
829 player->pendingweapon = player->readyweapon;
830 P_BringUpWeapon(player);
831}
832
833//
834// P_MovePsprites
835// Called every tic by player thinking routine.
836//
837
838void P_MovePsprites(player_t *player)
839{
840 pspdef_t *psp = player->psprites;
841 int i;
842
843 // a null state means not active
844 // drop tic count and possibly change state
845 // a -1 tic count never changes
846
847 for (i=0; i<NUMPSPRITES; i++, psp++)
848 if (psp->state && psp->tics != -1 && !--psp->tics)
849 P_SetPsprite(player, i, psp->state->nextstate);
850
851 player->psprites[ps_flash].sx = player->psprites[ps_weapon].sx;
852 player->psprites[ps_flash].sy = player->psprites[ps_weapon].sy;
853}
diff --git a/apps/plugins/doom/p_pspr.h b/apps/plugins/doom/p_pspr.h
new file mode 100644
index 0000000000..bb6517c4e1
--- /dev/null
+++ b/apps/plugins/doom/p_pspr.h
@@ -0,0 +1,93 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION:
28 * Sprite animation.
29 *
30 *-----------------------------------------------------------------------------*/
31
32#ifndef __P_PSPR__
33#define __P_PSPR__
34
35/* Basic data types.
36 * Needs fixed point, and BAM angles. */
37
38#include "m_fixed.h"
39#include "tables.h"
40
41/* Needs to include the precompiled sprite animation tables.
42 *
43 * Header generated by multigen utility.
44 * This includes all the data for thing animation,
45 * i.e. the Thing Atrributes table and the Frame Sequence table.
46 */
47
48#include "info.h"
49
50#ifdef __GNUG__
51#pragma interface
52#endif
53
54/*
55 * Frame flags:
56 * handles maximum brightness (torches, muzzle flare, light sources)
57 */
58
59#define FF_FULLBRIGHT 0x8000 /* flag in thing->frame */
60#define FF_FRAMEMASK 0x7fff
61
62/*
63 * Overlay psprites are scaled shapes
64 * drawn directly on the view screen,
65 * coordinates are given for a 320*200 view screen.
66 */
67
68typedef enum
69{
70 ps_weapon,
71 ps_flash,
72 NUMPSPRITES
73} psprnum_t;
74
75typedef struct
76{
77 state_t *state; /* a NULL state means not active */
78 int tics;
79 fixed_t sx;
80 fixed_t sy;
81} pspdef_t;
82
83extern int weapon_preferences[2][NUMWEAPONS+1]; /* killough 5/2/98 */
84int P_WeaponPreferred(int w1, int w2);
85
86struct player_s;
87int P_SwitchWeapon(struct player_s *player);
88boolean P_CheckAmmo(struct player_s *player);
89void P_SetupPsprites(struct player_s *curplayer);
90void P_MovePsprites(struct player_s *curplayer);
91void P_DropWeapon(struct player_s *player);
92
93#endif
diff --git a/apps/plugins/doom/p_saveg.c b/apps/plugins/doom/p_saveg.c
new file mode 100644
index 0000000000..bf1a2edc45
--- /dev/null
+++ b/apps/plugins/doom/p_saveg.c
@@ -0,0 +1,987 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION:
28 * Archiving: SaveGame I/O.
29 *
30 *-----------------------------------------------------------------------------*/
31
32#include "doomstat.h"
33#include "r_main.h"
34#include "p_maputl.h"
35#include "p_spec.h"
36#include "p_tick.h"
37#include "p_saveg.h"
38#include "m_random.h"
39#include "am_map.h"
40#include "p_enemy.h"
41#include "i_system.h"
42#include "rockmacros.h"
43byte *save_p;
44
45// Pads save_p to a 4-byte boundary
46// so that the load/save works on SGI&Gecko.
47#define PADSAVEP() do { save_p += (4 - ((int) save_p & 3)) & 3; } while (0)
48//
49// P_ArchivePlayers
50//
51void P_ArchivePlayers (void)
52{
53 int i;
54
55 CheckSaveGame(sizeof(player_t) * MAXPLAYERS); // killough
56 for (i=0 ; i<MAXPLAYERS ; i++)
57 if (playeringame[i])
58 {
59 int j;
60 player_t *dest;
61
62 PADSAVEP();
63 dest = (player_t *) save_p;
64 memcpy(dest, &players[i], sizeof(player_t));
65 save_p += sizeof(player_t);
66 for (j=0; j<NUMPSPRITES; j++)
67 if (dest->psprites[j].state)
68 dest->psprites[j].state =
69 (state_t *)(dest->psprites[j].state-states);
70 }
71}
72
73//
74// P_UnArchivePlayers
75//
76void P_UnArchivePlayers (void)
77{
78 int i;
79
80 for (i=0 ; i<MAXPLAYERS ; i++)
81 if (playeringame[i])
82 {
83 int j;
84
85 PADSAVEP();
86
87 memcpy(&players[i], save_p, sizeof(player_t));
88 save_p += sizeof(player_t);
89
90 // will be set when unarc thinker
91 players[i].mo = NULL;
92 players[i].message = NULL;
93 players[i].attacker = NULL;
94
95 for (j=0 ; j<NUMPSPRITES ; j++)
96 if (players[i]. psprites[j].state)
97 players[i]. psprites[j].state =
98 &states[ (int)players[i].psprites[j].state ];
99 }
100}
101
102
103//
104// P_ArchiveWorld
105//
106void P_ArchiveWorld (void)
107{
108 int i;
109 const sector_t *sec;
110 const line_t *li;
111 const side_t *si;
112 short *put;
113
114 // killough 3/22/98: fix bug caused by hoisting save_p too early
115 // killough 10/98: adjust size for changes below
116 size_t size =
117 (sizeof(short)*5 + sizeof sec->floorheight + sizeof sec->ceilingheight)
118 * numsectors + sizeof(short)*3*numlines + 4;
119
120 for (i=0; i<numlines; i++)
121 {
122 if (lines[i].sidenum[0] != -1)
123 size +=
124 sizeof(short)*3 + sizeof si->textureoffset + sizeof si->rowoffset;
125 if (lines[i].sidenum[1] != -1)
126 size +=
127 sizeof(short)*3 + sizeof si->textureoffset + sizeof si->rowoffset;
128 }
129
130 CheckSaveGame(size); // killough
131
132 PADSAVEP(); // killough 3/22/98
133
134 put = (short *)save_p;
135
136 // do sectors
137 for (i=0, sec = sectors ; i<numsectors ; i++,sec++)
138 {
139 // killough 10/98: save full floor & ceiling heights, including fraction
140 memcpy(put, &sec->floorheight, sizeof sec->floorheight);
141 put = (void *)((char *) put + sizeof sec->floorheight);
142 memcpy(put, &sec->ceilingheight, sizeof sec->ceilingheight);
143 put = (void *)((char *) put + sizeof sec->ceilingheight);
144
145 *put++ = sec->floorpic;
146 *put++ = sec->ceilingpic;
147 *put++ = sec->lightlevel;
148 *put++ = sec->special; // needed? yes -- transfer types
149 *put++ = sec->tag; // needed? need them -- killough
150 }
151
152 // do lines
153 for (i=0, li = lines ; i<numlines ; i++,li++)
154 {
155 int j;
156
157 *put++ = li->flags;
158 *put++ = li->special;
159 *put++ = li->tag;
160
161 for (j=0; j<2; j++)
162 if (li->sidenum[j] != -1)
163 {
164 si = &sides[li->sidenum[j]];
165
166 // killough 10/98: save full sidedef offsets,
167 // preserving fractional scroll offsets
168
169 memcpy(put, &si->textureoffset, sizeof si->textureoffset);
170 put = (void *)((char *) put + sizeof si->textureoffset);
171 memcpy(put, &si->rowoffset, sizeof si->rowoffset);
172 put = (void *)((char *) put + sizeof si->rowoffset);
173
174 *put++ = si->toptexture;
175 *put++ = si->bottomtexture;
176 *put++ = si->midtexture;
177 }
178 }
179 save_p = (byte *) put;
180}
181
182
183
184//
185// P_UnArchiveWorld
186//
187void P_UnArchiveWorld (void)
188{
189 int i;
190 sector_t *sec;
191 line_t *li;
192 const short *get;
193
194 PADSAVEP(); // killough 3/22/98
195
196 get = (short *) save_p;
197
198 // do sectors
199 for (i=0, sec = sectors ; i<numsectors ; i++,sec++)
200 {
201 // killough 10/98: load full floor & ceiling heights, including fractions
202
203 memcpy(&sec->floorheight, get, sizeof sec->floorheight);
204 get = (void *)((char *) get + sizeof sec->floorheight);
205 memcpy(&sec->ceilingheight, get, sizeof sec->ceilingheight);
206 get = (void *)((char *) get + sizeof sec->ceilingheight);
207
208 sec->floorpic = *get++;
209 sec->ceilingpic = *get++;
210 sec->lightlevel = *get++;
211 sec->special = *get++;
212 sec->tag = *get++;
213 sec->ceilingdata = 0; //jff 2/22/98 now three thinker fields, not two
214 sec->floordata = 0;
215 sec->lightingdata = 0;
216 sec->soundtarget = 0;
217 }
218
219 // do lines
220 for (i=0, li = lines ; i<numlines ; i++,li++)
221 {
222 int j;
223
224 li->flags = *get++;
225 li->special = *get++;
226 li->tag = *get++;
227 for (j=0 ; j<2 ; j++)
228 if (li->sidenum[j] != -1)
229 {
230 side_t *si = &sides[li->sidenum[j]];
231
232 // killough 10/98: load full sidedef offsets, including fractions
233
234 memcpy(&si->textureoffset, get, sizeof si->textureoffset);
235 get = (void *)((char *) get + sizeof si->textureoffset);
236 memcpy(&si->rowoffset, get, sizeof si->rowoffset);
237 get = (void *)((char *) get + sizeof si->rowoffset);
238
239 si->toptexture = *get++;
240 si->bottomtexture = *get++;
241 si->midtexture = *get++;
242 }
243 }
244 save_p = (byte *) get;
245}
246
247//
248// Thinkers
249//
250
251typedef enum {
252 tc_end,
253 tc_mobj
254} thinkerclass_t;
255
256// phares 9/13/98: Moved this code outside of P_ArchiveThinkers so the
257// thinker indices could be used by the code that saves sector info.
258
259static int number_of_thinkers;
260
261void P_ThinkerToIndex(void)
262{
263 thinker_t *th;
264
265 // killough 2/14/98:
266 // count the number of thinkers, and mark each one with its index, using
267 // the prev field as a placeholder, since it can be restored later.
268
269 number_of_thinkers = 0;
270 for (th = thinkercap.next ; th != &thinkercap ; th=th->next)
271 if (th->function == P_MobjThinker)
272 th->prev = (thinker_t *) ++number_of_thinkers;
273}
274
275// phares 9/13/98: Moved this code outside of P_ArchiveThinkers so the
276// thinker indices could be used by the code that saves sector info.
277
278void P_IndexToThinker(void)
279{
280 // killough 2/14/98: restore prev pointers
281 thinker_t *th;
282 thinker_t *prev = &thinkercap;
283
284 for (th = thinkercap.next ; th != &thinkercap ; prev=th, th=th->next)
285 th->prev = prev;
286}
287
288//
289// P_ArchiveThinkers
290//
291// 2/14/98 killough: substantially modified to fix savegame bugs
292
293void P_ArchiveThinkers (void)
294{
295 thinker_t *th;
296
297 CheckSaveGame(sizeof brain); // killough 3/26/98: Save boss brain state
298 memcpy(save_p, &brain, sizeof brain);
299 save_p += sizeof brain;
300
301 /* check that enough room is available in savegame buffer
302 * - killough 2/14/98
303 * cph - use number_of_thinkers saved by P_ThinkerToIndex above
304 */
305 CheckSaveGame(number_of_thinkers*(sizeof(mobj_t)+4));
306
307 // save off the current thinkers
308 for (th = thinkercap.next ; th != &thinkercap ; th=th->next)
309 if (th->function == P_MobjThinker)
310 {
311 mobj_t *mobj;
312
313 *save_p++ = tc_mobj;
314 PADSAVEP();
315 mobj = (mobj_t *)save_p;
316 memcpy (mobj, th, sizeof(*mobj));
317 save_p += sizeof(*mobj);
318 mobj->state = (state_t *)(mobj->state - states);
319
320 // killough 2/14/98: convert pointers into indices.
321 // Fixes many savegame problems, by properly saving
322 // target and tracer fields. Note: we store NULL if
323 // the thinker pointed to by these fields is not a
324 // mobj thinker.
325
326 if (mobj->target)
327 mobj->target = mobj->target->thinker.function ==
328 P_MobjThinker ?
329 (mobj_t *) mobj->target->thinker.prev : NULL;
330
331 if (mobj->tracer)
332 mobj->tracer = mobj->tracer->thinker.function ==
333 P_MobjThinker ?
334 (mobj_t *) mobj->tracer->thinker.prev : NULL;
335
336 // killough 2/14/98: new field: save last known enemy. Prevents
337 // monsters from going to sleep after killing monsters and not
338 // seeing player anymore.
339
340 if (mobj->lastenemy)
341 mobj->lastenemy = mobj->lastenemy->thinker.function ==
342 P_MobjThinker ?
343 (mobj_t *) mobj->lastenemy->thinker.prev : NULL;
344
345 // killough 2/14/98: end changes
346
347 if (mobj->above_thing) // phares
348 mobj->above_thing = mobj->above_thing->thinker.function ==
349 P_MobjThinker ?
350 (mobj_t *) mobj->above_thing->thinker.prev : NULL;
351
352 if (mobj->below_thing)
353 mobj->below_thing = mobj->below_thing->thinker.function ==
354 P_MobjThinker ?
355 (mobj_t *) mobj->below_thing->thinker.prev : NULL; // phares
356
357 if (mobj->player)
358 mobj->player = (player_t *)((mobj->player-players) + 1);
359 }
360
361 // add a terminating marker
362 *save_p++ = tc_end;
363
364 // killough 9/14/98: save soundtargets
365 {
366 int i;
367 CheckSaveGame(numsectors * sizeof(mobj_t *)); // killough 9/14/98
368 for (i = 0; i < numsectors; i++)
369 {
370 mobj_t *target = sectors[i].soundtarget;
371 if (target)
372 target = (mobj_t *) target->thinker.prev;
373 memcpy(save_p, &target, sizeof target);
374 save_p += sizeof target;
375 }
376 }
377}
378
379/*
380 * killough 11/98
381 *
382 * Same as P_SetTarget() in p_tick.c, except that the target is nullified
383 * first, so that no old target's reference count is decreased (when loading
384 * savegames, old targets are indices, not really pointers to targets).
385 */
386
387static void P_SetNewTarget(mobj_t **mop, mobj_t *targ)
388{
389 *mop = NULL;
390 P_SetTarget(mop, targ);
391}
392
393//
394// P_UnArchiveThinkers
395//
396// 2/14/98 killough: substantially modified to fix savegame bugs
397//
398
399void P_UnArchiveThinkers (void)
400{
401 thinker_t *th;
402 mobj_t **mobj_p; // killough 2/14/98: Translation table
403 size_t size; // killough 2/14/98: size of or index into table
404
405 totallive = 0;
406 // killough 3/26/98: Load boss brain state
407 memcpy(&brain, save_p, sizeof brain);
408 save_p += sizeof brain;
409
410 // remove all the current thinkers
411 for (th = thinkercap.next; th != &thinkercap; )
412 {
413 thinker_t *next = th->next;
414 if (th->function == P_MobjThinker)
415 P_RemoveMobj ((mobj_t *) th);
416 else
417 Z_Free (th);
418 th = next;
419 }
420 P_InitThinkers ();
421
422 // killough 2/14/98: count number of thinkers by skipping through them
423 {
424 byte *sp = save_p; // save pointer and skip header
425 for (size = 1; *save_p++ == tc_mobj; size++) // killough 2/14/98
426 { // skip all entries, adding up count
427 PADSAVEP();
428 save_p += sizeof(mobj_t);
429 }
430
431 if (*--save_p != tc_end)
432 I_Error ("P_UnArchiveThinkers: Unknown tclass %i in savegame", *save_p);
433
434 // first table entry special: 0 maps to NULL
435 *(mobj_p = malloc(size * sizeof *mobj_p)) = 0; // table of pointers
436 save_p = sp; // restore save pointer
437 }
438
439 // read in saved thinkers
440 for (size = 1; *save_p++ == tc_mobj; size++) // killough 2/14/98
441 {
442 mobj_t *mobj = Z_Malloc(sizeof(mobj_t), PU_LEVEL, NULL);
443
444 // killough 2/14/98 -- insert pointers to thinkers into table, in order:
445 mobj_p[size] = mobj;
446
447 PADSAVEP();
448 memcpy (mobj, save_p, sizeof(mobj_t));
449 save_p += sizeof(mobj_t);
450 mobj->state = states + (int) mobj->state;
451
452 if (mobj->player)
453 (mobj->player = &players[(int) mobj->player - 1]) -> mo = mobj;
454
455 P_SetThingPosition (mobj);
456 mobj->info = &mobjinfo[mobj->type];
457
458 // killough 2/28/98:
459 // Fix for falling down into a wall after savegame loaded:
460 // mobj->floorz = mobj->subsector->sector->floorheight;
461 // mobj->ceilingz = mobj->subsector->sector->ceilingheight;
462
463 mobj->thinker.function = P_MobjThinker;
464 P_AddThinker (&mobj->thinker);
465
466 if (!((mobj->flags ^ MF_COUNTKILL) & (MF_FRIEND | MF_COUNTKILL | MF_CORPSE)))
467 totallive++;
468 }
469
470 // killough 2/14/98: adjust target and tracer fields, plus
471 // lastenemy field, to correctly point to mobj thinkers.
472 // NULL entries automatically handled by first table entry.
473 //
474 // killough 11/98: use P_SetNewTarget() to set fields
475
476 for (th = thinkercap.next ; th != &thinkercap ; th=th->next)
477 {
478 P_SetNewTarget(&((mobj_t *) th)->target,
479 mobj_p[(size_t)((mobj_t *)th)->target]);
480
481 P_SetNewTarget(&((mobj_t *) th)->tracer,
482 mobj_p[(size_t)((mobj_t *)th)->tracer]);
483
484 P_SetNewTarget(&((mobj_t *) th)->lastenemy,
485 mobj_p[(size_t)((mobj_t *)th)->lastenemy]);
486
487 // phares: added two new fields for Sprite Height problem
488
489 P_SetNewTarget(&((mobj_t *) th)->above_thing,
490 mobj_p[(size_t)((mobj_t *)th)->above_thing]);
491
492 P_SetNewTarget(&((mobj_t *) th)->below_thing,
493 mobj_p[(size_t)((mobj_t *)th)->below_thing]);
494 }
495
496 { // killough 9/14/98: restore soundtargets
497 int i;
498 for (i = 0; i < numsectors; i++)
499 {
500 mobj_t *target;
501 memcpy(&target, save_p, sizeof target);
502 save_p += sizeof target;
503 P_SetNewTarget(&sectors[i].soundtarget, mobj_p[(size_t) target]);
504 }
505 }
506
507 free(mobj_p); // free translation table
508
509 // killough 3/26/98: Spawn icon landings:
510 if (gamemode == commercial)
511 P_SpawnBrainTargets();
512}
513
514//
515// P_ArchiveSpecials
516//
517enum {
518 tc_ceiling,
519 tc_door,
520 tc_floor,
521 tc_plat,
522 tc_flash,
523 tc_strobe,
524 tc_glow,
525 tc_elevator, //jff 2/22/98 new elevator type thinker
526 tc_scroll, // killough 3/7/98: new scroll effect thinker
527 tc_pusher, // phares 3/22/98: new push/pull effect thinker
528 tc_flicker, // killough 10/4/98
529 tc_endspecials
530} specials_e;
531
532//
533// Things to handle:
534//
535// T_MoveCeiling, (ceiling_t: sector_t * swizzle), - active list
536// T_VerticalDoor, (vldoor_t: sector_t * swizzle),
537// T_MoveFloor, (floormove_t: sector_t * swizzle),
538// T_LightFlash, (lightflash_t: sector_t * swizzle),
539// T_StrobeFlash, (strobe_t: sector_t *),
540// T_Glow, (glow_t: sector_t *),
541// T_PlatRaise, (plat_t: sector_t *), - active list
542// T_MoveElevator, (plat_t: sector_t *), - active list // jff 2/22/98
543// T_Scroll // killough 3/7/98
544// T_Pusher // phares 3/22/98
545// T_FireFlicker // killough 10/4/98
546//
547
548void P_ArchiveSpecials (void)
549{
550 thinker_t *th;
551 size_t size = 0; // killough
552
553 // save off the current thinkers (memory size calculation -- killough)
554
555 for (th = thinkercap.next ; th != &thinkercap ; th=th->next)
556 if (!th->function)
557 {
558 platlist_t *pl;
559 ceilinglist_t *cl; //jff 2/22/98 need this for ceilings too now
560 for (pl=activeplats; pl; pl=pl->next)
561 if (pl->plat == (plat_t *) th) // killough 2/14/98
562 {
563 size += 4+sizeof(plat_t);
564 goto end;
565 }
566 for (cl=activeceilings; cl; cl=cl->next) // search for activeceiling
567 if (cl->ceiling == (ceiling_t *) th) //jff 2/22/98
568 {
569 size += 4+sizeof(ceiling_t);
570 goto end;
571 }
572end:;
573 }
574 else
575 size +=
576 th->function==T_MoveCeiling ? 4+sizeof(ceiling_t) :
577 th->function==T_VerticalDoor ? 4+sizeof(vldoor_t) :
578 th->function==T_MoveFloor ? 4+sizeof(floormove_t):
579 th->function==T_PlatRaise ? 4+sizeof(plat_t) :
580 th->function==T_LightFlash ? 4+sizeof(lightflash_t):
581 th->function==T_StrobeFlash ? 4+sizeof(strobe_t) :
582 th->function==T_Glow ? 4+sizeof(glow_t) :
583 th->function==T_MoveElevator ? 4+sizeof(elevator_t):
584 th->function==T_Scroll ? 4+sizeof(scroll_t) :
585 th->function==T_Pusher ? 4+sizeof(pusher_t) :
586 th->function==T_FireFlicker? 4+sizeof(fireflicker_t) :
587 0;
588
589 CheckSaveGame(size); // killough
590
591 // save off the current thinkers
592 for (th=thinkercap.next; th!=&thinkercap; th=th->next)
593 {
594 if (!th->function)
595 {
596 platlist_t *pl;
597 ceilinglist_t *cl; //jff 2/22/98 add iter variable for ceilings
598
599 // killough 2/8/98: fix plat original height bug.
600 // Since acv==NULL, this could be a plat in stasis.
601 // so check the active plats list, and save this
602 // plat (jff: or ceiling) even if it is in stasis.
603
604 for (pl=activeplats; pl; pl=pl->next)
605 if (pl->plat == (plat_t *) th) // killough 2/14/98
606 goto plat;
607
608 for (cl=activeceilings; cl; cl=cl->next)
609 if (cl->ceiling == (ceiling_t *) th) //jff 2/22/98
610 goto ceiling;
611
612 continue;
613 }
614
615 if (th->function == T_MoveCeiling)
616 {
617 ceiling_t *ceiling;
618ceiling: // killough 2/14/98
619 *save_p++ = tc_ceiling;
620 PADSAVEP();
621 ceiling = (ceiling_t *)save_p;
622 memcpy (ceiling, th, sizeof(*ceiling));
623 save_p += sizeof(*ceiling);
624 ceiling->sector = (sector_t *)(ceiling->sector - sectors);
625 continue;
626 }
627
628 if (th->function == T_VerticalDoor)
629 {
630 vldoor_t *door;
631 *save_p++ = tc_door;
632 PADSAVEP();
633 door = (vldoor_t *) save_p;
634 memcpy (door, th, sizeof *door);
635 save_p += sizeof(*door);
636 door->sector = (sector_t *)(door->sector - sectors);
637 //jff 1/31/98 archive line remembered by door as well
638 door->line = (line_t *) (door->line ? door->line-lines : -1);
639 continue;
640 }
641
642 if (th->function == T_MoveFloor)
643 {
644 floormove_t *floor;
645 *save_p++ = tc_floor;
646 PADSAVEP();
647 floor = (floormove_t *)save_p;
648 memcpy (floor, th, sizeof(*floor));
649 save_p += sizeof(*floor);
650 floor->sector = (sector_t *)(floor->sector - sectors);
651 continue;
652 }
653
654 if (th->function == T_PlatRaise)
655 {
656 plat_t *plat;
657plat: // killough 2/14/98: added fix for original plat height above
658 *save_p++ = tc_plat;
659 PADSAVEP();
660 plat = (plat_t *)save_p;
661 memcpy (plat, th, sizeof(*plat));
662 save_p += sizeof(*plat);
663 plat->sector = (sector_t *)(plat->sector - sectors);
664 continue;
665 }
666
667 if (th->function == T_LightFlash)
668 {
669 lightflash_t *flash;
670 *save_p++ = tc_flash;
671 PADSAVEP();
672 flash = (lightflash_t *)save_p;
673 memcpy (flash, th, sizeof(*flash));
674 save_p += sizeof(*flash);
675 flash->sector = (sector_t *)(flash->sector - sectors);
676 continue;
677 }
678
679 if (th->function == T_StrobeFlash)
680 {
681 strobe_t *strobe;
682 *save_p++ = tc_strobe;
683 PADSAVEP();
684 strobe = (strobe_t *)save_p;
685 memcpy (strobe, th, sizeof(*strobe));
686 save_p += sizeof(*strobe);
687 strobe->sector = (sector_t *)(strobe->sector - sectors);
688 continue;
689 }
690
691 if (th->function == T_Glow)
692 {
693 glow_t *glow;
694 *save_p++ = tc_glow;
695 PADSAVEP();
696 glow = (glow_t *)save_p;
697 memcpy (glow, th, sizeof(*glow));
698 save_p += sizeof(*glow);
699 glow->sector = (sector_t *)(glow->sector - sectors);
700 continue;
701 }
702
703 // killough 10/4/98: save flickers
704 if (th->function == T_FireFlicker)
705 {
706 fireflicker_t *flicker;
707 *save_p++ = tc_flicker;
708 PADSAVEP();
709 flicker = (fireflicker_t *)save_p;
710 memcpy (flicker, th, sizeof(*flicker));
711 save_p += sizeof(*flicker);
712 flicker->sector = (sector_t *)(flicker->sector - sectors);
713 continue;
714 }
715
716 //jff 2/22/98 new case for elevators
717 if (th->function == T_MoveElevator)
718 {
719 elevator_t *elevator; //jff 2/22/98
720 *save_p++ = tc_elevator;
721 PADSAVEP();
722 elevator = (elevator_t *)save_p;
723 memcpy (elevator, th, sizeof(*elevator));
724 save_p += sizeof(*elevator);
725 elevator->sector = (sector_t *)(elevator->sector - sectors);
726 continue;
727 }
728
729 // killough 3/7/98: Scroll effect thinkers
730 if (th->function == T_Scroll)
731 {
732 *save_p++ = tc_scroll;
733 memcpy (save_p, th, sizeof(scroll_t));
734 save_p += sizeof(scroll_t);
735 continue;
736 }
737
738 // phares 3/22/98: Push/Pull effect thinkers
739
740 if (th->function == T_Pusher)
741 {
742 *save_p++ = tc_pusher;
743 memcpy (save_p, th, sizeof(pusher_t));
744 save_p += sizeof(pusher_t);
745 continue;
746 }
747 }
748
749 // add a terminating marker
750 *save_p++ = tc_endspecials;
751}
752
753
754//
755// P_UnArchiveSpecials
756//
757void P_UnArchiveSpecials (void)
758{
759 byte tclass;
760
761 // read in saved thinkers
762 while ((tclass = *save_p++) != tc_endspecials) // killough 2/14/98
763 switch (tclass)
764 {
765 case tc_ceiling:
766 PADSAVEP();
767 {
768 ceiling_t *ceiling = Z_Malloc (sizeof(*ceiling), PU_LEVEL, NULL);
769 memcpy (ceiling, save_p, sizeof(*ceiling));
770 save_p += sizeof(*ceiling);
771 ceiling->sector = &sectors[(int)ceiling->sector];
772 ceiling->sector->ceilingdata = ceiling; //jff 2/22/98
773
774 if (ceiling->thinker.function)
775 ceiling->thinker.function = T_MoveCeiling;
776
777 P_AddThinker (&ceiling->thinker);
778 P_AddActiveCeiling(ceiling);
779 break;
780 }
781
782 case tc_door:
783 PADSAVEP();
784 {
785 vldoor_t *door = Z_Malloc (sizeof(*door), PU_LEVEL, NULL);
786 memcpy (door, save_p, sizeof(*door));
787 save_p += sizeof(*door);
788 door->sector = &sectors[(int)door->sector];
789
790 //jff 1/31/98 unarchive line remembered by door as well
791 door->line = (int)door->line!=-1? &lines[(int)door->line] : NULL;
792
793 door->sector->ceilingdata = door; //jff 2/22/98
794 door->thinker.function = T_VerticalDoor;
795 P_AddThinker (&door->thinker);
796 break;
797 }
798
799 case tc_floor:
800 PADSAVEP();
801 {
802 floormove_t *floor = Z_Malloc (sizeof(*floor), PU_LEVEL, NULL);
803 memcpy (floor, save_p, sizeof(*floor));
804 save_p += sizeof(*floor);
805 floor->sector = &sectors[(int)floor->sector];
806 floor->sector->floordata = floor; //jff 2/22/98
807 floor->thinker.function = T_MoveFloor;
808 P_AddThinker (&floor->thinker);
809 break;
810 }
811
812 case tc_plat:
813 PADSAVEP();
814 {
815 plat_t *plat = Z_Malloc (sizeof(*plat), PU_LEVEL, NULL);
816 memcpy (plat, save_p, sizeof(*plat));
817 save_p += sizeof(*plat);
818 plat->sector = &sectors[(int)plat->sector];
819 plat->sector->floordata = plat; //jff 2/22/98
820
821 if (plat->thinker.function)
822 plat->thinker.function = T_PlatRaise;
823
824 P_AddThinker (&plat->thinker);
825 P_AddActivePlat(plat);
826 break;
827 }
828
829 case tc_flash:
830 PADSAVEP();
831 {
832 lightflash_t *flash = Z_Malloc (sizeof(*flash), PU_LEVEL, NULL);
833 memcpy (flash, save_p, sizeof(*flash));
834 save_p += sizeof(*flash);
835 flash->sector = &sectors[(int)flash->sector];
836 flash->thinker.function = T_LightFlash;
837 P_AddThinker (&flash->thinker);
838 break;
839 }
840
841 case tc_strobe:
842 PADSAVEP();
843 {
844 strobe_t *strobe = Z_Malloc (sizeof(*strobe), PU_LEVEL, NULL);
845 memcpy (strobe, save_p, sizeof(*strobe));
846 save_p += sizeof(*strobe);
847 strobe->sector = &sectors[(int)strobe->sector];
848 strobe->thinker.function = T_StrobeFlash;
849 P_AddThinker (&strobe->thinker);
850 break;
851 }
852
853 case tc_glow:
854 PADSAVEP();
855 {
856 glow_t *glow = Z_Malloc (sizeof(*glow), PU_LEVEL, NULL);
857 memcpy (glow, save_p, sizeof(*glow));
858 save_p += sizeof(*glow);
859 glow->sector = &sectors[(int)glow->sector];
860 glow->thinker.function = T_Glow;
861 P_AddThinker (&glow->thinker);
862 break;
863 }
864
865 case tc_flicker: // killough 10/4/98
866 PADSAVEP();
867 {
868 fireflicker_t *flicker = Z_Malloc (sizeof(*flicker), PU_LEVEL, NULL);
869 memcpy (flicker, save_p, sizeof(*flicker));
870 save_p += sizeof(*flicker);
871 flicker->sector = &sectors[(int)flicker->sector];
872 flicker->thinker.function = T_FireFlicker;
873 P_AddThinker (&flicker->thinker);
874 break;
875 }
876
877 //jff 2/22/98 new case for elevators
878 case tc_elevator:
879 PADSAVEP();
880 {
881 elevator_t *elevator = Z_Malloc (sizeof(*elevator), PU_LEVEL, NULL);
882 memcpy (elevator, save_p, sizeof(*elevator));
883 save_p += sizeof(*elevator);
884 elevator->sector = &sectors[(int)elevator->sector];
885 elevator->sector->floordata = elevator; //jff 2/22/98
886 elevator->sector->ceilingdata = elevator; //jff 2/22/98
887 elevator->thinker.function = T_MoveElevator;
888 P_AddThinker (&elevator->thinker);
889 break;
890 }
891
892 case tc_scroll: // killough 3/7/98: scroll effect thinkers
893 {
894 scroll_t *scroll = Z_Malloc (sizeof(scroll_t), PU_LEVEL, NULL);
895 memcpy (scroll, save_p, sizeof(scroll_t));
896 save_p += sizeof(scroll_t);
897 scroll->thinker.function = T_Scroll;
898 P_AddThinker(&scroll->thinker);
899 break;
900 }
901
902 case tc_pusher: // phares 3/22/98: new Push/Pull effect thinkers
903 {
904 pusher_t *pusher = Z_Malloc (sizeof(pusher_t), PU_LEVEL, NULL);
905 memcpy (pusher, save_p, sizeof(pusher_t));
906 save_p += sizeof(pusher_t);
907 pusher->thinker.function = T_Pusher;
908 pusher->source = P_GetPushThing(pusher->affectee);
909 P_AddThinker(&pusher->thinker);
910 break;
911 }
912
913 default:
914 I_Error("P_UnarchiveSpecials: Unknown tclass %i in savegame", tclass);
915 }
916}
917
918// killough 2/16/98: save/restore random number generator state information
919
920void P_ArchiveRNG(void)
921{
922 CheckSaveGame(sizeof rng);
923 memcpy(save_p, &rng, sizeof rng);
924 save_p += sizeof rng;
925}
926
927void P_UnArchiveRNG(void)
928{
929 memcpy(&rng, save_p, sizeof rng);
930 save_p += sizeof rng;
931}
932
933// killough 2/22/98: Save/restore automap state
934// killough 2/22/98: Save/restore automap state
935void P_ArchiveMap(void)
936{
937 int zero = 0, one = 1;
938 CheckSaveGame(2 * sizeof zero + sizeof markpointnum +
939 markpointnum * sizeof *markpoints +
940 sizeof automapmode + sizeof one);
941
942 memcpy(save_p, &automapmode, sizeof automapmode);
943 save_p += sizeof automapmode;
944 memcpy(save_p, &one, sizeof one); // CPhipps - used to be viewactive, now
945 save_p += sizeof one; // that's worked out locally by D_Display
946 memcpy(save_p, &zero, sizeof zero); // CPhipps - used to be followplayer
947 save_p += sizeof zero; // that is now part of automapmode
948 memcpy(save_p, &zero, sizeof zero); // CPhipps - used to be automap_grid, ditto
949 save_p += sizeof zero;
950 memcpy(save_p, &markpointnum, sizeof markpointnum);
951 save_p += sizeof markpointnum;
952
953 if (markpointnum)
954 {
955 memcpy(save_p, markpoints, sizeof *markpoints * markpointnum);
956 save_p += markpointnum * sizeof *markpoints;
957 }
958}
959
960void P_UnArchiveMap(void)
961{
962 int unused;
963 memcpy(&automapmode, save_p, sizeof automapmode);
964 save_p += sizeof automapmode;
965 memcpy(&unused, save_p, sizeof unused);
966 save_p += sizeof unused;
967 memcpy(&unused, save_p, sizeof unused);
968 save_p += sizeof unused;
969 memcpy(&unused, save_p, sizeof unused);
970 save_p += sizeof unused;
971
972 if (automapmode & am_active)
973 AM_Start();
974
975 memcpy(&markpointnum, save_p, sizeof markpointnum);
976 save_p += sizeof markpointnum;
977
978 if (markpointnum)
979 {
980 while (markpointnum >= markpointnum_max)
981 markpoints = realloc(markpoints, sizeof *markpoints *
982 (markpointnum_max = markpointnum_max ? markpointnum_max*2 : 16));
983 memcpy(markpoints, save_p, markpointnum * sizeof *markpoints);
984 save_p += markpointnum * sizeof *markpoints;
985 }
986}
987
diff --git a/apps/plugins/doom/p_saveg.h b/apps/plugins/doom/p_saveg.h
new file mode 100644
index 0000000000..1bfe1d4291
--- /dev/null
+++ b/apps/plugins/doom/p_saveg.h
@@ -0,0 +1,63 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION:
28 * Savegame I/O, archiving, persistence.
29 *
30 *-----------------------------------------------------------------------------*/
31
32#ifndef __P_SAVEG__
33#define __P_SAVEG__
34
35#ifdef __GNUG__
36#pragma interface
37#endif
38
39/* Persistent storage/archiving.
40 * These are the load / save game routines. */
41void P_ArchivePlayers(void);
42void P_UnArchivePlayers(void);
43void P_ArchiveWorld(void);
44void P_UnArchiveWorld(void);
45void P_ArchiveThinkers(void);
46void P_UnArchiveThinkers(void);
47void P_ArchiveSpecials(void);
48void P_UnArchiveSpecials(void);
49void P_ThinkerToIndex(void); /* phares 9/13/98: save soundtarget in savegame */
50void P_IndexToThinker(void); /* phares 9/13/98: save soundtarget in savegame */
51
52/* 1/18/98 killough: add RNG info to savegame */
53void P_ArchiveRNG(void);
54void P_UnArchiveRNG(void);
55
56/* 2/21/98 killough: add automap info to savegame */
57void P_ArchiveMap(void);
58void P_UnArchiveMap(void);
59
60extern byte *save_p;
61void CheckSaveGame(size_t); /* killough */
62
63#endif
diff --git a/apps/plugins/doom/p_setup.c b/apps/plugins/doom/p_setup.c
new file mode 100644
index 0000000000..d40372d6da
--- /dev/null
+++ b/apps/plugins/doom/p_setup.c
@@ -0,0 +1,1255 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION:
28 * Do all the WAD I/O, get map description,
29 * set up initial state and misc. LUTs.
30 *
31 *-----------------------------------------------------------------------------*/
32
33#include <math.h>
34
35#include "doomstat.h"
36#include "m_bbox.h"
37#include "m_argv.h"
38#include "g_game.h"
39#include "w_wad.h"
40#include "r_main.h"
41#include "r_things.h"
42#include "p_maputl.h"
43#include "p_map.h"
44#include "p_setup.h"
45#include "p_spec.h"
46#include "p_tick.h"
47#include "p_enemy.h"
48#include "s_sound.h"
49#include "i_system.h"
50#include "m_swap.h"
51
52#include "rockmacros.h"
53//
54// MAP related Lookup tables.
55// Store VERTEXES, LINEDEFS, SIDEDEFS, etc.
56//
57
58int numvertexes;
59vertex_t *vertexes;
60
61int numsegs;
62seg_t *segs;
63
64int numsectors;
65sector_t *sectors;
66
67int numsubsectors;
68subsector_t *subsectors;
69
70int numnodes;
71node_t *nodes;
72
73int numlines;
74line_t *lines;
75
76int numsides;
77side_t *sides;
78
79
80////////////////////////////////////////////////////////////////////////////////////////////
81// figgi 08/21/00 -- constants and globals for glBsp support
82#define gNd2 0x32644E67 // figgi -- suppport for new GL_VERT format v2.0
83#define GL_VERT_OFFSET 4
84
85int firstglvertex = 0;
86boolean usingGLNodes = false;
87boolean forceOldBsp = false;
88
89enum
90{
91 ML_GL_LABEL=0, // A separator name, GL_ExMx or GL_MAPxx
92 ML_GL_VERTS, // Extra Vertices
93 ML_GL_SEGS, // Segs, from linedefs & minisegs
94 ML_GL_SSECT, // SubSectors, list of segs
95 ML_GL_NODES // GL BSP nodes
96};
97////////////////////////////////////////////////////////////////////////////////////////////
98
99
100// BLOCKMAP
101// Created from axis aligned bounding box
102// of the map, a rectangular array of
103// blocks of size ...
104// Used to speed up collision detection
105// by spatial subdivision in 2D.
106//
107// Blockmap size.
108
109int bmapwidth, bmapheight; // size in mapblocks
110
111// killough 3/1/98: remove blockmap limit internally:
112long *blockmap; // was short -- killough
113
114// offsets in blockmap are from here
115long *blockmaplump; // was short -- killough
116
117fixed_t bmaporgx, bmaporgy; // origin of block map
118
119mobj_t **blocklinks; // for thing chains
120
121//
122// REJECT
123// For fast sight rejection.
124// Speeds up enemy AI by skipping detailed
125// LineOf Sight calculation.
126// Without the special effect, this could
127// be used as a PVS lookup as well.
128//
129
130static int rejectlump = -1;// cph - store reject lump num if cached
131const byte *rejectmatrix; // cph - const*
132
133// Maintain single and multi player starting spots.
134
135// 1/11/98 killough: Remove limit on deathmatch starts
136mapthing_t *deathmatchstarts; // killough
137size_t num_deathmatchstarts; // killough
138
139mapthing_t *deathmatch_p;
140mapthing_t playerstarts[MAXPLAYERS];
141
142//
143// P_LoadVertexes
144//
145// killough 5/3/98: reformatted, cleaned up
146//
147static void P_LoadVertexes (int lump)
148{
149 const byte *data; // cph - const
150 int i;
151
152 // Determine number of lumps:
153 // total lump length / vertex record length.
154 numvertexes = W_LumpLength(lump) / sizeof(mapvertex_t);
155
156 // Allocate zone memory for buffer.
157 vertexes = Z_Malloc(numvertexes*sizeof(vertex_t),PU_LEVEL,0);
158
159 // Load data into cache.
160 data = W_CacheLumpNum(lump); // cph - wad handling updated
161
162 // Copy and convert vertex coordinates,
163 // internal representation as fixed.
164 for (i=0; i<numvertexes; i++)
165 {
166 vertexes[i].x = SHORT(((mapvertex_t *) data)[i].x)<<FRACBITS;
167 vertexes[i].y = SHORT(((mapvertex_t *) data)[i].y)<<FRACBITS;
168 }
169
170 // Free buffer memory.
171 W_UnlockLumpNum(lump);
172}
173
174//
175// P_LoadSegs
176//
177// killough 5/3/98: reformatted, cleaned up
178
179static void P_LoadSegs (int lump)
180{
181 int i;
182 const byte *data; // cph - const
183
184 numsegs = W_LumpLength(lump) / sizeof(mapseg_t);
185 segs = Z_Calloc(numsegs,sizeof(seg_t),PU_LEVEL,0);
186 data = W_CacheLumpNum(lump); // cph - wad lump handling updated
187
188 for (i=0; i<numsegs; i++)
189 {
190 seg_t *li = segs+i;
191 mapseg_t *ml = (mapseg_t *) data + i;
192
193 int side, linedef;
194 line_t *ldef;
195
196 li->v1 = &vertexes[SHORT(ml->v1)];
197 li->v2 = &vertexes[SHORT(ml->v2)];
198
199 li->miniseg = false; // figgi -- there are no minisegs in classic BSP nodes
200
201 li->angle = (SHORT(ml->angle))<<16;
202 li->offset =(SHORT(ml->offset))<<16;
203 linedef = SHORT(ml->linedef);
204 ldef = &lines[linedef];
205 li->linedef = ldef;
206 side = SHORT(ml->side);
207 li->sidedef = &sides[ldef->sidenum[side]];
208 li->frontsector = sides[ldef->sidenum[side]].sector;
209
210 // killough 5/3/98: ignore 2s flag if second sidedef missing:
211 if (ldef->flags & ML_TWOSIDED && ldef->sidenum[side^1]!=-1)
212 li->backsector = sides[ldef->sidenum[side^1]].sector;
213 else
214 li->backsector = 0;
215 }
216
217 W_UnlockLumpNum(lump); // cph - release the data
218}
219
220
221//
222// P_LoadSubsectors
223//
224// killough 5/3/98: reformatted, cleaned up
225
226static void P_LoadSubsectors (int lump)
227{
228 const byte *data; // cph - const*
229 int i;
230
231 numsubsectors = W_LumpLength (lump) / sizeof(mapsubsector_t);
232 subsectors = Z_Calloc(numsubsectors,sizeof(subsector_t),PU_LEVEL,0);
233 data = W_CacheLumpNum(lump); // cph - wad lump handling updated
234
235 for (i=0; i<numsubsectors; i++)
236 {
237 subsectors[i].numlines = (unsigned short)SHORT(((mapsubsector_t *) data)[i].numsegs );
238 subsectors[i].firstline = (unsigned short)SHORT(((mapsubsector_t *) data)[i].firstseg);
239 }
240
241 W_UnlockLumpNum(lump); // cph - release the data
242}
243
244//
245// P_LoadSectors
246//
247// killough 5/3/98: reformatted, cleaned up
248
249static void P_LoadSectors (int lump)
250{
251 const byte *data; // cph - const*
252 int i;
253
254 numsectors = W_LumpLength (lump) / sizeof(mapsector_t);
255 sectors = Z_Calloc (numsectors,sizeof(sector_t),PU_LEVEL,0);
256 data = W_CacheLumpNum (lump); // cph - wad lump handling updated
257
258 for (i=0; i<numsectors; i++)
259 {
260 sector_t *ss = sectors + i;
261 const mapsector_t *ms = (mapsector_t *) data + i;
262
263 ss->floorheight = SHORT(ms->floorheight)<<FRACBITS;
264 ss->ceilingheight = SHORT(ms->ceilingheight)<<FRACBITS;
265 ss->floorpic = R_FlatNumForName(ms->floorpic);
266 ss->ceilingpic = R_FlatNumForName(ms->ceilingpic);
267 ss->lightlevel = SHORT(ms->lightlevel);
268 ss->special = SHORT(ms->special);
269 ss->oldspecial = SHORT(ms->special);
270 ss->tag = SHORT(ms->tag);
271 ss->thinglist = NULL;
272 ss->touching_thinglist = NULL; // phares 3/14/98
273
274 ss->nextsec = -1; //jff 2/26/98 add fields to support locking out
275 ss->prevsec = -1; // stair retriggering until build completes
276
277 // killough 3/7/98:
278 ss->floor_xoffs = 0;
279 ss->floor_yoffs = 0; // floor and ceiling flats offsets
280 ss->ceiling_xoffs = 0;
281 ss->ceiling_yoffs = 0;
282 ss->heightsec = -1; // sector used to get floor and ceiling height
283 ss->floorlightsec = -1; // sector used to get floor lighting
284 // killough 3/7/98: end changes
285
286 // killough 4/11/98 sector used to get ceiling lighting:
287 ss->ceilinglightsec = -1;
288
289 // killough 4/4/98: colormaps:
290 ss->bottommap = ss->midmap = ss->topmap = 0;
291
292 // killough 10/98: sky textures coming from sidedefs:
293 ss->sky = 0;
294 }
295
296 W_UnlockLumpNum(lump); // cph - release the data
297}
298
299
300//
301// P_LoadNodes
302//
303// killough 5/3/98: reformatted, cleaned up
304
305static void P_LoadNodes (int lump)
306{
307 const byte *data; // cph - const*
308 int i;
309
310 numnodes = W_LumpLength (lump) / sizeof(mapnode_t);
311 nodes = Z_Malloc (numnodes*sizeof(node_t),PU_LEVEL,0);
312 data = W_CacheLumpNum (lump); // cph - wad lump handling updated
313
314 for (i=0; i<numnodes; i++)
315 {
316 node_t *no = nodes + i;
317 mapnode_t *mn = (mapnode_t *) data + i;
318 int j;
319
320 no->x = SHORT(mn->x)<<FRACBITS;
321 no->y = SHORT(mn->y)<<FRACBITS;
322 no->dx = SHORT(mn->dx)<<FRACBITS;
323 no->dy = SHORT(mn->dy)<<FRACBITS;
324
325 for (j=0 ; j<2 ; j++)
326 {
327 int k;
328 no->children[j] = SHORT(mn->children[j]);
329 for (k=0 ; k<4 ; k++)
330 no->bbox[j][k] = SHORT(mn->bbox[j][k])<<FRACBITS;
331 }
332 }
333
334 W_UnlockLumpNum(lump); // cph - release the data
335}
336
337
338//
339// P_LoadThings
340//
341// killough 5/3/98: reformatted, cleaned up
342
343static void P_LoadThings (int lump)
344{
345 mapthing_t tempthing; // this needed to be added as the SHORT calls were overwriting eachother on reload
346 int i, numthings = W_LumpLength (lump) / sizeof(mapthing_t);
347 const byte *data = W_CacheLumpNum (lump); // cph - wad lump handling updated, const*
348
349 for (i=0; i<numthings; i++)
350 {
351 mapthing_t *mt = (mapthing_t *) data + i;
352
353 // Do not spawn cool, new monsters if !commercial
354 if (gamemode != commercial)
355 switch(mt->type)
356 {
357 case 68: // Arachnotron
358 case 64: // Archvile
359 case 88: // Boss Brain
360 case 89: // Boss Shooter
361 case 69: // Hell Knight
362 case 67: // Mancubus
363 case 71: // Pain Elemental
364 case 65: // Former Human Commando
365 case 66: // Revenant
366 case 84: // Wolf SS
367 continue;
368 }
369
370 // Do spawn all other stuff.
371 tempthing.x = SHORT(mt->x);
372 tempthing.y = SHORT(mt->y);
373 tempthing.angle = SHORT(mt->angle);
374 tempthing.type = SHORT(mt->type);
375 tempthing.options = SHORT(mt->options);
376
377 P_SpawnMapThing (&tempthing);
378 }
379
380 W_UnlockLumpNum(lump); // cph - release the data
381}
382
383//
384// P_LoadLineDefs
385// Also counts secret lines for intermissions.
386// ^^^
387// ??? killough ???
388// Does this mean secrets used to be linedef-based, rather than sector-based?
389//
390// killough 4/4/98: split into two functions, to allow sidedef overloading
391//
392// killough 5/3/98: reformatted, cleaned up
393
394static void P_LoadLineDefs (int lump)
395{
396 const byte *data; // cph - const*
397 int i;
398
399 numlines = W_LumpLength (lump) / sizeof(maplinedef_t);
400 lines = Z_Calloc (numlines,sizeof(line_t),PU_LEVEL,0);
401 data = W_CacheLumpNum (lump); // cph - wad lump handling updated
402
403 for (i=0; i<numlines; i++)
404 {
405 maplinedef_t *mld = (maplinedef_t *) data + i;
406 line_t *ld = lines+i;
407 vertex_t *v1, *v2;
408
409 ld->flags = SHORT(mld->flags);
410 ld->special = SHORT(mld->special);
411 ld->tag = SHORT(mld->tag);
412 v1 = ld->v1 = &vertexes[SHORT(mld->v1)];
413 v2 = ld->v2 = &vertexes[SHORT(mld->v2)];
414 ld->dx = v2->x - v1->x;
415 ld->dy = v2->y - v1->y;
416
417 ld->tranlump = -1; // killough 4/11/98: no translucency by default
418
419 ld->slopetype = !ld->dx ? ST_VERTICAL : !ld->dy ? ST_HORIZONTAL :
420 FixedDiv(ld->dy, ld->dx) > 0 ? ST_POSITIVE : ST_NEGATIVE;
421
422 if (v1->x < v2->x)
423 {
424 ld->bbox[BOXLEFT] = v1->x;
425 ld->bbox[BOXRIGHT] = v2->x;
426 }
427 else
428 {
429 ld->bbox[BOXLEFT] = v2->x;
430 ld->bbox[BOXRIGHT] = v1->x;
431 }
432
433 if (v1->y < v2->y)
434 {
435 ld->bbox[BOXBOTTOM] = v1->y;
436 ld->bbox[BOXTOP] = v2->y;
437 }
438 else
439 {
440 ld->bbox[BOXBOTTOM] = v2->y;
441 ld->bbox[BOXTOP] = v1->y;
442 }
443
444 ld->sidenum[0] = SHORT(mld->sidenum[0]);
445 ld->sidenum[1] = SHORT(mld->sidenum[1]);
446
447 // killough 4/4/98: support special sidedef interpretation below
448 if (ld->sidenum[0] != -1 && ld->special)
449 sides[*ld->sidenum].special = ld->special;
450 }
451
452 W_UnlockLumpNum(lump); // cph - release the lump
453}
454
455// killough 4/4/98: delay using sidedefs until they are loaded
456// killough 5/3/98: reformatted, cleaned up
457
458static void P_LoadLineDefs2(int lump)
459{
460 (void)lump;
461 int i = numlines;
462 register line_t *ld = lines;
463 for (;i--;ld++)
464 {
465 { // cph 2002/07/20 - these errors are fatal if not fixed, so apply them in compatibility mode - a desync is better than a crash!
466 // killough 11/98: fix common wad errors (missing sidedefs):
467
468 if (ld->sidenum[0] == -1) {
469 ld->sidenum[0] = 0; // Substitute dummy sidedef for missing right side
470 // cph - print a warning about the bug
471 printf("P_LoadSegs: linedef %d missing first sidedef\n",numlines-i);
472 }
473
474 if ((ld->sidenum[1] == -1) && (ld->flags & ML_TWOSIDED)) {
475 ld->flags &= ~ML_TWOSIDED; // Clear 2s flag for missing left side
476 // cph - print a warning about the bug
477 printf("P_LoadSegs: linedef %d has two-sided flag set, but no second sidedef\n",numlines-i);
478 }
479 }
480
481 ld->frontsector = ld->sidenum[0]!=-1 ? sides[ld->sidenum[0]].sector : 0;
482 ld->backsector = ld->sidenum[1]!=-1 ? sides[ld->sidenum[1]].sector : 0;
483 switch (ld->special)
484 { // killough 4/11/98: handle special types
485 int lump, j;
486
487 case 260: // killough 4/11/98: translucent 2s textures
488 lump = sides[*ld->sidenum].special; // translucency from sidedef
489 if (!ld->tag) // if tag==0,
490 ld->tranlump = lump; // affect this linedef only
491 else
492 for (j=0;j<numlines;j++) // if tag!=0,
493 if (lines[j].tag == ld->tag) // affect all matching linedefs
494 lines[j].tranlump = lump;
495 break;
496 }
497 }
498}
499
500//
501// P_LoadSideDefs
502//
503// killough 4/4/98: split into two functions
504
505static void P_LoadSideDefs (int lump)
506{
507 numsides = W_LumpLength(lump) / sizeof(mapsidedef_t);
508 sides = Z_Calloc(numsides,sizeof(side_t),PU_LEVEL,0);
509}
510
511// killough 4/4/98: delay using texture names until
512// after linedefs are loaded, to allow overloading.
513// killough 5/3/98: reformatted, cleaned up
514
515static void P_LoadSideDefs2(int lump)
516{
517 const byte *data = W_CacheLumpNum(lump); // cph - const*, wad lump handling updated
518 int i;
519
520 for (i=0; i<numsides; i++)
521 {
522 register mapsidedef_t *msd = (mapsidedef_t *) data + i;
523 register side_t *sd = sides + i;
524 register sector_t *sec;
525
526 sd->textureoffset = SHORT(msd->textureoffset)<<FRACBITS;
527 sd->rowoffset = SHORT(msd->rowoffset)<<FRACBITS;
528
529 // killough 4/4/98: allow sidedef texture names to be overloaded
530 // killough 4/11/98: refined to allow colormaps to work as wall
531 // textures if invalid as colormaps but valid as textures.
532
533 sd->sector = sec = &sectors[SHORT(msd->sector)];
534 switch (sd->special)
535 {
536 case 242: // variable colormap via 242 linedef
537 sd->bottomtexture =
538 (sec->bottommap = R_ColormapNumForName(msd->bottomtexture)) < 0 ?
539 sec->bottommap = 0, R_TextureNumForName(msd->bottomtexture): 0 ;
540 sd->midtexture =
541 (sec->midmap = R_ColormapNumForName(msd->midtexture)) < 0 ?
542 sec->midmap = 0, R_TextureNumForName(msd->midtexture) : 0 ;
543 sd->toptexture =
544 (sec->topmap = R_ColormapNumForName(msd->toptexture)) < 0 ?
545 sec->topmap = 0, R_TextureNumForName(msd->toptexture) : 0 ;
546 break;
547
548 case 260: // killough 4/11/98: apply translucency to 2s normal texture
549 sd->midtexture = strncasecmp("TRANMAP", msd->midtexture, 8) ?
550 (sd->special = W_CheckNumForName(msd->midtexture)) < 0 ||
551 W_LumpLength(sd->special) != 65536 ?
552 sd->special=0, R_TextureNumForName(msd->midtexture) :
553 (sd->special++, 0) : (sd->special=0);
554 sd->toptexture = R_TextureNumForName(msd->toptexture);
555 sd->bottomtexture = R_TextureNumForName(msd->bottomtexture);
556 break;
557
558 default: // normal cases
559 sd->midtexture = R_TextureNumForName(msd->midtexture);
560 sd->toptexture = R_TextureNumForName(msd->toptexture);
561 sd->bottomtexture = R_TextureNumForName(msd->bottomtexture);
562 break;
563 }
564 }
565
566 W_UnlockLumpNum(lump); // cph - release the lump
567}
568
569//
570// jff 10/6/98
571// New code added to speed up calculation of internal blockmap
572// Algorithm is order of nlines*(ncols+nrows) not nlines*ncols*nrows
573//
574
575#define blkshift 7 /* places to shift rel position for cell num */
576#define blkmask ((1<<blkshift)-1)/* mask for rel position within cell */
577#define blkmargin 0 /* size guardband around map used */
578// jff 10/8/98 use guardband>0
579// jff 10/12/98 0 ok with + 1 in rows,cols
580
581typedef struct linelist_t // type used to list lines in each block
582{
583 long num;
584 struct linelist_t *next;
585} linelist_t;
586
587//
588// Subroutine to add a line number to a block list
589// It simply returns if the line is already in the block
590//
591
592static void AddBlockLine
593(
594 linelist_t **lists,
595 int *count,
596 int *done,
597 int blockno,
598 long lineno
599)
600{
601 linelist_t *l;
602
603 if (done[blockno])
604 return;
605
606 l = malloc(sizeof(linelist_t));
607 l->num = lineno;
608 l->next = lists[blockno];
609 lists[blockno] = l;
610 count[blockno]++;
611 done[blockno] = 1;
612}
613
614//
615// Actually construct the blockmap lump from the level data
616//
617// This finds the intersection of each linedef with the column and
618// row lines at the left and bottom of each blockmap cell. It then
619// adds the line to all block lists touching the intersection.
620//
621
622void P_CreateBlockMap()
623{
624 int xorg,yorg; // blockmap origin (lower left)
625 int nrows,ncols; // blockmap dimensions
626 linelist_t **blocklists=NULL; // array of pointers to lists of lines
627 int *blockcount=NULL; // array of counters of line lists
628 int *blockdone=NULL; // array keeping track of blocks/line
629 int NBlocks; // number of cells = nrows*ncols
630 long linetotal=0; // total length of all blocklists
631 int i,j;
632 int map_minx=INT_MAX; // init for map limits search
633 int map_miny=INT_MAX;
634 int map_maxx=INT_MIN;
635 int map_maxy=INT_MIN;
636
637 // scan for map limits, which the blockmap must enclose
638
639 for (i=0;i<numvertexes;i++)
640 {
641 fixed_t t;
642
643 if ((t=vertexes[i].x) < map_minx)
644 map_minx = t;
645 else if (t > map_maxx)
646 map_maxx = t;
647 if ((t=vertexes[i].y) < map_miny)
648 map_miny = t;
649 else if (t > map_maxy)
650 map_maxy = t;
651 }
652 map_minx >>= FRACBITS; // work in map coords, not fixed_t
653 map_maxx >>= FRACBITS;
654 map_miny >>= FRACBITS;
655 map_maxy >>= FRACBITS;
656
657 // set up blockmap area to enclose level plus margin
658
659 xorg = map_minx-blkmargin;
660 yorg = map_miny-blkmargin;
661 ncols = (map_maxx+blkmargin-xorg+1+blkmask)>>blkshift; //jff 10/12/98
662 nrows = (map_maxy+blkmargin-yorg+1+blkmask)>>blkshift; //+1 needed for
663 NBlocks = ncols*nrows; //map exactly 1 cell
664
665 // create the array of pointers on NBlocks to blocklists
666 // also create an array of linelist counts on NBlocks
667 // finally make an array in which we can mark blocks done per line
668
669 // CPhipps - calloc's
670 blocklists = calloc(NBlocks,sizeof(linelist_t *));
671 blockcount = calloc(NBlocks,sizeof(int));
672 blockdone = malloc(NBlocks*sizeof(int));
673
674 // initialize each blocklist, and enter the trailing -1 in all blocklists
675 // note the linked list of lines grows backwards
676
677 for (i=0;i<NBlocks;i++)
678 {
679 blocklists[i] = malloc(sizeof(linelist_t));
680 blocklists[i]->num = -1;
681 blocklists[i]->next = NULL;
682 blockcount[i]++;
683 }
684
685 // For each linedef in the wad, determine all blockmap blocks it touches,
686 // and add the linedef number to the blocklists for those blocks
687
688 for (i=0;i<numlines;i++)
689 {
690 int x1 = lines[i].v1->x>>FRACBITS; // lines[i] map coords
691 int y1 = lines[i].v1->y>>FRACBITS;
692 int x2 = lines[i].v2->x>>FRACBITS;
693 int y2 = lines[i].v2->y>>FRACBITS;
694 int dx = x2-x1;
695 int dy = y2-y1;
696 int vert = !dx; // lines[i] slopetype
697 int horiz = !dy;
698 int spos = (dx^dy) > 0;
699 int sneg = (dx^dy) < 0;
700 int bx,by; // block cell coords
701 int minx = x1>x2? x2 : x1; // extremal lines[i] coords
702 int maxx = x1>x2? x1 : x2;
703 int miny = y1>y2? y2 : y1;
704 int maxy = y1>y2? y1 : y2;
705
706 // no blocks done for this linedef yet
707
708 memset(blockdone,0,NBlocks*sizeof(int));
709
710 // The line always belongs to the blocks containing its endpoints
711
712 bx = (x1-xorg)>>blkshift;
713 by = (y1-yorg)>>blkshift;
714 AddBlockLine(blocklists,blockcount,blockdone,by*ncols+bx,i);
715 bx = (x2-xorg)>>blkshift;
716 by = (y2-yorg)>>blkshift;
717 AddBlockLine(blocklists,blockcount,blockdone,by*ncols+bx,i);
718
719
720 // For each column, see where the line along its left edge, which
721 // it contains, intersects the Linedef i. Add i to each corresponding
722 // blocklist.
723
724 if (!vert) // don't interesect vertical lines with columns
725 {
726 for (j=0;j<ncols;j++)
727 {
728 // intersection of Linedef with x=xorg+(j<<blkshift)
729 // (y-y1)*dx = dy*(x-x1)
730 // y = dy*(x-x1)+y1*dx;
731
732 int x = xorg+(j<<blkshift); // (x,y) is intersection
733 int y = (dy*(x-x1))/dx+y1;
734 int yb = (y-yorg)>>blkshift; // block row number
735 int yp = (y-yorg)&blkmask; // y position within block
736
737 if (yb<0 || yb>nrows-1) // outside blockmap, continue
738 continue;
739
740 if (x<minx || x>maxx) // line doesn't touch column
741 continue;
742
743 // The cell that contains the intersection point is always added
744
745 AddBlockLine(blocklists,blockcount,blockdone,ncols*yb+j,i);
746
747 // if the intersection is at a corner it depends on the slope
748 // (and whether the line extends past the intersection) which
749 // blocks are hit
750
751 if (yp==0) // intersection at a corner
752 {
753 if (sneg) // \ - blocks x,y-, x-,y
754 {
755 if (yb>0 && miny<y)
756 AddBlockLine(blocklists,blockcount,blockdone,ncols*(yb-1)+j,i);
757 if (j>0 && minx<x)
758 AddBlockLine(blocklists,blockcount,blockdone,ncols*yb+j-1,i);
759 }
760 else if (spos) // / - block x-,y-
761 {
762 if (yb>0 && j>0 && minx<x)
763 AddBlockLine(blocklists,blockcount,blockdone,ncols*(yb-1)+j-1,i);
764 }
765 else if (horiz) // - - block x-,y
766 {
767 if (j>0 && minx<x)
768 AddBlockLine(blocklists,blockcount,blockdone,ncols*yb+j-1,i);
769 }
770 }
771 else if (j>0 && minx<x) // else not at corner: x-,y
772 AddBlockLine(blocklists,blockcount,blockdone,ncols*yb+j-1,i);
773 }
774 }
775
776 // For each row, see where the line along its bottom edge, which
777 // it contains, intersects the Linedef i. Add i to all the corresponding
778 // blocklists.
779
780 if (!horiz)
781 {
782 for (j=0;j<nrows;j++)
783 {
784 // intersection of Linedef with y=yorg+(j<<blkshift)
785 // (x,y) on Linedef i satisfies: (y-y1)*dx = dy*(x-x1)
786 // x = dx*(y-y1)/dy+x1;
787
788 int y = yorg+(j<<blkshift); // (x,y) is intersection
789 int x = (dx*(y-y1))/dy+x1;
790 int xb = (x-xorg)>>blkshift; // block column number
791 int xp = (x-xorg)&blkmask; // x position within block
792
793 if (xb<0 || xb>ncols-1) // outside blockmap, continue
794 continue;
795
796 if (y<miny || y>maxy) // line doesn't touch row
797 continue;
798
799 // The cell that contains the intersection point is always added
800
801 AddBlockLine(blocklists,blockcount,blockdone,ncols*j+xb,i);
802
803 // if the intersection is at a corner it depends on the slope
804 // (and whether the line extends past the intersection) which
805 // blocks are hit
806
807 if (xp==0) // intersection at a corner
808 {
809 if (sneg) // \ - blocks x,y-, x-,y
810 {
811 if (j>0 && miny<y)
812 AddBlockLine(blocklists,blockcount,blockdone,ncols*(j-1)+xb,i);
813 if (xb>0 && minx<x)
814 AddBlockLine(blocklists,blockcount,blockdone,ncols*j+xb-1,i);
815 }
816 else if (vert) // | - block x,y-
817 {
818 if (j>0 && miny<y)
819 AddBlockLine(blocklists,blockcount,blockdone,ncols*(j-1)+xb,i);
820 }
821 else if (spos) // / - block x-,y-
822 {
823 if (xb>0 && j>0 && miny<y)
824 AddBlockLine(blocklists,blockcount,blockdone,ncols*(j-1)+xb-1,i);
825 }
826 }
827 else if (j>0 && miny<y) // else not on a corner: x,y-
828 AddBlockLine(blocklists,blockcount,blockdone,ncols*(j-1)+xb,i);
829 }
830 }
831 }
832
833 // Add initial 0 to all blocklists
834 // count the total number of lines (and 0's and -1's)
835
836 memset(blockdone,0,NBlocks*sizeof(int));
837 for (i=0,linetotal=0;i<NBlocks;i++)
838 {
839 AddBlockLine(blocklists,blockcount,blockdone,i,0);
840 linetotal += blockcount[i];
841 }
842
843 // Create the blockmap lump
844
845 blockmaplump = Z_Malloc(sizeof(*blockmaplump) * (4+NBlocks+linetotal),
846 PU_LEVEL, 0);
847 // blockmap header
848
849 blockmaplump[0] = bmaporgx = xorg << FRACBITS;
850 blockmaplump[1] = bmaporgy = yorg << FRACBITS;
851 blockmaplump[2] = bmapwidth = ncols;
852 blockmaplump[3] = bmapheight = nrows;
853
854 // offsets to lists and block lists
855
856 for (i=0;i<NBlocks;i++)
857 {
858 linelist_t *bl = blocklists[i];
859 long offs = blockmaplump[4+i] = // set offset to block's list
860 (i? blockmaplump[4+i-1] : 4+NBlocks) + (i? blockcount[i-1] : 0);
861
862 // add the lines in each block's list to the blockmaplump
863 // delete each list node as we go
864
865 while (bl)
866 {
867 linelist_t *tmp = bl->next;
868 blockmaplump[offs++] = bl->num;
869 free(bl);
870 bl = tmp;
871 }
872 }
873
874 // free all temporary storage
875
876 free (blocklists);
877 free (blockcount);
878 free (blockdone);
879}
880
881// jff 10/6/98
882// End new code added to speed up calculation of internal blockmap
883
884//
885// P_LoadBlockMap
886//
887// killough 3/1/98: substantially modified to work
888// towards removing blockmap limit (a wad limitation)
889//
890// killough 3/30/98: Rewritten to remove blockmap limit,
891// though current algorithm is brute-force and unoptimal.
892//
893
894static void P_LoadBlockMap (int lump)
895{
896 long count;
897
898 if (M_CheckParm("-blockmap") || (count = W_LumpLength(lump)/2) >= 0x10000)
899 P_CreateBlockMap();
900 else
901 {
902 long i;
903 // cph - const*, wad lump handling updated
904 const short *wadblockmaplump = W_CacheLumpNum(lump);
905 blockmaplump = Z_Malloc(sizeof(*blockmaplump) * count, PU_LEVEL, 0);
906
907 // killough 3/1/98: Expand wad blockmap into larger internal one,
908 // by treating all offsets except -1 as unsigned and zero-extending
909 // them. This potentially doubles the size of blockmaps allowed,
910 // because Doom originally considered the offsets as always signed.
911
912 blockmaplump[0] = SHORT(wadblockmaplump[0]);
913 blockmaplump[1] = SHORT(wadblockmaplump[1]);
914 blockmaplump[2] = (long)(SHORT(wadblockmaplump[2])) & 0xffff;
915 blockmaplump[3] = (long)(SHORT(wadblockmaplump[3])) & 0xffff;
916
917 for (i=4 ; i<count ; i++)
918 {
919 short t = SHORT(wadblockmaplump[i]); // killough 3/1/98
920 blockmaplump[i] = t == -1 ? -1l : (long) t & 0xffff;
921 }
922
923 W_UnlockLumpNum(lump); // cph - unlock the lump
924
925 bmaporgx = blockmaplump[0]<<FRACBITS;
926 bmaporgy = blockmaplump[1]<<FRACBITS;
927 bmapwidth = blockmaplump[2];
928 bmapheight = blockmaplump[3];
929 }
930
931 // clear out mobj chains - CPhipps - use calloc
932 blocklinks = Z_Calloc (bmapwidth*bmapheight,sizeof(*blocklinks),PU_LEVEL,0);
933 blockmap = blockmaplump+4;
934}
935
936//
937// P_GroupLines
938// Builds sector line lists and subsector sector numbers.
939// Finds block bounding boxes for sectors.
940//
941// killough 5/3/98: reformatted, cleaned up
942// cph 18/8/99: rewritten to avoid O(numlines * numsectors) section
943// It makes things more complicated, but saves seconds on big levels
944// figgi 09/18/00 -- adapted for gl-nodes
945
946// cph - convenient sub-function
947static void P_AddLineToSector(line_t* li, sector_t* sector)
948{
949 fixed_t *bbox = (void*)sector->blockbox;
950
951 sector->lines[sector->linecount++] = li;
952 M_AddToBox (bbox, li->v1->x, li->v1->y);
953 M_AddToBox (bbox, li->v2->x, li->v2->y);
954}
955
956void P_GroupLines (void)
957{
958 register line_t *li;
959 register sector_t *sector;
960 int i,j, total = numlines;
961
962 // figgi
963 for (i=0 ; i<numsubsectors ; i++)
964 {
965 seg_t *seg = &segs[subsectors[i].firstline];
966 subsectors[i].sector = NULL;
967 for(j=0; j<subsectors[i].numlines; j++)
968 {
969 if(seg->sidedef)
970 {
971 subsectors[i].sector = seg->sidedef->sector;
972 break;
973 }
974 seg++;
975 }
976 if(subsectors[i].sector == NULL)
977 I_Error("P_GroupLines: Subsector a part of no sector!\n");
978 }
979
980 // count number of lines in each sector
981 for (i=0,li=lines; i<numlines; i++, li++)
982 {
983 li->frontsector->linecount++;
984 if (li->backsector && li->backsector != li->frontsector)
985 {
986 li->backsector->linecount++;
987 total++;
988 }
989 }
990
991 { // allocate line tables for each sector
992 line_t **linebuffer = Z_Malloc(total*sizeof(line_t *), PU_LEVEL, 0);
993
994 for (i=0, sector = sectors; i<numsectors; i++, sector++)
995 {
996 sector->lines = linebuffer;
997 linebuffer += sector->linecount;
998 sector->linecount = 0;
999 M_ClearBox(sector->blockbox);
1000 }
1001 }
1002
1003 // Enter those lines
1004 for (i=0,li=lines; i<numlines; i++, li++)
1005 {
1006 P_AddLineToSector(li, li->frontsector);
1007 if (li->backsector && li->backsector != li->frontsector)
1008 P_AddLineToSector(li, li->backsector);
1009 }
1010
1011 for (i=0, sector = sectors; i<numsectors; i++, sector++)
1012 {
1013 fixed_t *bbox = (void*)sector->blockbox; // cph - For convenience, so
1014 // I can sue the old code unchanged
1015 int block;
1016
1017 // set the degenmobj_t to the middle of the bounding box
1018 sector->soundorg.x = (bbox[BOXRIGHT]+bbox[BOXLEFT])/2;
1019 sector->soundorg.y = (bbox[BOXTOP]+bbox[BOXBOTTOM])/2;
1020
1021 // adjust bounding box to map blocks
1022 block = (bbox[BOXTOP]-bmaporgy+MAXRADIUS)>>MAPBLOCKSHIFT;
1023 block = block >= bmapheight ? bmapheight-1 : block;
1024 sector->blockbox[BOXTOP]=block;
1025
1026 block = (bbox[BOXBOTTOM]-bmaporgy-MAXRADIUS)>>MAPBLOCKSHIFT;
1027 block = block < 0 ? 0 : block;
1028 sector->blockbox[BOXBOTTOM]=block;
1029
1030 block = (bbox[BOXRIGHT]-bmaporgx+MAXRADIUS)>>MAPBLOCKSHIFT;
1031 block = block >= bmapwidth ? bmapwidth-1 : block;
1032 sector->blockbox[BOXRIGHT]=block;
1033
1034 block = (bbox[BOXLEFT]-bmaporgx-MAXRADIUS)>>MAPBLOCKSHIFT;
1035 block = block < 0 ? 0 : block;
1036 sector->blockbox[BOXLEFT]=block;
1037 }
1038
1039}
1040
1041//
1042// killough 10/98
1043//
1044// Remove slime trails.
1045//
1046// Slime trails are inherent to Doom's coordinate system -- i.e. there is
1047// nothing that a node builder can do to prevent slime trails ALL of the time,
1048// because it's a product of the integer coodinate system, and just because
1049// two lines pass through exact integer coordinates, doesn't necessarily mean
1050// that they will intersect at integer coordinates. Thus we must allow for
1051// fractional coordinates if we are to be able to split segs with node lines,
1052// as a node builder must do when creating a BSP tree.
1053//
1054// A wad file does not allow fractional coordinates, so node builders are out
1055// of luck except that they can try to limit the number of splits (they might
1056// also be able to detect the degree of roundoff error and try to avoid splits
1057// with a high degree of roundoff error). But we can use fractional coordinates
1058// here, inside the engine. It's like the difference between square inches and
1059// square miles, in terms of granularity.
1060//
1061// For each vertex of every seg, check to see whether it's also a vertex of
1062// the linedef associated with the seg (i.e, it's an endpoint). If it's not
1063// an endpoint, and it wasn't already moved, move the vertex towards the
1064// linedef by projecting it using the law of cosines. Formula:
1065//
1066// 2 2 2 2
1067// dx x0 + dy x1 + dx dy (y0 - y1) dy y0 + dx y1 + dx dy (x0 - x1)
1068// {---------------------------------, ---------------------------------}
1069// 2 2 2 2
1070// dx + dy dx + dy
1071//
1072// (x0,y0) is the vertex being moved, and (x1,y1)-(x1+dx,y1+dy) is the
1073// reference linedef.
1074//
1075// Segs corresponding to orthogonal linedefs (exactly vertical or horizontal
1076// linedefs), which comprise at least half of all linedefs in most wads, don't
1077// need to be considered, because they almost never contribute to slime trails
1078// (because then any roundoff error is parallel to the linedef, which doesn't
1079// cause slime). Skipping simple orthogonal lines lets the code finish quicker.
1080//
1081// Please note: This section of code is not interchangable with TeamTNT's
1082// code which attempts to fix the same problem.
1083//
1084// Firelines (TM) is a Rezistered Trademark of MBF Productions
1085//
1086
1087void P_RemoveSlimeTrails(void) // killough 10/98
1088{
1089 byte *hit = calloc(1, numvertexes); // Hitlist for vertices
1090 int i;
1091 for (i=0; i<numsegs; i++) // Go through each seg
1092 {
1093 const line_t *l;
1094
1095 if (segs[i].miniseg == true) //figgi -- skip minisegs
1096 return;
1097
1098 l = segs[i].linedef; // The parent linedef
1099 if (l->dx && l->dy) // We can ignore orthogonal lines
1100 {
1101 vertex_t *v = segs[i].v1;
1102 do
1103 if (!hit[v - vertexes]) // If we haven't processed vertex
1104 {
1105 hit[v - vertexes] = 1; // Mark this vertex as processed
1106 if (v != l->v1 && v != l->v2) // Exclude endpoints of linedefs
1107 { // Project the vertex back onto the parent linedef
1108 int_64_t dx2 = (l->dx >> FRACBITS) * (l->dx >> FRACBITS);
1109 int_64_t dy2 = (l->dy >> FRACBITS) * (l->dy >> FRACBITS);
1110 int_64_t dxy = (l->dx >> FRACBITS) * (l->dy >> FRACBITS);
1111 int_64_t s = dx2 + dy2;
1112 int x0 = v->x, y0 = v->y, x1 = l->v1->x, y1 = l->v1->y;
1113 v->x = (int)((dx2 * x0 + dy2 * x1 + dxy * (y0 - y1)) / s);
1114 v->y = (int)((dy2 * y0 + dx2 * y1 + dxy * (x0 - x1)) / s);
1115 }
1116 } // Obsfucated C contest entry: :)
1117 while ((v != segs[i].v2) && (v = segs[i].v2));
1118 }
1119 }
1120 free(hit);
1121}
1122
1123//
1124// P_SetupLevel
1125//
1126// killough 5/3/98: reformatted, cleaned up
1127
1128void P_SetupLevel(int episode, int map, int playermask, skill_t skill)
1129{
1130 (void)playermask;
1131 (void)skill;
1132 int i;
1133 char lumpname[9];
1134 int lumpnum;
1135
1136
1137 totalkills = totalitems = totalsecret = wminfo.maxfrags = 0;
1138 wminfo.partime = 180;
1139
1140 for (i=0; i<MAXPLAYERS; i++)
1141 players[i].killcount = players[i].secretcount = players[i].itemcount = 0;
1142
1143 // Initial height of PointOfView will be set by player think.
1144 players[consoleplayer].viewz = 1;
1145
1146 // Make sure all sounds are stopped before Z_FreeTags.
1147 S_Start();
1148
1149 Z_FreeTags(PU_LEVEL, PU_PURGELEVEL-1);
1150 if (rejectlump != -1) { // cph - unlock the reject table
1151 W_UnlockLumpNum(rejectlump);
1152 rejectlump = -1;
1153 }
1154
1155 P_InitThinkers();
1156
1157 // if working with a devlopment map, reload it
1158 // W_Reload (); killough 1/31/98: W_Reload obsolete
1159
1160 // find map name
1161 if (gamemode == commercial)
1162 {
1163 if (map<10)
1164 snprintf (lumpname,sizeof(lumpname),"map0%d", map);
1165 else
1166 snprintf (lumpname,sizeof(lumpname),"map%d", map);
1167 }
1168 else
1169 {
1170 snprintf(lumpname,sizeof(lumpname), "E%dM%d", episode, map); // killough 1/24/98: simplify
1171 }
1172
1173 lumpnum = W_GetNumForName(lumpname);
1174
1175 leveltime = 0;
1176
1177 // note: most of this ordering is important
1178
1179 // killough 3/1/98: P_LoadBlockMap call moved down to below
1180 // killough 4/4/98: split load of sidedefs into two parts,
1181 // to allow texture names to be used in special linedefs
1182
1183 usingGLNodes = false;
1184 P_LoadVertexes (lumpnum+ML_VERTEXES);
1185 P_LoadSectors (lumpnum+ML_SECTORS);
1186 P_LoadSideDefs (lumpnum+ML_SIDEDEFS);
1187 P_LoadLineDefs (lumpnum+ML_LINEDEFS);
1188 P_LoadSideDefs2 (lumpnum+ML_SIDEDEFS);
1189 P_LoadLineDefs2 (lumpnum+ML_LINEDEFS);
1190 P_LoadBlockMap (lumpnum+ML_BLOCKMAP);
1191
1192 P_LoadSubsectors(lumpnum + ML_SSECTORS);
1193 P_LoadNodes(lumpnum + ML_NODES);
1194 P_LoadSegs(lumpnum + ML_SEGS);
1195
1196 if (rejectlump != -1)
1197 W_UnlockLumpNum(rejectlump);
1198 rejectlump = lumpnum+ML_REJECT;
1199 {
1200 int rjlen = W_LumpLength(rejectlump);
1201 int rjreq = (numsectors*numsectors+7)/8;
1202 if (rjlen < rjreq) {
1203 printf("P_SetupLevel: REJECT too short (%d<%d) - padded\n",rjlen,rjreq);
1204 rejectmatrix = W_CacheLumpNumPadded(rejectlump,rjreq,0xff);
1205 } else {
1206 rejectmatrix = W_CacheLumpNum(rejectlump);
1207 }
1208 }
1209 P_GroupLines();
1210
1211 P_RemoveSlimeTrails(); // killough 10/98: remove slime trails from wad
1212
1213 // Note: you don't need to clear player queue slots --
1214 // a much simpler fix is in g_game.c -- killough 10/98
1215
1216 bodyqueslot = 0;
1217 deathmatch_p = deathmatchstarts;
1218 P_MapStart();
1219 P_LoadThings(lumpnum+ML_THINGS);
1220
1221 // if deathmatch, randomly spawn the active players
1222 if (deathmatch)
1223 for (i=0; i<MAXPLAYERS; i++)
1224 if (playeringame[i])
1225 {
1226 players[i].mo = NULL;
1227 G_DeathMatchSpawnPlayer(i);
1228 }
1229
1230 // killough 3/26/98: Spawn icon landings:
1231 if (gamemode==commercial)
1232 P_SpawnBrainTargets();
1233
1234 // clear special respawning que
1235 iquehead = iquetail = 0;
1236
1237 // set up world state
1238 P_SpawnSpecials();
1239
1240 P_MapEnd();
1241
1242 // preload graphics
1243 if (precache)
1244 R_PrecacheLevel();
1245}
1246
1247//
1248// P_Init
1249//
1250void P_Init (void)
1251{
1252 P_InitSwitchList();
1253 P_InitPicAnims();
1254 R_InitSprites(sprnames);
1255}
diff --git a/apps/plugins/doom/p_setup.h b/apps/plugins/doom/p_setup.h
new file mode 100644
index 0000000000..7d334576bc
--- /dev/null
+++ b/apps/plugins/doom/p_setup.h
@@ -0,0 +1,55 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION:
28 * Setup a game, startup stuff.
29 *
30 *-----------------------------------------------------------------------------*/
31
32#ifndef __P_SETUP__
33#define __P_SETUP__
34
35#include "p_mobj.h"
36
37#ifdef __GNUG__
38#pragma interface
39#endif
40
41void P_SetupLevel(int episode, int map, int playermask, skill_t skill);
42void P_Init(void); /* Called by startup code. */
43
44extern const byte *rejectmatrix; /* for fast sight rejection - cph - const* */
45
46/* killough 3/1/98: change blockmap from "short" to "long" offsets: */
47extern long *blockmaplump; /* offsets in blockmap are from here */
48extern long *blockmap;
49extern int bmapwidth;
50extern int bmapheight; /* in mapblocks */
51extern fixed_t bmaporgx;
52extern fixed_t bmaporgy; /* origin of block map */
53extern mobj_t **blocklinks; /* for thing chains */
54
55#endif
diff --git a/apps/plugins/doom/p_sight.c b/apps/plugins/doom/p_sight.c
new file mode 100644
index 0000000000..737fcf6be9
--- /dev/null
+++ b/apps/plugins/doom/p_sight.c
@@ -0,0 +1,346 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION:
28 * LineOfSight/Visibility checks, uses REJECT Lookup Table.
29 *
30 *-----------------------------------------------------------------------------*/
31
32#include "doomstat.h"
33#include "r_main.h"
34#include "p_maputl.h"
35#include "p_setup.h"
36#include "m_bbox.h"
37#include "rockmacros.h"
38//
39// P_CheckSight
40//
41// killough 4/19/98:
42// Convert LOS info to struct for reentrancy and efficiency of data locality
43
44typedef struct {
45 fixed_t sightzstart, t2x, t2y; // eye z of looker
46 divline_t strace; // from t1 to t2
47 fixed_t topslope, bottomslope; // slopes to top and bottom of target
48 fixed_t bbox[4];
49 fixed_t maxz,minz; // cph - z optimisations for 2sided lines
50} los_t;
51
52static los_t los; // cph - made static
53
54//
55// P_DivlineSide
56// Returns side 0 (front), 1 (back), or 2 (on).
57//
58// killough 4/19/98: made static, cleaned up
59
60inline static int P_DivlineSide(fixed_t x, fixed_t y, const divline_t *node)
61{
62 fixed_t left, right;
63 return
64 !node->dx ? x == node->x ? 2 : x <= node->x ? node->dy > 0 : node->dy < 0 :
65 !node->dy ? x == node->y ? 2 : y <= node->y ? node->dx < 0 : node->dx > 0 :
66 (right = ((y - node->y) >> FRACBITS) * (node->dx >> FRACBITS)) <
67 (left = ((x - node->x) >> FRACBITS) * (node->dy >> FRACBITS)) ? 0 :
68 right == left ? 2 : 1;
69}
70
71//
72// P_InterceptVector2
73// Returns the fractional intercept point
74// along the first divline.
75//
76// killough 4/19/98: made static, cleaned up
77
78static fixed_t P_InterceptVector2(const divline_t *v2, const divline_t *v1)
79{
80 fixed_t den;
81 return (den = FixedMul(v1->dy>>8, v2->dx) - FixedMul(v1->dx>>8, v2->dy)) ?
82 FixedDiv(FixedMul((v1->x - v2->x)>>8, v1->dy) +
83 FixedMul((v2->y - v1->y)>>8, v1->dx), den) : 0;
84}
85
86//
87// P_CrossSubsector
88// Returns true
89// if strace crosses the given subsector successfully.
90//
91// killough 4/19/98: made static and cleaned up
92
93static boolean P_CrossSubsector(int num)
94{
95 seg_t *seg = segs + subsectors[num].firstline;
96 int count;
97 fixed_t opentop = 0, openbottom = 0;
98 const sector_t *front = NULL, *back = NULL;
99
100#ifdef RANGECHECK
101 if (num >= numsubsectors)
102 I_Error("P_CrossSubsector: ss %i with numss = %i", num, numsubsectors);
103#endif
104
105 for (count = subsectors[num].numlines; --count >= 0; seg++) { // check lines
106 line_t *line = seg->linedef;
107 divline_t divl;
108
109 if(!line) // figgi -- skip minisegs
110 continue;
111
112 // allready checked other side?
113 if (line->validcount == validcount)
114 continue;
115
116 line->validcount = validcount;
117
118 /* OPTIMIZE: killough 4/20/98: Added quick bounding-box rejection test
119 * cph - this is causing demo desyncs on original Doom demos.
120 * Who knows why. Exclude test for those.
121 */
122 if (!demo_compatibility)
123 if (line->bbox[BOXLEFT ] > los.bbox[BOXRIGHT ] ||
124 line->bbox[BOXRIGHT ] < los.bbox[BOXLEFT ] ||
125 line->bbox[BOXBOTTOM] > los.bbox[BOXTOP ] ||
126 line->bbox[BOXTOP] < los.bbox[BOXBOTTOM])
127 continue;
128
129 // cph - do what we can before forced to check intersection
130 if (line->flags & ML_TWOSIDED) {
131
132 // no wall to block sight with?
133 if ((front = seg->frontsector)->floorheight ==
134 (back = seg->backsector)->floorheight &&
135 front->ceilingheight == back->ceilingheight)
136 continue;
137
138 // possible occluder
139 // because of ceiling height differences
140 opentop = front->ceilingheight < back->ceilingheight ?
141 front->ceilingheight : back->ceilingheight ;
142
143 // because of floor height differences
144 openbottom = front->floorheight > back->floorheight ?
145 front->floorheight : back->floorheight ;
146
147 // cph - reject if does not intrude in the z-space of the possible LOS
148 if ((opentop >= los.maxz) && (openbottom <= los.minz))
149 continue;
150 }
151
152 { // Forget this line if it doesn't cross the line of sight
153 const vertex_t *v1,*v2;
154
155 v1 = line->v1;
156 v2 = line->v2;
157
158 if (P_DivlineSide(v1->x, v1->y, &los.strace) ==
159 P_DivlineSide(v2->x, v2->y, &los.strace))
160 continue;
161
162 divl.dx = v2->x - (divl.x = v1->x);
163 divl.dy = v2->y - (divl.y = v1->y);
164
165 // line isn't crossed?
166 if (P_DivlineSide(los.strace.x, los.strace.y, &divl) ==
167 P_DivlineSide(los.t2x, los.t2y, &divl))
168 continue;
169 }
170
171 // cph - if bottom >= top or top < minz or bottom > maxz then it must be
172 // solid wrt this LOS
173 if (!(line->flags & ML_TWOSIDED) || (openbottom >= opentop) ||
174 (opentop < los.minz) || (openbottom > los.maxz))
175 return false;
176
177 { // crosses a two sided line
178 fixed_t frac = P_InterceptVector2(&los.strace, &divl);
179
180 if (front->floorheight != back->floorheight)
181 {
182 fixed_t slope = FixedDiv(openbottom - los.sightzstart , frac);
183 if (slope > los.bottomslope)
184 los.bottomslope = slope;
185 }
186
187 if (front->ceilingheight != back->ceilingheight)
188 {
189 fixed_t slope = FixedDiv(opentop - los.sightzstart , frac);
190 if (slope < los.topslope)
191 los.topslope = slope;
192 }
193
194 if (los.topslope <= los.bottomslope)
195 return false; // stop
196 }
197 }
198 // passed the subsector ok
199 return true;
200}
201
202//
203// P_CrossBSPNode
204// Returns true
205// if strace crosses the given node successfully.
206//
207// killough 4/20/98: rewritten to remove tail recursion, clean up, and optimize
208// cph - Made to use R_PointOnSide instead of P_DivlineSide, since the latter
209// could return 2 which was ambigous, and the former is
210// better optimised; also removes two casts :-)
211
212static boolean P_CrossBSPNode_LxDoom(int bspnum)
213{
214 while (!(bspnum & NF_SUBSECTOR))
215 {
216 register const node_t *bsp = nodes + bspnum;
217 int side,side2;
218 side = R_PointOnSide(los.strace.x, los.strace.y, bsp);
219 side2 = R_PointOnSide(los.t2x, los.t2y, bsp);
220 if (side == side2)
221 bspnum = bsp->children[side]; // doesn't touch the other side
222 else // the partition plane is crossed here
223 if (!P_CrossBSPNode_LxDoom(bsp->children[side]))
224 return 0; // cross the starting side
225 else
226 bspnum = bsp->children[side^1]; // cross the ending side
227 }
228 return P_CrossSubsector(bspnum == -1 ? 0 : bspnum & ~NF_SUBSECTOR);
229}
230
231static boolean P_CrossBSPNode_PrBoom(int bspnum)
232{
233 while (!(bspnum & NF_SUBSECTOR))
234 {
235 register const node_t *bsp = nodes + bspnum;
236 int side,side2;
237 side = P_DivlineSide(los.strace.x,los.strace.y,(divline_t *)bsp)&1;
238 side2= P_DivlineSide(los.t2x, los.t2y, (divline_t *) bsp);
239 if (side == side2)
240 bspnum = bsp->children[side]; // doesn't touch the other side
241 else // the partition plane is crossed here
242 if (!P_CrossBSPNode_PrBoom(bsp->children[side]))
243 return 0; // cross the starting side
244 else
245 bspnum = bsp->children[side^1]; // cross the ending side
246 }
247 return P_CrossSubsector(bspnum == -1 ? 0 : bspnum & ~NF_SUBSECTOR);
248}
249
250/* proff - Moved the compatibility check outside the functions
251 * this gives a slight speedup
252 */
253static boolean P_CrossBSPNode(int bspnum)
254{
255 /* cph - LxDoom used some R_* funcs here */
256 if (compatibility_level == lxdoom_1_compatibility)
257 return P_CrossBSPNode_LxDoom(bspnum);
258 else
259 return P_CrossBSPNode_PrBoom(bspnum);
260}
261
262//
263// P_CheckSight
264// Returns true
265// if a straight line between t1 and t2 is unobstructed.
266// Uses REJECT.
267//
268// killough 4/20/98: cleaned up, made to use new LOS struct
269
270boolean P_CheckSight(mobj_t *t1, mobj_t *t2)
271{
272 const sector_t *s1 = t1->subsector->sector;
273 const sector_t *s2 = t2->subsector->sector;
274 int pnum = (s1-sectors)*numsectors + (s2-sectors);
275
276 // First check for trivial rejection.
277 // Determine subsector entries in REJECT table.
278 //
279 // Check in REJECT table.
280
281 if (rejectmatrix[pnum>>3] & (1 << (pnum&7))) // can't possibly be connected
282 return false;
283
284 // killough 4/19/98: make fake floors and ceilings block monster view
285
286 if ((s1->heightsec != -1 &&
287 ((t1->z + t1->height <= sectors[s1->heightsec].floorheight &&
288 t2->z >= sectors[s1->heightsec].floorheight) ||
289 (t1->z >= sectors[s1->heightsec].ceilingheight &&
290 t2->z + t1->height <= sectors[s1->heightsec].ceilingheight)))
291 ||
292 (s2->heightsec != -1 &&
293 ((t2->z + t2->height <= sectors[s2->heightsec].floorheight &&
294 t1->z >= sectors[s2->heightsec].floorheight) ||
295 (t2->z >= sectors[s2->heightsec].ceilingheight &&
296 t1->z + t2->height <= sectors[s2->heightsec].ceilingheight))))
297 return false;
298
299 /* killough 11/98: shortcut for melee situations
300 * same subsector? obviously visible
301 * cph - compatibility optioned for demo sync, cf HR06-UV.LMP */
302 if ((t1->subsector == t2->subsector) &&
303 (compatibility_level >= mbf_compatibility))
304 return true;
305
306 // An unobstructed LOS is possible.
307 // Now look from eyes of t1 to any part of t2.
308
309 validcount++;
310
311 los.topslope = (los.bottomslope = t2->z - (los.sightzstart =
312 t1->z + t1->height -
313 (t1->height>>2))) + t2->height;
314 los.strace.dx = (los.t2x = t2->x) - (los.strace.x = t1->x);
315 los.strace.dy = (los.t2y = t2->y) - (los.strace.y = t1->y);
316
317 if (t1->x > t2->x)
318 los.bbox[BOXRIGHT] = t1->x, los.bbox[BOXLEFT] = t2->x;
319 else
320 los.bbox[BOXRIGHT] = t2->x, los.bbox[BOXLEFT] = t1->x;
321
322 if (t1->y > t2->y)
323 los.bbox[BOXTOP] = t1->y, los.bbox[BOXBOTTOM] = t2->y;
324 else
325 los.bbox[BOXTOP] = t2->y, los.bbox[BOXBOTTOM] = t1->y;
326
327 /* cph - calculate min and max z of the potential line of sight
328 * For old demos, we disable this optimisation by setting them to
329 * the extremes */
330 switch (compatibility_level) {
331 case lxdoom_1_compatibility:
332 if (los.sightzstart < t2->z) {
333 los.maxz = t2->z + t2->height; los.minz = los.sightzstart;
334 } else if (los.sightzstart > t2->z + t2->height) {
335 los.maxz = los.sightzstart; los.minz = t2->z;
336 } else {
337 los.maxz = t2->z + t2->height; los.minz = t2->z;
338 }
339 break;
340 default:
341 los.maxz = INT_MAX; los.minz = INT_MIN;
342 }
343
344 // the head node is the last node output
345 return P_CrossBSPNode(numnodes-1);
346}
diff --git a/apps/plugins/doom/p_spec.c b/apps/plugins/doom/p_spec.c
new file mode 100644
index 0000000000..2876b7f4e5
--- /dev/null
+++ b/apps/plugins/doom/p_spec.c
@@ -0,0 +1,3255 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION:
28 * -Loads and initializes texture and flat animation sequences
29 * -Implements utility functions for all linedef/sector special handlers
30 * -Dispatches walkover and gun line triggers
31 * -Initializes and implements special sector types
32 * -Implements donut linedef triggers
33 * -Initializes and implements BOOM linedef triggers for
34 * Scrollers/Conveyors
35 * Friction
36 * Wind/Current
37 *
38 *-----------------------------------------------------------------------------*/
39
40#include "doomstat.h"
41#include "p_spec.h"
42#include "p_tick.h"
43#include "p_setup.h"
44#include "m_random.h"
45#include "d_englsh.h"
46#include "m_argv.h"
47#include "w_wad.h"
48#include "r_main.h"
49#include "p_maputl.h"
50#include "p_map.h"
51#include "g_game.h"
52#include "p_inter.h"
53#include "m_swap.h"
54#include "s_sound.h"
55#include "sounds.h"
56#include "m_bbox.h" // phares 3/20/98
57//#include "d_deh.h"
58#include "r_plane.h"
59#include "i_system.h"
60#include "rockmacros.h"
61//
62// Animating textures and planes
63// There is another anim_t used in wi_stuff, unrelated.
64//
65typedef struct
66{
67 boolean istexture;
68 int picnum;
69 int basepic;
70 int numpics;
71 int speed;
72
73} anim_t;
74
75//
76// source animation definition
77//
78//
79#ifdef _MSC_VER // proff: This is the same as __attribute__ ((packed)) in GNUC
80#pragma pack(push)
81#pragma pack(1)
82#endif //_MSC_VER
83
84#if defined(__MWERKS__)
85#pragma options align=packed
86#endif
87
88typedef struct
89{
90 signed char istexture; //jff 3/23/98 make char for comparison // cph - make signed
91 char endname[9]; // if false, it is a flat
92 char startname[9];
93 int speed;
94} PACKEDATTR animdef_t; //jff 3/23/98 pack to read from memory
95
96#define MAXANIMS 32 // no longer a strict limit -- killough
97
98static anim_t* lastanim;
99static anim_t* anims; // new structure w/o limits -- killough
100static size_t maxanims;
101
102// killough 3/7/98: Initialize generalized scrolling
103static void P_SpawnScrollers(void);
104
105static void P_SpawnFriction(void); // phares 3/16/98
106static void P_SpawnPushers(void); // phares 3/20/98
107
108extern int allow_pushers;
109extern int variable_friction; // phares 3/20/98
110
111//
112// P_InitPicAnims
113//
114// Load the table of animation definitions, checking for existence of
115// the start and end of each frame. If the start doesn't exist the sequence
116// is skipped, if the last doesn't exist, BOOM exits.
117//
118// Wall/Flat animation sequences, defined by name of first and last frame,
119// The full animation sequence is given using all lumps between the start
120// and end entry, in the order found in the WAD file.
121//
122// This routine modified to read its data from a predefined lump or
123// PWAD lump called ANIMATED rather than a static table in this module to
124// allow wad designers to insert or modify animation sequences.
125//
126// Lump format is an array of byte packed animdef_t structures, terminated
127// by a structure with istexture == -1. The lump can be generated from a
128// text source file using SWANTBLS.EXE, distributed with the BOOM utils.
129// The standard list of switches and animations is contained in the example
130// source text file DEFSWANI.DAT also in the BOOM util distribution.
131//
132//
133void P_InitPicAnims (void)
134{
135 int i;
136 const animdef_t *animdefs; //jff 3/23/98 pointer to animation lump
137 int lump = W_GetNumForName("ANIMATED"); // cph - new wad lump handling
138 // Init animation
139
140 //jff 3/23/98 read from predefined or wad lump instead of table
141 animdefs = (const animdef_t *)W_CacheLumpNum(lump);
142
143 lastanim = anims;
144 for (i=0 ; animdefs[i].istexture != -1 ; i++)
145 {
146 // 1/11/98 killough -- removed limit by array-doubling
147 if (lastanim >= anims + maxanims)
148 {
149 size_t newmax = maxanims ? maxanims*2 : MAXANIMS;
150 anims = realloc(anims, newmax*sizeof(*anims)); // killough
151 lastanim = anims + maxanims;
152 maxanims = newmax;
153 }
154
155 if (animdefs[i].istexture)
156 {
157 // different episode ?
158 if (R_CheckTextureNumForName(animdefs[i].startname) == -1)
159 continue;
160
161 lastanim->picnum = R_TextureNumForName (animdefs[i].endname);
162 lastanim->basepic = R_TextureNumForName (animdefs[i].startname);
163 }
164 else
165 {
166 if ((W_CheckNumForName)(animdefs[i].startname, ns_flats) == -1) // killough 4/17/98
167 continue;
168
169 lastanim->picnum = R_FlatNumForName (animdefs[i].endname);
170 lastanim->basepic = R_FlatNumForName (animdefs[i].startname);
171 }
172
173 lastanim->istexture = animdefs[i].istexture;
174 lastanim->numpics = lastanim->picnum - lastanim->basepic + 1;
175
176 if (lastanim->numpics < 2)
177 I_Error ("P_InitPicAnims: bad cycle from %s to %s",
178 animdefs[i].startname,
179 animdefs[i].endname);
180
181 lastanim->speed = LONG(animdefs[i].speed); // killough 5/5/98: add LONG()
182 lastanim++;
183 }
184 W_UnlockLumpNum(lump);
185}
186
187///////////////////////////////////////////////////////////////
188//
189// Linedef and Sector Special Implementation Utility Functions
190//
191///////////////////////////////////////////////////////////////
192
193//
194// getSide()
195//
196// Will return a side_t*
197// given the number of the current sector,
198// the line number, and the side (0/1) that you want.
199//
200// Note: if side=1 is specified, it must exist or results undefined
201//
202side_t* getSide
203( int currentSector,
204 int line,
205 int side )
206{
207 return &sides[ (sectors[currentSector].lines[line])->sidenum[side] ];
208}
209
210
211//
212// getSector()
213//
214// Will return a sector_t*
215// given the number of the current sector,
216// the line number and the side (0/1) that you want.
217//
218// Note: if side=1 is specified, it must exist or results undefined
219//
220sector_t* getSector
221( int currentSector,
222 int line,
223 int side )
224{
225 return sides[ (sectors[currentSector].lines[line])->sidenum[side] ].sector;
226}
227
228
229//
230// twoSided()
231//
232// Given the sector number and the line number,
233// it will tell you whether the line is two-sided or not.
234//
235// modified to return actual two-sidedness rather than presence
236// of 2S flag unless compatibility optioned
237//
238int twoSided
239( int sector,
240 int line )
241{
242 //jff 1/26/98 return what is actually needed, whether the line
243 //has two sidedefs, rather than whether the 2S flag is set
244
245 return comp[comp_model] ?
246 (sectors[sector].lines[line])->flags & ML_TWOSIDED
247 :
248 (sectors[sector].lines[line])->sidenum[1] != -1;
249}
250
251
252//
253// getNextSector()
254//
255// Return sector_t * of sector next to current across line.
256//
257// Note: returns NULL if not two-sided line, or both sides refer to sector
258//
259sector_t* getNextSector
260( line_t* line,
261 sector_t* sec )
262{
263 //jff 1/26/98 check unneeded since line->backsector already
264 //returns NULL if the line is not two sided, and does so from
265 //the actual two-sidedness of the line, rather than its 2S flag
266
267 if (comp[comp_model])
268 {
269 if (!(line->flags & ML_TWOSIDED))
270 return NULL;
271 }
272
273 if (line->frontsector == sec) {
274 if (comp[comp_model] || line->backsector!=sec)
275 return line->backsector; //jff 5/3/98 don't retn sec unless compatibility
276 else // fixes an intra-sector line breaking functions
277 return NULL; // like floor->highest floor
278 }
279 return line->frontsector;
280}
281
282
283//
284// P_FindLowestFloorSurrounding()
285//
286// Returns the fixed point value of the lowest floor height
287// in the sector passed or its surrounding sectors.
288//
289fixed_t P_FindLowestFloorSurrounding(sector_t* sec)
290{
291 int i;
292 line_t* check;
293 sector_t* other;
294 fixed_t floor = sec->floorheight;
295
296 for (i=0 ;i < sec->linecount ; i++)
297 {
298 check = sec->lines[i];
299 other = getNextSector(check,sec);
300
301 if (!other)
302 continue;
303
304 if (other->floorheight < floor)
305 floor = other->floorheight;
306 }
307 return floor;
308}
309
310
311//
312// P_FindHighestFloorSurrounding()
313//
314// Passed a sector, returns the fixed point value of the largest
315// floor height in the surrounding sectors, not including that passed
316//
317// NOTE: if no surrounding sector exists -32000*FRACUINT is returned
318// if compatibility then -500*FRACUNIT is the smallest return possible
319//
320fixed_t P_FindHighestFloorSurrounding(sector_t *sec)
321{
322 int i;
323 line_t* check;
324 sector_t* other;
325 fixed_t floor = -500*FRACUNIT;
326
327 //jff 1/26/98 Fix initial value for floor to not act differently
328 //in sections of wad that are below -500 units
329 if (!comp[comp_model]) /* jff 3/12/98 avoid ovf */
330 floor = -32000*FRACUNIT; // in height calculations
331
332 for (i=0 ;i < sec->linecount ; i++)
333 {
334 check = sec->lines[i];
335 other = getNextSector(check,sec);
336
337 if (!other)
338 continue;
339
340 if (other->floorheight > floor)
341 floor = other->floorheight;
342 }
343 return floor;
344}
345
346
347//
348// P_FindNextHighestFloor()
349//
350// Passed a sector and a floor height, returns the fixed point value
351// of the smallest floor height in a surrounding sector larger than
352// the floor height passed. If no such height exists the floorheight
353// passed is returned.
354//
355// Rewritten by Lee Killough to avoid fixed array and to be faster
356//
357fixed_t P_FindNextHighestFloor(sector_t *sec, int currentheight)
358{
359 sector_t *other;
360 int i;
361
362 for (i=0 ;i < sec->linecount ; i++)
363 if ((other = getNextSector(sec->lines[i],sec)) &&
364 other->floorheight > currentheight)
365 {
366 int height = other->floorheight;
367 while (++i < sec->linecount)
368 if ((other = getNextSector(sec->lines[i],sec)) &&
369 other->floorheight < height &&
370 other->floorheight > currentheight)
371 height = other->floorheight;
372 return height;
373 }
374 return currentheight;
375}
376
377
378//
379// P_FindNextLowestFloor()
380//
381// Passed a sector and a floor height, returns the fixed point value
382// of the largest floor height in a surrounding sector smaller than
383// the floor height passed. If no such height exists the floorheight
384// passed is returned.
385//
386// jff 02/03/98 Twiddled Lee's P_FindNextHighestFloor to make this
387//
388fixed_t P_FindNextLowestFloor(sector_t *sec, int currentheight)
389{
390 sector_t *other;
391 int i;
392
393 for (i=0 ;i < sec->linecount ; i++)
394 if ((other = getNextSector(sec->lines[i],sec)) &&
395 other->floorheight < currentheight)
396 {
397 int height = other->floorheight;
398 while (++i < sec->linecount)
399 if ((other = getNextSector(sec->lines[i],sec)) &&
400 other->floorheight > height &&
401 other->floorheight < currentheight)
402 height = other->floorheight;
403 return height;
404 }
405 return currentheight;
406}
407
408
409//
410// P_FindNextLowestCeiling()
411//
412// Passed a sector and a ceiling height, returns the fixed point value
413// of the largest ceiling height in a surrounding sector smaller than
414// the ceiling height passed. If no such height exists the ceiling height
415// passed is returned.
416//
417// jff 02/03/98 Twiddled Lee's P_FindNextHighestFloor to make this
418//
419fixed_t P_FindNextLowestCeiling(sector_t *sec, int currentheight)
420{
421 sector_t *other;
422 int i;
423
424 for (i=0 ;i < sec->linecount ; i++)
425 if ((other = getNextSector(sec->lines[i],sec)) &&
426 other->ceilingheight < currentheight)
427 {
428 int height = other->ceilingheight;
429 while (++i < sec->linecount)
430 if ((other = getNextSector(sec->lines[i],sec)) &&
431 other->ceilingheight > height &&
432 other->ceilingheight < currentheight)
433 height = other->ceilingheight;
434 return height;
435 }
436 return currentheight;
437}
438
439
440//
441// P_FindNextHighestCeiling()
442//
443// Passed a sector and a ceiling height, returns the fixed point value
444// of the smallest ceiling height in a surrounding sector larger than
445// the ceiling height passed. If no such height exists the ceiling height
446// passed is returned.
447//
448// jff 02/03/98 Twiddled Lee's P_FindNextHighestFloor to make this
449//
450fixed_t P_FindNextHighestCeiling(sector_t *sec, int currentheight)
451{
452 sector_t *other;
453 int i;
454
455 for (i=0 ;i < sec->linecount ; i++)
456 if ((other = getNextSector(sec->lines[i],sec)) &&
457 other->ceilingheight > currentheight)
458 {
459 int height = other->ceilingheight;
460 while (++i < sec->linecount)
461 if ((other = getNextSector(sec->lines[i],sec)) &&
462 other->ceilingheight < height &&
463 other->ceilingheight > currentheight)
464 height = other->ceilingheight;
465 return height;
466 }
467 return currentheight;
468}
469
470
471//
472// P_FindLowestCeilingSurrounding()
473//
474// Passed a sector, returns the fixed point value of the smallest
475// ceiling height in the surrounding sectors, not including that passed
476//
477// NOTE: if no surrounding sector exists 32000*FRACUINT is returned
478// but if compatibility then INT_MAX is the return
479//
480fixed_t P_FindLowestCeilingSurrounding(sector_t* sec)
481{
482 int i;
483 line_t* check;
484 sector_t* other;
485 fixed_t height = INT_MAX;
486
487 /* jff 3/12/98 avoid ovf in height calculations */
488 if (!comp[comp_model]) height = 32000*FRACUNIT;
489
490 for (i=0 ;i < sec->linecount ; i++)
491 {
492 check = sec->lines[i];
493 other = getNextSector(check,sec);
494
495 if (!other)
496 continue;
497
498 if (other->ceilingheight < height)
499 height = other->ceilingheight;
500 }
501 return height;
502}
503
504
505//
506// P_FindHighestCeilingSurrounding()
507//
508// Passed a sector, returns the fixed point value of the largest
509// ceiling height in the surrounding sectors, not including that passed
510//
511// NOTE: if no surrounding sector exists -32000*FRACUINT is returned
512// but if compatibility then 0 is the smallest return possible
513//
514fixed_t P_FindHighestCeilingSurrounding(sector_t* sec)
515{
516 int i;
517 line_t* check;
518 sector_t* other;
519 fixed_t height = 0;
520
521 /* jff 1/26/98 Fix initial value for floor to not act differently
522 * in sections of wad that are below 0 units
523 * jff 3/12/98 avoid ovf in height calculations */
524 if (!comp[comp_model]) height = -32000*FRACUNIT;
525
526 for (i=0 ;i < sec->linecount ; i++)
527 {
528 check = sec->lines[i];
529 other = getNextSector(check,sec);
530
531 if (!other)
532 continue;
533
534 if (other->ceilingheight > height)
535 height = other->ceilingheight;
536 }
537 return height;
538}
539
540
541//
542// P_FindShortestTextureAround()
543//
544// Passed a sector number, returns the shortest lower texture on a
545// linedef bounding the sector.
546//
547// Note: If no lower texture exists 32000*FRACUNIT is returned.
548// but if compatibility then INT_MAX is returned
549//
550// jff 02/03/98 Add routine to find shortest lower texture
551//
552fixed_t P_FindShortestTextureAround(int secnum)
553{
554 int minsize = INT_MAX;
555 side_t* side;
556 int i;
557 sector_t *sec = &sectors[secnum];
558
559 if (!comp[comp_model])
560 minsize = 32000<<FRACBITS; //jff 3/13/98 prevent overflow in height calcs
561
562 for (i = 0; i < sec->linecount; i++)
563 {
564 if (twoSided(secnum, i))
565 {
566 side = getSide(secnum,i,0);
567 if (side->bottomtexture > 0) //jff 8/14/98 texture 0 is a placeholder
568 if (textureheight[side->bottomtexture] < minsize)
569 minsize = textureheight[side->bottomtexture];
570 side = getSide(secnum,i,1);
571 if (side->bottomtexture > 0) //jff 8/14/98 texture 0 is a placeholder
572 if (textureheight[side->bottomtexture] < minsize)
573 minsize = textureheight[side->bottomtexture];
574 }
575 }
576 return minsize;
577}
578
579
580//
581// P_FindShortestUpperAround()
582//
583// Passed a sector number, returns the shortest upper texture on a
584// linedef bounding the sector.
585//
586// Note: If no upper texture exists 32000*FRACUNIT is returned.
587// but if compatibility then INT_MAX is returned
588//
589// jff 03/20/98 Add routine to find shortest upper texture
590//
591fixed_t P_FindShortestUpperAround(int secnum)
592{
593 int minsize = INT_MAX;
594 side_t* side;
595 int i;
596 sector_t *sec = &sectors[secnum];
597
598 if (!comp[comp_model])
599 minsize = 32000<<FRACBITS; //jff 3/13/98 prevent overflow
600 // in height calcs
601 for (i = 0; i < sec->linecount; i++)
602 {
603 if (twoSided(secnum, i))
604 {
605 side = getSide(secnum,i,0);
606 if (side->toptexture > 0) //jff 8/14/98 texture 0 is a placeholder
607 if (textureheight[side->toptexture] < minsize)
608 minsize = textureheight[side->toptexture];
609 side = getSide(secnum,i,1);
610 if (side->toptexture > 0) //jff 8/14/98 texture 0 is a placeholder
611 if (textureheight[side->toptexture] < minsize)
612 minsize = textureheight[side->toptexture];
613 }
614 }
615 return minsize;
616}
617
618
619//
620// P_FindModelFloorSector()
621//
622// Passed a floor height and a sector number, return a pointer to a
623// a sector with that floor height across the lowest numbered two sided
624// line surrounding the sector.
625//
626// Note: If no sector at that height bounds the sector passed, return NULL
627//
628// jff 02/03/98 Add routine to find numeric model floor
629// around a sector specified by sector number
630// jff 3/14/98 change first parameter to plain height to allow call
631// from routine not using floormove_t
632//
633sector_t *P_FindModelFloorSector(fixed_t floordestheight,int secnum)
634{
635 int i;
636 sector_t *sec=NULL;
637 int linecount;
638
639 sec = &sectors[secnum]; //jff 3/2/98 woops! better do this
640 //jff 5/23/98 don't disturb sec->linecount while searching
641 // but allow early exit in old demos
642 linecount = sec->linecount;
643 for (i = 0; i < (demo_compatibility && sec->linecount<linecount?
644 sec->linecount : linecount); i++)
645 {
646 if ( twoSided(secnum, i) )
647 {
648 if (getSide(secnum,i,0)->sector-sectors == secnum)
649 sec = getSector(secnum,i,1);
650 else
651 sec = getSector(secnum,i,0);
652
653 if (sec->floorheight == floordestheight)
654 return sec;
655 }
656 }
657 return NULL;
658}
659
660
661//
662// P_FindModelCeilingSector()
663//
664// Passed a ceiling height and a sector number, return a pointer to a
665// a sector with that ceiling height across the lowest numbered two sided
666// line surrounding the sector.
667//
668// Note: If no sector at that height bounds the sector passed, return NULL
669//
670// jff 02/03/98 Add routine to find numeric model ceiling
671// around a sector specified by sector number
672// used only from generalized ceiling types
673// jff 3/14/98 change first parameter to plain height to allow call
674// from routine not using ceiling_t
675//
676sector_t *P_FindModelCeilingSector(fixed_t ceildestheight,int secnum)
677{
678 int i;
679 sector_t *sec=NULL;
680 int linecount;
681
682 sec = &sectors[secnum]; //jff 3/2/98 woops! better do this
683 //jff 5/23/98 don't disturb sec->linecount while searching
684 // but allow early exit in old demos
685 linecount = sec->linecount;
686 for (i = 0; i < (demo_compatibility && sec->linecount<linecount?
687 sec->linecount : linecount); i++)
688 {
689 if ( twoSided(secnum, i) )
690 {
691 if (getSide(secnum,i,0)->sector-sectors == secnum)
692 sec = getSector(secnum,i,1);
693 else
694 sec = getSector(secnum,i,0);
695
696 if (sec->ceilingheight == ceildestheight)
697 return sec;
698 }
699 }
700 return NULL;
701}
702
703//
704// RETURN NEXT SECTOR # THAT LINE TAG REFERS TO
705//
706
707// Find the next sector with the same tag as a linedef.
708// Rewritten by Lee Killough to use chained hashing to improve speed
709
710int P_FindSectorFromLineTag(const line_t *line, int start)
711{
712 start = start >= 0 ? sectors[start].nexttag :
713 sectors[(unsigned) line->tag % (unsigned) numsectors].firsttag;
714 while (start >= 0 && sectors[start].tag != line->tag)
715 start = sectors[start].nexttag;
716 return start;
717}
718
719// killough 4/16/98: Same thing, only for linedefs
720
721int P_FindLineFromLineTag(const line_t *line, int start)
722{
723 start = start >= 0 ? lines[start].nexttag :
724 lines[(unsigned) line->tag % (unsigned) numlines].firsttag;
725 while (start >= 0 && lines[start].tag != line->tag)
726 start = lines[start].nexttag;
727 return start;
728}
729
730// Hash the sector tags across the sectors and linedefs.
731static void P_InitTagLists(void)
732{
733 register int i;
734
735 for (i=numsectors; --i>=0; ) // Initially make all slots empty.
736 sectors[i].firsttag = -1;
737 for (i=numsectors; --i>=0; ) // Proceed from last to first sector
738 { // so that lower sectors appear first
739 int j = (unsigned) sectors[i].tag % (unsigned) numsectors; // Hash func
740 sectors[i].nexttag = sectors[j].firsttag; // Prepend sector to chain
741 sectors[j].firsttag = i;
742 }
743
744 // killough 4/17/98: same thing, only for linedefs
745
746 for (i=numlines; --i>=0; ) // Initially make all slots empty.
747 lines[i].firsttag = -1;
748 for (i=numlines; --i>=0; ) // Proceed from last to first linedef
749 { // so that lower linedefs appear first
750 int j = (unsigned) lines[i].tag % (unsigned) numlines; // Hash func
751 lines[i].nexttag = lines[j].firsttag; // Prepend linedef to chain
752 lines[j].firsttag = i;
753 }
754}
755
756//
757// P_FindMinSurroundingLight()
758//
759// Passed a sector and a light level, returns the smallest light level
760// in a surrounding sector less than that passed. If no smaller light
761// level exists, the light level passed is returned.
762//
763int P_FindMinSurroundingLight
764( sector_t* sector,
765 int max )
766{
767 int i;
768 int min;
769 line_t* line;
770 sector_t* check;
771
772 min = max;
773 for (i=0 ; i < sector->linecount ; i++)
774 {
775 line = sector->lines[i];
776 check = getNextSector(line,sector);
777
778 if (!check)
779 continue;
780
781 if (check->lightlevel < min)
782 min = check->lightlevel;
783 }
784 return min;
785}
786
787
788//
789// P_CanUnlockGenDoor()
790//
791// Passed a generalized locked door linedef and a player, returns whether
792// the player has the keys necessary to unlock that door.
793//
794// Note: The linedef passed MUST be a generalized locked door type
795// or results are undefined.
796//
797// jff 02/05/98 routine added to test for unlockability of
798// generalized locked doors
799//
800boolean P_CanUnlockGenDoor
801( line_t* line,
802 player_t* player)
803{
804 // does this line special distinguish between skulls and keys?
805 int skulliscard = (line->special & LockedNKeys)>>LockedNKeysShift;
806
807 // determine for each case of lock type if player's keys are adequate
808 switch((line->special & LockedKey)>>LockedKeyShift)
809 {
810 case AnyKey:
811 if
812 (
813 !player->cards[it_redcard] &&
814 !player->cards[it_redskull] &&
815 !player->cards[it_bluecard] &&
816 !player->cards[it_blueskull] &&
817 !player->cards[it_yellowcard] &&
818 !player->cards[it_yellowskull]
819 )
820 {
821 player->message = PD_ANY; // Ty 03/27/98 - externalized
822 S_StartSound(player->mo,sfx_oof); // killough 3/20/98
823 return false;
824 }
825 break;
826 case RCard:
827 if
828 (
829 !player->cards[it_redcard] &&
830 (!skulliscard || !player->cards[it_redskull])
831 )
832 {
833 player->message = skulliscard? PD_REDK : PD_REDC; // Ty 03/27/98 - externalized
834 S_StartSound(player->mo,sfx_oof); // killough 3/20/98
835 return false;
836 }
837 break;
838 case BCard:
839 if
840 (
841 !player->cards[it_bluecard] &&
842 (!skulliscard || !player->cards[it_blueskull])
843 )
844 {
845 player->message = skulliscard? PD_BLUEK : PD_BLUEC; // Ty 03/27/98 - externalized
846 S_StartSound(player->mo,sfx_oof); // killough 3/20/98
847 return false;
848 }
849 break;
850 case YCard:
851 if
852 (
853 !player->cards[it_yellowcard] &&
854 (!skulliscard || !player->cards[it_yellowskull])
855 )
856 {
857 player->message = skulliscard? PD_YELLOWK : PD_YELLOWC; // Ty 03/27/98 - externalized
858 S_StartSound(player->mo,sfx_oof); // killough 3/20/98
859 return false;
860 }
861 break;
862 case RSkull:
863 if
864 (
865 !player->cards[it_redskull] &&
866 (!skulliscard || !player->cards[it_redcard])
867 )
868 {
869 player->message = skulliscard? PD_REDK : PD_REDS; // Ty 03/27/98 - externalized
870 S_StartSound(player->mo,sfx_oof); // killough 3/20/98
871 return false;
872 }
873 break;
874 case BSkull:
875 if
876 (
877 !player->cards[it_blueskull] &&
878 (!skulliscard || !player->cards[it_bluecard])
879 )
880 {
881 player->message = skulliscard? PD_BLUEK : PD_BLUES; // Ty 03/27/98 - externalized
882 S_StartSound(player->mo,sfx_oof); // killough 3/20/98
883 return false;
884 }
885 break;
886 case YSkull:
887 if
888 (
889 !player->cards[it_yellowskull] &&
890 (!skulliscard || !player->cards[it_yellowcard])
891 )
892 {
893 player->message = skulliscard? PD_YELLOWK : PD_YELLOWS; // Ty 03/27/98 - externalized
894 S_StartSound(player->mo,sfx_oof); // killough 3/20/98
895 return false;
896 }
897 break;
898 case AllKeys:
899 if
900 (
901 !skulliscard &&
902 (
903 !player->cards[it_redcard] ||
904 !player->cards[it_redskull] ||
905 !player->cards[it_bluecard] ||
906 !player->cards[it_blueskull] ||
907 !player->cards[it_yellowcard] ||
908 !player->cards[it_yellowskull]
909 )
910 )
911 {
912 player->message = PD_ALL6; // Ty 03/27/98 - externalized
913 S_StartSound(player->mo,sfx_oof); // killough 3/20/98
914 return false;
915 }
916 if
917 (
918 skulliscard &&
919 (
920 (!player->cards[it_redcard] &&
921 !player->cards[it_redskull]) ||
922 (!player->cards[it_bluecard] &&
923 !player->cards[it_blueskull]) ||
924 (!player->cards[it_yellowcard] &&
925 !player->cards[it_yellowskull])
926 )
927 )
928 {
929 player->message = PD_ALL3; // Ty 03/27/98 - externalized
930 S_StartSound(player->mo,sfx_oof); // killough 3/20/98
931 return false;
932 }
933 break;
934 }
935 return true;
936}
937
938
939//
940// P_SectorActive()
941//
942// Passed a linedef special class (floor, ceiling, lighting) and a sector
943// returns whether the sector is already busy with a linedef special of the
944// same class. If old demo compatibility true, all linedef special classes
945// are the same.
946//
947// jff 2/23/98 added to prevent old demos from
948// succeeding in starting multiple specials on one sector
949//
950int P_SectorActive(special_e t,sector_t *sec)
951{
952 if (demo_compatibility) // return whether any thinker is active
953 return sec->floordata || sec->ceilingdata || sec->lightingdata;
954 else
955 switch (t) // return whether thinker of same type is active
956 {
957 case floor_special:
958 return (int)sec->floordata;
959 case ceiling_special:
960 return (int)sec->ceilingdata;
961 case lighting_special:
962 return (int)sec->lightingdata;
963 }
964 return 1; // don't know which special, must be active, shouldn't be here
965}
966
967
968//
969// P_CheckTag()
970//
971// Passed a line, returns true if the tag is non-zero or the line special
972// allows no tag without harm. If compatibility, all linedef specials are
973// allowed to have zero tag.
974//
975// Note: Only line specials activated by walkover, pushing, or shooting are
976// checked by this routine.
977//
978// jff 2/27/98 Added to check for zero tag allowed for regular special types
979//
980int P_CheckTag(line_t *line)
981{
982 /* tag not zero, allowed, or
983 * killough 11/98: compatibility option */
984 if (comp[comp_zerotags] || line->tag)
985 return 1;
986
987 switch(line->special)
988 {
989 case 1: // Manual door specials
990 case 26:
991 case 27:
992 case 28:
993 case 31:
994 case 32:
995 case 33:
996 case 34:
997 case 117:
998 case 118:
999
1000 case 139: // Lighting specials
1001 case 170:
1002 case 79:
1003 case 35:
1004 case 138:
1005 case 171:
1006 case 81:
1007 case 13:
1008 case 192:
1009 case 169:
1010 case 80:
1011 case 12:
1012 case 194:
1013 case 173:
1014 case 157:
1015 case 104:
1016 case 193:
1017 case 172:
1018 case 156:
1019 case 17:
1020
1021 case 195: // Thing teleporters
1022 case 174:
1023 case 97:
1024 case 39:
1025 case 126:
1026 case 125:
1027 case 210:
1028 case 209:
1029 case 208:
1030 case 207:
1031
1032 case 11: // Exits
1033 case 52:
1034 case 197:
1035 case 51:
1036 case 124:
1037 case 198:
1038
1039 case 48: // Scrolling walls
1040 case 85:
1041 return 1; // zero tag allowed
1042
1043 default:
1044 break;
1045 }
1046 return 0; // zero tag not allowed
1047}
1048
1049
1050//
1051// P_IsSecret()
1052//
1053// Passed a sector, returns if the sector secret type is still active, i.e.
1054// secret type is set and the secret has not yet been obtained.
1055//
1056// jff 3/14/98 added to simplify checks for whether sector is secret
1057// in automap and other places
1058//
1059boolean P_IsSecret(sector_t *sec)
1060{
1061 return (sec->special==9 || (sec->special&SECRET_MASK));
1062}
1063
1064
1065//
1066// P_WasSecret()
1067//
1068// Passed a sector, returns if the sector secret type is was active, i.e.
1069// secret type was set and the secret has been obtained already.
1070//
1071// jff 3/14/98 added to simplify checks for whether sector is secret
1072// in automap and other places
1073//
1074boolean P_WasSecret(sector_t *sec)
1075{
1076 return (sec->oldspecial==9 || (sec->oldspecial&SECRET_MASK));
1077}
1078
1079
1080//////////////////////////////////////////////////////////////////////////
1081//
1082// Events
1083//
1084// Events are operations triggered by using, crossing,
1085// or shooting special lines, or by timed thinkers.
1086//
1087/////////////////////////////////////////////////////////////////////////
1088
1089//
1090// P_CrossSpecialLine - Walkover Trigger Dispatcher
1091//
1092// Called every time a thing origin is about
1093// to cross a line with a non 0 special, whether a walkover type or not.
1094//
1095// jff 02/12/98 all W1 lines were fixed to check the result from the EV_
1096// function before clearing the special. This avoids losing the function
1097// of the line, should the sector already be active when the line is
1098// crossed. Change is qualified by demo_compatibility.
1099//
1100// CPhipps - take a line_t pointer instead of a line number, as in MBF
1101void P_CrossSpecialLine(line_t *line, int side, mobj_t *thing)
1102{
1103 int ok;
1104
1105 // Things that should never trigger lines
1106 if (!thing->player)
1107 {
1108 // Things that should NOT trigger specials...
1109 switch(thing->type)
1110 {
1111 case MT_ROCKET:
1112 case MT_PLASMA:
1113 case MT_BFG:
1114 case MT_TROOPSHOT:
1115 case MT_HEADSHOT:
1116 case MT_BRUISERSHOT:
1117 return;
1118 break;
1119
1120 default: break;
1121 }
1122 }
1123
1124 //jff 02/04/98 add check here for generalized lindef types
1125 if (!demo_compatibility) // generalized types not recognized if old demo
1126 {
1127 // pointer to line function is NULL by default, set non-null if
1128 // line special is walkover generalized linedef type
1129 int (*linefunc)(line_t *line)=NULL;
1130
1131 // check each range of generalized linedefs
1132 if ((unsigned)line->special >= GenEnd)
1133 {
1134 // Out of range for GenFloors
1135 }
1136 else if ((unsigned)line->special >= GenFloorBase)
1137 {
1138 if (!thing->player)
1139 if ((line->special & FloorChange) || !(line->special & FloorModel))
1140 return; // FloorModel is "Allow Monsters" if FloorChange is 0
1141 if (!line->tag) //jff 2/27/98 all walk generalized types require tag
1142 return;
1143 linefunc = EV_DoGenFloor;
1144 }
1145 else if ((unsigned)line->special >= GenCeilingBase)
1146 {
1147 if (!thing->player)
1148 if ((line->special & CeilingChange) || !(line->special & CeilingModel))
1149 return; // CeilingModel is "Allow Monsters" if CeilingChange is 0
1150 if (!line->tag) //jff 2/27/98 all walk generalized types require tag
1151 return;
1152 linefunc = EV_DoGenCeiling;
1153 }
1154 else if ((unsigned)line->special >= GenDoorBase)
1155 {
1156 if (!thing->player)
1157 {
1158 if (!(line->special & DoorMonster))
1159 return; // monsters disallowed from this door
1160 if (line->flags & ML_SECRET) // they can't open secret doors either
1161 return;
1162 }
1163 if (!line->tag) //3/2/98 move outside the monster check
1164 return;
1165 linefunc = EV_DoGenDoor;
1166 }
1167 else if ((unsigned)line->special >= GenLockedBase)
1168 {
1169 if (!thing->player)
1170 return; // monsters disallowed from unlocking doors
1171 if (((line->special&TriggerType)==WalkOnce) || ((line->special&TriggerType)==WalkMany))
1172 { //jff 4/1/98 check for being a walk type before reporting door type
1173 if (!P_CanUnlockGenDoor(line,thing->player))
1174 return;
1175 }
1176 else
1177 return;
1178 linefunc = EV_DoGenLockedDoor;
1179 }
1180 else if ((unsigned)line->special >= GenLiftBase)
1181 {
1182 if (!thing->player)
1183 if (!(line->special & LiftMonster))
1184 return; // monsters disallowed
1185 if (!line->tag) //jff 2/27/98 all walk generalized types require tag
1186 return;
1187 linefunc = EV_DoGenLift;
1188 }
1189 else if ((unsigned)line->special >= GenStairsBase)
1190 {
1191 if (!thing->player)
1192 if (!(line->special & StairMonster))
1193 return; // monsters disallowed
1194 if (!line->tag) //jff 2/27/98 all walk generalized types require tag
1195 return;
1196 linefunc = EV_DoGenStairs;
1197 }
1198
1199 if (linefunc) // if it was a valid generalized type
1200 switch((line->special & TriggerType) >> TriggerTypeShift)
1201 {
1202 case WalkOnce:
1203 if (linefunc(line))
1204 line->special = 0; // clear special if a walk once type
1205 return;
1206 case WalkMany:
1207 linefunc(line);
1208 return;
1209 default: // if not a walk type, do nothing here
1210 return;
1211 }
1212 }
1213
1214 if (!thing->player)
1215 {
1216 ok = 0;
1217 switch(line->special)
1218 {
1219 case 39: // teleport trigger
1220 case 97: // teleport retrigger
1221 case 125: // teleport monsteronly trigger
1222 case 126: // teleport monsteronly retrigger
1223 case 4: // raise door
1224 case 10: // plat down-wait-up-stay trigger
1225 case 88: // plat down-wait-up-stay retrigger
1226 //jff 3/5/98 add ability of monsters etc. to use teleporters
1227 case 208: //silent thing teleporters
1228 case 207:
1229 case 243: //silent line-line teleporter
1230 case 244: //jff 3/6/98 make fit within DCK's 256 linedef types
1231 case 262: //jff 4/14/98 add monster only
1232 case 263: //jff 4/14/98 silent thing,line,line rev types
1233 case 264: //jff 4/14/98 plus player/monster silent line
1234 case 265: // reversed types
1235 case 266:
1236 case 267:
1237 case 268:
1238 case 269:
1239 ok = 1;
1240 break;
1241 }
1242 if (!ok)
1243 return;
1244 }
1245
1246 if (!P_CheckTag(line)) //jff 2/27/98 disallow zero tag on some types
1247 return;
1248
1249 // Dispatch on the line special value to the line's action routine
1250 // If a once only function, and successful, clear the line special
1251
1252 switch (line->special)
1253 {
1254 // Regular walk once triggers
1255
1256 case 2:
1257 // Open Door
1258 if (EV_DoDoor(line,p_open) || demo_compatibility)
1259 line->special = 0;
1260 break;
1261
1262 case 3:
1263 // Close Door
1264 if (EV_DoDoor(line,p_close) || demo_compatibility)
1265 line->special = 0;
1266 break;
1267
1268 case 4:
1269 // Raise Door
1270 if (EV_DoDoor(line,normal) || demo_compatibility)
1271 line->special = 0;
1272 break;
1273
1274 case 5:
1275 // Raise Floor
1276 if (EV_DoFloor(line,raiseFloor) || demo_compatibility)
1277 line->special = 0;
1278 break;
1279
1280 case 6:
1281 // Fast Ceiling Crush & Raise
1282 if (EV_DoCeiling(line,fastCrushAndRaise) || demo_compatibility)
1283 line->special = 0;
1284 break;
1285
1286 case 8:
1287 // Build Stairs
1288 if (EV_BuildStairs(line,build8) || demo_compatibility)
1289 line->special = 0;
1290 break;
1291
1292 case 10:
1293 // PlatDownWaitUp
1294 if (EV_DoPlat(line,downWaitUpStay,0) || demo_compatibility)
1295 line->special = 0;
1296 break;
1297
1298 case 12:
1299 // Light Turn On - brightest near
1300 if (EV_LightTurnOn(line,0) || demo_compatibility)
1301 line->special = 0;
1302 break;
1303
1304 case 13:
1305 // Light Turn On 255
1306 if (EV_LightTurnOn(line,255) || demo_compatibility)
1307 line->special = 0;
1308 break;
1309
1310 case 16:
1311 // Close Door 30
1312 if (EV_DoDoor(line,close30ThenOpen) || demo_compatibility)
1313 line->special = 0;
1314 break;
1315
1316 case 17:
1317 // Start Light Strobing
1318 if (EV_StartLightStrobing(line) || demo_compatibility)
1319 line->special = 0;
1320 break;
1321
1322 case 19:
1323 // Lower Floor
1324 if (EV_DoFloor(line,lowerFloor) || demo_compatibility)
1325 line->special = 0;
1326 break;
1327
1328 case 22:
1329 // Raise floor to nearest height and change texture
1330 if (EV_DoPlat(line,raiseToNearestAndChange,0) || demo_compatibility)
1331 line->special = 0;
1332 break;
1333
1334 case 25:
1335 // Ceiling Crush and Raise
1336 if (EV_DoCeiling(line,crushAndRaise) || demo_compatibility)
1337 line->special = 0;
1338 break;
1339
1340 case 30:
1341 // Raise floor to shortest texture height
1342 // on either side of lines.
1343 if (EV_DoFloor(line,raiseToTexture) || demo_compatibility)
1344 line->special = 0;
1345 break;
1346
1347 case 35:
1348 // Lights Very Dark
1349 if (EV_LightTurnOn(line,35) || demo_compatibility)
1350 line->special = 0;
1351 break;
1352
1353 case 36:
1354 // Lower Floor (TURBO)
1355 if (EV_DoFloor(line,turboLower) || demo_compatibility)
1356 line->special = 0;
1357 break;
1358
1359 case 37:
1360 // LowerAndChange
1361 if (EV_DoFloor(line,lowerAndChange) || demo_compatibility)
1362 line->special = 0;
1363 break;
1364
1365 case 38:
1366 // Lower Floor To Lowest
1367 if (EV_DoFloor(line, lowerFloorToLowest) || demo_compatibility)
1368 line->special = 0;
1369 break;
1370
1371 case 39:
1372 // TELEPORT! //jff 02/09/98 fix using up with wrong side crossing
1373 if (EV_Teleport(line, side, thing) || demo_compatibility)
1374 line->special = 0;
1375 break;
1376
1377 case 40:
1378 // RaiseCeilingLowerFloor
1379 if (demo_compatibility)
1380 {
1381 EV_DoCeiling( line, raiseToHighest );
1382 EV_DoFloor( line, lowerFloorToLowest ); //jff 02/12/98 doesn't work
1383 line->special = 0;
1384 }
1385 else
1386 if (EV_DoCeiling(line, raiseToHighest))
1387 line->special = 0;
1388 break;
1389
1390 case 44:
1391 // Ceiling Crush
1392 if (EV_DoCeiling(line, lowerAndCrush) || demo_compatibility)
1393 line->special = 0;
1394 break;
1395
1396 case 52:
1397 // EXIT!
1398 // killough 10/98: prevent zombies from exiting levels
1399 if (!(thing->player && thing->player->health <= 0 && !comp[comp_zombie]))
1400 G_ExitLevel ();
1401 break;
1402
1403 case 53:
1404 // Perpetual Platform Raise
1405 if (EV_DoPlat(line,perpetualRaise,0) || demo_compatibility)
1406 line->special = 0;
1407 break;
1408
1409 case 54:
1410 // Platform Stop
1411 if (EV_StopPlat(line) || demo_compatibility)
1412 line->special = 0;
1413 break;
1414
1415 case 56:
1416 // Raise Floor Crush
1417 if (EV_DoFloor(line,raiseFloorCrush) || demo_compatibility)
1418 line->special = 0;
1419 break;
1420
1421 case 57:
1422 // Ceiling Crush Stop
1423 if (EV_CeilingCrushStop(line) || demo_compatibility)
1424 line->special = 0;
1425 break;
1426
1427 case 58:
1428 // Raise Floor 24
1429 if (EV_DoFloor(line,raiseFloor24) || demo_compatibility)
1430 line->special = 0;
1431 break;
1432
1433 case 59:
1434 // Raise Floor 24 And Change
1435 if (EV_DoFloor(line,raiseFloor24AndChange) || demo_compatibility)
1436 line->special = 0;
1437 break;
1438
1439 case 100:
1440 // Build Stairs Turbo 16
1441 if (EV_BuildStairs(line,turbo16) || demo_compatibility)
1442 line->special = 0;
1443 break;
1444
1445 case 104:
1446 // Turn lights off in sector(tag)
1447 if (EV_TurnTagLightsOff(line) || demo_compatibility)
1448 line->special = 0;
1449 break;
1450
1451 case 108:
1452 // Blazing Door Raise (faster than TURBO!)
1453 if (EV_DoDoor(line,blazeRaise) || demo_compatibility)
1454 line->special = 0;
1455 break;
1456
1457 case 109:
1458 // Blazing Door Open (faster than TURBO!)
1459 if (EV_DoDoor (line,blazeOpen) || demo_compatibility)
1460 line->special = 0;
1461 break;
1462
1463 case 110:
1464 // Blazing Door Close (faster than TURBO!)
1465 if (EV_DoDoor (line,blazeClose) || demo_compatibility)
1466 line->special = 0;
1467 break;
1468
1469 case 119:
1470 // Raise floor to nearest surr. floor
1471 if (EV_DoFloor(line,raiseFloorToNearest) || demo_compatibility)
1472 line->special = 0;
1473 break;
1474
1475 case 121:
1476 // Blazing PlatDownWaitUpStay
1477 if (EV_DoPlat(line,blazeDWUS,0) || demo_compatibility)
1478 line->special = 0;
1479 break;
1480
1481 case 124:
1482 // Secret EXIT
1483 // killough 10/98: prevent zombies from exiting levels
1484 // CPhipps - change for lxdoom's compatibility handling
1485 if (!(thing->player && thing->player->health <= 0 && !comp[comp_zombie]))
1486 G_SecretExitLevel ();
1487 break;
1488
1489 case 125:
1490 // TELEPORT MonsterONLY
1491 if (!thing->player &&
1492 (EV_Teleport(line, side, thing) || demo_compatibility))
1493 line->special = 0;
1494 break;
1495
1496 case 130:
1497 // Raise Floor Turbo
1498 if (EV_DoFloor(line,raiseFloorTurbo) || demo_compatibility)
1499 line->special = 0;
1500 break;
1501
1502 case 141:
1503 // Silent Ceiling Crush & Raise
1504 if (EV_DoCeiling(line,silentCrushAndRaise) || demo_compatibility)
1505 line->special = 0;
1506 break;
1507
1508 // Regular walk many retriggerable
1509
1510 case 72:
1511 // Ceiling Crush
1512 EV_DoCeiling( line, lowerAndCrush );
1513 break;
1514
1515 case 73:
1516 // Ceiling Crush and Raise
1517 EV_DoCeiling(line,crushAndRaise);
1518 break;
1519
1520 case 74:
1521 // Ceiling Crush Stop
1522 EV_CeilingCrushStop(line);
1523 break;
1524
1525 case 75:
1526 // Close Door
1527 EV_DoDoor(line,p_close);
1528 break;
1529
1530 case 76:
1531 // Close Door 30
1532 EV_DoDoor(line,close30ThenOpen);
1533 break;
1534
1535 case 77:
1536 // Fast Ceiling Crush & Raise
1537 EV_DoCeiling(line,fastCrushAndRaise);
1538 break;
1539
1540 case 79:
1541 // Lights Very Dark
1542 EV_LightTurnOn(line,35);
1543 break;
1544
1545 case 80:
1546 // Light Turn On - brightest near
1547 EV_LightTurnOn(line,0);
1548 break;
1549
1550 case 81:
1551 // Light Turn On 255
1552 EV_LightTurnOn(line,255);
1553 break;
1554
1555 case 82:
1556 // Lower Floor To Lowest
1557 EV_DoFloor( line, lowerFloorToLowest );
1558 break;
1559
1560 case 83:
1561 // Lower Floor
1562 EV_DoFloor(line,lowerFloor);
1563 break;
1564
1565 case 84:
1566 // LowerAndChange
1567 EV_DoFloor(line,lowerAndChange);
1568 break;
1569
1570 case 86:
1571 // Open Door
1572 EV_DoDoor(line,p_open);
1573 break;
1574
1575 case 87:
1576 // Perpetual Platform Raise
1577 EV_DoPlat(line,perpetualRaise,0);
1578 break;
1579
1580 case 88:
1581 // PlatDownWaitUp
1582 EV_DoPlat(line,downWaitUpStay,0);
1583 break;
1584
1585 case 89:
1586 // Platform Stop
1587 EV_StopPlat(line);
1588 break;
1589
1590 case 90:
1591 // Raise Door
1592 EV_DoDoor(line,normal);
1593 break;
1594
1595 case 91:
1596 // Raise Floor
1597 EV_DoFloor(line,raiseFloor);
1598 break;
1599
1600 case 92:
1601 // Raise Floor 24
1602 EV_DoFloor(line,raiseFloor24);
1603 break;
1604
1605 case 93:
1606 // Raise Floor 24 And Change
1607 EV_DoFloor(line,raiseFloor24AndChange);
1608 break;
1609
1610 case 94:
1611 // Raise Floor Crush
1612 EV_DoFloor(line,raiseFloorCrush);
1613 break;
1614
1615 case 95:
1616 // Raise floor to nearest height
1617 // and change texture.
1618 EV_DoPlat(line,raiseToNearestAndChange,0);
1619 break;
1620
1621 case 96:
1622 // Raise floor to shortest texture height
1623 // on either side of lines.
1624 EV_DoFloor(line,raiseToTexture);
1625 break;
1626
1627 case 97:
1628 // TELEPORT!
1629 EV_Teleport( line, side, thing );
1630 break;
1631
1632 case 98:
1633 // Lower Floor (TURBO)
1634 EV_DoFloor(line,turboLower);
1635 break;
1636
1637 case 105:
1638 // Blazing Door Raise (faster than TURBO!)
1639 EV_DoDoor (line,blazeRaise);
1640 break;
1641
1642 case 106:
1643 // Blazing Door Open (faster than TURBO!)
1644 EV_DoDoor (line,blazeOpen);
1645 break;
1646
1647 case 107:
1648 // Blazing Door Close (faster than TURBO!)
1649 EV_DoDoor (line,blazeClose);
1650 break;
1651
1652 case 120:
1653 // Blazing PlatDownWaitUpStay.
1654 EV_DoPlat(line,blazeDWUS,0);
1655 break;
1656
1657 case 126:
1658 // TELEPORT MonsterONLY.
1659 if (!thing->player)
1660 EV_Teleport( line, side, thing );
1661 break;
1662
1663 case 128:
1664 // Raise To Nearest Floor
1665 EV_DoFloor(line,raiseFloorToNearest);
1666 break;
1667
1668 case 129:
1669 // Raise Floor Turbo
1670 EV_DoFloor(line,raiseFloorTurbo);
1671 break;
1672
1673 // Extended walk triggers
1674
1675 // jff 1/29/98 added new linedef types to fill all functions out so that
1676 // all have varieties SR, S1, WR, W1
1677
1678 // killough 1/31/98: "factor out" compatibility test, by
1679 // adding inner switch qualified by compatibility flag.
1680 // relax test to demo_compatibility
1681
1682 // killough 2/16/98: Fix problems with W1 types being cleared too early
1683
1684 default:
1685 if (!demo_compatibility)
1686 switch (line->special)
1687 {
1688 // Extended walk once triggers
1689
1690 case 142:
1691 // Raise Floor 512
1692 // 142 W1 EV_DoFloor(raiseFloor512)
1693 if (EV_DoFloor(line,raiseFloor512))
1694 line->special = 0;
1695 break;
1696
1697 case 143:
1698 // Raise Floor 24 and change
1699 // 143 W1 EV_DoPlat(raiseAndChange,24)
1700 if (EV_DoPlat(line,raiseAndChange,24))
1701 line->special = 0;
1702 break;
1703
1704 case 144:
1705 // Raise Floor 32 and change
1706 // 144 W1 EV_DoPlat(raiseAndChange,32)
1707 if (EV_DoPlat(line,raiseAndChange,32))
1708 line->special = 0;
1709 break;
1710
1711 case 145:
1712 // Lower Ceiling to Floor
1713 // 145 W1 EV_DoCeiling(lowerToFloor)
1714 if (EV_DoCeiling( line, lowerToFloor ))
1715 line->special = 0;
1716 break;
1717
1718 case 146:
1719 // Lower Pillar, Raise Donut
1720 // 146 W1 EV_DoDonut()
1721 if (EV_DoDonut(line))
1722 line->special = 0;
1723 break;
1724
1725 case 199:
1726 // Lower ceiling to lowest surrounding ceiling
1727 // 199 W1 EV_DoCeiling(lowerToLowest)
1728 if (EV_DoCeiling(line,lowerToLowest))
1729 line->special = 0;
1730 break;
1731
1732 case 200:
1733 // Lower ceiling to highest surrounding floor
1734 // 200 W1 EV_DoCeiling(lowerToMaxFloor)
1735 if (EV_DoCeiling(line,lowerToMaxFloor))
1736 line->special = 0;
1737 break;
1738
1739 case 207:
1740 // killough 2/16/98: W1 silent teleporter (normal kind)
1741 if (EV_SilentTeleport(line, side, thing))
1742 line->special = 0;
1743 break;
1744
1745 //jff 3/16/98 renumber 215->153
1746 case 153: //jff 3/15/98 create texture change no motion type
1747 // Texture/Type Change Only (Trig)
1748 // 153 W1 Change Texture/Type Only
1749 if (EV_DoChange(line,trigChangeOnly))
1750 line->special = 0;
1751 break;
1752
1753 case 239: //jff 3/15/98 create texture change no motion type
1754 // Texture/Type Change Only (Numeric)
1755 // 239 W1 Change Texture/Type Only
1756 if (EV_DoChange(line,numChangeOnly))
1757 line->special = 0;
1758 break;
1759
1760 case 219:
1761 // Lower floor to next lower neighbor
1762 // 219 W1 Lower Floor Next Lower Neighbor
1763 if (EV_DoFloor(line,lowerFloorToNearest))
1764 line->special = 0;
1765 break;
1766
1767 case 227:
1768 // Raise elevator next floor
1769 // 227 W1 Raise Elevator next floor
1770 if (EV_DoElevator(line,elevateUp))
1771 line->special = 0;
1772 break;
1773
1774 case 231:
1775 // Lower elevator next floor
1776 // 231 W1 Lower Elevator next floor
1777 if (EV_DoElevator(line,elevateDown))
1778 line->special = 0;
1779 break;
1780
1781 case 235:
1782 // Elevator to current floor
1783 // 235 W1 Elevator to current floor
1784 if (EV_DoElevator(line,elevateCurrent))
1785 line->special = 0;
1786 break;
1787
1788 case 243: //jff 3/6/98 make fit within DCK's 256 linedef types
1789 // killough 2/16/98: W1 silent teleporter (linedef-linedef kind)
1790 if (EV_SilentLineTeleport(line, side, thing, false))
1791 line->special = 0;
1792 break;
1793
1794 case 262: //jff 4/14/98 add silent line-line reversed
1795 if (EV_SilentLineTeleport(line, side, thing, true))
1796 line->special = 0;
1797 break;
1798
1799 case 264: //jff 4/14/98 add monster-only silent line-line reversed
1800 if (!thing->player &&
1801 EV_SilentLineTeleport(line, side, thing, true))
1802 line->special = 0;
1803 break;
1804
1805 case 266: //jff 4/14/98 add monster-only silent line-line
1806 if (!thing->player &&
1807 EV_SilentLineTeleport(line, side, thing, false))
1808 line->special = 0;
1809 break;
1810
1811 case 268: //jff 4/14/98 add monster-only silent
1812 if (!thing->player && EV_SilentTeleport(line, side, thing))
1813 line->special = 0;
1814 break;
1815
1816 //jff 1/29/98 end of added W1 linedef types
1817
1818 // Extended walk many retriggerable
1819
1820 //jff 1/29/98 added new linedef types to fill all functions
1821 //out so that all have varieties SR, S1, WR, W1
1822
1823 case 147:
1824 // Raise Floor 512
1825 // 147 WR EV_DoFloor(raiseFloor512)
1826 EV_DoFloor(line,raiseFloor512);
1827 break;
1828
1829 case 148:
1830 // Raise Floor 24 and Change
1831 // 148 WR EV_DoPlat(raiseAndChange,24)
1832 EV_DoPlat(line,raiseAndChange,24);
1833 break;
1834
1835 case 149:
1836 // Raise Floor 32 and Change
1837 // 149 WR EV_DoPlat(raiseAndChange,32)
1838 EV_DoPlat(line,raiseAndChange,32);
1839 break;
1840
1841 case 150:
1842 // Start slow silent crusher
1843 // 150 WR EV_DoCeiling(silentCrushAndRaise)
1844 EV_DoCeiling(line,silentCrushAndRaise);
1845 break;
1846
1847 case 151:
1848 // RaiseCeilingLowerFloor
1849 // 151 WR EV_DoCeiling(raiseToHighest),
1850 // EV_DoFloor(lowerFloortoLowest)
1851 EV_DoCeiling( line, raiseToHighest );
1852 EV_DoFloor( line, lowerFloorToLowest );
1853 break;
1854
1855 case 152:
1856 // Lower Ceiling to Floor
1857 // 152 WR EV_DoCeiling(lowerToFloor)
1858 EV_DoCeiling( line, lowerToFloor );
1859 break;
1860
1861 //jff 3/16/98 renumber 153->256
1862 case 256:
1863 // Build stairs, step 8
1864 // 256 WR EV_BuildStairs(build8)
1865 EV_BuildStairs(line,build8);
1866 break;
1867
1868 //jff 3/16/98 renumber 154->257
1869 case 257:
1870 // Build stairs, step 16
1871 // 257 WR EV_BuildStairs(turbo16)
1872 EV_BuildStairs(line,turbo16);
1873 break;
1874
1875 case 155:
1876 // Lower Pillar, Raise Donut
1877 // 155 WR EV_DoDonut()
1878 EV_DoDonut(line);
1879 break;
1880
1881 case 156:
1882 // Start lights strobing
1883 // 156 WR Lights EV_StartLightStrobing()
1884 EV_StartLightStrobing(line);
1885 break;
1886
1887 case 157:
1888 // Lights to dimmest near
1889 // 157 WR Lights EV_TurnTagLightsOff()
1890 EV_TurnTagLightsOff(line);
1891 break;
1892
1893 case 201:
1894 // Lower ceiling to lowest surrounding ceiling
1895 // 201 WR EV_DoCeiling(lowerToLowest)
1896 EV_DoCeiling(line,lowerToLowest);
1897 break;
1898
1899 case 202:
1900 // Lower ceiling to highest surrounding floor
1901 // 202 WR EV_DoCeiling(lowerToMaxFloor)
1902 EV_DoCeiling(line,lowerToMaxFloor);
1903 break;
1904
1905 case 208:
1906 // killough 2/16/98: WR silent teleporter (normal kind)
1907 EV_SilentTeleport(line, side, thing);
1908 break;
1909
1910 case 212: //jff 3/14/98 create instant toggle floor type
1911 // Toggle floor between C and F instantly
1912 // 212 WR Instant Toggle Floor
1913 EV_DoPlat(line,toggleUpDn,0);
1914 break;
1915
1916 //jff 3/16/98 renumber 216->154
1917 case 154: //jff 3/15/98 create texture change no motion type
1918 // Texture/Type Change Only (Trigger)
1919 // 154 WR Change Texture/Type Only
1920 EV_DoChange(line,trigChangeOnly);
1921 break;
1922
1923 case 240: //jff 3/15/98 create texture change no motion type
1924 // Texture/Type Change Only (Numeric)
1925 // 240 WR Change Texture/Type Only
1926 EV_DoChange(line,numChangeOnly);
1927 break;
1928
1929 case 220:
1930 // Lower floor to next lower neighbor
1931 // 220 WR Lower Floor Next Lower Neighbor
1932 EV_DoFloor(line,lowerFloorToNearest);
1933 break;
1934
1935 case 228:
1936 // Raise elevator next floor
1937 // 228 WR Raise Elevator next floor
1938 EV_DoElevator(line,elevateUp);
1939 break;
1940
1941 case 232:
1942 // Lower elevator next floor
1943 // 232 WR Lower Elevator next floor
1944 EV_DoElevator(line,elevateDown);
1945 break;
1946
1947 case 236:
1948 // Elevator to current floor
1949 // 236 WR Elevator to current floor
1950 EV_DoElevator(line,elevateCurrent);
1951 break;
1952
1953 case 244: //jff 3/6/98 make fit within DCK's 256 linedef types
1954 // killough 2/16/98: WR silent teleporter (linedef-linedef kind)
1955 EV_SilentLineTeleport(line, side, thing, false);
1956 break;
1957
1958 case 263: //jff 4/14/98 add silent line-line reversed
1959 EV_SilentLineTeleport(line, side, thing, true);
1960 break;
1961
1962 case 265: //jff 4/14/98 add monster-only silent line-line reversed
1963 if (!thing->player)
1964 EV_SilentLineTeleport(line, side, thing, true);
1965 break;
1966
1967 case 267: //jff 4/14/98 add monster-only silent line-line
1968 if (!thing->player)
1969 EV_SilentLineTeleport(line, side, thing, false);
1970 break;
1971
1972 case 269: //jff 4/14/98 add monster-only silent
1973 if (!thing->player)
1974 EV_SilentTeleport(line, side, thing);
1975 break;
1976
1977 //jff 1/29/98 end of added WR linedef types
1978 }
1979 break;
1980 }
1981}
1982
1983//
1984// P_ShootSpecialLine - Gun trigger special dispatcher
1985//
1986// Called when a thing shoots a special line with bullet, shell, saw, or fist.
1987//
1988// jff 02/12/98 all G1 lines were fixed to check the result from the EV_
1989// function before clearing the special. This avoids losing the function
1990// of the line, should the sector already be in motion when the line is
1991// impacted. Change is qualified by demo_compatibility.
1992//
1993void P_ShootSpecialLine
1994( mobj_t* thing,
1995 line_t* line )
1996{
1997 //jff 02/04/98 add check here for generalized linedef
1998 if (!demo_compatibility)
1999 {
2000 // pointer to line function is NULL by default, set non-null if
2001 // line special is gun triggered generalized linedef type
2002 int (*linefunc)(line_t *line)=NULL;
2003
2004 // check each range of generalized linedefs
2005 if ((unsigned)line->special >= GenEnd)
2006 {
2007 // Out of range for GenFloors
2008 }
2009 else if ((unsigned)line->special >= GenFloorBase)
2010 {
2011 if (!thing->player)
2012 if ((line->special & FloorChange) || !(line->special & FloorModel))
2013 return; // FloorModel is "Allow Monsters" if FloorChange is 0
2014 if (!line->tag) //jff 2/27/98 all gun generalized types require tag
2015 return;
2016
2017 linefunc = EV_DoGenFloor;
2018 }
2019 else if ((unsigned)line->special >= GenCeilingBase)
2020 {
2021 if (!thing->player)
2022 if ((line->special & CeilingChange) || !(line->special & CeilingModel))
2023 return; // CeilingModel is "Allow Monsters" if CeilingChange is 0
2024 if (!line->tag) //jff 2/27/98 all gun generalized types require tag
2025 return;
2026 linefunc = EV_DoGenCeiling;
2027 }
2028 else if ((unsigned)line->special >= GenDoorBase)
2029 {
2030 if (!thing->player)
2031 {
2032 if (!(line->special & DoorMonster))
2033 return; // monsters disallowed from this door
2034 if (line->flags & ML_SECRET) // they can't open secret doors either
2035 return;
2036 }
2037 if (!line->tag) //jff 3/2/98 all gun generalized types require tag
2038 return;
2039 linefunc = EV_DoGenDoor;
2040 }
2041 else if ((unsigned)line->special >= GenLockedBase)
2042 {
2043 if (!thing->player)
2044 return; // monsters disallowed from unlocking doors
2045 if (((line->special&TriggerType)==GunOnce) || ((line->special&TriggerType)==GunMany))
2046 { //jff 4/1/98 check for being a gun type before reporting door type
2047 if (!P_CanUnlockGenDoor(line,thing->player))
2048 return;
2049 }
2050 else
2051 return;
2052 if (!line->tag) //jff 2/27/98 all gun generalized types require tag
2053 return;
2054
2055 linefunc = EV_DoGenLockedDoor;
2056 }
2057 else if ((unsigned)line->special >= GenLiftBase)
2058 {
2059 if (!thing->player)
2060 if (!(line->special & LiftMonster))
2061 return; // monsters disallowed
2062 linefunc = EV_DoGenLift;
2063 }
2064 else if ((unsigned)line->special >= GenStairsBase)
2065 {
2066 if (!thing->player)
2067 if (!(line->special & StairMonster))
2068 return; // monsters disallowed
2069 if (!line->tag) //jff 2/27/98 all gun generalized types require tag
2070 return;
2071 linefunc = EV_DoGenStairs;
2072 }
2073 else if ((unsigned)line->special >= GenCrusherBase)
2074 {
2075 if (!thing->player)
2076 if (!(line->special & StairMonster))
2077 return; // monsters disallowed
2078 if (!line->tag) //jff 2/27/98 all gun generalized types require tag
2079 return;
2080 linefunc = EV_DoGenCrusher;
2081 }
2082
2083 if (linefunc)
2084 switch((line->special & TriggerType) >> TriggerTypeShift)
2085 {
2086 case GunOnce:
2087 if (linefunc(line))
2088 P_ChangeSwitchTexture(line,0);
2089 return;
2090 case GunMany:
2091 if (linefunc(line))
2092 P_ChangeSwitchTexture(line,1);
2093 return;
2094 default: // if not a gun type, do nothing here
2095 return;
2096 }
2097 }
2098
2099 // Impacts that other things can activate.
2100 if (!thing->player)
2101 {
2102 int ok = 0;
2103 switch(line->special)
2104 {
2105 case 46:
2106 // 46 GR Open door on impact weapon is monster activatable
2107 ok = 1;
2108 break;
2109 }
2110 if (!ok)
2111 return;
2112 }
2113
2114 if (!P_CheckTag(line)) //jff 2/27/98 disallow zero tag on some types
2115 return;
2116
2117 switch(line->special)
2118 {
2119 case 24:
2120 // 24 G1 raise floor to highest adjacent
2121 if (EV_DoFloor(line,raiseFloor) || demo_compatibility)
2122 P_ChangeSwitchTexture(line,0);
2123 break;
2124
2125 case 46:
2126 // 46 GR open door, stay open
2127 EV_DoDoor(line,p_open);
2128 P_ChangeSwitchTexture(line,1);
2129 break;
2130
2131 case 47:
2132 // 47 G1 raise floor to nearest and change texture and type
2133 if (EV_DoPlat(line,raiseToNearestAndChange,0) || demo_compatibility)
2134 P_ChangeSwitchTexture(line,0);
2135 break;
2136
2137 //jff 1/30/98 added new gun linedefs here
2138 // killough 1/31/98: added demo_compatibility check, added inner switch
2139
2140 default:
2141 if (!demo_compatibility)
2142 switch (line->special)
2143 {
2144 case 197:
2145 // Exit to next level
2146 // killough 10/98: prevent zombies from exiting levels
2147 if(thing->player && thing->player->health<=0 && !comp[comp_zombie])
2148 break;
2149 P_ChangeSwitchTexture(line,0);
2150 G_ExitLevel();
2151 break;
2152
2153 case 198:
2154 // Exit to secret level
2155 // killough 10/98: prevent zombies from exiting levels
2156 if(thing->player && thing->player->health<=0 && !comp[comp_zombie])
2157 break;
2158 P_ChangeSwitchTexture(line,0);
2159 G_SecretExitLevel();
2160 break;
2161 //jff end addition of new gun linedefs
2162 }
2163 break;
2164 }
2165}
2166
2167
2168//
2169// P_PlayerInSpecialSector()
2170//
2171// Called every tick frame
2172// that the player origin is in a special sector
2173//
2174// Changed to ignore sector types the engine does not recognize
2175//
2176void P_PlayerInSpecialSector (player_t* player)
2177{
2178 sector_t* sector;
2179
2180 sector = player->mo->subsector->sector;
2181
2182 // Falling, not all the way down yet?
2183 // Sector specials don't apply in mid-air
2184 if (player->mo->z != sector->floorheight)
2185 return;
2186
2187 // Has hit ground.
2188 //jff add if to handle old vs generalized types
2189 if (sector->special<32) // regular sector specials
2190 {
2191 switch (sector->special)
2192 {
2193 case 5:
2194 // 5/10 unit damage per 31 ticks
2195 if (!player->powers[pw_ironfeet])
2196 if (!(leveltime&0x1f))
2197 P_DamageMobj (player->mo, NULL, NULL, 10);
2198 break;
2199
2200 case 7:
2201 // 2/5 unit damage per 31 ticks
2202 if (!player->powers[pw_ironfeet])
2203 if (!(leveltime&0x1f))
2204 P_DamageMobj (player->mo, NULL, NULL, 5);
2205 break;
2206
2207 case 16:
2208 // 10/20 unit damage per 31 ticks
2209 case 4:
2210 // 10/20 unit damage plus blinking light (light already spawned)
2211 if (!player->powers[pw_ironfeet]
2212 || (P_Random(pr_slimehurt)<5) ) // even with suit, take damage
2213 {
2214 if (!(leveltime&0x1f))
2215 P_DamageMobj (player->mo, NULL, NULL, 20);
2216 }
2217 break;
2218
2219 case 9:
2220 // Tally player in secret sector, clear secret special
2221 player->secretcount++;
2222 sector->special = 0;
2223 break;
2224
2225 case 11:
2226 // Exit on health < 11, take 10/20 damage per 31 ticks
2227 if (comp[comp_god]) /* killough 2/21/98: add compatibility switch */
2228 player->cheats &= ~CF_GODMODE; // on godmode cheat clearing
2229 // does not affect invulnerability
2230 if (!(leveltime&0x1f))
2231 P_DamageMobj (player->mo, NULL, NULL, 20);
2232
2233 if (player->health <= 10)
2234 G_ExitLevel();
2235 break;
2236
2237 default:
2238 //jff 1/24/98 Don't exit as DOOM2 did, just ignore
2239 break;
2240 };
2241 }
2242 else //jff 3/14/98 handle extended sector types for secrets and damage
2243 {
2244 switch ((sector->special&DAMAGE_MASK)>>DAMAGE_SHIFT)
2245 {
2246 case 0: // no damage
2247 break;
2248 case 1: // 2/5 damage per 31 ticks
2249 if (!player->powers[pw_ironfeet])
2250 if (!(leveltime&0x1f))
2251 P_DamageMobj (player->mo, NULL, NULL, 5);
2252 break;
2253 case 2: // 5/10 damage per 31 ticks
2254 if (!player->powers[pw_ironfeet])
2255 if (!(leveltime&0x1f))
2256 P_DamageMobj (player->mo, NULL, NULL, 10);
2257 break;
2258 case 3: // 10/20 damage per 31 ticks
2259 if (!player->powers[pw_ironfeet]
2260 || (P_Random(pr_slimehurt)<5)) // take damage even with suit
2261 {
2262 if (!(leveltime&0x1f))
2263 P_DamageMobj (player->mo, NULL, NULL, 20);
2264 }
2265 break;
2266 }
2267 if (sector->special&SECRET_MASK)
2268 {
2269 player->secretcount++;
2270 sector->special &= ~SECRET_MASK;
2271 if (sector->special<32) // if all extended bits clear,
2272 sector->special=0; // sector is not special anymore
2273 }
2274
2275 // phares 3/19/98:
2276 //
2277 // If FRICTION_MASK or PUSH_MASK is set, we don't care at this
2278 // point, since the code to deal with those situations is
2279 // handled by Thinkers.
2280
2281 }
2282}
2283
2284//
2285// P_UpdateSpecials()
2286//
2287// Check level timer, frag counter,
2288// animate flats, scroll walls,
2289// change button textures
2290//
2291// Reads and modifies globals:
2292// levelTimer, levelTimeCount,
2293// levelFragLimit, levelFragLimitCount
2294//
2295
2296boolean levelTimer;
2297int levelTimeCount;
2298boolean levelFragLimit; // Ty 03/18/98 Added -frags support
2299int levelFragLimitCount; // Ty 03/18/98 Added -frags support
2300
2301void P_UpdateSpecials (void)
2302{
2303 anim_t* anim;
2304 int pic;
2305 int i;
2306
2307 // Downcount level timer, exit level if elapsed
2308 if (levelTimer == true)
2309 {
2310 levelTimeCount--;
2311 if (!levelTimeCount)
2312 G_ExitLevel();
2313 }
2314
2315 // Check frag counters, if frag limit reached, exit level // Ty 03/18/98
2316 // Seems like the total frags should be kept in a simple
2317 // array somewhere, but until they are...
2318 if (levelFragLimit == true) // we used -frags so compare count
2319 {
2320 int k,m,fragcount,exitflag=false;
2321 for (k=0;k<MAXPLAYERS;k++)
2322 {
2323 if (!playeringame[k]) continue;
2324 fragcount = 0;
2325 for (m=0;m<MAXPLAYERS;m++)
2326 {
2327 if (!playeringame[m]) continue;
2328 fragcount += (m!=k)? players[k].frags[m] : -players[k].frags[m];
2329 }
2330 if (fragcount >= levelFragLimitCount) exitflag = true;
2331 if (exitflag == true) break; // skip out of the loop--we're done
2332 }
2333 if (exitflag == true)
2334 G_ExitLevel();
2335 }
2336
2337 // Animate flats and textures globally
2338 for (anim = anims ; anim < lastanim ; anim++)
2339 {
2340 for (i=anim->basepic ; i<anim->basepic+anim->numpics ; i++)
2341 {
2342 pic = anim->basepic + ( (leveltime/anim->speed + i)%anim->numpics );
2343 if (anim->istexture)
2344 texturetranslation[i] = pic;
2345 else
2346 flattranslation[i] = pic;
2347 }
2348 }
2349
2350 // Check buttons (retriggerable switches) and change texture on timeout
2351 for (i = 0; i < MAXBUTTONS; i++)
2352 if (buttonlist[i].btimer)
2353 {
2354 buttonlist[i].btimer--;
2355 if (!buttonlist[i].btimer)
2356 {
2357 switch(buttonlist[i].where)
2358 {
2359 case top:
2360 sides[buttonlist[i].line->sidenum[0]].toptexture =
2361 buttonlist[i].btexture;
2362 break;
2363
2364 case middle:
2365 sides[buttonlist[i].line->sidenum[0]].midtexture =
2366 buttonlist[i].btexture;
2367 break;
2368
2369 case bottom:
2370 sides[buttonlist[i].line->sidenum[0]].bottomtexture =
2371 buttonlist[i].btexture;
2372 break;
2373 }
2374 S_StartSound((mobj_t *)&buttonlist[i].soundorg,sfx_swtchn);
2375 memset(&buttonlist[i],0,sizeof(button_t));
2376 }
2377 }
2378}
2379
2380//////////////////////////////////////////////////////////////////////
2381//
2382// Sector and Line special thinker spawning at level startup
2383//
2384//////////////////////////////////////////////////////////////////////
2385
2386//
2387// P_SpawnSpecials
2388// After the map has been loaded,
2389// scan for specials that spawn thinkers
2390//
2391
2392// Parses command line parameters.
2393void P_SpawnSpecials (void)
2394{
2395 sector_t* sector;
2396 int i;
2397 int episode;
2398
2399 episode = 1;
2400 if (W_CheckNumForName("texture2") >= 0)
2401 episode = 2;
2402
2403 // See if -timer needs to be used.
2404 levelTimer = false;
2405
2406 i = M_CheckParm("-avg"); // Austin Virtual Gaming 20 min timer on DM play
2407 if (i && deathmatch)
2408 {
2409 levelTimer = true;
2410 levelTimeCount = 20 * 60 * TICRATE;
2411 }
2412
2413 i = M_CheckParm("-timer"); // user defined timer on game play
2414 if (i && deathmatch)
2415 {
2416 int time;
2417 time = atoi(myargv[i+1]) * 60 * TICRATE;
2418 levelTimer = true;
2419 levelTimeCount = time;
2420 }
2421
2422 // See if -frags has been used
2423 levelFragLimit = false;
2424 i = M_CheckParm("-frags"); // Ty 03/18/98 Added -frags support
2425 if (i && deathmatch)
2426 {
2427 int frags;
2428 frags = atoi(myargv[i+1]);
2429 if (frags <= 0) frags = 10; // default 10 if no count provided
2430 levelFragLimit = true;
2431 levelFragLimitCount = frags;
2432 }
2433
2434
2435 // Init special sectors.
2436 sector = sectors;
2437 for (i=0 ; i<numsectors ; i++, sector++)
2438 {
2439 if (!sector->special)
2440 continue;
2441
2442 if (sector->special&SECRET_MASK) //jff 3/15/98 count extended
2443 totalsecret++; // secret sectors too
2444
2445 switch (sector->special&31)
2446 {
2447 case 1:
2448 // random off
2449 P_SpawnLightFlash (sector);
2450 break;
2451
2452 case 2:
2453 // strobe fast
2454 P_SpawnStrobeFlash(sector,FASTDARK,0);
2455 break;
2456
2457 case 3:
2458 // strobe slow
2459 P_SpawnStrobeFlash(sector,SLOWDARK,0);
2460 break;
2461
2462 case 4:
2463 // strobe fast/death slime
2464 P_SpawnStrobeFlash(sector,FASTDARK,0);
2465 sector->special |= 3<<DAMAGE_SHIFT; //jff 3/14/98 put damage bits in
2466 break;
2467
2468 case 8:
2469 // glowing light
2470 P_SpawnGlowingLight(sector);
2471 break;
2472 case 9:
2473 // secret sector
2474 if (sector->special<32) //jff 3/14/98 bits don't count unless not
2475 totalsecret++; // a generalized sector type
2476 break;
2477
2478 case 10:
2479 // door close in 30 seconds
2480 P_SpawnDoorCloseIn30 (sector);
2481 break;
2482
2483 case 12:
2484 // sync strobe slow
2485 P_SpawnStrobeFlash (sector, SLOWDARK, 1);
2486 break;
2487
2488 case 13:
2489 // sync strobe fast
2490 P_SpawnStrobeFlash (sector, FASTDARK, 1);
2491 break;
2492
2493 case 14:
2494 // door raise in 5 minutes
2495 P_SpawnDoorRaiseIn5Mins (sector, i);
2496 break;
2497
2498 case 17:
2499 // fire flickering
2500 P_SpawnFireFlicker(sector);
2501 break;
2502 }
2503 }
2504
2505 P_RemoveAllActiveCeilings(); // jff 2/22/98 use killough's scheme
2506
2507 P_RemoveAllActivePlats(); // killough
2508
2509 for (i = 0;i < MAXBUTTONS;i++)
2510 memset(&buttonlist[i],0,sizeof(button_t));
2511
2512 // P_InitTagLists() must be called before P_FindSectorFromLineTag()
2513 // or P_FindLineFromLineTag() can be called.
2514
2515 P_InitTagLists(); // killough 1/30/98: Create xref tables for tags
2516
2517 P_SpawnScrollers(); // killough 3/7/98: Add generalized scrollers
2518
2519 P_SpawnFriction(); // phares 3/12/98: New friction model using linedefs
2520
2521 P_SpawnPushers(); // phares 3/20/98: New pusher model using linedefs
2522
2523 for (i=0; i<numlines; i++)
2524 switch (lines[i].special)
2525 {
2526 int s, sec;
2527
2528 // killough 3/7/98:
2529 // support for drawn heights coming from different sector
2530 case 242:
2531 sec = sides[*lines[i].sidenum].sector-sectors;
2532 for (s = -1; (s = P_FindSectorFromLineTag(lines+i,s)) >= 0;)
2533 sectors[s].heightsec = sec;
2534 break;
2535
2536 // killough 3/16/98: Add support for setting
2537 // floor lighting independently (e.g. lava)
2538 case 213:
2539 sec = sides[*lines[i].sidenum].sector-sectors;
2540 for (s = -1; (s = P_FindSectorFromLineTag(lines+i,s)) >= 0;)
2541 sectors[s].floorlightsec = sec;
2542 break;
2543
2544 // killough 4/11/98: Add support for setting
2545 // ceiling lighting independently
2546 case 261:
2547 sec = sides[*lines[i].sidenum].sector-sectors;
2548 for (s = -1; (s = P_FindSectorFromLineTag(lines+i,s)) >= 0;)
2549 sectors[s].ceilinglightsec = sec;
2550 break;
2551
2552 // killough 10/98:
2553 //
2554 // Support for sky textures being transferred from sidedefs.
2555 // Allows scrolling and other effects (but if scrolling is
2556 // used, then the same sector tag needs to be used for the
2557 // sky sector, the sky-transfer linedef, and the scroll-effect
2558 // linedef). Still requires user to use F_SKY1 for the floor
2559 // or ceiling texture, to distinguish floor and ceiling sky.
2560
2561 case 271: // Regular sky
2562 case 272: // Same, only flipped
2563 for (s = -1; (s = P_FindSectorFromLineTag(lines+i,s)) >= 0;)
2564 sectors[s].sky = i | PL_SKYFLAT;
2565 break;
2566 }
2567}
2568
2569// killough 2/28/98:
2570//
2571// This function, with the help of r_plane.c and r_bsp.c, supports generalized
2572// scrolling floors and walls, with optional mobj-carrying properties, e.g.
2573// conveyor belts, rivers, etc. A linedef with a special type affects all
2574// tagged sectors the same way, by creating scrolling and/or object-carrying
2575// properties. Multiple linedefs may be used on the same sector and are
2576// cumulative, although the special case of scrolling a floor and carrying
2577// things on it, requires only one linedef. The linedef's direction determines
2578// the scrolling direction, and the linedef's length determines the scrolling
2579// speed. This was designed so that an edge around the sector could be used to
2580// control the direction of the sector's scrolling, which is usually what is
2581// desired.
2582//
2583// Process the active scrollers.
2584//
2585// This is the main scrolling code
2586// killough 3/7/98
2587
2588void T_Scroll(scroll_t *s)
2589{
2590 fixed_t dx = s->dx, dy = s->dy;
2591
2592 if (s->control != -1)
2593 { // compute scroll amounts based on a sector's height changes
2594 fixed_t height = sectors[s->control].floorheight +
2595 sectors[s->control].ceilingheight;
2596 fixed_t delta = height - s->last_height;
2597 s->last_height = height;
2598 dx = FixedMul(dx, delta);
2599 dy = FixedMul(dy, delta);
2600 }
2601
2602 // killough 3/14/98: Add acceleration
2603 if (s->accel)
2604 {
2605 s->vdx = dx += s->vdx;
2606 s->vdy = dy += s->vdy;
2607 }
2608
2609 if (!(dx | dy)) // no-op if both (x,y) offsets 0
2610 return;
2611
2612 switch (s->type)
2613 {
2614 side_t *side;
2615 sector_t *sec;
2616 fixed_t height, waterheight; // killough 4/4/98: add waterheight
2617 msecnode_t *node;
2618 mobj_t *thing;
2619
2620 case sc_side: // killough 3/7/98: Scroll wall texture
2621 side = sides + s->affectee;
2622 side->textureoffset += dx;
2623 side->rowoffset += dy;
2624 break;
2625
2626 case sc_floor: // killough 3/7/98: Scroll floor texture
2627 sec = sectors + s->affectee;
2628 sec->floor_xoffs += dx;
2629 sec->floor_yoffs += dy;
2630 break;
2631
2632 case sc_ceiling: // killough 3/7/98: Scroll ceiling texture
2633 sec = sectors + s->affectee;
2634 sec->ceiling_xoffs += dx;
2635 sec->ceiling_yoffs += dy;
2636 break;
2637
2638 case sc_carry:
2639
2640 // killough 3/7/98: Carry things on floor
2641 // killough 3/20/98: use new sector list which reflects true members
2642 // killough 3/27/98: fix carrier bug
2643 // killough 4/4/98: Underwater, carry things even w/o gravity
2644
2645 sec = sectors + s->affectee;
2646 height = sec->floorheight;
2647 waterheight = sec->heightsec != -1 &&
2648 sectors[sec->heightsec].floorheight > height ?
2649 sectors[sec->heightsec].floorheight : INT_MIN;
2650
2651 for (node = sec->touching_thinglist; node; node = node->m_snext)
2652 if (!((thing = node->m_thing)->flags & MF_NOCLIP) &&
2653 (!(thing->flags & MF_NOGRAVITY || thing->z > height) ||
2654 thing->z < waterheight))
2655 {
2656 // Move objects only if on floor or underwater,
2657 // non-floating, and clipped.
2658 thing->momx += dx;
2659 thing->momy += dy;
2660 }
2661 break;
2662
2663 case sc_carry_ceiling: // to be added later
2664 break;
2665 }
2666}
2667
2668//
2669// Add_Scroller()
2670//
2671// Add a generalized scroller to the thinker list.
2672//
2673// type: the enumerated type of scrolling: floor, ceiling, floor carrier,
2674// wall, floor carrier & scroller
2675//
2676// (dx,dy): the direction and speed of the scrolling or its acceleration
2677//
2678// control: the sector whose heights control this scroller's effect
2679// remotely, or -1 if no control sector
2680//
2681// affectee: the index of the affected object (sector or sidedef)
2682//
2683// accel: non-zero if this is an accelerative effect
2684//
2685
2686static void Add_Scroller(int type, fixed_t dx, fixed_t dy,
2687 int control, int affectee, int accel)
2688{
2689 scroll_t *s = Z_Malloc(sizeof *s, PU_LEVSPEC, 0);
2690 s->thinker.function = T_Scroll;
2691 s->type = type;
2692 s->dx = dx;
2693 s->dy = dy;
2694 s->accel = accel;
2695 s->vdx = s->vdy = 0;
2696 if ((s->control = control) != -1)
2697 s->last_height =
2698 sectors[control].floorheight + sectors[control].ceilingheight;
2699 s->affectee = affectee;
2700 P_AddThinker(&s->thinker);
2701}
2702
2703// Adds wall scroller. Scroll amount is rotated with respect to wall's
2704// linedef first, so that scrolling towards the wall in a perpendicular
2705// direction is translated into vertical motion, while scrolling along
2706// the wall in a parallel direction is translated into horizontal motion.
2707//
2708// killough 5/25/98: cleaned up arithmetic to avoid drift due to roundoff
2709//
2710// killough 10/98:
2711// fix scrolling aliasing problems, caused by long linedefs causing overflowing
2712
2713static void Add_WallScroller(fixed_t dx, fixed_t dy, const line_t *l,
2714 int control, int accel)
2715{
2716 fixed_t x = D_abs(l->dx), y = D_abs(l->dy), d;
2717 if (y > x)
2718 d = x, x = y, y = d;
2719 d = FixedDiv(x, finesine[(tantoangle[FixedDiv(y,x) >> DBITS] + ANG90)
2720 >> ANGLETOFINESHIFT]);
2721
2722 // CPhipps - Import scroller calc overflow fix, compatibility optioned
2723 if (compatibility_level >= lxdoom_1_compatibility) {
2724 x = (fixed_t)(((int_64_t)dy * -(int_64_t)l->dy - (int_64_t)dx * (int_64_t)l->dx) / (int_64_t)d); // killough 10/98:
2725 y = (fixed_t)(((int_64_t)dy * (int_64_t)l->dx - (int_64_t)dx * (int_64_t)l->dy) / (int_64_t)d); // Use long long arithmetic
2726 } else {
2727 x = -FixedDiv(FixedMul(dy, l->dy) + FixedMul(dx, l->dx), d);
2728 y = -FixedDiv(FixedMul(dx, l->dy) - FixedMul(dy, l->dx), d);
2729 }
2730 Add_Scroller(sc_side, x, y, control, *l->sidenum, accel);
2731}
2732
2733// Amount (dx,dy) vector linedef is shifted right to get scroll amount
2734#define SCROLL_SHIFT 5
2735
2736// Factor to scale scrolling effect into mobj-carrying properties = 3/32.
2737// (This is so scrolling floors and objects on them can move at same speed.)
2738#define CARRYFACTOR ((fixed_t)(FRACUNIT*.09375))
2739
2740// Initialize the scrollers
2741static void P_SpawnScrollers(void)
2742{
2743 int i;
2744 line_t *l = lines;
2745
2746 for (i=0;i<numlines;i++,l++)
2747 {
2748 fixed_t dx = l->dx >> SCROLL_SHIFT; // direction and speed of scrolling
2749 fixed_t dy = l->dy >> SCROLL_SHIFT;
2750 int control = -1, accel = 0; // no control sector or acceleration
2751 int special = l->special;
2752
2753 // killough 3/7/98: Types 245-249 are same as 250-254 except that the
2754 // first side's sector's heights cause scrolling when they change, and
2755 // this linedef controls the direction and speed of the scrolling. The
2756 // most complicated linedef since donuts, but powerful :)
2757 //
2758 // killough 3/15/98: Add acceleration. Types 214-218 are the same but
2759 // are accelerative.
2760
2761 if (special >= 245 && special <= 249) // displacement scrollers
2762 {
2763 special += 250-245;
2764 control = sides[*l->sidenum].sector - sectors;
2765 }
2766 else
2767 if (special >= 214 && special <= 218) // accelerative scrollers
2768 {
2769 accel = 1;
2770 special += 250-214;
2771 control = sides[*l->sidenum].sector - sectors;
2772 }
2773
2774 switch (special)
2775 {
2776 register int s;
2777
2778 case 250: // scroll effect ceiling
2779 for (s=-1; (s = P_FindSectorFromLineTag(l,s)) >= 0;)
2780 Add_Scroller(sc_ceiling, -dx, dy, control, s, accel);
2781 break;
2782
2783 case 251: // scroll effect floor
2784 case 253: // scroll and carry objects on floor
2785 for (s=-1; (s = P_FindSectorFromLineTag(l,s)) >= 0;)
2786 Add_Scroller(sc_floor, -dx, dy, control, s, accel);
2787 if (special != 253)
2788 break;
2789
2790 case 252: // carry objects on floor
2791 dx = FixedMul(dx,CARRYFACTOR);
2792 dy = FixedMul(dy,CARRYFACTOR);
2793 for (s=-1; (s = P_FindSectorFromLineTag(l,s)) >= 0;)
2794 Add_Scroller(sc_carry, dx, dy, control, s, accel);
2795 break;
2796
2797 // killough 3/1/98: scroll wall according to linedef
2798 // (same direction and speed as scrolling floors)
2799 case 254:
2800 for (s=-1; (s = P_FindLineFromLineTag(l,s)) >= 0;)
2801 if (s != i)
2802 Add_WallScroller(dx, dy, lines+s, control, accel);
2803 break;
2804
2805 case 255: // killough 3/2/98: scroll according to sidedef offsets
2806 s = lines[i].sidenum[0];
2807 Add_Scroller(sc_side, -sides[s].textureoffset,
2808 sides[s].rowoffset, -1, s, accel);
2809 break;
2810
2811 case 48: // scroll first side
2812 Add_Scroller(sc_side, FRACUNIT, 0, -1, lines[i].sidenum[0], accel);
2813 break;
2814
2815 case 85: // jff 1/30/98 2-way scroll
2816 Add_Scroller(sc_side, -FRACUNIT, 0, -1, lines[i].sidenum[0], accel);
2817 break;
2818 }
2819 }
2820}
2821
2822// killough 3/7/98 -- end generalized scroll effects
2823
2824////////////////////////////////////////////////////////////////////////////
2825//
2826// FRICTION EFFECTS
2827//
2828// phares 3/12/98: Start of friction effects
2829//
2830// As the player moves, friction is applied by decreasing the x and y
2831// momentum values on each tic. By varying the percentage of decrease,
2832// we can simulate muddy or icy conditions. In mud, the player slows
2833// down faster. In ice, the player slows down more slowly.
2834//
2835// The amount of friction change is controlled by the length of a linedef
2836// with type 223. A length < 100 gives you mud. A length > 100 gives you ice.
2837//
2838// Also, each sector where these effects are to take place is given a
2839// new special type _______. Changing the type value at runtime allows
2840// these effects to be turned on or off.
2841//
2842// Sector boundaries present problems. The player should experience these
2843// friction changes only when his feet are touching the sector floor. At
2844// sector boundaries where floor height changes, the player can find
2845// himself still 'in' one sector, but with his feet at the floor level
2846// of the next sector (steps up or down). To handle this, Thinkers are used
2847// in icy/muddy sectors. These thinkers examine each object that is touching
2848// their sectors, looking for players whose feet are at the same level as
2849// their floors. Players satisfying this condition are given new friction
2850// values that are applied by the player movement code later.
2851//
2852// killough 8/28/98:
2853//
2854// Completely redid code, which did not need thinkers, and which put a heavy
2855// drag on CPU. Friction is now a property of sectors, NOT objects inside
2856// them. All objects, not just players, are affected by it, if they touch
2857// the sector's floor. Code simpler and faster, only calling on friction
2858// calculations when an object needs friction considered, instead of doing
2859// friction calculations on every sector during every tic.
2860//
2861// Although this -might- ruin Boom demo sync involving friction, it's the only
2862// way, short of code explosion, to fix the original design bug. Fixing the
2863// design bug in Boom's original friction code, while maintaining demo sync
2864// under every conceivable circumstance, would double or triple code size, and
2865// would require maintenance of buggy legacy code which is only useful for old
2866// demos. Doom demos, which are more important IMO, are not affected by this
2867// change.
2868//
2869/////////////////////////////
2870//
2871// Initialize the sectors where friction is increased or decreased
2872
2873static void P_SpawnFriction(void)
2874{
2875 int i;
2876 line_t *l = lines;
2877
2878 // killough 8/28/98: initialize all sectors to normal friction first
2879 for (i = 0; i < numsectors; i++)
2880 {
2881 sectors[i].friction = ORIG_FRICTION;
2882 sectors[i].movefactor = ORIG_FRICTION_FACTOR;
2883 }
2884
2885 for (i = 0 ; i < numlines ; i++,l++)
2886 if (l->special == 223)
2887 {
2888 int length = P_AproxDistance(l->dx,l->dy)>>FRACBITS;
2889 int friction = (0x1EB8*length)/0x80 + 0xD000;
2890 int movefactor, s;
2891
2892 // The following check might seem odd. At the time of movement,
2893 // the move distance is multiplied by 'friction/0x10000', so a
2894 // higher friction value actually means 'less friction'.
2895
2896 if (friction > ORIG_FRICTION) // ice
2897 movefactor = ((0x10092 - friction)*(0x70))/0x158;
2898 else
2899 movefactor = ((friction - 0xDB34)*(0xA))/0x80;
2900
2901 if (mbf_features)
2902 { // killough 8/28/98: prevent odd situations
2903 if (friction > FRACUNIT)
2904 friction = FRACUNIT;
2905 if (friction < 0)
2906 friction = 0;
2907 if (movefactor < 32)
2908 movefactor = 32;
2909 }
2910
2911 for (s = -1; (s = P_FindSectorFromLineTag(l,s)) >= 0 ; )
2912 {
2913 // killough 8/28/98:
2914 //
2915 // Instead of spawning thinkers, which are slow and expensive,
2916 // modify the sector's own friction values. Friction should be
2917 // a property of sectors, not objects which reside inside them.
2918 // Original code scanned every object in every friction sector
2919 // on every tic, adjusting its friction, putting unnecessary
2920 // drag on CPU. New code adjusts friction of sector only once
2921 // at level startup, and then uses this friction value.
2922
2923 sectors[s].friction = friction;
2924 sectors[s].movefactor = movefactor;
2925 }
2926 }
2927}
2928
2929//
2930// phares 3/12/98: End of friction effects
2931//
2932////////////////////////////////////////////////////////////////////////////
2933
2934////////////////////////////////////////////////////////////////////////////
2935//
2936// PUSH/PULL EFFECT
2937//
2938// phares 3/20/98: Start of push/pull effects
2939//
2940// This is where push/pull effects are applied to objects in the sectors.
2941//
2942// There are four kinds of push effects
2943//
2944// 1) Pushing Away
2945//
2946// Pushes you away from a point source defined by the location of an
2947// MT_PUSH Thing. The force decreases linearly with distance from the
2948// source. This force crosses sector boundaries and is felt w/in a circle
2949// whose center is at the MT_PUSH. The force is felt only if the point
2950// MT_PUSH can see the target object.
2951//
2952// 2) Pulling toward
2953//
2954// Same as Pushing Away except you're pulled toward an MT_PULL point
2955// source. This force crosses sector boundaries and is felt w/in a circle
2956// whose center is at the MT_PULL. The force is felt only if the point
2957// MT_PULL can see the target object.
2958//
2959// 3) Wind
2960//
2961// Pushes you in a constant direction. Full force above ground, half
2962// force on the ground, nothing if you're below it (water).
2963//
2964// 4) Current
2965//
2966// Pushes you in a constant direction. No force above ground, full
2967// force if on the ground or below it (water).
2968//
2969// The magnitude of the force is controlled by the length of a controlling
2970// linedef. The force vector for types 3 & 4 is determined by the angle
2971// of the linedef, and is constant.
2972//
2973// For each sector where these effects occur, the sector special type has
2974// to have the PUSH_MASK bit set. If this bit is turned off by a switch
2975// at run-time, the effect will not occur. The controlling sector for
2976// types 1 & 2 is the sector containing the MT_PUSH/MT_PULL Thing.
2977
2978
2979#define PUSH_FACTOR 7
2980
2981/////////////////////////////
2982//
2983// Add a push thinker to the thinker list
2984
2985static void Add_Pusher(int type, int x_mag, int y_mag, mobj_t* source, int affectee)
2986{
2987 pusher_t *p = Z_Malloc(sizeof *p, PU_LEVSPEC, 0);
2988
2989 p->thinker.function = T_Pusher;
2990 p->source = source;
2991 p->type = type;
2992 p->x_mag = x_mag>>FRACBITS;
2993 p->y_mag = y_mag>>FRACBITS;
2994 p->magnitude = P_AproxDistance(p->x_mag,p->y_mag);
2995 if (source) // point source exist?
2996 {
2997 p->radius = (p->magnitude)<<(FRACBITS+1); // where force goes to zero
2998 p->x = p->source->x;
2999 p->y = p->source->y;
3000 }
3001 p->affectee = affectee;
3002 P_AddThinker(&p->thinker);
3003}
3004
3005/////////////////////////////
3006//
3007// PIT_PushThing determines the angle and magnitude of the effect.
3008// The object's x and y momentum values are changed.
3009//
3010// tmpusher belongs to the point source (MT_PUSH/MT_PULL).
3011//
3012// killough 10/98: allow to affect things besides players
3013
3014pusher_t* tmpusher; // pusher structure for blockmap searches
3015
3016boolean PIT_PushThing(mobj_t* thing)
3017{
3018 /* killough 10/98: made more general */
3019 if (!mbf_features ?
3020 thing->player && !(thing->flags & (MF_NOCLIP | MF_NOGRAVITY)) :
3021 (sentient(thing) || thing->flags & MF_SHOOTABLE) &&
3022 !(thing->flags & MF_NOCLIP))
3023 {
3024 angle_t pushangle;
3025 fixed_t speed;
3026 fixed_t sx = tmpusher->x;
3027 fixed_t sy = tmpusher->y;
3028
3029 speed = (tmpusher->magnitude -
3030 ((P_AproxDistance(thing->x - sx,thing->y - sy)
3031 >>FRACBITS)>>1))<<(FRACBITS-PUSH_FACTOR-1);
3032
3033 // killough 10/98: make magnitude decrease with square
3034 // of distance, making it more in line with real nature,
3035 // so long as it's still in range with original formula.
3036 //
3037 // Removes angular distortion, and makes effort required
3038 // to stay close to source, grow increasingly hard as you
3039 // get closer, as expected. Still, it doesn't consider z :(
3040
3041 if (speed > 0 && mbf_features)
3042 {
3043 int x = (thing->x-sx) >> FRACBITS;
3044 int y = (thing->y-sy) >> FRACBITS;
3045 speed = (int)(((uint_64_t) tmpusher->magnitude << 23) / (x*x+y*y+1));
3046 }
3047
3048 // If speed <= 0, you're outside the effective radius. You also have
3049 // to be able to see the push/pull source point.
3050
3051 if (speed > 0 && P_CheckSight(thing,tmpusher->source))
3052 {
3053 pushangle = R_PointToAngle2(thing->x,thing->y,sx,sy);
3054 if (tmpusher->source->type == MT_PUSH)
3055 pushangle += ANG180; // away
3056 pushangle >>= ANGLETOFINESHIFT;
3057 thing->momx += FixedMul(speed,finecosine[pushangle]);
3058 thing->momy += FixedMul(speed,finesine[pushangle]);
3059 }
3060 }
3061 return true;
3062}
3063
3064/////////////////////////////
3065//
3066// T_Pusher looks for all objects that are inside the radius of
3067// the effect.
3068//
3069
3070void T_Pusher(pusher_t *p)
3071{
3072 sector_t *sec;
3073 mobj_t *thing;
3074 msecnode_t* node;
3075 int xspeed,yspeed;
3076 int xl,xh,yl,yh,bx,by;
3077 int radius;
3078 int ht = 0;
3079
3080 if (!allow_pushers)
3081 return;
3082
3083 sec = sectors + p->affectee;
3084
3085 // Be sure the special sector type is still turned on. If so, proceed.
3086 // Else, bail out; the sector type has been changed on us.
3087
3088 if (!(sec->special & PUSH_MASK))
3089 return;
3090
3091 // For constant pushers (wind/current) there are 3 situations:
3092 //
3093 // 1) Affected Thing is above the floor.
3094 //
3095 // Apply the full force if wind, no force if current.
3096 //
3097 // 2) Affected Thing is on the ground.
3098 //
3099 // Apply half force if wind, full force if current.
3100 //
3101 // 3) Affected Thing is below the ground (underwater effect).
3102 //
3103 // Apply no force if wind, full force if current.
3104
3105 if (p->type == p_push)
3106 {
3107
3108 // Seek out all pushable things within the force radius of this
3109 // point pusher. Crosses sectors, so use blockmap.
3110
3111 tmpusher = p; // MT_PUSH/MT_PULL point source
3112 radius = p->radius; // where force goes to zero
3113 tmbbox[BOXTOP] = p->y + radius;
3114 tmbbox[BOXBOTTOM] = p->y - radius;
3115 tmbbox[BOXRIGHT] = p->x + radius;
3116 tmbbox[BOXLEFT] = p->x - radius;
3117
3118 xl = (tmbbox[BOXLEFT] - bmaporgx - MAXRADIUS)>>MAPBLOCKSHIFT;
3119 xh = (tmbbox[BOXRIGHT] - bmaporgx + MAXRADIUS)>>MAPBLOCKSHIFT;
3120 yl = (tmbbox[BOXBOTTOM] - bmaporgy - MAXRADIUS)>>MAPBLOCKSHIFT;
3121 yh = (tmbbox[BOXTOP] - bmaporgy + MAXRADIUS)>>MAPBLOCKSHIFT;
3122 for (bx=xl ; bx<=xh ; bx++)
3123 for (by=yl ; by<=yh ; by++)
3124 P_BlockThingsIterator(bx,by,PIT_PushThing);
3125 return;
3126 }
3127
3128 // constant pushers p_wind and p_current
3129
3130 if (sec->heightsec != -1) // special water sector?
3131 ht = sectors[sec->heightsec].floorheight;
3132 node = sec->touching_thinglist; // things touching this sector
3133 for ( ; node ; node = node->m_snext)
3134 {
3135 thing = node->m_thing;
3136 if (!thing->player || (thing->flags & (MF_NOGRAVITY | MF_NOCLIP)))
3137 continue;
3138 if (p->type == p_wind)
3139 {
3140 if (sec->heightsec == -1) // NOT special water sector
3141 if (thing->z > thing->floorz) // above ground
3142 {
3143 xspeed = p->x_mag; // full force
3144 yspeed = p->y_mag;
3145 }
3146 else // on ground
3147 {
3148 xspeed = (p->x_mag)>>1; // half force
3149 yspeed = (p->y_mag)>>1;
3150 }
3151 else // special water sector
3152 {
3153 if (thing->z > ht) // above ground
3154 {
3155 xspeed = p->x_mag; // full force
3156 yspeed = p->y_mag;
3157 }
3158 else if (thing->player->viewz < ht) // underwater
3159 xspeed = yspeed = 0; // no force
3160 else // wading in water
3161 {
3162 xspeed = (p->x_mag)>>1; // half force
3163 yspeed = (p->y_mag)>>1;
3164 }
3165 }
3166 }
3167 else // p_current
3168 {
3169 if (sec->heightsec == -1) // NOT special water sector
3170 if (thing->z > sec->floorheight) // above ground
3171 xspeed = yspeed = 0; // no force
3172 else // on ground
3173 {
3174 xspeed = p->x_mag; // full force
3175 yspeed = p->y_mag;
3176 }
3177 else // special water sector
3178 if (thing->z > ht) // above ground
3179 xspeed = yspeed = 0; // no force
3180 else // underwater
3181 {
3182 xspeed = p->x_mag; // full force
3183 yspeed = p->y_mag;
3184 }
3185 }
3186 thing->momx += xspeed<<(FRACBITS-PUSH_FACTOR);
3187 thing->momy += yspeed<<(FRACBITS-PUSH_FACTOR);
3188 }
3189}
3190
3191/////////////////////////////
3192//
3193// P_GetPushThing() returns a pointer to an MT_PUSH or MT_PULL thing,
3194// NULL otherwise.
3195
3196mobj_t* P_GetPushThing(int s)
3197{
3198 mobj_t* thing;
3199 sector_t* sec;
3200
3201 sec = sectors + s;
3202 thing = sec->thinglist;
3203 while (thing)
3204 {
3205 switch(thing->type)
3206 {
3207 case MT_PUSH:
3208 case MT_PULL:
3209 return thing;
3210 default:
3211 break;
3212 }
3213 thing = thing->snext;
3214 }
3215 return NULL;
3216}
3217
3218/////////////////////////////
3219//
3220// Initialize the sectors where pushers are present
3221//
3222
3223static void P_SpawnPushers(void)
3224{
3225 int i;
3226 line_t *l = lines;
3227 register int s;
3228 mobj_t* thing;
3229
3230 for (i = 0 ; i < numlines ; i++,l++)
3231 switch(l->special)
3232 {
3233 case 224: // wind
3234 for (s = -1; (s = P_FindSectorFromLineTag(l,s)) >= 0 ; )
3235 Add_Pusher(p_wind,l->dx,l->dy,NULL,s);
3236 break;
3237 case 225: // current
3238 for (s = -1; (s = P_FindSectorFromLineTag(l,s)) >= 0 ; )
3239 Add_Pusher(p_current,l->dx,l->dy,NULL,s);
3240 break;
3241 case 226: // push/pull
3242 for (s = -1; (s = P_FindSectorFromLineTag(l,s)) >= 0 ; )
3243 {
3244 thing = P_GetPushThing(s);
3245 if (thing) // No MT_P* means no effect
3246 Add_Pusher(p_push,l->dx,l->dy,thing,s);
3247 }
3248 break;
3249 }
3250}
3251
3252//
3253// phares 3/20/98: End of Pusher effects
3254//
3255////////////////////////////////////////////////////////////////////////////
diff --git a/apps/plugins/doom/p_spec.h b/apps/plugins/doom/p_spec.h
new file mode 100644
index 0000000000..7a13ad8aa0
--- /dev/null
+++ b/apps/plugins/doom/p_spec.h
@@ -0,0 +1,1148 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION: definitions, declarations and prototypes for specials
28 *
29 *-----------------------------------------------------------------------------*/
30
31#ifndef __P_SPEC__
32#define __P_SPEC__
33
34#include "r_defs.h"
35#include "d_player.h"
36
37// Define values for map objects
38#define MO_TELEPORTMAN 14
39
40// p_floor
41
42#define ELEVATORSPEED (FRACUNIT*4)
43#define FLOORSPEED FRACUNIT
44
45// p_ceilng
46
47#define CEILSPEED FRACUNIT
48#define CEILWAIT 150
49
50// p_doors
51
52#define VDOORSPEED (FRACUNIT*2)
53#define VDOORWAIT 150
54
55// p_plats
56
57#define PLATWAIT 3
58#define PLATSPEED FRACUNIT
59
60// p_switch
61
62// 4 players, 4 buttons each at once, max.
63// killough 2/14/98: redefine in terms of MAXPLAYERS
64#define MAXBUTTONS (MAXPLAYERS*4)
65
66// 1 second, in ticks.
67#define BUTTONTIME TICRATE
68
69// p_lights
70
71#define GLOWSPEED 8
72#define STROBEBRIGHT 5
73#define FASTDARK 15
74#define SLOWDARK 35
75
76//jff 3/14/98 add bits and shifts for generalized sector types
77
78#define DAMAGE_MASK 0x60
79#define DAMAGE_SHIFT 5
80#define SECRET_MASK 0x80
81#define SECRET_SHIFT 7
82#define FRICTION_MASK 0x100
83#define FRICTION_SHIFT 8
84#define PUSH_MASK 0x200
85#define PUSH_SHIFT 9
86
87//jff 02/04/98 Define masks, shifts, for fields in
88// generalized linedef types
89
90#define GenEnd 0x8000
91#define GenFloorBase 0x6000
92#define GenCeilingBase 0x4000
93#define GenDoorBase 0x3c00
94#define GenLockedBase 0x3800
95#define GenLiftBase 0x3400
96#define GenStairsBase 0x3000
97#define GenCrusherBase 0x2F80
98
99#define TriggerType 0x0007
100#define TriggerTypeShift 0
101
102// define masks and shifts for the floor type fields
103
104#define FloorCrush 0x1000
105#define FloorChange 0x0c00
106#define FloorTarget 0x0380
107#define FloorDirection 0x0040
108#define FloorModel 0x0020
109#define FloorSpeed 0x0018
110
111#define FloorCrushShift 12
112#define FloorChangeShift 10
113#define FloorTargetShift 7
114#define FloorDirectionShift 6
115#define FloorModelShift 5
116#define FloorSpeedShift 3
117
118// define masks and shifts for the ceiling type fields
119
120#define CeilingCrush 0x1000
121#define CeilingChange 0x0c00
122#define CeilingTarget 0x0380
123#define CeilingDirection 0x0040
124#define CeilingModel 0x0020
125#define CeilingSpeed 0x0018
126
127#define CeilingCrushShift 12
128#define CeilingChangeShift 10
129#define CeilingTargetShift 7
130#define CeilingDirectionShift 6
131#define CeilingModelShift 5
132#define CeilingSpeedShift 3
133
134// define masks and shifts for the lift type fields
135
136#define LiftTarget 0x0300
137#define LiftDelay 0x00c0
138#define LiftMonster 0x0020
139#define LiftSpeed 0x0018
140
141#define LiftTargetShift 8
142#define LiftDelayShift 6
143#define LiftMonsterShift 5
144#define LiftSpeedShift 3
145
146// define masks and shifts for the stairs type fields
147
148#define StairIgnore 0x0200
149#define StairDirection 0x0100
150#define StairStep 0x00c0
151#define StairMonster 0x0020
152#define StairSpeed 0x0018
153
154#define StairIgnoreShift 9
155#define StairDirectionShift 8
156#define StairStepShift 6
157#define StairMonsterShift 5
158#define StairSpeedShift 3
159
160// define masks and shifts for the crusher type fields
161
162#define CrusherSilent 0x0040
163#define CrusherMonster 0x0020
164#define CrusherSpeed 0x0018
165
166#define CrusherSilentShift 6
167#define CrusherMonsterShift 5
168#define CrusherSpeedShift 3
169
170// define masks and shifts for the door type fields
171
172#define DoorDelay 0x0300
173#define DoorMonster 0x0080
174#define DoorKind 0x0060
175#define DoorSpeed 0x0018
176
177#define DoorDelayShift 8
178#define DoorMonsterShift 7
179#define DoorKindShift 5
180#define DoorSpeedShift 3
181
182// define masks and shifts for the locked door type fields
183
184#define LockedNKeys 0x0200
185#define LockedKey 0x01c0
186#define LockedKind 0x0020
187#define LockedSpeed 0x0018
188
189#define LockedNKeysShift 9
190#define LockedKeyShift 6
191#define LockedKindShift 5
192#define LockedSpeedShift 3
193
194// define names for the TriggerType field of the general linedefs
195
196typedef enum
197{
198 WalkOnce,
199 WalkMany,
200 SwitchOnce,
201 SwitchMany,
202 GunOnce,
203 GunMany,
204 PushOnce,
205 PushMany,
206} triggertype_e;
207
208// define names for the Speed field of the general linedefs
209
210typedef enum
211{
212 SpeedSlow,
213 SpeedNormal,
214 SpeedFast,
215 SpeedTurbo,
216} motionspeed_e;
217
218// define names for the Target field of the general floor
219
220typedef enum
221{
222 FtoHnF,
223 FtoLnF,
224 FtoNnF,
225 FtoLnC,
226 FtoC,
227 FbyST,
228 Fby24,
229 Fby32,
230} floortarget_e;
231
232// define names for the Changer Type field of the general floor
233
234typedef enum
235{
236 FNoChg,
237 FChgZero,
238 FChgTxt,
239 FChgTyp,
240} floorchange_e;
241
242// define names for the Change Model field of the general floor
243
244typedef enum
245{
246 FTriggerModel,
247 FNumericModel,
248} floormodel_t;
249
250// define names for the Target field of the general ceiling
251
252typedef enum
253{
254 CtoHnC,
255 CtoLnC,
256 CtoNnC,
257 CtoHnF,
258 CtoF,
259 CbyST,
260 Cby24,
261 Cby32,
262} ceilingtarget_e;
263
264// define names for the Changer Type field of the general ceiling
265
266typedef enum
267{
268 CNoChg,
269 CChgZero,
270 CChgTxt,
271 CChgTyp,
272} ceilingchange_e;
273
274// define names for the Change Model field of the general ceiling
275
276typedef enum
277{
278 CTriggerModel,
279 CNumericModel,
280} ceilingmodel_t;
281
282// define names for the Target field of the general lift
283
284typedef enum
285{
286 F2LnF,
287 F2NnF,
288 F2LnC,
289 LnF2HnF,
290} lifttarget_e;
291
292// define names for the door Kind field of the general ceiling
293
294typedef enum
295{
296 OdCDoor,
297 ODoor,
298 CdODoor,
299 CDoor,
300} doorkind_e;
301
302// define names for the locked door Kind field of the general ceiling
303
304typedef enum
305{
306 AnyKey,
307 RCard,
308 BCard,
309 YCard,
310 RSkull,
311 BSkull,
312 YSkull,
313 AllKeys,
314} keykind_e;
315
316//////////////////////////////////////////////////////////////////
317//
318// enums for classes of linedef triggers
319//
320//////////////////////////////////////////////////////////////////
321
322//jff 2/23/98 identify the special classes that can share sectors
323
324typedef enum
325{
326 floor_special,
327 ceiling_special,
328 lighting_special,
329} special_e;
330
331//jff 3/15/98 pure texture/type change for better generalized support
332typedef enum
333{
334 trigChangeOnly,
335 numChangeOnly,
336} change_e;
337
338// p_plats
339
340typedef enum
341{
342 up,
343 down,
344 waiting,
345 in_stasis
346} plat_e;
347
348typedef enum
349{
350 perpetualRaise,
351 downWaitUpStay,
352 raiseAndChange,
353 raiseToNearestAndChange,
354 blazeDWUS,
355 genLift, //jff added to support generalized Plat types
356 genPerpetual,
357 toggleUpDn, //jff 3/14/98 added to support instant toggle type
358
359} plattype_e;
360
361// p_doors
362
363typedef enum
364{
365 normal,
366 close30ThenOpen,
367 p_close,
368 p_open,
369 raiseIn5Mins,
370 blazeRaise,
371 blazeOpen,
372 blazeClose,
373
374 //jff 02/05/98 add generalize door types
375 genRaise,
376 genBlazeRaise,
377 genOpen,
378 genBlazeOpen,
379 genClose,
380 genBlazeClose,
381 genCdO,
382 genBlazeCdO,
383} vldoor_e;
384
385// p_ceilng
386
387typedef enum
388{
389 lowerToFloor,
390 raiseToHighest,
391 lowerToLowest,
392 lowerToMaxFloor,
393 lowerAndCrush,
394 crushAndRaise,
395 fastCrushAndRaise,
396 silentCrushAndRaise,
397
398 //jff 02/04/98 add types for generalized ceiling mover
399 genCeiling,
400 genCeilingChg,
401 genCeilingChg0,
402 genCeilingChgT,
403
404 //jff 02/05/98 add types for generalized ceiling mover
405 genCrusher,
406 genSilentCrusher,
407
408} ceiling_e;
409
410// p_floor
411
412typedef enum
413{
414 // lower floor to highest surrounding floor
415 lowerFloor,
416
417 // lower floor to lowest surrounding floor
418 lowerFloorToLowest,
419
420 // lower floor to highest surrounding floor VERY FAST
421 turboLower,
422
423 // raise floor to lowest surrounding CEILING
424 raiseFloor,
425
426 // raise floor to next highest surrounding floor
427 raiseFloorToNearest,
428
429 //jff 02/03/98 lower floor to next lowest neighbor
430 lowerFloorToNearest,
431
432 //jff 02/03/98 lower floor 24 absolute
433 lowerFloor24,
434
435 //jff 02/03/98 lower floor 32 absolute
436 lowerFloor32Turbo,
437
438 // raise floor to shortest height texture around it
439 raiseToTexture,
440
441 // lower floor to lowest surrounding floor
442 // and change floorpic
443 lowerAndChange,
444
445 raiseFloor24,
446
447 //jff 02/03/98 raise floor 32 absolute
448 raiseFloor32Turbo,
449
450 raiseFloor24AndChange,
451 raiseFloorCrush,
452
453 // raise to next highest floor, turbo-speed
454 raiseFloorTurbo,
455 donutRaise,
456 raiseFloor512,
457
458 //jff 02/04/98 add types for generalized floor mover
459 genFloor,
460 genFloorChg,
461 genFloorChg0,
462 genFloorChgT,
463
464 //new types for stair builders
465 buildStair,
466 genBuildStair,
467} floor_e;
468
469typedef enum
470{
471 build8, // slowly build by 8
472 turbo16 // quickly build by 16
473
474} stair_e;
475
476typedef enum
477{
478 elevateUp,
479 elevateDown,
480 elevateCurrent,
481} elevator_e;
482
483//////////////////////////////////////////////////////////////////
484//
485// general enums
486//
487//////////////////////////////////////////////////////////////////
488
489// texture type enum
490typedef enum
491{
492 top,
493 middle,
494 bottom
495
496} bwhere_e;
497
498// crush check returns
499typedef enum
500{
501 ok,
502 crushed,
503 pastdest
504} result_e;
505
506//////////////////////////////////////////////////////////////////
507//
508// linedef and sector special data types
509//
510//////////////////////////////////////////////////////////////////
511
512// p_switch
513
514// switch animation structure type
515
516#if defined(__MWERKS__)
517#pragma options align=packed
518#endif
519
520typedef struct
521{
522 char name1[9];
523 char name2[9];
524 short episode;
525} PACKEDATTR switchlist_t; //jff 3/23/98 pack to read from memory
526
527#if defined(__MWERKS__)
528#pragma options align=reset
529#endif
530
531typedef struct
532{
533 line_t* line;
534 bwhere_e where;
535 int btexture;
536 int btimer;
537 mobj_t* soundorg;
538
539} button_t;
540
541// p_lights
542
543typedef struct
544{
545 thinker_t thinker;
546 sector_t* sector;
547 int count;
548 int maxlight;
549 int minlight;
550
551} fireflicker_t;
552
553typedef struct
554{
555 thinker_t thinker;
556 sector_t* sector;
557 int count;
558 int maxlight;
559 int minlight;
560 int maxtime;
561 int mintime;
562
563} lightflash_t;
564
565typedef struct
566{
567 thinker_t thinker;
568 sector_t* sector;
569 int count;
570 int minlight;
571 int maxlight;
572 int darktime;
573 int brighttime;
574
575} strobe_t;
576
577typedef struct
578{
579 thinker_t thinker;
580 sector_t* sector;
581 int minlight;
582 int maxlight;
583 int direction;
584
585} glow_t;
586
587// p_plats
588
589typedef struct
590{
591 thinker_t thinker;
592 sector_t* sector;
593 fixed_t speed;
594 fixed_t low;
595 fixed_t high;
596 int wait;
597 int count;
598 plat_e status;
599 plat_e oldstatus;
600 boolean crush;
601 int tag;
602 plattype_e type;
603
604 struct platlist *list; // killough
605} plat_t;
606
607// New limit-free plat structure -- killough
608
609typedef struct platlist {
610 plat_t *plat;
611 struct platlist *next,**prev;
612} platlist_t;
613
614// p_ceilng
615
616typedef struct
617{
618 thinker_t thinker;
619 vldoor_e type;
620 sector_t* sector;
621 fixed_t topheight;
622 fixed_t speed;
623
624 // 1 = up, 0 = waiting at top, -1 = down
625 int direction;
626
627 // tics to wait at the top
628 int topwait;
629 // (keep in case a door going down is reset)
630 // when it reaches 0, start going down
631 int topcountdown;
632
633 //jff 1/31/98 keep track of line door is triggered by
634 line_t *line;
635
636 /* killough 10/98: sector tag for gradual lighting effects */
637 int lighttag;
638} vldoor_t;
639
640// p_doors
641
642typedef struct
643{
644 thinker_t thinker;
645 ceiling_e type;
646 sector_t* sector;
647 fixed_t bottomheight;
648 fixed_t topheight;
649 fixed_t speed;
650 fixed_t oldspeed;
651 boolean crush;
652
653 //jff 02/04/98 add these to support ceiling changers
654 int newspecial;
655 int oldspecial; //jff 3/14/98 add to fix bug in change transfers
656 short texture;
657
658 // 1 = up, 0 = waiting, -1 = down
659 int direction;
660
661 // ID
662 int tag;
663 int olddirection;
664 struct ceilinglist *list; // jff 2/22/98 copied from killough's plats
665} ceiling_t;
666
667typedef struct ceilinglist {
668 ceiling_t *ceiling;
669 struct ceilinglist *next,**prev;
670} ceilinglist_t;
671
672// p_floor
673
674typedef struct
675{
676 thinker_t thinker;
677 floor_e type;
678 boolean crush;
679 sector_t* sector;
680 int direction;
681 int newspecial;
682 int oldspecial; //jff 3/14/98 add to fix bug in change transfers
683 short texture;
684 fixed_t floordestheight;
685 fixed_t speed;
686
687} floormove_t;
688
689typedef struct
690{
691 thinker_t thinker;
692 elevator_e type;
693 sector_t* sector;
694 int direction;
695 fixed_t floordestheight;
696 fixed_t ceilingdestheight;
697 fixed_t speed;
698} elevator_t;
699
700// p_spec
701
702// killough 3/7/98: Add generalized scroll effects
703
704typedef struct {
705 thinker_t thinker; // Thinker structure for scrolling
706 fixed_t dx, dy; // (dx,dy) scroll speeds
707 int affectee; // Number of affected sidedef, sector, tag, or whatever
708 int control; // Control sector (-1 if none) used to control scrolling
709 fixed_t last_height; // Last known height of control sector
710 fixed_t vdx, vdy; // Accumulated velocity if accelerative
711 int accel; // Whether it's accelerative
712 enum
713 {
714 sc_side,
715 sc_floor,
716 sc_ceiling,
717 sc_carry,
718 sc_carry_ceiling, // killough 4/11/98: carry objects hanging on ceilings
719 } type; // Type of scroll effect
720} scroll_t;
721
722// phares 3/12/98: added new model of friction for ice/sludge effects
723
724typedef struct {
725 thinker_t thinker; // Thinker structure for friction
726 int friction; // friction value (E800 = normal)
727 int movefactor; // inertia factor when adding to momentum
728 int affectee; // Number of affected sector
729} friction_t;
730
731// phares 3/20/98: added new model of Pushers for push/pull effects
732
733typedef struct {
734 thinker_t thinker; // Thinker structure for Pusher
735 enum
736 {
737 p_push,
738 p_pull,
739 p_wind,
740 p_current,
741 } type;
742 mobj_t* source; // Point source if point pusher
743 int x_mag; // X Strength
744 int y_mag; // Y Strength
745 int magnitude; // Vector strength for point pusher
746 int radius; // Effective radius for point pusher
747 int x; // X of point source if point pusher
748 int y; // Y of point source if point pusher
749 int affectee; // Number of affected sector
750} pusher_t;
751
752//////////////////////////////////////////////////////////////////
753//
754// external data declarations
755//
756//////////////////////////////////////////////////////////////////
757
758//
759// End-level timer (-TIMER option)
760//
761extern boolean levelTimer;
762extern int levelTimeCount;
763
764// list of retriggerable buttons active
765extern button_t buttonlist[MAXBUTTONS];
766
767extern platlist_t *activeplats; // killough 2/14/98
768
769extern ceilinglist_t *activeceilings; // jff 2/22/98
770
771////////////////////////////////////////////////////////////////
772//
773// Linedef and sector special utility function prototypes
774//
775////////////////////////////////////////////////////////////////
776
777int twoSided
778( int sector,
779 int line );
780
781sector_t* getSector
782( int currentSector,
783 int line,
784 int side );
785
786side_t* getSide
787( int currentSector,
788 int line,
789 int side );
790
791fixed_t P_FindLowestFloorSurrounding
792( sector_t* sec );
793
794fixed_t P_FindHighestFloorSurrounding
795( sector_t* sec );
796
797fixed_t P_FindNextHighestFloor
798( sector_t* sec,
799 int currentheight );
800
801fixed_t P_FindNextLowestFloor
802( sector_t* sec,
803 int currentheight );
804
805fixed_t P_FindLowestCeilingSurrounding
806( sector_t* sec ); // jff 2/04/98
807
808fixed_t P_FindHighestCeilingSurrounding
809( sector_t* sec ); // jff 2/04/98
810
811fixed_t P_FindNextLowestCeiling
812( sector_t *sec,
813 int currentheight ); // jff 2/04/98
814
815fixed_t P_FindNextHighestCeiling
816( sector_t *sec,
817 int currentheight ); // jff 2/04/98
818
819fixed_t P_FindShortestTextureAround
820( int secnum ); // jff 2/04/98
821
822fixed_t P_FindShortestUpperAround
823( int secnum ); // jff 2/04/98
824
825sector_t* P_FindModelFloorSector
826( fixed_t floordestheight,
827 int secnum ); //jff 02/04/98
828
829sector_t* P_FindModelCeilingSector
830( fixed_t ceildestheight,
831 int secnum ); //jff 02/04/98
832
833int P_FindSectorFromLineTag
834( const line_t *line,
835 int start ); // killough 4/17/98
836
837int P_FindLineFromLineTag
838( const line_t *line,
839 int start ); // killough 4/17/98
840
841int P_FindMinSurroundingLight
842( sector_t* sector,
843 int max );
844
845sector_t* getNextSector
846( line_t* line,
847 sector_t* sec );
848
849int P_CheckTag
850(line_t *line); // jff 2/27/98
851
852boolean P_CanUnlockGenDoor
853( line_t* line,
854 player_t* player);
855
856int P_SectorActive
857( special_e t,
858 sector_t* s );
859
860boolean P_IsSecret
861( sector_t *sec );
862
863boolean P_WasSecret
864( sector_t *sec );
865
866void P_ChangeSwitchTexture
867( line_t* line,
868 int useAgain );
869
870////////////////////////////////////////////////////////////////
871//
872// Linedef and sector special action function prototypes
873//
874////////////////////////////////////////////////////////////////
875
876// p_lights
877
878void T_LightFlash
879( lightflash_t* flash );
880
881void T_StrobeFlash
882( strobe_t* flash );
883
884// jff 8/8/98 add missing thinker for flicker
885void T_FireFlicker
886( fireflicker_t* flick );
887
888void T_Glow
889( glow_t* g );
890
891// p_plats
892
893void T_PlatRaise
894( plat_t* plat );
895
896// p_doors
897
898void T_VerticalDoor
899( vldoor_t* door );
900
901// p_ceilng
902
903void T_MoveCeiling
904( ceiling_t* ceiling );
905
906// p_floor
907
908result_e T_MovePlane
909( sector_t* sector,
910 fixed_t speed,
911 fixed_t dest,
912 boolean crush,
913 int floorOrCeiling,
914 int direction );
915
916void T_MoveFloor
917( floormove_t* floor );
918
919void T_MoveElevator
920( elevator_t* elevator );
921
922// p_spec
923
924void T_Scroll
925( scroll_t * ); // killough 3/7/98: scroll effect thinker
926
927void T_Friction
928( friction_t * ); // phares 3/12/98: friction thinker
929
930void T_Pusher
931( pusher_t * ); // phares 3/20/98: Push thinker
932
933////////////////////////////////////////////////////////////////
934//
935// Linedef and sector special handler prototypes
936//
937////////////////////////////////////////////////////////////////
938
939// p_telept
940
941int EV_Teleport
942( line_t* line,
943 int side,
944 mobj_t* thing );
945
946// killough 2/14/98: Add silent teleporter
947int EV_SilentTeleport
948( line_t* line,
949 int side,
950 mobj_t* thing );
951
952// killough 1/31/98: Add silent line teleporter
953int EV_SilentLineTeleport
954( line_t* line,
955 int side,
956 mobj_t* thing,
957 boolean reverse);
958
959// p_floor
960
961int
962EV_DoElevator
963( line_t* line,
964 elevator_e type );
965
966int EV_BuildStairs
967( line_t* line,
968 stair_e type );
969
970int EV_DoFloor
971( line_t* line,
972 floor_e floortype );
973
974// p_ceilng
975
976int EV_DoCeiling
977( line_t* line,
978 ceiling_e type );
979
980int EV_CeilingCrushStop
981( line_t* line );
982
983// p_doors
984
985int EV_VerticalDoor
986( line_t* line,
987 mobj_t* thing );
988
989int EV_DoDoor
990( line_t* line,
991 vldoor_e type );
992
993int EV_DoLockedDoor
994( line_t* line,
995 vldoor_e type,
996 mobj_t* thing );
997
998// p_lights
999
1000int EV_StartLightStrobing
1001( line_t* line );
1002
1003int EV_TurnTagLightsOff
1004( line_t* line );
1005
1006int EV_LightTurnOn
1007( line_t* line,
1008 int bright );
1009
1010int EV_LightTurnOnPartway(line_t* line, fixed_t level); // killough 10/10/98
1011
1012// p_floor
1013
1014int EV_DoChange
1015( line_t* line,
1016 change_e changetype );
1017
1018int EV_DoDonut
1019( line_t* line );
1020
1021// p_plats
1022
1023int EV_DoPlat
1024( line_t* line,
1025 plattype_e type,
1026 int amount );
1027
1028int EV_StopPlat
1029( line_t* line );
1030
1031// p_genlin
1032
1033int EV_DoGenFloor
1034( line_t* line );
1035
1036int EV_DoGenCeiling
1037( line_t* line );
1038
1039int EV_DoGenLift
1040( line_t* line );
1041
1042int EV_DoGenStairs
1043( line_t* line );
1044
1045int EV_DoGenCrusher
1046( line_t* line );
1047
1048int EV_DoGenDoor
1049( line_t* line );
1050
1051int EV_DoGenLockedDoor
1052( line_t* line );
1053
1054////////////////////////////////////////////////////////////////
1055//
1056// Linedef and sector special thinker spawning
1057//
1058////////////////////////////////////////////////////////////////
1059
1060// at game start
1061void P_InitPicAnims
1062( void );
1063
1064void P_InitSwitchList
1065( void );
1066
1067// at map load
1068void P_SpawnSpecials
1069( void );
1070
1071// every tic
1072void P_UpdateSpecials
1073( void );
1074
1075// when needed
1076boolean P_UseSpecialLine
1077( mobj_t* thing,
1078 line_t* line,
1079 int side );
1080
1081void P_ShootSpecialLine
1082( mobj_t* thing,
1083 line_t* line );
1084
1085void P_CrossSpecialLine(line_t *line, int side, mobj_t *thing);
1086
1087void P_PlayerInSpecialSector
1088( player_t* player );
1089
1090// p_lights
1091
1092void P_SpawnFireFlicker
1093( sector_t* sector );
1094
1095void P_SpawnLightFlash
1096( sector_t* sector );
1097
1098void P_SpawnStrobeFlash
1099( sector_t* sector,
1100 int fastOrSlow,
1101 int inSync );
1102
1103void P_SpawnGlowingLight
1104( sector_t* sector );
1105
1106// p_plats
1107
1108void P_AddActivePlat
1109( plat_t* plat );
1110
1111void P_RemoveActivePlat
1112( plat_t* plat );
1113
1114void P_RemoveAllActivePlats
1115( void ); // killough
1116
1117void P_ActivateInStasis
1118( int tag );
1119
1120// p_doors
1121
1122void P_SpawnDoorCloseIn30
1123( sector_t* sec );
1124
1125void P_SpawnDoorRaiseIn5Mins
1126( sector_t* sec,
1127 int secnum );
1128
1129// p_ceilng
1130
1131void P_RemoveActiveCeiling
1132( ceiling_t* ceiling ); //jff 2/22/98
1133
1134void P_RemoveAllActiveCeilings
1135( void ); //jff 2/22/98
1136
1137void P_AddActiveCeiling
1138( ceiling_t* c );
1139
1140void P_RemoveActiveCeiling
1141( ceiling_t* c );
1142
1143int P_ActivateInStasisCeiling
1144( line_t* line );
1145
1146mobj_t* P_GetPushThing(int); // phares 3/23/98
1147
1148#endif
diff --git a/apps/plugins/doom/p_switch.c b/apps/plugins/doom/p_switch.c
new file mode 100644
index 0000000000..698c4c8ee3
--- /dev/null
+++ b/apps/plugins/doom/p_switch.c
@@ -0,0 +1,1138 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION:
28 * Switches, buttons. Two-state animation. Exits.
29 *
30 *-----------------------------------------------------------------------------*/
31
32#include "doomstat.h"
33#include "w_wad.h"
34#include "r_main.h"
35#include "p_spec.h"
36#include "g_game.h"
37#include "s_sound.h"
38#include "sounds.h"
39#include "m_swap.h"
40#include "i_system.h"
41#include "rockmacros.h"
42// killough 2/8/98: Remove switch limit
43
44static int *switchlist; // killough
45static int max_numswitches; // killough
46static int numswitches; // killough
47
48button_t buttonlist[MAXBUTTONS];
49
50//
51// P_InitSwitchList()
52//
53// Only called at game initialization in order to list the set of switches
54// and buttons known to the engine. This enables their texture to change
55// when activated, and in the case of buttons, change back after a timeout.
56//
57// This routine modified to read its data from a predefined lump or
58// PWAD lump called SWITCHES rather than a static table in this module to
59// allow wad designers to insert or modify switches.
60//
61// Lump format is an array of byte packed switchlist_t structures, terminated
62// by a structure with episode == -0. The lump can be generated from a
63// text source file using SWANTBLS.EXE, distributed with the BOOM utils.
64// The standard list of switches and animations is contained in the example
65// source text file DEFSWANI.DAT also in the BOOM util distribution.
66//
67// Rewritten by Lee Killough to remove limit 2/8/98
68//
69void P_InitSwitchList(void)
70{
71 int i, index = 0;
72 int episode = (gamemode == registered || gamemode==retail) ?
73 2 : gamemode == commercial ? 3 : 1;
74 const switchlist_t *alphSwitchList; //jff 3/23/98 pointer to switch table
75 int lump = W_GetNumForName("SWITCHES"); // cph - new wad lump handling
76
77 //jff 3/23/98 read the switch table from a predefined lump
78 alphSwitchList = (const switchlist_t *)W_CacheLumpNum(lump);
79
80 for (i=0;;i++)
81 {
82 if (index+1 >= max_numswitches)
83 switchlist = realloc(switchlist, sizeof *switchlist *
84 (max_numswitches = max_numswitches ? max_numswitches*2 : 8));
85 if (SHORT(alphSwitchList[i].episode) <= episode) //jff 5/11/98 endianess
86 {
87 if (!SHORT(alphSwitchList[i].episode))
88 break;
89 switchlist[index++] = R_TextureNumForName(alphSwitchList[i].name1);
90 switchlist[index++] = R_TextureNumForName(alphSwitchList[i].name2);
91 }
92 }
93
94 numswitches = index/2;
95 switchlist[index] = -1;
96 W_UnlockLumpNum(lump);
97}
98
99//
100// P_StartButton()
101//
102// Start a button (retriggerable switch) counting down till it turns off.
103//
104// Passed the linedef the button is on, which texture on the sidedef contains
105// the button, the texture number of the button, and the time the button is
106// to remain active in gametics.
107// No return.
108//
109void P_StartButton
110( line_t* line,
111 bwhere_e w,
112 int texture,
113 int time )
114{
115 int i;
116
117 // See if button is already pressed
118 for (i = 0;i < MAXBUTTONS;i++)
119 if (buttonlist[i].btimer && buttonlist[i].line == line)
120 return;
121
122 for (i = 0;i < MAXBUTTONS;i++)
123 if (!buttonlist[i].btimer) // use first unused element of list
124 {
125 buttonlist[i].line = line;
126 buttonlist[i].where = w;
127 buttonlist[i].btexture = texture;
128 buttonlist[i].btimer = time;
129 buttonlist[i].soundorg = (mobj_t *)&line->frontsector->soundorg;
130 return;
131 }
132
133 I_Error("P_StartButton: no button slots left!");
134}
135
136//
137// P_ChangeSwitchTexture()
138//
139// Function that changes switch wall texture on activation.
140//
141// Passed the line which the switch is on, and whether its retriggerable.
142// If not retriggerable, this function clears the line special to insure that
143//
144// No return
145//
146void P_ChangeSwitchTexture
147( line_t* line,
148 int useAgain )
149{
150 int texTop;
151 int texMid;
152 int texBot;
153 int i;
154 int sound;
155
156 if (!useAgain)
157 line->special = 0;
158
159 texTop = sides[line->sidenum[0]].toptexture;
160 texMid = sides[line->sidenum[0]].midtexture;
161 texBot = sides[line->sidenum[0]].bottomtexture;
162
163 sound = sfx_swtchn;
164
165 // EXIT SWITCH?
166 if (line->special == 11)
167 sound = sfx_swtchx;
168
169 for (i = 0;i < numswitches*2;i++)
170 {
171 if (switchlist[i] == texTop) // if an upper texture
172 {
173 S_StartSound(buttonlist->soundorg,sound); // switch activation sound
174 sides[line->sidenum[0]].toptexture = switchlist[i^1]; //chg texture
175
176 if (useAgain)
177 P_StartButton(line,top,switchlist[i],BUTTONTIME); //start timer
178
179 return;
180 }
181 else
182 {
183 if (switchlist[i] == texMid) // if a normal texture
184 {
185 S_StartSound(buttonlist->soundorg,sound); // switch activation sound
186 sides[line->sidenum[0]].midtexture = switchlist[i^1]; //chg texture
187
188 if (useAgain)
189 P_StartButton(line, middle,switchlist[i],BUTTONTIME); //start timer
190
191 return;
192 }
193 else
194 {
195 if (switchlist[i] == texBot) // if a lower texture
196 {
197 S_StartSound(buttonlist->soundorg,sound); // switch activation sound
198 sides[line->sidenum[0]].bottomtexture = switchlist[i^1];//chg texture
199
200 if (useAgain)
201 P_StartButton(line, bottom,switchlist[i],BUTTONTIME); //start timer
202
203 return;
204 }
205 }
206 }
207 }
208}
209
210
211//
212// P_UseSpecialLine
213//
214//
215// Called when a thing uses (pushes) a special line.
216// Only the front sides of lines are usable.
217// Dispatches to the appropriate linedef function handler.
218//
219// Passed the thing using the line, the line being used, and the side used
220// Returns true if a thinker was created
221//
222boolean
223P_UseSpecialLine
224( mobj_t* thing,
225 line_t* line,
226 int side )
227{
228
229 if (side) //jff 6/1/98 fix inadvertent deletion of side test
230 return false;
231
232 //jff 02/04/98 add check here for generalized floor/ceil mover
233 if (!demo_compatibility)
234 {
235 // pointer to line function is NULL by default, set non-null if
236 // line special is push or switch generalized linedef type
237 int (*linefunc)(line_t *line)=NULL;
238
239 // check each range of generalized linedefs
240 if ((unsigned)line->special >= GenEnd)
241 {
242 // Out of range for GenFloors
243 }
244 else if ((unsigned)line->special >= GenFloorBase)
245 {
246 if (!thing->player)
247 if ((line->special & FloorChange) || !(line->special & FloorModel))
248 return false; // FloorModel is "Allow Monsters" if FloorChange is 0
249 if (!line->tag && ((line->special&6)!=6)) //jff 2/27/98 all non-manual
250 return false; // generalized types require tag
251 linefunc = EV_DoGenFloor;
252 }
253 else if ((unsigned)line->special >= GenCeilingBase)
254 {
255 if (!thing->player)
256 if ((line->special & CeilingChange) || !(line->special & CeilingModel))
257 return false; // CeilingModel is "Allow Monsters" if CeilingChange is 0
258 if (!line->tag && ((line->special&6)!=6)) //jff 2/27/98 all non-manual
259 return false; // generalized types require tag
260 linefunc = EV_DoGenCeiling;
261 }
262 else if ((unsigned)line->special >= GenDoorBase)
263 {
264 if (!thing->player)
265 {
266 if (!(line->special & DoorMonster))
267 return false; // monsters disallowed from this door
268 if (line->flags & ML_SECRET) // they can't open secret doors either
269 return false;
270 }
271 if (!line->tag && ((line->special&6)!=6)) //jff 3/2/98 all non-manual
272 return false; // generalized types require tag
273 linefunc = EV_DoGenDoor;
274 }
275 else if ((unsigned)line->special >= GenLockedBase)
276 {
277 if (!thing->player)
278 return false; // monsters disallowed from unlocking doors
279 if (!P_CanUnlockGenDoor(line,thing->player))
280 return false;
281 if (!line->tag && ((line->special&6)!=6)) //jff 2/27/98 all non-manual
282 return false; // generalized types require tag
283
284 linefunc = EV_DoGenLockedDoor;
285 }
286 else if ((unsigned)line->special >= GenLiftBase)
287 {
288 if (!thing->player)
289 if (!(line->special & LiftMonster))
290 return false; // monsters disallowed
291 if (!line->tag && ((line->special&6)!=6)) //jff 2/27/98 all non-manual
292 return false; // generalized types require tag
293 linefunc = EV_DoGenLift;
294 }
295 else if ((unsigned)line->special >= GenStairsBase)
296 {
297 if (!thing->player)
298 if (!(line->special & StairMonster))
299 return false; // monsters disallowed
300 if (!line->tag && ((line->special&6)!=6)) //jff 2/27/98 all non-manual
301 return false; // generalized types require tag
302 linefunc = EV_DoGenStairs;
303 }
304 else if ((unsigned)line->special >= GenCrusherBase)
305 {
306 if (!thing->player)
307 if (!(line->special & CrusherMonster))
308 return false; // monsters disallowed
309 if (!line->tag && ((line->special&6)!=6)) //jff 2/27/98 all non-manual
310 return false; // generalized types require tag
311 linefunc = EV_DoGenCrusher;
312 }
313
314 if (linefunc)
315 switch((line->special & TriggerType) >> TriggerTypeShift)
316 {
317 case PushOnce:
318 if (!side)
319 if (linefunc(line))
320 line->special = 0;
321 return true;
322 case PushMany:
323 if (!side)
324 linefunc(line);
325 return true;
326 case SwitchOnce:
327 if (linefunc(line))
328 P_ChangeSwitchTexture(line,0);
329 return true;
330 case SwitchMany:
331 if (linefunc(line))
332 P_ChangeSwitchTexture(line,1);
333 return true;
334 default: // if not a switch/push type, do nothing here
335 return false;
336 }
337 }
338
339 // Switches that other things can activate.
340 if (!thing->player)
341 {
342 // never open secret doors
343 if (line->flags & ML_SECRET)
344 return false;
345
346 switch(line->special)
347 {
348 case 1: // MANUAL DOOR RAISE
349 case 32: // MANUAL BLUE
350 case 33: // MANUAL RED
351 case 34: // MANUAL YELLOW
352 //jff 3/5/98 add ability to use teleporters for monsters
353 case 195: // switch teleporters
354 case 174:
355 case 210: // silent switch teleporters
356 case 209:
357 break;
358
359 default:
360 return false;
361 break;
362 }
363 }
364
365 if (!P_CheckTag(line)) //jff 2/27/98 disallow zero tag on some types
366 return false;
367
368 // Dispatch to handler according to linedef type
369 switch (line->special)
370 {
371 // Manual doors, push type with no tag
372 case 1: // Vertical Door
373 case 26: // Blue Door/Locked
374 case 27: // Yellow Door /Locked
375 case 28: // Red Door /Locked
376
377 case 31: // Manual door open
378 case 32: // Blue locked door open
379 case 33: // Red locked door open
380 case 34: // Yellow locked door open
381
382 case 117: // Blazing door raise
383 case 118: // Blazing door open
384 EV_VerticalDoor (line, thing);
385 break;
386
387 // Switches (non-retriggerable)
388 case 7:
389 // Build Stairs
390 if (EV_BuildStairs(line,build8))
391 P_ChangeSwitchTexture(line,0);
392 break;
393
394 case 9:
395 // Change Donut
396 if (EV_DoDonut(line))
397 P_ChangeSwitchTexture(line,0);
398 break;
399
400 case 11:
401 /* Exit level
402 * killough 10/98: prevent zombies from exiting levels
403 */
404 if (thing->player && thing->player->health <= 0 && !comp[comp_zombie])
405 {
406 S_StartSound(thing, sfx_noway);
407 return false;
408 }
409
410 P_ChangeSwitchTexture(line,0);
411 G_ExitLevel ();
412 break;
413
414 case 14:
415 // Raise Floor 32 and change texture
416 if (EV_DoPlat(line,raiseAndChange,32))
417 P_ChangeSwitchTexture(line,0);
418 break;
419
420 case 15:
421 // Raise Floor 24 and change texture
422 if (EV_DoPlat(line,raiseAndChange,24))
423 P_ChangeSwitchTexture(line,0);
424 break;
425
426 case 18:
427 // Raise Floor to next highest floor
428 if (EV_DoFloor(line, raiseFloorToNearest))
429 P_ChangeSwitchTexture(line,0);
430 break;
431
432 case 20:
433 // Raise Plat next highest floor and change texture
434 if (EV_DoPlat(line,raiseToNearestAndChange,0))
435 P_ChangeSwitchTexture(line,0);
436 break;
437
438 case 21:
439 // PlatDownWaitUpStay
440 if (EV_DoPlat(line,downWaitUpStay,0))
441 P_ChangeSwitchTexture(line,0);
442 break;
443
444 case 23:
445 // Lower Floor to Lowest
446 if (EV_DoFloor(line,lowerFloorToLowest))
447 P_ChangeSwitchTexture(line,0);
448 break;
449
450 case 29:
451 // Raise Door
452 if (EV_DoDoor(line,normal))
453 P_ChangeSwitchTexture(line,0);
454 break;
455
456 case 41:
457 // Lower Ceiling to Floor
458 if (EV_DoCeiling(line,lowerToFloor))
459 P_ChangeSwitchTexture(line,0);
460 break;
461
462 case 71:
463 // Turbo Lower Floor
464 if (EV_DoFloor(line,turboLower))
465 P_ChangeSwitchTexture(line,0);
466 break;
467
468 case 49:
469 // Ceiling Crush And Raise
470 if (EV_DoCeiling(line,crushAndRaise))
471 P_ChangeSwitchTexture(line,0);
472 break;
473
474 case 50:
475 // Close Door
476 if (EV_DoDoor(line,p_close))
477 P_ChangeSwitchTexture(line,0);
478 break;
479
480 case 51:
481 /* Secret EXIT
482 * killough 10/98: prevent zombies from exiting levels
483 */
484 if (thing->player && thing->player->health <= 0 && !comp[comp_zombie])
485 {
486 S_StartSound(thing, sfx_noway);
487 return false;
488 }
489
490 P_ChangeSwitchTexture(line,0);
491 G_SecretExitLevel ();
492 break;
493
494 case 55:
495 // Raise Floor Crush
496 if (EV_DoFloor(line,raiseFloorCrush))
497 P_ChangeSwitchTexture(line,0);
498 break;
499
500 case 101:
501 // Raise Floor
502 if (EV_DoFloor(line,raiseFloor))
503 P_ChangeSwitchTexture(line,0);
504 break;
505
506 case 102:
507 // Lower Floor to Surrounding floor height
508 if (EV_DoFloor(line,lowerFloor))
509 P_ChangeSwitchTexture(line,0);
510 break;
511
512 case 103:
513 // Open Door
514 if (EV_DoDoor(line,p_open))
515 P_ChangeSwitchTexture(line,0);
516 break;
517
518 case 111:
519 // Blazing Door Raise (faster than TURBO!)
520 if (EV_DoDoor (line,blazeRaise))
521 P_ChangeSwitchTexture(line,0);
522 break;
523
524 case 112:
525 // Blazing Door Open (faster than TURBO!)
526 if (EV_DoDoor (line,blazeOpen))
527 P_ChangeSwitchTexture(line,0);
528 break;
529
530 case 113:
531 // Blazing Door Close (faster than TURBO!)
532 if (EV_DoDoor (line,blazeClose))
533 P_ChangeSwitchTexture(line,0);
534 break;
535
536 case 122:
537 // Blazing PlatDownWaitUpStay
538 if (EV_DoPlat(line,blazeDWUS,0))
539 P_ChangeSwitchTexture(line,0);
540 break;
541
542 case 127:
543 // Build Stairs Turbo 16
544 if (EV_BuildStairs(line,turbo16))
545 P_ChangeSwitchTexture(line,0);
546 break;
547
548 case 131:
549 // Raise Floor Turbo
550 if (EV_DoFloor(line,raiseFloorTurbo))
551 P_ChangeSwitchTexture(line,0);
552 break;
553
554 case 133:
555 // BlzOpenDoor BLUE
556 case 135:
557 // BlzOpenDoor RED
558 case 137:
559 // BlzOpenDoor YELLOW
560 if (EV_DoLockedDoor (line,blazeOpen,thing))
561 P_ChangeSwitchTexture(line,0);
562 break;
563
564 case 140:
565 // Raise Floor 512
566 if (EV_DoFloor(line,raiseFloor512))
567 P_ChangeSwitchTexture(line,0);
568 break;
569
570 // killough 1/31/98: factored out compatibility check;
571 // added inner switch, relaxed check to demo_compatibility
572
573 default:
574 if (!demo_compatibility)
575 switch (line->special)
576 {
577 //jff 1/29/98 added linedef types to fill all functions out so that
578 // all possess SR, S1, WR, W1 types
579
580 case 158:
581 // Raise Floor to shortest lower texture
582 // 158 S1 EV_DoFloor(raiseToTexture), CSW(0)
583 if (EV_DoFloor(line,raiseToTexture))
584 P_ChangeSwitchTexture(line,0);
585 break;
586
587 case 159:
588 // Raise Floor to shortest lower texture
589 // 159 S1 EV_DoFloor(lowerAndChange)
590 if (EV_DoFloor(line,lowerAndChange))
591 P_ChangeSwitchTexture(line,0);
592 break;
593
594 case 160:
595 // Raise Floor 24 and change
596 // 160 S1 EV_DoFloor(raiseFloor24AndChange)
597 if (EV_DoFloor(line,raiseFloor24AndChange))
598 P_ChangeSwitchTexture(line,0);
599 break;
600
601 case 161:
602 // Raise Floor 24
603 // 161 S1 EV_DoFloor(raiseFloor24)
604 if (EV_DoFloor(line,raiseFloor24))
605 P_ChangeSwitchTexture(line,0);
606 break;
607
608 case 162:
609 // Moving floor min n to max n
610 // 162 S1 EV_DoPlat(perpetualRaise,0)
611 if (EV_DoPlat(line,perpetualRaise,0))
612 P_ChangeSwitchTexture(line,0);
613 break;
614
615 case 163:
616 // Stop Moving floor
617 // 163 S1 EV_DoPlat(perpetualRaise,0)
618 EV_StopPlat(line);
619 P_ChangeSwitchTexture(line,0);
620 break;
621
622 case 164:
623 // Start fast crusher
624 // 164 S1 EV_DoCeiling(fastCrushAndRaise)
625 if (EV_DoCeiling(line,fastCrushAndRaise))
626 P_ChangeSwitchTexture(line,0);
627 break;
628
629 case 165:
630 // Start slow silent crusher
631 // 165 S1 EV_DoCeiling(silentCrushAndRaise)
632 if (EV_DoCeiling(line,silentCrushAndRaise))
633 P_ChangeSwitchTexture(line,0);
634 break;
635
636 case 166:
637 // Raise ceiling, Lower floor
638 // 166 S1 EV_DoCeiling(raiseToHighest), EV_DoFloor(lowerFloortoLowest)
639 if (EV_DoCeiling(line, raiseToHighest) ||
640 EV_DoFloor(line, lowerFloorToLowest))
641 P_ChangeSwitchTexture(line,0);
642 break;
643
644 case 167:
645 // Lower floor and Crush
646 // 167 S1 EV_DoCeiling(lowerAndCrush)
647 if (EV_DoCeiling(line, lowerAndCrush))
648 P_ChangeSwitchTexture(line,0);
649 break;
650
651 case 168:
652 // Stop crusher
653 // 168 S1 EV_CeilingCrushStop()
654 if (EV_CeilingCrushStop(line))
655 P_ChangeSwitchTexture(line,0);
656 break;
657
658 case 169:
659 // Lights to brightest neighbor sector
660 // 169 S1 EV_LightTurnOn(0)
661 EV_LightTurnOn(line,0);
662 P_ChangeSwitchTexture(line,0);
663 break;
664
665 case 170:
666 // Lights to near dark
667 // 170 S1 EV_LightTurnOn(35)
668 EV_LightTurnOn(line,35);
669 P_ChangeSwitchTexture(line,0);
670 break;
671
672 case 171:
673 // Lights on full
674 // 171 S1 EV_LightTurnOn(255)
675 EV_LightTurnOn(line,255);
676 P_ChangeSwitchTexture(line,0);
677 break;
678
679 case 172:
680 // Start Lights Strobing
681 // 172 S1 EV_StartLightStrobing()
682 EV_StartLightStrobing(line);
683 P_ChangeSwitchTexture(line,0);
684 break;
685
686 case 173:
687 // Lights to Dimmest Near
688 // 173 S1 EV_TurnTagLightsOff()
689 EV_TurnTagLightsOff(line);
690 P_ChangeSwitchTexture(line,0);
691 break;
692
693 case 174:
694 // Teleport
695 // 174 S1 EV_Teleport(side,thing)
696 if (EV_Teleport(line,side,thing))
697 P_ChangeSwitchTexture(line,0);
698 break;
699
700 case 175:
701 // Close Door, Open in 30 secs
702 // 175 S1 EV_DoDoor(close30ThenOpen)
703 if (EV_DoDoor(line,close30ThenOpen))
704 P_ChangeSwitchTexture(line,0);
705 break;
706
707 case 189: //jff 3/15/98 create texture change no motion type
708 // Texture Change Only (Trigger)
709 // 189 S1 Change Texture/Type Only
710 if (EV_DoChange(line,trigChangeOnly))
711 P_ChangeSwitchTexture(line,0);
712 break;
713
714 case 203:
715 // Lower ceiling to lowest surrounding ceiling
716 // 203 S1 EV_DoCeiling(lowerToLowest)
717 if (EV_DoCeiling(line,lowerToLowest))
718 P_ChangeSwitchTexture(line,0);
719 break;
720
721 case 204:
722 // Lower ceiling to highest surrounding floor
723 // 204 S1 EV_DoCeiling(lowerToMaxFloor)
724 if (EV_DoCeiling(line,lowerToMaxFloor))
725 P_ChangeSwitchTexture(line,0);
726 break;
727
728 case 209:
729 // killough 1/31/98: silent teleporter
730 //jff 209 S1 SilentTeleport
731 if (EV_SilentTeleport(line, side, thing))
732 P_ChangeSwitchTexture(line,0);
733 break;
734
735 case 241: //jff 3/15/98 create texture change no motion type
736 // Texture Change Only (Numeric)
737 // 241 S1 Change Texture/Type Only
738 if (EV_DoChange(line,numChangeOnly))
739 P_ChangeSwitchTexture(line,0);
740 break;
741
742 case 221:
743 // Lower floor to next lowest floor
744 // 221 S1 Lower Floor To Nearest Floor
745 if (EV_DoFloor(line,lowerFloorToNearest))
746 P_ChangeSwitchTexture(line,0);
747 break;
748
749 case 229:
750 // Raise elevator next floor
751 // 229 S1 Raise Elevator next floor
752 if (EV_DoElevator(line,elevateUp))
753 P_ChangeSwitchTexture(line,0);
754 break;
755
756 case 233:
757 // Lower elevator next floor
758 // 233 S1 Lower Elevator next floor
759 if (EV_DoElevator(line,elevateDown))
760 P_ChangeSwitchTexture(line,0);
761 break;
762
763 case 237:
764 // Elevator to current floor
765 // 237 S1 Elevator to current floor
766 if (EV_DoElevator(line,elevateCurrent))
767 P_ChangeSwitchTexture(line,0);
768 break;
769
770
771 // jff 1/29/98 end of added S1 linedef types
772
773 //jff 1/29/98 added linedef types to fill all functions out so that
774 // all possess SR, S1, WR, W1 types
775
776 case 78: //jff 3/15/98 create texture change no motion type
777 // Texture Change Only (Numeric)
778 // 78 SR Change Texture/Type Only
779 if (EV_DoChange(line,numChangeOnly))
780 P_ChangeSwitchTexture(line,1);
781 break;
782
783 case 176:
784 // Raise Floor to shortest lower texture
785 // 176 SR EV_DoFloor(raiseToTexture), CSW(1)
786 if (EV_DoFloor(line,raiseToTexture))
787 P_ChangeSwitchTexture(line,1);
788 break;
789
790 case 177:
791 // Raise Floor to shortest lower texture
792 // 177 SR EV_DoFloor(lowerAndChange)
793 if (EV_DoFloor(line,lowerAndChange))
794 P_ChangeSwitchTexture(line,1);
795 break;
796
797 case 178:
798 // Raise Floor 512
799 // 178 SR EV_DoFloor(raiseFloor512)
800 if (EV_DoFloor(line,raiseFloor512))
801 P_ChangeSwitchTexture(line,1);
802 break;
803
804 case 179:
805 // Raise Floor 24 and change
806 // 179 SR EV_DoFloor(raiseFloor24AndChange)
807 if (EV_DoFloor(line,raiseFloor24AndChange))
808 P_ChangeSwitchTexture(line,1);
809 break;
810
811 case 180:
812 // Raise Floor 24
813 // 180 SR EV_DoFloor(raiseFloor24)
814 if (EV_DoFloor(line,raiseFloor24))
815 P_ChangeSwitchTexture(line,1);
816 break;
817
818 case 181:
819 // Moving floor min n to max n
820 // 181 SR EV_DoPlat(perpetualRaise,0)
821
822 EV_DoPlat(line,perpetualRaise,0);
823 P_ChangeSwitchTexture(line,1);
824 break;
825
826 case 182:
827 // Stop Moving floor
828 // 182 SR EV_DoPlat(perpetualRaise,0)
829 EV_StopPlat(line);
830 P_ChangeSwitchTexture(line,1);
831 break;
832
833 case 183:
834 // Start fast crusher
835 // 183 SR EV_DoCeiling(fastCrushAndRaise)
836 if (EV_DoCeiling(line,fastCrushAndRaise))
837 P_ChangeSwitchTexture(line,1);
838 break;
839
840 case 184:
841 // Start slow crusher
842 // 184 SR EV_DoCeiling(crushAndRaise)
843 if (EV_DoCeiling(line,crushAndRaise))
844 P_ChangeSwitchTexture(line,1);
845 break;
846
847 case 185:
848 // Start slow silent crusher
849 // 185 SR EV_DoCeiling(silentCrushAndRaise)
850 if (EV_DoCeiling(line,silentCrushAndRaise))
851 P_ChangeSwitchTexture(line,1);
852 break;
853
854 case 186:
855 // Raise ceiling, Lower floor
856 // 186 SR EV_DoCeiling(raiseToHighest), EV_DoFloor(lowerFloortoLowest)
857 if (EV_DoCeiling(line, raiseToHighest) ||
858 EV_DoFloor(line, lowerFloorToLowest))
859 P_ChangeSwitchTexture(line,1);
860 break;
861
862 case 187:
863 // Lower floor and Crush
864 // 187 SR EV_DoCeiling(lowerAndCrush)
865 if (EV_DoCeiling(line, lowerAndCrush))
866 P_ChangeSwitchTexture(line,1);
867 break;
868
869 case 188:
870 // Stop crusher
871 // 188 SR EV_CeilingCrushStop()
872 if (EV_CeilingCrushStop(line))
873 P_ChangeSwitchTexture(line,1);
874 break;
875
876 case 190: //jff 3/15/98 create texture change no motion type
877 // Texture Change Only (Trigger)
878 // 190 SR Change Texture/Type Only
879 if (EV_DoChange(line,trigChangeOnly))
880 P_ChangeSwitchTexture(line,1);
881 break;
882
883 case 191:
884 // Lower Pillar, Raise Donut
885 // 191 SR EV_DoDonut()
886 if (EV_DoDonut(line))
887 P_ChangeSwitchTexture(line,1);
888 break;
889
890 case 192:
891 // Lights to brightest neighbor sector
892 // 192 SR EV_LightTurnOn(0)
893 EV_LightTurnOn(line,0);
894 P_ChangeSwitchTexture(line,1);
895 break;
896
897 case 193:
898 // Start Lights Strobing
899 // 193 SR EV_StartLightStrobing()
900 EV_StartLightStrobing(line);
901 P_ChangeSwitchTexture(line,1);
902 break;
903
904 case 194:
905 // Lights to Dimmest Near
906 // 194 SR EV_TurnTagLightsOff()
907 EV_TurnTagLightsOff(line);
908 P_ChangeSwitchTexture(line,1);
909 break;
910
911 case 195:
912 // Teleport
913 // 195 SR EV_Teleport(side,thing)
914 if (EV_Teleport(line,side,thing))
915 P_ChangeSwitchTexture(line,1);
916 break;
917
918 case 196:
919 // Close Door, Open in 30 secs
920 // 196 SR EV_DoDoor(close30ThenOpen)
921 if (EV_DoDoor(line,close30ThenOpen))
922 P_ChangeSwitchTexture(line,1);
923 break;
924
925 case 205:
926 // Lower ceiling to lowest surrounding ceiling
927 // 205 SR EV_DoCeiling(lowerToLowest)
928 if (EV_DoCeiling(line,lowerToLowest))
929 P_ChangeSwitchTexture(line,1);
930 break;
931
932 case 206:
933 // Lower ceiling to highest surrounding floor
934 // 206 SR EV_DoCeiling(lowerToMaxFloor)
935 if (EV_DoCeiling(line,lowerToMaxFloor))
936 P_ChangeSwitchTexture(line,1);
937 break;
938
939 case 210:
940 // killough 1/31/98: silent teleporter
941 //jff 210 SR SilentTeleport
942 if (EV_SilentTeleport(line, side, thing))
943 P_ChangeSwitchTexture(line,1);
944 break;
945
946 case 211: //jff 3/14/98 create instant toggle floor type
947 // Toggle Floor Between C and F Instantly
948 // 211 SR Toggle Floor Instant
949 if (EV_DoPlat(line,toggleUpDn,0))
950 P_ChangeSwitchTexture(line,1);
951 break;
952
953 case 222:
954 // Lower floor to next lowest floor
955 // 222 SR Lower Floor To Nearest Floor
956 if (EV_DoFloor(line,lowerFloorToNearest))
957 P_ChangeSwitchTexture(line,1);
958 break;
959
960 case 230:
961 // Raise elevator next floor
962 // 230 SR Raise Elevator next floor
963 if (EV_DoElevator(line,elevateUp))
964 P_ChangeSwitchTexture(line,1);
965 break;
966
967 case 234:
968 // Lower elevator next floor
969 // 234 SR Lower Elevator next floor
970 if (EV_DoElevator(line,elevateDown))
971 P_ChangeSwitchTexture(line,1);
972 break;
973
974 case 238:
975 // Elevator to current floor
976 // 238 SR Elevator to current floor
977 if (EV_DoElevator(line,elevateCurrent))
978 P_ChangeSwitchTexture(line,1);
979 break;
980
981 case 258:
982 // Build stairs, step 8
983 // 258 SR EV_BuildStairs(build8)
984 if (EV_BuildStairs(line,build8))
985 P_ChangeSwitchTexture(line,1);
986 break;
987
988 case 259:
989 // Build stairs, step 16
990 // 259 SR EV_BuildStairs(turbo16)
991 if (EV_BuildStairs(line,turbo16))
992 P_ChangeSwitchTexture(line,1);
993 break;
994
995 // 1/29/98 jff end of added SR linedef types
996
997 }
998 break;
999
1000 // Buttons (retriggerable switches)
1001 case 42:
1002 // Close Door
1003 if (EV_DoDoor(line,p_close))
1004 P_ChangeSwitchTexture(line,1);
1005 break;
1006
1007 case 43:
1008 // Lower Ceiling to Floor
1009 if (EV_DoCeiling(line,lowerToFloor))
1010 P_ChangeSwitchTexture(line,1);
1011 break;
1012
1013 case 45:
1014 // Lower Floor to Surrounding floor height
1015 if (EV_DoFloor(line,lowerFloor))
1016 P_ChangeSwitchTexture(line,1);
1017 break;
1018
1019 case 60:
1020 // Lower Floor to Lowest
1021 if (EV_DoFloor(line,lowerFloorToLowest))
1022 P_ChangeSwitchTexture(line,1);
1023 break;
1024
1025 case 61:
1026 // Open Door
1027 if (EV_DoDoor(line,p_open))
1028 P_ChangeSwitchTexture(line,1);
1029 break;
1030
1031 case 62:
1032 // PlatDownWaitUpStay
1033 if (EV_DoPlat(line,downWaitUpStay,1))
1034 P_ChangeSwitchTexture(line,1);
1035 break;
1036
1037 case 63:
1038 // Raise Door
1039 if (EV_DoDoor(line,normal))
1040 P_ChangeSwitchTexture(line,1);
1041 break;
1042
1043 case 64:
1044 // Raise Floor to ceiling
1045 if (EV_DoFloor(line,raiseFloor))
1046 P_ChangeSwitchTexture(line,1);
1047 break;
1048
1049 case 66:
1050 // Raise Floor 24 and change texture
1051 if (EV_DoPlat(line,raiseAndChange,24))
1052 P_ChangeSwitchTexture(line,1);
1053 break;
1054
1055 case 67:
1056 // Raise Floor 32 and change texture
1057 if (EV_DoPlat(line,raiseAndChange,32))
1058 P_ChangeSwitchTexture(line,1);
1059 break;
1060
1061 case 65:
1062 // Raise Floor Crush
1063 if (EV_DoFloor(line,raiseFloorCrush))
1064 P_ChangeSwitchTexture(line,1);
1065 break;
1066
1067 case 68:
1068 // Raise Plat to next highest floor and change texture
1069 if (EV_DoPlat(line,raiseToNearestAndChange,0))
1070 P_ChangeSwitchTexture(line,1);
1071 break;
1072
1073 case 69:
1074 // Raise Floor to next highest floor
1075 if (EV_DoFloor(line, raiseFloorToNearest))
1076 P_ChangeSwitchTexture(line,1);
1077 break;
1078
1079 case 70:
1080 // Turbo Lower Floor
1081 if (EV_DoFloor(line,turboLower))
1082 P_ChangeSwitchTexture(line,1);
1083 break;
1084
1085 case 114:
1086 // Blazing Door Raise (faster than TURBO!)
1087 if (EV_DoDoor (line,blazeRaise))
1088 P_ChangeSwitchTexture(line,1);
1089 break;
1090
1091 case 115:
1092 // Blazing Door Open (faster than TURBO!)
1093 if (EV_DoDoor (line,blazeOpen))
1094 P_ChangeSwitchTexture(line,1);
1095 break;
1096
1097 case 116:
1098 // Blazing Door Close (faster than TURBO!)
1099 if (EV_DoDoor (line,blazeClose))
1100 P_ChangeSwitchTexture(line,1);
1101 break;
1102
1103 case 123:
1104 // Blazing PlatDownWaitUpStay
1105 if (EV_DoPlat(line,blazeDWUS,0))
1106 P_ChangeSwitchTexture(line,1);
1107 break;
1108
1109 case 132:
1110 // Raise Floor Turbo
1111 if (EV_DoFloor(line,raiseFloorTurbo))
1112 P_ChangeSwitchTexture(line,1);
1113 break;
1114
1115 case 99:
1116 // BlzOpenDoor BLUE
1117 case 134:
1118 // BlzOpenDoor RED
1119 case 136:
1120 // BlzOpenDoor YELLOW
1121 if (EV_DoLockedDoor (line,blazeOpen,thing))
1122 P_ChangeSwitchTexture(line,1);
1123 break;
1124
1125 case 138:
1126 // Light Turn On
1127 EV_LightTurnOn(line,255);
1128 P_ChangeSwitchTexture(line,1);
1129 break;
1130
1131 case 139:
1132 // Light Turn Off
1133 EV_LightTurnOn(line,35);
1134 P_ChangeSwitchTexture(line,1);
1135 break;
1136 }
1137 return true;
1138}
diff --git a/apps/plugins/doom/p_telept.c b/apps/plugins/doom/p_telept.c
new file mode 100644
index 0000000000..9282e9f42e
--- /dev/null
+++ b/apps/plugins/doom/p_telept.c
@@ -0,0 +1,322 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION:
28 * Teleportation.
29 *
30 *-----------------------------------------------------------------------------*/
31
32#include "doomdef.h"
33#include "doomstat.h"
34#include "p_spec.h"
35#include "p_maputl.h"
36#include "p_map.h"
37#include "r_main.h"
38#include "p_tick.h"
39#include "s_sound.h"
40#include "sounds.h"
41#include "p_user.h"
42#include "rockmacros.h"
43//
44// TELEPORTATION
45//
46// killough 5/3/98: reformatted, cleaned up
47
48int EV_Teleport(line_t *line, int side, mobj_t *thing)
49{
50 thinker_t *thinker;
51 mobj_t *m;
52 int i;
53
54 // don't teleport missiles
55 // Don't teleport if hit back of line,
56 // so you can get out of teleporter.
57 if (side || thing->flags & MF_MISSILE)
58 return 0;
59
60 // killough 1/31/98: improve performance by using
61 // P_FindSectorFromLineTag instead of simple linear search.
62
63 for (i = -1; (i = P_FindSectorFromLineTag(line, i)) >= 0;)
64 for (thinker=thinkercap.next; thinker!=&thinkercap; thinker=thinker->next)
65 if (thinker->function == P_MobjThinker &&
66 (m = (mobj_t *) thinker)->type == MT_TELEPORTMAN &&
67 m->subsector->sector-sectors == i)
68 {
69 fixed_t oldx = thing->x, oldy = thing->y, oldz = thing->z;
70 player_t *player = thing->player;
71
72 // killough 5/12/98: exclude voodoo dolls:
73 if (player && player->mo != thing)
74 player = NULL;
75
76 if (!P_TeleportMove(thing, m->x, m->y, false)) /* killough 8/9/98 */
77 return 0;
78
79 if (!(demo_compatibility && gamemission >= pack_tnt))
80 thing->z = thing->floorz;
81
82 if (player)
83 player->viewz = thing->z + player->viewheight;
84
85 // spawn teleport fog and emit sound at source
86 S_StartSound(P_SpawnMobj(oldx, oldy, oldz, MT_TFOG), sfx_telept);
87
88 // spawn teleport fog and emit sound at destination
89 S_StartSound(P_SpawnMobj(m->x +
90 20*finecosine[m->angle>>ANGLETOFINESHIFT],
91 m->y +
92 20*finesine[m->angle>>ANGLETOFINESHIFT],
93 thing->z, MT_TFOG),
94 sfx_telept);
95
96 /* don't move for a bit
97 * cph - DEMOSYNC - BOOM had (player) here? */
98 if (thing->player)
99 thing->reactiontime = 18;
100
101 thing->angle = m->angle;
102
103 thing->momx = thing->momy = thing->momz = 0;
104
105 /* killough 10/98: kill all bobbing momentum too */
106 if (player)
107 player->momx = player->momy = 0;
108
109 return 1;
110 }
111 return 0;
112}
113
114//
115// Silent TELEPORTATION, by Lee Killough
116// Primarily for rooms-over-rooms etc.
117//
118
119int EV_SilentTeleport(line_t *line, int side, mobj_t *thing)
120{
121 int i;
122 mobj_t *m;
123 thinker_t *th;
124
125 // don't teleport missiles
126 // Don't teleport if hit back of line,
127 // so you can get out of teleporter.
128
129 if (side || thing->flags & MF_MISSILE)
130 return 0;
131
132 for (i = -1; (i = P_FindSectorFromLineTag(line, i)) >= 0;)
133 for (th = thinkercap.next; th != &thinkercap; th = th->next)
134 if (th->function == P_MobjThinker &&
135 (m = (mobj_t *) th)->type == MT_TELEPORTMAN &&
136 m->subsector->sector-sectors == i)
137 {
138 // Height of thing above ground, in case of mid-air teleports:
139 fixed_t z = thing->z - thing->floorz;
140
141 // Get the angle between the exit thing and source linedef.
142 // Rotate 90 degrees, so that walking perpendicularly across
143 // teleporter linedef causes thing to exit in the direction
144 // indicated by the exit thing.
145 angle_t angle =
146 R_PointToAngle2(0, 0, line->dx, line->dy) - m->angle + ANG90;
147
148 // Sine, cosine of angle adjustment
149 fixed_t s = finesine[angle>>ANGLETOFINESHIFT];
150 fixed_t c = finecosine[angle>>ANGLETOFINESHIFT];
151
152 // Momentum of thing crossing teleporter linedef
153 fixed_t momx = thing->momx;
154 fixed_t momy = thing->momy;
155
156 // Whether this is a player, and if so, a pointer to its player_t
157 player_t *player = thing->player;
158
159 // Attempt to teleport, aborting if blocked
160 if (!P_TeleportMove(thing, m->x, m->y, false)) /* killough 8/9/98 */
161 return 0;
162
163 // Rotate thing according to difference in angles
164 thing->angle += angle;
165
166 // Adjust z position to be same height above ground as before
167 thing->z = z + thing->floorz;
168
169 // Rotate thing's momentum to come out of exit just like it entered
170 thing->momx = FixedMul(momx, c) - FixedMul(momy, s);
171 thing->momy = FixedMul(momy, c) + FixedMul(momx, s);
172
173 // Adjust player's view, in case there has been a height change
174 // Voodoo dolls are excluded by making sure player->mo == thing.
175 if (player && player->mo == thing)
176 {
177 // Save the current deltaviewheight, used in stepping
178 fixed_t deltaviewheight = player->deltaviewheight;
179
180 // Clear deltaviewheight, since we don't want any changes
181 player->deltaviewheight = 0;
182
183 // Set player's view according to the newly set parameters
184 P_CalcHeight(player);
185
186 // Reset the delta to have the same dynamics as before
187 player->deltaviewheight = deltaviewheight;
188 }
189 return 1;
190 }
191 return 0;
192}
193
194//
195// Silent linedef-based TELEPORTATION, by Lee Killough
196// Primarily for rooms-over-rooms etc.
197// This is the complete player-preserving kind of teleporter.
198// It has advantages over the teleporter with thing exits.
199//
200
201// maximum fixed_t units to move object to avoid hiccups
202#define FUDGEFACTOR 10
203
204int EV_SilentLineTeleport(line_t *line, int side, mobj_t *thing,
205 boolean reverse)
206{
207 int i;
208 line_t *l;
209
210 if (side || thing->flags & MF_MISSILE)
211 return 0;
212
213 for (i = -1; (i = P_FindLineFromLineTag(line, i)) >= 0;)
214 if ((l=lines+i) != line && l->backsector)
215 {
216 // Get the thing's position along the source linedef
217 fixed_t pos = D_abs(line->dx) > D_abs(line->dy) ?
218 FixedDiv(thing->x - line->v1->x, line->dx) :
219 FixedDiv(thing->y - line->v1->y, line->dy) ;
220
221 // Get the angle between the two linedefs, for rotating
222 // orientation and momentum. Rotate 180 degrees, and flip
223 // the position across the exit linedef, if reversed.
224 angle_t angle = (reverse ? pos = FRACUNIT-pos, 0 : ANG180) +
225 R_PointToAngle2(0, 0, l->dx, l->dy) -
226 R_PointToAngle2(0, 0, line->dx, line->dy);
227
228 // Interpolate position across the exit linedef
229 fixed_t x = l->v2->x - FixedMul(pos, l->dx);
230 fixed_t y = l->v2->y - FixedMul(pos, l->dy);
231
232 // Sine, cosine of angle adjustment
233 fixed_t s = finesine[angle>>ANGLETOFINESHIFT];
234 fixed_t c = finecosine[angle>>ANGLETOFINESHIFT];
235
236 // Maximum distance thing can be moved away from interpolated
237 // exit, to ensure that it is on the correct side of exit linedef
238 int fudge = FUDGEFACTOR;
239
240 // Whether this is a player, and if so, a pointer to its player_t.
241 // Voodoo dolls are excluded by making sure thing->player->mo==thing.
242 player_t *player = thing->player && thing->player->mo == thing ?
243 thing->player : NULL;
244
245 // Whether walking towards first side of exit linedef steps down
246 int stepdown =
247 l->frontsector->floorheight < l->backsector->floorheight;
248
249 // Height of thing above ground
250 fixed_t z = thing->z - thing->floorz;
251
252 // Side to exit the linedef on positionally.
253 //
254 // Notes:
255 //
256 // This flag concerns exit position, not momentum. Due to
257 // roundoff error, the thing can land on either the left or
258 // the right side of the exit linedef, and steps must be
259 // taken to make sure it does not end up on the wrong side.
260 //
261 // Exit momentum is always towards side 1 in a reversed
262 // teleporter, and always towards side 0 otherwise.
263 //
264 // Exiting positionally on side 1 is always safe, as far
265 // as avoiding oscillations and stuck-in-wall problems,
266 // but may not be optimum for non-reversed teleporters.
267 //
268 // Exiting on side 0 can cause oscillations if momentum
269 // is towards side 1, as it is with reversed teleporters.
270 //
271 // Exiting on side 1 slightly improves player viewing
272 // when going down a step on a non-reversed teleporter.
273
274 int side = reverse || (player && stepdown);
275
276 // Make sure we are on correct side of exit linedef.
277 while (P_PointOnLineSide(x, y, l) != side && --fudge>=0)
278 if (D_abs(l->dx) > D_abs(l->dy))
279 y -= (l->dx < 0) != side ? -1 : 1;
280 else
281 x += (l->dy < 0) != side ? -1 : 1;
282
283 // Attempt to teleport, aborting if blocked
284 if (!P_TeleportMove(thing, x, y, false)) /* killough 8/9/98 */
285 return 0;
286
287 // Adjust z position to be same height above ground as before.
288 // Ground level at the exit is measured as the higher of the
289 // two floor heights at the exit linedef.
290 thing->z = z + sides[l->sidenum[stepdown]].sector->floorheight;
291
292 // Rotate thing's orientation according to difference in linedef angles
293 thing->angle += angle;
294
295 // Momentum of thing crossing teleporter linedef
296 x = thing->momx;
297 y = thing->momy;
298
299 // Rotate thing's momentum to come out of exit just like it entered
300 thing->momx = FixedMul(x, c) - FixedMul(y, s);
301 thing->momy = FixedMul(y, c) + FixedMul(x, s);
302
303 // Adjust a player's view, in case there has been a height change
304 if (player)
305 {
306 // Save the current deltaviewheight, used in stepping
307 fixed_t deltaviewheight = player->deltaviewheight;
308
309 // Clear deltaviewheight, since we don't want any changes now
310 player->deltaviewheight = 0;
311
312 // Set player's view according to the newly set parameters
313 P_CalcHeight(player);
314
315 // Reset the delta to have the same dynamics as before
316 player->deltaviewheight = deltaviewheight;
317 }
318
319 return 1;
320 }
321 return 0;
322}
diff --git a/apps/plugins/doom/p_tick.c b/apps/plugins/doom/p_tick.c
new file mode 100644
index 0000000000..4bf8feaf7e
--- /dev/null
+++ b/apps/plugins/doom/p_tick.c
@@ -0,0 +1,255 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION:
28 * Thinker, Ticker.
29 *
30 *-----------------------------------------------------------------------------*/
31
32#include "doomstat.h"
33#include "p_user.h"
34#include "p_spec.h"
35#include "p_tick.h"
36#include "p_map.h"
37#include "rockmacros.h"
38int leveltime;
39
40//
41// THINKERS
42// All thinkers should be allocated by Z_Malloc
43// so they can be operated on uniformly.
44// The actual structures will vary in size,
45// but the first element must be thinker_t.
46//
47
48// Both the head and tail of the thinker list.
49thinker_t thinkercap;
50
51// killough 8/29/98: we maintain several separate threads, each containing
52// a special class of thinkers, to allow more efficient searches.
53
54thinker_t thinkerclasscap[NUMTHCLASS];
55
56//
57// P_InitThinkers
58//
59
60void P_InitThinkers(void)
61{
62 int i;
63
64 for (i=0; i<NUMTHCLASS; i++) // killough 8/29/98: initialize threaded lists
65 thinkerclasscap[i].cprev = thinkerclasscap[i].cnext = &thinkerclasscap[i];
66
67 thinkercap.prev = thinkercap.next = &thinkercap;
68}
69
70//
71// killough 8/29/98:
72//
73// We maintain separate threads of friends and enemies, to permit more
74// efficient searches.
75//
76
77void P_UpdateThinker(thinker_t *thinker)
78{
79 // find the class the thinker belongs to
80
81 int class = thinker->function == P_MobjThinker &&
82 ((mobj_t *) thinker)->health > 0 &&
83 (((mobj_t *) thinker)->flags & MF_COUNTKILL ||
84 ((mobj_t *) thinker)->type == MT_SKULL) ?
85 ((mobj_t *) thinker)->flags & MF_FRIEND ?
86 th_friends : th_enemies : th_misc;
87
88 // Remove from current thread
89 thinker_t *th = thinker->cnext;
90 (th->cprev = thinker->cprev)->cnext = th;
91
92 // Add to appropriate thread
93 th = &thinkerclasscap[class];
94 th->cprev->cnext = thinker;
95 thinker->cnext = th;
96 thinker->cprev = th->cprev;
97 th->cprev = thinker;
98}
99
100//
101// P_AddThinker
102// Adds a new thinker at the end of the list.
103//
104
105void P_AddThinker(thinker_t* thinker)
106{
107 thinkercap.prev->next = thinker;
108 thinker->next = &thinkercap;
109 thinker->prev = thinkercap.prev;
110 thinkercap.prev = thinker;
111
112 thinker->references = 0; // killough 11/98: init reference counter to 0
113
114 // killough 8/29/98: set sentinel pointers, and then add to appropriate list
115 thinker->cnext = thinker->cprev = thinker;
116 P_UpdateThinker(thinker);
117}
118
119//
120// killough 11/98:
121//
122// Make currentthinker external, so that P_RemoveThinkerDelayed
123// can adjust currentthinker when thinkers self-remove.
124
125static thinker_t *currentthinker;
126
127//
128// P_RemoveThinkerDelayed()
129//
130// Called automatically as part of the thinker loop in P_RunThinkers(),
131// on nodes which are pending deletion.
132//
133// If this thinker has no more pointers referencing it indirectly,
134// remove it, and set currentthinker to one node preceeding it, so
135// that the next step in P_RunThinkers() will get its successor.
136//
137
138void P_RemoveThinkerDelayed(thinker_t *thinker)
139{
140 if (!thinker->references)
141 {
142 thinker_t *next = thinker->next;
143 (next->prev = currentthinker = thinker->prev)->next = next;
144 Z_Free(thinker);
145 }
146}
147
148//
149// P_RemoveThinker
150//
151// Deallocation is lazy -- it will not actually be freed
152// until its thinking turn comes up.
153//
154// killough 4/25/98:
155//
156// Instead of marking the function with -1 value cast to a function pointer,
157// set the function to P_RemoveThinkerDelayed(), so that later, it will be
158// removed automatically as part of the thinker process.
159//
160
161void P_RemoveThinker(thinker_t *thinker)
162{
163 thinker->function = P_RemoveThinkerDelayed;
164
165 // killough 8/29/98: remove immediately from threaded list
166 (thinker->cnext->cprev = thinker->cprev)->cnext = thinker->cnext;
167}
168
169/*
170 * P_SetTarget
171 *
172 * This function is used to keep track of pointer references to mobj thinkers.
173 * In Doom, objects such as lost souls could sometimes be removed despite
174 * their still being referenced. In Boom, 'target' mobj fields were tested
175 * during each gametic, and any objects pointed to by them would be prevented
176 * from being removed. But this was incomplete, and was slow (every mobj was
177 * checked during every gametic). Now, we keep a count of the number of
178 * references, and delay removal until the count is 0.
179 */
180
181void P_SetTarget(mobj_t **mop, mobj_t *targ)
182{
183 if (*mop) // If there was a target already, decrease its refcount
184 (*mop)->thinker.references--;
185 if ((*mop = targ)) // Set new target and if non-NULL, increase its counter
186 targ->thinker.references++;
187}
188
189//
190// P_RunThinkers
191//
192// killough 4/25/98:
193//
194// Fix deallocator to stop using "next" pointer after node has been freed
195// (a Doom bug).
196//
197// Process each thinker. For thinkers which are marked deleted, we must
198// load the "next" pointer prior to freeing the node. In Doom, the "next"
199// pointer was loaded AFTER the thinker was freed, which could have caused
200// crashes.
201//
202// But if we are not deleting the thinker, we should reload the "next"
203// pointer after calling the function, in case additional thinkers are
204// added at the end of the list.
205//
206// killough 11/98:
207//
208// Rewritten to delete nodes implicitly, by making currentthinker
209// external and using P_RemoveThinkerDelayed() implicitly.
210//
211
212static void P_RunThinkers (void)
213{
214 for (currentthinker = thinkercap.next;
215 currentthinker != &thinkercap;
216 currentthinker = currentthinker->next)
217 if (currentthinker->function)
218 currentthinker->function(currentthinker);
219}
220
221//
222// P_Ticker
223//
224
225void P_Ticker (void)
226{
227 int i;
228
229 /* pause if in menu and at least one tic has been run
230 *
231 * killough 9/29/98: note that this ties in with basetic,
232 * since G_Ticker does the pausing during recording or
233 * playback, and compenates by incrementing basetic.
234 *
235 * All of this complicated mess is used to preserve demo sync.
236 */
237
238 if (paused || (menuactive && !demoplayback && !netgame &&
239 players[consoleplayer].viewz != 1))
240 return;
241
242 P_MapStart();
243 // not if this is an intermission screen
244 if(gamestate==GS_LEVEL)
245 for (i=0; i<MAXPLAYERS; i++)
246 if (playeringame[i])
247 P_PlayerThink(&players[i]);
248
249 P_RunThinkers();
250 P_UpdateSpecials();
251 P_RespawnSpecials();
252 P_MapEnd();
253 leveltime++; // for par times
254}
255
diff --git a/apps/plugins/doom/p_tick.h b/apps/plugins/doom/p_tick.h
new file mode 100644
index 0000000000..5a495166b3
--- /dev/null
+++ b/apps/plugins/doom/p_tick.h
@@ -0,0 +1,66 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION:
28 * Core thinker processing prototypes.
29 *-----------------------------------------------------------------------------*/
30
31#ifndef __P_TICK__
32#define __P_TICK__
33
34#include "d_think.h"
35
36#ifdef __GNUG__
37#pragma interface
38#endif
39
40/* Called by C_Ticker, can call G_PlayerExited.
41 * Carries out all thinking of monsters and players. */
42
43void P_Ticker(void);
44
45extern thinker_t thinkercap; // Both the head and tail of the thinker list
46
47void P_InitThinkers(void);
48void P_AddThinker(thinker_t *thinker);
49void P_RemoveThinker(thinker_t *thinker);
50void P_RemoveThinkerDelayed(thinker_t *thinker); // killough 4/25/98
51
52void P_UpdateThinker(thinker_t *thinker); // killough 8/29/98
53
54void P_SetTarget(mobj_t **mo, mobj_t *target); // killough 11/98
55
56// killough 8/29/98: threads of thinkers, for more efficient searches
57typedef enum {
58 th_misc,
59 th_friends,
60 th_enemies,
61 NUMTHCLASS
62} th_class;
63
64extern thinker_t thinkerclasscap[];
65
66#endif
diff --git a/apps/plugins/doom/p_user.c b/apps/plugins/doom/p_user.c
new file mode 100644
index 0000000000..abbe36b12c
--- /dev/null
+++ b/apps/plugins/doom/p_user.c
@@ -0,0 +1,420 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION:
28 * Player related stuff.
29 * Bobbing POV/weapon, movement.
30 * Pending weapon.
31 *
32 *-----------------------------------------------------------------------------*/
33
34#include "doomstat.h"
35#include "d_event.h"
36#include "r_main.h"
37#include "p_map.h"
38#include "p_spec.h"
39#include "p_user.h"
40#include "rockmacros.h"
41// Index of the special effects (INVUL inverse) map.
42
43#define INVERSECOLORMAP 32
44
45//
46// Movement.
47//
48
49// 16 pixels of bob
50
51#define MAXBOB 0x100000
52
53boolean onground; // whether player is on ground or in air
54
55//
56// P_Thrust
57// Moves the given origin along a given angle.
58//
59
60void P_Thrust(player_t* player,angle_t angle,fixed_t move)
61{
62 angle >>= ANGLETOFINESHIFT;
63 player->mo->momx += FixedMul(move,finecosine[angle]);
64 player->mo->momy += FixedMul(move,finesine[angle]);
65}
66
67
68/*
69 * P_Bob
70 * Same as P_Thrust, but only affects bobbing.
71 *
72 * killough 10/98: We apply thrust separately between the real physical player
73 * and the part which affects bobbing. This way, bobbing only comes from player
74 * motion, nothing external, avoiding many problems, e.g. bobbing should not
75 * occur on conveyors, unless the player walks on one, and bobbing should be
76 * reduced at a regular rate, even on ice (where the player coasts).
77 */
78
79void P_Bob(player_t *player, angle_t angle, fixed_t move)
80{
81 player->momx += FixedMul(move,finecosine[angle >>= ANGLETOFINESHIFT]);
82 player->momy += FixedMul(move,finesine[angle]);
83}
84
85//
86// P_CalcHeight
87// Calculate the walking / running height adjustment
88//
89
90void P_CalcHeight (player_t* player)
91{
92 int angle;
93 fixed_t bob;
94
95 // Regular movement bobbing
96 // (needs to be calculated for gun swing
97 // even if not on ground)
98 // OPTIMIZE: tablify angle
99 // Note: a LUT allows for effects
100 // like a ramp with low health.
101
102
103 /* killough 10/98: Make bobbing depend only on player-applied motion.
104 *
105 * Note: don't reduce bobbing here if on ice: if you reduce bobbing here,
106 * it causes bobbing jerkiness when the player moves from ice to non-ice,
107 * and vice-versa.
108 */
109 player->bob = !mbf_features ?
110 (FixedMul (player->mo->momx, player->mo->momx)
111 + FixedMul (player->mo->momy,player->mo->momy))>>2 :
112 player_bobbing ? (FixedMul(player->momx,player->momx) +
113 FixedMul(player->momy,player->momy))>>2 : 0;
114
115 if (player->bob > MAXBOB)
116 player->bob = MAXBOB;
117
118 if (!onground || player->cheats & CF_NOMOMENTUM)
119 {
120 player->viewz = player->mo->z + VIEWHEIGHT;
121
122 if (player->viewz > player->mo->ceilingz-4*FRACUNIT)
123 player->viewz = player->mo->ceilingz-4*FRACUNIT;
124
125 // The following line was in the Id source and appears // phares 2/25/98
126 // to be a bug. player->viewz is checked in a similar
127 // manner at a different exit below.
128
129 // player->viewz = player->mo->z + player->viewheight;
130 return;
131 }
132
133 angle = (FINEANGLES/20*leveltime)&FINEMASK;
134 bob = FixedMul(player->bob/2,finesine[angle]);
135
136 // move viewheight
137
138 if (player->playerstate == PST_LIVE)
139 {
140 player->viewheight += player->deltaviewheight;
141
142 if (player->viewheight > VIEWHEIGHT)
143 {
144 player->viewheight = VIEWHEIGHT;
145 player->deltaviewheight = 0;
146 }
147
148 if (player->viewheight < VIEWHEIGHT/2)
149 {
150 player->viewheight = VIEWHEIGHT/2;
151 if (player->deltaviewheight <= 0)
152 player->deltaviewheight = 1;
153 }
154
155 if (player->deltaviewheight)
156 {
157 player->deltaviewheight += FRACUNIT/4;
158 if (!player->deltaviewheight)
159 player->deltaviewheight = 1;
160 }
161 }
162
163 player->viewz = player->mo->z + player->viewheight + bob;
164
165 if (player->viewz > player->mo->ceilingz-4*FRACUNIT)
166 player->viewz = player->mo->ceilingz-4*FRACUNIT;
167}
168
169
170//
171// P_MovePlayer
172//
173// Adds momentum if the player is not in the air
174//
175// killough 10/98: simplified
176
177void P_MovePlayer (player_t* player)
178{
179 ticcmd_t *cmd = &player->cmd;
180 mobj_t *mo = player->mo;
181
182 mo->angle += cmd->angleturn << 16;
183 onground = mo->z <= mo->floorz;
184
185 // killough 10/98:
186 //
187 // We must apply thrust to the player and bobbing separately, to avoid
188 // anomalies. The thrust applied to bobbing is always the same strength on
189 // ice, because the player still "works just as hard" to move, while the
190 // thrust applied to the movement varies with 'movefactor'.
191
192 if (cmd->forwardmove | cmd->sidemove) // killough 10/98
193 {
194 if (onground || mo->flags & MF_BOUNCES) // killough 8/9/98
195 {
196 int friction, movefactor = P_GetMoveFactor(mo, &friction);
197
198 // killough 11/98:
199 // On sludge, make bobbing depend on efficiency.
200 // On ice, make it depend on effort.
201
202 int bobfactor =
203 friction < ORIG_FRICTION ? movefactor : ORIG_FRICTION_FACTOR;
204
205 if (cmd->forwardmove)
206 {
207 P_Bob(player,mo->angle,cmd->forwardmove*bobfactor);
208 P_Thrust(player,mo->angle,cmd->forwardmove*movefactor);
209 }
210
211 if (cmd->sidemove)
212 {
213 P_Bob(player,mo->angle-ANG90,cmd->sidemove*bobfactor);
214 P_Thrust(player,mo->angle-ANG90,cmd->sidemove*movefactor);
215 }
216 }
217 if (mo->state == states+S_PLAY)
218 P_SetMobjState(mo,S_PLAY_RUN1);
219 }
220}
221
222#define ANG5 (ANG90/18)
223
224//
225// P_DeathThink
226// Fall on your face when dying.
227// Decrease POV height to floor height.
228//
229
230void P_DeathThink (player_t* player)
231{
232 angle_t angle;
233 angle_t delta;
234
235 P_MovePsprites (player);
236
237 // fall to the ground
238
239 if (player->viewheight > 6*FRACUNIT)
240 player->viewheight -= FRACUNIT;
241
242 if (player->viewheight < 6*FRACUNIT)
243 player->viewheight = 6*FRACUNIT;
244
245 player->deltaviewheight = 0;
246 onground = (player->mo->z <= player->mo->floorz);
247 P_CalcHeight (player);
248
249 if (player->attacker && player->attacker != player->mo)
250 {
251 angle = R_PointToAngle2 (player->mo->x,
252 player->mo->y,
253 player->attacker->x,
254 player->attacker->y);
255
256 delta = angle - player->mo->angle;
257
258 if (delta < ANG5 || delta > (unsigned)-ANG5)
259 {
260 // Looking at killer,
261 // so fade damage flash down.
262
263 player->mo->angle = angle;
264
265 if (player->damagecount)
266 player->damagecount--;
267 }
268 else if (delta < ANG180)
269 player->mo->angle += ANG5;
270 else
271 player->mo->angle -= ANG5;
272 }
273 else if (player->damagecount)
274 player->damagecount--;
275
276 if (player->cmd.buttons & BT_USE)
277 player->playerstate = PST_REBORN;
278}
279
280
281//
282// P_PlayerThink
283//
284
285void P_PlayerThink (player_t* player)
286{
287 ticcmd_t* cmd;
288 weapontype_t newweapon;
289
290 // killough 2/8/98, 3/21/98:
291 if (player->cheats & CF_NOCLIP)
292 player->mo->flags |= MF_NOCLIP;
293 else
294 player->mo->flags &= ~MF_NOCLIP;
295
296 // chain saw run forward
297
298 cmd = &player->cmd;
299 if (player->mo->flags & MF_JUSTATTACKED)
300 {
301 cmd->angleturn = 0;
302 cmd->forwardmove = 0xc800/512;
303 cmd->sidemove = 0;
304 player->mo->flags &= ~MF_JUSTATTACKED;
305 }
306
307 if (player->playerstate == PST_DEAD)
308 {
309 P_DeathThink (player);
310 return;
311 }
312
313 // Move around.
314 // Reactiontime is used to prevent movement
315 // for a bit after a teleport.
316
317 if (player->mo->reactiontime)
318 player->mo->reactiontime--;
319 else
320 P_MovePlayer (player);
321
322 P_CalcHeight (player); // Determines view height and bobbing
323
324 // Determine if there's anything about the sector you're in that's
325 // going to affect you, like painful floors.
326
327 if (player->mo->subsector->sector->special)
328 P_PlayerInSpecialSector (player);
329
330 // Check for weapon change.
331
332 if (cmd->buttons & BT_CHANGE)
333 {
334 // The actual changing of the weapon is done
335 // when the weapon psprite can do it
336 // (read: not in the middle of an attack).
337
338 newweapon = (cmd->buttons & BT_WEAPONMASK)>>BT_WEAPONSHIFT;
339
340 // killough 3/22/98: For demo compatibility we must perform the fist
341 // and SSG weapons switches here, rather than in G_BuildTiccmd(). For
342 // other games which rely on user preferences, we must use the latter.
343
344 if (demo_compatibility)
345 { // compatibility mode -- required for old demos -- killough
346 if (newweapon == wp_fist && player->weaponowned[wp_chainsaw] &&
347 (player->readyweapon != wp_chainsaw ||
348 !player->powers[pw_strength]))
349 newweapon = wp_chainsaw;
350 if (gamemode == commercial &&
351 newweapon == wp_shotgun &&
352 player->weaponowned[wp_supershotgun] &&
353 player->readyweapon != wp_supershotgun)
354 newweapon = wp_supershotgun;
355 }
356
357 // killough 2/8/98, 3/22/98 -- end of weapon selection changes
358
359 if (player->weaponowned[newweapon] && newweapon != player->readyweapon)
360
361 // Do not go to plasma or BFG in shareware,
362 // even if cheated.
363
364 if ((newweapon != wp_plasma && newweapon != wp_bfg)
365 || (gamemode != shareware) )
366 player->pendingweapon = newweapon;
367 }
368
369 // check for use
370
371 if (cmd->buttons & BT_USE)
372 {
373 if (!player->usedown)
374 {
375 P_UseLines (player);
376 player->usedown = true;
377 }
378 }
379 else
380 player->usedown = false;
381
382 // cycle psprites
383
384 P_MovePsprites (player);
385
386 // Counters, time dependent power ups.
387
388 // Strength counts up to diminish fade.
389
390 if (player->powers[pw_strength])
391 player->powers[pw_strength]++;
392
393 // killough 1/98: Make idbeholdx toggle:
394
395 if (player->powers[pw_invulnerability] > 0) // killough
396 player->powers[pw_invulnerability]--;
397
398 if (player->powers[pw_invisibility] > 0) // killough
399 if (! --player->powers[pw_invisibility] )
400 player->mo->flags &= ~MF_SHADOW;
401
402 if (player->powers[pw_infrared] > 0) // killough
403 player->powers[pw_infrared]--;
404
405 if (player->powers[pw_ironfeet] > 0) // killough
406 player->powers[pw_ironfeet]--;
407
408 if (player->damagecount)
409 player->damagecount--;
410
411 if (player->bonuscount)
412 player->bonuscount--;
413
414 // Handling colormaps.
415 // killough 3/20/98: reformat to terse C syntax
416
417 player->fixedcolormap = player->powers[pw_invulnerability] > 4*32 ||
418 player->powers[pw_invulnerability] & 8 ? INVERSECOLORMAP :
419 player->powers[pw_infrared] > 4*32 || player->powers[pw_infrared] & 8;
420}
diff --git a/apps/plugins/doom/p_user.h b/apps/plugins/doom/p_user.h
new file mode 100644
index 0000000000..a236b2a03c
--- /dev/null
+++ b/apps/plugins/doom/p_user.h
@@ -0,0 +1,45 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION:
28 * Player related stuff.
29 * Bobbing POV/weapon, movement.
30 * Pending weapon.
31 *
32 *-----------------------------------------------------------------------------*/
33
34#ifndef __P_USER__
35#define __P_USER__
36
37#include "d_player.h"
38
39void P_PlayerThink(player_t *player);
40void P_CalcHeight(player_t *player);
41void P_DeathThink(player_t *player);
42void P_MovePlayer(player_t *player);
43void P_Thrust(player_t *player, angle_t angle, fixed_t move);
44
45#endif /* __P_USER__ */
diff --git a/apps/plugins/doom/r_bsp.c b/apps/plugins/doom/r_bsp.c
new file mode 100644
index 0000000000..358787dc58
--- /dev/null
+++ b/apps/plugins/doom/r_bsp.c
@@ -0,0 +1,576 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION:
28 * BSP traversal, handling of LineSegs for rendering.
29 *
30 *-----------------------------------------------------------------------------*/
31
32#include "doomdef.h"
33
34#include "m_bbox.h"
35
36#include "i_system.h"
37
38#include "r_main.h"
39#include "r_plane.h"
40#include "r_things.h"
41
42// State.
43#include "doomstat.h"
44#include "r_state.h"
45#include "r_segs.h"
46#include "rockmacros.h"
47
48seg_t *curline;
49side_t *sidedef;
50line_t *linedef;
51sector_t *frontsector;
52sector_t *backsector;
53drawseg_t *ds_p;
54
55
56drawseg_t *drawsegs;
57unsigned maxdrawsegs;
58
59//
60// R_ClearDrawSegs
61//
62void R_ClearDrawSegs (void)
63{
64 ds_p = drawsegs;
65}
66
67// CPhipps -
68// Instead of clipsegs, let's try using an array with one entry for each column,
69// indicating whether it's blocked by a solid wall yet or not.
70
71byte solidcol[SCREENWIDTH] IBSS_ATTR;
72
73// CPhipps -
74// R_ClipWallSegment
75//
76// Replaces the old R_Clip*WallSegment functions. It draws bits of walls in those
77// columns which aren't solid, and updates the solidcol[] array appropriately
78
79void R_ClipWallSegment(int first, int last, boolean solid)
80{
81 byte *p;
82 while (first < last) {
83 if (solidcol[first]) {
84 if (!(p = memchr(solidcol+first, 0, last-first))) return; // All solid
85 first = p - solidcol;
86 } else {
87 int to;
88 if (!(p = memchr(solidcol+first, 1, last-first))) to = last;
89 else to = p - solidcol;
90 R_StoreWallRange(first, to-1);
91 if (solid) {
92 memset(solidcol+first,1,to-first);
93 }
94 first = to;
95 }
96 }
97}
98
99//
100// R_ClearClipSegs
101//
102
103void R_ClearClipSegs (void)
104{
105 memset(solidcol, 0, SCREENWIDTH);
106}
107
108// killough 1/18/98 -- This function is used to fix the automap bug which
109// showed lines behind closed doors simply because the door had a dropoff.
110//
111// cph - converted to R_RecalcLineFlags. This recalculates all the flags for
112// a line, including closure and texture tiling.
113
114static void R_RecalcLineFlags(void)
115{
116 linedef->r_validcount = gametic;
117
118 /* First decide if the line is closed, normal, or invisible */
119 if (!(linedef->flags & ML_TWOSIDED)
120 || backsector->ceilingheight <= frontsector->floorheight
121 || backsector->floorheight >= frontsector->ceilingheight
122 || (
123 // if door is closed because back is shut:
124 backsector->ceilingheight <= backsector->floorheight
125
126 // preserve a kind of transparent door/lift special effect:
127 && (backsector->ceilingheight >= frontsector->ceilingheight ||
128 curline->sidedef->toptexture)
129
130 && (backsector->floorheight <= frontsector->floorheight ||
131 curline->sidedef->bottomtexture)
132
133 // properly render skies (consider door "open" if both ceilings are sky):
134 && (backsector->ceilingpic !=skyflatnum ||
135 frontsector->ceilingpic!=skyflatnum)
136 )
137 )
138 linedef->r_flags = RF_CLOSED;
139 else {
140 // Reject empty lines used for triggers
141 // and special events.
142 // Identical floor and ceiling on both sides,
143 // identical light levels on both sides,
144 // and no middle texture.
145 // CPhipps - recode for speed, not certain if this is portable though
146 if (backsector->ceilingheight != frontsector->ceilingheight
147 || backsector->floorheight != frontsector->floorheight
148 || curline->sidedef->midtexture
149 || memcmp(&backsector->floor_xoffs, &frontsector->floor_xoffs,
150 sizeof(frontsector->floor_xoffs) + sizeof(frontsector->floor_yoffs) +
151 sizeof(frontsector->ceiling_xoffs) + sizeof(frontsector->ceiling_yoffs) +
152 sizeof(frontsector->ceilingpic) + sizeof(frontsector->floorpic) +
153 sizeof(frontsector->lightlevel) + sizeof(frontsector->floorlightsec) +
154 sizeof(frontsector->ceilinglightsec))) {
155 linedef->r_flags = 0; return;
156 } else
157 linedef->r_flags = RF_IGNORE;
158 }
159
160 /* cph - I'm too lazy to try and work with offsets in this */
161 if (curline->sidedef->rowoffset) return;
162
163 /* Now decide on texture tiling */
164 if (linedef->flags & ML_TWOSIDED) {
165 int c;
166
167 /* Does top texture need tiling */
168 if ((c = frontsector->ceilingheight - backsector->ceilingheight) > 0 &&
169 (textureheight[texturetranslation[curline->sidedef->toptexture]] > c))
170 linedef->r_flags |= RF_TOP_TILE;
171
172 /* Does bottom texture need tiling */
173 if ((c = frontsector->floorheight - backsector->floorheight) > 0 &&
174 (textureheight[texturetranslation[curline->sidedef->bottomtexture]] > c))
175 linedef->r_flags |= RF_BOT_TILE;
176 } else {
177 int c;
178 /* Does middle texture need tiling */
179 if ((c = frontsector->ceilingheight - frontsector->floorheight) > 0 &&
180 (textureheight[texturetranslation[curline->sidedef->midtexture]] > c))
181 linedef->r_flags |= RF_MID_TILE;
182 }
183}
184
185//
186// killough 3/7/98: Hack floor/ceiling heights for deep water etc.
187//
188// If player's view height is underneath fake floor, lower the
189// drawn ceiling to be just under the floor height, and replace
190// the drawn floor and ceiling textures, and light level, with
191// the control sector's.
192//
193// Similar for ceiling, only reflected.
194//
195// killough 4/11/98, 4/13/98: fix bugs, add 'back' parameter
196//
197
198sector_t *R_FakeFlat(sector_t *sec, sector_t *tempsec,
199 int *floorlightlevel, int *ceilinglightlevel,
200 boolean back)
201{
202 if (floorlightlevel)
203 *floorlightlevel = sec->floorlightsec == -1 ?
204 sec->lightlevel : sectors[sec->floorlightsec].lightlevel;
205
206 if (ceilinglightlevel)
207 *ceilinglightlevel = sec->ceilinglightsec == -1 ? // killough 4/11/98
208 sec->lightlevel : sectors[sec->ceilinglightsec].lightlevel;
209
210 if (sec->heightsec != -1)
211 {
212 const sector_t *s = &sectors[sec->heightsec];
213 int heightsec = viewplayer->mo->subsector->sector->heightsec;
214 int underwater = heightsec!=-1 && viewz<=sectors[heightsec].floorheight;
215
216 // Replace sector being drawn, with a copy to be hacked
217 *tempsec = *sec;
218
219 // Replace floor and ceiling height with other sector's heights.
220 tempsec->floorheight = s->floorheight;
221 tempsec->ceilingheight = s->ceilingheight;
222
223 // killough 11/98: prevent sudden light changes from non-water sectors:
224 if (underwater && (tempsec-> floorheight = sec->floorheight,
225 tempsec->ceilingheight = s->floorheight-1, !back))
226 { // head-below-floor hack
227 tempsec->floorpic = s->floorpic;
228 tempsec->floor_xoffs = s->floor_xoffs;
229 tempsec->floor_yoffs = s->floor_yoffs;
230
231 if (underwater) {
232 if (s->ceilingpic == skyflatnum) {
233 tempsec->floorheight = tempsec->ceilingheight+1;
234 tempsec->ceilingpic = tempsec->floorpic;
235 tempsec->ceiling_xoffs = tempsec->floor_xoffs;
236 tempsec->ceiling_yoffs = tempsec->floor_yoffs;
237 } else {
238 tempsec->ceilingpic = s->ceilingpic;
239 tempsec->ceiling_xoffs = s->ceiling_xoffs;
240 tempsec->ceiling_yoffs = s->ceiling_yoffs;
241 }
242 }
243
244 tempsec->lightlevel = s->lightlevel;
245
246 if (floorlightlevel)
247 *floorlightlevel = s->floorlightsec == -1 ? s->lightlevel :
248 sectors[s->floorlightsec].lightlevel; // killough 3/16/98
249
250 if (ceilinglightlevel)
251 *ceilinglightlevel = s->ceilinglightsec == -1 ? s->lightlevel :
252 sectors[s->ceilinglightsec].lightlevel; // killough 4/11/98
253 }
254 else
255 if (heightsec != -1 && viewz >= sectors[heightsec].ceilingheight &&
256 sec->ceilingheight > s->ceilingheight)
257 { // Above-ceiling hack
258 tempsec->ceilingheight = s->ceilingheight;
259 tempsec->floorheight = s->ceilingheight + 1;
260
261 tempsec->floorpic = tempsec->ceilingpic = s->ceilingpic;
262 tempsec->floor_xoffs = tempsec->ceiling_xoffs = s->ceiling_xoffs;
263 tempsec->floor_yoffs = tempsec->ceiling_yoffs = s->ceiling_yoffs;
264
265 if (s->floorpic != skyflatnum)
266 {
267 tempsec->ceilingheight = sec->ceilingheight;
268 tempsec->floorpic = s->floorpic;
269 tempsec->floor_xoffs = s->floor_xoffs;
270 tempsec->floor_yoffs = s->floor_yoffs;
271 }
272
273 tempsec->lightlevel = s->lightlevel;
274
275 if (floorlightlevel)
276 *floorlightlevel = s->floorlightsec == -1 ? s->lightlevel :
277 sectors[s->floorlightsec].lightlevel; // killough 3/16/98
278
279 if (ceilinglightlevel)
280 *ceilinglightlevel = s->ceilinglightsec == -1 ? s->lightlevel :
281 sectors[s->ceilinglightsec].lightlevel; // killough 4/11/98
282 }
283 sec = tempsec; // Use other sector
284 }
285 return sec;
286}
287
288//
289// R_AddLine
290// Clips the given segment
291// and adds any visible pieces to the line list.
292//
293
294static void R_AddLine (seg_t *line)
295{
296 int x1;
297 int x2;
298 angle_t angle1;
299 angle_t angle2;
300 angle_t span;
301 angle_t tspan;
302 static sector_t tempsec; // killough 3/8/98: ceiling/water hack
303 // boolean solid = true;
304
305 curline = line;
306
307 angle1 = R_PointToAngle (line->v1->x, line->v1->y);
308 angle2 = R_PointToAngle (line->v2->x, line->v2->y);
309
310 // Clip to view edges.
311 span = angle1 - angle2;
312
313 // Back side, i.e. backface culling
314 if (span >= ANG180)
315 return;
316
317 // Global angle needed by segcalc.
318 rw_angle1 = angle1;
319 angle1 -= viewangle;
320 angle2 -= viewangle;
321
322 tspan = angle1 + clipangle;
323 if (tspan > 2*clipangle)
324 {
325 tspan -= 2*clipangle;
326
327 // Totally off the left edge?
328 if (tspan >= span)
329 return;
330
331 angle1 = clipangle;
332 }
333
334 tspan = clipangle - angle2;
335 if (tspan > 2*clipangle)
336 {
337 tspan -= 2*clipangle;
338
339 // Totally off the left edge?
340 if (tspan >= span)
341 return;
342 angle2 = 0-clipangle;
343 }
344
345 // The seg is in the view range,
346 // but not necessarily visible.
347
348 angle1 = (angle1+ANG90)>>ANGLETOFINESHIFT;
349 angle2 = (angle2+ANG90)>>ANGLETOFINESHIFT;
350
351 // killough 1/31/98: Here is where "slime trails" can SOMETIMES occur:
352 x1 = viewangletox[angle1];
353 x2 = viewangletox[angle2];
354
355 // Does not cross a pixel?
356 if (x1 >= x2) // killough 1/31/98 -- change == to >= for robustness
357 return;
358
359 backsector = line->backsector;
360
361 // Single sided line?
362 if (backsector)
363 // killough 3/8/98, 4/4/98: hack for invisible ceilings / deep water
364 backsector = R_FakeFlat(backsector, &tempsec, NULL, NULL, true);
365
366 /* cph - roll up linedef properties in flags */
367 if ((linedef = curline->linedef)->r_validcount != gametic)
368 R_RecalcLineFlags();
369
370 if (linedef->r_flags & RF_IGNORE)
371 {
372 return;
373 }
374 else
375 R_ClipWallSegment (x1, x2, linedef->r_flags & RF_CLOSED);
376}
377
378//
379// R_CheckBBox
380// Checks BSP node/subtree bounding box.
381// Returns true
382// if some part of the bbox might be visible.
383//
384
385static const int checkcoord[12][4] = // killough -- static const
386 {
387 {3,0,2,1},
388 {3,0,2,0},
389 {3,1,2,0},
390 {0},
391 {2,0,2,1},
392 {0,0,0,0},
393 {3,1,3,0},
394 {0},
395 {2,0,3,1},
396 {2,1,3,1},
397 {2,1,3,0}
398 };
399
400// killough 1/28/98: static // CPhipps - const parameter, reformatted
401static boolean R_CheckBBox(const fixed_t *bspcoord)
402{
403 angle_t angle1, angle2;
404
405 {
406 int boxpos;
407 const int* check;
408
409 // Find the corners of the box
410 // that define the edges from current viewpoint.
411 boxpos = (viewx <= bspcoord[BOXLEFT] ? 0 : viewx < bspcoord[BOXRIGHT ] ? 1 : 2) +
412 (viewy >= bspcoord[BOXTOP ] ? 0 : viewy > bspcoord[BOXBOTTOM] ? 4 : 8);
413
414 if (boxpos == 5)
415 return true;
416
417 check = checkcoord[boxpos];
418 angle1 = R_PointToAngle (bspcoord[check[0]], bspcoord[check[1]]) - viewangle;
419 angle2 = R_PointToAngle (bspcoord[check[2]], bspcoord[check[3]]) - viewangle;
420 }
421
422 // cph - replaced old code, which was unclear and badly commented
423 // Much more efficient code now
424 if ((signed)angle1 < (signed)angle2) { /* it's "behind" us */
425 /* Either angle1 or angle2 is behind us, so it doesn't matter if we
426 * change it to the corect sign
427 */
428 if ((angle1 >= ANG180) && (angle1 < ANG270))
429 angle1 = INT_MAX; /* which is ANG180-1 */
430 else
431 angle2 = INT_MIN;
432 }
433
434 if ((signed)angle2 >= (signed)clipangle) return false; // Both off left edge
435 if ((signed)angle1 <= -(signed)clipangle) return false; // Both off right edge
436 if ((signed)angle1 >= (signed)clipangle) angle1 = clipangle; // Clip at left edge
437 if ((signed)angle2 <= -(signed)clipangle) angle2 = 0-clipangle; // Clip at right edge
438
439 // Find the first clippost
440 // that touches the source post
441 // (adjacent pixels are touching).
442 angle1 = (angle1+ANG90)>>ANGLETOFINESHIFT;
443 angle2 = (angle2+ANG90)>>ANGLETOFINESHIFT;
444 {
445 int sx1 = viewangletox[angle1];
446 int sx2 = viewangletox[angle2];
447 // const cliprange_t *start;
448
449 // Does not cross a pixel.
450 if (sx1 == sx2)
451 return false;
452
453 if (!memchr(solidcol+sx1, 0, sx2-sx1)) return false;
454 // All columns it covers are already solidly covered
455 }
456
457 return true;
458}
459
460//
461// R_Subsector
462// Determine floor/ceiling planes.
463// Add sprites of things in sector.
464// Draw one or more line segments.
465//
466// killough 1/31/98 -- made static, polished
467
468// Had to move this out of the function - causes stack overflows in RockBox
469sector_t tempsec IBSS_ATTR; // killough 3/7/98: deep water hack
470static void R_Subsector(int num)
471{
472 int count;
473 seg_t *line;
474 subsector_t *sub;
475
476 int floorlightlevel; // killough 3/16/98: set floor lightlevel
477 int ceilinglightlevel; // killough 4/11/98
478
479#ifdef RANGECHECK
480 if (num>=numsubsectors)
481 I_Error ("R_Subsector: ss %i with numss = %i", num, numsubsectors);
482#endif
483
484 sub = &subsectors[num];
485 frontsector = sub->sector;
486 count = sub->numlines;
487 line = &segs[sub->firstline];
488// sscount++;
489
490 // killough 3/8/98, 4/4/98: Deep water / fake ceiling effect
491 frontsector = R_FakeFlat(frontsector, &tempsec, &floorlightlevel,
492 &ceilinglightlevel, false); // killough 4/11/98
493
494 // killough 3/7/98: Add (x,y) offsets to flats, add deep water check
495 // killough 3/16/98: add floorlightlevel
496 // killough 10/98: add support for skies transferred from sidedefs
497
498 floorplane = frontsector->floorheight < viewz || // killough 3/7/98
499 (frontsector->heightsec != -1 &&
500 sectors[frontsector->heightsec].ceilingpic == skyflatnum)
501 ?
502 R_FindPlane(frontsector->floorheight,
503 frontsector->floorpic == skyflatnum && // kilough 10/98
504 frontsector->sky & PL_SKYFLAT ? frontsector->sky :
505 frontsector->floorpic,
506 floorlightlevel, // killough 3/16/98
507 frontsector->floor_xoffs, // killough 3/7/98
508 frontsector->floor_yoffs
509 ) : NULL;
510
511 ceilingplane = frontsector->ceilingheight > viewz ||
512 frontsector->ceilingpic == skyflatnum ||
513 (frontsector->heightsec != -1 &&
514 sectors[frontsector->heightsec].floorpic == skyflatnum)
515 ?
516 R_FindPlane(frontsector->ceilingheight, // killough 3/8/98
517 frontsector->ceilingpic == skyflatnum && // kilough 10/98
518 frontsector->sky & PL_SKYFLAT ? frontsector->sky :
519 frontsector->ceilingpic,
520 ceilinglightlevel, // killough 4/11/98
521 frontsector->ceiling_xoffs, // killough 3/7/98
522 frontsector->ceiling_yoffs
523 ) : NULL;
524
525 // killough 9/18/98: Fix underwater slowdown, by passing real sector
526 // instead of fake one. Improve sprite lighting by basing sprite
527 // lightlevels on floor & ceiling lightlevels in the surrounding area.
528 //
529 // 10/98 killough:
530 //
531 // NOTE: TeamTNT fixed this bug incorrectly, messing up sprite lighting!!!
532 // That is part of the 242 effect!!! If you simply pass sub->sector to
533 // the old code you will not get correct lighting for underwater sprites!!!
534 // Either you must pass the fake sector and handle validcount here, on the
535 // real sector, or you must account for the lighting in some other way,
536 // like passing it as an argument.
537
538 R_AddSprites(sub, (floorlightlevel+ceilinglightlevel)/2);
539
540 while (count--)
541 {
542 if (line->miniseg == false)
543 R_AddLine (line);
544 line++;
545 }
546
547}
548
549//
550// RenderBSPNode
551// Renders all subsectors below a given node,
552// traversing subtree recursively.
553// Just call with BSP root.
554//
555// killough 5/2/98: reformatted, removed tail recursion
556
557void R_RenderBSPNode(int bspnum)
558{
559 while (!(bspnum & NF_SUBSECTOR)) // Found a subsector?
560 {
561 const node_t *bsp = &nodes[bspnum];
562
563 // Decide which side the view point is on.
564 int side = R_PointOnSide(viewx, viewy, bsp);
565 // Recursively divide front space.
566 R_RenderBSPNode(bsp->children[side]);
567
568 // Possibly divide back space.
569
570 if (!R_CheckBBox(bsp->bbox[side^1]))
571 return;
572
573 bspnum = bsp->children[side^1];
574 }
575 R_Subsector(bspnum == -1 ? 0 : bspnum & ~NF_SUBSECTOR);
576}
diff --git a/apps/plugins/doom/r_bsp.h b/apps/plugins/doom/r_bsp.h
new file mode 100644
index 0000000000..2ea653833d
--- /dev/null
+++ b/apps/plugins/doom/r_bsp.h
@@ -0,0 +1,78 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION:
28 * Refresh module, BSP traversal and handling.
29 *
30 *-----------------------------------------------------------------------------*/
31
32
33#ifndef __R_BSP__
34#define __R_BSP__
35
36#ifdef __GNUG__
37#pragma interface
38#endif
39
40extern seg_t *curline;
41extern side_t *sidedef;
42extern line_t *linedef;
43extern sector_t *frontsector;
44extern sector_t *backsector;
45extern int rw_x;
46extern int rw_stopx;
47extern boolean segtextured;
48extern boolean markfloor; /* false if the back side is the same plane */
49extern boolean markceiling;
50
51//extern boolean skymap;
52
53/* old code -- killough:
54 * extern drawseg_t drawsegs[MAXDRAWSEGS];
55 * new code -- killough: */
56extern drawseg_t *drawsegs;
57extern unsigned maxdrawsegs;
58
59extern drawseg_t* ds_p;
60
61/*extern lighttable_t** hscalelight;
62extern lighttable_t** vscalelight;
63extern lighttable_t** dscalelight;
64*/
65
66//typedef void (*drawfunc_t) (int start, int stop);
67
68
69// BSP?
70void R_ClearClipSegs (void);
71void R_ClearDrawSegs (void);
72void R_RenderBSPNode (int bspnum);
73int R_DoorClosed(void); /* killough 1/17/98 */
74
75/* killough 4/13/98: fake floors/ceilings for deep water / fake ceilings: */
76sector_t *R_FakeFlat(sector_t *, sector_t *, int *, int *, boolean);
77
78#endif
diff --git a/apps/plugins/doom/r_data.c b/apps/plugins/doom/r_data.c
new file mode 100644
index 0000000000..aad16e4d95
--- /dev/null
+++ b/apps/plugins/doom/r_data.c
@@ -0,0 +1,975 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION:
28 * Preparation of data for rendering,
29 * generation of lookups, caching, retrieval by name.
30 *
31 *-----------------------------------------------------------------------------*/
32
33#include "doomstat.h"
34#include "w_wad.h"
35#include "r_main.h"
36#include "r_sky.h"
37#include "i_system.h"
38#include "m_swap.h"
39#include "p_tick.h"
40//#include "lprintf.h" // jff 08/03/98 - declaration of lprintf
41#include "rockmacros.h"
42//
43// Graphics.
44// DOOM graphics for walls and sprites
45// is stored in vertical runs of opaque pixels (posts).
46// A column is composed of zero or more posts,
47// a patch or sprite is composed of zero or more columns.
48//
49
50//
51// Texture definition.
52// Each texture is composed of one or more patches,
53// with patches being lumps stored in the WAD.
54// The lumps are referenced by number, and patched
55// into the rectangular texture space using origin
56// and possibly other attributes.
57//
58
59typedef struct
60{
61 short originx;
62 short originy;
63 short patch;
64 short stepdir; // unused in Doom but might be used in Phase 2 Boom
65 short colormap; // unused in Doom but might be used in Phase 2 Boom
66} PACKEDATTR mappatch_t;
67
68typedef struct
69{
70 char name[8];
71 boolean masked;
72 short width;
73 short height;
74 char pad[4]; // unused in Doom but might be used in Boom Phase 2
75 short patchcount;
76 mappatch_t patches[1];
77} PACKEDATTR maptexture_t;
78
79// A maptexturedef_t describes a rectangular texture, which is composed
80// of one or more mappatch_t structures that arrange graphic patches.
81
82// killough 4/17/98: make firstcolormaplump,lastcolormaplump external
83int firstcolormaplump, lastcolormaplump; // killough 4/17/98
84
85int firstflat, lastflat, numflats;
86int firstspritelump, lastspritelump, numspritelumps;
87int numtextures;
88static texture_t **textures;
89fixed_t *textureheight; //needed for texture pegging (and TFE fix - killough)
90int *flattranslation; // for global animation
91int *texturetranslation;
92// needed for pre-rendering
93fixed_t *spritewidth, *spriteoffset, *spritetopoffset;
94
95//
96// MAPTEXTURE_T CACHING
97// When a texture is first needed,
98// it counts the number of composite columns
99// required in the texture and allocates space
100// for a column directory and any new columns.
101// The directory will simply point inside other patches
102// if there is only one patch in a given column,
103// but any columns with multiple patches
104// will have new column_ts generated.
105//
106
107//
108// R_DrawColumnInCache
109// Clip and draw a column
110// from a patch into a cached post.
111//
112// Rewritten by Lee Killough for performance and to fix Medusa bug
113//
114
115void R_DrawColumnInCache(const column_t *patch, byte *cache,
116 int originy, int cacheheight, byte *marks)
117{
118 while (patch->topdelta != 0xff)
119 {
120 int count = patch->length;
121 int position = originy + patch->topdelta;
122
123 if (position < 0)
124 {
125 count += position;
126 position = 0;
127 }
128
129 if (position + count > cacheheight)
130 count = cacheheight - position;
131
132 if (count > 0)
133 {
134 memcpy (cache + position, (byte *)patch + 3, count);
135
136 // killough 4/9/98: remember which cells in column have been drawn,
137 // so that column can later be converted into a series of posts, to
138 // fix the Medusa bug.
139
140 memset (marks + position, 0xff, count);
141 }
142
143 patch = (column_t *)((byte *) patch + patch->length + 4);
144 }
145}
146
147//
148// R_GenerateComposite
149// Using the texture definition,
150// the composite texture is created from the patches,
151// and each column is cached.
152//
153// Rewritten by Lee Killough for performance and to fix Medusa bug
154
155void R_GenerateComposite(int texnum)
156{
157 texture_t *texture = textures[texnum];
158 byte *block = Z_Malloc(texture->compositesize, PU_STATIC,
159 (void **)&texture->composite);
160 // Composite the columns together.
161 texpatch_t *patch = texture->patches;
162 short *collump = texture->columnlump;
163 unsigned *colofs = texture->columnofs; // killough 4/9/98: make 32-bit
164 int i = texture->patchcount;
165 // killough 4/9/98: marks to identify transparent regions in merged textures
166 byte *marks = calloc(texture->width, texture->height), *source;
167
168 for (; --i >=0; patch++)
169 {
170 const patch_t *realpatch = W_CacheLumpNum(patch->patch); // cph
171 int x1 = patch->originx, x2 = x1 + SHORT(realpatch->width);
172 const int *cofs = realpatch->columnofs-x1;
173 if (x1<0)
174 x1 = 0;
175 if (x2 > texture->width)
176 x2 = texture->width;
177 for (; x1<x2 ; x1++)
178 if (collump[x1] == -1) // Column has multiple patches?
179 // killough 1/25/98, 4/9/98: Fix medusa bug.
180 R_DrawColumnInCache((column_t*)((byte*)realpatch+LONG(cofs[x1])),
181 block+colofs[x1],patch->originy,texture->height,
182 marks + x1 * texture->height);
183
184 W_UnlockLumpNum(patch->patch); // cph - unlock the patch lump
185 }
186
187 // killough 4/9/98: Next, convert multipatched columns into true columns,
188 // to fix Medusa bug while still allowing for transparent regions.
189
190 source = malloc(texture->height); // temporary column
191 for (i=0; i < texture->width; i++)
192 if (collump[i] == -1) // process only multipatched columns
193 {
194 column_t *col = (column_t *)(block + colofs[i] - 3); // cached column
195 const byte *mark = marks + i * texture->height;
196 int j = 0;
197
198 // save column in temporary so we can shuffle it around
199 memcpy(source, (byte *) col + 3, texture->height);
200
201 for (;;) // reconstruct the column by scanning transparency marks
202 {
203 while (j < texture->height && !mark[j]) // skip transparent cells
204 j++;
205 if (j >= texture->height) // if at end of column
206 {
207 col->topdelta = -1; // end-of-column marker
208 break;
209 }
210 col->topdelta = j; // starting offset of post
211 for (col->length=0; j < texture->height && mark[j]; j++)
212 col->length++; // count opaque cells
213 // copy opaque cells from the temporary back into the column
214 memcpy((byte *) col + 3, source + col->topdelta, col->length);
215 col = (column_t *)((byte *) col + col->length + 4); // next post
216 }
217 }
218 free(source); // free temporary column
219 free(marks); // free transparency marks
220
221 // Now that the texture has been built in column cache,
222 // it is purgable from zone memory.
223
224 Z_ChangeTag(block, PU_CACHE);
225}
226
227//
228// R_GenerateLookup
229//
230// Rewritten by Lee Killough for performance and to fix Medusa bug
231//
232
233static void R_GenerateLookup(int texnum, int *const errors)
234{
235 texture_t *texture = textures[texnum];
236
237 // killough 4/9/98: make column offsets 32-bit;
238 // clean up malloc-ing to use sizeof
239 // CPhipps - moved allocing here
240 short *collump = texture->columnlump =
241 Z_Malloc(texture->width*sizeof(*texture->columnlump), PU_STATIC,0);
242 unsigned *colofs = texture->columnofs =
243 Z_Malloc(texture->width*sizeof(*texture->columnofs), PU_STATIC,0);
244
245 // killough 4/9/98: keep count of posts in addition to patches.
246 // Part of fix for medusa bug for multipatched 2s normals.
247
248 struct {
249 unsigned short patches, posts;
250 } *count = calloc(sizeof *count, texture->width);
251
252 {
253 int i = texture->patchcount;
254 const texpatch_t *patch = texture->patches;
255
256 while (--i >= 0)
257 {
258 int pat = patch->patch;
259 const patch_t *realpatch = W_CacheLumpNum(pat);
260 int x1 = patch++->originx, x2 = x1 + SHORT(realpatch->width), x = x1;
261 const int *cofs = realpatch->columnofs-x1;
262
263 if (x2 > texture->width)
264 x2 = texture->width;
265 if (x1 < 0)
266 x = 0;
267 for ( ; x<x2 ; x++)
268 {
269 // killough 4/9/98: keep a count of the number of posts in column,
270 // to fix Medusa bug while allowing for transparent multipatches.
271
272 const column_t *col = (column_t*)((byte*)realpatch+LONG(cofs[x]));
273 for (;col->topdelta != 0xff; count[x].posts++)
274 col = (column_t *)((byte *) col + col->length + 4);
275 count[x].patches++;
276 collump[x] = pat;
277 colofs[x] = LONG(cofs[x])+3;
278 }
279
280 W_UnlockLumpNum(pat);
281 }
282 }
283
284 // Composited texture not created yet.
285 texture->composite = NULL;
286
287 // Now count the number of columns
288 // that are covered by more than one patch.
289 // Fill in the lump / offset, so columns
290 // with only a single patch are all done.
291
292 {
293 int x = texture->width;
294 int height = texture->height;
295 int csize = 0;
296
297 while (--x >= 0)
298 {
299 if (!count[x].patches) // killough 4/9/98
300 {
301 //jff 8/3/98 use logical output routine
302 printf("\nR_GenerateLookup: Column %d is without a patch in texture %s",
303 x, texture->name);
304 if (errors) ++*errors;
305 else I_Error("R_GenerateLookup: Failed");
306 }
307 if (count[x].patches > 1) // killough 4/9/98
308 {
309 // killough 1/25/98, 4/9/98:
310 //
311 // Fix Medusa bug, by adding room for column header
312 // and trailer bytes for each post in merged column.
313 // For now, just allocate conservatively 4 bytes
314 // per post per patch per column, since we don't
315 // yet know how many posts the merged column will
316 // require, and it's bounded above by this limit.
317
318 collump[x] = -1; // mark lump as multipatched
319 colofs[x] = csize + 3; // three header bytes in a column
320 csize += 4*count[x].posts+1; // 1 stop byte plus 4 bytes per post
321 }
322 csize += height; // height bytes of texture data
323 }
324 texture->compositesize = csize;
325 }
326 free(count); // killough 4/9/98
327}
328
329//
330// R_GetColumn
331//
332
333const byte *R_GetColumn(int tex, int col)
334{
335 const texture_t *texture = textures[tex];
336 if (!texture->columnlump) R_GenerateLookup(tex, NULL);
337 {
338 int lump = texture->columnlump[col &= texture->widthmask];
339 int ofs = texture->columnofs[col]; // cph - WARNING: must be after the above line
340 // cph - remember the last lump, so we can unlock it if no longer needed,
341 // or reuse it if possible to reduce lump locking/unlocking
342 static int lastlump = -1;
343 static const byte* lastlumpdata;
344
345 if ((lump<=0) && (lastlump<=0))
346 lump = lastlump; // cph - force equal
347
348 if (lump != lastlump) {
349 // cph - must change the cached lump
350 if (lastlump>0)
351 W_UnlockLumpNum(lastlump);
352
353 if ((lastlump = lump) > 0)
354 lastlumpdata = W_CacheLumpNum(lump);
355#ifdef RANGECHECK
356 else
357 lastlumpdata = NULL;
358#endif
359 }
360
361 if (lump > 0)
362 return lastlumpdata + ofs;
363
364 if (!texture->composite)
365 R_GenerateComposite(tex);
366
367 return texture->composite + ofs;
368 }
369}
370
371//
372// R_InitTextures
373// Initializes the texture list
374// with the textures from the world map.
375//
376
377void R_InitTextures (void)
378{
379 maptexture_t *mtexture;
380 texture_t *texture;
381 mappatch_t *mpatch;
382 texpatch_t *patch;
383 int i, j;
384 int maptex_lump[2] = {-1, -1};
385 const int *maptex;
386 const int *maptex1, *maptex2;
387 char name[9];
388 int names_lump; // cph - new wad lump handling
389 const char *names; // cph -
390 const char *name_p;// const*'s
391 int *patchlookup;
392 int totalwidth;
393 int nummappatches;
394 int offset;
395 int maxoff, maxoff2;
396 int numtextures1, numtextures2;
397 const int *directory;
398 int errors = 0;
399
400 // Load the patch names from pnames.lmp.
401 name[8] = 0;
402 names = W_CacheLumpNum(names_lump = W_GetNumForName("PNAMES"));
403 nummappatches = LONG(*((const int *)names));
404 name_p = names+4;
405 patchlookup = malloc(nummappatches*sizeof(*patchlookup)); // killough
406
407 for (i=0 ; i<nummappatches ; i++)
408 {
409 strncpy (name,name_p+i*8, 8);
410 patchlookup[i] = W_CheckNumForName(name);
411 if (patchlookup[i] == -1)
412 {
413 // killough 4/17/98:
414 // Some wads use sprites as wall patches, so repeat check and
415 // look for sprites this time, but only if there were no wall
416 // patches found. This is the same as allowing for both, except
417 // that wall patches always win over sprites, even when they
418 // appear first in a wad. This is a kludgy solution to the wad
419 // lump namespace problem.
420
421 patchlookup[i] = (W_CheckNumForName)(name, ns_sprites);
422
423 if (patchlookup[i] == -1 && devparm)
424 //jff 8/3/98 use logical output routine
425 printf("\nWarning: patch %.8s, index %d does not exist",name,i);
426 }
427 }
428 W_UnlockLumpNum(names_lump); // cph - release the lump
429
430 // Load the map texture definitions from textures.lmp.
431 // The data is contained in one or two lumps,
432 // TEXTURE1 for shareware, plus TEXTURE2 for commercial.
433
434 maptex = maptex1 = W_CacheLumpNum(maptex_lump[0] = W_GetNumForName("TEXTURE1"));
435 numtextures1 = LONG(*maptex);
436 maxoff = W_LumpLength(maptex_lump[0]);
437 directory = maptex+1;
438
439 if (W_CheckNumForName("TEXTURE2") != -1)
440 {
441 maptex2 = W_CacheLumpNum(maptex_lump[1] = W_GetNumForName("TEXTURE2"));
442 numtextures2 = LONG(*maptex2);
443 maxoff2 = W_LumpLength(maptex_lump[1]);
444 }
445 else
446 {
447 maptex2 = NULL;
448 numtextures2 = 0;
449 maxoff2 = 0;
450 }
451 numtextures = numtextures1 + numtextures2;
452
453 // killough 4/9/98: make column offsets 32-bit;
454 // clean up malloc-ing to use sizeof
455
456 textures = Z_Malloc(numtextures*sizeof*textures, PU_STATIC, 0);
457 textureheight = Z_Malloc(numtextures*sizeof*textureheight, PU_STATIC, 0);
458
459 totalwidth = 0;
460
461 for (i=0 ; i<numtextures ; i++, directory++)
462 {
463 if (i == numtextures1)
464 {
465 // Start looking in second texture file.
466 maptex = maptex2;
467 maxoff = maxoff2;
468 directory = maptex+1;
469 }
470
471 offset = LONG(*directory);
472
473 if (offset > maxoff)
474 I_Error("R_InitTextures: Bad texture directory");
475
476 mtexture = (maptexture_t *) ( (byte *)maptex + offset);
477
478 texture = textures[i] =
479 Z_Malloc(sizeof(texture_t) +
480 sizeof(texpatch_t)*(SHORT(mtexture->patchcount)-1),
481 PU_STATIC, 0);
482
483 texture->width = SHORT(mtexture->width);
484 texture->height = SHORT(mtexture->height);
485 texture->patchcount = SHORT(mtexture->patchcount);
486
487 /* Mattias Engdegård emailed me of the following explenation of
488 * why memcpy doesnt work on some systems:
489 * "I suppose it is the mad unaligned allocation
490 * going on (and which gcc in some way manages to cope with
491 * through the __attribute__ ((packed))), and which it forgets
492 * when optimizing memcpy (to a single word move) since it appears
493 * to be aligned. Technically a gcc bug, but I can't blame it when
494 * it's stressed with that amount of
495 * non-standard nonsense."
496 * So in short the unaligned struct confuses gcc's optimizer so
497 * i took the memcpy out alltogether to avoid future problems-Jess
498 */
499 /* The above was #ifndef SPARC, but i got a mail from
500 * Putera Joseph F NPRI <PuteraJF@Npt.NUWC.Navy.Mil> containing:
501 * I had to use the memcpy function on a sparc machine. The
502 * other one would give me a core dump.
503 * cph - I find it hard to believe that sparc memcpy is broken,
504 * but I don't believe the pointers to memcpy have to be aligned
505 * either. Use fast memcpy on other machines anyway.
506 */
507 /*
508 proff - I took this out, because Oli Kraus (olikraus@yahoo.com) told
509 me the memcpy produced a buserror. Since this function isn't time-
510 critical I'm using the for loop now.
511 */
512 /*
513 #ifndef GCC
514 memcpy(texture->name, mtexture->name, sizeof(texture->name));
515 #else
516 */
517 {
518 unsigned int j;
519 for(j=0;j<sizeof(texture->name);j++)
520 texture->name[j]=mtexture->name[j];
521 }
522 /* #endif */
523
524 mpatch = mtexture->patches;
525 patch = texture->patches;
526
527 for (j=0 ; j<texture->patchcount ; j++, mpatch++, patch++)
528 {
529 patch->originx = SHORT(mpatch->originx);
530 patch->originy = SHORT(mpatch->originy);
531 patch->patch = patchlookup[SHORT(mpatch->patch)];
532 if (patch->patch == -1)
533 {
534 //jff 8/3/98 use logical output routine
535 printf("\nR_InitTextures: Missing patch %d in texture %s",
536 SHORT(mpatch->patch), texture->name); // killough 4/17/98
537 ++errors;
538 }
539 }
540
541 texture->columnofs = NULL; texture->columnlump = NULL;
542
543 for (j=1; j*2 <= texture->width; j<<=1)
544 ;
545 texture->widthmask = j-1;
546 textureheight[i] = texture->height<<FRACBITS;
547
548 totalwidth += texture->width;
549 }
550
551 free(patchlookup); // killough
552
553 for (i=0; i<2; i++) // cph - release the TEXTUREx lumps
554 if (maptex_lump[i] != -1)
555 W_UnlockLumpNum(maptex_lump[i]);
556
557 if (errors)
558 I_Error("R_InitTextures: %d errors", errors);
559
560 // Precalculate whatever possible.
561 if (devparm) // cph - If in development mode, generate now so all errors are found at once
562 for (i=0 ; i<numtextures ; i++)
563 R_GenerateLookup(i, &errors);
564
565 if (errors)
566 I_Error("R_InitTextures: %d errors", errors);
567
568 // Create translation table for global animation.
569 // killough 4/9/98: make column offsets 32-bit;
570 // clean up malloc-ing to use sizeof
571
572 texturetranslation =
573 Z_Malloc((numtextures+1)*sizeof*texturetranslation, PU_STATIC, 0);
574
575 for (i=0 ; i<numtextures ; i++)
576 texturetranslation[i] = i;
577
578 // killough 1/31/98: Initialize texture hash table
579 for (i = 0; i<numtextures; i++)
580 textures[i]->index = -1;
581 while (--i >= 0)
582 {
583 int j = W_LumpNameHash(textures[i]->name) % (unsigned) numtextures;
584 textures[i]->next = textures[j]->index; // Prepend to chain
585 textures[j]->index = i;
586 }
587}
588
589//
590// R_InitFlats
591//
592void R_InitFlats(void)
593{
594 int i;
595
596 firstflat = W_GetNumForName("F_START") + 1;
597 lastflat = W_GetNumForName("F_END") - 1;
598 numflats = lastflat - firstflat + 1;
599
600 // Create translation table for global animation.
601 // killough 4/9/98: make column offsets 32-bit;
602 // clean up malloc-ing to use sizeof
603
604 flattranslation =
605 Z_Malloc((numflats+1)*sizeof(*flattranslation), PU_STATIC, 0);
606
607 for (i=0 ; i<numflats ; i++)
608 flattranslation[i] = i;
609}
610
611//
612// R_InitSpriteLumps
613// Finds the width and hoffset of all sprites in the wad,
614// so the sprite does not need to be cached completely
615// just for having the header info ready during rendering.
616//
617void R_InitSpriteLumps(void)
618{
619 int i;
620 const patch_t *patch;
621
622 firstspritelump = W_GetNumForName("S_START") + 1;
623 lastspritelump = W_GetNumForName("S_END") - 1;
624 numspritelumps = lastspritelump - firstspritelump + 1;
625
626 // killough 4/9/98: make columnd offsets 32-bit;
627 // clean up malloc-ing to use sizeof
628
629 spritewidth = Z_Malloc(numspritelumps*sizeof*spritewidth, PU_STATIC, 0);
630 spriteoffset = Z_Malloc(numspritelumps*sizeof*spriteoffset, PU_STATIC, 0);
631 spritetopoffset =
632 Z_Malloc(numspritelumps*sizeof*spritetopoffset, PU_STATIC, 0);
633
634 for (i=0 ; i< numspritelumps ; i++)
635 {
636 patch = W_CacheLumpNum(firstspritelump+i);
637 spritewidth[i] = SHORT(patch->width)<<FRACBITS;
638 spriteoffset[i] = SHORT(patch->leftoffset)<<FRACBITS;
639 spritetopoffset[i] = SHORT(patch->topoffset)<<FRACBITS;
640 W_UnlockLumpNum(firstspritelump+i);
641 }
642}
643
644//
645// R_InitColormaps
646//
647// killough 3/20/98: rewritten to allow dynamic colormaps
648// and to remove unnecessary 256-byte alignment
649//
650// killough 4/4/98: Add support for C_START/C_END markers
651//
652
653void R_InitColormaps(void)
654{
655 int i;
656 firstcolormaplump = W_GetNumForName("C_START");
657 lastcolormaplump = W_GetNumForName("C_END");
658 numcolormaps = lastcolormaplump - firstcolormaplump;
659 colormaps = Z_Malloc(sizeof(*colormaps) * numcolormaps, PU_STATIC, 0);
660 colormaps[0] = (lighttable_t *)W_CacheLumpName("COLORMAP");
661 for (i=1; i<numcolormaps; i++)
662 colormaps[i] = (lighttable_t *)W_CacheLumpNum(i+firstcolormaplump);
663 // cph - always lock
664}
665
666// killough 4/4/98: get colormap number from name
667// killough 4/11/98: changed to return -1 for illegal names
668// killough 4/17/98: changed to use ns_colormaps tag
669
670int R_ColormapNumForName(const char *name)
671{
672 register int i = 0;
673 if (strncasecmp(name,"COLORMAP",8)) // COLORMAP predefined to return 0
674 if ((i = (W_CheckNumForName)(name, ns_colormaps)) != -1)
675 i -= firstcolormaplump;
676 return i;
677}
678
679//
680// R_InitTranMap
681//
682// Initialize translucency filter map
683//
684// By Lee Killough 2/21/98
685//
686
687struct _cache {
688 unsigned char pct;
689 unsigned char playpal[256];
690} cache;
691
692int tran_filter_pct = 66; // filter percent
693
694#define TSC 12 /* number of fixed point digits in filter percent */
695
696void R_InitTranMap(int progress)
697{
698 int lump = W_CheckNumForName("TRANMAP");
699
700 // If a tranlucency filter map lump is present, use it
701 if (lump != -1) // Set a pointer to the translucency filter maps.
702 main_tranmap = W_CacheLumpNum(lump); // killough 4/11/98
703 else
704 { // Compose a default transparent filter map based on PLAYPAL.
705 const byte *playpal = W_CacheLumpName("PLAYPAL");
706 byte *my_tranmap;
707
708 int cachefd = open(GAMEBASE"tranmap.dat",O_RDONLY);
709
710 main_tranmap = my_tranmap = Z_Malloc(256*256, PU_STATIC, 0); // killough 4/11/98
711
712 // Use cached translucency filter if it's available
713
714 if ((cachefd<0) ? cachefd = open(GAMEBASE"tranmap.dat",O_WRONLY | O_CREAT) , 1 :
715 read(cachefd, &cache, sizeof(cache)) != sizeof(cache) ||
716 cache.pct != tran_filter_pct ||
717 memcmp(cache.playpal, playpal, sizeof cache.playpal) ||
718 read(cachefd, my_tranmap, 256*256) != 256*256 ) // killough 4/11/98
719 {
720
721 long *stackdeath=malloc(256*7*sizeof(long)); // This was a bunch of static varibles, way too big for rockbox
722 long *pal[3], *tot, *pal_w1[3];
723 pal[0]=&stackdeath[0];
724 pal[1]=&stackdeath[256];
725 pal[2]=&stackdeath[256*2];
726 tot=&stackdeath[256*3];
727 pal_w1[0]=&stackdeath[256*4];
728 pal_w1[1]=&stackdeath[256*5];
729 pal_w1[2]=&stackdeath[256*6];
730 long w1 = ((unsigned long) tran_filter_pct<<TSC)/100;
731 long w2 = (1l<<TSC)-w1;
732
733 if (progress)
734 printf("Please wait: Tranmap build");
735 // First, convert playpal into long int type, and transpose array,
736 // for fast inner-loop calculations. Precompute tot array.
737
738 {
739 register int i = 255;
740 register const unsigned char *p = playpal+255*3;
741 do
742 {
743 register long t,d;
744 pal_w1[0][i] = (pal[0][i] = t = p[0]) * w1;
745 d = t*t;
746 pal_w1[1][i] = (pal[1][i] = t = p[1]) * w1;
747 d += t*t;
748 pal_w1[2][i] = (pal[2][i] = t = p[2]) * w1;
749 d += t*t;
750 p -= 3;
751 tot[i] = d << (TSC-1);
752 } while (--i>=0);
753 }
754
755 // Next, compute all entries using minimum arithmetic.
756
757 {
758 int i,j;
759 byte *tp = my_tranmap;
760 for (i=0;i<256;i++)
761 {
762 long r1 = pal[0][i] * w2;
763 long g1 = pal[1][i] * w2;
764 long b1 = pal[2][i] * w2;
765 if (!(i & 31) && progress)
766 //jff 8/3/98 use logical output routine
767 printf(" Computing: %d", 256/32-i/32);
768 for (j=0;j<256;j++,tp++)
769 {
770 register int color = 255;
771 register long err;
772 long r = pal_w1[0][j] + r1;
773 long g = pal_w1[1][j] + g1;
774 long b = pal_w1[2][j] + b1;
775 long best = LONG_MAX;
776 do
777 if ((err = tot[color] - pal[0][color]*r
778 - pal[1][color]*g - pal[2][color]*b) < best)
779 best = err, *tp = color;
780 while (--color >= 0);
781 }
782 }
783 }
784
785 free(stackdeath); // Free this beast
786
787 if (cachefd) // write out the cached translucency map
788 {
789 cache.pct = tran_filter_pct;
790 memcpy(cache.playpal, playpal, 256);
791 lseek(cachefd, 0, SEEK_SET);
792 write(cachefd, &cache, sizeof cache);
793 write(cachefd,main_tranmap, 256*256);
794 // CPhipps - leave close for a few lines...
795 }
796
797 }
798
799 if (cachefd) // killough 11/98: fix filehandle leak
800 close(cachefd);
801
802 W_UnlockLumpName("PLAYPAL");
803 }
804}
805
806//
807// R_InitData
808// Locates all the lumps
809// that will be used by all views
810// Must be called after W_Init.
811//
812void R_InitData (void)
813{
814 R_InitTextures ();
815 printf ("\nInitTextures");
816 R_InitFlats ();
817 printf ("\nInitFlats");
818 R_InitSpriteLumps ();
819 printf ("\nInitSprites");
820 if (general_translucency) // killough 3/1/98
821 R_InitTranMap(1);
822 R_InitColormaps ();
823 printf ("\nInitColormaps");
824}
825
826//
827// R_FlatNumForName
828// Retrieval, get a flat number for a flat name.
829//
830// killough 4/17/98: changed to use ns_flats namespace
831//
832
833int R_FlatNumForName(const char *name) // killough -- const added
834{
835 int i = (W_CheckNumForName)(name, ns_flats);
836 if (i == -1)
837 I_Error("R_FlatNumForName: %s not found", name);
838 return i - firstflat;
839}
840
841//
842// R_CheckTextureNumForName
843// Check whether texture is available.
844// Filter out NoTexture indicator.
845//
846// Rewritten by Lee Killough to use hash table for fast lookup. Considerably
847// reduces the time needed to start new levels. See w_wad.c for comments on
848// the hashing algorithm, which is also used for lump searches.
849//
850// killough 1/21/98, 1/31/98
851//
852
853int R_CheckTextureNumForName(const char *name)
854{
855 int i = 0;
856 if (*name != '-') // "NoTexture" marker.
857 {
858 i = textures[W_LumpNameHash(name) % (unsigned) numtextures]->index;
859 while (i >= 0 && strncasecmp(textures[i]->name,name,8))
860 i = textures[i]->next;
861 }
862 return i;
863}
864
865//
866// R_TextureNumForName
867// Calls R_CheckTextureNumForName,
868// aborts with error message.
869//
870
871int R_TextureNumForName(const char *name) // const added -- killough
872{
873 int i = R_CheckTextureNumForName(name);
874 if (i == -1)
875 I_Error("R_TextureNumForName: %s not found", name);
876 return i;
877}
878
879//
880// R_PrecacheLevel
881// Preloads all relevant graphics for the level.
882//
883// Totally rewritten by Lee Killough to use less memory,
884// to avoid using alloca(), and to improve performance.
885// cph - new wad lump handling, calls cache functions but acquires no locks
886
887void R_PrecacheLevel(void)
888{
889 register int i;
890 register byte *hitlist;
891
892 if (demoplayback)
893 return;
894
895 {
896 size_t size = numflats > numsprites ? numflats : numsprites;
897 hitlist = malloc((size_t)numtextures > size ? (unsigned)numtextures : size);
898 }
899 // Precache flats.
900
901 memset(hitlist, 0, numflats);
902
903 for (i = numsectors; --i >= 0; )
904 hitlist[sectors[i].floorpic] = hitlist[sectors[i].ceilingpic] = 1;
905
906 for (i = numflats; --i >= 0; )
907 if (hitlist[i])
908 (W_CacheLumpNum)(firstflat + i, 0);
909
910 // Precache textures.
911
912 memset(hitlist, 0, numtextures);
913
914 for (i = numsides; --i >= 0;)
915 hitlist[sides[i].bottomtexture] =
916 hitlist[sides[i].toptexture] =
917 hitlist[sides[i].midtexture] = 1;
918
919 // Sky texture is always present.
920 // Note that F_SKY1 is the name used to
921 // indicate a sky floor/ceiling as a flat,
922 // while the sky texture is stored like
923 // a wall texture, with an episode dependend
924 // name.
925
926 hitlist[skytexture] = 1;
927
928 for (i = numtextures; --i >= 0; )
929 if (hitlist[i])
930 {
931 texture_t *texture = textures[i];
932 int j = texture->patchcount;
933 while (--j >= 0)
934 (W_CacheLumpNum)(texture->patches[j].patch, 0);
935 }
936
937 // Precache sprites.
938 memset(hitlist, 0, numsprites);
939
940 {
941 thinker_t *th;
942 for (th = thinkercap.next ; th != &thinkercap ; th=th->next)
943 if (th->function == P_MobjThinker)
944 hitlist[((mobj_t *)th)->sprite] = 1;
945 }
946
947 for (i=numsprites; --i >= 0;)
948 if (hitlist[i])
949 {
950 int j = sprites[i].numframes;
951 while (--j >= 0)
952 {
953 short *sflump = sprites[i].spriteframes[j].lump;
954 int k = 7;
955 do
956 (W_CacheLumpNum)(firstspritelump + sflump[k], 0);
957 while (--k >= 0);
958 }
959 }
960 free(hitlist);
961}
962
963// Proff - Added for OpenGL
964void R_SetPatchNum(patchnum_t *patchnum, const char *name)
965{
966 patch_t *patch;
967
968 patch = (patch_t *) W_CacheLumpName(name);
969 patchnum->width = patch->width;
970 patchnum->height = patch->height;
971 patchnum->leftoffset = patch->leftoffset;
972 patchnum->topoffset = patch->topoffset;
973 patchnum->lumpnum = W_GetNumForName(name);
974 W_UnlockLumpName(name);
975}
diff --git a/apps/plugins/doom/r_data.h b/apps/plugins/doom/r_data.h
new file mode 100644
index 0000000000..12c9eb74af
--- /dev/null
+++ b/apps/plugins/doom/r_data.h
@@ -0,0 +1,105 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION:
28 * Refresh module, data I/O, caching, retrieval of graphics
29 * by name.
30 *
31 *-----------------------------------------------------------------------------*/
32
33
34#ifndef __R_DATA__
35#define __R_DATA__
36
37#include "r_defs.h"
38#include "r_state.h"
39
40#ifdef __GNUG__
41#pragma interface
42#endif
43
44// A single patch from a texture definition, basically
45// a rectangular area within the texture rectangle.
46typedef struct
47{
48 int originx, originy; // Block origin, which has already accounted
49 int patch; // for the internal origin of the patch.
50} texpatch_t;
51
52//
53// Texture definition.
54// A DOOM wall texture is a list of patches
55// which are to be combined in a predefined order.
56//
57
58typedef struct
59{
60 char name[8]; // Keep name for switch changing, etc.
61 int next, index; // killough 1/31/98: used in hashing algorithm
62 // CPhipps - moved arrays with per-texture entries to elements here
63 unsigned widthmask;
64 size_t compositesize;
65 byte *composite;
66 short *columnlump;
67 unsigned *columnofs;
68 // CPhipps - end of additions
69 short width, height;
70 short patchcount; // All the patches[patchcount] are drawn
71 texpatch_t patches[1]; // back-to-front into the cached texture.
72} texture_t;
73
74// Retrieve column data for span blitting.
75const byte*
76R_GetColumn
77( int tex,
78 int col );
79
80
81// I/O, setting up the stuff.
82void R_InitData (void);
83void R_PrecacheLevel (void);
84
85
86// Retrieval.
87// Floor/ceiling opaque texture tiles,
88// lookup by name. For animation?
89int R_FlatNumForName (const char* name); // killough -- const added
90
91
92// Called by P_Ticker for switches and animations,
93// returns the texture number for the texture name.
94int R_TextureNumForName (const char *name); // killough -- const added
95int R_CheckTextureNumForName (const char *name);
96
97void R_InitTranMap(int); // killough 3/6/98: translucency initialization
98int R_ColormapNumForName(const char *name); // killough 4/4/98
99
100extern const byte *main_tranmap, *tranmap;
101
102/* Proff - Added for OpenGL - cph - const char* param */
103void R_SetPatchNum(patchnum_t *patchnum, const char *name);
104
105#endif
diff --git a/apps/plugins/doom/r_defs.h b/apps/plugins/doom/r_defs.h
new file mode 100644
index 0000000000..a3bd5cdf33
--- /dev/null
+++ b/apps/plugins/doom/r_defs.h
@@ -0,0 +1,422 @@
1// Emacs style mode select -*- C++ -*-
2//-----------------------------------------------------------------------------
3//
4// $Id$
5//
6// Copyright (C) 1993-1996 by id Software, Inc.
7//
8// This program is free software; you can redistribute it and/or
9// modify it under the terms of the GNU General Public License
10// as published by the Free Software Foundation; either version 2
11// of the License, or (at your option) any later version.
12//
13// This program is distributed in the hope that it will be useful,
14// but WITHOUT ANY WARRANTY; without even the implied warranty of
15// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16// GNU General Public License for more details.
17//
18// DESCRIPTION:
19// Refresh/rendering module, shared data struct definitions.
20//
21//-----------------------------------------------------------------------------
22
23#ifndef __R_DEFS__
24#define __R_DEFS__
25
26// Screenwidth.
27#include "doomdef.h"
28
29// Some more or less basic data types
30// we depend on.
31#include "m_fixed.h"
32
33// We rely on the thinker data struct
34// to handle sound origins in sectors.
35#include "d_think.h"
36// SECTORS do store MObjs anyway.
37#include "p_mobj.h"
38
39#ifdef __GNUG__
40#pragma interface
41#endif
42
43// Silhouette, needed for clipping Segs (mainly)
44// and sprites representing things.
45#define SIL_NONE 0
46#define SIL_BOTTOM 1
47#define SIL_TOP 2
48#define SIL_BOTH 3
49
50#define MAXDRAWSEGS 256
51
52//
53// INTERNAL MAP TYPES
54// used by play and refresh
55//
56
57//
58// Your plain vanilla vertex.
59// Note: transformed values not buffered locally,
60// like some DOOM-alikes ("wt", "WebView") do.
61//
62typedef struct
63{
64 fixed_t x, y;
65} vertex_t;
66
67
68// Forward of LineDefs, for Sectors.
69struct line_s;
70
71// Each sector has a degenmobj_t in its center for sound origin purposes.
72typedef struct
73{
74 thinker_t thinker; // not used for anything
75 fixed_t x, y, z;
76} degenmobj_t;
77
78//
79// The SECTORS record, at runtime.
80// Stores things/mobjs.
81//
82
83typedef struct
84{
85 fixed_t floorheight;
86 fixed_t ceilingheight;
87 int nexttag,firsttag; // killough 1/30/98: improves searches for tags.
88 int soundtraversed; // 0 = untraversed, 1,2 = sndlines-1
89 mobj_t *soundtarget; // thing that made a sound (or null)
90 int blockbox[4]; // mapblock bounding box for height changes
91 degenmobj_t soundorg; // origin for any sounds played by the sector
92 int validcount; // if == validcount, already checked
93 mobj_t *thinglist; // list of mobjs in sector
94
95 /* killough 8/28/98: friction is a sector property, not an mobj property.
96 * these fields used to be in mobj_t, but presented performance problems
97 * when processed as mobj properties. Fix is to make them sector properties.
98 */
99 int friction,movefactor;
100
101 // thinker_t for reversable actions
102 void *floordata; // jff 2/22/98 make thinkers on
103 void *ceilingdata; // floors, ceilings, lighting,
104 void *lightingdata; // independent of one another
105
106 // jff 2/26/98 lockout machinery for stairbuilding
107 int stairlock; // -2 on first locked -1 after thinker done 0 normally
108 int prevsec; // -1 or number of sector for previous step
109 int nextsec; // -1 or number of next step sector
110
111 // killough 3/7/98: support flat heights drawn at another sector's heights
112 int heightsec; // other sector, or -1 if no other sector
113
114 int bottommap, midmap, topmap; // killough 4/4/98: dynamic colormaps
115
116 // list of mobjs that are at least partially in the sector
117 // thinglist is a subset of touching_thinglist
118 struct msecnode_s *touching_thinglist; // phares 3/14/98
119
120 int linecount;
121 struct line_s **lines;
122
123 // killough 10/98: support skies coming from sidedefs. Allows scrolling
124 // skies and other effects. No "level info" kind of lump is needed,
125 // because you can use an arbitrary number of skies per level with this
126 // method. This field only applies when skyflatnum is used for floorpic
127 // or ceilingpic, because the rest of Doom needs to know which is sky
128 // and which isn't, etc.
129
130 int sky;
131
132 // killough 3/7/98: floor and ceiling texture offsets
133 fixed_t floor_xoffs, floor_yoffs;
134 fixed_t ceiling_xoffs, ceiling_yoffs;
135
136 // killough 4/11/98: support for lightlevels coming from another sector
137 int floorlightsec, ceilinglightsec;
138
139 short floorpic;
140 short ceilingpic;
141 short lightlevel;
142 short special;
143 short oldspecial; //jff 2/16/98 remembers if sector WAS secret (automap)
144 short tag;
145 void* specialdata; // ROCKDOOM obsolete
146} sector_t;
147
148//
149// The SideDef.
150//
151
152typedef struct
153{
154 fixed_t textureoffset; // add this to the calculated texture column
155 fixed_t rowoffset; // add this to the calculated texture top
156 short toptexture; // Texture indices. We do not maintain names here.
157 short bottomtexture;
158 short midtexture;
159 sector_t* sector; // Sector the SideDef is facing.
160
161 // killough 4/4/98, 4/11/98: highest referencing special linedef's type,
162 // or lump number of special effect. Allows texture names to be overloaded
163 // for other functions.
164
165 int special;
166
167} side_t;
168
169//
170// Move clipping aid for LineDefs.
171//
172typedef enum
173{
174 ST_HORIZONTAL,
175 ST_VERTICAL,
176 ST_POSITIVE,
177 ST_NEGATIVE
178} slopetype_t;
179
180typedef struct line_s
181{
182 vertex_t *v1, *v2; // Vertices, from v1 to v2.
183 fixed_t dx, dy; // Precalculated v2 - v1 for side checking.
184 short flags; // Animation related.
185 short special;
186 short tag;
187 short sidenum[2]; // Visual appearance: SideDefs.
188 fixed_t bbox[4]; // A bounding box, for the linedef's extent
189 slopetype_t slopetype; // To aid move clipping.
190 sector_t *frontsector; // Front and back sector.
191 sector_t *backsector;
192 int validcount; // if == validcount, already checked
193 void *specialdata; // thinker_t for reversable actions
194 int tranlump; // killough 4/11/98: translucency filter, -1 == none
195 int firsttag,nexttag; // killough 4/17/98: improves searches for tags.
196 int r_validcount; // cph: if == gametic, r_flags already done
197 enum { // cph:
198 RF_TOP_TILE = 1, // Upper texture needs tiling
199 RF_MID_TILE = 2, // Mid texture needs tiling
200 RF_BOT_TILE = 4, // Lower texture needs tiling
201 RF_IGNORE = 8, // Renderer can skip this line
202 RF_CLOSED =16, // Line blocks view
203 } r_flags;
204} line_t;
205
206// phares 3/14/98
207//
208// Sector list node showing all sectors an object appears in.
209//
210// There are two threads that flow through these nodes. The first thread
211// starts at touching_thinglist in a sector_t and flows through the m_snext
212// links to find all mobjs that are entirely or partially in the sector.
213// The second thread starts at touching_sectorlist in an mobj_t and flows
214// through the m_tnext links to find all sectors a thing touches. This is
215// useful when applying friction or push effects to sectors. These effects
216// can be done as thinkers that act upon all objects touching their sectors.
217// As an mobj moves through the world, these nodes are created and
218// destroyed, with the links changed appropriately.
219//
220// For the links, NULL means top or end of list.
221
222typedef struct msecnode_s
223{
224 sector_t *m_sector; // a sector containing this object
225 struct mobj_s *m_thing; // this object
226 struct msecnode_s *m_tprev; // prev msecnode_t for this thing
227 struct msecnode_s *m_tnext; // next msecnode_t for this thing
228 struct msecnode_s *m_sprev; // prev msecnode_t for this sector
229 struct msecnode_s *m_snext; // next msecnode_t for this sector
230 boolean visited; // killough 4/4/98, 4/7/98: used in search algorithms
231} msecnode_t;
232
233//
234// The LineSeg.
235//
236typedef struct
237{
238 vertex_t *v1, *v2;
239 fixed_t offset;
240 angle_t angle;
241 side_t* sidedef;
242 line_t* linedef;
243
244 boolean miniseg;
245
246 // Sector references.
247 // Could be retrieved from linedef, too
248 // (but that would be slower -- killough)
249 // backsector is NULL for one sided lines
250
251 sector_t *frontsector, *backsector;
252} seg_t;
253
254//
255// A SubSector.
256// References a Sector.
257// Basically, this is a list of LineSegs,
258// indicating the visible walls that define
259// (all or some) sides of a convex BSP leaf.
260//
261
262typedef struct subsector_s
263{
264 sector_t *sector;
265 unsigned short numlines, firstline;
266} subsector_t;
267
268//
269// BSP node.
270//
271typedef struct
272{
273 fixed_t x, y, dx, dy; // Partition line.
274 fixed_t bbox[2][4]; // Bounding box for each child.
275 unsigned short children[2]; // If NF_SUBSECTOR its a subsector.
276} node_t;
277
278// posts are runs of non masked source pixels
279typedef struct
280{
281 byte topdelta; // -1 is the last post in a column
282 byte length; // length data bytes follows
283} post_t;
284
285// column_t is a list of 0 or more post_t, (byte)-1 terminated
286typedef post_t column_t;
287
288//
289// OTHER TYPES
290//
291
292// This could be wider for >8 bit display.
293// Indeed, true color support is posibble
294// precalculating 24bpp lightmap/colormap LUT.
295// from darkening PLAYPAL to all black.
296// Could even us emore than 32 levels.
297typedef byte lighttable_t;
298
299//
300// Masked 2s linedefs
301//
302typedef struct drawseg_s
303{
304 seg_t* curline;
305 int x1, x2;
306 fixed_t scale1, scale2, scalestep;
307 int silhouette; // 0=none, 1=bottom, 2=top, 3=both
308 fixed_t bsilheight; // do not clip sprites above this
309 fixed_t tsilheight; // do not clip sprites below this
310
311 // Pointers to lists for sprite clipping,
312 // all three adjusted so [x1] is first value.
313 short *sprtopclip, *sprbottomclip, *maskedtexturecol;
314
315} drawseg_t;
316
317//
318// Patches.
319// A patch holds one or more columns.
320// Patches are used for sprites and all masked pictures,
321// and we compose textures from the TEXTURE1/2 lists
322// of patches.
323//
324
325typedef struct
326{
327 short width, height; // bounding box size
328 short leftoffset; // pixels to the left of origin
329 short topoffset; // pixels below the origin
330 int columnofs[8]; // only [width] used
331} patch_t;
332
333// proff: Added for OpenGL
334typedef struct
335{
336 int width,height;
337 int leftoffset,topoffset;
338 int lumpnum;
339} patchnum_t;
340
341//
342// A vissprite_t is a thing that will be drawn during a refresh.
343// i.e. a sprite object that is partly visible.
344//
345
346typedef struct vissprite_s
347{
348 int x1, x2;
349 fixed_t gx, gy; // for line side calculation
350 fixed_t gz, gzt; // global bottom / top for silhouette clipping
351 fixed_t startfrac; // horizontal position of x1
352 fixed_t scale;
353 fixed_t xiscale; // negative if flipped
354 fixed_t texturemid;
355 int patch;
356 uint_64_t mobjflags;
357
358 // for color translation and shadow draw, maxbright frames as well
359 lighttable_t *colormap;
360
361 // killough 3/27/98: height sector for underwater/fake ceiling support
362 int heightsec;
363} vissprite_t;
364
365//
366// Sprites are patches with a special naming convention
367// so they can be recognized by R_InitSprites.
368// The base name is NNNNFx or NNNNFxFx, with
369// x indicating the rotation, x = 0, 1-7.
370// The sprite and frame specified by a thing_t
371// is range checked at run time.
372// A sprite is a patch_t that is assumed to represent
373// a three dimensional object and may have multiple
374// rotations pre drawn.
375// Horizontal flipping is used to save space,
376// thus NNNNF2F5 defines a mirrored patch.
377// Some sprites will only have one picture used
378// for all views: NNNNF0
379//
380typedef struct
381{
382 // If false use 0 for any position.
383 // Note: as eight entries are available,
384 // we might as well insert the same name eight times.
385 boolean rotate;
386
387 // Lump to use for view angles 0-7.
388 short lump[8];
389
390 // Flip bit (1 = flip) to use for view angles 0-7.
391 byte flip[8];
392
393} spriteframe_t;
394
395//
396// A sprite definition:
397// a number of animation frames.
398//
399
400typedef struct
401{
402 int numframes;
403 spriteframe_t *spriteframes;
404} spritedef_t;
405
406//
407// Now what is a visplane, anyway?
408//
409typedef struct visplane
410{
411 struct visplane *next; // Next visplane in hash chain -- killough
412 int picnum, lightlevel, minx, maxx;
413 fixed_t height;
414 fixed_t xoffs, yoffs; // killough 2/28/98: Support scrolling flats
415 unsigned short pad1; // leave pads for [minx-1]/[maxx+1]
416 unsigned short top[SCREENWIDTH];
417 unsigned short pad2, pad3; // killough 2/8/98, 4/25/98
418 unsigned short bottom[SCREENWIDTH];
419 unsigned short pad4;
420} visplane_t;
421
422#endif
diff --git a/apps/plugins/doom/r_draw.c b/apps/plugins/doom/r_draw.c
new file mode 100644
index 0000000000..df682776cd
--- /dev/null
+++ b/apps/plugins/doom/r_draw.c
@@ -0,0 +1,677 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION:
28 * The actual span/column drawing functions.
29 * Here find the main potential for optimization,
30 * e.g. inline assembly, different algorithms.
31 *
32 *-----------------------------------------------------------------------------*/
33
34#include "doomstat.h"
35#include "w_wad.h"
36#include "r_main.h"
37#include "v_video.h"
38#include "st_stuff.h"
39#include "g_game.h"
40#include "am_map.h"
41//#include "lprintf.h"
42#include "rockmacros.h"
43
44#define MAXWIDTH 1120
45#define MAXHEIGHT 832
46
47// status bar height at bottom of screen
48#define SBARHEIGHT 32
49
50//
51// All drawing to the view buffer is accomplished in this file.
52// The other refresh files only know about ccordinates,
53// not the architecture of the frame buffer.
54// Conveniently, the frame buffer is a linear one,
55// and we need only the base address,
56// and the total size == width*height*depth/8.,
57//
58
59//byte* viewimage;
60int viewwidth;
61int scaledviewwidth;
62int viewheight;
63int viewwindowx;
64int viewwindowy;
65
66byte *topleft IBSS_ATTR;
67
68// Color tables for different players,
69// translate a limited part to another
70// (color ramps used for suit colors).
71//
72
73// CPhipps - made const*'s
74const byte *tranmap IBSS_ATTR; // translucency filter maps 256x256 // phares
75const byte *main_tranmap IBSS_ATTR; // killough 4/11/98
76
77//
78// R_DrawColumn
79// Source is the top of the column to scale.
80//
81
82lighttable_t *dc_colormap IBSS_ATTR;
83int dc_x IBSS_ATTR;
84int dc_yl IBSS_ATTR;
85int dc_yh IBSS_ATTR;
86fixed_t dc_iscale IBSS_ATTR;
87fixed_t dc_texturemid IBSS_ATTR;
88int dc_texheight IBSS_ATTR; // killough
89const byte *dc_source IBSS_ATTR; // first pixel in a column (possibly virtual)
90
91
92//
93// A column is a vertical slice/span from a wall texture that,
94// given the DOOM style restrictions on the view orientation,
95// will always have constant z depth.
96// Thus a special case loop for very fast rendering can
97// be used. It has also been used with Wolfenstein 3D.
98//
99void R_DrawColumn (void)
100{
101 int count;
102 register byte *dest; // killough
103 register fixed_t frac; // killough
104
105 // leban 1/17/99:
106 // removed the + 1 here, adjusted the if test, and added an increment
107 // later. this helps a compiler pipeline a bit better. the x86
108 // assembler also does this.
109 count = dc_yh - dc_yl;
110
111 // Zero length, column does not exceed a pixel.
112 if (count < 0)
113 return;
114
115#ifdef RANGECHECK
116 if ((unsigned)dc_x >= SCREENWIDTH
117 || dc_yl < 0
118 || dc_yh >= SCREENHEIGHT)
119 I_Error ("R_DrawColumn: %d to %d at %d", dc_yl, dc_yh, dc_x);
120#endif
121
122 count++;
123
124 // Framebuffer destination address.
125 dest = topleft + dc_yl*SCREENWIDTH + dc_x;
126
127 // Determine scaling,
128 // which is the only mapping to be done.
129#define fracstep dc_iscale
130 frac = dc_texturemid + (dc_yl-centery)*fracstep;
131
132 // Inner loop that does the actual texture mapping,
133 // e.g. a DDA-lile scaling.
134 // This is as fast as it gets. (Yeah, right!!! -- killough)
135 //
136 // killough 2/1/98: more performance tuning
137
138 if (dc_texheight == 128) {
139 while(count--)
140 {
141 *dest = dc_colormap[dc_source[(frac>>FRACBITS)&127]];
142 frac += fracstep;
143 dest += SCREENWIDTH;
144 }
145 } else if (dc_texheight == 0) {
146 /* cph - another special case */
147 while (count--) {
148 *dest = dc_colormap[dc_source[frac>>FRACBITS]];
149 frac += fracstep;
150 dest += SCREENWIDTH;
151 }
152 } else {
153 register unsigned heightmask = dc_texheight-1; // CPhipps - specify type
154 if (! (dc_texheight & heightmask) ) // power of 2 -- killough
155 {
156 while (count>0) // texture height is a power of 2 -- killough
157 {
158 *dest = dc_colormap[dc_source[(frac>>FRACBITS) & heightmask]];
159 dest += SCREENWIDTH;
160 frac += fracstep;
161 count--;
162 }
163 }
164 else
165 {
166 heightmask++;
167 heightmask <<= FRACBITS;
168
169 if (frac < 0)
170 while ((frac += heightmask) < 0);
171 else
172 while (frac >= (int)heightmask)
173 frac -= heightmask;
174
175 while(count>0)
176 {
177 // Re-map color indices from wall texture column
178 // using a lighting/special effects LUT.
179
180 // heightmask is the Tutti-Frutti fix -- killough
181
182 *dest = dc_colormap[dc_source[frac>>FRACBITS]];
183 dest += SCREENWIDTH;
184 if ((frac += fracstep) >= (int)heightmask)
185 frac -= heightmask;
186 count--;
187 }
188 }
189 }
190}
191#undef fracstep
192
193// Here is the version of R_DrawColumn that deals with translucent // phares
194// textures and sprites. It's identical to R_DrawColumn except // |
195// for the spot where the color index is stuffed into *dest. At // V
196// that point, the existing color index and the new color index
197// are mapped through the TRANMAP lump filters to get a new color
198// index whose RGB values are the average of the existing and new
199// colors.
200//
201// Since we're concerned about performance, the 'translucent or
202// opaque' decision is made outside this routine, not down where the
203// actual code differences are.
204
205void R_DrawTLColumn (void)
206{
207 int count;
208 register byte *dest; // killough
209 register fixed_t frac; // killough
210
211 count = dc_yh - dc_yl + 1;
212
213 // Zero length, column does not exceed a pixel.
214 if (count <= 0)
215 return;
216
217#ifdef RANGECHECK
218 if ((unsigned)dc_x >= (unsigned)SCREENWIDTH
219 || dc_yl < 0
220 || dc_yh >= SCREENHEIGHT)
221 I_Error("R_DrawTLColumn: %i to %i at %i", dc_yl, dc_yh, dc_x);
222#endif
223
224 // Framebuffer destination address.
225 dest = topleft + dc_yl*SCREENWIDTH + dc_x;
226
227 // Determine scaling,
228 // which is the only mapping to be done.
229#define fracstep dc_iscale
230 frac = dc_texturemid + (dc_yl-centery)*fracstep;
231
232 // Inner loop that does the actual texture mapping,
233 // e.g. a DDA-lile scaling.
234 // This is as fast as it gets. (Yeah, right!!! -- killough)
235 //
236 // killough 2/1/98, 2/21/98: more performance tuning
237
238 {
239 register const byte *source = dc_source;
240 register const lighttable_t *colormap = dc_colormap;
241 register unsigned heightmask = dc_texheight-1; // CPhipps - specify type
242 if (dc_texheight & heightmask) // not a power of 2 -- killough
243 {
244 heightmask++;
245 heightmask <<= FRACBITS;
246
247 if (frac < 0)
248 while ((frac += heightmask) < 0);
249 else
250 while (frac >= (int)heightmask)
251 frac -= heightmask;
252
253 do
254 {
255 // Re-map color indices from wall texture column
256 // using a lighting/special effects LUT.
257
258 // heightmask is the Tutti-Frutti fix -- killough
259
260 *dest = tranmap[(*dest<<8)+colormap[source[frac>>FRACBITS]]]; // phares
261 dest += SCREENWIDTH;
262 if ((frac += fracstep) >= (int)heightmask)
263 frac -= heightmask;
264 }
265 while (--count);
266 }
267 else
268 {
269 while ((count-=2)>=0) // texture height is a power of 2 -- killough
270 {
271 *dest = tranmap[(*dest<<8)+colormap[source[(frac>>FRACBITS) & heightmask]]]; // phares
272 dest += SCREENWIDTH;
273 frac += fracstep;
274 *dest = tranmap[(*dest<<8)+colormap[source[(frac>>FRACBITS) & heightmask]]]; // phares
275 dest += SCREENWIDTH;
276 frac += fracstep;
277 }
278 if (count & 1)
279 *dest = tranmap[(*dest<<8)+colormap[source[(frac>>FRACBITS) & heightmask]]]; // phares
280 }
281 }
282}
283#undef fracstep
284
285//
286// Spectre/Invisibility.
287//
288
289#define FUZZTABLE 50
290// proff 08/17/98: Changed for high-res
291//#define FUZZOFF (SCREENWIDTH)
292#define FUZZOFF 1
293
294static const int fuzzoffset_org[FUZZTABLE] ICONST_ATTR = {
295 FUZZOFF,-FUZZOFF,FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,
296 FUZZOFF,FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,
297 FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,-FUZZOFF,-FUZZOFF,-FUZZOFF,
298 FUZZOFF,-FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,
299 FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,-FUZZOFF,FUZZOFF,
300 FUZZOFF,-FUZZOFF,-FUZZOFF,-FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,
301 FUZZOFF,FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,FUZZOFF
302 } ;
303
304static int fuzzoffset[FUZZTABLE] IBSS_ATTR;
305
306static int fuzzpos IBSS_ATTR = 0;
307
308//
309// Framebuffer postprocessing.
310// Creates a fuzzy image by copying pixels
311// from adjacent ones to left and right.
312// Used with an all black colormap, this
313// could create the SHADOW effect,
314// i.e. spectres and invisible players.
315//
316
317void R_DrawFuzzColumn(void)
318{
319 int count;
320 byte *dest;
321 fixed_t frac;
322 fixed_t fracstep;
323
324 // Adjust borders. Low...
325 if (!dc_yl)
326 dc_yl = 1;
327
328 // .. and high.
329 if (dc_yh == viewheight-1)
330 dc_yh = viewheight - 2;
331
332 count = dc_yh - dc_yl;
333
334 // Zero length.
335 if (count < 0)
336 return;
337
338#ifdef RANGECHECK
339 if ((unsigned) dc_x >= (unsigned)SCREENWIDTH
340 || dc_yl < 0
341 || (unsigned)dc_yh >= (unsigned)SCREENHEIGHT)
342 I_Error("R_DrawFuzzColumn: %i to %i at %i", dc_yl, dc_yh, dc_x);
343#endif
344
345 // Keep till detailshift bug in blocky mode fixed,
346 // or blocky mode removed.
347
348 // Does not work with blocky mode.
349 dest = topleft + dc_yl*SCREENWIDTH + dc_x;
350
351 // Looks familiar.
352 fracstep = dc_iscale;
353 frac = dc_texturemid + (dc_yl-centery)*fracstep;
354
355 // Looks like an attempt at dithering,
356 // using the colormap #6 (of 0-31, a bit brighter than average).
357
358 do
359 {
360 // Lookup framebuffer, and retrieve
361 // a pixel that is either one column
362 // left or right of the current one.
363 // Add index from colormap to index.
364 // killough 3/20/98: use fullcolormap instead of colormaps
365
366 *dest = fullcolormap[6*256+dest[fuzzoffset[fuzzpos]]];
367
368 // Some varying invisibility effects can be gotten by playing // phares
369 // with this logic. For example, try // phares
370 // // phares
371 // *dest = fullcolormap[0*256+dest[FUZZOFF]]; // phares
372
373 // Clamp table lookup index.
374 if (++fuzzpos == FUZZTABLE)
375 fuzzpos = 0;
376
377 dest += SCREENWIDTH;
378
379 frac += fracstep;
380 } while (count--);
381}
382
383//
384// R_DrawTranslatedColumn
385// Used to draw player sprites
386// with the green colorramp mapped to others.
387// Could be used with different translation
388// tables, e.g. the lighter colored version
389// of the BaronOfHell, the HellKnight, uses
390// identical sprites, kinda brightened up.
391//
392
393byte *dc_translation, *translationtables;
394
395void R_DrawTranslatedColumn (void)
396{
397 int count;
398 byte *dest;
399 fixed_t frac;
400 fixed_t fracstep;
401
402 count = dc_yh - dc_yl;
403 if (count < 0)
404 return;
405
406#ifdef RANGECHECK
407 if ((unsigned)dc_x >= (unsigned)SCREENWIDTH
408 || dc_yl < 0
409 || (unsigned)dc_yh >= (unsigned)SCREENHEIGHT)
410 I_Error("R_DrawColumn: %i to %i at %i", dc_yl, dc_yh, dc_x);
411#endif
412
413 // FIXME. As above.
414 dest = topleft + dc_yl*SCREENWIDTH + dc_x;
415
416 // Looks familiar.
417 fracstep = dc_iscale;
418 frac = dc_texturemid + (dc_yl-centery)*fracstep;
419
420 // Here we do an additional index re-mapping.
421 do
422 {
423 // Translation tables are used
424 // to map certain colorramps to other ones,
425 // used with PLAY sprites.
426 // Thus the "green" ramp of the player 0 sprite
427 // is mapped to gray, red, black/indigo.
428
429 *dest = dc_colormap[dc_translation[dc_source[frac>>FRACBITS]]];
430 dest += SCREENWIDTH;
431
432 frac += fracstep;
433 }
434 while (count--);
435}
436
437//
438// R_InitTranslationTables
439// Creates the translation tables to map
440// the green color ramp to gray, brown, red.
441// Assumes a given structure of the PLAYPAL.
442// Could be read from a lump instead.
443//
444
445byte playernumtotrans[MAXPLAYERS];
446extern lighttable_t *(*c_zlight)[LIGHTLEVELS][MAXLIGHTZ];
447
448void R_InitTranslationTables (void)
449{
450 int i, j;
451#define MAXTRANS 3
452 byte transtocolour[MAXTRANS];
453
454 // killough 5/2/98:
455 // Remove dependency of colormaps aligned on 256-byte boundary
456
457 if (translationtables == NULL) // CPhipps - allow multiple calls
458 translationtables = Z_Malloc(256*MAXTRANS, PU_STATIC, 0);
459
460 for (i=0; i<MAXTRANS; i++) transtocolour[i] = 255;
461
462 for (i=0; i<MAXPLAYERS; i++) {
463 byte wantcolour = mapcolor_plyr[i];
464 playernumtotrans[i] = 0;
465 if (wantcolour != 0x70) // Not green, would like translation
466 for (j=0; j<MAXTRANS; j++)
467 if (transtocolour[j] == 255) {
468 transtocolour[j] = wantcolour; playernumtotrans[i] = j+1; break;
469 }
470 }
471
472 // translate just the 16 green colors
473 for (i=0; i<256; i++)
474 if (i >= 0x70 && i<= 0x7f)
475 {
476 // CPhipps - configurable player colours
477 translationtables[i] = colormaps[0][((i&0xf)<<9) + transtocolour[0]];
478 translationtables[i+256] = colormaps[0][((i&0xf)<<9) + transtocolour[1]];
479 translationtables[i+512] = colormaps[0][((i&0xf)<<9) + transtocolour[2]];
480 }
481 else // Keep all other colors as is.
482 translationtables[i]=translationtables[i+256]=translationtables[i+512]=i;
483}
484
485//
486// R_DrawSpan
487// With DOOM style restrictions on view orientation,
488// the floors and ceilings consist of horizontal slices
489// or spans with constant z depth.
490// However, rotation around the world z axis is possible,
491// thus this mapping, while simpler and faster than
492// perspective correct texture mapping, has to traverse
493// the texture at an angle in all but a few cases.
494// In consequence, flats are not stored by column (like walls),
495// and the inner loop has to step in texture space u and v.
496//
497
498int ds_y IBSS_ATTR;
499int ds_x1 IBSS_ATTR;
500int ds_x2 IBSS_ATTR;
501
502lighttable_t *ds_colormap IBSS_ATTR;
503
504fixed_t ds_xfrac IBSS_ATTR;
505fixed_t ds_yfrac IBSS_ATTR;
506fixed_t ds_xstep IBSS_ATTR;
507fixed_t ds_ystep IBSS_ATTR;
508
509// start of a 64*64 tile image
510byte *ds_source IBSS_ATTR;
511
512void R_DrawSpan (void)
513{
514 register unsigned count,xfrac = ds_xfrac,yfrac = ds_yfrac;
515
516 byte *source;
517 byte *colormap;
518 byte *dest;
519
520 source = ds_source;
521 colormap = ds_colormap;
522 dest = topleft + ds_y*SCREENWIDTH + ds_x1;
523 count = ds_x2 - ds_x1 + 1;
524
525 while (count)
526 {
527 register unsigned xtemp = xfrac >> 16;
528 register unsigned ytemp = yfrac >> 10;
529 register unsigned spot;
530 ytemp &= 4032;
531 xtemp &= 63;
532 spot = xtemp | ytemp;
533 xfrac += ds_xstep;
534 yfrac += ds_ystep;
535 *dest++ = colormap[source[spot]];
536 count--;
537 }
538}
539
540//
541// R_InitBuffer
542// Creats lookup tables that avoid
543// multiplies and other hazzles
544// for getting the framebuffer address
545// of a pixel to draw.
546//
547
548void R_InitBuffer(int width, int height)
549{
550 int i=0;
551 // Handle resize,
552 // e.g. smaller view windows
553 // with border and/or status bar.
554
555 viewwindowx = (SCREENWIDTH-width) >> 1;
556
557 // Same with base row offset.
558
559 viewwindowy = width==SCREENWIDTH ? 0 : (SCREENHEIGHT-(ST_SCALED_HEIGHT-1)-height)>>1;
560
561 topleft = screens[0] + viewwindowy*SCREENWIDTH + viewwindowx;
562
563 // Preclaculate all row offsets.
564 // CPhipps - merge viewwindowx into here
565 for (i=0; i<FUZZTABLE; i++)
566 fuzzoffset[i] = fuzzoffset_org[i]*SCREENWIDTH;
567}
568
569
570//
571// R_FillBackScreen
572// Fills the back screen with a pattern
573// for variable screen sizes
574// Also draws a beveled edge.
575//
576// CPhipps - patch drawing updated
577
578void R_FillBackScreen (void)
579{
580 int x,y;
581
582 if (scaledviewwidth == SCREENWIDTH)
583 return;
584
585 V_DrawBackground(gamemode == commercial ? "GRNROCK" : "FLOOR7_2", 1);
586
587 for (x=0 ; x<scaledviewwidth ; x+=8)
588 V_DrawNamePatch(viewwindowx+x,viewwindowy-8,1,"brdr_t", CR_DEFAULT, VPT_NONE);
589
590 for (x=0 ; x<scaledviewwidth ; x+=8)
591 V_DrawNamePatch(viewwindowx+x,viewwindowy+viewheight,1,"brdr_b", CR_DEFAULT, VPT_NONE);
592
593 for (y=0 ; y<viewheight ; y+=8)
594 V_DrawNamePatch(viewwindowx-8,viewwindowy+y,1,"brdr_l", CR_DEFAULT, VPT_NONE);
595
596 for (y=0 ; y<viewheight ; y+=8)
597 V_DrawNamePatch(viewwindowx+scaledviewwidth,viewwindowy+y,1,"brdr_r", CR_DEFAULT, VPT_NONE);
598
599 // Draw beveled edge.
600 V_DrawNamePatch(viewwindowx-8,viewwindowy-8,1,"brdr_tl", CR_DEFAULT, VPT_NONE);
601
602 V_DrawNamePatch(viewwindowx+scaledviewwidth,viewwindowy-8,1,"brdr_tr", CR_DEFAULT, VPT_NONE);
603
604 V_DrawNamePatch(viewwindowx-8,viewwindowy+viewheight,1,"brdr_bl", CR_DEFAULT, VPT_NONE);
605
606 V_DrawNamePatch(viewwindowx+scaledviewwidth,viewwindowy+viewheight,1,"brdr_br", CR_DEFAULT, VPT_NONE);
607}
608
609//
610// Copy a screen buffer.
611//
612
613void R_VideoErase(unsigned ofs, int count)
614{
615 memcpy(screens[0]+ofs, screens[1]+ofs, count); // LFB copy.
616}
617
618
619//
620// R_DrawViewBorder
621// Draws the border around the view
622// for different size windows?
623//
624
625void R_DrawViewBorder(void)
626{
627 int top, side, ofs, i;
628 // proff/nicolas 09/20/98: Added for high-res (inspired by DosDOOM)
629 int side2;
630
631 // proff/nicolas 09/20/98: Removed for high-res
632 // if (scaledviewwidth == SCREENWIDTH)
633 // return;
634
635 // proff/nicolas 09/20/98: Added for high-res (inspired by DosDOOM)
636 if ((SCREENHEIGHT != viewheight) ||
637 ((automapmode & am_active) && ! (automapmode & am_overlay)))
638 {
639 ofs = ( SCREENHEIGHT - ST_SCALED_HEIGHT ) * SCREENWIDTH;
640 side= ( SCREENWIDTH - ST_SCALED_WIDTH ) / 2;
641 side2 = side * 2;
642
643 R_VideoErase ( ofs, side );
644
645 ofs += ( SCREENWIDTH - side );
646 for ( i = 1; i < ST_SCALED_HEIGHT; i++ )
647 {
648 R_VideoErase ( ofs, side2 );
649 ofs += SCREENWIDTH;
650 }
651
652 R_VideoErase ( ofs, side );
653 }
654
655 if ( viewheight >= ( SCREENHEIGHT - ST_SCALED_HEIGHT ))
656 return; // if high-res, donŽt go any further!
657
658 top = ((SCREENHEIGHT-ST_SCALED_HEIGHT)-viewheight)/2;
659 side = (SCREENWIDTH-scaledviewwidth)/2;
660
661 // copy top and one line of left side
662 R_VideoErase (0, top*SCREENWIDTH+side);
663
664 // copy one line of right side and bottom
665 ofs = (viewheight+top)*SCREENWIDTH-side;
666 R_VideoErase (ofs, top*SCREENWIDTH+side);
667
668 // copy sides using wraparound
669 ofs = top*SCREENWIDTH + SCREENWIDTH-side;
670 side <<= 1;
671
672 for (i=1 ; i<viewheight ; i++)
673 {
674 R_VideoErase (ofs, side);
675 ofs += SCREENWIDTH;
676 }
677}
diff --git a/apps/plugins/doom/r_draw.h b/apps/plugins/doom/r_draw.h
new file mode 100644
index 0000000000..3b43135836
--- /dev/null
+++ b/apps/plugins/doom/r_draw.h
@@ -0,0 +1,99 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION:
28 * System specific interface stuff.
29 *
30 *-----------------------------------------------------------------------------*/
31
32#ifndef __R_DRAW__
33#define __R_DRAW__
34
35#include "r_defs.h"
36
37#ifdef __GNUG__
38#pragma interface
39#endif
40
41extern lighttable_t *dc_colormap;
42extern int dc_x;
43extern int dc_yl;
44extern int dc_yh;
45extern fixed_t dc_iscale;
46extern fixed_t dc_texturemid;
47extern int dc_texheight; // killough
48
49// first pixel in a column
50extern const byte *dc_source;
51
52// The span blitting interface.
53// Hook in assembler or system specific BLT here.
54
55void R_DrawColumn(void) ICODE_ATTR;
56void R_DrawTLColumn(void) ICODE_ATTR; // drawing translucent textures // phares
57void R_DrawFuzzColumn(void) ICODE_ATTR; // The Spectre/Invisibility effect.
58
59// Draw with color translation tables, for player sprite rendering,
60// Green/Red/Blue/Indigo shirts.
61
62void R_DrawTranslatedColumn(void);
63
64void R_VideoErase(unsigned ofs, int count);
65
66extern lighttable_t *ds_colormap;
67
68extern int ds_y;
69extern int ds_x1;
70extern int ds_x2;
71extern fixed_t ds_xfrac;
72extern fixed_t ds_yfrac;
73extern fixed_t ds_xstep;
74extern fixed_t ds_ystep;
75
76// start of a 64*64 tile image
77extern byte *ds_source;
78extern byte playernumtotrans[MAXPLAYERS]; // CPhipps - what translation table for what player
79extern byte *translationtables;
80extern byte *dc_translation;
81
82// Span blitting for rows, floor/ceiling. No Spectre effect needed.
83void R_DrawSpan(void) ICODE_ATTR;
84
85void R_InitBuffer(int width, int height);
86
87// Initialize color translation tables, for player rendering etc.
88void R_InitTranslationTables(void);
89
90// Rendering function.
91void R_FillBackScreen(void);
92
93// If the view size is not full screen, draws a border around it.
94void R_DrawViewBorder(void);
95
96extern const byte *tranmap; // translucency filter maps 256x256 // phares
97extern const byte *main_tranmap; // killough 4/11/98
98
99#endif
diff --git a/apps/plugins/doom/r_main.c b/apps/plugins/doom/r_main.c
new file mode 100644
index 0000000000..f79097a969
--- /dev/null
+++ b/apps/plugins/doom/r_main.c
@@ -0,0 +1,531 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION:
28 * Rendering main loop and setup functions,
29 * utility functions (BSP, geometry, trigonometry).
30 * See tables.c, too.
31 *
32 *-----------------------------------------------------------------------------*/
33
34#include "doomstat.h"
35#include "w_wad.h"
36#include "r_main.h"
37#include "r_things.h"
38#include "r_plane.h"
39#include "r_bsp.h"
40#include "r_draw.h"
41#include "m_bbox.h"
42#include "r_sky.h"
43#include "v_video.h"
44#include "i_system.h"
45//#include "lprintf.h"
46#include "st_stuff.h"
47#include "rockmacros.h"
48
49// Fineangles in the SCREENWIDTH wide window.
50#define FIELDOFVIEW 2048
51
52// killough: viewangleoffset is a legacy from the pre-v1.2 days, when Doom
53// had Left/Mid/Right viewing. +/-ANG90 offsets were placed here on each
54// node, by d_net.c, to set up a L/M/R session.
55
56int viewangleoffset;
57
58int validcount = 1; // increment every time a check is made
59lighttable_t *fixedcolormap;
60int centerx IBSS_ATTR;
61int centery IBSS_ATTR;
62fixed_t centerxfrac, centeryfrac;
63fixed_t projection;
64fixed_t viewx, viewy, viewz;
65angle_t viewangle;
66fixed_t viewcos, viewsin;
67player_t *viewplayer;
68extern lighttable_t **walllights;
69
70//
71// precalculated math tables
72//
73
74angle_t clipangle;
75
76// The viewangletox[viewangle + FINEANGLES/4] lookup
77// maps the visible view angles to screen X coordinates,
78// flattening the arc to a flat projection plane.
79// There will be many angles mapped to the same X.
80
81int viewangletox[FINEANGLES/2];
82
83// The xtoviewangleangle[] table maps a screen pixel
84// to the lowest viewangle that maps back to x ranges
85// from clipangle to -clipangle.
86
87angle_t xtoviewangle[SCREENWIDTH+1]; // killough 2/8/98
88
89// killough 3/20/98: Support dynamic colormaps, e.g. deep water
90// killough 4/4/98: support dynamic number of them as well
91
92int numcolormaps;
93lighttable_t *(*c_scalelight)[LIGHTLEVELS][MAXLIGHTSCALE];
94lighttable_t *(*c_zlight)[LIGHTLEVELS][MAXLIGHTZ];
95lighttable_t *(*scalelight)[MAXLIGHTSCALE];
96lighttable_t *(*zlight)[MAXLIGHTZ];
97lighttable_t *fullcolormap;
98lighttable_t **colormaps;
99
100// killough 3/20/98, 4/4/98: end dynamic colormaps
101
102int extralight; // bumped light from gun blasts
103
104void (*colfunc)(void);
105
106//
107// R_PointOnSide
108// Traverse BSP (sub) tree,
109// check point against partition plane.
110// Returns side 0 (front) or 1 (back).
111//
112// killough 5/2/98: reformatted
113//
114
115int R_PointOnSide(fixed_t x, fixed_t y, const node_t *node)
116{
117 if (!node->dx)
118 return x <= node->x ? node->dy > 0 : node->dy < 0;
119
120 if (!node->dy)
121 return y <= node->y ? node->dx < 0 : node->dx > 0;
122
123 x -= node->x;
124 y -= node->y;
125
126 // Try to quickly decide by looking at sign bits.
127 if ((node->dy ^ node->dx ^ x ^ y) < 0)
128 return (node->dy ^ x) < 0; // (left is negative)
129 return FixedMul(y, node->dx>>FRACBITS) >= FixedMul(node->dy>>FRACBITS, x);
130}
131
132// killough 5/2/98: reformatted
133
134int R_PointOnSegSide(fixed_t x, fixed_t y, const seg_t *line)
135{
136 fixed_t lx = line->v1->x;
137 fixed_t ly = line->v1->y;
138 fixed_t ldx = line->v2->x - lx;
139 fixed_t ldy = line->v2->y - ly;
140
141 if (!ldx)
142 return x <= lx ? ldy > 0 : ldy < 0;
143
144 if (!ldy)
145 return y <= ly ? ldx < 0 : ldx > 0;
146
147 x -= lx;
148 y -= ly;
149
150 // Try to quickly decide by looking at sign bits.
151 if ((ldy ^ ldx ^ x ^ y) < 0)
152 return (ldy ^ x) < 0; // (left is negative)
153 return FixedMul(y, ldx>>FRACBITS) >= FixedMul(ldy>>FRACBITS, x);
154}
155
156//
157// R_PointToAngle
158// To get a global angle from cartesian coordinates,
159// the coordinates are flipped until they are in
160// the first octant of the coordinate system, then
161// the y (<=x) is scaled and divided by x to get a
162// tangent (slope) value which is looked up in the
163// tantoangle[] table. The +1 size of tantoangle[]
164// is to handle the case when x==y without additional
165// checking.
166//
167// killough 5/2/98: reformatted, cleaned up
168
169angle_t R_PointToAngle(fixed_t x, fixed_t y)
170{
171 return (y -= viewy, (x -= viewx) || y) ?
172 x >= 0 ?
173 y >= 0 ?
174 (x > y) ? tantoangle[SlopeDiv(y,x)] : // octant 0
175 ANG90-1-tantoangle[SlopeDiv(x,y)] : // octant 1
176 x > (y = -y) ? 0-tantoangle[SlopeDiv(y,x)] : // octant 8
177 ANG270+tantoangle[SlopeDiv(x,y)] : // octant 7
178 y >= 0 ? (x = -x) > y ? ANG180-1-tantoangle[SlopeDiv(y,x)] : // octant 3
179 ANG90 + tantoangle[SlopeDiv(x,y)] : // octant 2
180 (x = -x) > (y = -y) ? ANG180+tantoangle[ SlopeDiv(y,x)] : // octant 4
181 ANG270-1-tantoangle[SlopeDiv(x,y)] : // octant 5
182 0;
183}
184
185angle_t R_PointToAngle2(fixed_t viewx, fixed_t viewy, fixed_t x, fixed_t y)
186{
187 return (y -= viewy, (x -= viewx) || y) ?
188 x >= 0 ?
189 y >= 0 ?
190 (x > y) ? tantoangle[SlopeDiv(y,x)] : // octant 0
191 ANG90-1-tantoangle[SlopeDiv(x,y)] : // octant 1
192 x > (y = -y) ? 0-tantoangle[SlopeDiv(y,x)] : // octant 8
193 ANG270+tantoangle[SlopeDiv(x,y)] : // octant 7
194 y >= 0 ? (x = -x) > y ? ANG180-1-tantoangle[SlopeDiv(y,x)] : // octant 3
195 ANG90 + tantoangle[SlopeDiv(x,y)] : // octant 2
196 (x = -x) > (y = -y) ? ANG180+tantoangle[ SlopeDiv(y,x)] : // octant 4
197 ANG270-1-tantoangle[SlopeDiv(x,y)] : // octant 5
198 0;
199}
200
201//
202// R_InitTextureMapping
203//
204// killough 5/2/98: reformatted
205
206static void R_InitTextureMapping (void)
207{
208 register int i,x;
209 fixed_t focallength;
210
211 // Use tangent table to generate viewangletox:
212 // viewangletox will give the next greatest x
213 // after the view angle.
214 //
215 // Calc focallength
216 // so FIELDOFVIEW angles covers SCREENWIDTH.
217
218 focallength = FixedDiv(centerxfrac, finetangent[FINEANGLES/4+FIELDOFVIEW/2]);
219
220 for (i=0 ; i<FINEANGLES/2 ; i++)
221 {
222 int t;
223 if (finetangent[i] > FRACUNIT*2)
224 t = -1;
225 else
226 if (finetangent[i] < -FRACUNIT*2)
227 t = viewwidth+1;
228 else
229 {
230 t = FixedMul(finetangent[i], focallength);
231 t = (centerxfrac - t + FRACUNIT-1) >> FRACBITS;
232 if (t < -1)
233 t = -1;
234 else
235 if (t > viewwidth+1)
236 t = viewwidth+1;
237 }
238 viewangletox[i] = t;
239 }
240
241 // Scan viewangletox[] to generate xtoviewangle[]:
242 // xtoviewangle will give the smallest view angle
243 // that maps to x.
244
245 for (x=0; x<=viewwidth; x++)
246 {
247 for (i=0; viewangletox[i] > x; i++)
248 ;
249 xtoviewangle[x] = (i<<ANGLETOFINESHIFT)-ANG90;
250 }
251
252 // Take out the fencepost cases from viewangletox.
253 for (i=0; i<FINEANGLES/2; i++)
254 if (viewangletox[i] == -1)
255 viewangletox[i] = 0;
256 else
257 if (viewangletox[i] == viewwidth+1)
258 viewangletox[i] = viewwidth;
259
260 clipangle = xtoviewangle[0];
261}
262
263//
264// R_InitLightTables
265// Only inits the zlight table,
266// because the scalelight table changes with view size.
267//
268
269#define DISTMAP 2
270
271void R_InitLightTables (void)
272{
273 int i;
274
275 // killough 4/4/98: dynamic colormaps
276 c_zlight = malloc(sizeof(*c_zlight) * numcolormaps);
277 c_scalelight = malloc(sizeof(*c_scalelight) * numcolormaps);
278
279 // Calculate the light levels to use
280 // for each level / distance combination.
281 for (i=0; i< LIGHTLEVELS; i++)
282 {
283 int j, startmap = ((LIGHTLEVELS-1-i)*2)*NUMCOLORMAPS/LIGHTLEVELS;
284 for (j=0; j<MAXLIGHTZ; j++)
285 {
286 // CPhipps - use 320 here instead of SCREENWIDTH, otherwise hires is
287 // brighter than normal res
288 int scale = FixedDiv ((320/2*FRACUNIT), (j+1)<<LIGHTZSHIFT);
289 int t, level = startmap - (scale >>= LIGHTSCALESHIFT)/DISTMAP;
290
291 if (level < 0)
292 level = 0;
293 else
294 if (level >= NUMCOLORMAPS)
295 level = NUMCOLORMAPS-1;
296
297 // killough 3/20/98: Initialize multiple colormaps
298 level *= 256;
299 for (t=0; t<numcolormaps; t++) // killough 4/4/98
300 c_zlight[t][i][j] = colormaps[t] + level;
301 }
302 }
303}
304
305//
306// R_SetViewSize
307// Do not really change anything here,
308// because it might be in the middle of a refresh.
309// The change will take effect next refresh.
310//
311
312boolean setsizeneeded;
313int setblocks;
314
315void R_SetViewSize(int blocks)
316{
317 setsizeneeded = true;
318 setblocks = blocks;
319}
320
321//
322// R_ExecuteSetViewSize
323//
324
325void R_ExecuteSetViewSize (void)
326{
327 int i;
328
329 setsizeneeded = false;
330
331 if (setblocks == 11)
332 {
333 scaledviewwidth = SCREENWIDTH;
334 viewheight = SCREENHEIGHT;
335 }
336 else
337 {
338 scaledviewwidth = setblocks*32;
339 viewheight = (setblocks*168/10)&~7;
340 }
341
342 viewwidth = scaledviewwidth;
343
344 centery = viewheight/2;
345 centerx = viewwidth/2;
346 centerxfrac = centerx<<FRACBITS;
347 centeryfrac = centery<<FRACBITS;
348 projection = centerxfrac;
349
350 R_InitBuffer (scaledviewwidth, viewheight);
351
352 R_InitTextureMapping();
353
354 // psprite scales
355 pspritescale = FRACUNIT*viewwidth/SCREENWIDTH;
356 pspriteiscale = FRACUNIT*SCREENWIDTH/viewwidth;
357
358 // thing clipping
359 for (i=0 ; i<viewwidth ; i++)
360 screenheightarray[i] = viewheight;
361
362 // planes
363 for (i=0 ; i<viewheight ; i++)
364 { // killough 5/2/98: reformatted
365 fixed_t dy = D_abs(((i-viewheight/2)<<FRACBITS)+FRACUNIT/2);
366 yslope[i] = FixedDiv ( (viewwidth)/2*FRACUNIT, dy);
367 }
368
369 for (i=0 ; i<viewwidth ; i++)
370 {
371 fixed_t cosadj = D_abs(finecosine[xtoviewangle[i]>>ANGLETOFINESHIFT]);
372 distscale[i] = FixedDiv(FRACUNIT,cosadj);
373 }
374
375 // Calculate the light levels to use
376 // for each level / scale combination.
377 for (i=0; i<LIGHTLEVELS; i++)
378 {
379 int j, startmap = ((LIGHTLEVELS-1-i)*2)*NUMCOLORMAPS/LIGHTLEVELS;
380 for (j=0 ; j<MAXLIGHTSCALE ; j++)
381 {
382 // CPhipps - use 320 here instead of SCREENWIDTH, otherwise hires is
383 // brighter than normal res
384 int scale = FixedDiv ((320/2*FRACUNIT), (j+1)<<LIGHTZSHIFT);
385 int t, level = startmap - (scale >>= LIGHTSCALESHIFT)/DISTMAP;
386
387 if (level < 0)
388 level = 0;
389
390 if (level >= NUMCOLORMAPS)
391 level = NUMCOLORMAPS-1;
392
393 // killough 3/20/98: initialize multiple colormaps
394 level *= 256;
395
396 for (t=0; t<numcolormaps; t++) // killough 4/4/98
397 c_scalelight[t][i][j] = colormaps[t] + level;
398 }
399 }
400}
401
402//
403// R_Init
404//
405
406extern int screenblocks;
407
408void R_Init (void)
409{
410 // CPhipps - R_DrawColumn isn't constant anymore, so must
411 // initialise in code
412 colfunc = R_DrawColumn; // current column draw function
413 if (SCREENWIDTH<320)
414 I_Error("R_Init: Screenwidth(%d) < 320",SCREENWIDTH);
415#if 1
416 printf("\nR_LoadTrigTables: ");
417 R_LoadTrigTables();
418#endif
419 printf("\nR_InitData: ");
420 R_InitData();
421 R_SetViewSize(screenblocks);
422 printf("\nR_Init: R_InitPlanes ");
423 R_InitPlanes();
424 printf("R_InitLightTables ");
425 R_InitLightTables();
426 printf("R_InitSkyMap ");
427 R_InitSkyMap();
428 printf("R_InitTranslationsTables ");
429 R_InitTranslationTables();
430}
431
432//
433// R_PointInSubsector
434//
435// killough 5/2/98: reformatted, cleaned up
436
437subsector_t *R_PointInSubsector(fixed_t x, fixed_t y)
438{
439 int nodenum = numnodes-1;
440 while (!(nodenum & NF_SUBSECTOR))
441 nodenum = nodes[nodenum].children[R_PointOnSide(x, y, nodes+nodenum)];
442 return &subsectors[nodenum & ~NF_SUBSECTOR];
443}
444
445//
446// R_SetupFrame
447//
448
449void R_SetupFrame (player_t *player)
450{
451 int i, cm;
452
453 viewplayer = player;
454 viewx = player->mo->x;
455 viewy = player->mo->y;
456 viewangle = player->mo->angle + viewangleoffset;
457 extralight = player->extralight;
458
459 viewz = player->viewz;
460
461 viewsin = finesine[viewangle>>ANGLETOFINESHIFT];
462 viewcos = finecosine[viewangle>>ANGLETOFINESHIFT];
463
464 // killough 3/20/98, 4/4/98: select colormap based on player status
465
466 if (player->mo->subsector->sector->heightsec != -1)
467 {
468 const sector_t *s = player->mo->subsector->sector->heightsec + sectors;
469 cm = viewz < s->floorheight ? s->bottommap : viewz > s->ceilingheight ?
470 s->topmap : s->midmap;
471 if (cm < 0 || cm > numcolormaps)
472 cm = 0;
473 }
474 else
475 cm = 0;
476
477 fullcolormap = colormaps[cm];
478 zlight = c_zlight[cm];
479 scalelight = c_scalelight[cm];
480
481 if (player->fixedcolormap)
482 {
483 // killough 3/20/98: localize scalelightfixed (readability/optimization)
484 static lighttable_t *scalelightfixed[MAXLIGHTSCALE];
485
486 fixedcolormap = fullcolormap // killough 3/20/98: use fullcolormap
487 + player->fixedcolormap*256*sizeof(lighttable_t);
488
489 walllights = scalelightfixed;
490
491 for (i=0 ; i<MAXLIGHTSCALE ; i++)
492 scalelightfixed[i] = fixedcolormap;
493 }
494 else
495 fixedcolormap = 0;
496
497 validcount++;
498}
499
500//
501// R_RenderView
502//
503void R_RenderPlayerView (player_t* player)
504{
505 R_SetupFrame (player);
506
507 // Clear buffers.
508 R_ClearClipSegs ();
509 R_ClearDrawSegs ();
510 R_ClearPlanes ();
511 R_ClearSprites ();
512
513 // check for new console commands.
514 // NetUpdate ();
515
516 // The head node is the last node output.
517 R_RenderBSPNode (numnodes-1);
518
519 // Check for new console commands.
520 // NetUpdate ();
521
522 R_DrawPlanes ();
523
524 // Check for new console commands.
525 // NetUpdate ();
526
527 R_DrawMasked ();
528
529 // Check for new console commands.
530 // NetUpdate ();
531}
diff --git a/apps/plugins/doom/r_main.h b/apps/plugins/doom/r_main.h
new file mode 100644
index 0000000000..10978b3e71
--- /dev/null
+++ b/apps/plugins/doom/r_main.h
@@ -0,0 +1,125 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION:
28 * Renderer main interface.
29 *
30 *-----------------------------------------------------------------------------*/
31
32#ifndef __R_MAIN__
33#define __R_MAIN__
34
35#include "d_player.h"
36#include "r_data.h"
37
38#ifdef __GNUG__
39#pragma interface
40#endif
41
42//
43// POV related.
44//
45
46extern fixed_t viewcos;
47extern fixed_t viewsin;
48extern int viewwidth;
49extern int viewheight;
50extern int viewwindowx;
51extern int viewwindowy;
52extern int centerx;
53extern int centery;
54extern fixed_t centerxfrac;
55extern fixed_t centeryfrac;
56extern fixed_t projection;
57extern int validcount;
58extern int linecount;
59extern int loopcount;
60
61//
62// Rendering stats
63//
64
65extern int rendered_visplanes, rendered_segs, rendered_vissprites;
66extern boolean rendering_stats;
67
68//
69// Lighting LUT.
70// Used for z-depth cuing per column/row,
71// and other lighting effects (sector ambient, flash).
72//
73
74// Lighting constants.
75
76#define LIGHTLEVELS 16
77#define LIGHTSEGSHIFT 4
78#define MAXLIGHTSCALE 48
79#define LIGHTSCALESHIFT 12
80#define MAXLIGHTZ 128
81#define LIGHTZSHIFT 20
82
83// killough 3/20/98: Allow colormaps to be dynamic (e.g. underwater)
84extern lighttable_t *(*scalelight)[MAXLIGHTSCALE];
85extern lighttable_t *(*zlight)[MAXLIGHTZ];
86extern lighttable_t *fullcolormap;
87extern int numcolormaps; // killough 4/4/98: dynamic number of maps
88extern lighttable_t **colormaps;
89// killough 3/20/98, 4/4/98: end dynamic colormaps
90
91extern int extralight;
92extern lighttable_t *fixedcolormap;
93
94// Number of diminishing brightness levels.
95// There a 0-31, i.e. 32 LUT in the COLORMAP lump.
96
97#define NUMCOLORMAPS 32
98
99//
100// Function pointers to switch refresh/drawing functions.
101// Used to select shadow mode etc.
102//
103
104extern void (*colfunc)(void);
105
106//
107// Utility functions.
108//
109
110int R_PointOnSide(fixed_t x, fixed_t y, const node_t *node);
111int R_PointOnSegSide(fixed_t x, fixed_t y, const seg_t *line);
112angle_t R_PointToAngle(fixed_t x, fixed_t y);
113angle_t R_PointToAngle2(fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2);
114subsector_t *R_PointInSubsector(fixed_t x, fixed_t y);
115
116//
117// REFRESH - the actual rendering functions.
118//
119
120void R_RenderPlayerView(player_t *player); // Called by G_Drawer.
121void R_Init(void); // Called by startup code.
122void R_SetViewSize(int blocks); // Called by M_Responder.
123void R_ExecuteSetViewSize(void); // cph - called by D_Display to complete a view resize
124
125#endif
diff --git a/apps/plugins/doom/r_plane.c b/apps/plugins/doom/r_plane.c
new file mode 100644
index 0000000000..60d37f876b
--- /dev/null
+++ b/apps/plugins/doom/r_plane.c
@@ -0,0 +1,434 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION:
28 * Here is a core component: drawing the floors and ceilings,
29 * while maintaining a per column clipping list only.
30 * Moreover, the sky areas have to be determined.
31 *
32 * MAXVISPLANES is no longer a limit on the number of visplanes,
33 * but a limit on the number of hash slots; larger numbers mean
34 * better performance usually but after a point they are wasted,
35 * and memory and time overheads creep in.
36 *
37 * For more information on visplanes, see:
38 *
39 * http://classicgaming.com/doom/editing/
40 *
41 * Lee Killough
42 *
43 *-----------------------------------------------------------------------------*/
44
45#include "z_zone.h" /* memory allocation wrappers -- killough */
46
47#include "doomstat.h"
48#include "w_wad.h"
49#include "r_main.h"
50#include "r_draw.h"
51#include "r_things.h"
52#include "r_sky.h"
53#include "r_plane.h"
54#include "rockmacros.h"
55
56#define MAXVISPLANES 128 /* must be a power of 2 */
57
58static visplane_t *visplanes[MAXVISPLANES] IBSS_ATTR; // killough
59static visplane_t *freetail; // killough
60static visplane_t **freehead = &freetail; // killough
61visplane_t *floorplane, *ceilingplane;
62
63// killough -- hash function for visplanes
64// Empirically verified to be fairly uniform:
65
66#define visplane_hash(picnum,lightlevel,height) \
67 ((unsigned)((picnum)*3+(lightlevel)+(height)*7) & (MAXVISPLANES-1))
68
69size_t maxopenings;
70short *openings,*lastopening;
71
72// Clip values are the solid pixel bounding the range.
73// floorclip starts out SCREENHEIGHT
74// ceilingclip starts out -1
75
76short floorclip[SCREENWIDTH], ceilingclip[SCREENWIDTH];
77
78// spanstart holds the start of a plane span; initialized to 0 at start
79
80static int spanstart[SCREENHEIGHT]; // killough 2/8/98
81
82//
83// texture mapping
84//
85
86static lighttable_t **planezlight;
87static fixed_t planeheight;
88
89// killough 2/8/98: make variables static
90
91static fixed_t basexscale, baseyscale;
92static fixed_t cachedheight[SCREENHEIGHT];
93static fixed_t cacheddistance[SCREENHEIGHT];
94static fixed_t cachedxstep[SCREENHEIGHT];
95static fixed_t cachedystep[SCREENHEIGHT];
96static fixed_t xoffs, yoffs; // killough 2/28/98: flat offsets
97
98fixed_t yslope[SCREENHEIGHT], distscale[SCREENWIDTH];
99
100//
101// R_InitPlanes
102// Only at game startup.
103//
104void R_InitPlanes (void)
105{
106}
107
108//
109// R_MapPlane
110//
111// Uses global vars:
112// planeheight
113// ds_source
114// basexscale
115// baseyscale
116// viewx
117// viewy
118// xoffs
119// yoffs
120//
121// BASIC PRIMITIVE
122//
123
124static void R_MapPlane(int y, int x1, int x2)
125{
126 angle_t angle;
127 fixed_t distance, length;
128 unsigned index;
129
130#ifdef RANGECHECK
131 if (x2 < x1 || x1<0 || x2>=viewwidth || (unsigned)y>(unsigned)viewheight)
132 I_Error ("R_MapPlane: %i, %i at %i",x1,x2,y);
133#endif
134
135 if (planeheight != cachedheight[y])
136 {
137 cachedheight[y] = planeheight;
138 distance = cacheddistance[y] = FixedMul (planeheight, yslope[y]);
139 ds_xstep = cachedxstep[y] = FixedMul (distance,basexscale);
140 ds_ystep = cachedystep[y] = FixedMul (distance,baseyscale);
141 }
142 else
143 {
144 distance = cacheddistance[y];
145 ds_xstep = cachedxstep[y];
146 ds_ystep = cachedystep[y];
147 }
148
149 length = FixedMul (distance,distscale[x1]);
150 angle = (viewangle + xtoviewangle[x1])>>ANGLETOFINESHIFT;
151
152 // killough 2/28/98: Add offsets
153 ds_xfrac = viewx + FixedMul(finecosine[angle], length) + xoffs;
154 ds_yfrac = -viewy - FixedMul(finesine[angle], length) + yoffs;
155
156 if (!(ds_colormap = fixedcolormap))
157 {
158 index = distance >> LIGHTZSHIFT;
159 if (index >= MAXLIGHTZ )
160 index = MAXLIGHTZ-1;
161 ds_colormap = planezlight[index];
162 }
163
164 ds_y = y;
165 ds_x1 = x1;
166 ds_x2 = x2;
167
168 R_DrawSpan();
169}
170
171//
172// R_ClearPlanes
173// At begining of frame.
174//
175
176void R_ClearPlanes(void)
177{
178 int i;
179 angle_t angle;
180
181 // opening / clipping determination
182 for (i=0 ; i<viewwidth ; i++)
183 floorclip[i] = viewheight, ceilingclip[i] = -1;
184
185 for (i=0;i<MAXVISPLANES;i++) // new code -- killough
186 for (*freehead = visplanes[i], visplanes[i] = NULL; *freehead; )
187 freehead = &(*freehead)->next;
188
189 lastopening = openings;
190
191 // texture calculation
192 memset (cachedheight, 0, sizeof(cachedheight));
193
194 // left to right mapping
195 angle = (viewangle-ANG90)>>ANGLETOFINESHIFT;
196
197 // scale will be unit scale at SCREENWIDTH/2 distance
198 basexscale = FixedDiv (finecosine[angle],centerxfrac);
199 baseyscale = -FixedDiv (finesine[angle],centerxfrac);
200}
201
202// New function, by Lee Killough
203
204static visplane_t *new_visplane(unsigned hash)
205{
206 visplane_t *check = freetail;
207 if (!check)
208 check = calloc(1, sizeof *check);
209 else
210 if (!(freetail = freetail->next))
211 freehead = &freetail;
212 check->next = visplanes[hash];
213 visplanes[hash] = check;
214 return check;
215}
216
217/*
218 * R_DupPlane
219 *
220 * cph 2003/04/18 - create duplicate of existing visplane and set initial range
221 */
222visplane_t *R_DupPlane(const visplane_t *pl, int start, int stop)
223{
224 unsigned hash = visplane_hash(pl->picnum, pl->lightlevel, pl->height);
225 visplane_t *new_pl = new_visplane(hash);
226
227 new_pl->height = pl->height;
228 new_pl->picnum = pl->picnum;
229 new_pl->lightlevel = pl->lightlevel;
230 new_pl->xoffs = pl->xoffs; // killough 2/28/98
231 new_pl->yoffs = pl->yoffs;
232 new_pl->minx = start;
233 new_pl->maxx = stop;
234 memset(new_pl->top, 0xff, sizeof new_pl->top);
235 return new_pl;
236}
237
238//
239// R_FindPlane
240//
241// killough 2/28/98: Add offsets
242
243visplane_t *R_FindPlane(fixed_t height, int picnum, int lightlevel,
244 fixed_t xoffs, fixed_t yoffs)
245{
246 visplane_t *check;
247 unsigned hash; // killough
248
249 if (picnum == skyflatnum || picnum & PL_SKYFLAT)
250 height = lightlevel = 0; // killough 7/19/98: most skies map together
251
252 // New visplane algorithm uses hash table -- killough
253 hash = visplane_hash(picnum,lightlevel,height);
254
255 for (check=visplanes[hash]; check; check=check->next) // killough
256 if (height == check->height &&
257 picnum == check->picnum &&
258 lightlevel == check->lightlevel &&
259 xoffs == check->xoffs && // killough 2/28/98: Add offset checks
260 yoffs == check->yoffs)
261 return check;
262
263 check = new_visplane(hash); // killough
264
265 check->height = height;
266 check->picnum = picnum;
267 check->lightlevel = lightlevel;
268 check->minx = viewwidth; // Was SCREENWIDTH -- killough 11/98
269 check->maxx = -1;
270 check->xoffs = xoffs; // killough 2/28/98: Save offsets
271 check->yoffs = yoffs;
272
273 memset (check->top, 0xff, sizeof check->top);
274
275 return check;
276}
277
278//
279// R_CheckPlane
280//
281visplane_t *R_CheckPlane(visplane_t *pl, int start, int stop)
282{
283 int intrl, intrh, unionl, unionh, x;
284
285 if (start < pl->minx)
286 intrl = pl->minx, unionl = start;
287 else
288 unionl = pl->minx, intrl = start;
289
290 if (stop > pl->maxx)
291 intrh = pl->maxx, unionh = stop;
292 else
293 unionh = pl->maxx, intrh = stop;
294
295 for (x=intrl ; x <= intrh && pl->top[x] == 0xffff; x++)
296 ;
297
298 if (x > intrh) { /* Can use existing plane; extend range */
299 pl->minx = unionl; pl->maxx = unionh;
300 return pl;
301 } else /* Cannot use existing plane; create a new one */
302 return R_DupPlane(pl,start,stop);
303}
304
305//
306// R_MakeSpans
307//
308
309static void R_MakeSpans(int x, int t1, int b1, int t2, int b2)
310{
311 for (; t1 < t2 && t1 <= b1; t1++)
312 R_MapPlane(t1, spanstart[t1], x-1);
313 for (; b1 > b2 && b1 >= t1; b1--)
314 R_MapPlane(b1, spanstart[b1] ,x-1);
315 while (t2 < t1 && t2 <= b2)
316 spanstart[t2++] = x;
317 while (b2 > b1 && b2 >= t2)
318 spanstart[b2--] = x;
319}
320
321// New function, by Lee Killough
322
323static void R_DoDrawPlane(visplane_t *pl)
324{
325 register int x;
326 if (pl->minx <= pl->maxx) {
327 if (pl->picnum == skyflatnum || pl->picnum & PL_SKYFLAT) { // sky flat
328 int texture;
329 angle_t an, flip;
330
331 // killough 10/98: allow skies to come from sidedefs.
332 // Allows scrolling and/or animated skies, as well as
333 // arbitrary multiple skies per level without having
334 // to use info lumps.
335
336 an = viewangle;
337
338 if (pl->picnum & PL_SKYFLAT)
339 {
340 // Sky Linedef
341 const line_t *l = &lines[pl->picnum & ~PL_SKYFLAT];
342
343 // Sky transferred from first sidedef
344 const side_t *s = *l->sidenum + sides;
345
346 // Texture comes from upper texture of reference sidedef
347 texture = texturetranslation[s->toptexture];
348
349 // Horizontal offset is turned into an angle offset,
350 // to allow sky rotation as well as careful positioning.
351 // However, the offset is scaled very small, so that it
352 // allows a long-period of sky rotation.
353
354 an += s->textureoffset;
355
356 // Vertical offset allows careful sky positioning.
357
358 dc_texturemid = s->rowoffset - 28*FRACUNIT;
359
360 // We sometimes flip the picture horizontally.
361 //
362 // Doom always flipped the picture, so we make it optional,
363 // to make it easier to use the new feature, while to still
364 // allow old sky textures to be used.
365
366 flip = l->special==272 ? 0u : ~0u;
367 }
368 else
369 { // Normal Doom sky, only one allowed per level
370 dc_texturemid = skytexturemid; // Default y-offset
371 texture = skytexture; // Default texture
372 flip = 0; // Doom flips it
373 }
374
375 /* Sky is always drawn full bright, i.e. colormaps[0] is used.
376 * Because of this hack, sky is not affected by INVUL inverse mapping.
377 * Until Boom fixed this. Compat option added in MBF. */
378
379 if (comp[comp_skymap] || !(dc_colormap = fixedcolormap))
380 dc_colormap = fullcolormap; // killough 3/20/98
381 dc_texheight = textureheight[skytexture]>>FRACBITS; // killough
382 // proff 09/21/98: Changed for high-res
383 dc_iscale = FRACUNIT*200/viewheight;
384
385 // killough 10/98: Use sky scrolling offset, and possibly flip picture
386 for (x = pl->minx; (dc_x = x) <= pl->maxx; x++)
387 if ((dc_yl = pl->top[x]) <= (dc_yh = pl->bottom[x]))
388 {
389 dc_source = R_GetColumn(texture, ((an + xtoviewangle[x])^flip) >>
390 ANGLETOSKYSHIFT);
391 colfunc();
392 }
393 } else { // regular flat
394
395 int stop, light;
396
397 ds_source = W_CacheLumpNum(firstflat + flattranslation[pl->picnum]);
398
399 xoffs = pl->xoffs; // killough 2/28/98: Add offsets
400 yoffs = pl->yoffs;
401 planeheight = D_abs(pl->height-viewz);
402 light = (pl->lightlevel >> LIGHTSEGSHIFT) + extralight;
403
404 if (light >= LIGHTLEVELS)
405 light = LIGHTLEVELS-1;
406
407 if (light < 0)
408 light = 0;
409
410 stop = pl->maxx + 1;
411 planezlight = zlight[light];
412 pl->top[pl->minx-1] = pl->top[stop] = 0xffff;
413
414 for (x = pl->minx ; x <= stop ; x++)
415 R_MakeSpans(x,pl->top[x-1],pl->bottom[x-1],pl->top[x],pl->bottom[x]);
416
417 W_UnlockLumpNum(firstflat + flattranslation[pl->picnum]);
418 }
419 }
420}
421
422//
423// RDrawPlanes
424// At the end of each frame.
425//
426
427void R_DrawPlanes (void)
428{
429 visplane_t *pl;
430 int i;
431 for (i=0;i<MAXVISPLANES;i++)
432 for (pl=visplanes[i]; pl; pl=pl->next)
433 R_DoDrawPlane(pl);
434}
diff --git a/apps/plugins/doom/r_plane.h b/apps/plugins/doom/r_plane.h
new file mode 100644
index 0000000000..9696ea28e8
--- /dev/null
+++ b/apps/plugins/doom/r_plane.h
@@ -0,0 +1,65 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION:
28 * Refresh, visplane stuff (floor, ceilings).
29 *
30 *-----------------------------------------------------------------------------*/
31
32#ifndef __R_PLANE__
33#define __R_PLANE__
34
35#include "r_data.h"
36
37#ifdef __GNUG__
38#pragma interface
39#endif
40
41/* killough 10/98: special mask indicates sky flat comes from sidedef */
42#define PL_SKYFLAT (0x80000000)
43
44/* Visplane related. */
45extern short *lastopening;
46
47extern short floorclip[], ceilingclip[];
48extern fixed_t yslope[], distscale[];
49
50void R_InitPlanes(void);
51void R_ClearPlanes(void);
52void R_DrawPlanes (void);
53
54visplane_t *R_FindPlane(
55 fixed_t height,
56 int picnum,
57 int lightlevel,
58 fixed_t xoffs, /* killough 2/28/98: add x-y offsets */
59 fixed_t yoffs
60);
61
62visplane_t *R_CheckPlane(visplane_t *pl, int start, int stop);
63visplane_t *R_DupPlane(const visplane_t *pl, int start, int stop);
64
65#endif
diff --git a/apps/plugins/doom/r_segs.c b/apps/plugins/doom/r_segs.c
new file mode 100644
index 0000000000..4771132c77
--- /dev/null
+++ b/apps/plugins/doom/r_segs.c
@@ -0,0 +1,843 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION:
28 * All the clipping: columns, horizontal spans, sky columns.
29 *
30 *-----------------------------------------------------------------------------*/
31//
32// 4/25/98, 5/2/98 killough: reformatted, beautified
33
34#include "doomstat.h"
35#include "r_main.h"
36#include "r_bsp.h"
37#include "r_plane.h"
38#include "r_things.h"
39#include "r_draw.h"
40#include "w_wad.h"
41//#include "lprintf.h"
42#include "rockmacros.h"
43
44// OPTIMIZE: closed two sided lines as single sided
45
46// killough 1/6/98: replaced globals with statics where appropriate
47
48// True if any of the segs textures might be visible.
49boolean segtextured;
50boolean markfloor; // False if the back side is the same plane.
51boolean markceiling;
52static boolean maskedtexture;
53static int toptexture;
54static int bottomtexture;
55static int midtexture;
56
57static fixed_t toptexheight, midtexheight, bottomtexheight; // cph
58
59angle_t rw_normalangle;// angle to line origin
60int rw_angle1;
61fixed_t rw_distance;
62lighttable_t** walllights;
63
64//
65// regular wall
66//
67int rw_x;
68int rw_stopx;
69static angle_t rw_centerangle;
70static fixed_t rw_offset;
71static fixed_t rw_scale;
72static fixed_t rw_scalestep;
73static fixed_t rw_midtexturemid;
74static fixed_t rw_toptexturemid;
75static fixed_t rw_bottomtexturemid;
76static int worldtop;
77static int worldbottom;
78static int worldhigh;
79static int worldlow;
80static fixed_t pixhigh;
81static fixed_t pixlow;
82static fixed_t pixhighstep;
83static fixed_t pixlowstep;
84static fixed_t topfrac;
85static fixed_t topstep;
86static fixed_t bottomfrac;
87static fixed_t bottomstep;
88static short *maskedtexturecol;
89
90//
91// R_ScaleFromGlobalAngle
92// Returns the texture mapping scale
93// for the current line (horizontal span)
94// at the given angle.
95// rw_distance must be calculated first.
96//
97// killough 5/2/98: reformatted, cleaned up
98static fixed_t R_ScaleFromGlobalAngle (angle_t visangle)
99{
100 int anglea = ANG90 + (visangle-viewangle);
101 int angleb = ANG90 + (visangle-rw_normalangle);
102 int sinea = finesine[anglea>>ANGLETOFINESHIFT];
103 int sineb = finesine[angleb>>ANGLETOFINESHIFT];
104 fixed_t num = FixedMul(projection,sineb);
105 int den = FixedMul(rw_distance,sinea);
106
107 return den > num>>16 ? (num=FixedDiv (num, den)) > 64*FRACUNIT ?
108 64*FRACUNIT : num < 256 ? 256 : num : 64*FRACUNIT ;
109}
110//
111// R_RenderMaskedSegRange
112//
113
114int fake_contrast IBSS_ATTR;
115
116void R_RenderMaskedSegRange(drawseg_t *ds, int x1, int x2)
117{
118 column_t *col;
119 int lightnum;
120 int texnum;
121 sector_t tempsec; // killough 4/13/98
122
123 // Calculate light table.
124 // Use different light tables
125 // for horizontal / vertical / diagonal. Diagonal?
126
127 curline = ds->curline; // OPTIMIZE: get rid of LIGHTSEGSHIFT globally
128
129 // killough 4/11/98: draw translucent 2s normal textures
130
131 colfunc = R_DrawColumn;
132 if (curline->linedef->tranlump >= 0 && general_translucency)
133 {
134 colfunc = R_DrawTLColumn;
135 tranmap = main_tranmap;
136 if (curline->linedef->tranlump > 0)
137 tranmap = W_CacheLumpNum(curline->linedef->tranlump-1);
138 }
139
140 // killough 4/11/98: end translucent 2s normal code
141
142 frontsector = curline->frontsector;
143 backsector = curline->backsector;
144
145 texnum = texturetranslation[curline->sidedef->midtexture];
146
147 // killough 4/13/98: get correct lightlevel for 2s normal textures
148 lightnum = (R_FakeFlat(frontsector, &tempsec, NULL, NULL, false)
149 ->lightlevel >> LIGHTSEGSHIFT)+extralight;
150
151 /* cph - ...what is this for? adding contrast to rooms?
152 * It looks crap in outdoor areas */
153 if (fake_contrast) {
154 if (curline->v1->y == curline->v2->y)
155 lightnum--;
156 else
157 if (curline->v1->x == curline->v2->x)
158 lightnum++;
159 }
160
161 walllights = lightnum >= LIGHTLEVELS ? scalelight[LIGHTLEVELS-1] :
162 lightnum < 0 ? scalelight[0] : scalelight[lightnum];
163
164 maskedtexturecol = ds->maskedtexturecol;
165
166 rw_scalestep = ds->scalestep;
167 spryscale = ds->scale1 + (x1 - ds->x1)*rw_scalestep;
168 mfloorclip = ds->sprbottomclip;
169 mceilingclip = ds->sprtopclip;
170
171 // find positioning
172 if (curline->linedef->flags & ML_DONTPEGBOTTOM)
173 {
174 dc_texturemid = frontsector->floorheight > backsector->floorheight
175 ? frontsector->floorheight : backsector->floorheight;
176 dc_texturemid = dc_texturemid + textureheight[texnum] - viewz;
177 }
178 else
179 {
180 dc_texturemid =frontsector->ceilingheight<backsector->ceilingheight
181 ? frontsector->ceilingheight : backsector->ceilingheight;
182 dc_texturemid = dc_texturemid - viewz;
183 }
184
185 dc_texturemid += curline->sidedef->rowoffset;
186
187 if (fixedcolormap)
188 dc_colormap = fixedcolormap;
189
190 // draw the columns
191 for (dc_x = x1 ; dc_x <= x2 ; dc_x++, spryscale += rw_scalestep)
192 if (maskedtexturecol[dc_x] != SHRT_MAX)
193 {
194 if (!fixedcolormap) // calculate lighting
195 {
196 unsigned index = spryscale>>LIGHTSCALESHIFT;
197
198 if (index >= MAXLIGHTSCALE )
199 index = MAXLIGHTSCALE-1;
200
201 dc_colormap = walllights[index];
202 }
203
204 // killough 3/2/98:
205 //
206 // This calculation used to overflow and cause crashes in Doom:
207 //
208 // sprtopscreen = centeryfrac - FixedMul(dc_texturemid, spryscale);
209 //
210 // This code fixes it, by using double-precision intermediate
211 // arithmetic and by skipping the drawing of 2s normals whose
212 // mapping to screen coordinates is totally out of range:
213
214 {
215 int_64_t t = ((int_64_t) centeryfrac << FRACBITS) -
216 (int_64_t) dc_texturemid * spryscale;
217 if (t + (int_64_t) textureheight[texnum] * spryscale < 0 ||
218 t > (int_64_t) SCREENHEIGHT << FRACBITS*2)
219 continue; // skip if the texture is out of screen's range
220 sprtopscreen = (long)(t >> FRACBITS);
221 }
222
223 dc_iscale = 0xffffffffu / (unsigned) spryscale;
224
225 // killough 1/25/98: here's where Medusa came in, because
226 // it implicitly assumed that the column was all one patch.
227 // Originally, Doom did not construct complete columns for
228 // multipatched textures, so there were no header or trailer
229 // bytes in the column referred to below, which explains
230 // the Medusa effect. The fix is to construct true columns
231 // when forming multipatched textures (see r_data.c).
232
233 // draw the texture
234 col = (column_t *)((byte *)
235 R_GetColumn(texnum,maskedtexturecol[dc_x]) - 3);
236 R_DrawMaskedColumn (col);
237 maskedtexturecol[dc_x] = SHRT_MAX;
238 }
239
240 // Except for main_tranmap, mark others purgable at this point
241 if (curline->linedef->tranlump > 0 && general_translucency)
242 W_UnlockLumpNum(curline->linedef->tranlump-1); // cph - unlock it
243}
244
245//
246// R_RenderSegLoop
247// Draws zero, one, or two textures (and possibly a masked texture) for walls.
248// Can draw or mark the starting pixel of floor and ceiling textures.
249// CALLED: CORE LOOPING ROUTINE.
250//
251
252extern byte solidcol[SCREENWIDTH];
253#define HEIGHTBITS 12
254#define HEIGHTUNIT (1<<HEIGHTBITS)
255static int didsolidcol; /* True if at least one column was marked solid */
256
257static void R_RenderSegLoop (void)
258{
259 fixed_t texturecolumn = 0; // shut up compiler warning
260 for ( ; rw_x < rw_stopx ; rw_x++)
261 {
262
263 // mark floor / ceiling areas
264
265 int yh = bottomfrac>>HEIGHTBITS;
266 int yl = (topfrac+HEIGHTUNIT-1)>>HEIGHTBITS;
267
268 // no space above wall?
269 int bottom,top = ceilingclip[rw_x]+1;
270
271 if (yl < top)
272 yl = top;
273
274 if (markceiling)
275 {
276 bottom = yl-1;
277
278 if (bottom >= floorclip[rw_x])
279 bottom = floorclip[rw_x]-1;
280
281 if (top <= bottom)
282 {
283 ceilingplane->top[rw_x] = top;
284 ceilingplane->bottom[rw_x] = bottom;
285 }
286 }
287
288 // yh = bottomfrac>>HEIGHTBITS;
289
290 bottom = floorclip[rw_x]-1;
291 if (yh > bottom)
292 yh = bottom;
293
294 if (markfloor)
295 {
296
297 top = yh < ceilingclip[rw_x] ? ceilingclip[rw_x] : yh;
298
299 if (++top <= bottom)
300 {
301 floorplane->top[rw_x] = top;
302 floorplane->bottom[rw_x] = bottom;
303 }
304 }
305
306 // texturecolumn and lighting are independent of wall tiers
307 if (segtextured)
308 {
309 unsigned index;
310
311 // calculate texture offset
312 angle_t angle =(rw_centerangle+xtoviewangle[rw_x])>>ANGLETOFINESHIFT;
313
314 texturecolumn = rw_offset-FixedMul(finetangent[angle],rw_distance);
315 texturecolumn >>= FRACBITS;
316 // calculate lighting
317 index = rw_scale>>LIGHTSCALESHIFT;
318
319 if (index >= MAXLIGHTSCALE )
320 index = MAXLIGHTSCALE-1;
321
322 dc_colormap = walllights[index];
323 dc_x = rw_x;
324 dc_iscale = 0xffffffffu / (unsigned)rw_scale;
325 }
326
327 // draw the wall tiers
328 if (midtexture)
329 {
330
331 dc_yl = yl; // single sided line
332 dc_yh = yh;
333 dc_texturemid = rw_midtexturemid;
334 dc_source = R_GetColumn(midtexture, texturecolumn);
335 dc_texheight = midtexheight;
336 colfunc ();
337 ceilingclip[rw_x] = viewheight;
338 floorclip[rw_x] = -1;
339 }
340 else
341 {
342
343 // two sided line
344 if (toptexture)
345 {
346 // top wall
347 int mid = pixhigh>>HEIGHTBITS;
348 pixhigh += pixhighstep;
349
350 if (mid >= floorclip[rw_x])
351 mid = floorclip[rw_x]-1;
352
353 if (mid >= yl)
354 {
355 dc_yl = yl;
356 dc_yh = mid;
357 dc_texturemid = rw_toptexturemid;
358 dc_source = R_GetColumn(toptexture,texturecolumn);
359 dc_texheight = toptexheight;
360 colfunc ();
361 ceilingclip[rw_x] = mid;
362 }
363 else
364 ceilingclip[rw_x] = yl-1;
365 }
366 else // no top wall
367 {
368
369 if (markceiling)
370 ceilingclip[rw_x] = yl-1;
371 }
372
373 if (bottomtexture) // bottom wall
374 {
375 int mid = (pixlow+HEIGHTUNIT-1)>>HEIGHTBITS;
376 pixlow += pixlowstep;
377
378 // no space above wall?
379 if (mid <= ceilingclip[rw_x])
380 mid = ceilingclip[rw_x]+1;
381
382 if (mid <= yh)
383 {
384 dc_yl = mid;
385 dc_yh = yh;
386 dc_texturemid = rw_bottomtexturemid;
387 dc_source = R_GetColumn(bottomtexture,
388 texturecolumn);
389 dc_texheight = bottomtexheight;
390 colfunc ();
391 floorclip[rw_x] = mid;
392 }
393 else
394 floorclip[rw_x] = yh+1;
395 }
396 else // no bottom wall
397 {
398 if (markfloor)
399 floorclip[rw_x] = yh+1;
400 }
401
402 // cph - if we completely blocked further sight through this column,
403 // add this info to the solid columns array for r_bsp.c
404 if ((markceiling || markfloor) &&
405 (floorclip[rw_x] <= ceilingclip[rw_x] + 1)) {
406 solidcol[rw_x] = 1; didsolidcol = 1;
407 }
408
409 // save texturecol for backdrawing of masked mid texture
410 if (maskedtexture)
411 maskedtexturecol[rw_x] = texturecolumn;
412 }
413
414 rw_scale += rw_scalestep;
415 topfrac += topstep;
416 bottomfrac += bottomstep;
417 }
418}
419
420// killough 5/2/98: move from r_main.c, made static, simplified
421
422static fixed_t R_PointToDist(fixed_t x, fixed_t y)
423{
424 fixed_t dx = D_abs(x - viewx);
425 fixed_t dy = D_abs(y - viewy);
426
427 if (dy > dx)
428 {
429 fixed_t t = dx;
430 dx = dy;
431 dy = t;
432 }
433
434 return FixedDiv(dx, finesine[(tantoangle[FixedDiv(dy,dx) >> DBITS]
435 + ANG90) >> ANGLETOFINESHIFT]);
436}
437
438//
439// R_StoreWallRange
440// A wall segment will be drawn
441// between start and stop pixels (inclusive).
442//
443void R_StoreWallRange(const int start, const int stop)
444{
445 fixed_t hyp;
446 fixed_t sineval;
447 angle_t distangle, offsetangle;
448
449 if (ds_p == drawsegs+maxdrawsegs) // killough 1/98 -- fix 2s line HOM
450 {
451 unsigned pos = ds_p - drawsegs; // jff 8/9/98 fix from ZDOOM1.14a
452 unsigned newmax = maxdrawsegs ? maxdrawsegs*2 : 128; // killough
453 drawsegs = realloc(drawsegs,newmax*sizeof(*drawsegs));
454 ds_p = drawsegs + pos; // jff 8/9/98 fix from ZDOOM1.14a
455 maxdrawsegs = newmax;
456 }
457
458 if(curline->miniseg == false) // figgi -- skip minisegs
459 curline->linedef->flags |= ML_MAPPED;
460
461
462#ifdef RANGECHECK
463 if (start >=viewwidth || start > stop)
464 I_Error ("Bad R_RenderWallRange: %i to %i", start , stop);
465#endif
466
467 sidedef = curline->sidedef;
468 linedef = curline->linedef;
469
470 // mark the segment as visible for auto map
471 linedef->flags |= ML_MAPPED;
472
473 // calculate rw_distance for scale calculation
474 rw_normalangle = curline->angle + ANG90;
475
476 offsetangle = D_abs(rw_normalangle-rw_angle1);
477
478 if (offsetangle > ANG90)
479 offsetangle = ANG90;
480
481 distangle = ANG90 - offsetangle;
482 hyp = (viewx==curline->v1->x && viewy==curline->v1->y)?
483 0 : R_PointToDist (curline->v1->x, curline->v1->y);
484 sineval = finesine[distangle>>ANGLETOFINESHIFT];
485 rw_distance = FixedMul(hyp, sineval);
486
487 ds_p->x1 = rw_x = start;
488 ds_p->x2 = stop;
489 ds_p->curline = curline;
490 rw_stopx = stop+1;
491
492 { // killough 1/6/98, 2/1/98: remove limit on openings
493 extern short *openings;
494 extern size_t maxopenings;
495 size_t pos = lastopening - openings;
496 size_t need = (rw_stopx - start)*4 + pos;
497 if (need > maxopenings)
498 {
499 drawseg_t *ds; //jff 8/9/98 needed for fix from ZDoom
500 short *oldopenings = openings;
501 short *oldlast = lastopening;
502
503 do
504 maxopenings = maxopenings ? maxopenings*2 : 16384;
505 while (need > maxopenings);
506 openings = realloc(openings, maxopenings * sizeof(*openings));
507 lastopening = openings + pos;
508
509 // jff 8/9/98 borrowed fix for openings from ZDOOM1.14
510 // [RH] We also need to adjust the openings pointers that
511 // were already stored in drawsegs.
512 for (ds = drawsegs; ds < ds_p; ds++)
513 {
514#define ADJUST(p) if (ds->p + ds->x1 >= oldopenings && ds->p + ds->x1 <= oldlast)\
515 ds->p = ds->p - oldopenings + openings;
516 ADJUST (maskedtexturecol);
517 ADJUST (sprtopclip);
518 ADJUST (sprbottomclip);
519 }
520#undef ADJUST
521 }
522 } // killough: end of code to remove limits on openings
523
524 // calculate scale at both ends and step
525
526 ds_p->scale1 = rw_scale =
527 R_ScaleFromGlobalAngle (viewangle + xtoviewangle[start]);
528
529 if (stop > start)
530 {
531 ds_p->scale2 = R_ScaleFromGlobalAngle (viewangle + xtoviewangle[stop]);
532 ds_p->scalestep = rw_scalestep = (ds_p->scale2-rw_scale) / (stop-start);
533 }
534 else
535 ds_p->scale2 = ds_p->scale1;
536
537 // calculate texture boundaries
538 // and decide if floor / ceiling marks are needed
539
540 worldtop = frontsector->ceilingheight - viewz;
541 worldbottom = frontsector->floorheight - viewz;
542
543 midtexture = toptexture = bottomtexture = maskedtexture = 0;
544 ds_p->maskedtexturecol = NULL;
545
546 if (!backsector)
547 {
548 // single sided line
549 midtexture = texturetranslation[sidedef->midtexture];
550 midtexheight = (linedef->r_flags & RF_MID_TILE) ? 0 : textureheight[midtexture] >> FRACBITS;
551
552 // a single sided line is terminal, so it must mark ends
553 markfloor = markceiling = true;
554
555 if (linedef->flags & ML_DONTPEGBOTTOM)
556 { // bottom of texture at bottom
557 fixed_t vtop = frontsector->floorheight +
558 textureheight[sidedef->midtexture];
559 rw_midtexturemid = vtop - viewz;
560 }
561 else // top of texture at top
562 rw_midtexturemid = worldtop;
563
564 rw_midtexturemid += FixedMod(sidedef->rowoffset, textureheight[midtexture]);
565
566 ds_p->silhouette = SIL_BOTH;
567 ds_p->sprtopclip = screenheightarray;
568 ds_p->sprbottomclip = negonearray;
569 ds_p->bsilheight = INT_MAX;
570 ds_p->tsilheight = INT_MIN;
571 }
572 else // two sided line
573 {
574 ds_p->sprtopclip = ds_p->sprbottomclip = NULL;
575 ds_p->silhouette = 0;
576
577 if (linedef->r_flags & RF_CLOSED) { /* cph - closed 2S line e.g. door */
578 // cph - killough's (outdated) comment follows - this deals with both
579 // "automap fixes", his and mine
580 // killough 1/17/98: this test is required if the fix
581 // for the automap bug (r_bsp.c) is used, or else some
582 // sprites will be displayed behind closed doors. That
583 // fix prevents lines behind closed doors with dropoffs
584 // from being displayed on the automap.
585
586 ds_p->silhouette = SIL_BOTH;
587 ds_p->sprbottomclip = negonearray;
588 ds_p->bsilheight = INT_MAX;
589 ds_p->sprtopclip = screenheightarray;
590 ds_p->tsilheight = INT_MIN;
591
592 } else { /* not solid - old code */
593
594 if (frontsector->floorheight > backsector->floorheight)
595 {
596 ds_p->silhouette = SIL_BOTTOM;
597 ds_p->bsilheight = frontsector->floorheight;
598 }
599 else
600 if (backsector->floorheight > viewz)
601 {
602 ds_p->silhouette = SIL_BOTTOM;
603 ds_p->bsilheight = INT_MAX;
604 }
605
606 if (frontsector->ceilingheight < backsector->ceilingheight)
607 {
608 ds_p->silhouette |= SIL_TOP;
609 ds_p->tsilheight = frontsector->ceilingheight;
610 }
611 else
612 if (backsector->ceilingheight < viewz)
613 {
614 ds_p->silhouette |= SIL_TOP;
615 ds_p->tsilheight = INT_MIN;
616 }
617 }
618
619 worldhigh = backsector->ceilingheight - viewz;
620 worldlow = backsector->floorheight - viewz;
621
622 // hack to allow height changes in outdoor areas
623 if (frontsector->ceilingpic == skyflatnum
624 && backsector->ceilingpic == skyflatnum)
625 worldtop = worldhigh;
626
627 markfloor = worldlow != worldbottom
628 || backsector->floorpic != frontsector->floorpic
629 || backsector->lightlevel != frontsector->lightlevel
630
631 // killough 3/7/98: Add checks for (x,y) offsets
632 || backsector->floor_xoffs != frontsector->floor_xoffs
633 || backsector->floor_yoffs != frontsector->floor_yoffs
634
635 // killough 4/15/98: prevent 2s normals
636 // from bleeding through deep water
637 || frontsector->heightsec != -1
638
639 // killough 4/17/98: draw floors if different light levels
640 || backsector->floorlightsec != frontsector->floorlightsec
641 ;
642
643 markceiling = worldhigh != worldtop
644 || backsector->ceilingpic != frontsector->ceilingpic
645 || backsector->lightlevel != frontsector->lightlevel
646
647 // killough 3/7/98: Add checks for (x,y) offsets
648 || backsector->ceiling_xoffs != frontsector->ceiling_xoffs
649 || backsector->ceiling_yoffs != frontsector->ceiling_yoffs
650
651 // killough 4/15/98: prevent 2s normals
652 // from bleeding through fake ceilings
653 || (frontsector->heightsec != -1 &&
654 frontsector->ceilingpic!=skyflatnum)
655
656 // killough 4/17/98: draw ceilings if different light levels
657 || backsector->ceilinglightsec != frontsector->ceilinglightsec
658 ;
659
660 if (backsector->ceilingheight <= frontsector->floorheight
661 || backsector->floorheight >= frontsector->ceilingheight)
662 markceiling = markfloor = true; // closed door
663
664 if (worldhigh < worldtop) // top texture
665 {
666 toptexture = texturetranslation[sidedef->toptexture];
667 toptexheight = (linedef->r_flags & RF_TOP_TILE) ? 0 : textureheight[toptexture] >> FRACBITS;
668 rw_toptexturemid = linedef->flags & ML_DONTPEGTOP ? worldtop :
669 backsector->ceilingheight+textureheight[sidedef->toptexture]-viewz;
670 rw_toptexturemid += FixedMod(sidedef->rowoffset, textureheight[toptexture]);
671 }
672
673 if (worldlow > worldbottom) // bottom texture
674 {
675 bottomtexture = texturetranslation[sidedef->bottomtexture];
676 bottomtexheight = (linedef->r_flags & RF_BOT_TILE) ? 0 : textureheight[bottomtexture] >> FRACBITS;
677 rw_bottomtexturemid = linedef->flags & ML_DONTPEGBOTTOM ? worldtop :
678 worldlow;
679 rw_bottomtexturemid += FixedMod(sidedef->rowoffset, textureheight[bottomtexture]);
680 }
681
682 // allocate space for masked texture tables
683 if (sidedef->midtexture) // masked midtexture
684 {
685 maskedtexture = true;
686 ds_p->maskedtexturecol = maskedtexturecol = lastopening - rw_x;
687 lastopening += rw_stopx - rw_x;
688 }
689 }
690
691 // calculate rw_offset (only needed for textured lines)
692 segtextured = midtexture | toptexture | bottomtexture | maskedtexture;
693
694 if (segtextured)
695 {
696 offsetangle = rw_normalangle-rw_angle1;
697
698 if (offsetangle > ANG180)
699 offsetangle = 0-offsetangle;
700
701 if (offsetangle > ANG90)
702 offsetangle = ANG90;
703
704 sineval = finesine[offsetangle >>ANGLETOFINESHIFT];
705 rw_offset = FixedMul (hyp, sineval);
706
707 if (rw_normalangle-rw_angle1 < ANG180)
708 rw_offset = -rw_offset;
709
710 rw_offset += sidedef->textureoffset + curline->offset;
711
712 rw_centerangle = ANG90 + viewangle - rw_normalangle;
713
714 // calculate light table
715 // use different light tables
716 // for horizontal / vertical / diagonal
717 // OPTIMIZE: get rid of LIGHTSEGSHIFT globally
718 if (!fixedcolormap)
719 {
720 int lightnum = (frontsector->lightlevel >> LIGHTSEGSHIFT)+extralight;
721
722 /* cph - ...what is this for? adding contrast to rooms?
723 * It looks crap in outdoor areas */
724 if (fake_contrast) {
725 if (curline->v1->y == curline->v2->y)
726 lightnum--;
727 else if (curline->v1->x == curline->v2->x)
728 lightnum++;
729 }
730
731 if (lightnum < 0)
732 walllights = scalelight[0];
733 else if (lightnum >= LIGHTLEVELS)
734 walllights = scalelight[LIGHTLEVELS-1];
735 else
736 walllights = scalelight[lightnum];
737 }
738 }
739
740 // if a floor / ceiling plane is on the wrong side of the view
741 // plane, it is definitely invisible and doesn't need to be marked.
742
743 // killough 3/7/98: add deep water check
744 if (frontsector->heightsec == -1)
745 {
746 if (frontsector->floorheight >= viewz) // above view plane
747 markfloor = false;
748 if (frontsector->ceilingheight <= viewz &&
749 frontsector->ceilingpic != skyflatnum) // below view plane
750 markceiling = false;
751 }
752
753 // calculate incremental stepping values for texture edges
754 worldtop >>= 4;
755 worldbottom >>= 4;
756
757 topstep = -FixedMul (rw_scalestep, worldtop);
758 topfrac = (centeryfrac>>4) - FixedMul (worldtop, rw_scale);
759
760 bottomstep = -FixedMul (rw_scalestep,worldbottom);
761 bottomfrac = (centeryfrac>>4) - FixedMul (worldbottom, rw_scale);
762
763 if (backsector)
764 {
765 worldhigh >>= 4;
766 worldlow >>= 4;
767
768 if (worldhigh < worldtop)
769 {
770 pixhigh = (centeryfrac>>4) - FixedMul (worldhigh, rw_scale);
771 pixhighstep = -FixedMul (rw_scalestep,worldhigh);
772 }
773 if (worldlow > worldbottom)
774 {
775 pixlow = (centeryfrac>>4) - FixedMul (worldlow, rw_scale);
776 pixlowstep = -FixedMul (rw_scalestep,worldlow);
777 }
778 }
779
780 // render it
781 if (markceiling) {
782 if (ceilingplane) // killough 4/11/98: add NULL ptr checks
783 ceilingplane = R_CheckPlane (ceilingplane, rw_x, rw_stopx-1);
784 else
785 markceiling = 0;
786 }
787
788 if (markfloor) {
789 if (floorplane) // killough 4/11/98: add NULL ptr checks
790 /* cph 2003/04/18 - ceilingplane and floorplane might be the same
791 * visplane (e.g. if both skies); R_CheckPlane doesn't know about
792 * modifications to the plane that might happen in parallel with the check
793 * being made, so we have to override it and split them anyway if that is
794 * a possibility, otherwise the floor marking would overwrite the ceiling
795 * marking, resulting in HOM. */
796 if (markceiling && ceilingplane == floorplane)
797 floorplane = R_DupPlane (floorplane, rw_x, rw_stopx-1);
798 else
799 floorplane = R_CheckPlane (floorplane, rw_x, rw_stopx-1);
800 else
801 markfloor = 0;
802 }
803
804 didsolidcol = 0;
805 R_RenderSegLoop();
806
807 /* cph - if a column was made solid by this wall, we _must_ save full clipping info */
808 if (backsector && didsolidcol) {
809 if (!(ds_p->silhouette & SIL_BOTTOM)) {
810 ds_p->silhouette |= SIL_BOTTOM;
811 ds_p->bsilheight = backsector->floorheight;
812 }
813 if (!(ds_p->silhouette & SIL_TOP)) {
814 ds_p->silhouette |= SIL_TOP;
815 ds_p->tsilheight = backsector->ceilingheight;
816 }
817 }
818
819 // save sprite clipping info
820 if ((ds_p->silhouette & SIL_TOP || maskedtexture) && !ds_p->sprtopclip)
821 {
822 memcpy (lastopening, ceilingclip+start, 2*(rw_stopx-start));
823 ds_p->sprtopclip = lastopening - start;
824 lastopening += rw_stopx - start;
825 }
826 if ((ds_p->silhouette & SIL_BOTTOM || maskedtexture) && !ds_p->sprbottomclip)
827 {
828 memcpy (lastopening, floorclip+start, 2*(rw_stopx-start));
829 ds_p->sprbottomclip = lastopening - start;
830 lastopening += rw_stopx - start;
831 }
832 if (maskedtexture && !(ds_p->silhouette & SIL_TOP))
833 {
834 ds_p->silhouette |= SIL_TOP;
835 ds_p->tsilheight = INT_MIN;
836 }
837 if (maskedtexture && !(ds_p->silhouette & SIL_BOTTOM))
838 {
839 ds_p->silhouette |= SIL_BOTTOM;
840 ds_p->bsilheight = INT_MAX;
841 }
842 ds_p++;
843}
diff --git a/apps/plugins/doom/r_segs.h b/apps/plugins/doom/r_segs.h
new file mode 100644
index 0000000000..bbf56b6d6f
--- /dev/null
+++ b/apps/plugins/doom/r_segs.h
@@ -0,0 +1,42 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION:
28 * Refresh module, drawing LineSegs from BSP.
29 *
30 *-----------------------------------------------------------------------------*/
31
32#ifndef __R_SEGS__
33#define __R_SEGS__
34
35#ifdef __GNUG__
36#pragma interface
37#endif
38
39void R_RenderMaskedSegRange(drawseg_t *ds, int x1, int x2);
40void R_StoreWallRange(int start, int stop);
41
42#endif
diff --git a/apps/plugins/doom/r_sky.c b/apps/plugins/doom/r_sky.c
new file mode 100644
index 0000000000..2ec2603972
--- /dev/null
+++ b/apps/plugins/doom/r_sky.c
@@ -0,0 +1,53 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION:
28 * Sky rendering. The DOOM sky is a texture map like any
29 * wall, wrapping around. A 1024 columns equal 360 degrees.
30 * The default sky map is 256 columns and repeats 4 times
31 * on a 320 screen?
32 *
33 *-----------------------------------------------------------------------------*/
34
35#ifdef __GNUG__
36#pragma implementation "r_sky.h"
37#endif
38#include "r_sky.h"
39//
40// sky mapping
41//
42int skyflatnum;
43int skytexture;
44int skytexturemid;
45
46//
47// R_InitSkyMap
48// Called whenever the view size changes.
49//
50void R_InitSkyMap (void)
51{
52 skytexturemid = 100*FRACUNIT;
53}
diff --git a/apps/plugins/doom/r_sky.h b/apps/plugins/doom/r_sky.h
new file mode 100644
index 0000000000..1b817c1a44
--- /dev/null
+++ b/apps/plugins/doom/r_sky.h
@@ -0,0 +1,53 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION:
28 * Sky rendering.
29 *
30 *-----------------------------------------------------------------------------*/
31
32#ifndef __R_SKY__
33#define __R_SKY__
34
35#include "m_fixed.h"
36
37#ifdef __GNUG__
38#pragma interface
39#endif
40
41/* SKY, store the number for name. */
42#define SKYFLATNAME "F_SKY1"
43
44/* The sky map is 256*128*4 maps. */
45#define ANGLETOSKYSHIFT 22
46
47extern int skytexture;
48extern int skytexturemid;
49
50/* Called whenever the view size changes. */
51void R_InitSkyMap(void);
52
53#endif
diff --git a/apps/plugins/doom/r_state.h b/apps/plugins/doom/r_state.h
new file mode 100644
index 0000000000..2e11bb50c5
--- /dev/null
+++ b/apps/plugins/doom/r_state.h
@@ -0,0 +1,140 @@
1// Emacs style mode select -*- C++ -*-
2//-----------------------------------------------------------------------------
3//
4// $Id$
5//
6// Copyright (C) 1993-1996 by id Software, Inc.
7//
8// This program is free software; you can redistribute it and/or
9// modify it under the terms of the GNU General Public License
10// as published by the Free Software Foundation; either version 2
11// of the License, or (at your option) any later version.
12//
13// This program is distributed in the hope that it will be useful,
14// but WITHOUT ANY WARRANTY; without even the implied warranty of
15// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16// GNU General Public License for more details.
17//
18// DESCRIPTION:
19// Refresh/render internal state variables (global).
20//
21//-----------------------------------------------------------------------------
22
23
24#ifndef __R_STATE__
25#define __R_STATE__
26
27// Need data structure definitions.
28#include "d_player.h"
29#include "r_data.h"
30
31
32
33#ifdef __GNUG__
34#pragma interface
35#endif
36
37
38
39//
40// Refresh internal data structures,
41// for rendering.
42//
43
44// needed for texture pegging
45extern fixed_t* textureheight;
46
47// needed for pre rendering (fracs)
48extern fixed_t* spritewidth;
49
50extern fixed_t* spriteoffset;
51extern fixed_t* spritetopoffset;
52
53extern int viewwidth;
54extern int scaledviewwidth;
55extern int viewheight;
56
57extern int firstflat;
58
59// for global animation
60extern int* flattranslation;
61extern int* texturetranslation;
62
63
64// Sprite....
65extern int firstspritelump;
66extern int lastspritelump;
67extern int numspritelumps;
68
69
70
71//
72// Lookup tables for map data.
73//
74extern int numsprites;
75extern spritedef_t* sprites;
76
77extern int numvertexes;
78extern vertex_t* vertexes;
79
80extern int numsegs;
81extern seg_t* segs;
82
83extern int numsectors;
84extern sector_t* sectors;
85
86extern int numsubsectors;
87extern subsector_t* subsectors;
88
89extern int numnodes;
90extern node_t* nodes;
91
92extern int numlines;
93extern line_t* lines;
94
95extern int numsides;
96extern side_t* sides;
97
98
99//
100// POV data.
101//
102extern fixed_t viewx;
103extern fixed_t viewy;
104extern fixed_t viewz;
105
106extern angle_t viewangle;
107extern player_t* viewplayer;
108
109
110// ?
111extern angle_t clipangle;
112
113extern int viewangletox[FINEANGLES/2];
114extern angle_t xtoviewangle[SCREENWIDTH+1];
115//extern fixed_t finetangent[FINEANGLES/2];
116
117extern fixed_t rw_distance;
118extern angle_t rw_normalangle;
119
120
121
122// angle to line origin
123extern int rw_angle1;
124
125// Segs count?
126extern int sscount;
127
128extern visplane_t* floorplane;
129extern visplane_t* ceilingplane;
130
131
132#endif
133//-----------------------------------------------------------------------------
134//
135// $Log$
136// Revision 1.1 2006/03/28 15:44:01 dave
137// Patch #2969 - Doom! Currently only working on the H300.
138//
139//
140//-----------------------------------------------------------------------------
diff --git a/apps/plugins/doom/r_things.c b/apps/plugins/doom/r_things.c
new file mode 100644
index 0000000000..2e1f72e34c
--- /dev/null
+++ b/apps/plugins/doom/r_things.c
@@ -0,0 +1,976 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION:
28 * Refresh of things, i.e. objects represented by sprites.
29 *
30 *-----------------------------------------------------------------------------*/
31
32#include "doomdef.h"
33#include "m_swap.h"
34
35#include "doomstat.h"
36#include "w_wad.h"
37#include "r_main.h"
38#include "r_bsp.h"
39#include "r_segs.h"
40#include "r_draw.h"
41#include "r_things.h"
42#include "i_system.h"
43//#include "lprintf.h"
44#include "rockmacros.h"
45
46#define MINZ (FRACUNIT*4)
47#define BASEYCENTER 100
48
49typedef struct {
50 int x1;
51 int x2;
52 int column;
53 int topclip;
54 int bottomclip;
55} maskdraw_t;
56
57//
58// Sprite rotation 0 is facing the viewer,
59// rotation 1 is one angle turn CLOCKWISE around the axis.
60// This is not the same as the angle,
61// which increases counter clockwise (protractor).
62// There was a lot of stuff grabbed wrong, so I changed it...
63//
64fixed_t pspritescale;
65fixed_t pspriteiscale;
66
67static lighttable_t** spritelights;
68
69// constant arrays
70// used for psprite clipping and initializing clipping
71short negonearray[SCREENWIDTH];
72short screenheightarray[SCREENWIDTH];
73
74
75//
76// INITIALIZATION FUNCTIONS
77//
78
79// variables used to look up and range check thing_t sprites patches
80
81spritedef_t* sprites;
82int numsprites;
83
84#define MAX_SPRITE_FRAMES 29 /* Macroized -- killough 1/25/98 */
85
86static spriteframe_t sprtemp[MAX_SPRITE_FRAMES];
87static int maxframe;
88
89//
90// R_InstallSpriteLump
91// Local function for R_InitSprites.
92//
93
94static void R_InstallSpriteLump(int lump, unsigned frame,
95 unsigned rotation, boolean flipped)
96{
97
98 if (frame >= MAX_SPRITE_FRAMES || rotation > 8)
99 I_Error("R_InstallSpriteLump: Bad frame characters in lump %i", lump);
100
101 if ((int)frame > maxframe)
102 maxframe = frame;
103
104 if (rotation == 0)
105 { // the lump should be used for all rotations
106 int r;
107 for (r=0 ; r<8 ; r++)
108 if (sprtemp[frame].lump[r]==-1)
109 {
110 sprtemp[frame].lump[r] = lump - firstspritelump;
111 sprtemp[frame].flip[r] = (byte) flipped;
112 sprtemp[frame].rotate = false; //jff 4/24/98 if any subbed, rotless
113 }
114 return;
115 }
116
117 // the lump is only used for one rotation
118
119 if (sprtemp[frame].lump[--rotation] == -1)
120 {
121 sprtemp[frame].lump[rotation] = lump - firstspritelump;
122 sprtemp[frame].flip[rotation] = (byte) flipped;
123 sprtemp[frame].rotate = true; //jff 4/24/98 only change if rot used
124 }
125}
126
127//
128// R_InitSpriteDefs
129// Pass a null terminated list of sprite names
130// (4 chars exactly) to be used.
131//
132// Builds the sprite rotation matrixes to account
133// for horizontally flipped sprites.
134//
135// Will report an error if the lumps are inconsistent.
136// Only called at startup.
137//
138// Sprite lump names are 4 characters for the actor,
139// a letter for the frame, and a number for the rotation.
140//
141// A sprite that is flippable will have an additional
142// letter/number appended.
143//
144// The rotation character can be 0 to signify no rotations.
145//
146// 1/25/98, 1/31/98 killough : Rewritten for performance
147//
148// Empirically verified to have excellent hash
149// properties across standard Doom sprites:
150
151#define R_SpriteNameHash(s) ((unsigned)((s)[0]-((s)[1]*3-(s)[3]*2-(s)[2])*2))
152
153void R_InitSpriteDefs(const char * const * namelist)
154{
155 size_t numentries = lastspritelump-firstspritelump+1;
156 struct { int index, next; } *hash;
157 int i;
158
159 if (!numentries || !*namelist)
160 return;
161
162 // count the number of sprite names
163 for (i=0; namelist[i]; i++)
164 ;
165
166 numsprites = i;
167
168 sprites = Z_Malloc(numsprites *sizeof(*sprites), PU_STATIC, NULL);
169
170 // Create hash table based on just the first four letters of each sprite
171 // killough 1/31/98
172
173 hash = malloc(sizeof(*hash)*numentries); // allocate hash table
174
175 for (i=0; (size_t)i<numentries; i++) // initialize hash table as empty
176 hash[i].index = -1;
177
178 for (i=0; (size_t)i<numentries; i++) // Prepend each sprite to hash chain
179 { // prepend so that later ones win
180 int j = R_SpriteNameHash(lumpinfo[i+firstspritelump].name) % numentries;
181 hash[i].next = hash[j].index;
182 hash[j].index = i;
183 }
184
185 // scan all the lump names for each of the names,
186 // noting the highest frame letter.
187
188 for (i=0 ; i<numsprites ; i++)
189 {
190 const char *spritename = namelist[i];
191 int j = hash[R_SpriteNameHash(spritename) % numentries].index;
192
193 if (j >= 0)
194 {
195 memset(sprtemp, -1, sizeof(sprtemp));
196 maxframe = -1;
197 do
198 {
199 register lumpinfo_t *lump = lumpinfo + j + firstspritelump;
200
201 // Fast portable comparison -- killough
202 // (using int pointer cast is nonportable):
203
204 if (!((lump->name[0] ^ spritename[0]) |
205 (lump->name[1] ^ spritename[1]) |
206 (lump->name[2] ^ spritename[2]) |
207 (lump->name[3] ^ spritename[3])))
208 {
209 R_InstallSpriteLump(j+firstspritelump,
210 lump->name[4] - 'A',
211 lump->name[5] - '0',
212 false);
213 if (lump->name[6])
214 R_InstallSpriteLump(j+firstspritelump,
215 lump->name[6] - 'A',
216 lump->name[7] - '0',
217 true);
218 }
219 }
220 while ((j = hash[j].next) >= 0);
221
222 // check the frames that were found for completeness
223 if ((sprites[i].numframes = ++maxframe)) // killough 1/31/98
224 {
225 int frame;
226 for (frame = 0; frame < maxframe; frame++)
227 switch ((int) sprtemp[frame].rotate)
228 {
229 case -1:
230 // no rotations were found for that frame at all
231 I_Error ("R_InitSprites: No patches found "
232 "for %.8s frame %c", namelist[i], frame+'A');
233 break;
234
235 case 0:
236 // only the first rotation is needed
237 break;
238
239 case 1:
240 // must have all 8 frames
241 {
242 int rotation;
243 for (rotation=0 ; rotation<8 ; rotation++)
244 if (sprtemp[frame].lump[rotation] == -1)
245 I_Error ("R_InitSprites: Sprite %.8s frame %c "
246 "is missing rotations",
247 namelist[i], frame+'A');
248 break;
249 }
250 }
251 // allocate space for the frames present and copy sprtemp to it
252 sprites[i].spriteframes =
253 Z_Malloc (maxframe * sizeof(spriteframe_t), PU_STATIC, NULL);
254 memcpy (sprites[i].spriteframes, sprtemp,
255 maxframe*sizeof(spriteframe_t));
256 }
257 }
258 }
259 free(hash); // free hash table
260}
261
262//
263// GAME FUNCTIONS
264//
265
266static vissprite_t *vissprites, **vissprite_ptrs; // killough
267static size_t num_vissprite, num_vissprite_alloc, num_vissprite_ptrs;
268
269
270//
271// R_InitSprites
272// Called at program start.
273//
274void R_InitSprites(const char * const *namelist)
275{
276 int i;
277
278 for (i=0 ; i<SCREENWIDTH ; i++)
279 negonearray[i] = -1;
280 R_InitSpriteDefs (namelist);
281}
282
283void R_ClearSprites (void)
284{
285 num_vissprite = 0; // killough
286}
287
288//
289// R_NewVisSprite
290//
291
292vissprite_t *R_NewVisSprite(void)
293{
294 if (num_vissprite >= num_vissprite_alloc) // killough
295 {
296 num_vissprite_alloc = num_vissprite_alloc ? num_vissprite_alloc*2 : 128;
297 vissprites = realloc(vissprites,num_vissprite_alloc*sizeof(*vissprites));
298 }
299 return vissprites + num_vissprite++;
300}
301
302//
303// R_DrawMaskedColumn
304// Used for sprites and masked mid textures.
305// Masked means: partly transparent, i.e. stored
306// in posts/runs of opaque pixels.
307//
308
309short* mfloorclip;
310short* mceilingclip;
311fixed_t spryscale;
312fixed_t sprtopscreen;
313
314void R_DrawMaskedColumn(const column_t *column)
315{
316 int topscreen;
317 int bottomscreen;
318 fixed_t basetexturemid = dc_texturemid;
319
320 dc_texheight = 0; // killough 11/98
321 while (column->topdelta != 0xff)
322 {
323 // calculate unclipped screen coordinates for post
324 topscreen = sprtopscreen + spryscale*column->topdelta;
325 bottomscreen = topscreen + spryscale*column->length;
326
327 dc_yl = (topscreen+FRACUNIT-1)>>FRACBITS;
328 dc_yh = (bottomscreen-1)>>FRACBITS;
329
330 if (dc_yh >= mfloorclip[dc_x])
331 dc_yh = mfloorclip[dc_x]-1;
332
333 if (dc_yl <= mceilingclip[dc_x])
334 dc_yl = mceilingclip[dc_x]+1;
335
336 // killough 3/2/98, 3/27/98: Failsafe against overflow/crash:
337 if (dc_yl <= dc_yh && dc_yh < viewheight)
338 {
339 dc_source = (byte *)column + 3;
340 dc_texturemid = basetexturemid - (column->topdelta<<FRACBITS);
341
342 // Drawn by either R_DrawColumn
343 // or (SHADOW) R_DrawFuzzColumn.
344 colfunc ();
345 }
346 column = (const column_t *)( (byte *)column + column->length + 4);
347 }
348 dc_texturemid = basetexturemid;
349}
350
351//
352// R_DrawVisSprite
353// mfloorclip and mceilingclip should also be set.
354//
355// CPhipps - new wad lump handling, *'s to const*'s
356void R_DrawVisSprite(vissprite_t *vis, int x1, int x2)
357{
358 (void)x1;
359 (void)x2;
360 const column_t *column;
361 int texturecolumn;
362 fixed_t frac;
363 const patch_t *patch = W_CacheLumpNum (vis->patch+firstspritelump);
364
365 dc_colormap = vis->colormap;
366
367 // killough 4/11/98: rearrange and handle translucent sprites
368 // mixed with translucent/non-translucenct 2s normals
369
370 if (!dc_colormap) // NULL colormap = shadow draw
371 colfunc = R_DrawFuzzColumn; // killough 3/14/98
372 else
373 if (vis->mobjflags & MF_TRANSLATION)
374 {
375 colfunc = R_DrawTranslatedColumn;
376 dc_translation = translationtables - 256 +
377 ((vis->mobjflags & MF_TRANSLATION) >> (MF_TRANSSHIFT-8) );
378 }
379 else
380 if (vis->mobjflags & MF_TRANSLUCENT && general_translucency) // phares
381 {
382 colfunc = R_DrawTLColumn;
383 tranmap = main_tranmap; // killough 4/11/98
384 }
385 else
386 colfunc = R_DrawColumn; // killough 3/14/98, 4/11/98
387
388
389 // proff 11/06/98: Changed for high-res
390 dc_iscale = D_abs(vis->xiscale);
391 dc_texturemid = vis->texturemid;
392 frac = vis->startfrac;
393 spryscale = vis->scale;
394 sprtopscreen = centeryfrac - FixedMul(dc_texturemid,spryscale);
395
396 for (dc_x=vis->x1 ; dc_x<=vis->x2 ; dc_x++, frac += vis->xiscale)
397 {
398 texturecolumn = frac>>FRACBITS;
399
400#ifdef RANGECHECK
401 if (texturecolumn < 0 || texturecolumn >= SHORT(patch->width))
402 I_Error ("R_DrawSpriteRange: Bad texturecolumn");
403#endif
404
405 column = (const column_t *)((const byte *) patch +
406 LONG(patch->columnofs[texturecolumn]));
407 R_DrawMaskedColumn (column);
408 }
409 colfunc = R_DrawColumn; // killough 3/14/98
410 W_UnlockLumpNum(vis->patch+firstspritelump); // cph - release lump
411}
412
413//
414// R_ProjectSprite
415// Generates a vissprite for a thing if it might be visible.
416//
417
418void R_ProjectSprite (mobj_t* thing)
419{
420 fixed_t gzt; // killough 3/27/98
421 fixed_t tx;
422 fixed_t xscale;
423 int x1;
424 int x2;
425 spritedef_t *sprdef;
426 spriteframe_t *sprframe;
427 int lump;
428 boolean flip;
429 vissprite_t *vis;
430#ifndef GL_DOOM
431 fixed_t iscale;
432#endif
433 int heightsec; // killough 3/27/98
434
435 // transform the origin point
436 fixed_t tr_x = thing->x - viewx;
437 fixed_t tr_y = thing->y - viewy;
438
439 fixed_t gxt = FixedMul(tr_x,viewcos);
440 fixed_t gyt = -FixedMul(tr_y,viewsin);
441
442 fixed_t tz = gxt-gyt;
443
444 // thing is behind view plane?
445 if (tz < MINZ)
446 return;
447
448 xscale = FixedDiv(projection, tz);
449
450 gxt = -FixedMul(tr_x,viewsin);
451 gyt = FixedMul(tr_y,viewcos);
452 tx = -(gyt+gxt);
453
454 // too far off the side?
455 if (D_abs(tx)>(tz<<2))
456 return;
457
458 // decide which patch to use for sprite relative to player
459#ifdef RANGECHECK
460 if ((unsigned) thing->sprite >= (unsigned)numsprites)
461 I_Error ("R_ProjectSprite: Invalid sprite number %i", thing->sprite);
462#endif
463
464 sprdef = &sprites[thing->sprite];
465
466#ifdef RANGECHECK
467 if ((thing->frame&FF_FRAMEMASK) >= sprdef->numframes)
468 I_Error ("R_ProjectSprite: Invalid sprite frame %i : %i", thing->sprite,
469 thing->frame);
470#endif
471
472 sprframe = &sprdef->spriteframes[thing->frame & FF_FRAMEMASK];
473
474 if (sprframe->rotate)
475 {
476 // choose a different rotation based on player view
477 angle_t ang = R_PointToAngle(thing->x, thing->y);
478 unsigned rot = (ang-thing->angle+(unsigned)(ANG45/2)*9)>>29;
479 lump = sprframe->lump[rot];
480 flip = (boolean) sprframe->flip[rot];
481 }
482 else
483 {
484 // use single rotation for all views
485 lump = sprframe->lump[0];
486 flip = (boolean) sprframe->flip[0];
487 }
488
489 /* calculate edges of the shape
490 * cph 2003/08/1 - fraggle points out that this offset must be flipped if the
491 * sprite is flipped; e.g. FreeDoom imp is messed up by this. */
492 tx -= flip ? spritewidth[lump] - spriteoffset[lump] : spriteoffset[lump];
493 x1 = (centerxfrac + FixedMul(tx,xscale)) >>FRACBITS;
494
495 // off the right side?
496 if (x1 > viewwidth)
497 return;
498
499 tx += spritewidth[lump];
500 x2 = ((centerxfrac + FixedMul (tx,xscale) ) >>FRACBITS) - 1;
501
502 // off the left side
503 if (x2 < 0)
504 return;
505
506 gzt = thing->z + spritetopoffset[lump];
507
508 // killough 4/9/98: clip things which are out of view due to height
509 if (thing->z > viewz + FixedDiv(centeryfrac, xscale) ||
510 gzt < viewz - FixedDiv(centeryfrac-viewheight, xscale))
511 return;
512
513 // killough 3/27/98: exclude things totally separated
514 // from the viewer, by either water or fake ceilings
515 // killough 4/11/98: improve sprite clipping for underwater/fake ceilings
516
517 heightsec = thing->subsector->sector->heightsec;
518
519 if (heightsec != -1) // only clip things which are in special sectors
520 {
521 int phs = viewplayer->mo->subsector->sector->heightsec;
522 if (phs != -1 && viewz < sectors[phs].floorheight ?
523 thing->z >= sectors[heightsec].floorheight :
524 gzt < sectors[heightsec].floorheight)
525 return;
526 if (phs != -1 && viewz > sectors[phs].ceilingheight ?
527 gzt < sectors[heightsec].ceilingheight &&
528 viewz >= sectors[heightsec].ceilingheight :
529 thing->z >= sectors[heightsec].ceilingheight)
530 return;
531 }
532
533 // store information in a vissprite
534 vis = R_NewVisSprite ();
535
536 // killough 3/27/98: save sector for special clipping later
537 vis->heightsec = heightsec;
538
539 vis->mobjflags = thing->flags;
540 // proff 11/06/98: Changed for high-res
541 vis->scale = xscale;
542 vis->gx = thing->x;
543 vis->gy = thing->y;
544 vis->gz = thing->z;
545 vis->gzt = gzt; // killough 3/27/98
546 vis->texturemid = vis->gzt - viewz;
547 vis->x1 = x1 < 0 ? 0 : x1;
548 vis->x2 = x2 >= viewwidth ? viewwidth-1 : x2;
549 iscale = FixedDiv (FRACUNIT, xscale);
550
551 if (flip)
552 {
553 vis->startfrac = spritewidth[lump]-1;
554 vis->xiscale = -iscale;
555 }
556 else
557 {
558 vis->startfrac = 0;
559 vis->xiscale = iscale;
560 }
561
562 if (vis->x1 > x1)
563 vis->startfrac += vis->xiscale*(vis->x1-x1);
564 vis->patch = lump;
565
566 // get light level
567 if (thing->flags & MF_SHADOW)
568 vis->colormap = NULL; // shadow draw
569 else if (fixedcolormap)
570 vis->colormap = fixedcolormap; // fixed map
571 else if (thing->frame & FF_FULLBRIGHT)
572 vis->colormap = fullcolormap; // full bright // killough 3/20/98
573 else
574 { // diminished light
575 int index = xscale>>LIGHTSCALESHIFT;
576 if (index >= MAXLIGHTSCALE)
577 index = MAXLIGHTSCALE-1;
578 vis->colormap = spritelights[index];
579 }
580}
581
582//
583// R_AddSprites
584// During BSP traversal, this adds sprites by sector.
585//
586// killough 9/18/98: add lightlevel as parameter, fixing underwater lighting
587void R_AddSprites(subsector_t* subsec, int lightlevel)
588{
589 sector_t* sec=subsec->sector;
590 mobj_t *thing;
591 int lightnum;
592
593 // BSP is traversed by subsector.
594 // A sector might have been split into several
595 // subsectors during BSP building.
596 // Thus we check whether its already added.
597
598 if (sec->validcount == validcount)
599 return;
600
601 // Well, now it will be done.
602 sec->validcount = validcount;
603
604 lightnum = (lightlevel >> LIGHTSEGSHIFT)+extralight;
605
606 if (lightnum < 0)
607 spritelights = scalelight[0];
608 else if (lightnum >= LIGHTLEVELS)
609 spritelights = scalelight[LIGHTLEVELS-1];
610 else
611 spritelights = scalelight[lightnum];
612
613 // Handle all things in sector.
614
615 for (thing = sec->thinglist; thing; thing = thing->snext)
616 R_ProjectSprite(thing);
617}
618
619//
620// R_DrawPSprite
621//
622
623void R_DrawPSprite (pspdef_t *psp)
624{
625 fixed_t tx;
626 int x1, x2;
627 spritedef_t *sprdef;
628 spriteframe_t *sprframe;
629 int lump;
630 boolean flip;
631 vissprite_t *vis;
632 vissprite_t avis;
633
634 // decide which patch to use
635
636#ifdef RANGECHECK
637 if ( (unsigned)psp->state->sprite >= (unsigned)numsprites)
638 I_Error ("R_ProjectSprite: Invalid sprite number %i", psp->state->sprite);
639#endif
640
641 sprdef = &sprites[psp->state->sprite];
642
643#ifdef RANGECHECK
644 if ( (psp->state->frame & FF_FRAMEMASK) >= sprdef->numframes)
645 I_Error ("R_ProjectSprite: Invalid sprite frame %i : %li",
646 psp->state->sprite, psp->state->frame);
647#endif
648
649 sprframe = &sprdef->spriteframes[psp->state->frame & FF_FRAMEMASK];
650
651 lump = sprframe->lump[0];
652 flip = (boolean) sprframe->flip[0];
653
654 // calculate edges of the shape
655 tx = psp->sx-160*FRACUNIT;
656
657 tx -= spriteoffset[lump];
658 x1 = (centerxfrac + FixedMul (tx,pspritescale))>>FRACBITS;
659
660 // off the right side
661 if (x1 > viewwidth)
662 return;
663
664 tx += spritewidth[lump];
665 x2 = ((centerxfrac + FixedMul (tx, pspritescale) ) >>FRACBITS) - 1;
666
667 // off the left side
668 if (x2 < 0)
669 return;
670
671 // store information in a vissprite
672 vis = &avis;
673 vis->mobjflags = 0;
674 // killough 12/98: fix psprite positioning problem
675 vis->texturemid = (BASEYCENTER<<FRACBITS) /* + FRACUNIT/2 */ -
676 (psp->sy-spritetopoffset[lump]);
677 vis->x1 = x1 < 0 ? 0 : x1;
678 vis->x2 = x2 >= viewwidth ? viewwidth-1 : x2;
679 // proff 11/06/98: Added for high-res
680 vis->scale = pspritescale;
681
682 if (flip)
683 {
684 vis->xiscale = -pspriteiscale;
685 vis->startfrac = spritewidth[lump]-1;
686 }
687 else
688 {
689 vis->xiscale = pspriteiscale;
690 vis->startfrac = 0;
691 }
692
693 if (vis->x1 > x1)
694 vis->startfrac += vis->xiscale*(vis->x1-x1);
695
696 vis->patch = lump;
697
698 if (viewplayer->powers[pw_invisibility] > 4*32
699 || viewplayer->powers[pw_invisibility] & 8)
700 vis->colormap = NULL; // shadow draw
701 else if (fixedcolormap)
702 vis->colormap = fixedcolormap; // fixed color
703 else if (psp->state->frame & FF_FULLBRIGHT)
704 vis->colormap = fullcolormap; // full bright // killough 3/20/98
705 else
706 vis->colormap = spritelights[MAXLIGHTSCALE-1]; // local light
707
708 R_DrawVisSprite(vis, vis->x1, vis->x2);
709}
710
711//
712// R_DrawPlayerSprites
713//
714
715void R_DrawPlayerSprites(void)
716{
717 int i, lightnum;
718 pspdef_t *psp;
719
720 // get light level
721 lightnum = (viewplayer->mo->subsector->sector->lightlevel >> LIGHTSEGSHIFT)
722 + extralight;
723
724 if (lightnum < 0)
725 spritelights = scalelight[0];
726 else if (lightnum >= LIGHTLEVELS)
727 spritelights = scalelight[LIGHTLEVELS-1];
728 else
729 spritelights = scalelight[lightnum];
730
731 // clip to screen bounds
732 mfloorclip = screenheightarray;
733 mceilingclip = negonearray;
734
735 // add all active psprites
736 for (i=0, psp=viewplayer->psprites; i<NUMPSPRITES; i++,psp++)
737 if (psp->state)
738 R_DrawPSprite (psp);
739}
740
741//
742// R_SortVisSprites
743//
744// Rewritten by Lee Killough to avoid using unnecessary
745// linked lists, and to use faster sorting algorithm.
746//
747
748#define bcopyp(d, s, n) memcpy(d, s, (n) * sizeof(void *))
749
750// killough 9/2/98: merge sort
751
752static void msort(vissprite_t **s, vissprite_t **t, int n)
753{
754 if (n >= 16)
755 {
756 int n1 = n/2, n2 = n - n1;
757 vissprite_t **s1 = s, **s2 = s + n1, **d = t;
758
759 msort(s1, t, n1);
760 msort(s2, t, n2);
761
762 while ((*s1)->scale > (*s2)->scale ?
763 (*d++ = *s1++, --n1) : (*d++ = *s2++, --n2));
764
765 if (n2)
766 bcopyp(d, s2, n2);
767 else
768 bcopyp(d, s1, n1);
769
770 bcopyp(s, t, n);
771 }
772 else
773 {
774 int i;
775 for (i = 1; i < n; i++)
776 {
777 vissprite_t *temp = s[i];
778 if (s[i-1]->scale < temp->scale)
779 {
780 int j = i;
781 while ((s[j] = s[j-1])->scale < temp->scale && --j);
782 s[j] = temp;
783 }
784 }
785 }
786}
787
788void R_SortVisSprites (void)
789{
790 if (num_vissprite)
791 {
792 int i = num_vissprite;
793
794 // If we need to allocate more pointers for the vissprites,
795 // allocate as many as were allocated for sprites -- killough
796 // killough 9/22/98: allocate twice as many
797
798 if (num_vissprite_ptrs < num_vissprite*2)
799 {
800 free(vissprite_ptrs); // better than realloc -- no preserving needed
801 vissprite_ptrs = malloc((num_vissprite_ptrs = num_vissprite_alloc*2)
802 * sizeof *vissprite_ptrs);
803 }
804
805 while (--i>=0)
806 vissprite_ptrs[i] = vissprites+i;
807
808 // killough 9/22/98: replace qsort with merge sort, since the keys
809 // are roughly in order to begin with, due to BSP rendering.
810
811 msort(vissprite_ptrs, vissprite_ptrs + num_vissprite, num_vissprite);
812 }
813}
814
815//
816// R_DrawSprite
817//
818
819void R_DrawSprite (vissprite_t* spr)
820{
821 drawseg_t *ds;
822 short clipbot[SCREENWIDTH]; // killough 2/8/98:
823 short cliptop[SCREENWIDTH]; // change to MAX_*
824 int x;
825 int r1;
826 int r2;
827 fixed_t scale;
828 fixed_t lowscale;
829
830 for (x = spr->x1 ; x<=spr->x2 ; x++)
831 clipbot[x] = cliptop[x] = -2;
832
833 // Scan drawsegs from end to start for obscuring segs.
834 // The first drawseg that has a greater scale is the clip seg.
835
836 // Modified by Lee Killough:
837 // (pointer check was originally nonportable
838 // and buggy, by going past LEFT end of array):
839
840 // for (ds=ds_p-1 ; ds >= drawsegs ; ds--) old buggy code
841
842 for (ds=ds_p ; ds-- > drawsegs ; ) // new -- killough
843 { // determine if the drawseg obscures the sprite
844 if (ds->x1 > spr->x2 || ds->x2 < spr->x1 ||
845 (!ds->silhouette && !ds->maskedtexturecol))
846 continue; // does not cover sprite
847
848 r1 = ds->x1 < spr->x1 ? spr->x1 : ds->x1;
849 r2 = ds->x2 > spr->x2 ? spr->x2 : ds->x2;
850
851 if (ds->scale1 > ds->scale2)
852 {
853 lowscale = ds->scale2;
854 scale = ds->scale1;
855 }
856 else
857 {
858 lowscale = ds->scale1;
859 scale = ds->scale2;
860 }
861
862 if (scale < spr->scale || (lowscale < spr->scale &&
863 !R_PointOnSegSide (spr->gx, spr->gy, ds->curline)))
864 {
865 if (ds->maskedtexturecol) // masked mid texture?
866 R_RenderMaskedSegRange(ds, r1, r2);
867 continue; // seg is behind sprite
868 }
869
870 // clip this piece of the sprite
871 // killough 3/27/98: optimized and made much shorter
872
873 if (ds->silhouette&SIL_BOTTOM && spr->gz < ds->bsilheight) //bottom sil
874 for (x=r1 ; x<=r2 ; x++)
875 if (clipbot[x] == -2)
876 clipbot[x] = ds->sprbottomclip[x];
877
878 if (ds->silhouette&SIL_TOP && spr->gzt > ds->tsilheight) // top sil
879 for (x=r1 ; x<=r2 ; x++)
880 if (cliptop[x] == -2)
881 cliptop[x] = ds->sprtopclip[x];
882 }
883
884 // killough 3/27/98:
885 // Clip the sprite against deep water and/or fake ceilings.
886 // killough 4/9/98: optimize by adding mh
887 // killough 4/11/98: improve sprite clipping for underwater/fake ceilings
888 // killough 11/98: fix disappearing sprites
889
890 if (spr->heightsec != -1) // only things in specially marked sectors
891 {
892 fixed_t h,mh;
893 int phs = viewplayer->mo->subsector->sector->heightsec;
894 if ((mh = sectors[spr->heightsec].floorheight) > spr->gz &&
895 (h = centeryfrac - FixedMul(mh-=viewz, spr->scale)) >= 0 &&
896 (h >>= FRACBITS) < viewheight) {
897 if (mh <= 0 || (phs != -1 && viewz > sectors[phs].floorheight))
898 { // clip bottom
899 for (x=spr->x1 ; x<=spr->x2 ; x++)
900 if (clipbot[x] == -2 || h < clipbot[x])
901 clipbot[x] = h;
902 }
903 else // clip top
904 if (phs != -1 && viewz <= sectors[phs].floorheight) // killough 11/98
905 for (x=spr->x1 ; x<=spr->x2 ; x++)
906 if (cliptop[x] == -2 || h > cliptop[x])
907 cliptop[x] = h;
908 }
909
910 if ((mh = sectors[spr->heightsec].ceilingheight) < spr->gzt &&
911 (h = centeryfrac - FixedMul(mh-viewz, spr->scale)) >= 0 &&
912 (h >>= FRACBITS) < viewheight) {
913 if (phs != -1 && viewz >= sectors[phs].ceilingheight)
914 { // clip bottom
915 for (x=spr->x1 ; x<=spr->x2 ; x++)
916 if (clipbot[x] == -2 || h < clipbot[x])
917 clipbot[x] = h;
918 }
919 else // clip top
920 for (x=spr->x1 ; x<=spr->x2 ; x++)
921 if (cliptop[x] == -2 || h > cliptop[x])
922 cliptop[x] = h;
923 }
924 }
925 // killough 3/27/98: end special clipping for deep water / fake ceilings
926
927 // all clipping has been performed, so draw the sprite
928 // check for unclipped columns
929
930 for (x = spr->x1 ; x<=spr->x2 ; x++) {
931 if (clipbot[x] == -2)
932 clipbot[x] = viewheight;
933
934 if (cliptop[x] == -2)
935 cliptop[x] = -1;
936 }
937
938 mfloorclip = clipbot;
939 mceilingclip = cliptop;
940 R_DrawVisSprite (spr, spr->x1, spr->x2);
941}
942
943//
944// R_DrawMasked
945//
946
947void R_DrawMasked(void)
948{
949 int i;
950 drawseg_t *ds;
951
952 R_SortVisSprites();
953
954 // draw all vissprites back to front
955
956// rendered_vissprites = num_vissprite;
957 for (i = num_vissprite ;--i>=0; )
958 R_DrawSprite(vissprite_ptrs[i]); // killough
959
960 // render any remaining masked mid textures
961
962 // Modified by Lee Killough:
963 // (pointer check was originally nonportable
964 // and buggy, by going past LEFT end of array):
965
966 // for (ds=ds_p-1 ; ds >= drawsegs ; ds--) old buggy code
967
968 for (ds=ds_p ; ds-- > drawsegs ; ) // new -- killough
969 if (ds->maskedtexturecol)
970 R_RenderMaskedSegRange(ds, ds->x1, ds->x2);
971
972 // draw the psprites on top of everything
973 // but does not draw on side views
974 if (!viewangleoffset)
975 R_DrawPlayerSprites ();
976}
diff --git a/apps/plugins/doom/r_things.h b/apps/plugins/doom/r_things.h
new file mode 100644
index 0000000000..dc93e30d54
--- /dev/null
+++ b/apps/plugins/doom/r_things.h
@@ -0,0 +1,80 @@
1// Emacs style mode select -*- C++ -*-
2//-----------------------------------------------------------------------------
3//
4// $Id$
5//
6// Copyright (C) 1993-1996 by id Software, Inc.
7//
8// This program is free software; you can redistribute it and/or
9// modify it under the terms of the GNU General Public License
10// as published by the Free Software Foundation; either version 2
11// of the License, or (at your option) any later version.
12//
13// This program is distributed in the hope that it will be useful,
14// but WITHOUT ANY WARRANTY; without even the implied warranty of
15// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16// GNU General Public License for more details.
17//
18// DESCRIPTION:
19// Rendering of moving objects, sprites.
20//
21//-----------------------------------------------------------------------------
22
23
24#ifndef __R_THINGS__
25#define __R_THINGS__
26
27
28#ifdef __GNUG__
29#pragma interface
30#endif
31
32#define MAXVISSPRITES 128
33/*
34extern vissprite_t vissprites[MAXVISSPRITES];
35extern vissprite_t* vissprite_p;
36extern vissprite_t vsprsortedhead;*/
37
38// Constant arrays used for psprite clipping
39// and initializing clipping.
40extern short negonearray[SCREENWIDTH];
41extern short screenheightarray[SCREENWIDTH];
42
43// vars for R_DrawMaskedColumn
44extern short* mfloorclip;
45extern short* mceilingclip;
46extern fixed_t spryscale;
47extern fixed_t sprtopscreen;
48
49extern fixed_t pspritescale;
50extern fixed_t pspriteiscale;
51
52
53void R_DrawMaskedColumn (const column_t* column);
54
55
56void R_SortVisSprites (void);
57
58void R_AddSprites(subsector_t* subsec, int lightlevel);
59void R_AddPSprites (void);
60void R_DrawSprites (void);
61void R_InitSprites(const char * const * namelist);
62void R_ClearSprites (void);
63void R_DrawMasked (void);
64
65void
66R_ClipVisSprite
67( vissprite_t* vis,
68 int xl,
69 int xh );
70
71
72#endif
73//-----------------------------------------------------------------------------
74//
75// $Log$
76// Revision 1.1 2006/03/28 15:44:01 dave
77// Patch #2969 - Doom! Currently only working on the H300.
78//
79//
80//-----------------------------------------------------------------------------
diff --git a/apps/plugins/doom/rockdoom.c b/apps/plugins/doom/rockdoom.c
new file mode 100644
index 0000000000..ae994c1acd
--- /dev/null
+++ b/apps/plugins/doom/rockdoom.c
@@ -0,0 +1,706 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 *
9 * Copyright (C) 2005 Karl Kurbjun
10 *
11 * All files in this archive are subject to the GNU General Public License.
12 * See the file COPYING in the source tree root for full license agreement.
13 *
14 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
15 * KIND, either express or implied.
16 *
17 * H300 Port by Karl Kurbjun
18 * IPod port by Dave Chapman and Paul Louden
19 * Additional code contributed by Thom Johansen
20 * Based off work by: Digita Doom, IDoom, Prboom, lSDLDoom, LxDoom,
21 * MBF, Boom, DosDoom,
22 * and of course Original Doom by ID Software
23 * See: http://prboom.sourceforge.net/about.html for the history
24 *
25 *
26 ****************************************************************************/
27
28#include "d_main.h"
29#include "doomdef.h"
30#include "settings.h"
31#include "m_fixed.h"
32#include "m_argv.h"
33#include "m_misc.h"
34#include "g_game.h"
35#include "rockmacros.h"
36#include "doomstat.h"
37#include "i_system.h"
38
39PLUGIN_HEADER
40
41#ifdef USE_IRAM
42extern char iramcopy[];
43extern char iramstart[];
44extern char iramend[];
45extern char iedata[];
46extern char iend[];
47#endif
48
49extern boolean timingdemo, singledemo, demoplayback, fastdemo; // killough
50
51int filearray[9];
52int fpoint=1; // save 0 for closing
53
54int fileexists(const char * fname)
55{
56 int fd;
57 fd = open(fname,O_RDONLY);
58
59 if (fd>=0)
60 {
61 close(fd);
62 return 0;
63 }
64 return -1;
65}
66
67#ifndef SIMULATOR
68int my_open(const char *file, int flags)
69{
70 if(fpoint==8)
71 return -1;
72#undef open
73 filearray[fpoint]=rb->open(file, flags);
74
75 if(filearray[fpoint]<0)
76 return filearray[fpoint];
77
78 fpoint++;
79 return filearray[fpoint-1];
80}
81
82int my_close(int id)
83{
84 int i=0;
85 if(id<0)
86 return id;
87 while(filearray[i]!=id && i<8)
88 i++;
89
90 if(i==8)
91 {
92 printf("A requested FID did not exist!!!!");
93 return -9;
94 }
95#undef close
96 rb->close(id);
97
98 for(; i<fpoint-1; i++)
99 filearray[i]=filearray[i+1];
100
101 fpoint--;
102 return 0;
103}
104#endif
105struct plugin_api* rb;
106#define MAXARGVS 100
107
108// Here is a hacked up printf command to get the output from the game.
109int printf(const char *fmt, ...)
110{
111 static int p_xtpt;
112 char p_buf[50];
113 bool ok;
114 va_list ap;
115
116 va_start(ap, fmt);
117 ok = vsnprintf(p_buf,sizeof(p_buf), fmt, ap);
118 va_end(ap);
119
120 rb->lcd_putsxy(1,p_xtpt, (unsigned char *)p_buf);
121 rb->lcd_update();
122
123 p_xtpt+=8;
124 if(p_xtpt>LCD_HEIGHT-8)
125 {
126 p_xtpt=0;
127 rb->lcd_clear_display();
128 }
129 return 1;
130}
131
132char *my_strtok( char * s, const char * delim )
133{
134 register char *spanp;
135 register int c, sc;
136 char *tok;
137 static char *lasts;
138
139
140 if (s == NULL && (s = lasts) == NULL)
141 return (NULL);
142
143 /*
144 * Skip (span) leading delimiters (s += strspn(s, delim), sort of).
145 */
146cont:
147 c = *s++;
148 for (spanp = (char *)delim; (sc = *spanp++) != 0;) {
149 if (c == sc)
150 goto cont;
151 }
152
153 if (c == 0) { /* no non-delimiter characters */
154 lasts = NULL;
155 return (NULL);
156 }
157 tok = s - 1;
158
159 /*
160 * Scan token (scan for delimiters: s += strcspn(s, delim), sort of).
161 * Note that delim must have one NUL; we stop if we see that, too.
162 */
163 for (;;) {
164 c = *s++;
165 spanp = (char *)delim;
166 do {
167 if ((sc = *spanp++) == c) {
168 if (c == 0)
169 s = NULL;
170 else
171 s[-1] = 0;
172 lasts = s;
173 return (tok);
174 }
175 } while (sc != 0);
176 }
177 /* NOTREACHED */
178}
179#if 0
180 static char *tp=NULL;
181
182 if(string!=NULL)
183 tp=string;
184
185 while(*tp!=NULL)
186 {
187 if(*tp==*delimiters)
188 break;
189 tp++;
190 }
191 *tp=0;
192 return tp;
193}
194#endif
195
196inline void* memcpy(void* dst, const void* src, size_t size)
197{
198 return rb->memcpy(dst, src, size);
199}
200
201// From suduku
202int doom_menu_cb(int key, int m)
203{
204 (void)m;
205 switch(key)
206 {
207#ifdef MENU_ENTER2
208 case MENU_ENTER2:
209#endif
210 case MENU_ENTER:
211 key = BUTTON_NONE; /* eat the downpress, next menu reacts on release */
212 break;
213
214#ifdef MENU_ENTER2
215 case MENU_ENTER2 | BUTTON_REL:
216#endif
217 case MENU_ENTER | BUTTON_REL:
218 key = MENU_ENTER; /* fake downpress, next menu doesn't like release */
219 break;
220 }
221
222 return key;
223}
224
225struct argvlist
226{
227 int timedemo; // 1 says there's a timedemo
228 int demonum;
229 int addonnum;
230} argvlist;
231
232const unsigned char versions_builtin[7][20] =
233{
234 "Doom Shareware",
235 "Doom Registered",
236 "Ultimate Doom",
237 "Doom 2",
238 "Doom 2 French",
239 "Plutonia",
240 "TNT"
241};
242
243const unsigned char wads_builtin[7][30] =
244{
245 GAMEBASE"doom1.wad",
246 GAMEBASE"doom.wad",
247 GAMEBASE"doomu.wad",
248 GAMEBASE"doom2.wad",
249 GAMEBASE"doom2f.wad",
250 GAMEBASE"plutonia.wad",
251 GAMEBASE"tnt.wad"
252};
253
254int namemap[7];
255char *addonfiles[10];
256static struct opt_items demolmp[11];
257char addon[200];
258// This sets up the base game and builds up myargv/c
259bool Dhandle_ver (int dver)
260{
261 switch (dver) {
262 case 0: /* Doom Shareware */
263 gamemode = shareware;
264 gamemission = doom;
265 D_AddFile(wads_builtin[0],source_iwad);
266 break;
267 case 1: /* Doom registered */
268 gamemode = registered;
269 gamemission = doom;
270 D_AddFile(wads_builtin[1],source_iwad);
271 break;
272 case 2: /* Ultimate Doom */
273 gamemode = retail;
274 gamemission = doom;
275 D_AddFile(wads_builtin[2],source_iwad);
276 break;
277 case 3: /* Doom2 */
278 gamemode = commercial;
279 gamemission = doom2;
280 D_AddFile(wads_builtin[3],source_iwad);
281 break;
282 case 4: /* Doom2f */
283 gamemode = commercial;
284 gamemission = doom2;
285 D_AddFile(wads_builtin[4],source_iwad);
286 break;
287 case 5: /* Plutonia */
288 gamemode = commercial;
289 gamemission = pack_plut;
290 D_AddFile(wads_builtin[5],source_iwad);
291 break;
292 case 6: /* TNT */
293 gamemode = commercial;
294 gamemission = pack_tnt;
295 D_AddFile(wads_builtin[6],source_iwad);
296 break;
297 default:
298 gamemission = none;
299 return 0;
300 }
301 // Start adding to myargv
302 if(argvlist.timedemo && (gamemode == shareware))
303 {
304 singletics = true;
305 timingdemo = true; // show stats after quit
306 G_DeferedPlayDemo("demo3");
307 singledemo = true; // quit after one demo
308 }
309
310 if(argvlist.addonnum)
311 {
312 snprintf(addon,sizeof(addon),"%s%s", GAMEBASE"addons/", addonfiles[argvlist.addonnum]);
313 D_AddFile(addon,source_pwad);
314 modifiedgame = true;
315 }
316
317 if(argvlist.demonum)
318 {
319 snprintf(addon, sizeof(addon),"%s%s", GAMEBASE"demos/", demolmp[argvlist.demonum].string);
320 D_AddFile(addon, source_lmp);
321 G_DeferedPlayDemo(addon);
322 singledemo = true; // quit after one demo
323 }
324 return 1;
325}
326
327// This function builds up the basegame list for use in the options selection
328// it also sets the defaults for the argvlist
329int Dbuild_base (struct opt_items *names)
330{
331 if ( fileexists(GAMEBASE"prboom.wad") )
332 return 0;
333
334 D_AddFile (GAMEBASE"prboom.wad", source_pwad);
335
336 int i=0;
337 /* Doom Shareware */
338 if ( !fileexists (wads_builtin[0]) )
339 {
340 names[i].string=versions_builtin[0];
341 names[i].voice_id=0;
342 namemap[i]=0;
343 i++;
344 }
345
346 /* Doom registered */
347 if ( !fileexists (wads_builtin[1]) )
348 {
349 names[i].string=versions_builtin[1];
350 names[i].voice_id=0;
351 namemap[i]=1;
352 i++;
353 }
354
355 /* Ultimate Doom */
356 if ( !fileexists (wads_builtin[2]) )
357 {
358 names[i].string=versions_builtin[2];
359 names[i].voice_id=0;
360 namemap[i]=2;
361 i++;
362 }
363
364 /* Doom2 */
365 if ( !fileexists (wads_builtin[3]) )
366 {
367 names[i].string=versions_builtin[3];
368 names[i].voice_id=0;
369 namemap[i]=3;
370 i++;
371 }
372
373 /* Doom2f */
374 if ( !fileexists (wads_builtin[4]) )
375 {
376 names[i].string=versions_builtin[4];
377 names[i].voice_id=0;
378 namemap[i]=4;
379 i++;
380 }
381
382 /* Plutonia */
383 if ( !fileexists (wads_builtin[5]) )
384 {
385 names[i].string=versions_builtin[5];
386 names[i].voice_id=0;
387 namemap[i]=5;
388 i++;
389 }
390
391 /* TNT */
392 if ( !fileexists (wads_builtin[6]) )
393 {
394 names[i].string=versions_builtin[6];
395 names[i].voice_id=0;
396 namemap[i]=6;
397 i++;
398 }
399 // Set argvlist defaults
400 argvlist.timedemo=0;
401
402 return i;
403}
404
405int Dbuild_addons(struct opt_items *names)
406{
407 int i=1;
408
409 DIR *addons;
410 struct dirent *dptr;
411 char *startpt;
412
413 startpt=malloc(strlen("No Addon")*sizeof(char)); // Add this on to allow for no addon to be played
414 strcpy(startpt,"No Addon");
415 names[0].string=startpt;
416 names[0].voice_id=0;
417
418 addons=opendir(GAMEBASE"Addons/");
419 if(addons==NULL)
420 return 1;
421
422 while((dptr=rb->readdir(addons)) && i<10)
423 {
424 if(rb->strcasestr(dptr->d_name, ".WAD"))
425 {
426 addonfiles[i]=malloc(strlen(dptr->d_name)*sizeof(char));
427 strcpy(addonfiles[i],dptr->d_name);
428 names[i].string=addonfiles[i];
429 names[i].voice_id=0;
430 i++;
431 }
432 }
433 closedir(addons);
434 return i;
435}
436
437
438int Dbuild_demos(struct opt_items *names)
439{
440 int i=1;
441
442 DIR *demos;
443 struct dirent *dptr;
444 char *startpt;
445
446 startpt=malloc(strlen("No Demo")*sizeof(char)); // Add this on to allow for no demo to be played
447 strcpy(startpt,"No Demo");
448 names[0].string=startpt;
449 names[0].voice_id=0;
450
451 demos=opendir(GAMEBASE"Demos/");
452 if(demos==NULL)
453 return 1;
454
455 while((dptr=rb->readdir(demos)) && i<11)
456 {
457 if(rb->strcasestr(dptr->d_name, ".LMP"))
458 {
459 startpt=malloc(strlen(dptr->d_name)*sizeof(char));
460 strcpy(startpt,dptr->d_name);
461 names[i].string=startpt;
462 names[i].voice_id=0;
463 i++;
464 }
465 }
466 closedir(demos);
467 return i;
468}
469
470void Oset_keys()
471{
472}
473
474static const struct opt_items onoff[2] = {
475 { "Off", NULL },
476 { "On", NULL },
477};
478
479static struct opt_items addons[10];
480
481extern int fake_contrast;
482
483static bool Doptions()
484{
485 int m, result;
486 int menuquit=0;
487
488 static const struct menu_item items[] = {
489 { "Sound", NULL },
490 { "Set Keys(not working)", NULL },
491 { "Timedemo", NULL },
492 { "Player Bobbing", NULL },
493 { "Weapon Recoil", NULL },
494 { "Translucency", NULL },
495 { "Fake Contrast", NULL },
496 };
497
498 m = rb->menu_init(items, sizeof(items) / sizeof(*items),
499 doom_menu_cb, NULL, NULL, NULL);
500
501 while(!menuquit)
502 {
503 result=rb->menu_show(m);
504 switch (result)
505 {
506 case 0: /* Sound */
507 nosfxparm=!nosfxparm; // Have to invert it before setting
508 rb->set_option("Sound", &nosfxparm, INT, onoff, 2, NULL );
509 break;
510
511 case 1: /* Keys */
512 Oset_keys();
513 break;
514
515 case 2: /* Timedemo */
516 rb->set_option("Timedemo", &argvlist.timedemo, INT, onoff, 2, NULL );
517 break;
518
519 case 3: /* Player Bobbing */
520 rb->set_option("Player Bobbing", &default_player_bobbing, INT, onoff, 2, NULL );
521 break;
522
523 case 4: /* Weapon Recoil */
524 rb->set_option("Weapon Recoil", &default_weapon_recoil, INT, onoff, 2, NULL );
525 break;
526
527 case 5: /* Translucency */
528 rb->set_option("Translucency", &default_translucency, INT, onoff, 2, NULL );
529 break;
530
531 case 6: /* Fake Contrast */
532 rb->set_option("Fake Contrast", &fake_contrast, INT, onoff, 2, NULL );
533 break;
534
535 default:
536 menuquit=1;
537 break;
538 }
539 }
540
541 rb->menu_exit(m);
542
543 return (1);
544}
545
546//
547// Doom Menu
548//
549int doom_menu()
550{
551 int m;
552 int result;
553 int status;
554 int gamever;
555 bool menuquit=0;
556
557 static struct opt_items names[7];
558
559 static const struct menu_item items[] = {
560 { "Game", NULL },
561 { "Addons", NULL },
562 { "Demos", NULL },
563 { "Options", NULL },
564 { "Play Game", NULL },
565 { "Quit", NULL },
566 };
567
568 if( (status=Dbuild_base(names)) == 0 ) // Build up the base wad files (select last added file)
569 {
570 rb->splash(HZ, true, "Sorry, you have no base wads");
571 return -1;
572 }
573
574 int numadd=Dbuild_addons(addons);
575
576 int numdemos=Dbuild_demos(demolmp);
577 argvlist.demonum=0;
578
579 argvlist.addonnum=0;
580
581 gamever=status-1;
582
583 m = rb->menu_init(items, sizeof(items) / sizeof(*items),
584 doom_menu_cb, NULL, NULL, NULL);
585
586 while(!menuquit)
587 {
588 result=rb->menu_show(m);
589 switch (result) {
590 case 0: /* Game picker */
591 rb->set_option("Base Game", &gamever, INT, names, status, NULL );
592 break;
593
594 case 1: /* Addon picker */
595 rb->set_option("Select Addon", &argvlist.addonnum, INT, addons, numadd, NULL );
596 //Daddons(numadd);
597 break;
598
599 case 2: /* Demo's */
600 rb->set_option("Demo's", &argvlist.demonum, INT, demolmp, numdemos, NULL );
601 break;
602
603 case 3: /* Options */
604 Doptions();
605 break;
606
607 case 4: /* Play Game */
608 menuquit=1;
609 break;
610
611 case 5: /* Quit */
612 menuquit=1;
613 gamever=-1;
614 break;
615
616 default:
617 break;
618 }
619 }
620
621 rb->menu_exit(m);
622
623 return (gamever);
624}
625
626extern int systemvol;
627/* this is the plugin entry point */
628enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
629{
630 rb = api;
631 (void)parameter;
632
633#if !defined(SIMULATOR) && defined(HAVE_ADJUSTABLE_CPU_FREQ)
634 rb->cpu_boost(true);
635#endif
636
637#ifdef USE_IRAM
638 memcpy(iramstart, iramcopy, iramend-iramstart);
639 memset(iedata, 0, iend - iedata);
640#endif
641
642 rb->lcd_setfont(0);
643
644#ifdef FANCY_MENU
645 if(rb->load_main_backdrop(GAMEBASE"backdrop.bmp"))
646 rb->lcd_set_foreground(LCD_RGBPACK(85,208,56));
647
648 rb->lcd_clear_display();
649#endif
650
651 // We're using doom's memory management since it implements a proper free (and re-uses the memory)
652 // and now with prboom's code: realloc and calloc
653 printf ("Z_Init: Init zone memory allocation daemon. \n");
654 Z_Init ();
655
656 printf ("M_LoadDefaults: Load system defaults.\n");
657 M_LoadDefaults (); // load before initing other systems
658
659#ifdef FANCY_MENU
660 rb->lcd_setfont(FONT_UI);
661 rb->lcd_putsxy(5,LCD_HEIGHT-20, "RockDoom v0.90");
662 rb->lcd_update();
663 rb->sleep(HZ*2);
664 rb->lcd_setfont(0);
665#else
666 rb->splash(HZ*2, true, "RockDoom v0.90");
667#endif
668
669 myargv = malloc(sizeof(char *)*MAXARGVS);
670 memset(myargv,0,sizeof(char *)*MAXARGVS);
671 myargv[0]="doom.rock";
672 myargc=1;
673
674 int result=doom_menu();
675
676 if( result == -1) return PLUGIN_OK; // No base wads found or quit was selected
677
678 Dhandle_ver( namemap[ result ] );
679
680 rb->lcd_setfont(0);
681
682 rb->lcd_clear_display();
683
684// systemvol= rb->global_settings->volume-rb->global_settings->volume%((rb->sound_max(SOUND_VOLUME)-rb->sound_min(SOUND_VOLUME))/15);
685 general_translucency = default_translucency; // phares
686 D_DoomMain ();
687
688 M_SaveDefaults ();
689
690 I_Quit(); // Make SURE everything was closed out right
691
692 printf("There were still: %d files open", fpoint);
693 while(fpoint>0)
694 {
695 rb->close(filearray[fpoint]);
696 fpoint--;
697 }
698
699 rb->splash(HZ, true, "Bye");
700
701#if !defined(SIMULATOR) && defined(HAVE_ADJUSTABLE_CPU_FREQ)
702 rb->cpu_boost(false);
703#endif
704
705 return PLUGIN_OK;
706}
diff --git a/apps/plugins/doom/rockmacros.h b/apps/plugins/doom/rockmacros.h
new file mode 100644
index 0000000000..6caeb2aa8a
--- /dev/null
+++ b/apps/plugins/doom/rockmacros.h
@@ -0,0 +1,93 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2005 Michiel van der Kolk, Jens Arnold
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19#ifndef __ROCKMACROS_H__
20#define __ROCKMACROS_H__
21
22#include "plugin.h"
23#include "ctype.h"
24#include "autoconf.h"
25#include "z_zone.h"
26
27extern struct plugin_api* rb;
28
29/* libc functions */
30int printf(const char *fmt, ...);
31int fileexists(const char * fname);
32int my_open(const char *file, int flags);
33int my_close(int id);
34char *my_strtok( char * s, const char * delim );
35#define alloca __builtin_alloca
36#define fprintf(...) rb->fdprintf(__VA_ARGS__)
37#define vsnprintf(...) rb->vsnprintf(__VA_ARGS__)
38
39#ifdef SIMULATOR
40#undef opendir
41#undef closedir
42#undef mkdir
43#undef open
44#undef lseek
45#undef filesize
46#define opendir(a) rb->sim_opendir((a))
47#define closedir(a) rb->sim_closedir((a))
48#define mkdir(a,b) rb->sim_mkdir((a),(b))
49#define open(a,b) rb->sim_open((a),(b))
50#define lseek(a,b,c) rb->sim_lseek((a),(b),(c))
51#define filesize(a) rb->sim_filesize((a))
52#else /* !SIMULATOR */
53#define opendir(a) rb->opendir((a))
54#define closedir(a) rb->closedir((a))
55#define filesize(a) rb->filesize((a))
56#define mkdir(a) rb->mkdir((a),0777)
57#define open(a,b) my_open((a),(b))
58#define close(a) my_close((a))
59#define lseek(a,b,c) rb->lseek((a),(b),(c))
60#endif /* !SIMULATOR */
61
62#define strcat(a,b) rb->strcat((a),(b))
63#define read(a,b,c) rb->read((a),(b),(c))
64#define write(a,b,c) rb->write((a),(b),(c))
65#define memset(a,b,c) rb->memset((a),(b),(c))
66#define memmove(a,b,c) rb->memmove((a),(b),(c))
67#define memcmp(a,b,c) rb->memcmp((a),(b),(c))
68#define memchr(a,b,c) rb->memchr((a),(b),(c))
69#define strcpy(a,b) rb->strcpy((a),(b))
70#define strncpy(a,b,c) rb->strncpy((a),(b),(c))
71#define strlen(a) rb->strlen((a))
72#define strcmp(a,b) rb->strcmp((a),(b))
73#define strncmp(a,b,c) rb->strncmp((a),(b),(c))
74#define strchr(a,b) rb->strchr((a),(b))
75#define strrchr(a,b) rb->strrchr((a),(b))
76#define strcasecmp(a,b) rb->strcasecmp((a),(b))
77#define strncasecmp(a,b,c) rb->strncasecmp((a),(b),(c))
78#define srand(a) rb->srand((a))
79#define rand() rb->rand()
80#define atoi(a) rb->atoi((a))
81#define strcat(a,b) rb->strcat((a),(b))
82#define snprintf rb->snprintf
83
84/* Using #define isn't enough with GCC 4.0.1 */
85inline void* memcpy(void* dst, const void* src, size_t size);
86
87#define PACKEDATTR __attribute__((packed)) // Needed for a few things
88#define GAMEBASE "/games/doom/"
89//#define SIMPLECHECKS
90#define NO_PREDEFINED_LUMPS
91#define TABLES_AS_LUMPS // This frees up alot of space in the plugin buffer
92#define FANCY_MENU // This is a call to allow load_main_backdrop to run in doom
93#endif
diff --git a/apps/plugins/doom/s_sound.c b/apps/plugins/doom/s_sound.c
new file mode 100644
index 0000000000..c8ed7b2839
--- /dev/null
+++ b/apps/plugins/doom/s_sound.c
@@ -0,0 +1,608 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION: Platform-independent sound code
28 *
29 *-----------------------------------------------------------------------------*/
30
31#include "i_system.h"
32#include "i_sound.h"
33#include "sounds.h"
34#include "s_sound.h"
35
36#include "z_zone.h"
37#include "m_random.h"
38#include "w_wad.h"
39#include "d_main.h"
40#include "doomdef.h"
41#include "r_main.h"
42
43#include "doomstat.h"
44
45#include "rockmacros.h"
46
47// when to clip out sounds
48// Does not fit the large outdoor areas.
49#define S_CLIPPING_DIST (1200<<FRACBITS)
50
51// Distance tp origin when sounds should be maxed out.
52// This should relate to movement clipping resolution
53// (see BLOCKMAP handling).
54// Originally: (200*0x10000).
55
56#define S_CLOSE_DIST (160*0x10000)
57#define S_ATTENUATOR ((S_CLIPPING_DIST-S_CLOSE_DIST)>>FRACBITS)
58
59// Adjustable by menu.
60#define NORM_PITCH 128
61#define NORM_PRIORITY 64
62#define NORM_SEP 128
63#define S_STEREO_SWING (96<<FRACBITS)
64
65typedef struct
66{
67 sfxinfo_t *sfxinfo; // sound information (if null, channel avail.)
68 void *origin; // origin of sound
69 int handle; // handle of the sound being played
70 int is_pickup; // killough 4/25/98: whether sound is a player's weapon
71} channel_t;
72
73// the set of channels available
74static channel_t* channels;
75
76// These are not used, but should be (menu).
77// Maximum volume of a sound effect.
78// Internal default is max out of 0-15.
79int snd_SfxVolume = 15;
80
81// Maximum volume of music. Useless so far.
82int snd_MusicVolume = 15;
83
84// whether songs are mus_paused
85static boolean mus_paused;
86
87// music currently being played
88static musicinfo_t* mus_playing=0;
89
90// following is set
91// by the defaults code in M_misc:
92// number of channels available
93int default_numChannels;
94int numChannels;
95
96//jff 3/17/98 to keep track of last IDMUS specified music num
97int idmusnum;
98
99//
100// Internals.
101//
102
103void S_StopChannel(int cnum);
104
105int S_AdjustSoundParams(mobj_t *listener, mobj_t *source,
106 int *vol, int *sep, int *pitch);
107
108static int S_getChannel(void *origin, sfxinfo_t *sfxinfo, int is_pickup);
109
110//
111// Initializes sound stuff, including volume
112// Sets channels, SFX and music volume,
113// allocates channel buffer, sets S_sfx lookup.
114//
115
116void S_Init(int sfxVolume,int musicVolume )
117{
118 //jff 1/22/98 skip sound init if sound not enabled
119 numChannels = default_numChannels;
120 if (!nosfxparm)
121 {
122 int i;
123
124 printf("S_Init: default sfx volume %d\n", sfxVolume);
125
126 // Whatever these did with DMX, these are rather dummies now.
127 I_SetChannels();
128
129 S_SetSfxVolume(sfxVolume);
130
131 S_SetMusicVolume(musicVolume);
132
133 // Allocating the internal channels for mixing
134 // (the maximum numer of sounds rendered
135 // simultaneously) within zone memory.
136 // CPhipps - calloc
137 channels = (channel_t *) calloc(numChannels,sizeof(channel_t));
138
139 // no sounds are playing, and they are not mus_paused
140 mus_paused = 0;
141
142 // Note that sounds have not been cached (yet).
143 for (i=1 ; i<NUMSFX ; i++)
144 S_sfx[i].lumpnum = S_sfx[i].usefulness = -1;
145 }
146}
147
148//
149// Per level startup code.
150// Kills playing sounds at start of level,
151// determines music if any, changes music.
152//
153void S_Start(void)
154{
155 int cnum, mnum;
156
157 if (!nosfxparm)
158 {
159 // kill all playing sounds at start of level
160 // (trust me - a good idea)
161 for (cnum=0 ; cnum<numChannels ; cnum++)
162 if (channels[cnum].sfxinfo)
163 S_StopChannel(cnum);
164
165 // start new music for the level
166 mus_paused = 0;
167
168 if (gamemode == commercial)
169 mnum = mus_runnin + gamemap - 1;
170 else
171 {
172 int spmus[]= // Song - Who? - Where?
173 {
174 mus_e3m4, // American e4m1
175 mus_e3m2, // Romero e4m2
176 mus_e3m3, // Shawn e4m3
177 mus_e1m5, // American e4m4
178 mus_e2m7, // Tim e4m5
179 mus_e2m4, // Romero e4m6
180 mus_e2m6, // J.Anderson e4m7 CHIRON.WAD
181 mus_e2m5, // Shawn e4m8
182 mus_e1m9 // Tim e4m9
183 };
184
185 if (gameepisode < 4)
186 mnum = mus_e1m1 + (gameepisode-1)*9 + gamemap-1;
187 else
188 mnum = spmus[gamemap-1];
189 }
190
191 S_ChangeMusic(mnum, true);
192 }
193}
194
195void S_StartSoundAtVolume(void *origin_p, int sfx_id, int volume)
196{
197 int sep, pitch, priority, cnum, is_pickup;
198 sfxinfo_t* sfx;
199 mobj_t* origin = (mobj_t *) origin_p;
200
201 if (nosfxparm)
202 return;
203
204 is_pickup = sfx_id & PICKUP_SOUND || sfx_id == sfx_oof || (compatibility_level >= prboom_2_compatibility && sfx_id == sfx_noway); // killough 4/25/98
205 sfx_id &= ~PICKUP_SOUND;
206
207 // check for bogus sound #
208 if (sfx_id < 1 || sfx_id > NUMSFX)
209 I_Error("S_StartSoundAtVolume: Bad sfx #: %d", sfx_id);
210
211 sfx = &S_sfx[sfx_id];
212
213 // Initialize sound parameters
214 if (sfx->link)
215 {
216 pitch = sfx->pitch;
217 priority = sfx->priority;
218 volume += sfx->volume;
219
220 if (volume < 1)
221 return;
222
223 if (volume > snd_SfxVolume)
224 volume = snd_SfxVolume;
225 }
226 else
227 {
228 pitch = NORM_PITCH;
229 priority = NORM_PRIORITY;
230 }
231
232
233 // Check to see if it is audible,
234 // and if not, modify the params
235
236 if (!origin || origin == players[displayplayer].mo) {
237 sep = NORM_SEP;
238 volume *= 8;
239 } else
240 if (!S_AdjustSoundParams(players[displayplayer].mo, origin, &volume,
241 &sep, &pitch))
242 return;
243 else
244 if ( origin->x == players[displayplayer].mo->x &&
245 origin->y == players[displayplayer].mo->y)
246 sep = NORM_SEP;
247
248 // hacks to vary the sfx pitches
249 if (sfx_id >= sfx_sawup && sfx_id <= sfx_sawhit)
250 pitch += 8 - (M_Random()&15);
251 else
252 if (sfx_id != sfx_itemup && sfx_id != sfx_tink)
253 pitch += 16 - (M_Random()&31);
254
255 if (pitch<0)
256 pitch = 0;
257
258 if (pitch>255)
259 pitch = 255;
260
261 // kill old sound
262 for (cnum=0 ; cnum<numChannels ; cnum++)
263 if (channels[cnum].sfxinfo && channels[cnum].origin == origin &&
264 (comp[comp_sound] || channels[cnum].is_pickup == is_pickup))
265 {
266 S_StopChannel(cnum);
267 break;
268 }
269
270 // try to find a channel
271 cnum = S_getChannel(origin, sfx, is_pickup);
272
273 if (cnum<0)
274 return;
275
276 // get lumpnum if necessary
277 // killough 2/28/98: make missing sounds non-fatal
278 if (sfx->lumpnum < 0 && (sfx->lumpnum = I_GetSfxLumpNum(sfx)) < 0)
279 return;
280
281 // increase the usefulness
282 if (sfx->usefulness++ < 0)
283 sfx->usefulness = 1;
284
285 // Assigns the handle to one of the channels in the mix/output buffer.
286 channels[cnum].handle = I_StartSound(sfx_id, cnum, volume, sep, pitch, priority);
287}
288
289void S_StartSound(void *origin, int sfx_id)
290{
291 S_StartSoundAtVolume(origin, sfx_id, snd_SfxVolume);
292}
293
294void S_StopSound(void *origin)
295{
296 int cnum;
297
298 if (nosfxparm)
299 return;
300
301 for (cnum=0 ; cnum<numChannels ; cnum++)
302 if (channels[cnum].sfxinfo && channels[cnum].origin == origin)
303 {
304 S_StopChannel(cnum);
305 break;
306 }
307}
308
309//
310// Stop and resume music, during game PAUSE.
311//
312void S_PauseSound(void)
313{
314 if (nosfxparm)
315 return;
316
317 if (mus_playing && !mus_paused)
318 {
319 I_PauseSong(mus_playing->handle);
320 mus_paused = true;
321 }
322}
323
324void S_ResumeSound(void)
325{
326 if (nosfxparm)
327 return;
328
329 if (mus_playing && mus_paused)
330 {
331 I_ResumeSong(mus_playing->handle);
332 mus_paused = false;
333 }
334}
335
336//
337// Updates music & sounds
338//
339void S_UpdateSounds(void* listener_p)
340{
341 int cnum;
342
343 mobj_t* listener = (mobj_t*)listener_p;
344
345 if (nosfxparm)
346 return;
347
348 for (cnum=0 ; cnum<numChannels ; cnum++)
349 {
350 sfxinfo_t* sfx;
351 channel_t* c = &channels[cnum];
352
353 if ((sfx = c->sfxinfo))
354 {
355 if (I_SoundIsPlaying(c->handle))
356 {
357 // initialize parameters
358 int volume = snd_SfxVolume;
359 int sep = NORM_PITCH;
360 int pitch = NORM_SEP;
361
362 if (sfx->link)
363 {
364 pitch = sfx->pitch;
365 volume += sfx->volume;
366 if (volume < 1)
367 {
368 S_StopChannel(cnum);
369 continue;
370 }
371 else
372 if (volume > snd_SfxVolume)
373 volume = snd_SfxVolume;
374 }
375
376 // check non-local sounds for distance clipping
377 // or modify their params
378 if (c->origin && listener_p != c->origin) // killough 3/20/98
379 {
380 if (!S_AdjustSoundParams(listener, c->origin,
381 &volume, &sep, &pitch))
382 S_StopChannel(cnum);
383 else
384 I_UpdateSoundParams(c->handle, volume, sep, pitch);
385 }
386 }
387 else
388 S_StopChannel(cnum);
389 }
390 }
391}
392
393void S_SetMusicVolume(int volume)
394{
395 if (nosfxparm)
396 return;
397
398 if (volume < 0 || volume > 15)
399 I_Error("S_SetMusicVolume: Attempt to set music volume at %d", volume);
400 I_SetMusicVolume(volume);
401 snd_MusicVolume = volume;
402}
403
404void S_SetSfxVolume(int volume)
405{
406 if (nosfxparm)
407 return;
408
409 if (volume < 0 || volume > 127)
410 I_Error("S_SetSfxVolume: Attempt to set sfx volume at %d", volume);
411 snd_SfxVolume = volume;
412}
413
414//
415// Starts some music with the music id found in sounds.h.
416//
417void S_StartMusic(int m_id)
418{
419 if (nosfxparm)
420 return;
421 S_ChangeMusic(m_id, false);
422}
423
424void S_ChangeMusic(int musicnum, int looping)
425{
426 musicinfo_t *music;
427
428 if (nosfxparm)
429 return;
430
431 if (musicnum <= mus_None || musicnum >= NUMMUSIC)
432 I_Error("S_ChangeMusic: Bad music number %d", musicnum);
433
434 music = &S_music[musicnum];
435
436 if (mus_playing == music)
437 return;
438
439 // shutdown old music
440 S_StopMusic();
441
442 // get lumpnum if neccessary
443 if (!music->lumpnum)
444 {
445 char namebuf[9];
446 snprintf(namebuf,sizeof(namebuf),"d_%s", music->name);
447 music->lumpnum = W_GetNumForName(namebuf);
448 }
449
450 // load & register it
451 music->data = W_CacheLumpNum(music->lumpnum);
452// music->handle = I_RegisterSong(music->data, W_LumpLength(music->lumpnum));
453
454 // load & register it
455// music->data = (void *) W_CacheLumpNum(music->lumpnum);
456 music->handle = I_RegisterSong(music->data);
457
458 // play it
459 I_PlaySong(music->handle, looping);
460
461 mus_playing = music;
462}
463
464
465void S_StopMusic(void)
466{
467 if (nosfxparm)
468 return;
469
470 if (mus_playing)
471 {
472 if (mus_paused)
473 I_ResumeSong(mus_playing->handle);
474
475 I_StopSong(mus_playing->handle);
476 I_UnRegisterSong(mus_playing->handle);
477 if (mus_playing->lumpnum >= 0)
478 W_UnlockLumpNum(mus_playing->lumpnum); // cph - release the music data
479
480 mus_playing->data = 0;
481 mus_playing = 0;
482 }
483}
484
485void S_StopChannel(int cnum)
486{
487 int i;
488 channel_t* c = &channels[cnum];
489
490 if (nosfxparm)
491 return;
492
493 if (c->sfxinfo)
494 {
495 // stop the sound playing
496 if (I_SoundIsPlaying(c->handle))
497 I_StopSound(c->handle);
498
499 // check to see
500 // if other channels are playing the sound
501 for (i=0 ; i<numChannels ; i++)
502 if (cnum != i && c->sfxinfo == channels[i].sfxinfo)
503 break;
504
505 // degrade usefulness of sound data
506 c->sfxinfo->usefulness--;
507 c->sfxinfo = 0;
508 }
509}
510
511//
512// Changes volume, stereo-separation, and pitch variables
513// from the norm of a sound effect to be played.
514// If the sound is not audible, returns a 0.
515// Otherwise, modifies parameters and returns 1.
516//
517int S_AdjustSoundParams(mobj_t *listener, mobj_t *source,
518 int *vol, int *sep, int *pitch)
519{
520 (void)pitch;
521 fixed_t adx, ady, approx_dist;
522 angle_t angle;
523
524 if (nosfxparm)
525 return 0;
526
527 // calculate the distance to sound origin
528 // and clip it if necessary
529 adx = D_abs(listener->x - source->x);
530 ady = D_abs(listener->y - source->y);
531
532 // From _GG1_ p.428. Appox. eucledian distance fast.
533 approx_dist = adx + ady - ((adx < ady ? adx : ady)>>1);
534
535 if (!approx_dist) // killough 11/98: handle zero-distance as special case
536 {
537 *sep = NORM_SEP;
538 *vol = snd_SfxVolume;
539 return *vol > 0;
540 }
541
542 if (approx_dist > S_CLIPPING_DIST)
543 return 0;
544
545 // angle of source to listener
546 angle = R_PointToAngle2(listener->x, listener->y, source->x, source->y);
547
548 if (angle <= listener->angle)
549 angle += 0xffffffff;
550 angle -= listener->angle;
551 angle >>= ANGLETOFINESHIFT;
552
553 // stereo separation
554 *sep = 128 - (FixedMul(S_STEREO_SWING,finesine[angle])>>FRACBITS);
555
556 // volume calculation
557 if (approx_dist < S_CLOSE_DIST)
558 *vol = snd_SfxVolume*8;
559 else
560 // distance effect
561 *vol = (snd_SfxVolume * ((S_CLIPPING_DIST-approx_dist)>>FRACBITS) * 8)
562 / S_ATTENUATOR;
563
564 return (*vol > 0);
565}
566
567//
568// S_getChannel :
569// If none available, return -1. Otherwise channel #.
570//
571// killough 4/25/98: made static, added is_pickup argument
572
573static int S_getChannel(void *origin, sfxinfo_t *sfxinfo, int is_pickup)
574{
575 // channel number to use
576 int cnum;
577 channel_t* c;
578
579 if (nosfxparm)
580 return -1;
581
582 // Find an open channel
583 for (cnum=0; cnum<numChannels && channels[cnum].sfxinfo; cnum++)
584 if (origin && channels[cnum].origin == origin &&
585 channels[cnum].is_pickup == is_pickup)
586 {
587 S_StopChannel(cnum);
588 break;
589 }
590
591 // None available
592 if (cnum == numChannels)
593 { // Look for lower priority
594 for (cnum=0 ; cnum<numChannels ; cnum++)
595 if (channels[cnum].sfxinfo->priority >= sfxinfo->priority)
596 break;
597 if (cnum == numChannels)
598 return -1; // No lower priority. Sorry, Charlie.
599 else
600 S_StopChannel(cnum); // Otherwise, kick out lower priority.
601 }
602
603 c = &channels[cnum]; // channel is decided to be cnum.
604 c->sfxinfo = sfxinfo;
605 c->origin = origin;
606 c->is_pickup = is_pickup; // killough 4/25/98
607 return cnum;
608}
diff --git a/apps/plugins/doom/s_sound.h b/apps/plugins/doom/s_sound.h
new file mode 100644
index 0000000000..0a4857e82f
--- /dev/null
+++ b/apps/plugins/doom/s_sound.h
@@ -0,0 +1,96 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION:
28 * The not so system specific sound interface.
29 *
30 *-----------------------------------------------------------------------------*/
31
32#ifndef __S_SOUND__
33#define __S_SOUND__
34
35
36#ifdef __GNUG__
37#pragma interface
38#endif
39
40//
41// Initializes sound stuff, including volume
42// Sets channels, SFX and music volume,
43// allocates channel buffer, sets S_sfx lookup.
44//
45void S_Init(int sfxVolume, int musicVolume);
46
47//
48// Per level startup code.
49// Kills playing sounds at start of level,
50// determines music if any, changes music.
51//
52void S_Start(void);
53
54//
55// Start sound for thing at <origin>
56// using <sound_id> from sounds.h
57//
58void S_StartSound(void *origin, int sound_id);
59
60// Will start a sound at a given volume.
61void S_StartSoundAtVolume(void *origin, int sound_id, int volume);
62
63// killough 4/25/98: mask used to indicate sound origin is player item pickup
64#define PICKUP_SOUND (0x8000)
65
66// Stop sound for thing at <origin>
67void S_StopSound(void* origin);
68
69// Start music using <music_id> from sounds.h
70void S_StartMusic(int music_id);
71
72// Start music using <music_id> from sounds.h, and set whether looping
73void S_ChangeMusic(int music_id, int looping);
74
75// Stops the music fer sure.
76void S_StopMusic(void);
77
78// Stop and resume music, during game PAUSE.
79void S_PauseSound(void);
80void S_ResumeSound(void);
81
82//
83// Updates music & sounds
84//
85void S_UpdateSounds(void* listener);
86void S_SetMusicVolume(int volume);
87void S_SetSfxVolume(int volume);
88
89// machine-independent sound params
90extern int default_numChannels;
91extern int numChannels;
92
93//jff 3/17/98 holds last IDMUS number, or -1
94extern int idmusnum;
95
96#endif
diff --git a/apps/plugins/doom/sounds.c b/apps/plugins/doom/sounds.c
new file mode 100644
index 0000000000..200a402403
--- /dev/null
+++ b/apps/plugins/doom/sounds.c
@@ -0,0 +1,240 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION:
28 * Created by a sound utility.
29 * Kept as a sample, DOOM2 sounds.
30 *
31 *-----------------------------------------------------------------------------*/
32
33#include "doomtype.h"
34#include "sounds.h"
35
36//
37// Information about all the music
38//
39
40musicinfo_t S_music[] =
41 {
42 { 0, 0, 0, 0 },
43 { "e1m1", 0, 0, 0 },
44 { "e1m2", 0, 0, 0 },
45 { "e1m3", 0, 0, 0 },
46 { "e1m4", 0, 0, 0 },
47 { "e1m5", 0, 0, 0 },
48 { "e1m6", 0, 0, 0 },
49 { "e1m7", 0, 0, 0 },
50 { "e1m8", 0, 0, 0 },
51 { "e1m9", 0, 0, 0 },
52 { "e2m1", 0, 0, 0 },
53 { "e2m2", 0, 0, 0 },
54 { "e2m3", 0, 0, 0 },
55 { "e2m4", 0, 0, 0 },
56 { "e2m5", 0, 0, 0 },
57 { "e2m6", 0, 0, 0 },
58 { "e2m7", 0, 0, 0 },
59 { "e2m8", 0, 0, 0 },
60 { "e2m9", 0, 0, 0 },
61 { "e3m1", 0, 0, 0 },
62 { "e3m2", 0, 0, 0 },
63 { "e3m3", 0, 0, 0 },
64 { "e3m4", 0, 0, 0 },
65 { "e3m5", 0, 0, 0 },
66 { "e3m6", 0, 0, 0 },
67 { "e3m7", 0, 0, 0 },
68 { "e3m8", 0, 0, 0 },
69 { "e3m9", 0, 0, 0 },
70 { "inter", 0, 0, 0 },
71 { "intro", 0, 0, 0 },
72 { "bunny", 0, 0, 0 },
73 { "victor", 0, 0, 0 },
74 { "introa", 0, 0, 0 },
75 { "runnin", 0, 0, 0 },
76 { "stalks", 0, 0, 0 },
77 { "countd", 0, 0, 0 },
78 { "betwee", 0, 0, 0 },
79 { "doom", 0, 0, 0 },
80 { "the_da", 0, 0, 0 },
81 { "shawn", 0, 0, 0 },
82 { "ddtblu", 0, 0, 0 },
83 { "in_cit", 0, 0, 0 },
84 { "dead", 0, 0, 0 },
85 { "stlks2", 0, 0, 0 },
86 { "theda2", 0, 0, 0 },
87 { "doom2", 0, 0, 0 },
88 { "ddtbl2", 0, 0, 0 },
89 { "runni2", 0, 0, 0 },
90 { "dead2", 0, 0, 0 },
91 { "stlks3", 0, 0, 0 },
92 { "romero", 0, 0, 0 },
93 { "shawn2", 0, 0, 0 },
94 { "messag", 0, 0, 0 },
95 { "count2", 0, 0, 0 },
96 { "ddtbl3", 0, 0, 0 },
97 { "ampie", 0, 0, 0 },
98 { "theda3", 0, 0, 0 },
99 { "adrian", 0, 0, 0 },
100 { "messg2", 0, 0, 0 },
101 { "romer2", 0, 0, 0 },
102 { "tense", 0, 0, 0 },
103 { "shawn3", 0, 0, 0 },
104 { "openin", 0, 0, 0 },
105 { "evil", 0, 0, 0 },
106 { "ultima", 0, 0, 0 },
107 { "read_m", 0, 0, 0 },
108 { "dm2ttl", 0, 0, 0 },
109 { "dm2int", 0, 0, 0 }
110 };
111
112
113//
114// Information about all the sfx
115//
116
117sfxinfo_t S_sfx[] =
118 {
119 // S_sfx[0] needs to be a dummy for odd reasons.
120 { "none", false, 0, 0, -1, -1, 0, 0, 0 },
121
122 { "pistol", false, 64, 0, -1, -1, 0, 0, 0 },
123 { "shotgn", false, 64, 0, -1, -1, 0, 0, 0 },
124 { "sgcock", false, 64, 0, -1, -1, 0, 0, 0 },
125 { "dshtgn", false, 64, 0, -1, -1, 0, 0, 0 },
126 { "dbopn", false, 64, 0, -1, -1, 0, 0, 0 },
127 { "dbcls", false, 64, 0, -1, -1, 0, 0, 0 },
128 { "dbload", false, 64, 0, -1, -1, 0, 0, 0 },
129 { "plasma", false, 64, 0, -1, -1, 0, 0, 0 },
130 { "bfg", false, 64, 0, -1, -1, 0, 0, 0 },
131 { "sawup", false, 64, 0, -1, -1, 0, 0, 0 },
132 { "sawidl", false, 118, 0, -1, -1, 0, 0, 0 },
133 { "sawful", false, 64, 0, -1, -1, 0, 0, 0 },
134 { "sawhit", false, 64, 0, -1, -1, 0, 0, 0 },
135 { "rlaunc", false, 64, 0, -1, -1, 0, 0, 0 },
136 { "rxplod", false, 70, 0, -1, -1, 0, 0, 0 },
137 { "firsht", false, 70, 0, -1, -1, 0, 0, 0 },
138 { "firxpl", false, 70, 0, -1, -1, 0, 0, 0 },
139 { "pstart", false, 100, 0, -1, -1, 0, 0, 0 },
140 { "pstop", false, 100, 0, -1, -1, 0, 0, 0 },
141 { "doropn", false, 100, 0, -1, -1, 0, 0, 0 },
142 { "dorcls", false, 100, 0, -1, -1, 0, 0, 0 },
143 { "stnmov", false, 119, 0, -1, -1, 0, 0, 0 },
144 { "swtchn", false, 78, 0, -1, -1, 0, 0, 0 },
145 { "swtchx", false, 78, 0, -1, -1, 0, 0, 0 },
146 { "plpain", false, 96, 0, -1, -1, 0, 0, 0 },
147 { "dmpain", false, 96, 0, -1, -1, 0, 0, 0 },
148 { "popain", false, 96, 0, -1, -1, 0, 0, 0 },
149 { "vipain", false, 96, 0, -1, -1, 0, 0, 0 },
150 { "mnpain", false, 96, 0, -1, -1, 0, 0, 0 },
151 { "pepain", false, 96, 0, -1, -1, 0, 0, 0 },
152 { "slop", false, 78, 0, -1, -1, 0, 0, 0 },
153 { "itemup", true, 78, 0, -1, -1, 0, 0, 0 },
154 { "wpnup", true, 78, 0, -1, -1, 0, 0, 0 },
155 { "oof", false, 96, 0, -1, -1, 0, 0, 0 },
156 { "telept", false, 32, 0, -1, -1, 0, 0, 0 },
157 { "posit1", true, 98, 0, -1, -1, 0, 0, 0 },
158 { "posit2", true, 98, 0, -1, -1, 0, 0, 0 },
159 { "posit3", true, 98, 0, -1, -1, 0, 0, 0 },
160 { "bgsit1", true, 98, 0, -1, -1, 0, 0, 0 },
161 { "bgsit2", true, 98, 0, -1, -1, 0, 0, 0 },
162 { "sgtsit", true, 98, 0, -1, -1, 0, 0, 0 },
163 { "cacsit", true, 98, 0, -1, -1, 0, 0, 0 },
164 { "brssit", true, 94, 0, -1, -1, 0, 0, 0 },
165 { "cybsit", true, 92, 0, -1, -1, 0, 0, 0 },
166 { "spisit", true, 90, 0, -1, -1, 0, 0, 0 },
167 { "bspsit", true, 90, 0, -1, -1, 0, 0, 0 },
168 { "kntsit", true, 90, 0, -1, -1, 0, 0, 0 },
169 { "vilsit", true, 90, 0, -1, -1, 0, 0, 0 },
170 { "mansit", true, 90, 0, -1, -1, 0, 0, 0 },
171 { "pesit", true, 90, 0, -1, -1, 0, 0, 0 },
172 { "sklatk", false, 70, 0, -1, -1, 0, 0, 0 },
173 { "sgtatk", false, 70, 0, -1, -1, 0, 0, 0 },
174 { "skepch", false, 70, 0, -1, -1, 0, 0, 0 },
175 { "vilatk", false, 70, 0, -1, -1, 0, 0, 0 },
176 { "claw", false, 70, 0, -1, -1, 0, 0, 0 },
177 { "skeswg", false, 70, 0, -1, -1, 0, 0, 0 },
178 { "pldeth", false, 32, 0, -1, -1, 0, 0, 0 },
179 { "pdiehi", false, 32, 0, -1, -1, 0, 0, 0 },
180 { "podth1", false, 70, 0, -1, -1, 0, 0, 0 },
181 { "podth2", false, 70, 0, -1, -1, 0, 0, 0 },
182 { "podth3", false, 70, 0, -1, -1, 0, 0, 0 },
183 { "bgdth1", false, 70, 0, -1, -1, 0, 0, 0 },
184 { "bgdth2", false, 70, 0, -1, -1, 0, 0, 0 },
185 { "sgtdth", false, 70, 0, -1, -1, 0, 0, 0 },
186 { "cacdth", false, 70, 0, -1, -1, 0, 0, 0 },
187 { "skldth", false, 70, 0, -1, -1, 0, 0, 0 },
188 { "brsdth", false, 32, 0, -1, -1, 0, 0, 0 },
189 { "cybdth", false, 32, 0, -1, -1, 0, 0, 0 },
190 { "spidth", false, 32, 0, -1, -1, 0, 0, 0 },
191 { "bspdth", false, 32, 0, -1, -1, 0, 0, 0 },
192 { "vildth", false, 32, 0, -1, -1, 0, 0, 0 },
193 { "kntdth", false, 32, 0, -1, -1, 0, 0, 0 },
194 { "pedth", false, 32, 0, -1, -1, 0, 0, 0 },
195 { "skedth", false, 32, 0, -1, -1, 0, 0, 0 },
196 { "posact", true, 120, 0, -1, -1, 0, 0, 0 },
197 { "bgact", true, 120, 0, -1, -1, 0, 0, 0 },
198 { "dmact", true, 120, 0, -1, -1, 0, 0, 0 },
199 { "bspact", true, 100, 0, -1, -1, 0, 0, 0 },
200 { "bspwlk", true, 100, 0, -1, -1, 0, 0, 0 },
201 { "vilact", true, 100, 0, -1, -1, 0, 0, 0 },
202 { "noway", false, 78, 0, -1, -1, 0, 0, 0 },
203 { "barexp", false, 60, 0, -1, -1, 0, 0, 0 },
204 { "punch", false, 64, 0, -1, -1, 0, 0, 0 },
205 { "hoof", false, 70, 0, -1, -1, 0, 0, 0 },
206 { "metal", false, 70, 0, -1, -1, 0, 0, 0 },
207 { "chgun", false, 64, &S_sfx[sfx_pistol], 150, 0, 0, 0, 0 },
208 { "tink", false, 60, 0, -1, -1, 0, 0, 0 },
209 { "bdopn", false, 100, 0, -1, -1, 0, 0, 0 },
210 { "bdcls", false, 100, 0, -1, -1, 0, 0, 0 },
211 { "itmbk", false, 100, 0, -1, -1, 0, 0, 0 },
212 { "flame", false, 32, 0, -1, -1, 0, 0, 0 },
213 { "flamst", false, 32, 0, -1, -1, 0, 0, 0 },
214 { "getpow", false, 60, 0, -1, -1, 0, 0, 0 },
215 { "bospit", false, 70, 0, -1, -1, 0, 0, 0 },
216 { "boscub", false, 70, 0, -1, -1, 0, 0, 0 },
217 { "bossit", false, 70, 0, -1, -1, 0, 0, 0 },
218 { "bospn", false, 70, 0, -1, -1, 0, 0, 0 },
219 { "bosdth", false, 70, 0, -1, -1, 0, 0, 0 },
220 { "manatk", false, 70, 0, -1, -1, 0, 0, 0 },
221 { "mandth", false, 70, 0, -1, -1, 0, 0, 0 },
222 { "sssit", false, 70, 0, -1, -1, 0, 0, 0 },
223 { "ssdth", false, 70, 0, -1, -1, 0, 0, 0 },
224 { "keenpn", false, 70, 0, -1, -1, 0, 0, 0 },
225 { "keendt", false, 70, 0, -1, -1, 0, 0, 0 },
226 { "skeact", false, 70, 0, -1, -1, 0, 0, 0 },
227 { "skesit", false, 70, 0, -1, -1, 0, 0, 0 },
228 { "skeatk", false, 70, 0, -1, -1, 0, 0, 0 },
229 { "radio", false, 60, 0, -1, -1, 0, 0, 0 },
230
231#ifdef DOGS
232 // killough 11/98: dog sounds
233 { "dgsit", false, 98, 0, -1, -1, 0, 0, 0 },
234 { "dgatk", false, 70, 0, -1, -1, 0, 0, 0 },
235 { "dgact", false, 120, 0, -1, -1, 0, 0, 0 },
236 { "dgdth", false, 70, 0, -1, -1, 0, 0, 0 },
237 { "dgpain", false, 96, 0, -1, -1, 0, 0, 0 },
238#endif
239 };
240
diff --git a/apps/plugins/doom/sounds.h b/apps/plugins/doom/sounds.h
new file mode 100644
index 0000000000..887a8e785f
--- /dev/null
+++ b/apps/plugins/doom/sounds.h
@@ -0,0 +1,303 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION:
28 * Created by the sound utility written by Dave Taylor.
29 * Kept as a sample, DOOM2 sounds. Frozen.
30 *
31 *-----------------------------------------------------------------------------*/
32
33#ifndef __SOUNDS__
34#define __SOUNDS__
35
36//
37// SoundFX struct.
38//
39
40struct sfxinfo_struct;
41
42typedef struct sfxinfo_struct sfxinfo_t;
43
44struct sfxinfo_struct {
45
46 // up to 6-character name
47 const char *name; // CPhipps - const
48
49 // Sfx singularity (only one at a time)
50 int singularity;
51
52 // Sfx priority
53 int priority;
54
55 // referenced sound if a link
56 sfxinfo_t *link;
57
58 // pitch if a link
59 int pitch;
60
61 // volume if a link
62 int volume;
63
64 // sound data
65 void *data;
66
67 // this is checked every second to see if sound
68 // can be thrown out (if 0, then decrement, if -1,
69 // then throw out, if > 0, then it is in use)
70 int usefulness;
71
72 // lump number of sfx
73 int lumpnum;
74};
75
76//
77// MusicInfo struct.
78//
79
80typedef struct {
81 // up to 6-character name
82 const char *name; // CPhipps - const
83
84 // lump number of music
85 int lumpnum;
86
87 /* music data - cphipps 4/11 made const void* */
88 const void *data;
89
90 // music handle once registered
91 int handle;
92} musicinfo_t;
93
94// the complete set of sound effects
95extern sfxinfo_t S_sfx[];
96
97// the complete set of music
98extern musicinfo_t S_music[];
99
100//
101// Identifiers for all music in game.
102//
103
104typedef enum {
105 mus_None,
106 mus_e1m1,
107 mus_e1m2,
108 mus_e1m3,
109 mus_e1m4,
110 mus_e1m5,
111 mus_e1m6,
112 mus_e1m7,
113 mus_e1m8,
114 mus_e1m9,
115 mus_e2m1,
116 mus_e2m2,
117 mus_e2m3,
118 mus_e2m4,
119 mus_e2m5,
120 mus_e2m6,
121 mus_e2m7,
122 mus_e2m8,
123 mus_e2m9,
124 mus_e3m1,
125 mus_e3m2,
126 mus_e3m3,
127 mus_e3m4,
128 mus_e3m5,
129 mus_e3m6,
130 mus_e3m7,
131 mus_e3m8,
132 mus_e3m9,
133 mus_inter,
134 mus_intro,
135 mus_bunny,
136 mus_victor,
137 mus_introa,
138 mus_runnin,
139 mus_stalks,
140 mus_countd,
141 mus_betwee,
142 mus_doom,
143 mus_the_da,
144 mus_shawn,
145 mus_ddtblu,
146 mus_in_cit,
147 mus_dead,
148 mus_stlks2,
149 mus_theda2,
150 mus_doom2,
151 mus_ddtbl2,
152 mus_runni2,
153 mus_dead2,
154 mus_stlks3,
155 mus_romero,
156 mus_shawn2,
157 mus_messag,
158 mus_count2,
159 mus_ddtbl3,
160 mus_ampie,
161 mus_theda3,
162 mus_adrian,
163 mus_messg2,
164 mus_romer2,
165 mus_tense,
166 mus_shawn3,
167 mus_openin,
168 mus_evil,
169 mus_ultima,
170 mus_read_m,
171 mus_dm2ttl,
172 mus_dm2int,
173 NUMMUSIC
174} musicenum_t;
175
176//
177// Identifiers for all sfx in game.
178//
179
180typedef enum {
181 sfx_None,
182 sfx_pistol,
183 sfx_shotgn,
184 sfx_sgcock,
185 sfx_dshtgn,
186 sfx_dbopn,
187 sfx_dbcls,
188 sfx_dbload,
189 sfx_plasma,
190 sfx_bfg,
191 sfx_sawup,
192 sfx_sawidl,
193 sfx_sawful,
194 sfx_sawhit,
195 sfx_rlaunc,
196 sfx_rxplod,
197 sfx_firsht,
198 sfx_firxpl,
199 sfx_pstart,
200 sfx_pstop,
201 sfx_doropn,
202 sfx_dorcls,
203 sfx_stnmov,
204 sfx_swtchn,
205 sfx_swtchx,
206 sfx_plpain,
207 sfx_dmpain,
208 sfx_popain,
209 sfx_vipain,
210 sfx_mnpain,
211 sfx_pepain,
212 sfx_slop,
213 sfx_itemup,
214 sfx_wpnup,
215 sfx_oof,
216 sfx_telept,
217 sfx_posit1,
218 sfx_posit2,
219 sfx_posit3,
220 sfx_bgsit1,
221 sfx_bgsit2,
222 sfx_sgtsit,
223 sfx_cacsit,
224 sfx_brssit,
225 sfx_cybsit,
226 sfx_spisit,
227 sfx_bspsit,
228 sfx_kntsit,
229 sfx_vilsit,
230 sfx_mansit,
231 sfx_pesit,
232 sfx_sklatk,
233 sfx_sgtatk,
234 sfx_skepch,
235 sfx_vilatk,
236 sfx_claw,
237 sfx_skeswg,
238 sfx_pldeth,
239 sfx_pdiehi,
240 sfx_podth1,
241 sfx_podth2,
242 sfx_podth3,
243 sfx_bgdth1,
244 sfx_bgdth2,
245 sfx_sgtdth,
246 sfx_cacdth,
247 sfx_skldth,
248 sfx_brsdth,
249 sfx_cybdth,
250 sfx_spidth,
251 sfx_bspdth,
252 sfx_vildth,
253 sfx_kntdth,
254 sfx_pedth,
255 sfx_skedth,
256 sfx_posact,
257 sfx_bgact,
258 sfx_dmact,
259 sfx_bspact,
260 sfx_bspwlk,
261 sfx_vilact,
262 sfx_noway,
263 sfx_barexp,
264 sfx_punch,
265 sfx_hoof,
266 sfx_metal,
267 sfx_chgun,
268 sfx_tink,
269 sfx_bdopn,
270 sfx_bdcls,
271 sfx_itmbk,
272 sfx_flame,
273 sfx_flamst,
274 sfx_getpow,
275 sfx_bospit,
276 sfx_boscub,
277 sfx_bossit,
278 sfx_bospn,
279 sfx_bosdth,
280 sfx_manatk,
281 sfx_mandth,
282 sfx_sssit,
283 sfx_ssdth,
284 sfx_keenpn,
285 sfx_keendt,
286 sfx_skeact,
287 sfx_skesit,
288 sfx_skeatk,
289 sfx_radio,
290
291#ifdef DOGS
292 /* killough 11/98: dog sounds */
293 sfx_dgsit,
294 sfx_dgatk,
295 sfx_dgact,
296 sfx_dgdth,
297 sfx_dgpain,
298#endif
299
300 NUMSFX
301} sfxenum_t;
302
303#endif
diff --git a/apps/plugins/doom/st_lib.c b/apps/plugins/doom/st_lib.c
new file mode 100644
index 0000000000..adcd0e6688
--- /dev/null
+++ b/apps/plugins/doom/st_lib.c
@@ -0,0 +1,372 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION:
28 * The status bar widget code.
29 *
30 *-----------------------------------------------------------------------------*/
31
32#include "doomdef.h"
33#include "doomstat.h"
34#include "v_video.h"
35#include "w_wad.h"
36#include "m_swap.h"
37#include "st_stuff.h"
38#include "st_lib.h"
39#include "r_main.h"
40
41int sts_always_red; //jff 2/18/98 control to disable status color changes
42int sts_pct_always_gray; // killough 2/21/98: always gray %'s? bug or feature?
43
44//
45// STlib_init()
46//
47void STlib_init(void)
48{
49 // cph - no longer hold STMINUS pointer
50}
51
52//
53// STlib_initNum()
54//
55// Initializes an st_number_t widget
56//
57// Passed the widget, its position, the patches for the digits, a pointer
58// to the value displayed, a pointer to the on/off control, and the width
59// Returns nothing
60//
61void STlib_initNum
62( st_number_t* n,
63 int x,
64 int y,
65 const patchnum_t* pl,
66 int* num,
67 boolean* on,
68 int width )
69{
70 n->x = x;
71 n->y = y;
72 n->oldnum = 0;
73 n->width = width;
74 n->num = num;
75 n->on = on;
76 n->p = pl;
77}
78
79/*
80 * STlib_drawNum()
81 *
82 * A fairly efficient way to draw a number based on differences from the
83 * old number.
84 *
85 * Passed a st_number_t widget, a color range for output, and a flag
86 * indicating whether refresh is needed.
87 * Returns nothing
88 *
89 * jff 2/16/98 add color translation to digit output
90 * cphipps 10/99 - const pointer to colour trans table, made function static
91 */
92static void STlib_drawNum
93( st_number_t* n,
94 int cm,
95 boolean refresh )
96{
97
98 int numdigits = n->width;
99 int num = *n->num;
100
101 int w = SHORT(n->p[0].width);
102 int h = SHORT(n->p[0].height);
103 int x = n->x;
104
105 int neg;
106
107 // leban 1/20/99:
108 // strange that somebody went through all the work to draw only the
109 // differences, and then went and constantly redrew all the numbers.
110 // return without drawing if the number didn't change and the bar
111 // isn't refreshing.
112 if(n->oldnum == num && !refresh)
113 return;
114
115 // CPhipps - compact some code, use num instead of *n->num
116 if ((neg = (n->oldnum = num) < 0))
117 {
118 if (numdigits == 2 && num < -9)
119 num = -9;
120 else if (numdigits == 3 && num < -99)
121 num = -99;
122
123 num = -num;
124 }
125
126 // clear the area
127 x = n->x - numdigits*w;
128
129#ifdef RANGECHECK
130 if (n->y - ST_Y < 0)
131 I_Error("STlib_drawNum: n->y - ST_Y < 0");
132#endif
133
134 V_CopyRect(x, n->y - ST_Y, BG, w*numdigits, h, x, n->y, FG, VPT_STRETCH);
135
136 // if non-number, do not draw it
137 if (num == 1994)
138 return;
139
140 x = n->x;
141
142 //jff 2/16/98 add color translation to digit output
143 // in the special case of 0, you draw 0
144 if (!num)
145 // CPhipps - patch drawing updated, reformatted
146 V_DrawNumPatch(x - w, n->y, FG, n->p[0].lumpnum, cm,
147 (((cm!=CR_DEFAULT) && !sts_always_red) ? VPT_TRANS : VPT_NONE) | VPT_STRETCH);
148
149 // draw the new number
150 //jff 2/16/98 add color translation to digit output
151 while (num && numdigits--) {
152 // CPhipps - patch drawing updated, reformatted
153 x -= w;
154 V_DrawNumPatch(x, n->y, FG, n->p[num % 10].lumpnum, cm,
155 (((cm!=CR_DEFAULT) && !sts_always_red) ? VPT_TRANS : VPT_NONE) | VPT_STRETCH);
156 num /= 10;
157 }
158
159 // draw a minus sign if necessary
160 //jff 2/16/98 add color translation to digit output
161 // cph - patch drawing updated, load by name instead of acquiring pointer earlier
162 if (neg)
163 V_DrawNamePatch(x - w, n->y, FG, "STTMINUS", cm,
164 (((cm!=CR_DEFAULT) && !sts_always_red) ? VPT_TRANS : VPT_NONE) | VPT_STRETCH);
165}
166
167/*
168 * STlib_updateNum()
169 *
170 * Draws a number conditionally based on the widget's enable
171 *
172 * Passed a number widget, the output color range, and a refresh flag
173 * Returns nothing
174 *
175 * jff 2/16/98 add color translation to digit output
176 * cphipps 10/99 - make that pointer const
177 */
178void STlib_updateNum
179( st_number_t* n,
180 int cm,
181 boolean refresh )
182{
183 if (*n->on) STlib_drawNum(n, cm, refresh);
184}
185
186//
187// STlib_initPercent()
188//
189// Initialize a st_percent_t number with percent sign widget
190//
191// Passed a st_percent_t widget, the position, the digit patches, a pointer
192// to the number to display, a pointer to the enable flag, and patch
193// for the percent sign.
194// Returns nothing.
195//
196void STlib_initPercent
197( st_percent_t* p,
198 int x,
199 int y,
200 const patchnum_t* pl,
201 int* num,
202 boolean* on,
203 const patchnum_t* percent )
204{
205 STlib_initNum(&p->n, x, y, pl, num, on, 3);
206 p->p = percent;
207}
208
209/*
210 * STlib_updatePercent()
211 *
212 * Draws a number/percent conditionally based on the widget's enable
213 *
214 * Passed a precent widget, the output color range, and a refresh flag
215 * Returns nothing
216 *
217 * jff 2/16/98 add color translation to digit output
218 * cphipps - const for pointer to the colour translation table
219 */
220
221void STlib_updatePercent
222( st_percent_t* per,
223 int cm,
224 int refresh )
225{
226 if (*per->n.on && (refresh || (per->n.oldnum != *per->n.num))) {
227 // killough 2/21/98: fix percents not updated;
228 /* CPhipps - make %'s only be updated if number changed */
229 // CPhipps - patch drawing updated
230 V_DrawNumPatch(per->n.x, per->n.y, FG, per->p->lumpnum,
231 sts_pct_always_gray ? CR_GRAY : cm,
232 (sts_always_red ? VPT_NONE : VPT_TRANS) | VPT_STRETCH);
233 }
234
235 STlib_updateNum(&per->n, cm, refresh);
236}
237
238//
239// STlib_initMultIcon()
240//
241// Initialize a st_multicon_t widget, used for a multigraphic display
242// like the status bar's keys.
243//
244// Passed a st_multicon_t widget, the position, the graphic patches, a pointer
245// to the numbers representing what to display, and pointer to the enable flag
246// Returns nothing.
247//
248void STlib_initMultIcon
249( st_multicon_t* i,
250 int x,
251 int y,
252 const patchnum_t* il,
253 int* inum,
254 boolean* on )
255{
256 i->x = x;
257 i->y = y;
258 i->oldinum = -1;
259 i->inum = inum;
260 i->on = on;
261 i->p = il;
262}
263
264//
265// STlib_updateMultIcon()
266//
267// Draw a st_multicon_t widget, used for a multigraphic display
268// like the status bar's keys. Displays each when the control
269// numbers change or refresh is true
270//
271// Passed a st_multicon_t widget, and a refresh flag
272// Returns nothing.
273//
274void STlib_updateMultIcon
275( st_multicon_t* mi,
276 boolean refresh )
277{
278 int w;
279 int h;
280 int x;
281 int y;
282
283 if (*mi->on && (mi->oldinum != *mi->inum || refresh))
284 {
285 if (mi->oldinum != -1)
286 {
287 x = mi->x - SHORT(mi->p[mi->oldinum].leftoffset);
288 y = mi->y - SHORT(mi->p[mi->oldinum].topoffset);
289 w = SHORT(mi->p[mi->oldinum].width);
290 h = SHORT(mi->p[mi->oldinum].height);
291
292#ifdef RANGECHECK
293 if (y - ST_Y < 0)
294 I_Error("STlib_updateMultIcon: y - ST_Y < 0");
295#endif
296
297 V_CopyRect(x, y-ST_Y, BG, w, h, x, y, FG, VPT_STRETCH);
298 }
299 if (*mi->inum != -1) // killough 2/16/98: redraw only if != -1
300 V_DrawNumPatch(mi->x, mi->y, FG, mi->p[*mi->inum].lumpnum, CR_DEFAULT, VPT_STRETCH);
301 mi->oldinum = *mi->inum;
302 }
303}
304
305//
306// STlib_initBinIcon()
307//
308// Initialize a st_binicon_t widget, used for a multinumber display
309// like the status bar's weapons, that are present or not.
310//
311// Passed a st_binicon_t widget, the position, the digit patches, a pointer
312// to the flags representing what is displayed, and pointer to the enable flag
313// Returns nothing.
314//
315void STlib_initBinIcon
316( st_binicon_t* b,
317 int x,
318 int y,
319 const patchnum_t* i,
320 boolean* val,
321 boolean* on )
322{
323 b->x = x;
324 b->y = y;
325 b->oldval = 0;
326 b->val = val;
327 b->on = on;
328 b->p = i;
329}
330
331//
332// STlib_updateBinIcon()
333//
334// DInitialize a st_binicon_t widget, used for a multinumber display
335// like the status bar's weapons, that are present or not.
336//
337// Draw a st_binicon_t widget, used for a multinumber display
338// like the status bar's weapons that are present or not. Displays each
339// when the control flag changes or refresh is true
340//
341// Passed a st_binicon_t widget, and a refresh flag
342// Returns nothing.
343//
344void STlib_updateBinIcon
345( st_binicon_t* bi,
346 boolean refresh )
347{
348 int x;
349 int y;
350 int w;
351 int h;
352
353 if (*bi->on && (bi->oldval != (signed)*bi->val || refresh))
354 {
355 x = bi->x - SHORT(bi->p->leftoffset);
356 y = bi->y - SHORT(bi->p->topoffset);
357 w = SHORT(bi->p->width);
358 h = SHORT(bi->p->height);
359
360#ifdef RANGECHECK
361 if (y - ST_Y < 0)
362 I_Error("STlib_updateBinIcon: y - ST_Y < 0");
363#endif
364
365 if (*bi->val)
366 V_DrawNumPatch(bi->x, bi->y, FG, bi->p->lumpnum, CR_DEFAULT, VPT_STRETCH);
367 else
368 V_CopyRect(x, y-ST_Y, BG, w, h, x, y, FG, VPT_STRETCH);
369
370 bi->oldval = *bi->val;
371 }
372}
diff --git a/apps/plugins/doom/st_lib.h b/apps/plugins/doom/st_lib.h
new file mode 100644
index 0000000000..09e5faaf87
--- /dev/null
+++ b/apps/plugins/doom/st_lib.h
@@ -0,0 +1,207 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION:
28 * The status bar widget definitions and prototypes
29 *
30 *-----------------------------------------------------------------------------*/
31
32#ifndef __STLIB__
33#define __STLIB__
34
35// We are referring to patches.
36#include "r_defs.h"
37#include "v_video.h" // color ranges
38
39//
40// Background and foreground screen numbers
41//
42#define BG 4
43#define FG 0
44
45//
46// Typedefs of widgets
47//
48
49// Number widget
50
51typedef struct
52{
53 // upper right-hand corner
54 // of the number (right-justified)
55 int x;
56 int y;
57
58 // max # of digits in number
59 int width;
60
61 // last number value
62 int oldnum;
63
64 // pointer to current value
65 int* num;
66
67 // pointer to boolean stating
68 // whether to update number
69 boolean* on;
70
71 // list of patches for 0-9
72 const patchnum_t* p;
73
74 // user data
75 int data;
76} st_number_t;
77
78// Percent widget ("child" of number widget,
79// or, more precisely, contains a number widget.)
80typedef struct
81{
82 // number information
83 st_number_t n;
84
85 // percent sign graphic
86 const patchnum_t* p;
87} st_percent_t;
88
89// Multiple Icon widget
90typedef struct
91{
92 // center-justified location of icons
93 int x;
94 int y;
95
96 // last icon number
97 int oldinum;
98
99 // pointer to current icon
100 int* inum;
101
102 // pointer to boolean stating
103 // whether to update icon
104 boolean* on;
105
106 // list of icons
107 const patchnum_t* p;
108
109 // user data
110 int data;
111
112} st_multicon_t;
113
114// Binary Icon widget
115
116typedef struct
117{
118 // center-justified location of icon
119 int x;
120 int y;
121
122 // last icon value
123 int oldval;
124
125 // pointer to current icon status
126 boolean* val;
127
128 // pointer to boolean
129 // stating whether to update icon
130 boolean* on;
131
132 const patchnum_t* p; // icon
133 int data; // user data
134} st_binicon_t;
135
136//
137// Widget creation, access, and update routines
138//
139
140// Initializes widget library.
141// More precisely, initialize STMINUS,
142// everything else is done somewhere else.
143//
144void STlib_init(void);
145
146// Number widget routines
147void STlib_initNum
148( st_number_t* n,
149 int x,
150 int y,
151 const patchnum_t* pl,
152 int* num,
153 boolean* on,
154 int width );
155
156void STlib_updateNum
157( st_number_t* n,
158 int cm,
159 boolean refresh );
160
161
162// Percent widget routines
163void STlib_initPercent
164( st_percent_t* p,
165 int x,
166 int y,
167 const patchnum_t* pl,
168 int* num,
169 boolean* on,
170 const patchnum_t* percent );
171
172
173void STlib_updatePercent
174( st_percent_t* per,
175 int cm,
176 int refresh );
177
178
179// Multiple Icon widget routines
180void STlib_initMultIcon
181( st_multicon_t* mi,
182 int x,
183 int y,
184 const patchnum_t* il,
185 int* inum,
186 boolean* on );
187
188
189void STlib_updateMultIcon
190( st_multicon_t* mi,
191 boolean refresh );
192
193// Binary Icon widget routines
194
195void STlib_initBinIcon
196( st_binicon_t* b,
197 int x,
198 int y,
199 const patchnum_t* i,
200 boolean* val,
201 boolean* on );
202
203void STlib_updateBinIcon
204( st_binicon_t* bi,
205 boolean refresh );
206
207#endif
diff --git a/apps/plugins/doom/st_stuff.c b/apps/plugins/doom/st_stuff.c
new file mode 100644
index 0000000000..5d9244d951
--- /dev/null
+++ b/apps/plugins/doom/st_stuff.c
@@ -0,0 +1,1153 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION:
28 * Status bar code.
29 * Does the face/direction indicator animatin.
30 * Does palette indicators as well (red pain/berserk, bright pickup)
31 *
32 *-----------------------------------------------------------------------------*/
33
34#include "doomdef.h"
35#include "doomstat.h"
36#include "m_random.h"
37#include "i_video.h"
38#include "w_wad.h"
39#include "st_stuff.h"
40#include "st_lib.h"
41#include "r_main.h"
42#include "am_map.h"
43#include "m_cheat.h"
44#include "s_sound.h"
45#include "sounds.h"
46#include "dstrings.h"
47#include "r_draw.h"
48
49//
50// STATUS BAR DATA
51//
52
53// Palette indices.
54// For damage/bonus red-/gold-shifts
55#define STARTREDPALS 1
56#define STARTBONUSPALS 9
57#define NUMREDPALS 8
58#define NUMBONUSPALS 4
59// Radiation suit, green shift.
60#define RADIATIONPAL 13
61
62// Location of status bar
63#define ST_X 0
64#define ST_X2 104
65
66// proff 08/18/98: Changed for high-res
67#define ST_FX (ST_X+143)
68#define ST_FY (ST_Y+1)
69//#define ST_FX 143
70//#define ST_FY 169
71
72// Should be set to patch width
73// for tall numbers later on
74#define ST_TALLNUMWIDTH (tallnum[0]->width)
75
76// Number of status faces.
77#define ST_NUMPAINFACES 5
78#define ST_NUMSTRAIGHTFACES 3
79#define ST_NUMTURNFACES 2
80#define ST_NUMSPECIALFACES 3
81
82#define ST_FACESTRIDE \
83 (ST_NUMSTRAIGHTFACES+ST_NUMTURNFACES+ST_NUMSPECIALFACES)
84
85#define ST_NUMEXTRAFACES 2
86
87#define ST_NUMFACES \
88 (ST_FACESTRIDE*ST_NUMPAINFACES+ST_NUMEXTRAFACES)
89
90#define ST_TURNOFFSET (ST_NUMSTRAIGHTFACES)
91#define ST_OUCHOFFSET (ST_TURNOFFSET + ST_NUMTURNFACES)
92#define ST_EVILGRINOFFSET (ST_OUCHOFFSET + 1)
93#define ST_RAMPAGEOFFSET (ST_EVILGRINOFFSET + 1)
94#define ST_GODFACE (ST_NUMPAINFACES*ST_FACESTRIDE)
95#define ST_DEADFACE (ST_GODFACE+1)
96
97// proff 08/18/98: Changed for high-res
98#define ST_FACESX (ST_X+143)
99#define ST_FACESY (ST_Y)
100//#define ST_FACESX 143
101//#define ST_FACESY 168
102
103#define ST_EVILGRINCOUNT (2*TICRATE)
104#define ST_STRAIGHTFACECOUNT (TICRATE/2)
105#define ST_TURNCOUNT (1*TICRATE)
106#define ST_OUCHCOUNT (1*TICRATE)
107#define ST_RAMPAGEDELAY (2*TICRATE)
108
109#define ST_MUCHPAIN 20
110
111// Location and size of statistics,
112// justified according to widget type.
113// Problem is, within which space? STbar? Screen?
114// Note: this could be read in by a lump.
115// Problem is, is the stuff rendered
116// into a buffer,
117// or into the frame buffer?
118// I dunno, why don't you go and find out!!! killough
119
120// AMMO number pos.
121#define ST_AMMOWIDTH 3
122// proff 08/18/98: Changed for high-res
123#define ST_AMMOX (ST_X+44)
124#define ST_AMMOY (ST_Y+3)
125//#define ST_AMMOX 44
126//#define ST_AMMOY 171
127
128// HEALTH number pos.
129#define ST_HEALTHWIDTH 3
130// proff 08/18/98: Changed for high-res
131#define ST_HEALTHX (ST_X+90)
132#define ST_HEALTHY (ST_Y+3)
133//#define ST_HEALTHX 90
134//#define ST_HEALTHY 171
135
136// Weapon pos.
137// proff 08/18/98: Changed for high-res
138#define ST_ARMSX (ST_X+111)
139#define ST_ARMSY (ST_Y+4)
140#define ST_ARMSBGX (ST_X+104)
141#define ST_ARMSBGY (ST_Y)
142//#define ST_ARMSX 111
143//#define ST_ARMSY 172
144//#define ST_ARMSBGX 104
145//#define ST_ARMSBGY 168
146#define ST_ARMSXSPACE 12
147#define ST_ARMSYSPACE 10
148
149// Frags pos.
150// proff 08/18/98: Changed for high-res
151#define ST_FRAGSX (ST_X+138)
152#define ST_FRAGSY (ST_Y+3)
153//#define ST_FRAGSX 138
154//#define ST_FRAGSY 171
155#define ST_FRAGSWIDTH 2
156
157// ARMOR number pos.
158#define ST_ARMORWIDTH 3
159// proff 08/18/98: Changed for high-res
160#define ST_ARMORX (ST_X+221)
161#define ST_ARMORY (ST_Y+3)
162//#define ST_ARMORX 221
163//#define ST_ARMORY 171
164
165// Key icon positions.
166#define ST_KEY0WIDTH 8
167#define ST_KEY0HEIGHT 5
168// proff 08/18/98: Changed for high-res
169#define ST_KEY0X (ST_X+239)
170#define ST_KEY0Y (ST_Y+3)
171//#define ST_KEY0X 239
172//#define ST_KEY0Y 171
173#define ST_KEY1WIDTH ST_KEY0WIDTH
174// proff 08/18/98: Changed for high-res
175#define ST_KEY1X (ST_X+239)
176#define ST_KEY1Y (ST_Y+13)
177//#define ST_KEY1X 239
178//#define ST_KEY1Y 181
179#define ST_KEY2WIDTH ST_KEY0WIDTH
180// proff 08/18/98: Changed for high-res
181#define ST_KEY2X (ST_X+239)
182#define ST_KEY2Y (ST_Y+23)
183//#define ST_KEY2X 239
184//#define ST_KEY2Y 191
185
186// Ammunition counter.
187#define ST_AMMO0WIDTH 3
188#define ST_AMMO0HEIGHT 6
189// proff 08/18/98: Changed for high-res
190#define ST_AMMO0X (ST_X+288)
191#define ST_AMMO0Y (ST_Y+5)
192//#define ST_AMMO0X 288
193//#define ST_AMMO0Y 173
194#define ST_AMMO1WIDTH ST_AMMO0WIDTH
195// proff 08/18/98: Changed for high-res
196#define ST_AMMO1X (ST_X+288)
197#define ST_AMMO1Y (ST_Y+11)
198//#define ST_AMMO1X 288
199//#define ST_AMMO1Y 179
200#define ST_AMMO2WIDTH ST_AMMO0WIDTH
201// proff 08/18/98: Changed for high-res
202#define ST_AMMO2X (ST_X+288)
203#define ST_AMMO2Y (ST_Y+23)
204//#define ST_AMMO2X 288
205//#define ST_AMMO2Y 191
206#define ST_AMMO3WIDTH ST_AMMO0WIDTH
207// proff 08/18/98: Changed for high-res
208#define ST_AMMO3X (ST_X+288)
209#define ST_AMMO3Y (ST_Y+17)
210//#define ST_AMMO3X 288
211//#define ST_AMMO3Y 185
212
213// Indicate maximum ammunition.
214// Only needed because backpack exists.
215#define ST_MAXAMMO0WIDTH 3
216#define ST_MAXAMMO0HEIGHT 5
217// proff 08/18/98: Changed for high-res
218#define ST_MAXAMMO0X (ST_X+314)
219#define ST_MAXAMMO0Y (ST_Y+5)
220//#define ST_MAXAMMO0X 314
221//#define ST_MAXAMMO0Y 173
222#define ST_MAXAMMO1WIDTH ST_MAXAMMO0WIDTH
223// proff 08/18/98: Changed for high-res
224#define ST_MAXAMMO1X (ST_X+314)
225#define ST_MAXAMMO1Y (ST_Y+11)
226//#define ST_MAXAMMO1X 314
227//#define ST_MAXAMMO1Y 179
228#define ST_MAXAMMO2WIDTH ST_MAXAMMO0WIDTH
229// proff 08/18/98: Changed for high-res
230#define ST_MAXAMMO2X (ST_X+314)
231#define ST_MAXAMMO2Y (ST_Y+23)
232//#define ST_MAXAMMO2X 314
233//#define ST_MAXAMMO2Y 191
234#define ST_MAXAMMO3WIDTH ST_MAXAMMO0WIDTH
235// proff 08/18/98: Changed for high-res
236#define ST_MAXAMMO3X (ST_X+314)
237#define ST_MAXAMMO3Y (ST_Y+17)
238//#define ST_MAXAMMO3X 314
239//#define ST_MAXAMMO3Y 185
240
241// killough 2/8/98: weapon info position macros UNUSED, removed here
242
243// main player in game
244static player_t *plyr;
245
246// ST_Start() has just been called
247static boolean st_firsttime;
248
249// used to execute ST_Init() only once
250static int veryfirsttime = 1;
251
252// CPhipps - no longer do direct PLAYPAL handling here
253
254// used for timing
255static unsigned int st_clock;
256
257// used for making messages go away
258static int st_msgcounter=0;
259
260// used when in chat
261static st_chatstateenum_t st_chatstate;
262
263// whether in automap or first-person
264static st_stateenum_t st_gamestate;
265
266// whether left-side main status bar is active
267static boolean st_statusbaron;
268
269// whether status bar chat is active
270static boolean st_chat;
271
272// value of st_chat before message popped up
273static boolean st_oldchat;
274
275// whether chat window has the cursor on
276static boolean st_cursoron;
277
278// !deathmatch
279static boolean st_notdeathmatch;
280
281// !deathmatch && st_statusbaron
282static boolean st_armson;
283
284// !deathmatch
285static boolean st_fragson;
286
287// main bar left
288// CPhipps - convert to a bitmap
289static byte *sbar;
290static unsigned short sbar_width, sbar_height;
291
292// 0-9, tall numbers
293static patchnum_t tallnum[10];
294
295// tall % sign
296static patchnum_t tallpercent;
297
298// 0-9, short, yellow (,different!) numbers
299static patchnum_t shortnum[10];
300
301// 3 key-cards, 3 skulls, 3 card/skull combos
302// jff 2/24/98 extend number of patches by three skull/card combos
303static patchnum_t keys[NUMCARDS+3];
304
305// face status patches
306static patchnum_t faces[ST_NUMFACES];
307
308// face background
309static patchnum_t faceback; // CPhipps - single background, translated for different players
310
311// main bar right
312static patchnum_t armsbg;
313
314// weapon ownership patches
315static patchnum_t arms[6][2];
316
317// ready-weapon widget
318static st_number_t w_ready;
319
320//jff 2/16/98 status color change levels
321int ammo_red; // ammo percent less than which status is red
322int ammo_yellow; // ammo percent less is yellow more green
323int health_red; // health amount less than which status is red
324int health_yellow; // health amount less than which status is yellow
325int health_green; // health amount above is blue, below is green
326int armor_red; // armor amount less than which status is red
327int armor_yellow; // armor amount less than which status is yellow
328int armor_green; // armor amount above is blue, below is green
329
330// in deathmatch only, summary of frags stats
331static st_number_t w_frags;
332
333// health widget
334static st_percent_t w_health;
335
336// arms background
337static st_binicon_t w_armsbg;
338
339// weapon ownership widgets
340static st_multicon_t w_arms[6];
341
342// face status widget
343static st_multicon_t w_faces;
344
345// keycard widgets
346static st_multicon_t w_keyboxes[3];
347
348// armor widget
349static st_percent_t w_armor;
350
351// ammo widgets
352static st_number_t w_ammo[4];
353
354// max ammo widgets
355static st_number_t w_maxammo[4];
356
357// number of frags so far in deathmatch
358static int st_fragscount;
359
360// used to use appopriately pained face
361static int st_oldhealth = -1;
362
363// used for evil grin
364static boolean oldweaponsowned[NUMWEAPONS];
365
366// count until face changes
367static int st_facecount = 0;
368
369// current face index, used by w_faces
370static int st_faceindex = 0;
371
372// holds key-type for each key box on bar
373static int keyboxes[3];
374
375// a random number per tick
376static int st_randomnumber;
377
378extern char *mapnames[];
379
380
381//
382// STATUS BAR CODE
383//
384void ST_Stop(void);
385
386void ST_refreshBackground(void)
387{
388 int y=0;
389 int screen=BG;
390
391 if (st_statusbaron)
392 {
393 V_DrawNamePatch(ST_X, y, screen, "STBAR", CR_DEFAULT, VPT_STRETCH);
394
395 // killough 3/7/98: make face background change with displayplayer
396 if (netgame)
397 {
398 V_DrawNumPatch(ST_FX, y, BG, faceback.lumpnum,
399 displayplayer ? CR_LIMIT+displayplayer : CR_DEFAULT,
400 displayplayer ? (VPT_TRANS | VPT_STRETCH) : VPT_STRETCH);
401 }
402
403 V_CopyRect(ST_X, y, screen, ST_SCALED_WIDTH, ST_SCALED_HEIGHT, ST_X, ST_SCALED_Y, FG, VPT_NONE);
404 }
405}
406
407
408// Respond to keyboard input events,
409// intercept cheats.
410boolean ST_Responder(event_t *ev)
411{
412 // Filter automap on/off.
413 if (ev->type == ev_keyup && (ev->data1 & 0xffff0000) == AM_MSGHEADER)
414 {
415 switch(ev->data1)
416 {
417 case AM_MSGENTERED:
418 st_gamestate = AutomapState;
419 st_firsttime = true;
420 break;
421
422 case AM_MSGEXITED:
423 st_gamestate = FirstPersonState;
424 break;
425 }
426 }
427// else // if a user keypress...
428// if (ev->type == ev_keydown) // Try cheat responder in m_cheat.c
429// return M_FindCheats(ev->data1); // killough 4/17/98, 5/2/98
430 return false;
431}
432
433int ST_calcPainOffset(void)
434{
435 static int lastcalc;
436 static int oldhealth = -1;
437 int health = plyr->health > 100 ? 100 : plyr->health;
438
439 if (health != oldhealth)
440 {
441 lastcalc = ST_FACESTRIDE * (((100 - health) * ST_NUMPAINFACES) / 101);
442 oldhealth = health;
443 }
444 return lastcalc;
445}
446
447
448//
449// This is a not-very-pretty routine which handles
450// the face states and their timing.
451// the precedence of expressions is:
452// dead > evil grin > turned head > straight ahead
453//
454
455void ST_updateFaceWidget(void)
456{
457 int i;
458 angle_t badguyangle;
459 angle_t diffang;
460 static int lastattackdown = -1;
461 static int priority = 0;
462 boolean doevilgrin;
463
464 if (priority < 10)
465 {
466 // dead
467 if (!plyr->health)
468 {
469 priority = 9;
470 st_faceindex = ST_DEADFACE;
471 st_facecount = 1;
472 }
473 }
474
475 if (priority < 9)
476 {
477 if (plyr->bonuscount)
478 {
479 // picking up bonus
480 doevilgrin = false;
481
482 for (i=0;i<NUMWEAPONS;i++)
483 {
484 if (oldweaponsowned[i] != plyr->weaponowned[i])
485 {
486 doevilgrin = true;
487 oldweaponsowned[i] = plyr->weaponowned[i];
488 }
489 }
490 if (doevilgrin)
491 {
492 // evil grin if just picked up weapon
493 priority = 8;
494 st_facecount = ST_EVILGRINCOUNT;
495 st_faceindex = ST_calcPainOffset() + ST_EVILGRINOFFSET;
496 }
497 }
498
499 }
500
501 if (priority < 8)
502 {
503 if (plyr->damagecount && plyr->attacker && plyr->attacker != plyr->mo)
504 {
505 // being attacked
506 priority = 7;
507
508 if (plyr->health - st_oldhealth > ST_MUCHPAIN)
509 {
510 st_facecount = ST_TURNCOUNT;
511 st_faceindex = ST_calcPainOffset() + ST_OUCHOFFSET;
512 }
513 else
514 {
515 badguyangle = R_PointToAngle2(plyr->mo->x,
516 plyr->mo->y,
517 plyr->attacker->x,
518 plyr->attacker->y);
519
520 if (badguyangle > plyr->mo->angle)
521 {
522 // whether right or left
523 diffang = badguyangle - plyr->mo->angle;
524 i = diffang > ANG180;
525 }
526 else
527 {
528 // whether left or right
529 diffang = plyr->mo->angle - badguyangle;
530 i = diffang <= ANG180;
531 } // confusing, aint it?
532
533
534 st_facecount = ST_TURNCOUNT;
535 st_faceindex = ST_calcPainOffset();
536
537 if (diffang < ANG45)
538 {
539 // head-on
540 st_faceindex += ST_RAMPAGEOFFSET;
541 }
542 else if (i)
543 {
544 // turn face right
545 st_faceindex += ST_TURNOFFSET;
546 }
547 else
548 {
549 // turn face left
550 st_faceindex += ST_TURNOFFSET+1;
551 }
552 }
553 }
554 }
555
556 if (priority < 7)
557 {
558 // getting hurt because of your own damn stupidity
559 if (plyr->damagecount)
560 {
561 if (plyr->health - st_oldhealth > ST_MUCHPAIN)
562 {
563 priority = 7;
564 st_facecount = ST_TURNCOUNT;
565 st_faceindex = ST_calcPainOffset() + ST_OUCHOFFSET;
566 }
567 else
568 {
569 priority = 6;
570 st_facecount = ST_TURNCOUNT;
571 st_faceindex = ST_calcPainOffset() + ST_RAMPAGEOFFSET;
572 }
573
574 }
575
576 }
577
578 if (priority < 6)
579 {
580 // rapid firing
581 if (plyr->attackdown)
582 {
583 if (lastattackdown==-1)
584 lastattackdown = ST_RAMPAGEDELAY;
585 else if (!--lastattackdown)
586 {
587 priority = 5;
588 st_faceindex = ST_calcPainOffset() + ST_RAMPAGEOFFSET;
589 st_facecount = 1;
590 lastattackdown = 1;
591 }
592 }
593 else
594 lastattackdown = -1;
595
596 }
597
598 if (priority < 5)
599 {
600 // invulnerability
601 if ((plyr->cheats & CF_GODMODE)
602 || plyr->powers[pw_invulnerability])
603 {
604 priority = 4;
605
606 st_faceindex = ST_GODFACE;
607 st_facecount = 1;
608
609 }
610
611 }
612
613 // look left or look right if the facecount has timed out
614 if (!st_facecount)
615 {
616 st_faceindex = ST_calcPainOffset() + (st_randomnumber % 3);
617 st_facecount = ST_STRAIGHTFACECOUNT;
618 priority = 0;
619 }
620
621 st_facecount--;
622
623}
624
625int sts_traditional_keys; // killough 2/28/98: traditional status bar keys
626
627void ST_updateWidgets(void)
628{
629 static int largeammo = 1994; // means "n/a"
630 int i;
631
632 // must redirect the pointer if the ready weapon has changed.
633 // if (w_ready.data != plyr->readyweapon)
634 // {
635 if (weaponinfo[plyr->readyweapon].ammo == am_noammo)
636 w_ready.num = &largeammo;
637 else
638 w_ready.num = &plyr->ammo[weaponinfo[plyr->readyweapon].ammo];
639 //{
640 // static int tic=0;
641 // static int dir=-1;
642 // if (!(tic&15))
643 // plyr->ammo[weaponinfo[plyr->readyweapon].ammo]+=dir;
644 // if (plyr->ammo[weaponinfo[plyr->readyweapon].ammo] == -100)
645 // dir = 1;
646 // tic++;
647 // }
648 w_ready.data = plyr->readyweapon;
649
650 // if (*w_ready.on)
651 // STlib_updateNum(&w_ready, true);
652 // refresh weapon change
653 // }
654
655 // update keycard multiple widgets
656 for (i=0;i<3;i++)
657 {
658 keyboxes[i] = plyr->cards[i] ? i : -1;
659
660 //jff 2/24/98 select double key
661 //killough 2/28/98: preserve traditional keys by config option
662
663 if (plyr->cards[i+3])
664 keyboxes[i] = keyboxes[i]==-1 || sts_traditional_keys ? i+3 : i+6;
665 }
666
667 // refresh everything if this is him coming back to life
668 ST_updateFaceWidget();
669
670 // used by the w_armsbg widget
671 st_notdeathmatch = !deathmatch;
672
673 // used by w_arms[] widgets
674 st_armson = st_statusbaron && !deathmatch;
675
676 // used by w_frags widget
677 st_fragson = deathmatch && st_statusbaron;
678 st_fragscount = 0;
679
680 for (i=0 ; i<MAXPLAYERS ; i++)
681 {
682 if (i != displayplayer) // killough 3/7/98
683 st_fragscount += plyr->frags[i];
684 else
685 st_fragscount -= plyr->frags[i];
686 }
687
688 // get rid of chat window if up because of message
689 if (!--st_msgcounter)
690 st_chat = st_oldchat;
691
692}
693
694void ST_Ticker (void)
695{
696 st_clock++;
697 st_randomnumber = M_Random();
698 ST_updateWidgets();
699 st_oldhealth = plyr->health;
700}
701
702static int st_palette = 0;
703
704void ST_doPaletteStuff(void)
705{
706 int palette;
707 int cnt = plyr->damagecount;
708
709 if (plyr->powers[pw_strength])
710 {
711 // slowly fade the berzerk out
712 int bzc = 12 - (plyr->powers[pw_strength]>>6);
713 if (bzc > cnt)
714 cnt = bzc;
715 }
716
717 if (cnt)
718 {
719 palette = (cnt+7)>>3;
720 if (palette >= NUMREDPALS)
721 palette = NUMREDPALS-1;
722 palette += STARTREDPALS;
723 }
724 else
725 if (plyr->bonuscount)
726 {
727 palette = (plyr->bonuscount+7)>>3;
728 if (palette >= NUMBONUSPALS)
729 palette = NUMBONUSPALS-1;
730 palette += STARTBONUSPALS;
731 }
732 else
733 if (plyr->powers[pw_ironfeet] > 4*32 || plyr->powers[pw_ironfeet] & 8)
734 palette = RADIATIONPAL;
735 else
736 palette = 0;
737
738 if (palette != st_palette)
739 V_SetPalette(st_palette = palette); // CPhipps - use new palette function
740}
741
742void ST_drawWidgets(boolean refresh)
743{
744 int i;
745
746 // used by w_arms[] widgets
747 st_armson = st_statusbaron && !deathmatch;
748
749 // used by w_frags widget
750 st_fragson = deathmatch && st_statusbaron;
751
752 //jff 2/16/98 make color of ammo depend on amount
753 if (*w_ready.num*100 < ammo_red*plyr->maxammo[weaponinfo[w_ready.data].ammo])
754 STlib_updateNum(&w_ready, CR_RED, refresh);
755 else
756 if (*w_ready.num*100 <
757 ammo_yellow*plyr->maxammo[weaponinfo[w_ready.data].ammo])
758 STlib_updateNum(&w_ready, CR_GOLD, refresh);
759 else
760 STlib_updateNum(&w_ready, CR_GREEN, refresh);
761
762 for (i=0;i<4;i++)
763 {
764 STlib_updateNum(&w_ammo[i], CR_DEFAULT, refresh);
765 STlib_updateNum(&w_maxammo[i], CR_DEFAULT, refresh);
766 }
767
768 //jff 2/16/98 make color of health depend on amount
769 if (*w_health.n.num<health_red)
770 STlib_updatePercent(&w_health, CR_RED, refresh);
771 else if (*w_health.n.num<health_yellow)
772 STlib_updatePercent(&w_health, CR_GOLD, refresh);
773 else if (*w_health.n.num<=health_green)
774 STlib_updatePercent(&w_health, CR_GREEN, refresh);
775 else
776 STlib_updatePercent(&w_health, CR_BLUE2, refresh); //killough 2/28/98
777
778 //jff 2/16/98 make color of armor depend on amount
779 if (*w_armor.n.num<armor_red)
780 STlib_updatePercent(&w_armor, CR_RED, refresh);
781 else if (*w_armor.n.num<armor_yellow)
782 STlib_updatePercent(&w_armor, CR_GOLD, refresh);
783 else if (*w_armor.n.num<=armor_green)
784 STlib_updatePercent(&w_armor, CR_GREEN, refresh);
785 else
786 STlib_updatePercent(&w_armor, CR_BLUE2, refresh); //killough 2/28/98
787
788 STlib_updateBinIcon(&w_armsbg, refresh);
789
790 for (i=0;i<6;i++)
791 STlib_updateMultIcon(&w_arms[i], refresh);
792
793 STlib_updateMultIcon(&w_faces, refresh);
794
795 for (i=0;i<3;i++)
796 STlib_updateMultIcon(&w_keyboxes[i], refresh);
797
798 STlib_updateNum(&w_frags, CR_DEFAULT, refresh);
799
800}
801
802void ST_doRefresh(void)
803{
804
805 st_firsttime = false;
806
807 // draw status bar background to off-screen buff
808 ST_refreshBackground();
809
810 // and refresh all widgets
811 ST_drawWidgets(true);
812
813}
814
815void ST_diffDraw(void)
816{
817 // update all widgets
818 ST_drawWidgets(false);
819}
820
821void ST_Drawer(boolean st_statusbaron, boolean refresh)
822{
823 /* cph - let status bar on be controlled
824 * completely by the call from D_Display
825 * proff - really do it
826 */
827 st_firsttime = st_firsttime || refresh;
828
829 ST_doPaletteStuff(); // Do red-/gold-shifts from damage/items
830
831 if (st_statusbaron) {
832 if (st_firsttime)
833 ST_doRefresh(); /* If just after ST_Start(), refresh all */
834 else
835 ST_diffDraw(); /* Otherwise, update as little as possible */
836 }
837}
838
839//
840// ST_loadGraphics
841//
842// CPhipps - Loads graphics needed for status bar if doload is true,
843// unloads them otherwise
844//
845static void ST_loadGraphics(boolean doload)
846{
847
848 int i,facenum;
849
850 char namebuf[9];
851 // cph - macro that either acquires a pointer and lock for a lump, or
852 // unlocks it. var is referenced exactly once in either case, so ++ in arg works
853 /*
854 #define LOADORFREE(var,name) \
855 if (!doload) { W_UnlockLumpName(name); var = NULL; } \
856 else var = (const patch_t*)W_CacheLumpName(name)
857 */
858
859 // Load the numbers, tall and short
860 for (i=0;i<10;i++)
861 {
862 snprintf(namebuf, sizeof(namebuf),"STTNUM%d", i);
863 R_SetPatchNum(&tallnum[i],namebuf);
864
865 snprintf(namebuf, sizeof(namebuf),"STYSNUM%d", i);
866 R_SetPatchNum(&shortnum[i],namebuf);
867 }
868
869 // Load percent key.
870 R_SetPatchNum(&tallpercent,"STTPRCNT");
871
872 // key cards
873 for (i=0;i<NUMCARDS+3;i++) //jff 2/23/98 show both keys too
874 {
875 snprintf(namebuf, sizeof(namebuf), "STKEYS%d", i);
876 R_SetPatchNum(&keys[i], namebuf);
877 }
878
879 // arms background
880 R_SetPatchNum(&armsbg, "STARMS");
881
882 // arms ownership widgets
883 for (i=0;i<6;i++)
884 {
885 snprintf(namebuf, sizeof(namebuf),"STGNUM%d", i+2);
886 // gray #
887 R_SetPatchNum(&arms[i][0], namebuf);
888
889 // yellow #
890 arms[i][1] = shortnum[i+2];
891 }
892
893 // face backgrounds for different color players
894 // killough 3/7/98: add better support for spy mode by loading all
895 // player face backgrounds and using displayplayer to choose them:
896 R_SetPatchNum(&faceback, "STFB0");
897
898 // status bar background bits
899 if (doload)
900 sbar = V_PatchToBlock("STBAR", CR_DEFAULT, VPT_NONE,
901 &sbar_width, &sbar_height);
902 else {
903 free(sbar); sbar=NULL;
904 }
905
906 // face states
907 facenum = 0;
908 for (i=0;i<ST_NUMPAINFACES;i++)
909 {
910 int j;
911 for (j=0;j<ST_NUMSTRAIGHTFACES;j++)
912 {
913 snprintf(namebuf, sizeof(namebuf), "STFST%d%d", i, j);
914 R_SetPatchNum(&faces[facenum++], namebuf);
915 }
916 snprintf(namebuf, sizeof(namebuf), "STFTR%d0", i); // turn right
917 R_SetPatchNum(&faces[facenum++], namebuf);
918 snprintf(namebuf, sizeof(namebuf), "STFTL%d0", i); // turn left
919 R_SetPatchNum(&faces[facenum++], namebuf);
920 snprintf(namebuf, sizeof(namebuf), "STFOUCH%d", i); // ouch!
921 R_SetPatchNum(&faces[facenum++], namebuf);
922 snprintf(namebuf, sizeof(namebuf), "STFEVL%d", i); // evil grin ;)
923 R_SetPatchNum(&faces[facenum++], namebuf);
924 snprintf(namebuf, sizeof(namebuf), "STFKILL%d", i); // pissed off
925 R_SetPatchNum(&faces[facenum++], namebuf);
926 }
927 R_SetPatchNum(&faces[facenum++], "STFGOD0");
928 R_SetPatchNum(&faces[facenum++], "STFDEAD0");
929}
930
931void ST_loadData(void)
932{
933 ST_loadGraphics(true);
934}
935
936void ST_unloadData(void)
937{
938 ST_loadGraphics(false);
939}
940
941void ST_initData(void)
942{
943 int i;
944
945 st_firsttime = true;
946 plyr = &players[displayplayer]; // killough 3/7/98
947
948 st_clock = 0;
949 st_chatstate = StartChatState;
950 st_gamestate = FirstPersonState;
951
952 st_statusbaron = true;
953 st_oldchat = st_chat = false;
954 st_cursoron = false;
955
956 st_faceindex = 0;
957 st_palette = -1;
958
959 st_oldhealth = -1;
960
961 for (i=0;i<NUMWEAPONS;i++)
962 oldweaponsowned[i] = plyr->weaponowned[i];
963
964 for (i=0;i<3;i++)
965 keyboxes[i] = -1;
966
967 STlib_init();
968}
969
970void ST_createWidgets(void)
971{
972 int i;
973
974 // ready weapon ammo
975 STlib_initNum(&w_ready,
976 ST_AMMOX,
977 ST_AMMOY,
978 tallnum,
979 &plyr->ammo[weaponinfo[plyr->readyweapon].ammo],
980 &st_statusbaron,
981 ST_AMMOWIDTH );
982
983 // the last weapon type
984 w_ready.data = plyr->readyweapon;
985
986 // health percentage
987 STlib_initPercent(&w_health,
988 ST_HEALTHX,
989 ST_HEALTHY,
990 tallnum,
991 &plyr->health,
992 &st_statusbaron,
993 &tallpercent);
994
995 // arms background
996 STlib_initBinIcon(&w_armsbg,
997 ST_ARMSBGX,
998 ST_ARMSBGY,
999 &armsbg,
1000 &st_notdeathmatch,
1001 &st_statusbaron);
1002
1003 // weapons owned
1004 for(i=0;i<6;i++)
1005 {
1006 STlib_initMultIcon(&w_arms[i],
1007 ST_ARMSX+(i%3)*ST_ARMSXSPACE,
1008 ST_ARMSY+(i/3)*ST_ARMSYSPACE,
1009 arms[i], (int *) &plyr->weaponowned[i+1],
1010 &st_armson);
1011 }
1012
1013 // frags sum
1014 STlib_initNum(&w_frags,
1015 ST_FRAGSX,
1016 ST_FRAGSY,
1017 tallnum,
1018 &st_fragscount,
1019 &st_fragson,
1020 ST_FRAGSWIDTH);
1021
1022 // faces
1023 STlib_initMultIcon(&w_faces,
1024 ST_FACESX,
1025 ST_FACESY,
1026 faces,
1027 &st_faceindex,
1028 &st_statusbaron);
1029
1030 // armor percentage - should be colored later
1031 STlib_initPercent(&w_armor,
1032 ST_ARMORX,
1033 ST_ARMORY,
1034 tallnum,
1035 &plyr->armorpoints,
1036 &st_statusbaron, &tallpercent);
1037
1038 // keyboxes 0-2
1039 STlib_initMultIcon(&w_keyboxes[0],
1040 ST_KEY0X,
1041 ST_KEY0Y,
1042 keys,
1043 &keyboxes[0],
1044 &st_statusbaron);
1045
1046 STlib_initMultIcon(&w_keyboxes[1],
1047 ST_KEY1X,
1048 ST_KEY1Y,
1049 keys,
1050 &keyboxes[1],
1051 &st_statusbaron);
1052
1053 STlib_initMultIcon(&w_keyboxes[2],
1054 ST_KEY2X,
1055 ST_KEY2Y,
1056 keys,
1057 &keyboxes[2],
1058 &st_statusbaron);
1059
1060 // ammo count (all four kinds)
1061 STlib_initNum(&w_ammo[0],
1062 ST_AMMO0X,
1063 ST_AMMO0Y,
1064 shortnum,
1065 &plyr->ammo[0],
1066 &st_statusbaron,
1067 ST_AMMO0WIDTH);
1068
1069 STlib_initNum(&w_ammo[1],
1070 ST_AMMO1X,
1071 ST_AMMO1Y,
1072 shortnum,
1073 &plyr->ammo[1],
1074 &st_statusbaron,
1075 ST_AMMO1WIDTH);
1076
1077 STlib_initNum(&w_ammo[2],
1078 ST_AMMO2X,
1079 ST_AMMO2Y,
1080 shortnum,
1081 &plyr->ammo[2],
1082 &st_statusbaron,
1083 ST_AMMO2WIDTH);
1084
1085 STlib_initNum(&w_ammo[3],
1086 ST_AMMO3X,
1087 ST_AMMO3Y,
1088 shortnum,
1089 &plyr->ammo[3],
1090 &st_statusbaron,
1091 ST_AMMO3WIDTH);
1092
1093 // max ammo count (all four kinds)
1094 STlib_initNum(&w_maxammo[0],
1095 ST_MAXAMMO0X,
1096 ST_MAXAMMO0Y,
1097 shortnum,
1098 &plyr->maxammo[0],
1099 &st_statusbaron,
1100 ST_MAXAMMO0WIDTH);
1101
1102 STlib_initNum(&w_maxammo[1],
1103 ST_MAXAMMO1X,
1104 ST_MAXAMMO1Y,
1105 shortnum,
1106 &plyr->maxammo[1],
1107 &st_statusbaron,
1108 ST_MAXAMMO1WIDTH);
1109
1110 STlib_initNum(&w_maxammo[2],
1111 ST_MAXAMMO2X,
1112 ST_MAXAMMO2Y,
1113 shortnum,
1114 &plyr->maxammo[2],
1115 &st_statusbaron,
1116 ST_MAXAMMO2WIDTH);
1117
1118 STlib_initNum(&w_maxammo[3],
1119 ST_MAXAMMO3X,
1120 ST_MAXAMMO3Y,
1121 shortnum,
1122 &plyr->maxammo[3],
1123 &st_statusbaron,
1124 ST_MAXAMMO3WIDTH);
1125}
1126
1127static boolean st_stopped = true;
1128
1129void ST_Start(void)
1130{
1131 if (!st_stopped)
1132 ST_Stop();
1133 ST_initData();
1134 ST_createWidgets();
1135 st_stopped = false;
1136}
1137
1138void ST_Stop(void)
1139{
1140 if (st_stopped)
1141 return;
1142 V_SetPalette(0);
1143 st_stopped = true;
1144}
1145
1146void ST_Init(void)
1147{
1148 veryfirsttime = 0;
1149 ST_loadData();
1150 // proff 08/18/98: Changed for high-res
1151 screens[4] = Z_Malloc(SCREENWIDTH*(ST_SCALED_HEIGHT+1), PU_STATIC, 0);
1152 // screens[4] = Z_Malloc(ST_WIDTH*ST_HEIGHT, PU_STATIC, 0);
1153}
diff --git a/apps/plugins/doom/st_stuff.h b/apps/plugins/doom/st_stuff.h
new file mode 100644
index 0000000000..d65b01e571
--- /dev/null
+++ b/apps/plugins/doom/st_stuff.h
@@ -0,0 +1,101 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION:
28 * Status bar code.
29 * Does the face/direction indicator animatin.
30 * Does palette indicators as well (red pain/berserk, bright pickup)
31 *
32 *-----------------------------------------------------------------------------*/
33
34#ifndef __STSTUFF_H__
35#define __STSTUFF_H__
36
37#include "doomtype.h"
38#include "d_event.h"
39
40// Size of statusbar.
41// Now sensitive for scaling.
42
43// proff 08/18/98: Changed for high-res
44#define ST_HEIGHT 32
45#define ST_WIDTH 320
46#define ST_Y (200 - ST_HEIGHT)
47#define ST_SCALED_HEIGHT (ST_HEIGHT*SCREENHEIGHT/200)
48#define ST_SCALED_WIDTH SCREENWIDTH
49#define ST_SCALED_Y (SCREENHEIGHT - ST_SCALED_HEIGHT)
50
51//
52// STATUS BAR
53//
54
55// Called by main loop.
56boolean ST_Responder(event_t* ev);
57
58// Called by main loop.
59void ST_Ticker(void);
60
61// Called by main loop.
62void ST_Drawer(boolean st_statusbaron, boolean refresh);
63
64// Called when the console player is spawned on each level.
65void ST_Start(void);
66
67// Called by startup code.
68void ST_Init(void);
69
70// States for status bar code.
71typedef enum
72{
73 AutomapState,
74 FirstPersonState
75} st_stateenum_t;
76
77// States for the chat code.
78typedef enum
79{
80 StartChatState,
81 WaitDestState,
82 GetChatState
83} st_chatstateenum_t;
84
85boolean ST_Responder(event_t* ev);
86
87// killough 5/2/98: moved from m_misc.c:
88
89extern int health_red; // health amount less than which status is red
90extern int health_yellow; // health amount less than which status is yellow
91extern int health_green; // health amount above is blue, below is green
92extern int armor_red; // armor amount less than which status is red
93extern int armor_yellow; // armor amount less than which status is yellow
94extern int armor_green; // armor amount above is blue, below is green
95extern int ammo_red; // ammo percent less than which status is red
96extern int ammo_yellow; // ammo percent less is yellow more green
97extern int sts_always_red;// status numbers do not change colors
98extern int sts_pct_always_gray;// status percents do not change colors
99extern int sts_traditional_keys; // display keys the traditional way
100
101#endif
diff --git a/apps/plugins/doom/tables.c b/apps/plugins/doom/tables.c
new file mode 100644
index 0000000000..dfb237649a
--- /dev/null
+++ b/apps/plugins/doom/tables.c
@@ -0,0 +1,2196 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION:
28 * Lookup tables.
29 * Do not try to look them up :-).
30 * In the order of appearance:
31 *
32 * int finetangent[4096] - Tangens LUT.
33 * Should work with BAM fairly well (12 of 16bit,
34 * effectively, by shifting).
35 *
36 * int finesine[10240] - Sine lookup.
37 * Guess what, serves as cosine, too.
38 * Remarkable thing is, how to use BAMs with this?
39 *
40 * int tantoangle[2049] - ArcTan LUT,
41 * maps tan(angle) to angle fast. Gotta search.
42 *
43 *-----------------------------------------------------------------------------
44 */
45
46#include "w_wad.h"
47#include "tables.h"
48#include "i_system.h"
49
50// killough 5/3/98: reformatted
51
52int SlopeDiv(unsigned num, unsigned den)
53{
54 unsigned ans;
55
56 if (den < 512)
57 return SLOPERANGE;
58 ans = (num<<3)/(den>>8);
59 return ans <= SLOPERANGE ? ans : SLOPERANGE;
60}
61
62#ifdef TABLES_AS_LUMPS
63fixed_t *finetangent;
64#else
65const fixed_t finetangent[4096] = { -170910304,
66 -56965752,-34178904,-24413316,-18988036,-15535599,-13145455,-11392683,
67 -10052327,-8994149,-8137527,-7429880,-6835455,-6329090,-5892567,-5512368,
68 -5178251,-4882318,-4618375,-4381502,-4167737,-3973855,-3797206,-3635590,
69 -3487165,-3350381,-3223918,-3106651,-2997613,-2895966,-2800983,-2712030,
70 -2628549,-2550052,-2476104,-2406322,-2340362,-2277919,-2218719,-2162516,
71 -2109087,-2058233,-2009771,-1963536,-1919378,-1877161,-1836758,-1798063,
72 -1760956,-1725348,-1691149,-1658278,-1626658,-1596220,-1566898,-1538632,
73 -1511367,-1485049,-1459630,-1435065,-1411312,-1388330,-1366084,-1344537,
74 -1323658,-1303416,-1283783,-1264730,-1246234,-1228269,-1210813,-1193846,
75 -1177345,-1161294,-1145673,-1130465,-1115654,-1101225,-1087164,-1073455,
76 -1060087,-1047046,-1034322,-1021901,-1009774,-997931,-986361,-975054,
77 -964003,-953199,-942633,-932298,-922186,-912289,-902602,-893117,
78 -883829,-874730,-865817,-857081,-848520,-840127,-831898,-823827,
79 -815910,-808143,-800521,-793041,-785699,-778490,-771411,-764460,
80 -757631,-750922,-744331,-737853,-731486,-725227,-719074,-713023,
81 -707072,-701219,-695462,-689797,-684223,-678737,-673338,-668024,
82 -662792,-657640,-652568,-647572,-642651,-637803,-633028,-628323,
83 -623686,-619117,-614613,-610174,-605798,-601483,-597229,-593033,
84 -588896,-584815,-580789,-576818,-572901,-569035,-565221,-561456,
85 -557741,-554074,-550455,-546881,-543354,-539870,-536431,-533034,
86 -529680,-526366,-523094,-519861,-516667,-513512,-510394,-507313,
87 -504269,-501261,-498287,-495348,-492443,-489571,-486732,-483925,
88 -481150,-478406,-475692,-473009,-470355,-467730,-465133,-462565,
89 -460024,-457511,-455024,-452564,-450129,-447720,-445337,-442978,
90 -440643,-438332,-436045,-433781,-431540,-429321,-427125,-424951,
91 -422798,-420666,-418555,-416465,-414395,-412344,-410314,-408303,
92 -406311,-404338,-402384,-400448,-398530,-396630,-394747,-392882,
93 -391034,-389202,-387387,-385589,-383807,-382040,-380290,-378555,
94 -376835,-375130,-373440,-371765,-370105,-368459,-366826,-365208,
95 -363604,-362013,-360436,-358872,-357321,-355783,-354257,-352744,
96 -351244,-349756,-348280,-346816,-345364,-343924,-342495,-341078,
97 -339671,-338276,-336892,-335519,-334157,-332805,-331464,-330133,
98 -328812,-327502,-326201,-324910,-323629,-322358,-321097,-319844,
99 -318601,-317368,-316143,-314928,-313721,-312524,-311335,-310154,
100 -308983,-307819,-306664,-305517,-304379,-303248,-302126,-301011,
101 -299904,-298805,-297714,-296630,-295554,-294485,-293423,-292369,
102 -291322,-290282,-289249,-288223,-287204,-286192,-285186,-284188,
103 -283195,-282210,-281231,-280258,-279292,-278332,-277378,-276430,
104 -275489,-274553,-273624,-272700,-271782,-270871,-269965,-269064,
105 -268169,-267280,-266397,-265519,-264646,-263779,-262917,-262060,
106 -261209,-260363,-259522,-258686,-257855,-257029,-256208,-255392,
107 -254581,-253774,-252973,-252176,-251384,-250596,-249813,-249035,
108 -248261,-247492,-246727,-245966,-245210,-244458,-243711,-242967,
109 -242228,-241493,-240763,-240036,-239314,-238595,-237881,-237170,
110 -236463,-235761,-235062,-234367,-233676,-232988,-232304,-231624,
111 -230948,-230275,-229606,-228941,-228279,-227621,-226966,-226314,
112 -225666,-225022,-224381,-223743,-223108,-222477,-221849,-221225,
113 -220603,-219985,-219370,-218758,-218149,-217544,-216941,-216341,
114 -215745,-215151,-214561,-213973,-213389,-212807,-212228,-211652,
115 -211079,-210509,-209941,-209376,-208815,-208255,-207699,-207145,
116 -206594,-206045,-205500,-204956,-204416,-203878,-203342,-202809,
117 -202279,-201751,-201226,-200703,-200182,-199664,-199149,-198636,
118 -198125,-197616,-197110,-196606,-196105,-195606,-195109,-194614,
119 -194122,-193631,-193143,-192658,-192174,-191693,-191213,-190736,
120 -190261,-189789,-189318,-188849,-188382,-187918,-187455,-186995,
121 -186536,-186080,-185625,-185173,-184722,-184274,-183827,-183382,
122 -182939,-182498,-182059,-181622,-181186,-180753,-180321,-179891,
123 -179463,-179037,-178612,-178190,-177769,-177349,-176932,-176516,
124 -176102,-175690,-175279,-174870,-174463,-174057,-173653,-173251,
125 -172850,-172451,-172053,-171657,-171263,-170870,-170479,-170089,
126 -169701,-169315,-168930,-168546,-168164,-167784,-167405,-167027,
127 -166651,-166277,-165904,-165532,-165162,-164793,-164426,-164060,
128 -163695,-163332,-162970,-162610,-162251,-161893,-161537,-161182,
129 -160828,-160476,-160125,-159775,-159427,-159079,-158734,-158389,
130 -158046,-157704,-157363,-157024,-156686,-156349,-156013,-155678,
131 -155345,-155013,-154682,-154352,-154024,-153697,-153370,-153045,
132 -152722,-152399,-152077,-151757,-151438,-151120,-150803,-150487,
133 -150172,-149859,-149546,-149235,-148924,-148615,-148307,-148000,
134 -147693,-147388,-147084,-146782,-146480,-146179,-145879,-145580,
135 -145282,-144986,-144690,-144395,-144101,-143808,-143517,-143226,
136 -142936,-142647,-142359,-142072,-141786,-141501,-141217,-140934,
137 -140651,-140370,-140090,-139810,-139532,-139254,-138977,-138701,
138 -138426,-138152,-137879,-137607,-137335,-137065,-136795,-136526,
139 -136258,-135991,-135725,-135459,-135195,-134931,-134668,-134406,
140 -134145,-133884,-133625,-133366,-133108,-132851,-132594,-132339,
141 -132084,-131830,-131576,-131324,-131072,-130821,-130571,-130322,
142 -130073,-129825,-129578,-129332,-129086,-128841,-128597,-128353,
143 -128111,-127869,-127627,-127387,-127147,-126908,-126669,-126432,
144 -126195,-125959,-125723,-125488,-125254,-125020,-124787,-124555,
145 -124324,-124093,-123863,-123633,-123404,-123176,-122949,-122722,
146 -122496,-122270,-122045,-121821,-121597,-121374,-121152,-120930,
147 -120709,-120489,-120269,-120050,-119831,-119613,-119396,-119179,
148 -118963,-118747,-118532,-118318,-118104,-117891,-117678,-117466,
149 -117254,-117044,-116833,-116623,-116414,-116206,-115998,-115790,
150 -115583,-115377,-115171,-114966,-114761,-114557,-114354,-114151,
151 -113948,-113746,-113545,-113344,-113143,-112944,-112744,-112546,
152 -112347,-112150,-111952,-111756,-111560,-111364,-111169,-110974,
153 -110780,-110586,-110393,-110200,-110008,-109817,-109626,-109435,
154 -109245,-109055,-108866,-108677,-108489,-108301,-108114,-107927,
155 -107741,-107555,-107369,-107184,-107000,-106816,-106632,-106449,
156 -106266,-106084,-105902,-105721,-105540,-105360,-105180,-105000,
157 -104821,-104643,-104465,-104287,-104109,-103933,-103756,-103580,
158 -103404,-103229,-103054,-102880,-102706,-102533,-102360,-102187,
159 -102015,-101843,-101671,-101500,-101330,-101159,-100990,-100820,
160 -100651,-100482,-100314,-100146,-99979,-99812,-99645,-99479,
161 -99313,-99148,-98982,-98818,-98653,-98489,-98326,-98163,
162 -98000,-97837,-97675,-97513,-97352,-97191,-97030,-96870,
163 -96710,-96551,-96391,-96233,-96074,-95916,-95758,-95601,
164 -95444,-95287,-95131,-94975,-94819,-94664,-94509,-94354,
165 -94200,-94046,-93892,-93739,-93586,-93434,-93281,-93129,
166 -92978,-92826,-92675,-92525,-92375,-92225,-92075,-91926,
167 -91777,-91628,-91480,-91332,-91184,-91036,-90889,-90742,
168 -90596,-90450,-90304,-90158,-90013,-89868,-89724,-89579,
169 -89435,-89292,-89148,-89005,-88862,-88720,-88577,-88435,
170 -88294,-88152,-88011,-87871,-87730,-87590,-87450,-87310,
171 -87171,-87032,-86893,-86755,-86616,-86479,-86341,-86204,
172 -86066,-85930,-85793,-85657,-85521,-85385,-85250,-85114,
173 -84980,-84845,-84710,-84576,-84443,-84309,-84176,-84043,
174 -83910,-83777,-83645,-83513,-83381,-83250,-83118,-82987,
175 -82857,-82726,-82596,-82466,-82336,-82207,-82078,-81949,
176 -81820,-81691,-81563,-81435,-81307,-81180,-81053,-80925,
177 -80799,-80672,-80546,-80420,-80294,-80168,-80043,-79918,
178 -79793,-79668,-79544,-79420,-79296,-79172,-79048,-78925,
179 -78802,-78679,-78557,-78434,-78312,-78190,-78068,-77947,
180 -77826,-77705,-77584,-77463,-77343,-77223,-77103,-76983,
181 -76864,-76744,-76625,-76506,-76388,-76269,-76151,-76033,
182 -75915,-75797,-75680,-75563,-75446,-75329,-75213,-75096,
183 -74980,-74864,-74748,-74633,-74517,-74402,-74287,-74172,
184 -74058,-73944,-73829,-73715,-73602,-73488,-73375,-73262,
185 -73149,-73036,-72923,-72811,-72699,-72587,-72475,-72363,
186 -72252,-72140,-72029,-71918,-71808,-71697,-71587,-71477,
187 -71367,-71257,-71147,-71038,-70929,-70820,-70711,-70602,
188 -70494,-70385,-70277,-70169,-70061,-69954,-69846,-69739,
189 -69632,-69525,-69418,-69312,-69205,-69099,-68993,-68887,
190 -68781,-68676,-68570,-68465,-68360,-68255,-68151,-68046,
191 -67942,-67837,-67733,-67629,-67526,-67422,-67319,-67216,
192 -67113,-67010,-66907,-66804,-66702,-66600,-66498,-66396,
193 -66294,-66192,-66091,-65989,-65888,-65787,-65686,-65586,
194 -65485,-65385,-65285,-65185,-65085,-64985,-64885,-64786,
195 -64687,-64587,-64488,-64389,-64291,-64192,-64094,-63996,
196 -63897,-63799,-63702,-63604,-63506,-63409,-63312,-63215,
197 -63118,-63021,-62924,-62828,-62731,-62635,-62539,-62443,
198 -62347,-62251,-62156,-62060,-61965,-61870,-61775,-61680,
199 -61585,-61491,-61396,-61302,-61208,-61114,-61020,-60926,
200 -60833,-60739,-60646,-60552,-60459,-60366,-60273,-60181,
201 -60088,-59996,-59903,-59811,-59719,-59627,-59535,-59444,
202 -59352,-59261,-59169,-59078,-58987,-58896,-58805,-58715,
203 -58624,-58534,-58443,-58353,-58263,-58173,-58083,-57994,
204 -57904,-57815,-57725,-57636,-57547,-57458,-57369,-57281,
205 -57192,-57104,-57015,-56927,-56839,-56751,-56663,-56575,
206 -56487,-56400,-56312,-56225,-56138,-56051,-55964,-55877,
207 -55790,-55704,-55617,-55531,-55444,-55358,-55272,-55186,
208 -55100,-55015,-54929,-54843,-54758,-54673,-54587,-54502,
209 -54417,-54333,-54248,-54163,-54079,-53994,-53910,-53826,
210 -53741,-53657,-53574,-53490,-53406,-53322,-53239,-53156,
211 -53072,-52989,-52906,-52823,-52740,-52657,-52575,-52492,
212 -52410,-52327,-52245,-52163,-52081,-51999,-51917,-51835,
213 -51754,-51672,-51591,-51509,-51428,-51347,-51266,-51185,
214 -51104,-51023,-50942,-50862,-50781,-50701,-50621,-50540,
215 -50460,-50380,-50300,-50221,-50141,-50061,-49982,-49902,
216 -49823,-49744,-49664,-49585,-49506,-49427,-49349,-49270,
217 -49191,-49113,-49034,-48956,-48878,-48799,-48721,-48643,
218 -48565,-48488,-48410,-48332,-48255,-48177,-48100,-48022,
219 -47945,-47868,-47791,-47714,-47637,-47560,-47484,-47407,
220 -47331,-47254,-47178,-47102,-47025,-46949,-46873,-46797,
221 -46721,-46646,-46570,-46494,-46419,-46343,-46268,-46193,
222 -46118,-46042,-45967,-45892,-45818,-45743,-45668,-45593,
223 -45519,-45444,-45370,-45296,-45221,-45147,-45073,-44999,
224 -44925,-44851,-44778,-44704,-44630,-44557,-44483,-44410,
225 -44337,-44263,-44190,-44117,-44044,-43971,-43898,-43826,
226 -43753,-43680,-43608,-43535,-43463,-43390,-43318,-43246,
227 -43174,-43102,-43030,-42958,-42886,-42814,-42743,-42671,
228 -42600,-42528,-42457,-42385,-42314,-42243,-42172,-42101,
229 -42030,-41959,-41888,-41817,-41747,-41676,-41605,-41535,
230 -41465,-41394,-41324,-41254,-41184,-41113,-41043,-40973,
231 -40904,-40834,-40764,-40694,-40625,-40555,-40486,-40416,
232 -40347,-40278,-40208,-40139,-40070,-40001,-39932,-39863,
233 -39794,-39726,-39657,-39588,-39520,-39451,-39383,-39314,
234 -39246,-39178,-39110,-39042,-38973,-38905,-38837,-38770,
235 -38702,-38634,-38566,-38499,-38431,-38364,-38296,-38229,
236 -38161,-38094,-38027,-37960,-37893,-37826,-37759,-37692,
237 -37625,-37558,-37491,-37425,-37358,-37291,-37225,-37158,
238 -37092,-37026,-36959,-36893,-36827,-36761,-36695,-36629,
239 -36563,-36497,-36431,-36365,-36300,-36234,-36168,-36103,
240 -36037,-35972,-35907,-35841,-35776,-35711,-35646,-35580,
241 -35515,-35450,-35385,-35321,-35256,-35191,-35126,-35062,
242 -34997,-34932,-34868,-34803,-34739,-34675,-34610,-34546,
243 -34482,-34418,-34354,-34289,-34225,-34162,-34098,-34034,
244 -33970,-33906,-33843,-33779,-33715,-33652,-33588,-33525,
245 -33461,-33398,-33335,-33272,-33208,-33145,-33082,-33019,
246 -32956,-32893,-32830,-32767,-32705,-32642,-32579,-32516,
247 -32454,-32391,-32329,-32266,-32204,-32141,-32079,-32017,
248 -31955,-31892,-31830,-31768,-31706,-31644,-31582,-31520,
249 -31458,-31396,-31335,-31273,-31211,-31150,-31088,-31026,
250 -30965,-30904,-30842,-30781,-30719,-30658,-30597,-30536,
251 -30474,-30413,-30352,-30291,-30230,-30169,-30108,-30048,
252 -29987,-29926,-29865,-29805,-29744,-29683,-29623,-29562,
253 -29502,-29441,-29381,-29321,-29260,-29200,-29140,-29080,
254 -29020,-28959,-28899,-28839,-28779,-28719,-28660,-28600,
255 -28540,-28480,-28420,-28361,-28301,-28241,-28182,-28122,
256 -28063,-28003,-27944,-27884,-27825,-27766,-27707,-27647,
257 -27588,-27529,-27470,-27411,-27352,-27293,-27234,-27175,
258 -27116,-27057,-26998,-26940,-26881,-26822,-26763,-26705,
259 -26646,-26588,-26529,-26471,-26412,-26354,-26295,-26237,
260 -26179,-26120,-26062,-26004,-25946,-25888,-25830,-25772,
261 -25714,-25656,-25598,-25540,-25482,-25424,-25366,-25308,
262 -25251,-25193,-25135,-25078,-25020,-24962,-24905,-24847,
263 -24790,-24732,-24675,-24618,-24560,-24503,-24446,-24389,
264 -24331,-24274,-24217,-24160,-24103,-24046,-23989,-23932,
265 -23875,-23818,-23761,-23704,-23647,-23591,-23534,-23477,
266 -23420,-23364,-23307,-23250,-23194,-23137,-23081,-23024,
267 -22968,-22911,-22855,-22799,-22742,-22686,-22630,-22573,
268 -22517,-22461,-22405,-22349,-22293,-22237,-22181,-22125,
269 -22069,-22013,-21957,-21901,-21845,-21789,-21733,-21678,
270 -21622,-21566,-21510,-21455,-21399,-21343,-21288,-21232,
271 -21177,-21121,-21066,-21010,-20955,-20900,-20844,-20789,
272 -20734,-20678,-20623,-20568,-20513,-20457,-20402,-20347,
273 -20292,-20237,-20182,-20127,-20072,-20017,-19962,-19907,
274 -19852,-19797,-19742,-19688,-19633,-19578,-19523,-19469,
275 -19414,-19359,-19305,-19250,-19195,-19141,-19086,-19032,
276 -18977,-18923,-18868,-18814,-18760,-18705,-18651,-18597,
277 -18542,-18488,-18434,-18380,-18325,-18271,-18217,-18163,
278 -18109,-18055,-18001,-17946,-17892,-17838,-17784,-17731,
279 -17677,-17623,-17569,-17515,-17461,-17407,-17353,-17300,
280 -17246,-17192,-17138,-17085,-17031,-16977,-16924,-16870,
281 -16817,-16763,-16710,-16656,-16603,-16549,-16496,-16442,
282 -16389,-16335,-16282,-16229,-16175,-16122,-16069,-16015,
283 -15962,-15909,-15856,-15802,-15749,-15696,-15643,-15590,
284 -15537,-15484,-15431,-15378,-15325,-15272,-15219,-15166,
285 -15113,-15060,-15007,-14954,-14901,-14848,-14795,-14743,
286 -14690,-14637,-14584,-14531,-14479,-14426,-14373,-14321,
287 -14268,-14215,-14163,-14110,-14057,-14005,-13952,-13900,
288 -13847,-13795,-13742,-13690,-13637,-13585,-13533,-13480,
289 -13428,-13375,-13323,-13271,-13218,-13166,-13114,-13062,
290 -13009,-12957,-12905,-12853,-12800,-12748,-12696,-12644,
291 -12592,-12540,-12488,-12436,-12383,-12331,-12279,-12227,
292 -12175,-12123,-12071,-12019,-11967,-11916,-11864,-11812,
293 -11760,-11708,-11656,-11604,-11552,-11501,-11449,-11397,
294 -11345,-11293,-11242,-11190,-11138,-11086,-11035,-10983,
295 -10931,-10880,-10828,-10777,-10725,-10673,-10622,-10570,
296 -10519,-10467,-10415,-10364,-10312,-10261,-10209,-10158,
297 -10106,-10055,-10004,-9952,-9901,-9849,-9798,-9747,
298 -9695,-9644,-9592,-9541,-9490,-9438,-9387,-9336,
299 -9285,-9233,-9182,-9131,-9080,-9028,-8977,-8926,
300 -8875,-8824,-8772,-8721,-8670,-8619,-8568,-8517,
301 -8466,-8414,-8363,-8312,-8261,-8210,-8159,-8108,
302 -8057,-8006,-7955,-7904,-7853,-7802,-7751,-7700,
303 -7649,-7598,-7547,-7496,-7445,-7395,-7344,-7293,
304 -7242,-7191,-7140,-7089,-7038,-6988,-6937,-6886,
305 -6835,-6784,-6733,-6683,-6632,-6581,-6530,-6480,
306 -6429,-6378,-6327,-6277,-6226,-6175,-6124,-6074,
307 -6023,-5972,-5922,-5871,-5820,-5770,-5719,-5668,
308 -5618,-5567,-5517,-5466,-5415,-5365,-5314,-5264,
309 -5213,-5162,-5112,-5061,-5011,-4960,-4910,-4859,
310 -4808,-4758,-4707,-4657,-4606,-4556,-4505,-4455,
311 -4404,-4354,-4303,-4253,-4202,-4152,-4101,-4051,
312 -4001,-3950,-3900,-3849,-3799,-3748,-3698,-3648,
313 -3597,-3547,-3496,-3446,-3395,-3345,-3295,-3244,
314 -3194,-3144,-3093,-3043,-2992,-2942,-2892,-2841,
315 -2791,-2741,-2690,-2640,-2590,-2539,-2489,-2439,
316 -2388,-2338,-2288,-2237,-2187,-2137,-2086,-2036,
317 -1986,-1935,-1885,-1835,-1784,-1734,-1684,-1633,
318 -1583,-1533,-1483,-1432,-1382,-1332,-1281,-1231,
319 -1181,-1131,-1080,-1030,-980,-929,-879,-829,
320 -779,-728,-678,-628,-578,-527,-477,-427,
321 -376,-326,-276,-226,-175,-125,-75,-25,
322 25,75,125,175,226,276,326,376,
323 427,477,527,578,628,678,728,779,
324 829,879,929,980,1030,1080,1131,1181,
325 1231,1281,1332,1382,1432,1483,1533,1583,
326 1633,1684,1734,1784,1835,1885,1935,1986,
327 2036,2086,2137,2187,2237,2288,2338,2388,
328 2439,2489,2539,2590,2640,2690,2741,2791,
329 2841,2892,2942,2992,3043,3093,3144,3194,
330 3244,3295,3345,3395,3446,3496,3547,3597,
331 3648,3698,3748,3799,3849,3900,3950,4001,
332 4051,4101,4152,4202,4253,4303,4354,4404,
333 4455,4505,4556,4606,4657,4707,4758,4808,
334 4859,4910,4960,5011,5061,5112,5162,5213,
335 5264,5314,5365,5415,5466,5517,5567,5618,
336 5668,5719,5770,5820,5871,5922,5972,6023,
337 6074,6124,6175,6226,6277,6327,6378,6429,
338 6480,6530,6581,6632,6683,6733,6784,6835,
339 6886,6937,6988,7038,7089,7140,7191,7242,
340 7293,7344,7395,7445,7496,7547,7598,7649,
341 7700,7751,7802,7853,7904,7955,8006,8057,
342 8108,8159,8210,8261,8312,8363,8414,8466,
343 8517,8568,8619,8670,8721,8772,8824,8875,
344 8926,8977,9028,9080,9131,9182,9233,9285,
345 9336,9387,9438,9490,9541,9592,9644,9695,
346 9747,9798,9849,9901,9952,10004,10055,10106,
347 10158,10209,10261,10312,10364,10415,10467,10519,
348 10570,10622,10673,10725,10777,10828,10880,10931,
349 10983,11035,11086,11138,11190,11242,11293,11345,
350 11397,11449,11501,11552,11604,11656,11708,11760,
351 11812,11864,11916,11967,12019,12071,12123,12175,
352 12227,12279,12331,12383,12436,12488,12540,12592,
353 12644,12696,12748,12800,12853,12905,12957,13009,
354 13062,13114,13166,13218,13271,13323,13375,13428,
355 13480,13533,13585,13637,13690,13742,13795,13847,
356 13900,13952,14005,14057,14110,14163,14215,14268,
357 14321,14373,14426,14479,14531,14584,14637,14690,
358 14743,14795,14848,14901,14954,15007,15060,15113,
359 15166,15219,15272,15325,15378,15431,15484,15537,
360 15590,15643,15696,15749,15802,15856,15909,15962,
361 16015,16069,16122,16175,16229,16282,16335,16389,
362 16442,16496,16549,16603,16656,16710,16763,16817,
363 16870,16924,16977,17031,17085,17138,17192,17246,
364 17300,17353,17407,17461,17515,17569,17623,17677,
365 17731,17784,17838,17892,17946,18001,18055,18109,
366 18163,18217,18271,18325,18380,18434,18488,18542,
367 18597,18651,18705,18760,18814,18868,18923,18977,
368 19032,19086,19141,19195,19250,19305,19359,19414,
369 19469,19523,19578,19633,19688,19742,19797,19852,
370 19907,19962,20017,20072,20127,20182,20237,20292,
371 20347,20402,20457,20513,20568,20623,20678,20734,
372 20789,20844,20900,20955,21010,21066,21121,21177,
373 21232,21288,21343,21399,21455,21510,21566,21622,
374 21678,21733,21789,21845,21901,21957,22013,22069,
375 22125,22181,22237,22293,22349,22405,22461,22517,
376 22573,22630,22686,22742,22799,22855,22911,22968,
377 23024,23081,23137,23194,23250,23307,23364,23420,
378 23477,23534,23591,23647,23704,23761,23818,23875,
379 23932,23989,24046,24103,24160,24217,24274,24331,
380 24389,24446,24503,24560,24618,24675,24732,24790,
381 24847,24905,24962,25020,25078,25135,25193,25251,
382 25308,25366,25424,25482,25540,25598,25656,25714,
383 25772,25830,25888,25946,26004,26062,26120,26179,
384 26237,26295,26354,26412,26471,26529,26588,26646,
385 26705,26763,26822,26881,26940,26998,27057,27116,
386 27175,27234,27293,27352,27411,27470,27529,27588,
387 27647,27707,27766,27825,27884,27944,28003,28063,
388 28122,28182,28241,28301,28361,28420,28480,28540,
389 28600,28660,28719,28779,28839,28899,28959,29020,
390 29080,29140,29200,29260,29321,29381,29441,29502,
391 29562,29623,29683,29744,29805,29865,29926,29987,
392 30048,30108,30169,30230,30291,30352,30413,30474,
393 30536,30597,30658,30719,30781,30842,30904,30965,
394 31026,31088,31150,31211,31273,31335,31396,31458,
395 31520,31582,31644,31706,31768,31830,31892,31955,
396 32017,32079,32141,32204,32266,32329,32391,32454,
397 32516,32579,32642,32705,32767,32830,32893,32956,
398 33019,33082,33145,33208,33272,33335,33398,33461,
399 33525,33588,33652,33715,33779,33843,33906,33970,
400 34034,34098,34162,34225,34289,34354,34418,34482,
401 34546,34610,34675,34739,34803,34868,34932,34997,
402 35062,35126,35191,35256,35321,35385,35450,35515,
403 35580,35646,35711,35776,35841,35907,35972,36037,
404 36103,36168,36234,36300,36365,36431,36497,36563,
405 36629,36695,36761,36827,36893,36959,37026,37092,
406 37158,37225,37291,37358,37425,37491,37558,37625,
407 37692,37759,37826,37893,37960,38027,38094,38161,
408 38229,38296,38364,38431,38499,38566,38634,38702,
409 38770,38837,38905,38973,39042,39110,39178,39246,
410 39314,39383,39451,39520,39588,39657,39726,39794,
411 39863,39932,40001,40070,40139,40208,40278,40347,
412 40416,40486,40555,40625,40694,40764,40834,40904,
413 40973,41043,41113,41184,41254,41324,41394,41465,
414 41535,41605,41676,41747,41817,41888,41959,42030,
415 42101,42172,42243,42314,42385,42457,42528,42600,
416 42671,42743,42814,42886,42958,43030,43102,43174,
417 43246,43318,43390,43463,43535,43608,43680,43753,
418 43826,43898,43971,44044,44117,44190,44263,44337,
419 44410,44483,44557,44630,44704,44778,44851,44925,
420 44999,45073,45147,45221,45296,45370,45444,45519,
421 45593,45668,45743,45818,45892,45967,46042,46118,
422 46193,46268,46343,46419,46494,46570,46646,46721,
423 46797,46873,46949,47025,47102,47178,47254,47331,
424 47407,47484,47560,47637,47714,47791,47868,47945,
425 48022,48100,48177,48255,48332,48410,48488,48565,
426 48643,48721,48799,48878,48956,49034,49113,49191,
427 49270,49349,49427,49506,49585,49664,49744,49823,
428 49902,49982,50061,50141,50221,50300,50380,50460,
429 50540,50621,50701,50781,50862,50942,51023,51104,
430 51185,51266,51347,51428,51509,51591,51672,51754,
431 51835,51917,51999,52081,52163,52245,52327,52410,
432 52492,52575,52657,52740,52823,52906,52989,53072,
433 53156,53239,53322,53406,53490,53574,53657,53741,
434 53826,53910,53994,54079,54163,54248,54333,54417,
435 54502,54587,54673,54758,54843,54929,55015,55100,
436 55186,55272,55358,55444,55531,55617,55704,55790,
437 55877,55964,56051,56138,56225,56312,56400,56487,
438 56575,56663,56751,56839,56927,57015,57104,57192,
439 57281,57369,57458,57547,57636,57725,57815,57904,
440 57994,58083,58173,58263,58353,58443,58534,58624,
441 58715,58805,58896,58987,59078,59169,59261,59352,
442 59444,59535,59627,59719,59811,59903,59996,60088,
443 60181,60273,60366,60459,60552,60646,60739,60833,
444 60926,61020,61114,61208,61302,61396,61491,61585,
445 61680,61775,61870,61965,62060,62156,62251,62347,
446 62443,62539,62635,62731,62828,62924,63021,63118,
447 63215,63312,63409,63506,63604,63702,63799,63897,
448 63996,64094,64192,64291,64389,64488,64587,64687,
449 64786,64885,64985,65085,65185,65285,65385,65485,
450 65586,65686,65787,65888,65989,66091,66192,66294,
451 66396,66498,66600,66702,66804,66907,67010,67113,
452 67216,67319,67422,67526,67629,67733,67837,67942,
453 68046,68151,68255,68360,68465,68570,68676,68781,
454 68887,68993,69099,69205,69312,69418,69525,69632,
455 69739,69846,69954,70061,70169,70277,70385,70494,
456 70602,70711,70820,70929,71038,71147,71257,71367,
457 71477,71587,71697,71808,71918,72029,72140,72252,
458 72363,72475,72587,72699,72811,72923,73036,73149,
459 73262,73375,73488,73602,73715,73829,73944,74058,
460 74172,74287,74402,74517,74633,74748,74864,74980,
461 75096,75213,75329,75446,75563,75680,75797,75915,
462 76033,76151,76269,76388,76506,76625,76744,76864,
463 76983,77103,77223,77343,77463,77584,77705,77826,
464 77947,78068,78190,78312,78434,78557,78679,78802,
465 78925,79048,79172,79296,79420,79544,79668,79793,
466 79918,80043,80168,80294,80420,80546,80672,80799,
467 80925,81053,81180,81307,81435,81563,81691,81820,
468 81949,82078,82207,82336,82466,82596,82726,82857,
469 82987,83118,83250,83381,83513,83645,83777,83910,
470 84043,84176,84309,84443,84576,84710,84845,84980,
471 85114,85250,85385,85521,85657,85793,85930,86066,
472 86204,86341,86479,86616,86755,86893,87032,87171,
473 87310,87450,87590,87730,87871,88011,88152,88294,
474 88435,88577,88720,88862,89005,89148,89292,89435,
475 89579,89724,89868,90013,90158,90304,90450,90596,
476 90742,90889,91036,91184,91332,91480,91628,91777,
477 91926,92075,92225,92375,92525,92675,92826,92978,
478 93129,93281,93434,93586,93739,93892,94046,94200,
479 94354,94509,94664,94819,94975,95131,95287,95444,
480 95601,95758,95916,96074,96233,96391,96551,96710,
481 96870,97030,97191,97352,97513,97675,97837,98000,
482 98163,98326,98489,98653,98818,98982,99148,99313,
483 99479,99645,99812,99979,100146,100314,100482,100651,
484 100820,100990,101159,101330,101500,101671,101843,102015,
485 102187,102360,102533,102706,102880,103054,103229,103404,
486 103580,103756,103933,104109,104287,104465,104643,104821,
487 105000,105180,105360,105540,105721,105902,106084,106266,
488 106449,106632,106816,107000,107184,107369,107555,107741,
489 107927,108114,108301,108489,108677,108866,109055,109245,
490 109435,109626,109817,110008,110200,110393,110586,110780,
491 110974,111169,111364,111560,111756,111952,112150,112347,
492 112546,112744,112944,113143,113344,113545,113746,113948,
493 114151,114354,114557,114761,114966,115171,115377,115583,
494 115790,115998,116206,116414,116623,116833,117044,117254,
495 117466,117678,117891,118104,118318,118532,118747,118963,
496 119179,119396,119613,119831,120050,120269,120489,120709,
497 120930,121152,121374,121597,121821,122045,122270,122496,
498 122722,122949,123176,123404,123633,123863,124093,124324,
499 124555,124787,125020,125254,125488,125723,125959,126195,
500 126432,126669,126908,127147,127387,127627,127869,128111,
501 128353,128597,128841,129086,129332,129578,129825,130073,
502 130322,130571,130821,131072,131324,131576,131830,132084,
503 132339,132594,132851,133108,133366,133625,133884,134145,
504 134406,134668,134931,135195,135459,135725,135991,136258,
505 136526,136795,137065,137335,137607,137879,138152,138426,
506 138701,138977,139254,139532,139810,140090,140370,140651,
507 140934,141217,141501,141786,142072,142359,142647,142936,
508 143226,143517,143808,144101,144395,144690,144986,145282,
509 145580,145879,146179,146480,146782,147084,147388,147693,
510 148000,148307,148615,148924,149235,149546,149859,150172,
511 150487,150803,151120,151438,151757,152077,152399,152722,
512 153045,153370,153697,154024,154352,154682,155013,155345,
513 155678,156013,156349,156686,157024,157363,157704,158046,
514 158389,158734,159079,159427,159775,160125,160476,160828,
515 161182,161537,161893,162251,162610,162970,163332,163695,
516 164060,164426,164793,165162,165532,165904,166277,166651,
517 167027,167405,167784,168164,168546,168930,169315,169701,
518 170089,170479,170870,171263,171657,172053,172451,172850,
519 173251,173653,174057,174463,174870,175279,175690,176102,
520 176516,176932,177349,177769,178190,178612,179037,179463,
521 179891,180321,180753,181186,181622,182059,182498,182939,
522 183382,183827,184274,184722,185173,185625,186080,186536,
523 186995,187455,187918,188382,188849,189318,189789,190261,
524 190736,191213,191693,192174,192658,193143,193631,194122,
525 194614,195109,195606,196105,196606,197110,197616,198125,
526 198636,199149,199664,200182,200703,201226,201751,202279,
527 202809,203342,203878,204416,204956,205500,206045,206594,
528 207145,207699,208255,208815,209376,209941,210509,211079,
529 211652,212228,212807,213389,213973,214561,215151,215745,
530 216341,216941,217544,218149,218758,219370,219985,220603,
531 221225,221849,222477,223108,223743,224381,225022,225666,
532 226314,226966,227621,228279,228941,229606,230275,230948,
533 231624,232304,232988,233676,234367,235062,235761,236463,
534 237170,237881,238595,239314,240036,240763,241493,242228,
535 242967,243711,244458,245210,245966,246727,247492,248261,
536 249035,249813,250596,251384,252176,252973,253774,254581,
537 255392,256208,257029,257855,258686,259522,260363,261209,
538 262060,262917,263779,264646,265519,266397,267280,268169,
539 269064,269965,270871,271782,272700,273624,274553,275489,
540 276430,277378,278332,279292,280258,281231,282210,283195,
541 284188,285186,286192,287204,288223,289249,290282,291322,
542 292369,293423,294485,295554,296630,297714,298805,299904,
543 301011,302126,303248,304379,305517,306664,307819,308983,
544 310154,311335,312524,313721,314928,316143,317368,318601,
545 319844,321097,322358,323629,324910,326201,327502,328812,
546 330133,331464,332805,334157,335519,336892,338276,339671,
547 341078,342495,343924,345364,346816,348280,349756,351244,
548 352744,354257,355783,357321,358872,360436,362013,363604,
549 365208,366826,368459,370105,371765,373440,375130,376835,
550 378555,380290,382040,383807,385589,387387,389202,391034,
551 392882,394747,396630,398530,400448,402384,404338,406311,
552 408303,410314,412344,414395,416465,418555,420666,422798,
553 424951,427125,429321,431540,433781,436045,438332,440643,
554 442978,445337,447720,450129,452564,455024,457511,460024,
555 462565,465133,467730,470355,473009,475692,478406,481150,
556 483925,486732,489571,492443,495348,498287,501261,504269,
557 507313,510394,513512,516667,519861,523094,526366,529680,
558 533034,536431,539870,543354,546881,550455,554074,557741,
559 561456,565221,569035,572901,576818,580789,584815,588896,
560 593033,597229,601483,605798,610174,614613,619117,623686,
561 628323,633028,637803,642651,647572,652568,657640,662792,
562 668024,673338,678737,684223,689797,695462,701219,707072,
563 713023,719074,725227,731486,737853,744331,750922,757631,
564 764460,771411,778490,785699,793041,800521,808143,815910,
565 823827,831898,840127,848520,857081,865817,874730,883829,
566 893117,902602,912289,922186,932298,942633,953199,964003,
567 975054,986361,997931,1009774,1021901,1034322,1047046,1060087,
568 1073455,1087164,1101225,1115654,1130465,1145673,1161294,1177345,
569 1193846,1210813,1228269,1246234,1264730,1283783,1303416,1323658,
570 1344537,1366084,1388330,1411312,1435065,1459630,1485049,1511367,
571 1538632,1566898,1596220,1626658,1658278,1691149,1725348,1760956,
572 1798063,1836758,1877161,1919378,1963536,2009771,2058233,2109087,
573 2162516,2218719,2277919,2340362,2406322,2476104,2550052,2628549,
574 2712030,2800983,2895966,2997613,3106651,3223918,3350381,3487165,
575 3635590,3797206,3973855,4167737,4381502,4618375,4882318,5178251,
576 5512368,5892567,6329090,6835455,7429880,8137527,8994149,10052327,
577 11392683,13145455,15535599,18988036,24413316,34178904,56965752,170910304
578 };
579#endif
580
581fixed_t *finecosine;
582
583#ifdef TABLES_AS_LUMPS
584fixed_t *finesine;
585#else
586const fixed_t finesine[10240] = {
587 25,75,125,175,226,276,326,376,
588 427,477,527,578,628,678,728,779,
589 829,879,929,980,1030,1080,1130,1181,
590 1231,1281,1331,1382,1432,1482,1532,1583,
591 1633,1683,1733,1784,1834,1884,1934,1985,
592 2035,2085,2135,2186,2236,2286,2336,2387,
593 2437,2487,2537,2587,2638,2688,2738,2788,
594 2839,2889,2939,2989,3039,3090,3140,3190,
595 3240,3291,3341,3391,3441,3491,3541,3592,
596 3642,3692,3742,3792,3843,3893,3943,3993,
597 4043,4093,4144,4194,4244,4294,4344,4394,
598 4445,4495,4545,4595,4645,4695,4745,4796,
599 4846,4896,4946,4996,5046,5096,5146,5197,
600 5247,5297,5347,5397,5447,5497,5547,5597,
601 5647,5697,5748,5798,5848,5898,5948,5998,
602 6048,6098,6148,6198,6248,6298,6348,6398,
603 6448,6498,6548,6598,6648,6698,6748,6798,
604 6848,6898,6948,6998,7048,7098,7148,7198,
605 7248,7298,7348,7398,7448,7498,7548,7598,
606 7648,7697,7747,7797,7847,7897,7947,7997,
607 8047,8097,8147,8196,8246,8296,8346,8396,
608 8446,8496,8545,8595,8645,8695,8745,8794,
609 8844,8894,8944,8994,9043,9093,9143,9193,
610 9243,9292,9342,9392,9442,9491,9541,9591,
611 9640,9690,9740,9790,9839,9889,9939,9988,
612 10038,10088,10137,10187,10237,10286,10336,10386,
613 10435,10485,10534,10584,10634,10683,10733,10782,
614 10832,10882,10931,10981,11030,11080,11129,11179,
615 11228,11278,11327,11377,11426,11476,11525,11575,
616 11624,11674,11723,11773,11822,11872,11921,11970,
617 12020,12069,12119,12168,12218,12267,12316,12366,
618 12415,12464,12514,12563,12612,12662,12711,12760,
619 12810,12859,12908,12957,13007,13056,13105,13154,
620 13204,13253,13302,13351,13401,13450,13499,13548,
621 13597,13647,13696,13745,13794,13843,13892,13941,
622 13990,14040,14089,14138,14187,14236,14285,14334,
623 14383,14432,14481,14530,14579,14628,14677,14726,
624 14775,14824,14873,14922,14971,15020,15069,15118,
625 15167,15215,15264,15313,15362,15411,15460,15509,
626 15557,15606,15655,15704,15753,15802,15850,15899,
627 15948,15997,16045,16094,16143,16191,16240,16289,
628 16338,16386,16435,16484,16532,16581,16629,16678,
629 16727,16775,16824,16872,16921,16970,17018,17067,
630 17115,17164,17212,17261,17309,17358,17406,17455,
631 17503,17551,17600,17648,17697,17745,17793,17842,
632 17890,17939,17987,18035,18084,18132,18180,18228,
633 18277,18325,18373,18421,18470,18518,18566,18614,
634 18663,18711,18759,18807,18855,18903,18951,19000,
635 19048,19096,19144,19192,19240,19288,19336,19384,
636 19432,19480,19528,19576,19624,19672,19720,19768,
637 19816,19864,19912,19959,20007,20055,20103,20151,
638 20199,20246,20294,20342,20390,20438,20485,20533,
639 20581,20629,20676,20724,20772,20819,20867,20915,
640 20962,21010,21057,21105,21153,21200,21248,21295,
641 21343,21390,21438,21485,21533,21580,21628,21675,
642 21723,21770,21817,21865,21912,21960,22007,22054,
643 22102,22149,22196,22243,22291,22338,22385,22433,
644 22480,22527,22574,22621,22668,22716,22763,22810,
645 22857,22904,22951,22998,23045,23092,23139,23186,
646 23233,23280,23327,23374,23421,23468,23515,23562,
647 23609,23656,23703,23750,23796,23843,23890,23937,
648 23984,24030,24077,24124,24171,24217,24264,24311,
649 24357,24404,24451,24497,24544,24591,24637,24684,
650 24730,24777,24823,24870,24916,24963,25009,25056,
651 25102,25149,25195,25241,25288,25334,25381,25427,
652 25473,25520,25566,25612,25658,25705,25751,25797,
653 25843,25889,25936,25982,26028,26074,26120,26166,
654 26212,26258,26304,26350,26396,26442,26488,26534,
655 26580,26626,26672,26718,26764,26810,26856,26902,
656 26947,26993,27039,27085,27131,27176,27222,27268,
657 27313,27359,27405,27450,27496,27542,27587,27633,
658 27678,27724,27770,27815,27861,27906,27952,27997,
659 28042,28088,28133,28179,28224,28269,28315,28360,
660 28405,28451,28496,28541,28586,28632,28677,28722,
661 28767,28812,28858,28903,28948,28993,29038,29083,
662 29128,29173,29218,29263,29308,29353,29398,29443,
663 29488,29533,29577,29622,29667,29712,29757,29801,
664 29846,29891,29936,29980,30025,30070,30114,30159,
665 30204,30248,30293,30337,30382,30426,30471,30515,
666 30560,30604,30649,30693,30738,30782,30826,30871,
667 30915,30959,31004,31048,31092,31136,31181,31225,
668 31269,31313,31357,31402,31446,31490,31534,31578,
669 31622,31666,31710,31754,31798,31842,31886,31930,
670 31974,32017,32061,32105,32149,32193,32236,32280,
671 32324,32368,32411,32455,32499,32542,32586,32630,
672 32673,32717,32760,32804,32847,32891,32934,32978,
673 33021,33065,33108,33151,33195,33238,33281,33325,
674 33368,33411,33454,33498,33541,33584,33627,33670,
675 33713,33756,33799,33843,33886,33929,33972,34015,
676 34057,34100,34143,34186,34229,34272,34315,34358,
677 34400,34443,34486,34529,34571,34614,34657,34699,
678 34742,34785,34827,34870,34912,34955,34997,35040,
679 35082,35125,35167,35210,35252,35294,35337,35379,
680 35421,35464,35506,35548,35590,35633,35675,35717,
681 35759,35801,35843,35885,35927,35969,36011,36053,
682 36095,36137,36179,36221,36263,36305,36347,36388,
683 36430,36472,36514,36555,36597,36639,36681,36722,
684 36764,36805,36847,36889,36930,36972,37013,37055,
685 37096,37137,37179,37220,37262,37303,37344,37386,
686 37427,37468,37509,37551,37592,37633,37674,37715,
687 37756,37797,37838,37879,37920,37961,38002,38043,
688 38084,38125,38166,38207,38248,38288,38329,38370,
689 38411,38451,38492,38533,38573,38614,38655,38695,
690 38736,38776,38817,38857,38898,38938,38979,39019,
691 39059,39100,39140,39180,39221,39261,39301,39341,
692 39382,39422,39462,39502,39542,39582,39622,39662,
693 39702,39742,39782,39822,39862,39902,39942,39982,
694 40021,40061,40101,40141,40180,40220,40260,40300,
695 40339,40379,40418,40458,40497,40537,40576,40616,
696 40655,40695,40734,40773,40813,40852,40891,40931,
697 40970,41009,41048,41087,41127,41166,41205,41244,
698 41283,41322,41361,41400,41439,41478,41517,41556,
699 41595,41633,41672,41711,41750,41788,41827,41866,
700 41904,41943,41982,42020,42059,42097,42136,42174,
701 42213,42251,42290,42328,42366,42405,42443,42481,
702 42520,42558,42596,42634,42672,42711,42749,42787,
703 42825,42863,42901,42939,42977,43015,43053,43091,
704 43128,43166,43204,43242,43280,43317,43355,43393,
705 43430,43468,43506,43543,43581,43618,43656,43693,
706 43731,43768,43806,43843,43880,43918,43955,43992,
707 44029,44067,44104,44141,44178,44215,44252,44289,
708 44326,44363,44400,44437,44474,44511,44548,44585,
709 44622,44659,44695,44732,44769,44806,44842,44879,
710 44915,44952,44989,45025,45062,45098,45135,45171,
711 45207,45244,45280,45316,45353,45389,45425,45462,
712 45498,45534,45570,45606,45642,45678,45714,45750,
713 45786,45822,45858,45894,45930,45966,46002,46037,
714 46073,46109,46145,46180,46216,46252,46287,46323,
715 46358,46394,46429,46465,46500,46536,46571,46606,
716 46642,46677,46712,46747,46783,46818,46853,46888,
717 46923,46958,46993,47028,47063,47098,47133,47168,
718 47203,47238,47273,47308,47342,47377,47412,47446,
719 47481,47516,47550,47585,47619,47654,47688,47723,
720 47757,47792,47826,47860,47895,47929,47963,47998,
721 48032,48066,48100,48134,48168,48202,48237,48271,
722 48305,48338,48372,48406,48440,48474,48508,48542,
723 48575,48609,48643,48676,48710,48744,48777,48811,
724 48844,48878,48911,48945,48978,49012,49045,49078,
725 49112,49145,49178,49211,49244,49278,49311,49344,
726 49377,49410,49443,49476,49509,49542,49575,49608,
727 49640,49673,49706,49739,49771,49804,49837,49869,
728 49902,49935,49967,50000,50032,50065,50097,50129,
729 50162,50194,50226,50259,50291,50323,50355,50387,
730 50420,50452,50484,50516,50548,50580,50612,50644,
731 50675,50707,50739,50771,50803,50834,50866,50898,
732 50929,50961,50993,51024,51056,51087,51119,51150,
733 51182,51213,51244,51276,51307,51338,51369,51401,
734 51432,51463,51494,51525,51556,51587,51618,51649,
735 51680,51711,51742,51773,51803,51834,51865,51896,
736 51926,51957,51988,52018,52049,52079,52110,52140,
737 52171,52201,52231,52262,52292,52322,52353,52383,
738 52413,52443,52473,52503,52534,52564,52594,52624,
739 52653,52683,52713,52743,52773,52803,52832,52862,
740 52892,52922,52951,52981,53010,53040,53069,53099,
741 53128,53158,53187,53216,53246,53275,53304,53334,
742 53363,53392,53421,53450,53479,53508,53537,53566,
743 53595,53624,53653,53682,53711,53739,53768,53797,
744 53826,53854,53883,53911,53940,53969,53997,54026,
745 54054,54082,54111,54139,54167,54196,54224,54252,
746 54280,54308,54337,54365,54393,54421,54449,54477,
747 54505,54533,54560,54588,54616,54644,54672,54699,
748 54727,54755,54782,54810,54837,54865,54892,54920,
749 54947,54974,55002,55029,55056,55084,55111,55138,
750 55165,55192,55219,55246,55274,55300,55327,55354,
751 55381,55408,55435,55462,55489,55515,55542,55569,
752 55595,55622,55648,55675,55701,55728,55754,55781,
753 55807,55833,55860,55886,55912,55938,55965,55991,
754 56017,56043,56069,56095,56121,56147,56173,56199,
755 56225,56250,56276,56302,56328,56353,56379,56404,
756 56430,56456,56481,56507,56532,56557,56583,56608,
757 56633,56659,56684,56709,56734,56760,56785,56810,
758 56835,56860,56885,56910,56935,56959,56984,57009,
759 57034,57059,57083,57108,57133,57157,57182,57206,
760 57231,57255,57280,57304,57329,57353,57377,57402,
761 57426,57450,57474,57498,57522,57546,57570,57594,
762 57618,57642,57666,57690,57714,57738,57762,57785,
763 57809,57833,57856,57880,57903,57927,57950,57974,
764 57997,58021,58044,58067,58091,58114,58137,58160,
765 58183,58207,58230,58253,58276,58299,58322,58345,
766 58367,58390,58413,58436,58459,58481,58504,58527,
767 58549,58572,58594,58617,58639,58662,58684,58706,
768 58729,58751,58773,58795,58818,58840,58862,58884,
769 58906,58928,58950,58972,58994,59016,59038,59059,
770 59081,59103,59125,59146,59168,59190,59211,59233,
771 59254,59276,59297,59318,59340,59361,59382,59404,
772 59425,59446,59467,59488,59509,59530,59551,59572,
773 59593,59614,59635,59656,59677,59697,59718,59739,
774 59759,59780,59801,59821,59842,59862,59883,59903,
775 59923,59944,59964,59984,60004,60025,60045,60065,
776 60085,60105,60125,60145,60165,60185,60205,60225,
777 60244,60264,60284,60304,60323,60343,60363,60382,
778 60402,60421,60441,60460,60479,60499,60518,60537,
779 60556,60576,60595,60614,60633,60652,60671,60690,
780 60709,60728,60747,60766,60785,60803,60822,60841,
781 60859,60878,60897,60915,60934,60952,60971,60989,
782 61007,61026,61044,61062,61081,61099,61117,61135,
783 61153,61171,61189,61207,61225,61243,61261,61279,
784 61297,61314,61332,61350,61367,61385,61403,61420,
785 61438,61455,61473,61490,61507,61525,61542,61559,
786 61577,61594,61611,61628,61645,61662,61679,61696,
787 61713,61730,61747,61764,61780,61797,61814,61831,
788 61847,61864,61880,61897,61913,61930,61946,61963,
789 61979,61995,62012,62028,62044,62060,62076,62092,
790 62108,62125,62141,62156,62172,62188,62204,62220,
791 62236,62251,62267,62283,62298,62314,62329,62345,
792 62360,62376,62391,62407,62422,62437,62453,62468,
793 62483,62498,62513,62528,62543,62558,62573,62588,
794 62603,62618,62633,62648,62662,62677,62692,62706,
795 62721,62735,62750,62764,62779,62793,62808,62822,
796 62836,62850,62865,62879,62893,62907,62921,62935,
797 62949,62963,62977,62991,63005,63019,63032,63046,
798 63060,63074,63087,63101,63114,63128,63141,63155,
799 63168,63182,63195,63208,63221,63235,63248,63261,
800 63274,63287,63300,63313,63326,63339,63352,63365,
801 63378,63390,63403,63416,63429,63441,63454,63466,
802 63479,63491,63504,63516,63528,63541,63553,63565,
803 63578,63590,63602,63614,63626,63638,63650,63662,
804 63674,63686,63698,63709,63721,63733,63745,63756,
805 63768,63779,63791,63803,63814,63825,63837,63848,
806 63859,63871,63882,63893,63904,63915,63927,63938,
807 63949,63960,63971,63981,63992,64003,64014,64025,
808 64035,64046,64057,64067,64078,64088,64099,64109,
809 64120,64130,64140,64151,64161,64171,64181,64192,
810 64202,64212,64222,64232,64242,64252,64261,64271,
811 64281,64291,64301,64310,64320,64330,64339,64349,
812 64358,64368,64377,64387,64396,64405,64414,64424,
813 64433,64442,64451,64460,64469,64478,64487,64496,
814 64505,64514,64523,64532,64540,64549,64558,64566,
815 64575,64584,64592,64601,64609,64617,64626,64634,
816 64642,64651,64659,64667,64675,64683,64691,64699,
817 64707,64715,64723,64731,64739,64747,64754,64762,
818 64770,64777,64785,64793,64800,64808,64815,64822,
819 64830,64837,64844,64852,64859,64866,64873,64880,
820 64887,64895,64902,64908,64915,64922,64929,64936,
821 64943,64949,64956,64963,64969,64976,64982,64989,
822 64995,65002,65008,65015,65021,65027,65033,65040,
823 65046,65052,65058,65064,65070,65076,65082,65088,
824 65094,65099,65105,65111,65117,65122,65128,65133,
825 65139,65144,65150,65155,65161,65166,65171,65177,
826 65182,65187,65192,65197,65202,65207,65212,65217,
827 65222,65227,65232,65237,65242,65246,65251,65256,
828 65260,65265,65270,65274,65279,65283,65287,65292,
829 65296,65300,65305,65309,65313,65317,65321,65325,
830 65329,65333,65337,65341,65345,65349,65352,65356,
831 65360,65363,65367,65371,65374,65378,65381,65385,
832 65388,65391,65395,65398,65401,65404,65408,65411,
833 65414,65417,65420,65423,65426,65429,65431,65434,
834 65437,65440,65442,65445,65448,65450,65453,65455,
835 65458,65460,65463,65465,65467,65470,65472,65474,
836 65476,65478,65480,65482,65484,65486,65488,65490,
837 65492,65494,65496,65497,65499,65501,65502,65504,
838 65505,65507,65508,65510,65511,65513,65514,65515,
839 65516,65518,65519,65520,65521,65522,65523,65524,
840 65525,65526,65527,65527,65528,65529,65530,65530,
841 65531,65531,65532,65532,65533,65533,65534,65534,
842 65534,65535,65535,65535,65535,65535,65535,65535,
843 65535,65535,65535,65535,65535,65535,65535,65534,
844 65534,65534,65533,65533,65532,65532,65531,65531,
845 65530,65530,65529,65528,65527,65527,65526,65525,
846 65524,65523,65522,65521,65520,65519,65518,65516,
847 65515,65514,65513,65511,65510,65508,65507,65505,
848 65504,65502,65501,65499,65497,65496,65494,65492,
849 65490,65488,65486,65484,65482,65480,65478,65476,
850 65474,65472,65470,65467,65465,65463,65460,65458,
851 65455,65453,65450,65448,65445,65442,65440,65437,
852 65434,65431,65429,65426,65423,65420,65417,65414,
853 65411,65408,65404,65401,65398,65395,65391,65388,
854 65385,65381,65378,65374,65371,65367,65363,65360,
855 65356,65352,65349,65345,65341,65337,65333,65329,
856 65325,65321,65317,65313,65309,65305,65300,65296,
857 65292,65287,65283,65279,65274,65270,65265,65260,
858 65256,65251,65246,65242,65237,65232,65227,65222,
859 65217,65212,65207,65202,65197,65192,65187,65182,
860 65177,65171,65166,65161,65155,65150,65144,65139,
861 65133,65128,65122,65117,65111,65105,65099,65094,
862 65088,65082,65076,65070,65064,65058,65052,65046,
863 65040,65033,65027,65021,65015,65008,65002,64995,
864 64989,64982,64976,64969,64963,64956,64949,64943,
865 64936,64929,64922,64915,64908,64902,64895,64887,
866 64880,64873,64866,64859,64852,64844,64837,64830,
867 64822,64815,64808,64800,64793,64785,64777,64770,
868 64762,64754,64747,64739,64731,64723,64715,64707,
869 64699,64691,64683,64675,64667,64659,64651,64642,
870 64634,64626,64617,64609,64600,64592,64584,64575,
871 64566,64558,64549,64540,64532,64523,64514,64505,
872 64496,64487,64478,64469,64460,64451,64442,64433,
873 64424,64414,64405,64396,64387,64377,64368,64358,
874 64349,64339,64330,64320,64310,64301,64291,64281,
875 64271,64261,64252,64242,64232,64222,64212,64202,
876 64192,64181,64171,64161,64151,64140,64130,64120,
877 64109,64099,64088,64078,64067,64057,64046,64035,
878 64025,64014,64003,63992,63981,63971,63960,63949,
879 63938,63927,63915,63904,63893,63882,63871,63859,
880 63848,63837,63825,63814,63803,63791,63779,63768,
881 63756,63745,63733,63721,63709,63698,63686,63674,
882 63662,63650,63638,63626,63614,63602,63590,63578,
883 63565,63553,63541,63528,63516,63504,63491,63479,
884 63466,63454,63441,63429,63416,63403,63390,63378,
885 63365,63352,63339,63326,63313,63300,63287,63274,
886 63261,63248,63235,63221,63208,63195,63182,63168,
887 63155,63141,63128,63114,63101,63087,63074,63060,
888 63046,63032,63019,63005,62991,62977,62963,62949,
889 62935,62921,62907,62893,62879,62865,62850,62836,
890 62822,62808,62793,62779,62764,62750,62735,62721,
891 62706,62692,62677,62662,62648,62633,62618,62603,
892 62588,62573,62558,62543,62528,62513,62498,62483,
893 62468,62453,62437,62422,62407,62391,62376,62360,
894 62345,62329,62314,62298,62283,62267,62251,62236,
895 62220,62204,62188,62172,62156,62141,62125,62108,
896 62092,62076,62060,62044,62028,62012,61995,61979,
897 61963,61946,61930,61913,61897,61880,61864,61847,
898 61831,61814,61797,61780,61764,61747,61730,61713,
899 61696,61679,61662,61645,61628,61611,61594,61577,
900 61559,61542,61525,61507,61490,61473,61455,61438,
901 61420,61403,61385,61367,61350,61332,61314,61297,
902 61279,61261,61243,61225,61207,61189,61171,61153,
903 61135,61117,61099,61081,61062,61044,61026,61007,
904 60989,60971,60952,60934,60915,60897,60878,60859,
905 60841,60822,60803,60785,60766,60747,60728,60709,
906 60690,60671,60652,60633,60614,60595,60576,60556,
907 60537,60518,60499,60479,60460,60441,60421,60402,
908 60382,60363,60343,60323,60304,60284,60264,60244,
909 60225,60205,60185,60165,60145,60125,60105,60085,
910 60065,60045,60025,60004,59984,59964,59944,59923,
911 59903,59883,59862,59842,59821,59801,59780,59759,
912 59739,59718,59697,59677,59656,59635,59614,59593,
913 59572,59551,59530,59509,59488,59467,59446,59425,
914 59404,59382,59361,59340,59318,59297,59276,59254,
915 59233,59211,59190,59168,59146,59125,59103,59081,
916 59059,59038,59016,58994,58972,58950,58928,58906,
917 58884,58862,58840,58818,58795,58773,58751,58729,
918 58706,58684,58662,58639,58617,58594,58572,58549,
919 58527,58504,58481,58459,58436,58413,58390,58367,
920 58345,58322,58299,58276,58253,58230,58207,58183,
921 58160,58137,58114,58091,58067,58044,58021,57997,
922 57974,57950,57927,57903,57880,57856,57833,57809,
923 57785,57762,57738,57714,57690,57666,57642,57618,
924 57594,57570,57546,57522,57498,57474,57450,57426,
925 57402,57377,57353,57329,57304,57280,57255,57231,
926 57206,57182,57157,57133,57108,57083,57059,57034,
927 57009,56984,56959,56935,56910,56885,56860,56835,
928 56810,56785,56760,56734,56709,56684,56659,56633,
929 56608,56583,56557,56532,56507,56481,56456,56430,
930 56404,56379,56353,56328,56302,56276,56250,56225,
931 56199,56173,56147,56121,56095,56069,56043,56017,
932 55991,55965,55938,55912,55886,55860,55833,55807,
933 55781,55754,55728,55701,55675,55648,55622,55595,
934 55569,55542,55515,55489,55462,55435,55408,55381,
935 55354,55327,55300,55274,55246,55219,55192,55165,
936 55138,55111,55084,55056,55029,55002,54974,54947,
937 54920,54892,54865,54837,54810,54782,54755,54727,
938 54699,54672,54644,54616,54588,54560,54533,54505,
939 54477,54449,54421,54393,54365,54337,54308,54280,
940 54252,54224,54196,54167,54139,54111,54082,54054,
941 54026,53997,53969,53940,53911,53883,53854,53826,
942 53797,53768,53739,53711,53682,53653,53624,53595,
943 53566,53537,53508,53479,53450,53421,53392,53363,
944 53334,53304,53275,53246,53216,53187,53158,53128,
945 53099,53069,53040,53010,52981,52951,52922,52892,
946 52862,52832,52803,52773,52743,52713,52683,52653,
947 52624,52594,52564,52534,52503,52473,52443,52413,
948 52383,52353,52322,52292,52262,52231,52201,52171,
949 52140,52110,52079,52049,52018,51988,51957,51926,
950 51896,51865,51834,51803,51773,51742,51711,51680,
951 51649,51618,51587,51556,51525,51494,51463,51432,
952 51401,51369,51338,51307,51276,51244,51213,51182,
953 51150,51119,51087,51056,51024,50993,50961,50929,
954 50898,50866,50834,50803,50771,50739,50707,50675,
955 50644,50612,50580,50548,50516,50484,50452,50420,
956 50387,50355,50323,50291,50259,50226,50194,50162,
957 50129,50097,50065,50032,50000,49967,49935,49902,
958 49869,49837,49804,49771,49739,49706,49673,49640,
959 49608,49575,49542,49509,49476,49443,49410,49377,
960 49344,49311,49278,49244,49211,49178,49145,49112,
961 49078,49045,49012,48978,48945,48911,48878,48844,
962 48811,48777,48744,48710,48676,48643,48609,48575,
963 48542,48508,48474,48440,48406,48372,48338,48304,
964 48271,48237,48202,48168,48134,48100,48066,48032,
965 47998,47963,47929,47895,47860,47826,47792,47757,
966 47723,47688,47654,47619,47585,47550,47516,47481,
967 47446,47412,47377,47342,47308,47273,47238,47203,
968 47168,47133,47098,47063,47028,46993,46958,46923,
969 46888,46853,46818,46783,46747,46712,46677,46642,
970 46606,46571,46536,46500,46465,46429,46394,46358,
971 46323,46287,46252,46216,46180,46145,46109,46073,
972 46037,46002,45966,45930,45894,45858,45822,45786,
973 45750,45714,45678,45642,45606,45570,45534,45498,
974 45462,45425,45389,45353,45316,45280,45244,45207,
975 45171,45135,45098,45062,45025,44989,44952,44915,
976 44879,44842,44806,44769,44732,44695,44659,44622,
977 44585,44548,44511,44474,44437,44400,44363,44326,
978 44289,44252,44215,44178,44141,44104,44067,44029,
979 43992,43955,43918,43880,43843,43806,43768,43731,
980 43693,43656,43618,43581,43543,43506,43468,43430,
981 43393,43355,43317,43280,43242,43204,43166,43128,
982 43091,43053,43015,42977,42939,42901,42863,42825,
983 42787,42749,42711,42672,42634,42596,42558,42520,
984 42481,42443,42405,42366,42328,42290,42251,42213,
985 42174,42136,42097,42059,42020,41982,41943,41904,
986 41866,41827,41788,41750,41711,41672,41633,41595,
987 41556,41517,41478,41439,41400,41361,41322,41283,
988 41244,41205,41166,41127,41088,41048,41009,40970,
989 40931,40891,40852,40813,40773,40734,40695,40655,
990 40616,40576,40537,40497,40458,40418,40379,40339,
991 40300,40260,40220,40180,40141,40101,40061,40021,
992 39982,39942,39902,39862,39822,39782,39742,39702,
993 39662,39622,39582,39542,39502,39462,39422,39382,
994 39341,39301,39261,39221,39180,39140,39100,39059,
995 39019,38979,38938,38898,38857,38817,38776,38736,
996 38695,38655,38614,38573,38533,38492,38451,38411,
997 38370,38329,38288,38248,38207,38166,38125,38084,
998 38043,38002,37961,37920,37879,37838,37797,37756,
999 37715,37674,37633,37592,37551,37509,37468,37427,
1000 37386,37344,37303,37262,37220,37179,37137,37096,
1001 37055,37013,36972,36930,36889,36847,36805,36764,
1002 36722,36681,36639,36597,36556,36514,36472,36430,
1003 36388,36347,36305,36263,36221,36179,36137,36095,
1004 36053,36011,35969,35927,35885,35843,35801,35759,
1005 35717,35675,35633,35590,35548,35506,35464,35421,
1006 35379,35337,35294,35252,35210,35167,35125,35082,
1007 35040,34997,34955,34912,34870,34827,34785,34742,
1008 34699,34657,34614,34571,34529,34486,34443,34400,
1009 34358,34315,34272,34229,34186,34143,34100,34057,
1010 34015,33972,33929,33886,33843,33799,33756,33713,
1011 33670,33627,33584,33541,33498,33454,33411,33368,
1012 33325,33281,33238,33195,33151,33108,33065,33021,
1013 32978,32934,32891,32847,32804,32760,32717,32673,
1014 32630,32586,32542,32499,32455,32411,32368,32324,
1015 32280,32236,32193,32149,32105,32061,32017,31974,
1016 31930,31886,31842,31798,31754,31710,31666,31622,
1017 31578,31534,31490,31446,31402,31357,31313,31269,
1018 31225,31181,31136,31092,31048,31004,30959,30915,
1019 30871,30826,30782,30738,30693,30649,30604,30560,
1020 30515,30471,30426,30382,30337,30293,30248,30204,
1021 30159,30114,30070,30025,29980,29936,29891,29846,
1022 29801,29757,29712,29667,29622,29577,29533,29488,
1023 29443,29398,29353,29308,29263,29218,29173,29128,
1024 29083,29038,28993,28948,28903,28858,28812,28767,
1025 28722,28677,28632,28586,28541,28496,28451,28405,
1026 28360,28315,28269,28224,28179,28133,28088,28042,
1027 27997,27952,27906,27861,27815,27770,27724,27678,
1028 27633,27587,27542,27496,27450,27405,27359,27313,
1029 27268,27222,27176,27131,27085,27039,26993,26947,
1030 26902,26856,26810,26764,26718,26672,26626,26580,
1031 26534,26488,26442,26396,26350,26304,26258,26212,
1032 26166,26120,26074,26028,25982,25936,25889,25843,
1033 25797,25751,25705,25658,25612,25566,25520,25473,
1034 25427,25381,25334,25288,25241,25195,25149,25102,
1035 25056,25009,24963,24916,24870,24823,24777,24730,
1036 24684,24637,24591,24544,24497,24451,24404,24357,
1037 24311,24264,24217,24171,24124,24077,24030,23984,
1038 23937,23890,23843,23796,23750,23703,23656,23609,
1039 23562,23515,23468,23421,23374,23327,23280,23233,
1040 23186,23139,23092,23045,22998,22951,22904,22857,
1041 22810,22763,22716,22668,22621,22574,22527,22480,
1042 22433,22385,22338,22291,22243,22196,22149,22102,
1043 22054,22007,21960,21912,21865,21817,21770,21723,
1044 21675,21628,21580,21533,21485,21438,21390,21343,
1045 21295,21248,21200,21153,21105,21057,21010,20962,
1046 20915,20867,20819,20772,20724,20676,20629,20581,
1047 20533,20485,20438,20390,20342,20294,20246,20199,
1048 20151,20103,20055,20007,19959,19912,19864,19816,
1049 19768,19720,19672,19624,19576,19528,19480,19432,
1050 19384,19336,19288,19240,19192,19144,19096,19048,
1051 19000,18951,18903,18855,18807,18759,18711,18663,
1052 18614,18566,18518,18470,18421,18373,18325,18277,
1053 18228,18180,18132,18084,18035,17987,17939,17890,
1054 17842,17793,17745,17697,17648,17600,17551,17503,
1055 17455,17406,17358,17309,17261,17212,17164,17115,
1056 17067,17018,16970,16921,16872,16824,16775,16727,
1057 16678,16629,16581,16532,16484,16435,16386,16338,
1058 16289,16240,16191,16143,16094,16045,15997,15948,
1059 15899,15850,15802,15753,15704,15655,15606,15557,
1060 15509,15460,15411,15362,15313,15264,15215,15167,
1061 15118,15069,15020,14971,14922,14873,14824,14775,
1062 14726,14677,14628,14579,14530,14481,14432,14383,
1063 14334,14285,14236,14187,14138,14089,14040,13990,
1064 13941,13892,13843,13794,13745,13696,13646,13597,
1065 13548,13499,13450,13401,13351,13302,13253,13204,
1066 13154,13105,13056,13007,12957,12908,12859,12810,
1067 12760,12711,12662,12612,12563,12514,12464,12415,
1068 12366,12316,12267,12218,12168,12119,12069,12020,
1069 11970,11921,11872,11822,11773,11723,11674,11624,
1070 11575,11525,11476,11426,11377,11327,11278,11228,
1071 11179,11129,11080,11030,10981,10931,10882,10832,
1072 10782,10733,10683,10634,10584,10534,10485,10435,
1073 10386,10336,10286,10237,10187,10137,10088,10038,
1074 9988,9939,9889,9839,9790,9740,9690,9640,
1075 9591,9541,9491,9442,9392,9342,9292,9243,
1076 9193,9143,9093,9043,8994,8944,8894,8844,
1077 8794,8745,8695,8645,8595,8545,8496,8446,
1078 8396,8346,8296,8246,8196,8147,8097,8047,
1079 7997,7947,7897,7847,7797,7747,7697,7648,
1080 7598,7548,7498,7448,7398,7348,7298,7248,
1081 7198,7148,7098,7048,6998,6948,6898,6848,
1082 6798,6748,6698,6648,6598,6548,6498,6448,
1083 6398,6348,6298,6248,6198,6148,6098,6048,
1084 5998,5948,5898,5848,5798,5748,5697,5647,
1085 5597,5547,5497,5447,5397,5347,5297,5247,
1086 5197,5146,5096,5046,4996,4946,4896,4846,
1087 4796,4745,4695,4645,4595,4545,4495,4445,
1088 4394,4344,4294,4244,4194,4144,4093,4043,
1089 3993,3943,3893,3843,3792,3742,3692,3642,
1090 3592,3541,3491,3441,3391,3341,3291,3240,
1091 3190,3140,3090,3039,2989,2939,2889,2839,
1092 2788,2738,2688,2638,2587,2537,2487,2437,
1093 2387,2336,2286,2236,2186,2135,2085,2035,
1094 1985,1934,1884,1834,1784,1733,1683,1633,
1095 1583,1532,1482,1432,1382,1331,1281,1231,
1096 1181,1130,1080,1030,980,929,879,829,
1097 779,728,678,628,578,527,477,427,
1098 376,326,276,226,175,125,75,25,
1099 -25,-75,-125,-175,-226,-276,-326,-376,
1100 -427,-477,-527,-578,-628,-678,-728,-779,
1101 -829,-879,-929,-980,-1030,-1080,-1130,-1181,
1102 -1231,-1281,-1331,-1382,-1432,-1482,-1532,-1583,
1103 -1633,-1683,-1733,-1784,-1834,-1884,-1934,-1985,
1104 -2035,-2085,-2135,-2186,-2236,-2286,-2336,-2387,
1105 -2437,-2487,-2537,-2588,-2638,-2688,-2738,-2788,
1106 -2839,-2889,-2939,-2989,-3039,-3090,-3140,-3190,
1107 -3240,-3291,-3341,-3391,-3441,-3491,-3541,-3592,
1108 -3642,-3692,-3742,-3792,-3843,-3893,-3943,-3993,
1109 -4043,-4093,-4144,-4194,-4244,-4294,-4344,-4394,
1110 -4445,-4495,-4545,-4595,-4645,-4695,-4745,-4796,
1111 -4846,-4896,-4946,-4996,-5046,-5096,-5146,-5197,
1112 -5247,-5297,-5347,-5397,-5447,-5497,-5547,-5597,
1113 -5647,-5697,-5748,-5798,-5848,-5898,-5948,-5998,
1114 -6048,-6098,-6148,-6198,-6248,-6298,-6348,-6398,
1115 -6448,-6498,-6548,-6598,-6648,-6698,-6748,-6798,
1116 -6848,-6898,-6948,-6998,-7048,-7098,-7148,-7198,
1117 -7248,-7298,-7348,-7398,-7448,-7498,-7548,-7598,
1118 -7648,-7697,-7747,-7797,-7847,-7897,-7947,-7997,
1119 -8047,-8097,-8147,-8196,-8246,-8296,-8346,-8396,
1120 -8446,-8496,-8545,-8595,-8645,-8695,-8745,-8794,
1121 -8844,-8894,-8944,-8994,-9043,-9093,-9143,-9193,
1122 -9243,-9292,-9342,-9392,-9442,-9491,-9541,-9591,
1123 -9640,-9690,-9740,-9790,-9839,-9889,-9939,-9988,
1124 -10038,-10088,-10137,-10187,-10237,-10286,-10336,-10386,
1125 -10435,-10485,-10534,-10584,-10634,-10683,-10733,-10782,
1126 -10832,-10882,-10931,-10981,-11030,-11080,-11129,-11179,
1127 -11228,-11278,-11327,-11377,-11426,-11476,-11525,-11575,
1128 -11624,-11674,-11723,-11773,-11822,-11872,-11921,-11970,
1129 -12020,-12069,-12119,-12168,-12218,-12267,-12316,-12366,
1130 -12415,-12464,-12514,-12563,-12612,-12662,-12711,-12760,
1131 -12810,-12859,-12908,-12957,-13007,-13056,-13105,-13154,
1132 -13204,-13253,-13302,-13351,-13401,-13450,-13499,-13548,
1133 -13597,-13647,-13696,-13745,-13794,-13843,-13892,-13941,
1134 -13990,-14040,-14089,-14138,-14187,-14236,-14285,-14334,
1135 -14383,-14432,-14481,-14530,-14579,-14628,-14677,-14726,
1136 -14775,-14824,-14873,-14922,-14971,-15020,-15069,-15118,
1137 -15167,-15215,-15264,-15313,-15362,-15411,-15460,-15509,
1138 -15557,-15606,-15655,-15704,-15753,-15802,-15850,-15899,
1139 -15948,-15997,-16045,-16094,-16143,-16191,-16240,-16289,
1140 -16338,-16386,-16435,-16484,-16532,-16581,-16629,-16678,
1141 -16727,-16775,-16824,-16872,-16921,-16970,-17018,-17067,
1142 -17115,-17164,-17212,-17261,-17309,-17358,-17406,-17455,
1143 -17503,-17551,-17600,-17648,-17697,-17745,-17793,-17842,
1144 -17890,-17939,-17987,-18035,-18084,-18132,-18180,-18228,
1145 -18277,-18325,-18373,-18421,-18470,-18518,-18566,-18614,
1146 -18663,-18711,-18759,-18807,-18855,-18903,-18951,-19000,
1147 -19048,-19096,-19144,-19192,-19240,-19288,-19336,-19384,
1148 -19432,-19480,-19528,-19576,-19624,-19672,-19720,-19768,
1149 -19816,-19864,-19912,-19959,-20007,-20055,-20103,-20151,
1150 -20199,-20246,-20294,-20342,-20390,-20438,-20485,-20533,
1151 -20581,-20629,-20676,-20724,-20772,-20819,-20867,-20915,
1152 -20962,-21010,-21057,-21105,-21153,-21200,-21248,-21295,
1153 -21343,-21390,-21438,-21485,-21533,-21580,-21628,-21675,
1154 -21723,-21770,-21817,-21865,-21912,-21960,-22007,-22054,
1155 -22102,-22149,-22196,-22243,-22291,-22338,-22385,-22433,
1156 -22480,-22527,-22574,-22621,-22668,-22716,-22763,-22810,
1157 -22857,-22904,-22951,-22998,-23045,-23092,-23139,-23186,
1158 -23233,-23280,-23327,-23374,-23421,-23468,-23515,-23562,
1159 -23609,-23656,-23703,-23750,-23796,-23843,-23890,-23937,
1160 -23984,-24030,-24077,-24124,-24171,-24217,-24264,-24311,
1161 -24357,-24404,-24451,-24497,-24544,-24591,-24637,-24684,
1162 -24730,-24777,-24823,-24870,-24916,-24963,-25009,-25056,
1163 -25102,-25149,-25195,-25241,-25288,-25334,-25381,-25427,
1164 -25473,-25520,-25566,-25612,-25658,-25705,-25751,-25797,
1165 -25843,-25889,-25936,-25982,-26028,-26074,-26120,-26166,
1166 -26212,-26258,-26304,-26350,-26396,-26442,-26488,-26534,
1167 -26580,-26626,-26672,-26718,-26764,-26810,-26856,-26902,
1168 -26947,-26993,-27039,-27085,-27131,-27176,-27222,-27268,
1169 -27313,-27359,-27405,-27450,-27496,-27542,-27587,-27633,
1170 -27678,-27724,-27770,-27815,-27861,-27906,-27952,-27997,
1171 -28042,-28088,-28133,-28179,-28224,-28269,-28315,-28360,
1172 -28405,-28451,-28496,-28541,-28586,-28632,-28677,-28722,
1173 -28767,-28812,-28858,-28903,-28948,-28993,-29038,-29083,
1174 -29128,-29173,-29218,-29263,-29308,-29353,-29398,-29443,
1175 -29488,-29533,-29577,-29622,-29667,-29712,-29757,-29801,
1176 -29846,-29891,-29936,-29980,-30025,-30070,-30114,-30159,
1177 -30204,-30248,-30293,-30337,-30382,-30426,-30471,-30515,
1178 -30560,-30604,-30649,-30693,-30738,-30782,-30826,-30871,
1179 -30915,-30959,-31004,-31048,-31092,-31136,-31181,-31225,
1180 -31269,-31313,-31357,-31402,-31446,-31490,-31534,-31578,
1181 -31622,-31666,-31710,-31754,-31798,-31842,-31886,-31930,
1182 -31974,-32017,-32061,-32105,-32149,-32193,-32236,-32280,
1183 -32324,-32368,-32411,-32455,-32499,-32542,-32586,-32630,
1184 -32673,-32717,-32760,-32804,-32847,-32891,-32934,-32978,
1185 -33021,-33065,-33108,-33151,-33195,-33238,-33281,-33325,
1186 -33368,-33411,-33454,-33498,-33541,-33584,-33627,-33670,
1187 -33713,-33756,-33799,-33843,-33886,-33929,-33972,-34015,
1188 -34057,-34100,-34143,-34186,-34229,-34272,-34315,-34358,
1189 -34400,-34443,-34486,-34529,-34571,-34614,-34657,-34699,
1190 -34742,-34785,-34827,-34870,-34912,-34955,-34997,-35040,
1191 -35082,-35125,-35167,-35210,-35252,-35294,-35337,-35379,
1192 -35421,-35464,-35506,-35548,-35590,-35633,-35675,-35717,
1193 -35759,-35801,-35843,-35885,-35927,-35969,-36011,-36053,
1194 -36095,-36137,-36179,-36221,-36263,-36305,-36347,-36388,
1195 -36430,-36472,-36514,-36555,-36597,-36639,-36681,-36722,
1196 -36764,-36805,-36847,-36889,-36930,-36972,-37013,-37055,
1197 -37096,-37137,-37179,-37220,-37262,-37303,-37344,-37386,
1198 -37427,-37468,-37509,-37551,-37592,-37633,-37674,-37715,
1199 -37756,-37797,-37838,-37879,-37920,-37961,-38002,-38043,
1200 -38084,-38125,-38166,-38207,-38248,-38288,-38329,-38370,
1201 -38411,-38451,-38492,-38533,-38573,-38614,-38655,-38695,
1202 -38736,-38776,-38817,-38857,-38898,-38938,-38979,-39019,
1203 -39059,-39100,-39140,-39180,-39221,-39261,-39301,-39341,
1204 -39382,-39422,-39462,-39502,-39542,-39582,-39622,-39662,
1205 -39702,-39742,-39782,-39822,-39862,-39902,-39942,-39982,
1206 -40021,-40061,-40101,-40141,-40180,-40220,-40260,-40299,
1207 -40339,-40379,-40418,-40458,-40497,-40537,-40576,-40616,
1208 -40655,-40695,-40734,-40773,-40813,-40852,-40891,-40931,
1209 -40970,-41009,-41048,-41087,-41127,-41166,-41205,-41244,
1210 -41283,-41322,-41361,-41400,-41439,-41478,-41517,-41556,
1211 -41595,-41633,-41672,-41711,-41750,-41788,-41827,-41866,
1212 -41904,-41943,-41982,-42020,-42059,-42097,-42136,-42174,
1213 -42213,-42251,-42290,-42328,-42366,-42405,-42443,-42481,
1214 -42520,-42558,-42596,-42634,-42672,-42711,-42749,-42787,
1215 -42825,-42863,-42901,-42939,-42977,-43015,-43053,-43091,
1216 -43128,-43166,-43204,-43242,-43280,-43317,-43355,-43393,
1217 -43430,-43468,-43506,-43543,-43581,-43618,-43656,-43693,
1218 -43731,-43768,-43806,-43843,-43880,-43918,-43955,-43992,
1219 -44029,-44067,-44104,-44141,-44178,-44215,-44252,-44289,
1220 -44326,-44363,-44400,-44437,-44474,-44511,-44548,-44585,
1221 -44622,-44659,-44695,-44732,-44769,-44806,-44842,-44879,
1222 -44915,-44952,-44989,-45025,-45062,-45098,-45135,-45171,
1223 -45207,-45244,-45280,-45316,-45353,-45389,-45425,-45462,
1224 -45498,-45534,-45570,-45606,-45642,-45678,-45714,-45750,
1225 -45786,-45822,-45858,-45894,-45930,-45966,-46002,-46037,
1226 -46073,-46109,-46145,-46180,-46216,-46252,-46287,-46323,
1227 -46358,-46394,-46429,-46465,-46500,-46536,-46571,-46606,
1228 -46642,-46677,-46712,-46747,-46783,-46818,-46853,-46888,
1229 -46923,-46958,-46993,-47028,-47063,-47098,-47133,-47168,
1230 -47203,-47238,-47273,-47308,-47342,-47377,-47412,-47446,
1231 -47481,-47516,-47550,-47585,-47619,-47654,-47688,-47723,
1232 -47757,-47792,-47826,-47860,-47895,-47929,-47963,-47998,
1233 -48032,-48066,-48100,-48134,-48168,-48202,-48236,-48271,
1234 -48304,-48338,-48372,-48406,-48440,-48474,-48508,-48542,
1235 -48575,-48609,-48643,-48676,-48710,-48744,-48777,-48811,
1236 -48844,-48878,-48911,-48945,-48978,-49012,-49045,-49078,
1237 -49112,-49145,-49178,-49211,-49244,-49278,-49311,-49344,
1238 -49377,-49410,-49443,-49476,-49509,-49542,-49575,-49608,
1239 -49640,-49673,-49706,-49739,-49771,-49804,-49837,-49869,
1240 -49902,-49935,-49967,-50000,-50032,-50065,-50097,-50129,
1241 -50162,-50194,-50226,-50259,-50291,-50323,-50355,-50387,
1242 -50420,-50452,-50484,-50516,-50548,-50580,-50612,-50644,
1243 -50675,-50707,-50739,-50771,-50803,-50834,-50866,-50898,
1244 -50929,-50961,-50993,-51024,-51056,-51087,-51119,-51150,
1245 -51182,-51213,-51244,-51276,-51307,-51338,-51369,-51401,
1246 -51432,-51463,-51494,-51525,-51556,-51587,-51618,-51649,
1247 -51680,-51711,-51742,-51773,-51803,-51834,-51865,-51896,
1248 -51926,-51957,-51988,-52018,-52049,-52079,-52110,-52140,
1249 -52171,-52201,-52231,-52262,-52292,-52322,-52353,-52383,
1250 -52413,-52443,-52473,-52503,-52534,-52564,-52594,-52624,
1251 -52653,-52683,-52713,-52743,-52773,-52803,-52832,-52862,
1252 -52892,-52922,-52951,-52981,-53010,-53040,-53069,-53099,
1253 -53128,-53158,-53187,-53216,-53246,-53275,-53304,-53334,
1254 -53363,-53392,-53421,-53450,-53479,-53508,-53537,-53566,
1255 -53595,-53624,-53653,-53682,-53711,-53739,-53768,-53797,
1256 -53826,-53854,-53883,-53911,-53940,-53969,-53997,-54026,
1257 -54054,-54082,-54111,-54139,-54167,-54196,-54224,-54252,
1258 -54280,-54308,-54337,-54365,-54393,-54421,-54449,-54477,
1259 -54505,-54533,-54560,-54588,-54616,-54644,-54672,-54699,
1260 -54727,-54755,-54782,-54810,-54837,-54865,-54892,-54920,
1261 -54947,-54974,-55002,-55029,-55056,-55084,-55111,-55138,
1262 -55165,-55192,-55219,-55246,-55274,-55300,-55327,-55354,
1263 -55381,-55408,-55435,-55462,-55489,-55515,-55542,-55569,
1264 -55595,-55622,-55648,-55675,-55701,-55728,-55754,-55781,
1265 -55807,-55833,-55860,-55886,-55912,-55938,-55965,-55991,
1266 -56017,-56043,-56069,-56095,-56121,-56147,-56173,-56199,
1267 -56225,-56250,-56276,-56302,-56328,-56353,-56379,-56404,
1268 -56430,-56456,-56481,-56507,-56532,-56557,-56583,-56608,
1269 -56633,-56659,-56684,-56709,-56734,-56760,-56785,-56810,
1270 -56835,-56860,-56885,-56910,-56935,-56959,-56984,-57009,
1271 -57034,-57059,-57083,-57108,-57133,-57157,-57182,-57206,
1272 -57231,-57255,-57280,-57304,-57329,-57353,-57377,-57402,
1273 -57426,-57450,-57474,-57498,-57522,-57546,-57570,-57594,
1274 -57618,-57642,-57666,-57690,-57714,-57738,-57762,-57785,
1275 -57809,-57833,-57856,-57880,-57903,-57927,-57950,-57974,
1276 -57997,-58021,-58044,-58067,-58091,-58114,-58137,-58160,
1277 -58183,-58207,-58230,-58253,-58276,-58299,-58322,-58345,
1278 -58367,-58390,-58413,-58436,-58459,-58481,-58504,-58527,
1279 -58549,-58572,-58594,-58617,-58639,-58662,-58684,-58706,
1280 -58729,-58751,-58773,-58795,-58818,-58840,-58862,-58884,
1281 -58906,-58928,-58950,-58972,-58994,-59016,-59038,-59059,
1282 -59081,-59103,-59125,-59146,-59168,-59190,-59211,-59233,
1283 -59254,-59276,-59297,-59318,-59340,-59361,-59382,-59404,
1284 -59425,-59446,-59467,-59488,-59509,-59530,-59551,-59572,
1285 -59593,-59614,-59635,-59656,-59677,-59697,-59718,-59739,
1286 -59759,-59780,-59801,-59821,-59842,-59862,-59883,-59903,
1287 -59923,-59944,-59964,-59984,-60004,-60025,-60045,-60065,
1288 -60085,-60105,-60125,-60145,-60165,-60185,-60205,-60225,
1289 -60244,-60264,-60284,-60304,-60323,-60343,-60363,-60382,
1290 -60402,-60421,-60441,-60460,-60479,-60499,-60518,-60537,
1291 -60556,-60576,-60595,-60614,-60633,-60652,-60671,-60690,
1292 -60709,-60728,-60747,-60766,-60785,-60803,-60822,-60841,
1293 -60859,-60878,-60897,-60915,-60934,-60952,-60971,-60989,
1294 -61007,-61026,-61044,-61062,-61081,-61099,-61117,-61135,
1295 -61153,-61171,-61189,-61207,-61225,-61243,-61261,-61279,
1296 -61297,-61314,-61332,-61350,-61367,-61385,-61403,-61420,
1297 -61438,-61455,-61473,-61490,-61507,-61525,-61542,-61559,
1298 -61577,-61594,-61611,-61628,-61645,-61662,-61679,-61696,
1299 -61713,-61730,-61747,-61764,-61780,-61797,-61814,-61831,
1300 -61847,-61864,-61880,-61897,-61913,-61930,-61946,-61963,
1301 -61979,-61995,-62012,-62028,-62044,-62060,-62076,-62092,
1302 -62108,-62125,-62141,-62156,-62172,-62188,-62204,-62220,
1303 -62236,-62251,-62267,-62283,-62298,-62314,-62329,-62345,
1304 -62360,-62376,-62391,-62407,-62422,-62437,-62453,-62468,
1305 -62483,-62498,-62513,-62528,-62543,-62558,-62573,-62588,
1306 -62603,-62618,-62633,-62648,-62662,-62677,-62692,-62706,
1307 -62721,-62735,-62750,-62764,-62779,-62793,-62808,-62822,
1308 -62836,-62850,-62865,-62879,-62893,-62907,-62921,-62935,
1309 -62949,-62963,-62977,-62991,-63005,-63019,-63032,-63046,
1310 -63060,-63074,-63087,-63101,-63114,-63128,-63141,-63155,
1311 -63168,-63182,-63195,-63208,-63221,-63235,-63248,-63261,
1312 -63274,-63287,-63300,-63313,-63326,-63339,-63352,-63365,
1313 -63378,-63390,-63403,-63416,-63429,-63441,-63454,-63466,
1314 -63479,-63491,-63504,-63516,-63528,-63541,-63553,-63565,
1315 -63578,-63590,-63602,-63614,-63626,-63638,-63650,-63662,
1316 -63674,-63686,-63698,-63709,-63721,-63733,-63745,-63756,
1317 -63768,-63779,-63791,-63803,-63814,-63825,-63837,-63848,
1318 -63859,-63871,-63882,-63893,-63904,-63915,-63927,-63938,
1319 -63949,-63960,-63971,-63981,-63992,-64003,-64014,-64025,
1320 -64035,-64046,-64057,-64067,-64078,-64088,-64099,-64109,
1321 -64120,-64130,-64140,-64151,-64161,-64171,-64181,-64192,
1322 -64202,-64212,-64222,-64232,-64242,-64252,-64261,-64271,
1323 -64281,-64291,-64301,-64310,-64320,-64330,-64339,-64349,
1324 -64358,-64368,-64377,-64387,-64396,-64405,-64414,-64424,
1325 -64433,-64442,-64451,-64460,-64469,-64478,-64487,-64496,
1326 -64505,-64514,-64523,-64532,-64540,-64549,-64558,-64566,
1327 -64575,-64584,-64592,-64601,-64609,-64617,-64626,-64634,
1328 -64642,-64651,-64659,-64667,-64675,-64683,-64691,-64699,
1329 -64707,-64715,-64723,-64731,-64739,-64747,-64754,-64762,
1330 -64770,-64777,-64785,-64793,-64800,-64808,-64815,-64822,
1331 -64830,-64837,-64844,-64852,-64859,-64866,-64873,-64880,
1332 -64887,-64895,-64902,-64908,-64915,-64922,-64929,-64936,
1333 -64943,-64949,-64956,-64963,-64969,-64976,-64982,-64989,
1334 -64995,-65002,-65008,-65015,-65021,-65027,-65033,-65040,
1335 -65046,-65052,-65058,-65064,-65070,-65076,-65082,-65088,
1336 -65094,-65099,-65105,-65111,-65117,-65122,-65128,-65133,
1337 -65139,-65144,-65150,-65155,-65161,-65166,-65171,-65177,
1338 -65182,-65187,-65192,-65197,-65202,-65207,-65212,-65217,
1339 -65222,-65227,-65232,-65237,-65242,-65246,-65251,-65256,
1340 -65260,-65265,-65270,-65274,-65279,-65283,-65287,-65292,
1341 -65296,-65300,-65305,-65309,-65313,-65317,-65321,-65325,
1342 -65329,-65333,-65337,-65341,-65345,-65349,-65352,-65356,
1343 -65360,-65363,-65367,-65371,-65374,-65378,-65381,-65385,
1344 -65388,-65391,-65395,-65398,-65401,-65404,-65408,-65411,
1345 -65414,-65417,-65420,-65423,-65426,-65429,-65431,-65434,
1346 -65437,-65440,-65442,-65445,-65448,-65450,-65453,-65455,
1347 -65458,-65460,-65463,-65465,-65467,-65470,-65472,-65474,
1348 -65476,-65478,-65480,-65482,-65484,-65486,-65488,-65490,
1349 -65492,-65494,-65496,-65497,-65499,-65501,-65502,-65504,
1350 -65505,-65507,-65508,-65510,-65511,-65513,-65514,-65515,
1351 -65516,-65518,-65519,-65520,-65521,-65522,-65523,-65524,
1352 -65525,-65526,-65527,-65527,-65528,-65529,-65530,-65530,
1353 -65531,-65531,-65532,-65532,-65533,-65533,-65534,-65534,
1354 -65534,-65535,-65535,-65535,-65535,-65535,-65535,-65535,
1355 -65535,-65535,-65535,-65535,-65535,-65535,-65535,-65534,
1356 -65534,-65534,-65533,-65533,-65532,-65532,-65531,-65531,
1357 -65530,-65530,-65529,-65528,-65527,-65527,-65526,-65525,
1358 -65524,-65523,-65522,-65521,-65520,-65519,-65518,-65516,
1359 -65515,-65514,-65513,-65511,-65510,-65508,-65507,-65505,
1360 -65504,-65502,-65501,-65499,-65497,-65496,-65494,-65492,
1361 -65490,-65488,-65486,-65484,-65482,-65480,-65478,-65476,
1362 -65474,-65472,-65470,-65467,-65465,-65463,-65460,-65458,
1363 -65455,-65453,-65450,-65448,-65445,-65442,-65440,-65437,
1364 -65434,-65431,-65429,-65426,-65423,-65420,-65417,-65414,
1365 -65411,-65408,-65404,-65401,-65398,-65395,-65391,-65388,
1366 -65385,-65381,-65378,-65374,-65371,-65367,-65363,-65360,
1367 -65356,-65352,-65349,-65345,-65341,-65337,-65333,-65329,
1368 -65325,-65321,-65317,-65313,-65309,-65305,-65300,-65296,
1369 -65292,-65287,-65283,-65279,-65274,-65270,-65265,-65260,
1370 -65256,-65251,-65246,-65242,-65237,-65232,-65227,-65222,
1371 -65217,-65212,-65207,-65202,-65197,-65192,-65187,-65182,
1372 -65177,-65171,-65166,-65161,-65155,-65150,-65144,-65139,
1373 -65133,-65128,-65122,-65117,-65111,-65105,-65099,-65094,
1374 -65088,-65082,-65076,-65070,-65064,-65058,-65052,-65046,
1375 -65040,-65033,-65027,-65021,-65015,-65008,-65002,-64995,
1376 -64989,-64982,-64976,-64969,-64963,-64956,-64949,-64943,
1377 -64936,-64929,-64922,-64915,-64908,-64902,-64895,-64887,
1378 -64880,-64873,-64866,-64859,-64852,-64844,-64837,-64830,
1379 -64822,-64815,-64808,-64800,-64793,-64785,-64777,-64770,
1380 -64762,-64754,-64747,-64739,-64731,-64723,-64715,-64707,
1381 -64699,-64691,-64683,-64675,-64667,-64659,-64651,-64642,
1382 -64634,-64626,-64617,-64609,-64601,-64592,-64584,-64575,
1383 -64566,-64558,-64549,-64540,-64532,-64523,-64514,-64505,
1384 -64496,-64487,-64478,-64469,-64460,-64451,-64442,-64433,
1385 -64424,-64414,-64405,-64396,-64387,-64377,-64368,-64358,
1386 -64349,-64339,-64330,-64320,-64310,-64301,-64291,-64281,
1387 -64271,-64261,-64252,-64242,-64232,-64222,-64212,-64202,
1388 -64192,-64181,-64171,-64161,-64151,-64140,-64130,-64120,
1389 -64109,-64099,-64088,-64078,-64067,-64057,-64046,-64035,
1390 -64025,-64014,-64003,-63992,-63981,-63971,-63960,-63949,
1391 -63938,-63927,-63915,-63904,-63893,-63882,-63871,-63859,
1392 -63848,-63837,-63825,-63814,-63803,-63791,-63779,-63768,
1393 -63756,-63745,-63733,-63721,-63709,-63698,-63686,-63674,
1394 -63662,-63650,-63638,-63626,-63614,-63602,-63590,-63578,
1395 -63565,-63553,-63541,-63528,-63516,-63504,-63491,-63479,
1396 -63466,-63454,-63441,-63429,-63416,-63403,-63390,-63378,
1397 -63365,-63352,-63339,-63326,-63313,-63300,-63287,-63274,
1398 -63261,-63248,-63235,-63221,-63208,-63195,-63182,-63168,
1399 -63155,-63141,-63128,-63114,-63101,-63087,-63074,-63060,
1400 -63046,-63032,-63019,-63005,-62991,-62977,-62963,-62949,
1401 -62935,-62921,-62907,-62893,-62879,-62865,-62850,-62836,
1402 -62822,-62808,-62793,-62779,-62764,-62750,-62735,-62721,
1403 -62706,-62692,-62677,-62662,-62648,-62633,-62618,-62603,
1404 -62588,-62573,-62558,-62543,-62528,-62513,-62498,-62483,
1405 -62468,-62453,-62437,-62422,-62407,-62391,-62376,-62360,
1406 -62345,-62329,-62314,-62298,-62283,-62267,-62251,-62236,
1407 -62220,-62204,-62188,-62172,-62156,-62141,-62125,-62108,
1408 -62092,-62076,-62060,-62044,-62028,-62012,-61995,-61979,
1409 -61963,-61946,-61930,-61913,-61897,-61880,-61864,-61847,
1410 -61831,-61814,-61797,-61780,-61764,-61747,-61730,-61713,
1411 -61696,-61679,-61662,-61645,-61628,-61611,-61594,-61577,
1412 -61559,-61542,-61525,-61507,-61490,-61473,-61455,-61438,
1413 -61420,-61403,-61385,-61367,-61350,-61332,-61314,-61297,
1414 -61279,-61261,-61243,-61225,-61207,-61189,-61171,-61153,
1415 -61135,-61117,-61099,-61081,-61062,-61044,-61026,-61007,
1416 -60989,-60971,-60952,-60934,-60915,-60897,-60878,-60859,
1417 -60841,-60822,-60803,-60785,-60766,-60747,-60728,-60709,
1418 -60690,-60671,-60652,-60633,-60614,-60595,-60576,-60556,
1419 -60537,-60518,-60499,-60479,-60460,-60441,-60421,-60402,
1420 -60382,-60363,-60343,-60323,-60304,-60284,-60264,-60244,
1421 -60225,-60205,-60185,-60165,-60145,-60125,-60105,-60085,
1422 -60065,-60045,-60025,-60004,-59984,-59964,-59944,-59923,
1423 -59903,-59883,-59862,-59842,-59821,-59801,-59780,-59759,
1424 -59739,-59718,-59697,-59677,-59656,-59635,-59614,-59593,
1425 -59572,-59551,-59530,-59509,-59488,-59467,-59446,-59425,
1426 -59404,-59382,-59361,-59340,-59318,-59297,-59276,-59254,
1427 -59233,-59211,-59189,-59168,-59146,-59125,-59103,-59081,
1428 -59059,-59038,-59016,-58994,-58972,-58950,-58928,-58906,
1429 -58884,-58862,-58840,-58818,-58795,-58773,-58751,-58729,
1430 -58706,-58684,-58662,-58639,-58617,-58594,-58572,-58549,
1431 -58527,-58504,-58481,-58459,-58436,-58413,-58390,-58367,
1432 -58345,-58322,-58299,-58276,-58253,-58230,-58207,-58183,
1433 -58160,-58137,-58114,-58091,-58067,-58044,-58021,-57997,
1434 -57974,-57950,-57927,-57903,-57880,-57856,-57833,-57809,
1435 -57785,-57762,-57738,-57714,-57690,-57666,-57642,-57618,
1436 -57594,-57570,-57546,-57522,-57498,-57474,-57450,-57426,
1437 -57402,-57377,-57353,-57329,-57304,-57280,-57255,-57231,
1438 -57206,-57182,-57157,-57133,-57108,-57083,-57059,-57034,
1439 -57009,-56984,-56959,-56935,-56910,-56885,-56860,-56835,
1440 -56810,-56785,-56760,-56734,-56709,-56684,-56659,-56633,
1441 -56608,-56583,-56557,-56532,-56507,-56481,-56456,-56430,
1442 -56404,-56379,-56353,-56328,-56302,-56276,-56250,-56225,
1443 -56199,-56173,-56147,-56121,-56095,-56069,-56043,-56017,
1444 -55991,-55965,-55938,-55912,-55886,-55860,-55833,-55807,
1445 -55781,-55754,-55728,-55701,-55675,-55648,-55622,-55595,
1446 -55569,-55542,-55515,-55489,-55462,-55435,-55408,-55381,
1447 -55354,-55327,-55300,-55274,-55246,-55219,-55192,-55165,
1448 -55138,-55111,-55084,-55056,-55029,-55002,-54974,-54947,
1449 -54920,-54892,-54865,-54837,-54810,-54782,-54755,-54727,
1450 -54699,-54672,-54644,-54616,-54588,-54560,-54533,-54505,
1451 -54477,-54449,-54421,-54393,-54365,-54337,-54308,-54280,
1452 -54252,-54224,-54196,-54167,-54139,-54111,-54082,-54054,
1453 -54026,-53997,-53969,-53940,-53911,-53883,-53854,-53826,
1454 -53797,-53768,-53739,-53711,-53682,-53653,-53624,-53595,
1455 -53566,-53537,-53508,-53479,-53450,-53421,-53392,-53363,
1456 -53334,-53304,-53275,-53246,-53216,-53187,-53158,-53128,
1457 -53099,-53069,-53040,-53010,-52981,-52951,-52922,-52892,
1458 -52862,-52832,-52803,-52773,-52743,-52713,-52683,-52653,
1459 -52624,-52594,-52564,-52534,-52503,-52473,-52443,-52413,
1460 -52383,-52353,-52322,-52292,-52262,-52231,-52201,-52171,
1461 -52140,-52110,-52079,-52049,-52018,-51988,-51957,-51926,
1462 -51896,-51865,-51834,-51803,-51773,-51742,-51711,-51680,
1463 -51649,-51618,-51587,-51556,-51525,-51494,-51463,-51432,
1464 -51401,-51369,-51338,-51307,-51276,-51244,-51213,-51182,
1465 -51150,-51119,-51087,-51056,-51024,-50993,-50961,-50929,
1466 -50898,-50866,-50834,-50803,-50771,-50739,-50707,-50675,
1467 -50644,-50612,-50580,-50548,-50516,-50484,-50452,-50420,
1468 -50387,-50355,-50323,-50291,-50259,-50226,-50194,-50162,
1469 -50129,-50097,-50065,-50032,-50000,-49967,-49935,-49902,
1470 -49869,-49837,-49804,-49771,-49739,-49706,-49673,-49640,
1471 -49608,-49575,-49542,-49509,-49476,-49443,-49410,-49377,
1472 -49344,-49311,-49278,-49244,-49211,-49178,-49145,-49112,
1473 -49078,-49045,-49012,-48978,-48945,-48911,-48878,-48844,
1474 -48811,-48777,-48744,-48710,-48676,-48643,-48609,-48575,
1475 -48542,-48508,-48474,-48440,-48406,-48372,-48338,-48305,
1476 -48271,-48237,-48202,-48168,-48134,-48100,-48066,-48032,
1477 -47998,-47963,-47929,-47895,-47860,-47826,-47792,-47757,
1478 -47723,-47688,-47654,-47619,-47585,-47550,-47516,-47481,
1479 -47446,-47412,-47377,-47342,-47307,-47273,-47238,-47203,
1480 -47168,-47133,-47098,-47063,-47028,-46993,-46958,-46923,
1481 -46888,-46853,-46818,-46783,-46747,-46712,-46677,-46642,
1482 -46606,-46571,-46536,-46500,-46465,-46429,-46394,-46358,
1483 -46323,-46287,-46251,-46216,-46180,-46145,-46109,-46073,
1484 -46037,-46002,-45966,-45930,-45894,-45858,-45822,-45786,
1485 -45750,-45714,-45678,-45642,-45606,-45570,-45534,-45498,
1486 -45462,-45425,-45389,-45353,-45316,-45280,-45244,-45207,
1487 -45171,-45135,-45098,-45062,-45025,-44989,-44952,-44915,
1488 -44879,-44842,-44806,-44769,-44732,-44695,-44659,-44622,
1489 -44585,-44548,-44511,-44474,-44437,-44400,-44363,-44326,
1490 -44289,-44252,-44215,-44178,-44141,-44104,-44067,-44029,
1491 -43992,-43955,-43918,-43880,-43843,-43806,-43768,-43731,
1492 -43693,-43656,-43618,-43581,-43543,-43506,-43468,-43430,
1493 -43393,-43355,-43317,-43280,-43242,-43204,-43166,-43128,
1494 -43091,-43053,-43015,-42977,-42939,-42901,-42863,-42825,
1495 -42787,-42749,-42711,-42672,-42634,-42596,-42558,-42520,
1496 -42481,-42443,-42405,-42366,-42328,-42290,-42251,-42213,
1497 -42174,-42136,-42097,-42059,-42020,-41982,-41943,-41904,
1498 -41866,-41827,-41788,-41750,-41711,-41672,-41633,-41595,
1499 -41556,-41517,-41478,-41439,-41400,-41361,-41322,-41283,
1500 -41244,-41205,-41166,-41127,-41087,-41048,-41009,-40970,
1501 -40931,-40891,-40852,-40813,-40773,-40734,-40695,-40655,
1502 -40616,-40576,-40537,-40497,-40458,-40418,-40379,-40339,
1503 -40299,-40260,-40220,-40180,-40141,-40101,-40061,-40021,
1504 -39982,-39942,-39902,-39862,-39822,-39782,-39742,-39702,
1505 -39662,-39622,-39582,-39542,-39502,-39462,-39422,-39382,
1506 -39341,-39301,-39261,-39221,-39180,-39140,-39100,-39059,
1507 -39019,-38979,-38938,-38898,-38857,-38817,-38776,-38736,
1508 -38695,-38655,-38614,-38573,-38533,-38492,-38451,-38411,
1509 -38370,-38329,-38288,-38248,-38207,-38166,-38125,-38084,
1510 -38043,-38002,-37961,-37920,-37879,-37838,-37797,-37756,
1511 -37715,-37674,-37633,-37592,-37550,-37509,-37468,-37427,
1512 -37386,-37344,-37303,-37262,-37220,-37179,-37137,-37096,
1513 -37055,-37013,-36972,-36930,-36889,-36847,-36805,-36764,
1514 -36722,-36681,-36639,-36597,-36556,-36514,-36472,-36430,
1515 -36388,-36347,-36305,-36263,-36221,-36179,-36137,-36095,
1516 -36053,-36011,-35969,-35927,-35885,-35843,-35801,-35759,
1517 -35717,-35675,-35633,-35590,-35548,-35506,-35464,-35421,
1518 -35379,-35337,-35294,-35252,-35210,-35167,-35125,-35082,
1519 -35040,-34997,-34955,-34912,-34870,-34827,-34785,-34742,
1520 -34699,-34657,-34614,-34571,-34529,-34486,-34443,-34400,
1521 -34358,-34315,-34272,-34229,-34186,-34143,-34100,-34057,
1522 -34015,-33972,-33929,-33886,-33843,-33799,-33756,-33713,
1523 -33670,-33627,-33584,-33541,-33498,-33454,-33411,-33368,
1524 -33325,-33281,-33238,-33195,-33151,-33108,-33065,-33021,
1525 -32978,-32934,-32891,-32847,-32804,-32760,-32717,-32673,
1526 -32630,-32586,-32542,-32499,-32455,-32411,-32368,-32324,
1527 -32280,-32236,-32193,-32149,-32105,-32061,-32017,-31974,
1528 -31930,-31886,-31842,-31798,-31754,-31710,-31666,-31622,
1529 -31578,-31534,-31490,-31446,-31402,-31357,-31313,-31269,
1530 -31225,-31181,-31136,-31092,-31048,-31004,-30959,-30915,
1531 -30871,-30826,-30782,-30738,-30693,-30649,-30604,-30560,
1532 -30515,-30471,-30426,-30382,-30337,-30293,-30248,-30204,
1533 -30159,-30114,-30070,-30025,-29980,-29936,-29891,-29846,
1534 -29801,-29757,-29712,-29667,-29622,-29577,-29533,-29488,
1535 -29443,-29398,-29353,-29308,-29263,-29218,-29173,-29128,
1536 -29083,-29038,-28993,-28948,-28903,-28858,-28812,-28767,
1537 -28722,-28677,-28632,-28586,-28541,-28496,-28451,-28405,
1538 -28360,-28315,-28269,-28224,-28179,-28133,-28088,-28042,
1539 -27997,-27952,-27906,-27861,-27815,-27770,-27724,-27678,
1540 -27633,-27587,-27542,-27496,-27450,-27405,-27359,-27313,
1541 -27268,-27222,-27176,-27131,-27085,-27039,-26993,-26947,
1542 -26902,-26856,-26810,-26764,-26718,-26672,-26626,-26580,
1543 -26534,-26488,-26442,-26396,-26350,-26304,-26258,-26212,
1544 -26166,-26120,-26074,-26028,-25982,-25936,-25889,-25843,
1545 -25797,-25751,-25705,-25658,-25612,-25566,-25520,-25473,
1546 -25427,-25381,-25334,-25288,-25241,-25195,-25149,-25102,
1547 -25056,-25009,-24963,-24916,-24870,-24823,-24777,-24730,
1548 -24684,-24637,-24591,-24544,-24497,-24451,-24404,-24357,
1549 -24311,-24264,-24217,-24171,-24124,-24077,-24030,-23984,
1550 -23937,-23890,-23843,-23796,-23750,-23703,-23656,-23609,
1551 -23562,-23515,-23468,-23421,-23374,-23327,-23280,-23233,
1552 -23186,-23139,-23092,-23045,-22998,-22951,-22904,-22857,
1553 -22810,-22763,-22716,-22668,-22621,-22574,-22527,-22480,
1554 -22432,-22385,-22338,-22291,-22243,-22196,-22149,-22102,
1555 -22054,-22007,-21960,-21912,-21865,-21817,-21770,-21723,
1556 -21675,-21628,-21580,-21533,-21485,-21438,-21390,-21343,
1557 -21295,-21248,-21200,-21153,-21105,-21057,-21010,-20962,
1558 -20915,-20867,-20819,-20772,-20724,-20676,-20629,-20581,
1559 -20533,-20485,-20438,-20390,-20342,-20294,-20246,-20199,
1560 -20151,-20103,-20055,-20007,-19959,-19912,-19864,-19816,
1561 -19768,-19720,-19672,-19624,-19576,-19528,-19480,-19432,
1562 -19384,-19336,-19288,-19240,-19192,-19144,-19096,-19048,
1563 -19000,-18951,-18903,-18855,-18807,-18759,-18711,-18663,
1564 -18614,-18566,-18518,-18470,-18421,-18373,-18325,-18277,
1565 -18228,-18180,-18132,-18084,-18035,-17987,-17939,-17890,
1566 -17842,-17793,-17745,-17697,-17648,-17600,-17551,-17503,
1567 -17455,-17406,-17358,-17309,-17261,-17212,-17164,-17115,
1568 -17067,-17018,-16970,-16921,-16872,-16824,-16775,-16727,
1569 -16678,-16629,-16581,-16532,-16484,-16435,-16386,-16338,
1570 -16289,-16240,-16191,-16143,-16094,-16045,-15997,-15948,
1571 -15899,-15850,-15802,-15753,-15704,-15655,-15606,-15557,
1572 -15509,-15460,-15411,-15362,-15313,-15264,-15215,-15167,
1573 -15118,-15069,-15020,-14971,-14922,-14873,-14824,-14775,
1574 -14726,-14677,-14628,-14579,-14530,-14481,-14432,-14383,
1575 -14334,-14285,-14236,-14187,-14138,-14089,-14040,-13990,
1576 -13941,-13892,-13843,-13794,-13745,-13696,-13647,-13597,
1577 -13548,-13499,-13450,-13401,-13351,-13302,-13253,-13204,
1578 -13154,-13105,-13056,-13007,-12957,-12908,-12859,-12810,
1579 -12760,-12711,-12662,-12612,-12563,-12514,-12464,-12415,
1580 -12366,-12316,-12267,-12217,-12168,-12119,-12069,-12020,
1581 -11970,-11921,-11872,-11822,-11773,-11723,-11674,-11624,
1582 -11575,-11525,-11476,-11426,-11377,-11327,-11278,-11228,
1583 -11179,-11129,-11080,-11030,-10981,-10931,-10882,-10832,
1584 -10782,-10733,-10683,-10634,-10584,-10534,-10485,-10435,
1585 -10386,-10336,-10286,-10237,-10187,-10137,-10088,-10038,
1586 -9988,-9939,-9889,-9839,-9790,-9740,-9690,-9640,
1587 -9591,-9541,-9491,-9442,-9392,-9342,-9292,-9243,
1588 -9193,-9143,-9093,-9043,-8994,-8944,-8894,-8844,
1589 -8794,-8745,-8695,-8645,-8595,-8545,-8496,-8446,
1590 -8396,-8346,-8296,-8246,-8196,-8147,-8097,-8047,
1591 -7997,-7947,-7897,-7847,-7797,-7747,-7697,-7648,
1592 -7598,-7548,-7498,-7448,-7398,-7348,-7298,-7248,
1593 -7198,-7148,-7098,-7048,-6998,-6948,-6898,-6848,
1594 -6798,-6748,-6698,-6648,-6598,-6548,-6498,-6448,
1595 -6398,-6348,-6298,-6248,-6198,-6148,-6098,-6048,
1596 -5998,-5948,-5898,-5848,-5798,-5747,-5697,-5647,
1597 -5597,-5547,-5497,-5447,-5397,-5347,-5297,-5247,
1598 -5197,-5146,-5096,-5046,-4996,-4946,-4896,-4846,
1599 -4796,-4745,-4695,-4645,-4595,-4545,-4495,-4445,
1600 -4394,-4344,-4294,-4244,-4194,-4144,-4093,-4043,
1601 -3993,-3943,-3893,-3843,-3792,-3742,-3692,-3642,
1602 -3592,-3541,-3491,-3441,-3391,-3341,-3291,-3240,
1603 -3190,-3140,-3090,-3039,-2989,-2939,-2889,-2839,
1604 -2788,-2738,-2688,-2638,-2588,-2537,-2487,-2437,
1605 -2387,-2336,-2286,-2236,-2186,-2135,-2085,-2035,
1606 -1985,-1934,-1884,-1834,-1784,-1733,-1683,-1633,
1607 -1583,-1532,-1482,-1432,-1382,-1331,-1281,-1231,
1608 -1181,-1130,-1080,-1030,-980,-929,-879,-829,
1609 -779,-728,-678,-628,-578,-527,-477,-427,
1610 -376,-326,-276,-226,-175,-125,-75,-25,
1611 25,75,125,175,226,276,326,376,
1612 427,477,527,578,628,678,728,779,
1613 829,879,929,980,1030,1080,1130,1181,
1614 1231,1281,1331,1382,1432,1482,1532,1583,
1615 1633,1683,1733,1784,1834,1884,1934,1985,
1616 2035,2085,2135,2186,2236,2286,2336,2387,
1617 2437,2487,2537,2587,2638,2688,2738,2788,
1618 2839,2889,2939,2989,3039,3090,3140,3190,
1619 3240,3291,3341,3391,3441,3491,3542,3592,
1620 3642,3692,3742,3792,3843,3893,3943,3993,
1621 4043,4093,4144,4194,4244,4294,4344,4394,
1622 4445,4495,4545,4595,4645,4695,4745,4796,
1623 4846,4896,4946,4996,5046,5096,5146,5197,
1624 5247,5297,5347,5397,5447,5497,5547,5597,
1625 5647,5697,5747,5798,5848,5898,5948,5998,
1626 6048,6098,6148,6198,6248,6298,6348,6398,
1627 6448,6498,6548,6598,6648,6698,6748,6798,
1628 6848,6898,6948,6998,7048,7098,7148,7198,
1629 7248,7298,7348,7398,7448,7498,7548,7598,
1630 7648,7697,7747,7797,7847,7897,7947,7997,
1631 8047,8097,8147,8196,8246,8296,8346,8396,
1632 8446,8496,8545,8595,8645,8695,8745,8794,
1633 8844,8894,8944,8994,9043,9093,9143,9193,
1634 9243,9292,9342,9392,9442,9491,9541,9591,
1635 9640,9690,9740,9790,9839,9889,9939,9988,
1636 10038,10088,10137,10187,10237,10286,10336,10386,
1637 10435,10485,10534,10584,10634,10683,10733,10782,
1638 10832,10882,10931,10981,11030,11080,11129,11179,
1639 11228,11278,11327,11377,11426,11476,11525,11575,
1640 11624,11674,11723,11773,11822,11872,11921,11970,
1641 12020,12069,12119,12168,12218,12267,12316,12366,
1642 12415,12464,12514,12563,12612,12662,12711,12760,
1643 12810,12859,12908,12957,13007,13056,13105,13154,
1644 13204,13253,13302,13351,13401,13450,13499,13548,
1645 13597,13647,13696,13745,13794,13843,13892,13941,
1646 13990,14040,14089,14138,14187,14236,14285,14334,
1647 14383,14432,14481,14530,14579,14628,14677,14726,
1648 14775,14824,14873,14922,14971,15020,15069,15118,
1649 15167,15215,15264,15313,15362,15411,15460,15509,
1650 15557,15606,15655,15704,15753,15802,15850,15899,
1651 15948,15997,16045,16094,16143,16191,16240,16289,
1652 16338,16386,16435,16484,16532,16581,16629,16678,
1653 16727,16775,16824,16872,16921,16970,17018,17067,
1654 17115,17164,17212,17261,17309,17358,17406,17455,
1655 17503,17551,17600,17648,17697,17745,17793,17842,
1656 17890,17939,17987,18035,18084,18132,18180,18228,
1657 18277,18325,18373,18421,18470,18518,18566,18614,
1658 18663,18711,18759,18807,18855,18903,18951,19000,
1659 19048,19096,19144,19192,19240,19288,19336,19384,
1660 19432,19480,19528,19576,19624,19672,19720,19768,
1661 19816,19864,19912,19959,20007,20055,20103,20151,
1662 20199,20246,20294,20342,20390,20438,20485,20533,
1663 20581,20629,20676,20724,20772,20819,20867,20915,
1664 20962,21010,21057,21105,21153,21200,21248,21295,
1665 21343,21390,21438,21485,21533,21580,21628,21675,
1666 21723,21770,21817,21865,21912,21960,22007,22054,
1667 22102,22149,22196,22243,22291,22338,22385,22432,
1668 22480,22527,22574,22621,22668,22716,22763,22810,
1669 22857,22904,22951,22998,23045,23092,23139,23186,
1670 23233,23280,23327,23374,23421,23468,23515,23562,
1671 23609,23656,23703,23750,23796,23843,23890,23937,
1672 23984,24030,24077,24124,24171,24217,24264,24311,
1673 24357,24404,24451,24497,24544,24591,24637,24684,
1674 24730,24777,24823,24870,24916,24963,25009,25056,
1675 25102,25149,25195,25241,25288,25334,25381,25427,
1676 25473,25520,25566,25612,25658,25705,25751,25797,
1677 25843,25889,25936,25982,26028,26074,26120,26166,
1678 26212,26258,26304,26350,26396,26442,26488,26534,
1679 26580,26626,26672,26718,26764,26810,26856,26902,
1680 26947,26993,27039,27085,27131,27176,27222,27268,
1681 27313,27359,27405,27450,27496,27542,27587,27633,
1682 27678,27724,27770,27815,27861,27906,27952,27997,
1683 28042,28088,28133,28179,28224,28269,28315,28360,
1684 28405,28451,28496,28541,28586,28632,28677,28722,
1685 28767,28812,28858,28903,28948,28993,29038,29083,
1686 29128,29173,29218,29263,29308,29353,29398,29443,
1687 29488,29533,29577,29622,29667,29712,29757,29801,
1688 29846,29891,29936,29980,30025,30070,30114,30159,
1689 30204,30248,30293,30337,30382,30427,30471,30516,
1690 30560,30604,30649,30693,30738,30782,30826,30871,
1691 30915,30959,31004,31048,31092,31136,31181,31225,
1692 31269,31313,31357,31402,31446,31490,31534,31578,
1693 31622,31666,31710,31754,31798,31842,31886,31930,
1694 31974,32017,32061,32105,32149,32193,32236,32280,
1695 32324,32368,32411,32455,32499,32542,32586,32630,
1696 32673,32717,32760,32804,32847,32891,32934,32978,
1697 33021,33065,33108,33151,33195,33238,33281,33325,
1698 33368,33411,33454,33498,33541,33584,33627,33670,
1699 33713,33756,33799,33843,33886,33929,33972,34015,
1700 34057,34100,34143,34186,34229,34272,34315,34358,
1701 34400,34443,34486,34529,34571,34614,34657,34699,
1702 34742,34785,34827,34870,34912,34955,34997,35040,
1703 35082,35125,35167,35210,35252,35294,35337,35379,
1704 35421,35464,35506,35548,35590,35633,35675,35717,
1705 35759,35801,35843,35885,35927,35969,36011,36053,
1706 36095,36137,36179,36221,36263,36305,36347,36388,
1707 36430,36472,36514,36556,36597,36639,36681,36722,
1708 36764,36805,36847,36889,36930,36972,37013,37055,
1709 37096,37137,37179,37220,37262,37303,37344,37386,
1710 37427,37468,37509,37551,37592,37633,37674,37715,
1711 37756,37797,37838,37879,37920,37961,38002,38043,
1712 38084,38125,38166,38207,38248,38288,38329,38370,
1713 38411,38451,38492,38533,38573,38614,38655,38695,
1714 38736,38776,38817,38857,38898,38938,38979,39019,
1715 39059,39100,39140,39180,39221,39261,39301,39341,
1716 39382,39422,39462,39502,39542,39582,39622,39662,
1717 39702,39742,39782,39822,39862,39902,39942,39982,
1718 40021,40061,40101,40141,40180,40220,40260,40299,
1719 40339,40379,40418,40458,40497,40537,40576,40616,
1720 40655,40695,40734,40773,40813,40852,40891,40931,
1721 40970,41009,41048,41087,41127,41166,41205,41244,
1722 41283,41322,41361,41400,41439,41478,41517,41556,
1723 41595,41633,41672,41711,41750,41788,41827,41866,
1724 41904,41943,41982,42020,42059,42097,42136,42174,
1725 42213,42251,42290,42328,42366,42405,42443,42481,
1726 42520,42558,42596,42634,42672,42711,42749,42787,
1727 42825,42863,42901,42939,42977,43015,43053,43091,
1728 43128,43166,43204,43242,43280,43317,43355,43393,
1729 43430,43468,43506,43543,43581,43618,43656,43693,
1730 43731,43768,43806,43843,43880,43918,43955,43992,
1731 44029,44067,44104,44141,44178,44215,44252,44289,
1732 44326,44363,44400,44437,44474,44511,44548,44585,
1733 44622,44659,44695,44732,44769,44806,44842,44879,
1734 44915,44952,44989,45025,45062,45098,45135,45171,
1735 45207,45244,45280,45316,45353,45389,45425,45462,
1736 45498,45534,45570,45606,45642,45678,45714,45750,
1737 45786,45822,45858,45894,45930,45966,46002,46037,
1738 46073,46109,46145,46180,46216,46252,46287,46323,
1739 46358,46394,46429,46465,46500,46536,46571,46606,
1740 46642,46677,46712,46747,46783,46818,46853,46888,
1741 46923,46958,46993,47028,47063,47098,47133,47168,
1742 47203,47238,47273,47308,47342,47377,47412,47446,
1743 47481,47516,47550,47585,47619,47654,47688,47723,
1744 47757,47792,47826,47861,47895,47929,47963,47998,
1745 48032,48066,48100,48134,48168,48202,48237,48271,
1746 48305,48338,48372,48406,48440,48474,48508,48542,
1747 48575,48609,48643,48676,48710,48744,48777,48811,
1748 48844,48878,48911,48945,48978,49012,49045,49078,
1749 49112,49145,49178,49211,49244,49278,49311,49344,
1750 49377,49410,49443,49476,49509,49542,49575,49608,
1751 49640,49673,49706,49739,49771,49804,49837,49869,
1752 49902,49935,49967,50000,50032,50064,50097,50129,
1753 50162,50194,50226,50259,50291,50323,50355,50387,
1754 50420,50452,50484,50516,50548,50580,50612,50644,
1755 50675,50707,50739,50771,50803,50834,50866,50898,
1756 50929,50961,50993,51024,51056,51087,51119,51150,
1757 51182,51213,51244,51276,51307,51338,51369,51401,
1758 51432,51463,51494,51525,51556,51587,51618,51649,
1759 51680,51711,51742,51773,51803,51834,51865,51896,
1760 51926,51957,51988,52018,52049,52079,52110,52140,
1761 52171,52201,52231,52262,52292,52322,52353,52383,
1762 52413,52443,52473,52503,52534,52564,52594,52624,
1763 52653,52683,52713,52743,52773,52803,52832,52862,
1764 52892,52922,52951,52981,53010,53040,53069,53099,
1765 53128,53158,53187,53216,53246,53275,53304,53334,
1766 53363,53392,53421,53450,53479,53508,53537,53566,
1767 53595,53624,53653,53682,53711,53739,53768,53797,
1768 53826,53854,53883,53912,53940,53969,53997,54026,
1769 54054,54082,54111,54139,54167,54196,54224,54252,
1770 54280,54309,54337,54365,54393,54421,54449,54477,
1771 54505,54533,54560,54588,54616,54644,54672,54699,
1772 54727,54755,54782,54810,54837,54865,54892,54920,
1773 54947,54974,55002,55029,55056,55084,55111,55138,
1774 55165,55192,55219,55246,55274,55300,55327,55354,
1775 55381,55408,55435,55462,55489,55515,55542,55569,
1776 55595,55622,55648,55675,55701,55728,55754,55781,
1777 55807,55833,55860,55886,55912,55938,55965,55991,
1778 56017,56043,56069,56095,56121,56147,56173,56199,
1779 56225,56250,56276,56302,56328,56353,56379,56404,
1780 56430,56456,56481,56507,56532,56557,56583,56608,
1781 56633,56659,56684,56709,56734,56760,56785,56810,
1782 56835,56860,56885,56910,56935,56959,56984,57009,
1783 57034,57059,57083,57108,57133,57157,57182,57206,
1784 57231,57255,57280,57304,57329,57353,57377,57402,
1785 57426,57450,57474,57498,57522,57546,57570,57594,
1786 57618,57642,57666,57690,57714,57738,57762,57785,
1787 57809,57833,57856,57880,57903,57927,57950,57974,
1788 57997,58021,58044,58067,58091,58114,58137,58160,
1789 58183,58207,58230,58253,58276,58299,58322,58345,
1790 58367,58390,58413,58436,58459,58481,58504,58527,
1791 58549,58572,58594,58617,58639,58662,58684,58706,
1792 58729,58751,58773,58795,58818,58840,58862,58884,
1793 58906,58928,58950,58972,58994,59016,59038,59059,
1794 59081,59103,59125,59146,59168,59190,59211,59233,
1795 59254,59276,59297,59318,59340,59361,59382,59404,
1796 59425,59446,59467,59488,59509,59530,59551,59572,
1797 59593,59614,59635,59656,59677,59697,59718,59739,
1798 59759,59780,59801,59821,59842,59862,59883,59903,
1799 59923,59944,59964,59984,60004,60025,60045,60065,
1800 60085,60105,60125,60145,60165,60185,60205,60225,
1801 60244,60264,60284,60304,60323,60343,60363,60382,
1802 60402,60421,60441,60460,60479,60499,60518,60537,
1803 60556,60576,60595,60614,60633,60652,60671,60690,
1804 60709,60728,60747,60766,60785,60803,60822,60841,
1805 60859,60878,60897,60915,60934,60952,60971,60989,
1806 61007,61026,61044,61062,61081,61099,61117,61135,
1807 61153,61171,61189,61207,61225,61243,61261,61279,
1808 61297,61314,61332,61350,61367,61385,61403,61420,
1809 61438,61455,61473,61490,61507,61525,61542,61559,
1810 61577,61594,61611,61628,61645,61662,61679,61696,
1811 61713,61730,61747,61764,61780,61797,61814,61831,
1812 61847,61864,61880,61897,61913,61930,61946,61963,
1813 61979,61995,62012,62028,62044,62060,62076,62092,
1814 62108,62125,62141,62156,62172,62188,62204,62220,
1815 62236,62251,62267,62283,62298,62314,62329,62345,
1816 62360,62376,62391,62407,62422,62437,62453,62468,
1817 62483,62498,62513,62528,62543,62558,62573,62588,
1818 62603,62618,62633,62648,62662,62677,62692,62706,
1819 62721,62735,62750,62764,62779,62793,62808,62822,
1820 62836,62850,62865,62879,62893,62907,62921,62935,
1821 62949,62963,62977,62991,63005,63019,63032,63046,
1822 63060,63074,63087,63101,63114,63128,63141,63155,
1823 63168,63182,63195,63208,63221,63235,63248,63261,
1824 63274,63287,63300,63313,63326,63339,63352,63365,
1825 63378,63390,63403,63416,63429,63441,63454,63466,
1826 63479,63491,63504,63516,63528,63541,63553,63565,
1827 63578,63590,63602,63614,63626,63638,63650,63662,
1828 63674,63686,63698,63709,63721,63733,63745,63756,
1829 63768,63779,63791,63803,63814,63825,63837,63848,
1830 63859,63871,63882,63893,63904,63915,63927,63938,
1831 63949,63960,63971,63981,63992,64003,64014,64025,
1832 64035,64046,64057,64067,64078,64088,64099,64109,
1833 64120,64130,64140,64151,64161,64171,64181,64192,
1834 64202,64212,64222,64232,64242,64252,64261,64271,
1835 64281,64291,64301,64310,64320,64330,64339,64349,
1836 64358,64368,64377,64387,64396,64405,64414,64424,
1837 64433,64442,64451,64460,64469,64478,64487,64496,
1838 64505,64514,64523,64532,64540,64549,64558,64566,
1839 64575,64584,64592,64600,64609,64617,64626,64634,
1840 64642,64651,64659,64667,64675,64683,64691,64699,
1841 64707,64715,64723,64731,64739,64747,64754,64762,
1842 64770,64777,64785,64793,64800,64808,64815,64822,
1843 64830,64837,64844,64852,64859,64866,64873,64880,
1844 64887,64895,64902,64908,64915,64922,64929,64936,
1845 64943,64949,64956,64963,64969,64976,64982,64989,
1846 64995,65002,65008,65015,65021,65027,65033,65040,
1847 65046,65052,65058,65064,65070,65076,65082,65088,
1848 65094,65099,65105,65111,65117,65122,65128,65133,
1849 65139,65144,65150,65155,65161,65166,65171,65177,
1850 65182,65187,65192,65197,65202,65207,65212,65217,
1851 65222,65227,65232,65237,65242,65246,65251,65256,
1852 65260,65265,65270,65274,65279,65283,65287,65292,
1853 65296,65300,65305,65309,65313,65317,65321,65325,
1854 65329,65333,65337,65341,65345,65349,65352,65356,
1855 65360,65363,65367,65371,65374,65378,65381,65385,
1856 65388,65391,65395,65398,65401,65404,65408,65411,
1857 65414,65417,65420,65423,65426,65429,65431,65434,
1858 65437,65440,65442,65445,65448,65450,65453,65455,
1859 65458,65460,65463,65465,65467,65470,65472,65474,
1860 65476,65478,65480,65482,65484,65486,65488,65490,
1861 65492,65494,65496,65497,65499,65501,65502,65504,
1862 65505,65507,65508,65510,65511,65513,65514,65515,
1863 65516,65518,65519,65520,65521,65522,65523,65524,
1864 65525,65526,65527,65527,65528,65529,65530,65530,
1865 65531,65531,65532,65532,65533,65533,65534,65534,
1866 65534,65535,65535,65535,65535,65535,65535,65535
1867 };
1868#endif
1869
1870#ifdef TABLES_AS_LUMPS
1871angle_t *tantoangle;
1872#else
1873const angle_t tantoangle[2049] = {
1874 0,333772,667544,1001315,1335086,1668857,2002626,2336395,
1875 2670163,3003929,3337694,3671457,4005219,4338979,4672736,5006492,
1876 5340245,5673995,6007743,6341488,6675230,7008968,7342704,7676435,
1877 8010164,8343888,8677609,9011325,9345037,9678744,10012447,10346145,
1878 10679838,11013526,11347209,11680887,12014558,12348225,12681885,13015539,
1879 13349187,13682829,14016464,14350092,14683714,15017328,15350936,15684536,
1880 16018129,16351714,16685291,17018860,17352422,17685974,18019518,18353054,
1881 18686582,19020100,19353610,19687110,20020600,20354080,20687552,21021014,
1882 21354466,21687906,22021338,22354758,22688168,23021568,23354956,23688332,
1883 24021698,24355052,24688396,25021726,25355046,25688352,26021648,26354930,
1884 26688200,27021456,27354702,27687932,28021150,28354356,28687548,29020724,
1885 29353888,29687038,30020174,30353296,30686404,31019496,31352574,31685636,
1886 32018684,32351718,32684734,33017736,33350722,33683692,34016648,34349584,
1887 34682508,35015412,35348300,35681172,36014028,36346868,36679688,37012492,
1888 37345276,37678044,38010792,38343524,38676240,39008936,39341612,39674272,
1889 40006912,40339532,40672132,41004716,41337276,41669820,42002344,42334848,
1890 42667332,42999796,43332236,43664660,43997060,44329444,44661800,44994140,
1891 45326456,45658752,45991028,46323280,46655512,46987720,47319908,47652072,
1892 47984212,48316332,48648428,48980500,49312548,49644576,49976580,50308556,
1893 50640512,50972444,51304352,51636236,51968096,52299928,52631740,52963524,
1894 53295284,53627020,53958728,54290412,54622068,54953704,55285308,55616888,
1895 55948444,56279972,56611472,56942948,57274396,57605816,57937212,58268576,
1896 58599916,58931228,59262512,59593768,59924992,60256192,60587364,60918508,
1897 61249620,61580704,61911760,62242788,62573788,62904756,63235692,63566604,
1898 63897480,64228332,64559148,64889940,65220696,65551424,65882120,66212788,
1899 66543420,66874024,67204600,67535136,67865648,68196120,68526568,68856984,
1900 69187360,69517712,69848024,70178304,70508560,70838776,71168960,71499112,
1901 71829224,72159312,72489360,72819376,73149360,73479304,73809216,74139096,
1902 74468936,74798744,75128520,75458264,75787968,76117632,76447264,76776864,
1903 77106424,77435952,77765440,78094888,78424304,78753688,79083032,79412336,
1904 79741608,80070840,80400032,80729192,81058312,81387392,81716432,82045440,
1905 82374408,82703336,83032224,83361080,83689896,84018664,84347400,84676096,
1906 85004760,85333376,85661952,85990488,86318984,86647448,86975864,87304240,
1907 87632576,87960872,88289128,88617344,88945520,89273648,89601736,89929792,
1908 90257792,90585760,90913688,91241568,91569408,91897200,92224960,92552672,
1909 92880336,93207968,93535552,93863088,94190584,94518040,94845448,95172816,
1910 95500136,95827416,96154648,96481832,96808976,97136080,97463136,97790144,
1911 98117112,98444032,98770904,99097736,99424520,99751256,100077944,100404592,
1912 100731192,101057744,101384248,101710712,102037128,102363488,102689808,103016080,
1913 103342312,103668488,103994616,104320696,104646736,104972720,105298656,105624552,
1914 105950392,106276184,106601928,106927624,107253272,107578872,107904416,108229920,
1915 108555368,108880768,109206120,109531416,109856664,110181872,110507016,110832120,
1916 111157168,111482168,111807112,112132008,112456856,112781648,113106392,113431080,
1917 113755720,114080312,114404848,114729328,115053760,115378136,115702464,116026744,
1918 116350960,116675128,116999248,117323312,117647320,117971272,118295176,118619024,
1919 118942816,119266560,119590248,119913880,120237456,120560984,120884456,121207864,
1920 121531224,121854528,122177784,122500976,122824112,123147200,123470224,123793200,
1921 124116120,124438976,124761784,125084528,125407224,125729856,126052432,126374960,
1922 126697424,127019832,127342184,127664472,127986712,128308888,128631008,128953072,
1923 129275080,129597024,129918912,130240744,130562520,130884232,131205888,131527480,
1924 131849016,132170496,132491912,132813272,133134576,133455816,133776992,134098120,
1925 134419184,134740176,135061120,135382000,135702816,136023584,136344272,136664912,
1926 136985488,137306016,137626464,137946864,138267184,138587456,138907664,139227808,
1927 139547904,139867920,140187888,140507776,140827616,141147392,141467104,141786752,
1928 142106336,142425856,142745312,143064720,143384048,143703312,144022512,144341664,
1929 144660736,144979744,145298704,145617584,145936400,146255168,146573856,146892480,
1930 147211040,147529536,147847968,148166336,148484640,148802880,149121056,149439152,
1931 149757200,150075168,150393072,150710912,151028688,151346400,151664048,151981616,
1932 152299136,152616576,152933952,153251264,153568496,153885680,154202784,154519824,
1933 154836784,155153696,155470528,155787296,156104000,156420624,156737200,157053696,
1934 157370112,157686480,158002768,158318976,158635136,158951216,159267232,159583168,
1935 159899040,160214848,160530592,160846256,161161840,161477376,161792832,162108208,
1936 162423520,162738768,163053952,163369040,163684080,163999040,164313936,164628752,
1937 164943504,165258176,165572784,165887312,166201776,166516160,166830480,167144736,
1938 167458912,167773008,168087040,168400992,168714880,169028688,169342432,169656096,
1939 169969696,170283216,170596672,170910032,171223344,171536576,171849728,172162800,
1940 172475808,172788736,173101600,173414384,173727104,174039728,174352288,174664784,
1941 174977200,175289536,175601792,175913984,176226096,176538144,176850096,177161984,
1942 177473792,177785536,178097200,178408784,178720288,179031728,179343088,179654368,
1943 179965568,180276704,180587744,180898720,181209616,181520448,181831184,182141856,
1944 182452448,182762960,183073408,183383760,183694048,184004240,184314368,184624416,
1945 184934400,185244288,185554096,185863840,186173504,186483072,186792576,187102000,
1946 187411344,187720608,188029808,188338912,188647936,188956896,189265760,189574560,
1947 189883264,190191904,190500448,190808928,191117312,191425632,191733872,192042016,
1948 192350096,192658096,192966000,193273840,193581584,193889264,194196848,194504352,
1949 194811792,195119136,195426400,195733584,196040688,196347712,196654656,196961520,
1950 197268304,197574992,197881616,198188144,198494592,198800960,199107248,199413456,
1951 199719584,200025616,200331584,200637456,200943248,201248960,201554576,201860128,
1952 202165584,202470960,202776256,203081456,203386592,203691632,203996592,204301472,
1953 204606256,204910976,205215600,205520144,205824592,206128960,206433248,206737456,
1954 207041584,207345616,207649568,207953424,208257216,208560912,208864512,209168048,
1955 209471488,209774832,210078112,210381296,210684384,210987408,211290336,211593184,
1956 211895936,212198608,212501184,212803680,213106096,213408432,213710672,214012816,
1957 214314880,214616864,214918768,215220576,215522288,215823920,216125472,216426928,
1958 216728304,217029584,217330784,217631904,217932928,218233856,218534704,218835472,
1959 219136144,219436720,219737216,220037632,220337952,220638192,220938336,221238384,
1960 221538352,221838240,222138032,222437728,222737344,223036880,223336304,223635664,
1961 223934912,224234096,224533168,224832160,225131072,225429872,225728608,226027232,
1962 226325776,226624240,226922608,227220880,227519056,227817152,228115168,228413088,
1963 228710912,229008640,229306288,229603840,229901312,230198688,230495968,230793152,
1964 231090256,231387280,231684192,231981024,232277760,232574416,232870960,233167440,
1965 233463808,233760096,234056288,234352384,234648384,234944304,235240128,235535872,
1966 235831504,236127056,236422512,236717888,237013152,237308336,237603424,237898416,
1967 238193328,238488144,238782864,239077488,239372016,239666464,239960816,240255072,
1968 240549232,240843312,241137280,241431168,241724960,242018656,242312256,242605776,
1969 242899200,243192512,243485744,243778896,244071936,244364880,244657744,244950496,
1970 245243168,245535744,245828224,246120608,246412912,246705104,246997216,247289216,
1971 247581136,247872960,248164688,248456320,248747856,249039296,249330640,249621904,
1972 249913056,250204128,250495088,250785968,251076736,251367424,251658016,251948512,
1973 252238912,252529200,252819408,253109520,253399536,253689456,253979280,254269008,
1974 254558640,254848176,255137632,255426976,255716224,256005376,256294432,256583392,
1975 256872256,257161024,257449696,257738272,258026752,258315136,258603424,258891600,
1976 259179696,259467696,259755600,260043392,260331104,260618704,260906224,261193632,
1977 261480960,261768176,262055296,262342320,262629248,262916080,263202816,263489456,
1978 263776000,264062432,264348784,264635024,264921168,265207216,265493168,265779024,
1979 266064784,266350448,266636000,266921472,267206832,267492096,267777264,268062336,
1980 268347312,268632192,268916960,269201632,269486208,269770688,270055072,270339360,
1981 270623552,270907616,271191616,271475488,271759296,272042976,272326560,272610048,
1982 272893440,273176736,273459936,273743040,274026048,274308928,274591744,274874432,
1983 275157024,275439520,275721920,276004224,276286432,276568512,276850528,277132416,
1984 277414240,277695936,277977536,278259040,278540448,278821728,279102944,279384032,
1985 279665056,279945952,280226752,280507456,280788064,281068544,281348960,281629248,
1986 281909472,282189568,282469568,282749440,283029248,283308960,283588544,283868032,
1987 284147424,284426720,284705920,284985024,285264000,285542912,285821696,286100384,
1988 286378976,286657440,286935840,287214112,287492320,287770400,288048384,288326240,
1989 288604032,288881696,289159264,289436768,289714112,289991392,290268576,290545632,
1990 290822592,291099456,291376224,291652896,291929440,292205888,292482272,292758528,
1991 293034656,293310720,293586656,293862496,294138240,294413888,294689440,294964864,
1992 295240192,295515424,295790560,296065600,296340512,296615360,296890080,297164704,
1993 297439200,297713632,297987936,298262144,298536256,298810240,299084160,299357952,
1994 299631648,299905248,300178720,300452128,300725408,300998592,301271680,301544640,
1995 301817536,302090304,302362976,302635520,302908000,303180352,303452608,303724768,
1996 303996800,304268768,304540608,304812320,305083968,305355520,305626944,305898272,
1997 306169472,306440608,306711616,306982528,307253344,307524064,307794656,308065152,
1998 308335552,308605856,308876032,309146112,309416096,309685984,309955744,310225408,
1999 310494976,310764448,311033824,311303072,311572224,311841280,312110208,312379040,
2000 312647776,312916416,313184960,313453376,313721696,313989920,314258016,314526016,
2001 314793920,315061728,315329408,315597024,315864512,316131872,316399168,316666336,
2002 316933408,317200384,317467232,317733984,318000640,318267200,318533632,318799968,
2003 319066208,319332352,319598368,319864288,320130112,320395808,320661408,320926912,
2004 321192320,321457632,321722816,321987904,322252864,322517760,322782528,323047200,
2005 323311744,323576192,323840544,324104800,324368928,324632992,324896928,325160736,
2006 325424448,325688096,325951584,326215008,326478304,326741504,327004608,327267584,
2007 327530464,327793248,328055904,328318496,328580960,328843296,329105568,329367712,
2008 329629760,329891680,330153536,330415264,330676864,330938400,331199808,331461120,
2009 331722304,331983392,332244384,332505280,332766048,333026752,333287296,333547776,
2010 333808128,334068384,334328544,334588576,334848512,335108352,335368064,335627712,
2011 335887200,336146624,336405920,336665120,336924224,337183200,337442112,337700864,
2012 337959552,338218112,338476576,338734944,338993184,339251328,339509376,339767296,
2013 340025120,340282848,340540480,340797984,341055392,341312704,341569888,341826976,
2014 342083968,342340832,342597600,342854272,343110848,343367296,343623648,343879904,
2015 344136032,344392064,344648000,344903808,345159520,345415136,345670656,345926048,
2016 346181344,346436512,346691616,346946592,347201440,347456224,347710880,347965440,
2017 348219872,348474208,348728448,348982592,349236608,349490528,349744320,349998048,
2018 350251648,350505152,350758528,351011808,351264992,351518048,351771040,352023872,
2019 352276640,352529280,352781824,353034272,353286592,353538816,353790944,354042944,
2020 354294880,354546656,354798368,355049952,355301440,355552800,355804096,356055264,
2021 356306304,356557280,356808128,357058848,357309504,357560032,357810464,358060768,
2022 358311008,358561088,358811104,359060992,359310784,359560480,359810048,360059520,
2023 360308896,360558144,360807296,361056352,361305312,361554144,361802880,362051488,
2024 362300032,362548448,362796736,363044960,363293056,363541024,363788928,364036704,
2025 364284384,364531936,364779392,365026752,365274016,365521152,365768192,366015136,
2026 366261952,366508672,366755296,367001792,367248192,367494496,367740704,367986784,
2027 368232768,368478656,368724416,368970080,369215648,369461088,369706432,369951680,
2028 370196800,370441824,370686752,370931584,371176288,371420896,371665408,371909792,
2029 372154080,372398272,372642336,372886304,373130176,373373952,373617600,373861152,
2030 374104608,374347936,374591168,374834304,375077312,375320224,375563040,375805760,
2031 376048352,376290848,376533248,376775520,377017696,377259776,377501728,377743584,
2032 377985344,378227008,378468544,378709984,378951328,379192544,379433664,379674688,
2033 379915584,380156416,380397088,380637696,380878176,381118560,381358848,381599040,
2034 381839104,382079072,382318912,382558656,382798304,383037856,383277280,383516640,
2035 383755840,383994976,384233984,384472896,384711712,384950400,385188992,385427488,
2036 385665888,385904160,386142336,386380384,386618368,386856224,387093984,387331616,
2037 387569152,387806592,388043936,388281152,388518272,388755296,388992224,389229024,
2038 389465728,389702336,389938816,390175200,390411488,390647680,390883744,391119712,
2039 391355584,391591328,391826976,392062528,392297984,392533312,392768544,393003680,
2040 393238720,393473632,393708448,393943168,394177760,394412256,394646656,394880960,
2041 395115136,395349216,395583200,395817088,396050848,396284512,396518080,396751520,
2042 396984864,397218112,397451264,397684288,397917248,398150080,398382784,398615424,
2043 398847936,399080320,399312640,399544832,399776928,400008928,400240832,400472608,
2044 400704288,400935872,401167328,401398720,401629984,401861120,402092192,402323136,
2045 402553984,402784736,403015360,403245888,403476320,403706656,403936896,404167008,
2046 404397024,404626944,404856736,405086432,405316032,405545536,405774912,406004224,
2047 406233408,406462464,406691456,406920320,407149088,407377760,407606336,407834784,
2048 408063136,408291392,408519520,408747584,408975520,409203360,409431072,409658720,
2049 409886240,410113664,410340992,410568192,410795296,411022304,411249216,411476032,
2050 411702720,411929312,412155808,412382176,412608480,412834656,413060736,413286720,
2051 413512576,413738336,413964000,414189568,414415040,414640384,414865632,415090784,
2052 415315840,415540800,415765632,415990368,416215008,416439552,416663968,416888288,
2053 417112512,417336640,417560672,417784576,418008384,418232096,418455712,418679200,
2054 418902624,419125920,419349120,419572192,419795200,420018080,420240864,420463552,
2055 420686144,420908608,421130976,421353280,421575424,421797504,422019488,422241344,
2056 422463104,422684768,422906336,423127776,423349120,423570400,423791520,424012576,
2057 424233536,424454368,424675104,424895744,425116288,425336736,425557056,425777280,
2058 425997408,426217440,426437376,426657184,426876928,427096544,427316064,427535488,
2059 427754784,427974016,428193120,428412128,428631040,428849856,429068544,429287168,
2060 429505664,429724064,429942368,430160576,430378656,430596672,430814560,431032352,
2061 431250048,431467616,431685120,431902496,432119808,432336992,432554080,432771040,
2062 432987936,433204736,433421408,433637984,433854464,434070848,434287104,434503296,
2063 434719360,434935360,435151232,435367008,435582656,435798240,436013696,436229088,
2064 436444352,436659520,436874592,437089568,437304416,437519200,437733856,437948416,
2065 438162880,438377248,438591520,438805696,439019744,439233728,439447584,439661344,
2066 439875008,440088576,440302048,440515392,440728672,440941824,441154880,441367872,
2067 441580736,441793472,442006144,442218720,442431168,442643552,442855808,443067968,
2068 443280032,443492000,443703872,443915648,444127296,444338880,444550336,444761696,
2069 444972992,445184160,445395232,445606176,445817056,446027840,446238496,446449088,
2070 446659552,446869920,447080192,447290400,447500448,447710432,447920320,448130112,
2071 448339776,448549376,448758848,448968224,449177536,449386720,449595808,449804800,
2072 450013664,450222464,450431168,450639776,450848256,451056640,451264960,451473152,
2073 451681248,451889248,452097152,452304960,452512672,452720288,452927808,453135232,
2074 453342528,453549760,453756864,453963904,454170816,454377632,454584384,454791008,
2075 454997536,455203968,455410304,455616544,455822688,456028704,456234656,456440512,
2076 456646240,456851904,457057472,457262912,457468256,457673536,457878688,458083744,
2077 458288736,458493600,458698368,458903040,459107616,459312096,459516480,459720768,
2078 459924960,460129056,460333056,460536960,460740736,460944448,461148064,461351584,
2079 461554976,461758304,461961536,462164640,462367680,462570592,462773440,462976160,
2080 463178816,463381344,463583776,463786144,463988384,464190560,464392608,464594560,
2081 464796448,464998208,465199872,465401472,465602944,465804320,466005600,466206816,
2082 466407904,466608896,466809824,467010624,467211328,467411936,467612480,467812896,
2083 468013216,468213440,468413600,468613632,468813568,469013440,469213184,469412832,
2084 469612416,469811872,470011232,470210528,470409696,470608800,470807776,471006688,
2085 471205472,471404192,471602784,471801312,471999712,472198048,472396288,472594400,
2086 472792448,472990400,473188256,473385984,473583648,473781216,473978688,474176064,
2087 474373344,474570528,474767616,474964608,475161504,475358336,475555040,475751648,
2088 475948192,476144608,476340928,476537184,476733312,476929376,477125344,477321184,
2089 477516960,477712640,477908224,478103712,478299104,478494400,478689600,478884704,
2090 479079744,479274656,479469504,479664224,479858880,480053408,480247872,480442240,
2091 480636512,480830656,481024736,481218752,481412640,481606432,481800128,481993760,
2092 482187264,482380704,482574016,482767264,482960416,483153472,483346432,483539296,
2093 483732064,483924768,484117344,484309856,484502240,484694560,484886784,485078912,
2094 485270944,485462880,485654720,485846464,486038144,486229696,486421184,486612576,
2095 486803840,486995040,487186176,487377184,487568096,487758912,487949664,488140320,
2096 488330880,488521312,488711712,488901984,489092160,489282240,489472256,489662176,
2097 489851968,490041696,490231328,490420896,490610336,490799712,490988960,491178144,
2098 491367232,491556224,491745120,491933920,492122656,492311264,492499808,492688256,
2099 492876608,493064864,493253056,493441120,493629120,493817024,494004832,494192544,
2100 494380160,494567712,494755136,494942496,495129760,495316928,495504000,495691008,
2101 495877888,496064704,496251424,496438048,496624608,496811040,496997408,497183680,
2102 497369856,497555936,497741920,497927840,498113632,498299360,498484992,498670560,
2103 498856000,499041376,499226656,499411840,499596928,499781920,499966848,500151680,
2104 500336416,500521056,500705600,500890080,501074464,501258752,501442944,501627040,
2105 501811072,501995008,502178848,502362592,502546240,502729824,502913312,503096704,
2106 503280000,503463232,503646368,503829408,504012352,504195200,504377984,504560672,
2107 504743264,504925760,505108192,505290496,505472736,505654912,505836960,506018944,
2108 506200832,506382624,506564320,506745952,506927488,507108928,507290272,507471552,
2109 507652736,507833824,508014816,508195744,508376576,508557312,508737952,508918528,
2110 509099008,509279392,509459680,509639904,509820032,510000064,510180000,510359872,
2111 510539648,510719328,510898944,511078432,511257856,511437216,511616448,511795616,
2112 511974688,512153664,512332576,512511392,512690112,512868768,513047296,513225792,
2113 513404160,513582432,513760640,513938784,514116800,514294752,514472608,514650368,
2114 514828064,515005664,515183168,515360608,515537952,515715200,515892352,516069440,
2115 516246432,516423328,516600160,516776896,516953536,517130112,517306592,517482976,
2116 517659264,517835488,518011616,518187680,518363648,518539520,518715296,518891008,
2117 519066624,519242144,519417600,519592960,519768256,519943424,520118528,520293568,
2118 520468480,520643328,520818112,520992800,521167392,521341888,521516320,521690656,
2119 521864896,522039072,522213152,522387168,522561056,522734912,522908640,523082304,
2120 523255872,523429376,523602784,523776096,523949312,524122464,524295552,524468512,
2121 524641440,524814240,524986976,525159616,525332192,525504640,525677056,525849344,
2122 526021568,526193728,526365792,526537760,526709632,526881440,527053152,527224800,
2123 527396352,527567840,527739200,527910528,528081728,528252864,528423936,528594880,
2124 528765760,528936576,529107296,529277920,529448480,529618944,529789344,529959648,
2125 530129856,530300000,530470048,530640000,530809888,530979712,531149440,531319072,
2126 531488608,531658080,531827488,531996800,532166016,532335168,532504224,532673184,
2127 532842080,533010912,533179616,533348288,533516832,533685312,533853728,534022048,
2128 534190272,534358432,534526496,534694496,534862400,535030240,535197984,535365632,
2129 535533216,535700704,535868128,536035456,536202720,536369888,536536992,536704000,
2130 536870912
2131 };
2132#endif
2133
2134#ifdef TABLES_AS_LUMPS
2135
2136#include "m_swap.h"
2137
2138
2139
2140// R_LoadTrigTables
2141// Load trig tables from a wad file lump
2142// CPhipps 24/12/98 - fix endianness (!)
2143// KKurbjun 3/09/2006 - Modified to reduce initial footprint
2144//
2145void R_LoadTrigTables(void)
2146{
2147 finesine=malloc(10240*sizeof(fixed_t));
2148 finetangent=malloc(4096*sizeof(fixed_t));
2149 tantoangle=malloc(2049*sizeof(angle_t));
2150
2151 finecosine=finesine + FINEANGLES/4;
2152
2153 int lump;
2154 {
2155 lump = W_GetNumForName("SINETABL");
2156 if (W_LumpLength(lump) != 10240*sizeof(fixed_t))
2157 I_Error("R_LoadTrigTables: Invalid SINETABL");
2158 W_ReadLump(lump,(unsigned char*)finesine);
2159 }
2160
2161 {
2162 lump = W_GetNumForName("TANGTABL");
2163 if (W_LumpLength(lump) != 4096*sizeof(fixed_t))
2164 I_Error("R_LoadTrigTables: Invalid TANGTABL");
2165 W_ReadLump(lump,(unsigned char*)finetangent);
2166 }
2167
2168 {
2169 lump = W_GetNumForName("TANTOANG");
2170 if (W_LumpLength(lump) != 2049*sizeof(fixed_t))
2171 I_Error("R_LoadTrigTables: Invalid TANTOANG");
2172 W_ReadLump(lump,(unsigned char*)tantoangle);
2173 }
2174 // Endianness correction - might still be non-portable, but is fast where possible
2175 {
2176 size_t n;
2177 printf("Endianness...");
2178
2179 // This test doesn't assume the endianness of the tables, but deduces them from
2180 // en entry. I hope this is portable.
2181 if ((10 < finesine[1]) && (finesine[1] < 100)) {
2182 printf("ok.");
2183 return; // Endianness is correct
2184 }
2185
2186 // Must correct endianness of every long loaded (!)
2187#define CORRECT_TABLE_ENDIAN(tbl, size) \
2188 for (n = 0; n<size; n++) tbl[n] = doom_swap_l(tbl[n])
2189
2190 CORRECT_TABLE_ENDIAN(finesine, 10240);
2191 CORRECT_TABLE_ENDIAN(finetangent, 4096);
2192 CORRECT_TABLE_ENDIAN(tantoangle, 2049);
2193 printf("corrected.");
2194 }
2195}
2196#endif
diff --git a/apps/plugins/doom/tables.h b/apps/plugins/doom/tables.h
new file mode 100644
index 0000000000..f9ec4381ee
--- /dev/null
+++ b/apps/plugins/doom/tables.h
@@ -0,0 +1,103 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION:
28 * Lookup tables.
29 * Do not try to look them up :-).
30 * In the order of appearance:
31 *
32 * int finetangent[4096] - Tangens LUT.
33 * Should work with BAM fairly well (12 of 16bit,
34 * effectively, by shifting).
35 *
36 * int finesine[10240] - Sine lookup.
37 * Guess what, serves as cosine, too.
38 * Remarkable thing is, how to use BAMs with this?
39 *
40 * int tantoangle[2049] - ArcTan LUT,
41 * maps tan(angle) to angle fast. Gotta search.
42 *
43 *-----------------------------------------------------------------------------*/
44
45#ifndef __TABLES__
46#define __TABLES__
47
48#include "m_fixed.h"
49#include "rockmacros.h"
50
51#define FINEANGLES 8192
52#define FINEMASK (FINEANGLES-1)
53
54// 0x100000000 to 0x2000
55#define ANGLETOFINESHIFT 19
56
57#ifndef ALL_IN_ONE
58
59// TABLES_AS_LUMPS causes the tables to be loaded from a wad lump, and the normal
60// data to be stored as a predefined lump.
61// Only really useful for dumping the trig tables or with NO_PREDEFINED_LUMPS
62#define TABLES_AS_LUMPS
63#endif
64
65// Binary Angle Measument, BAM.
66#define ANG45 0x20000000
67#define ANG90 0x40000000
68#define ANG180 0x80000000
69#define ANG270 0xc0000000
70
71#define SLOPERANGE 2048
72#define SLOPEBITS 11
73#define DBITS (FRACBITS-SLOPEBITS)
74
75typedef unsigned angle_t;
76
77// Load trig tables if needed
78#ifdef TABLES_AS_LUMPS
79void R_LoadTrigTables(void);
80#define TRIG_CONST
81#else
82#define TRIG_CONST const
83#endif
84
85// Effective size is 10240.
86extern TRIG_CONST fixed_t *finesine;
87
88// Re-use data, is just PI/2 phase shift.
89extern TRIG_CONST fixed_t *finecosine;
90
91// Effective size is 4096.
92extern TRIG_CONST fixed_t *finetangent;
93
94// Effective size is 2049;
95// The +1 size is to handle the case when x==y without additional checking.
96
97extern TRIG_CONST angle_t *tantoangle;
98
99// Utility function, called by R_PointToAngle.
100int SlopeDiv(unsigned num, unsigned den);
101
102#undef TRIG_CONST
103#endif
diff --git a/apps/plugins/doom/v_video.c b/apps/plugins/doom/v_video.c
new file mode 100644
index 0000000000..a7dbe84d6a
--- /dev/null
+++ b/apps/plugins/doom/v_video.c
@@ -0,0 +1,700 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION:
28 * Gamma correction LUT stuff.
29 * Color range translation support
30 * Functions to draw patches (by post) directly to screen.
31 * Functions to blit a block to the screen.
32 *
33 *-----------------------------------------------------------------------------
34 */
35
36#include "doomdef.h"
37#include "r_main.h"
38#include "r_draw.h"
39#include "m_bbox.h"
40#include "w_wad.h" /* needed for color translation lump lookup */
41#include "v_video.h"
42#include "i_video.h"
43#include "i_system.h"
44#include "m_swap.h"
45#include "rockmacros.h"
46// Each screen is [SCREENWIDTH*SCREENHEIGHT];
47byte *screens[6];
48int dirtybox[4];
49
50/* jff 4/24/98 initialize this at runtime */
51const byte *colrngs[CR_LIMIT];
52
53// Now where did these came from?
54const byte gammatable[5][256] = // CPhipps - const
55 {
56 {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,
57 17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,
58 33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,
59 49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,
60 65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,
61 81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,
62 97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,
63 113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,
64 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
65 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
66 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,
67 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,
68 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
69 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,
70 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,
71 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255},
72
73 {2,4,5,7,8,10,11,12,14,15,16,18,19,20,21,23,24,25,26,27,29,30,31,
74 32,33,34,36,37,38,39,40,41,42,44,45,46,47,48,49,50,51,52,54,55,
75 56,57,58,59,60,61,62,63,64,65,66,67,69,70,71,72,73,74,75,76,77,
76 78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,
77 99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,
78 115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,129,
79 130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,
80 146,147,148,148,149,150,151,152,153,154,155,156,157,158,159,160,
81 161,162,163,163,164,165,166,167,168,169,170,171,172,173,174,175,
82 175,176,177,178,179,180,181,182,183,184,185,186,186,187,188,189,
83 190,191,192,193,194,195,196,196,197,198,199,200,201,202,203,204,
84 205,205,206,207,208,209,210,211,212,213,214,214,215,216,217,218,
85 219,220,221,222,222,223,224,225,226,227,228,229,230,230,231,232,
86 233,234,235,236,237,237,238,239,240,241,242,243,244,245,245,246,
87 247,248,249,250,251,252,252,253,254,255},
88
89 {4,7,9,11,13,15,17,19,21,22,24,26,27,29,30,32,33,35,36,38,39,40,42,
90 43,45,46,47,48,50,51,52,54,55,56,57,59,60,61,62,63,65,66,67,68,69,
91 70,72,73,74,75,76,77,78,79,80,82,83,84,85,86,87,88,89,90,91,92,93,
92 94,95,96,97,98,100,101,102,103,104,105,106,107,108,109,110,111,112,
93 113,114,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,
94 129,130,131,132,133,133,134,135,136,137,138,139,140,141,142,143,144,
95 144,145,146,147,148,149,150,151,152,153,153,154,155,156,157,158,159,
96 160,160,161,162,163,164,165,166,166,167,168,169,170,171,172,172,173,
97 174,175,176,177,178,178,179,180,181,182,183,183,184,185,186,187,188,
98 188,189,190,191,192,193,193,194,195,196,197,197,198,199,200,201,201,
99 202,203,204,205,206,206,207,208,209,210,210,211,212,213,213,214,215,
100 216,217,217,218,219,220,221,221,222,223,224,224,225,226,227,228,228,
101 229,230,231,231,232,233,234,235,235,236,237,238,238,239,240,241,241,
102 242,243,244,244,245,246,247,247,248,249,250,251,251,252,253,254,254,
103 255},
104
105 {8,12,16,19,22,24,27,29,31,34,36,38,40,41,43,45,47,49,50,52,53,55,
106 57,58,60,61,63,64,65,67,68,70,71,72,74,75,76,77,79,80,81,82,84,85,
107 86,87,88,90,91,92,93,94,95,96,98,99,100,101,102,103,104,105,106,107,
108 108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,
109 125,126,127,128,129,130,131,132,133,134,135,135,136,137,138,139,140,
110 141,142,143,143,144,145,146,147,148,149,150,150,151,152,153,154,155,
111 155,156,157,158,159,160,160,161,162,163,164,165,165,166,167,168,169,
112 169,170,171,172,173,173,174,175,176,176,177,178,179,180,180,181,182,
113 183,183,184,185,186,186,187,188,189,189,190,191,192,192,193,194,195,
114 195,196,197,197,198,199,200,200,201,202,202,203,204,205,205,206,207,
115 207,208,209,210,210,211,212,212,213,214,214,215,216,216,217,218,219,
116 219,220,221,221,222,223,223,224,225,225,226,227,227,228,229,229,230,
117 231,231,232,233,233,234,235,235,236,237,237,238,238,239,240,240,241,
118 242,242,243,244,244,245,246,246,247,247,248,249,249,250,251,251,252,
119 253,253,254,254,255},
120
121 {16,23,28,32,36,39,42,45,48,50,53,55,57,60,62,64,66,68,69,71,73,75,76,
122 78,80,81,83,84,86,87,89,90,92,93,94,96,97,98,100,101,102,103,105,106,
123 107,108,109,110,112,113,114,115,116,117,118,119,120,121,122,123,124,
124 125,126,128,128,129,130,131,132,133,134,135,136,137,138,139,140,141,
125 142,143,143,144,145,146,147,148,149,150,150,151,152,153,154,155,155,
126 156,157,158,159,159,160,161,162,163,163,164,165,166,166,167,168,169,
127 169,170,171,172,172,173,174,175,175,176,177,177,178,179,180,180,181,
128 182,182,183,184,184,185,186,187,187,188,189,189,190,191,191,192,193,
129 193,194,195,195,196,196,197,198,198,199,200,200,201,202,202,203,203,
130 204,205,205,206,207,207,208,208,209,210,210,211,211,212,213,213,214,
131 214,215,216,216,217,217,218,219,219,220,220,221,221,222,223,223,224,
132 224,225,225,226,227,227,228,228,229,229,230,230,231,232,232,233,233,
133 234,234,235,235,236,236,237,237,238,239,239,240,240,241,241,242,242,
134 243,243,244,244,245,245,246,246,247,247,248,248,249,249,250,250,251,
135 251,252,252,253,254,254,255,255}
136 };
137
138int usegamma;
139
140/*
141 * V_InitColorTranslation
142 *
143 * Loads the color translation tables from predefined lumps at game start
144 * No return
145 *
146 * Used for translating text colors from the red palette range
147 * to other colors. The first nine entries can be used to dynamically
148 * switch the output of text color thru the HUlib_drawText routine
149 * by embedding ESCn in the text to obtain color n. Symbols for n are
150 * provided in v_video.h.
151 *
152 * cphipps - constness of crdef_t stuff fixed
153 */
154
155typedef struct {
156 const char *name;
157 const byte **map;
158} crdef_t;
159
160// killough 5/2/98: table-driven approach
161static const crdef_t crdefs[] = {
162 {"CRBRICK", &colrngs[CR_BRICK ]},
163 {"CRTAN", &colrngs[CR_TAN ]},
164 {"CRGRAY", &colrngs[CR_GRAY ]},
165 {"CRGREEN", &colrngs[CR_GREEN ]},
166 {"CRBROWN", &colrngs[CR_BROWN ]},
167 {"CRGOLD", &colrngs[CR_GOLD ]},
168 {"CRRED", &colrngs[CR_RED ]},
169 {"CRBLUE", &colrngs[CR_BLUE ]},
170 {"CRORANGE", &colrngs[CR_ORANGE]},
171 {"CRYELLOW", &colrngs[CR_YELLOW]},
172 {"CRBLUE2", &colrngs[CR_BLUE2]},
173 {NULL, NULL}
174 };
175
176// killough 5/2/98: tiny engine driven by table above
177void V_InitColorTranslation(void)
178{
179 register const crdef_t *p;
180 for (p=crdefs; p->name; p++)
181 *p->map = W_CacheLumpName(p->name);
182}
183
184//
185// V_MarkRect
186//
187// Marks a rectangular portion of the screen specified by
188// upper left origin and height and width dirty to minimize
189// the amount of screen update necessary. No return.
190//
191#ifndef GL_DOOM
192void V_MarkRect(int x, int y, int width, int height)
193{
194 M_AddToBox(dirtybox, x, y);
195 M_AddToBox(dirtybox, x+width-1, y+height-1);
196}
197#endif /* GL_DOOM */
198
199//
200// V_CopyRect
201//
202// Copies a source rectangle in a screen buffer to a destination
203// rectangle in another screen buffer. Source origin in srcx,srcy,
204// destination origin in destx,desty, common size in width and height.
205// Source buffer specfified by srcscrn, destination buffer by destscrn.
206//
207// Marks the destination rectangle on the screen dirty.
208//
209// No return.
210//
211#ifndef GL_DOOM
212void V_CopyRect(int srcx, int srcy, int srcscrn, int width,
213 int height, int destx, int desty, int destscrn,
214 enum patch_translation_e flags)
215{
216 byte *src;
217 byte *dest;
218
219 if (flags & VPT_STRETCH)
220 {
221 srcx=srcx*SCREENWIDTH/320;
222 srcy=srcy*SCREENHEIGHT/200;
223 width=width*SCREENWIDTH/320;
224 height=height*SCREENHEIGHT/200;
225 destx=destx*SCREENWIDTH/320;
226 desty=desty*SCREENHEIGHT/200;
227 }
228
229#ifdef RANGECHECK
230 if (srcx<0
231 ||srcx+width >SCREENWIDTH
232 || srcy<0
233 || srcy+height>SCREENHEIGHT
234 ||destx<0||destx+width >SCREENWIDTH
235 || desty<0
236 || desty+height>SCREENHEIGHT)
237 I_Error ("V_CopyRect: Bad arguments");
238#endif
239
240 V_MarkRect (destx, desty, width, height);
241
242 src = screens[srcscrn]+SCREENWIDTH*srcy+srcx;
243 dest = screens[destscrn]+SCREENWIDTH*desty+destx;
244
245 for ( ; height>0 ; height--)
246 {
247 memcpy (dest, src, width);
248 src += SCREENWIDTH;
249 dest += SCREENWIDTH;
250 }
251}
252#endif /* GL_DOOM */
253
254//
255// V_DrawBlock
256//
257// Draw a linear block of pixels into the view buffer.
258//
259// The bytes at src are copied in linear order to the screen rectangle
260// at x,y in screenbuffer scrn, with size width by height.
261//
262// The destination rectangle is marked dirty.
263//
264// No return.
265//
266// CPhipps - modified to take the patch translation flags. For now, only stretching is
267// implemented, to support highres in the menus
268//
269#ifndef GL_DOOM
270void V_DrawBlock(int x, int y, int scrn, int width, int height,
271 const byte *src, enum patch_translation_e flags)
272{
273 byte *dest;
274
275#ifdef RANGECHECK
276 if (x<0
277 ||x+width >((flags & VPT_STRETCH) ? 320 : SCREENWIDTH)
278 || y<0
279 || y+height>((flags & VPT_STRETCH) ? 200 : SCREENHEIGHT))
280 I_Error ("V_DrawBlock: Bad V_DrawBlock");
281
282 if (flags & (VPT_TRANS | VPT_FLIP))
283 I_Error("V_DrawBlock: Unsupported flags (%u)", flags);
284#endif
285
286 if (flags & VPT_STRETCH) {
287 byte *dest;
288 int s_width;
289 fixed_t dx = (320 << FRACBITS) / SCREENWIDTH;
290
291 x = (x * SCREENWIDTH) / 320; y = (y * SCREENHEIGHT) / 200;
292 s_width = (width * SCREENWIDTH) / 320; height = (height * SCREENHEIGHT) / 200;
293
294 if (!scrn)
295 V_MarkRect (x, y, width, height);
296
297 dest = screens[scrn] + y*SCREENWIDTH+x;
298 // x & y no longer needed
299
300 while (height--) {
301 const byte *const src_row = src + width * ((height * 200) / SCREENHEIGHT);
302 byte *const dst_row = dest + SCREENWIDTH * height;
303 fixed_t tx;
304
305 for (x=0, tx=0; x<s_width; x++, tx+=dx)
306 dst_row[x] = src_row[tx >> FRACBITS];
307 }
308 } else {
309 V_MarkRect (x, y, width, height);
310
311 dest = screens[scrn] + y*SCREENWIDTH+x;
312
313 while (height--) {
314 memcpy (dest, src, width);
315 src += width;
316 dest += SCREENWIDTH;
317 }
318 }
319}
320#endif /* GL_DOOM */
321
322/*
323 * V_DrawBackground tiles a 64x64 patch over the entire screen, providing the
324 * background for the Help and Setup screens, and plot text betwen levels.
325 * cphipps - used to have M_DrawBackground, but that was used the framebuffer
326 * directly, so this is my code from the equivalent function in f_finale.c
327 */
328#ifndef GL_DOOM
329void V_DrawBackground(const char* flatname, int scrn)
330{
331 /* erase the entire screen to a tiled background */
332 const byte *src;
333 int x,y;
334 int lump;
335
336 // killough 4/17/98:
337 src = W_CacheLumpNum(lump = firstflat + R_FlatNumForName(flatname));
338
339 V_DrawBlock(0, 0, scrn, 64, 64, src, 0);
340
341 for (y=0 ; y<SCREENHEIGHT ; y+=64)
342 for (x=y ? 0 : 64; x<SCREENWIDTH ; x+=64)
343 V_CopyRect(0, 0, scrn, ((SCREENWIDTH-x) < 64) ? (SCREENWIDTH-x) : 64,
344 ((SCREENHEIGHT-y) < 64) ? (SCREENHEIGHT-y) : 64, x, y, scrn, VPT_NONE);
345 W_UnlockLumpNum(lump);
346}
347#endif
348
349//
350// V_GetBlock
351//
352// Gets a linear block of pixels from the view buffer.
353//
354// The pixels in the rectangle at x,y in screenbuffer scrn with size
355// width by height are linearly packed into the buffer dest.
356// No return
357//
358
359#ifndef GL_DOOM
360void V_GetBlock(int x, int y, int scrn, int width, int height, byte *dest)
361{
362 byte *src;
363
364#ifdef RANGECHECK
365 if (x<0
366 ||x+width >SCREENWIDTH
367 || y<0
368 || y+height>SCREENHEIGHT)
369 I_Error ("V_GetBlock: Bad arguments");
370#endif
371
372 src = screens[scrn] + y*SCREENWIDTH+x;
373
374 while (height--)
375 {
376 memcpy (dest, src, width);
377 src += SCREENWIDTH;
378 dest += width;
379 }
380}
381#endif /* GL_DOOM */
382
383//
384// V_Init
385//
386// Allocates the 4 full screen buffers in low DOS memory
387// No return
388//
389
390void V_Init (void)
391{
392 int i;
393 // CPhipps - allocate only 2 screens all the time, the rest can be allocated as and when needed
394#define PREALLOCED_SCREENS 2
395
396 // CPhipps - no point in "stick these in low dos memory on PCs" anymore
397 // Allocate the screens individually, so I_InitGraphics can release screens[0]
398 // if e.g. it wants a MitSHM buffer instead
399
400 for (i=0 ; i<PREALLOCED_SCREENS ; i++)
401 screens[i] = calloc(SCREENWIDTH*SCREENHEIGHT, 1);
402 for (; i<4; i++) // Clear the rest (paranoia)
403 screens[i] = NULL;
404}
405
406//
407// V_DrawMemPatch
408//
409// CPhipps - unifying patch drawing routine, handles all cases and combinations
410// of stretching, flipping and translating
411//
412// This function is big, hopefully not too big that gcc can't optimise it well.
413// In fact it packs pretty well, there is no big performance lose for all this merging;
414// the inner loops themselves are just the same as they always were
415// (indeed, laziness of the people who wrote the 'clones' of the original V_DrawPatch
416// means that their inner loops weren't so well optimised, so merging code may even speed them).
417//
418#ifndef GL_DOOM
419void V_DrawMemPatch(int x, int y, int scrn, const patch_t *patch,
420 int cm, enum patch_translation_e flags)
421{
422 const byte *trans;
423
424 if (cm<CR_LIMIT)
425 trans=colrngs[cm];
426 else
427 trans=translationtables + 256*((cm-CR_LIMIT)-1);
428 y -= SHORT(patch->topoffset);
429 x -= SHORT(patch->leftoffset);
430
431 // CPhipps - auto-no-stretch if not high-res
432 if (flags & VPT_STRETCH)
433 if ((SCREENWIDTH==320) && (SCREENHEIGHT==200))
434 flags &= ~VPT_STRETCH;
435
436 // CPhipps - null translation pointer => no translation
437 if (!trans)
438 flags &= ~VPT_TRANS;
439
440 if (x<0
441 ||x+SHORT(patch->width) > ((flags & VPT_STRETCH) ? 320 : SCREENWIDTH)
442 || y<0
443 || y+SHORT(patch->height) > ((flags & VPT_STRETCH) ? 200 : SCREENHEIGHT))
444 // killough 1/19/98: improved error message:
445 I_Error("V_DrawMemPatch: Patch (%d,%d)-(%d,%d) exceeds LFB"
446 "Bad V_DrawMemPatch (flags=%u)", x, y, x+SHORT(patch->width), y+SHORT(patch->height), flags);
447
448 if (!(flags & VPT_STRETCH)) {
449 unsigned int col;
450 const column_t *column;
451 byte *desttop = screens[scrn]+y*SCREENWIDTH+x;
452 unsigned int w = SHORT(patch->width);
453
454 if (!scrn)
455 V_MarkRect (x, y, w, SHORT(patch->height));
456
457 w--; // CPhipps - note: w = width-1 now, speeds up flipping
458
459 for (col=0 ; (unsigned int)col<=w ; desttop++, col++) {
460 column = (column_t *)((byte *)patch +
461 LONG(patch->columnofs[(flags & VPT_FLIP) ? w-col : col]));
462
463 // step through the posts in a column
464 while (column->topdelta != 0xff ) {
465 // killough 2/21/98: Unrolled and performance-tuned
466
467 register const byte *source = (byte *)column + 3;
468 register byte *dest = desttop + column->topdelta*SCREENWIDTH;
469 register int count = column->length;
470
471 if (!(flags & VPT_TRANS)) {
472 if ((count-=4)>=0)
473 do {
474 register byte s0,s1;
475 s0 = source[0];
476 s1 = source[1];
477 dest[0] = s0;
478 dest[SCREENWIDTH] = s1;
479 dest += SCREENWIDTH*2;
480 s0 = source[2];
481 s1 = source[3];
482 source += 4;
483 dest[0] = s0;
484 dest[SCREENWIDTH] = s1;
485 dest += SCREENWIDTH*2;
486 } while ((count-=4)>=0);
487 if (count+=4)
488 do {
489 *dest = *source++;
490 dest += SCREENWIDTH;
491 } while (--count);
492 column = (column_t *)(source+1); //killough 2/21/98 even faster
493 } else {
494 // CPhipps - merged translation code here
495 if ((count-=4)>=0)
496 do {
497 register byte s0,s1;
498 s0 = source[0];
499 s1 = source[1];
500 s0 = trans[s0];
501 s1 = trans[s1];
502 dest[0] = s0;
503 dest[SCREENWIDTH] = s1;
504 dest += SCREENWIDTH*2;
505 s0 = source[2];
506 s1 = source[3];
507 s0 = trans[s0];
508 s1 = trans[s1];
509 source += 4;
510 dest[0] = s0;
511 dest[SCREENWIDTH] = s1;
512 dest += SCREENWIDTH*2;
513 } while ((count-=4)>=0);
514 if (count+=4)
515 do {
516 *dest = trans[*source++];
517 dest += SCREENWIDTH;
518 } while (--count);
519 column = (column_t *)(source+1);
520 }
521 }
522 }
523 }
524 else {
525 // CPhipps - move stretched patch drawing code here
526 // - reformat initialisers, move variables into inner blocks
527
528 byte *desttop;
529 int col;
530 int w = (SHORT( patch->width ) << 16) - 1; // CPhipps - -1 for faster flipping
531 int stretchx, stretchy;
532 int DX = (SCREENWIDTH<<16) / 320;
533 int DXI = (320<<16) / SCREENWIDTH;
534 int DY = (SCREENHEIGHT<<16) / 200;
535 register int DYI = (200<<16) / SCREENHEIGHT;
536 int DY2, DYI2;
537
538 stretchx = ( x * DX ) >> 16;
539 stretchy = ( y * DY ) >> 16;
540 DY2 = DY / 2;
541 DYI2 = DYI* 2;
542
543 if (!scrn)
544 V_MarkRect ( stretchx, stretchy, (SHORT( patch->width ) * DX ) >> 16,
545 (SHORT( patch->height) * DY ) >> 16 );
546
547 desttop = screens[scrn] + stretchy * SCREENWIDTH + stretchx;
548
549 for ( col = 0; col <= w; x++, col+=DXI, desttop++ ) {
550 const column_t *column;
551 {
552 unsigned int d = patch->columnofs[(flags & VPT_FLIP) ? ((w - col)>>16): (col>>16)];
553 column = (column_t*)((byte*)patch + LONG(d));
554 }
555
556 while ( column->topdelta != 0xff ) {
557 register const byte *source = ( byte* ) column + 3;
558 register byte *dest = desttop + (( column->topdelta * DY ) >> 16 ) * SCREENWIDTH;
559 register int count = ( column->length * DY ) >> 16;
560 register int srccol = 0x8000;
561
562 if (flags & VPT_TRANS)
563 while (count--) {
564 *dest = trans[source[srccol>>16]];
565 dest += SCREENWIDTH;
566 srccol+= DYI;
567 }
568 else
569 while (count--) {
570 *dest = source[srccol>>16];
571 dest += SCREENWIDTH;
572 srccol+= DYI;
573 }
574 column = ( column_t* ) (( byte* ) column + ( column->length ) + 4 );
575 }
576 }
577 }
578}
579#endif // GL_DOOM
580
581// CPhipps - some simple, useful wrappers for that function, for drawing patches from wads
582
583// CPhipps - GNU C only suppresses generating a copy of a function if it is
584// static inline; other compilers have different behaviour.
585// This inline is _only_ for the function below
586
587#ifndef GL_DOOM
588#ifdef __GNUC__
589inline
590#endif
591void V_DrawNumPatch(int x, int y, int scrn, int lump,
592 int cm, enum patch_translation_e flags)
593{
594 V_DrawMemPatch(x, y, scrn, (const patch_t*)W_CacheLumpNum(lump),
595 cm, flags);
596 W_UnlockLumpNum(lump);
597}
598#endif // GL_DOOM
599
600/* cph -
601 * V_NamePatchWidth - returns width of a patch.
602 * V_NamePatchHeight- returns height of a patch.
603 *
604 * Doesn't really belong here, but is often used in conjunction with
605 * this code.
606 * This is needed to reduce the number of patches being held locked
607 * in memory, since a lot of code was locking and holding pointers
608 * to graphics in order to get this info easily. Also, we do endian
609 * correction here, which reduces the chance of other code forgetting
610 * this.
611 */
612int V_NamePatchWidth(const char* name)
613{
614 int lump = W_GetNumForName(name);
615 int w;
616
617 w = SHORT(((const patch_t*)W_CacheLumpNum(lump))->width);
618 W_UnlockLumpNum(lump);
619 return w;
620}
621
622int V_NamePatchHeight(const char* name)
623{
624 int lump = W_GetNumForName(name);
625 int w;
626
627 w = SHORT(((const patch_t*)W_CacheLumpNum(lump))->height);
628 W_UnlockLumpNum(lump);
629 return w;
630}
631
632// CPhipps -
633// V_PatchToBlock
634//
635// Returns a simple bitmap which contains the patch. See-through parts of the
636// patch will be undefined (in fact black for now)
637
638#ifndef GL_DOOM
639byte *V_PatchToBlock(const char* name, int cm,
640 enum patch_translation_e flags,
641 unsigned short* width, unsigned short* height)
642{
643 byte *oldscr = screens[1];
644 byte *block;
645 const patch_t *patch;
646
647 screens[1] = calloc(SCREENWIDTH*SCREENHEIGHT, 1);
648
649 patch = W_CacheLumpName(name);
650 V_DrawMemPatch(SHORT(patch->leftoffset), SHORT(patch->topoffset),
651 1, patch, cm, flags);
652
653#ifdef RANGECHECK
654 if (flags & VPT_STRETCH)
655 I_Error("V_PatchToBlock: Stretching not supported");
656#endif
657
658 *width = SHORT(patch->width); *height = SHORT(patch->height);
659
660 W_UnlockLumpName(name);
661
662 V_GetBlock(0, 0, 1, *width, *height,
663 block = malloc((long)(*width) * (*height)));
664
665 free(screens[1]);
666 screens[1] = oldscr;
667 return block;
668}
669#endif /* GL_DOOM */
670
671//
672// V_SetPalette
673//
674// CPhipps - New function to set the palette to palette number pal.
675// Handles loading of PLAYPAL and calls I_SetPalette
676
677void V_SetPalette(int pal)
678{
679#ifndef GL_DOOM
680 I_SetPalette(pal);
681#else
682 // proff 11/99: update the palette
683 gld_SetPalette(pal);
684#endif
685}
686
687//
688// V_FillRect
689//
690// CPhipps - New function to fill a rectangle with a given colour
691#ifndef GL_DOOM
692void V_FillRect(int scrn, int x, int y, int width, int height, byte colour)
693{
694 byte* dest = screens[scrn] + x + y*SCREENWIDTH;
695 while (height--) {
696 memset(dest, colour, width);
697 dest += SCREENWIDTH;
698 }
699}
700#endif
diff --git a/apps/plugins/doom/v_video.h b/apps/plugins/doom/v_video.h
new file mode 100644
index 0000000000..c9926e8997
--- /dev/null
+++ b/apps/plugins/doom/v_video.h
@@ -0,0 +1,185 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION:
28 * Gamma correction LUT.
29 * Color range translation support
30 * Functions to draw patches (by post) directly to screen.
31 * Functions to blit a block to the screen.
32 *
33 *-----------------------------------------------------------------------------*/
34
35#ifndef __V_VIDEO__
36#define __V_VIDEO__
37
38#include "doomtype.h"
39#include "doomdef.h"
40// Needed because we are refering to patches.
41#include "r_data.h"
42
43//
44// VIDEO
45//
46
47#define CENTERY (SCREENHEIGHT/2)
48
49// Screen 0 is the screen updated by I_Update screen.
50// Screen 1 is an extra buffer.
51
52// array of pointers to color translation tables
53extern const byte *colrngs[];
54
55// symbolic indices into color translation table pointer array
56typedef enum
57{
58 CR_BRICK, //0
59 CR_TAN, //1
60 CR_GRAY, //2
61 CR_GREEN, //3
62 CR_BROWN, //4
63 CR_GOLD, //5
64 CR_RED, //6
65 CR_BLUE, //7
66 CR_ORANGE, //8
67 CR_YELLOW, //9
68 CR_BLUE2, //10 // proff
69 CR_LIMIT //11 //jff 2/27/98 added for range check
70} crange_idx_e;
71//jff 1/16/98 end palette color range additions
72
73#define CR_DEFAULT CR_RED /* default value for out of range colors */
74
75extern byte *screens[6];
76extern int dirtybox[4];
77extern const byte gammatable[5][256];
78extern int usegamma;
79
80//jff 4/24/98 loads color translation lumps
81void V_InitColorTranslation(void);
82
83// Allocates buffer screens, call before R_Init.
84void V_Init (void);
85
86enum patch_translation_e {
87 VPT_NONE = 0, // Normal
88 VPT_FLIP = 1, // Flip image horizontally
89 VPT_TRANS = 2, // Translate image via a translation table
90 VPT_STRETCH = 4, // Stretch to compensate for high-res
91};
92
93#ifndef GL_DOOM
94void V_CopyRect(int srcx, int srcy, int srcscrn, int width, int height,
95 int destx, int desty, int destscrn,
96 enum patch_translation_e flags);
97#else
98#define V_CopyRect(sx,sy,ss,w,h,dx,dy,ds,f)
99#endif /* GL_DOOM */
100
101#ifdef GL_DOOM
102#define V_FillRect(s,x,y,w,h,c) gld_FillBlock(x,y,w,h,c)
103#else
104void V_FillRect(int scrn, int x, int y, int width, int height, byte colour);
105#endif
106
107// CPhipps - patch drawing
108// Consolidated into the 3 really useful functions:
109// V_DrawMemPatch - Draws the given patch_t
110#ifdef GL_DOOM
111#define V_DrawMemPatch(x,y,s,p,t,f) gld_DrawPatchFromMem(x,y,p,t,f)
112#else
113void V_DrawMemPatch(int x, int y, int scrn, const patch_t *patch,
114 int cm, enum patch_translation_e flags);
115#endif
116// V_DrawNumPatch - Draws the patch from lump num
117#ifdef GL_DOOM
118#define V_DrawNumPatch(x,y,s,l,t,f) gld_DrawNumPatch(x,y,l,t,f)
119#else
120void V_DrawNumPatch(int x, int y, int scrn, int lump,
121 int cm, enum patch_translation_e flags);
122#endif
123// V_DrawNamePatch - Draws the patch from lump "name"
124#ifdef GL_DOOM
125#define V_DrawNamePatch(x,y,s,n,t,f) gld_DrawNumPatch(x,y,W_GetNumForName(n),t,f)
126#else
127#define V_DrawNamePatch(x,y,s,n,t,f) V_DrawNumPatch(x,y,s,W_GetNumForName(n),t,f)
128#endif
129
130/* cph -
131 * Functions to return width & height of a patch.
132 * Doesn't really belong here, but is often used in conjunction with
133 * this code.
134 */
135int V_NamePatchWidth(const char* name);
136int V_NamePatchHeight(const char* name);
137
138// Draw a linear block of pixels into the view buffer.
139
140// CPhipps - added const's, patch translation flags for stretching
141#ifndef GL_DOOM
142void V_DrawBlock(int x, int y, int scrn, int width, int height,
143 const byte *src, enum patch_translation_e flags);
144#endif
145
146/* cphipps 10/99: function to tile a flat over the screen */
147#ifdef GL_DOOM
148#define V_DrawBackground(n,s) gld_DrawBackground(n)
149#else
150void V_DrawBackground(const char* flatname, int scrn);
151#endif
152
153// Reads a linear block of pixels into the view buffer.
154
155#ifndef GL_DOOM
156void V_GetBlock(int x, int y, int scrn, int width, int height, byte *dest);
157
158void V_MarkRect(int x, int y, int width,int height);
159
160// CPhipps - function to convert a patch_t into a simple block bitmap
161// Returns pointer to the malloc()'ed bitmap, and its width and height
162byte *V_PatchToBlock(const char* name, int cm,
163 enum patch_translation_e flags,
164 unsigned short* width, unsigned short* height);
165#else
166#define V_MarkRect(x,y,w,h)
167#define V_PatchToBlock(n,cm,f,w,h) NULL
168#endif
169
170// CPhipps - function to set the palette to palette number pal.
171void V_SetPalette(int pal);
172
173// CPhipps - function to plot a pixel
174
175#ifndef GL_DOOM
176#define V_PlotPixel(s,x,y,c) screens[s][x+SCREENWIDTH*y]=c
177#endif
178
179#define V_AllocScreen(scrn) screens[scrn] = malloc(SCREENWIDTH*SCREENHEIGHT)
180#define V_FreeScreen(scrn) free(screens[scrn]); screens[scrn] = NULL
181
182#ifdef GL_DOOM
183#include "gl_struct.h"
184#endif
185#endif
diff --git a/apps/plugins/doom/w_wad.c b/apps/plugins/doom/w_wad.c
new file mode 100644
index 0000000000..4bd3807191
--- /dev/null
+++ b/apps/plugins/doom/w_wad.c
@@ -0,0 +1,683 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION:
28 * Handles WAD file header, directory, lump I/O.
29 *
30 *-----------------------------------------------------------------------------
31 */
32
33#include "doomstat.h"
34#include "doomtype.h"
35
36#ifdef __GNUG__
37#pragma implementation "w_wad.h"
38#endif
39#include "w_wad.h"
40#include "m_swap.h"
41#include "i_system.h"
42
43#include "rockmacros.h"
44//
45// GLOBALS
46//
47
48// Location of each lump on disk.
49lumpinfo_t *lumpinfo IBSS_ATTR;
50int numlumps IBSS_ATTR; // killough
51void **lumpcache IBSS_ATTR; // killough
52#ifdef TIMEDIAG
53static int *locktic; // cph
54
55static void W_ReportLocks(void)
56{
57 int i;
58 lprintf(LO_DEBUG, "W_ReportLocks:\nLump Size Locks Tics\n");
59 for (i=0; i<numlumps; i++) {
60 if (lumpinfo[i].locks)
61 printf("%8.8s %6u %2d %6d\n", lumpinfo[i].name,
62 W_LumpLength(i), lumpinfo[i].locks, gametic - locktic[i]);
63 }
64}
65#endif
66
67#ifdef HEAPDUMP
68void W_PrintLump(FILE* fp, void* p) {
69 int i;
70 for (i=0; i<numlumps; i++)
71 if (lumpcache[i] == p) {
72 fdprintf(fp, " %8.8s %6u %2d %6d", lumpinfo[i].name,
73 W_LumpLength(i), lumpinfo[i].locks, gametic - locktic[i]);
74 return;
75 }
76 fprintf(fp, " not found");
77}
78#endif
79
80
81
82static int W_Filelength(int handle)
83{
84 /*
85 struct stat fileinfo;
86 if (fstat(handle,&fileinfo) == -1)
87 I_Error("W_Filelength: Error fstating");
88 return fileinfo.st_size;
89 */
90 return filesize(handle);
91}
92
93void ExtractFileBase (const char *path, char *dest)
94{
95 const char *src = path + strlen(path) - 1;
96 int length;
97
98 // back up until a \ or the start
99 while (src != path && src[-1] != ':' // killough 3/22/98: allow c:filename
100 && *(src-1) != '\\'
101 && *(src-1) != '/')
102 src--;
103
104 // copy up to eight characters
105 memset(dest,0,8);
106 length = 0;
107
108 while (*src && *src != '.' && ++length<9)
109 *dest++ = toupper(*src++);
110 /* cph - length check removed, just truncate at 8 chars.
111 * If there are 8 or more chars, we'll copy 8, and no zero termination
112 */
113}
114
115//
116// 1/18/98 killough: adds a default extension to a path
117// Note: Backslashes are treated specially, for MS-DOS.
118//
119
120char *AddDefaultExtension(char *path, const char *ext)
121{
122 char *p = path;
123 while (*p++);
124 while (p-->path && *p!='/' && *p!='\\')
125 if (*p=='.')
126 return path;
127 if (*ext!='.')
128 strcat(path,".");
129 return strcat(path,ext);
130}
131
132//
133// LUMP BASED ROUTINES.
134//
135
136//
137// W_AddFile
138// All files are optional, but at least one file must be
139// found (PWAD, if all required lumps are present).
140// Files with a .wad extension are wadlink files
141// with multiple lumps.
142// Other files are single lumps with the base filename
143// for the lump name.
144//
145// Reload hack removed by Lee Killough
146// CPhipps - source is an enum
147//
148
149static void W_AddFile(const char *filename, wad_source_t source)
150// killough 1/31/98: static, const
151{
152 wadinfo_t header;
153 lumpinfo_t* lump_p;
154 unsigned i;
155 int handle;
156 int length;
157 int startlump;
158 filelump_t *fileinfo, *fileinfo2free=NULL; //killough
159 filelump_t singleinfo;
160
161 // open the file and add to directory
162
163 handle = open(filename,O_RDONLY);
164
165#ifdef HAVE_NET
166 if (handle == -1 && D_NetGetWad(filename)) // CPhipps
167 handle = open(filename,O_RDONLY);
168#endif
169
170 if (handle == -1)
171 {
172 if ( strlen(filename)<=4 || // add error check -- killough
173 (strcasecmp(filename+strlen(filename)-4 , ".lmp" ) &&
174 strcasecmp(filename+strlen(filename)-4 , ".gwa" ) )
175 )
176 I_Error("W_AddFile: couldn't open %s",filename);
177 return;
178 }
179
180 //jff 8/3/98 use logical output routine
181 printf (" adding %s\n",filename);
182 startlump = numlumps;
183
184 if ( strlen(filename)<=4 ||
185 (
186 strcasecmp(filename+strlen(filename)-4,".wad") &&
187 strcasecmp(filename+strlen(filename)-4,".gwa")
188 )
189 )
190 {
191 // single lump file
192 fileinfo = &singleinfo;
193 singleinfo.filepos = 0;
194 singleinfo.size = LONG(W_Filelength(handle));
195 ExtractFileBase(filename, singleinfo.name);
196 numlumps++;
197 }
198 else
199 {
200 // WAD file
201 read(handle, &header, sizeof(header));
202 if (strncmp(header.identification,"IWAD",4) &&
203 strncmp(header.identification,"PWAD",4))
204 I_Error("W_AddFile: Wad file %s doesn't have IWAD or PWAD id", filename);
205 header.numlumps = LONG(header.numlumps);
206 header.infotableofs = LONG(header.infotableofs);
207 length = header.numlumps*sizeof(filelump_t);
208 fileinfo2free = fileinfo = malloc(length); // killough
209 lseek(handle, header.infotableofs, SEEK_SET);
210 read(handle, fileinfo, length);
211 numlumps += header.numlumps;
212 }
213
214 // Fill in lumpinfo
215 lumpinfo = realloc(lumpinfo, numlumps*sizeof(lumpinfo_t));
216
217 lump_p = &lumpinfo[startlump];
218 for (i=startlump ; (int)i<numlumps ; i++,lump_p++, fileinfo++)
219 {
220 lump_p->handle = handle; // killough 4/25/98
221 lump_p->position = LONG(fileinfo->filepos);
222 lump_p->size = LONG(fileinfo->size);
223#ifndef NO_PREDEFINED_LUMPS
224 lump_p->data = NULL; // killough 1/31/98
225#endif
226 lump_p->namespace = ns_global; // killough 4/17/98
227 strncpy (lump_p->name, fileinfo->name, 8);
228 lump_p->source = source; // Ty 08/29/98
229 lump_p->locks = 0; // CPhipps - initialise locks
230 }
231
232 free(fileinfo2free); // killough
233}
234
235// jff 1/23/98 Create routines to reorder the master directory
236// putting all flats into one marked block, and all sprites into another.
237// This will allow loading of sprites and flats from a PWAD with no
238// other changes to code, particularly fast hashes of the lumps.
239//
240// killough 1/24/98 modified routines to be a little faster and smaller
241
242static int IsMarker(const char *marker, const char *name)
243{
244 return !strncasecmp(name, marker, 8) ||
245 (*name == *marker && !strncasecmp(name+1, marker, 7));
246}
247
248// killough 4/17/98: add namespace tags
249
250static void W_CoalesceMarkedResource(const char *start_marker,
251 const char *end_marker, int namespace)
252{
253 lumpinfo_t *marked = malloc(sizeof(*marked) * numlumps);
254 size_t i, num_marked = 0, num_unmarked = 0;
255 int is_marked = 0, mark_end = 0;
256 lumpinfo_t *lump = lumpinfo;
257
258 for (i=numlumps; i--; lump++)
259 if (IsMarker(start_marker, lump->name)) // start marker found
260 { // If this is the first start marker, add start marker to marked lumps
261 if (!num_marked)
262 {
263 strncpy(marked->name, start_marker, 8);
264 marked->size = 0; // killough 3/20/98: force size to be 0
265 marked->namespace = ns_global; // killough 4/17/98
266 num_marked = 1;
267 }
268 is_marked = 1; // start marking lumps
269 }
270 else
271 if (IsMarker(end_marker, lump->name)) // end marker found
272 {
273 mark_end = 1; // add end marker below
274 is_marked = 0; // stop marking lumps
275 }
276 else
277 if (is_marked) // if we are marking lumps,
278 { // move lump to marked list
279 marked[num_marked] = *lump;
280 marked[num_marked++].namespace = namespace; // killough 4/17/98
281 }
282 else
283 lumpinfo[num_unmarked++] = *lump; // else move down THIS list
284
285 // Append marked list to end of unmarked list
286 memcpy(lumpinfo + num_unmarked, marked, num_marked * sizeof(*marked));
287
288 free(marked); // free marked list
289
290 numlumps = num_unmarked + num_marked; // new total number of lumps
291
292 if (mark_end) // add end marker
293 {
294 lumpinfo[numlumps].size = 0; // killough 3/20/98: force size to be 0
295 lumpinfo[numlumps].namespace = ns_global; // killough 4/17/98
296 strncpy(lumpinfo[numlumps++].name, end_marker, 8);
297 }
298}
299
300// Hash function used for lump names.
301// Must be mod'ed with table size.
302// Can be used for any 8-character names.
303// by Lee Killough
304
305unsigned W_LumpNameHash(const char *s)
306{
307 unsigned hash;
308 (void) ((hash = toupper(s[0]), s[1]) &&
309 (hash = hash*3+toupper(s[1]), s[2]) &&
310 (hash = hash*2+toupper(s[2]), s[3]) &&
311 (hash = hash*2+toupper(s[3]), s[4]) &&
312 (hash = hash*2+toupper(s[4]), s[5]) &&
313 (hash = hash*2+toupper(s[5]), s[6]) &&
314 (hash = hash*2+toupper(s[6]),
315 hash = hash*2+toupper(s[7]))
316 );
317 return hash;
318}
319
320//
321// W_CheckNumForName
322// Returns -1 if name not found.
323//
324// Rewritten by Lee Killough to use hash table for performance. Significantly
325// cuts down on time -- increases Doom performance over 300%. This is the
326// single most important optimization of the original Doom sources, because
327// lump name lookup is used so often, and the original Doom used a sequential
328// search. For large wads with > 1000 lumps this meant an average of over
329// 500 were probed during every search. Now the average is under 2 probes per
330// search. There is no significant benefit to packing the names into longwords
331// with this new hashing algorithm, because the work to do the packing is
332// just as much work as simply doing the string comparisons with the new
333// algorithm, which minimizes the expected number of comparisons to under 2.
334//
335// killough 4/17/98: add namespace parameter to prevent collisions
336// between different resources such as flats, sprites, colormaps
337//
338
339int (W_CheckNumForName)(register const char *name, register int namespace)
340{
341 // Hash function maps the name to one of possibly numlump chains.
342 // It has been tuned so that the average chain length never exceeds 2.
343
344 int i;
345
346 if (!lumpinfo)
347 return -1;
348
349 i = lumpinfo[W_LumpNameHash(name) % (unsigned) numlumps].index;
350
351 // We search along the chain until end, looking for case-insensitive
352 // matches which also match a namespace tag. Separate hash tables are
353 // not used for each namespace, because the performance benefit is not
354 // worth the overhead, considering namespace collisions are rare in
355 // Doom wads.
356
357 while (i >= 0 && (strncasecmp(lumpinfo[i].name, name, 8) ||
358 lumpinfo[i].namespace != (unsigned)namespace))
359 i = lumpinfo[i].next;
360
361 // Return the matching lump, or -1 if none found.
362
363 return i;
364}
365
366//
367// killough 1/31/98: Initialize lump hash table
368//
369
370static void W_InitLumpHash(void)
371{
372 int i;
373
374 for (i=0; i<numlumps; i++)
375 lumpinfo[i].index = -1; // mark slots empty
376
377 // Insert nodes to the beginning of each chain, in first-to-last
378 // lump order, so that the last lump of a given name appears first
379 // in any chain, observing pwad ordering rules. killough
380
381 for (i=0; i<numlumps; i++)
382 { // hash function:
383 int j = W_LumpNameHash(lumpinfo[i].name) % (unsigned) numlumps;
384 lumpinfo[i].next = lumpinfo[j].index; // Prepend to list
385 lumpinfo[j].index = i;
386 }
387}
388
389// End of lump hashing -- killough 1/31/98
390
391
392
393// W_GetNumForName
394// Calls W_CheckNumForName, but bombs out if not found.
395//
396int W_GetNumForName (const char* name) // killough -- const added
397{
398 int i = W_CheckNumForName (name);
399 if (i == -1)
400 I_Error("W_GetNumForName: %s not found", name);
401 return i;
402}
403
404// W_Init
405// Loads each of the files in the wadfiles array.
406// All files are optional, but at least one file
407// must be found.
408// Files with a .wad extension are idlink files
409// with multiple lumps.
410// Other files are single lumps with the base filename
411// for the lump name.
412// Lump names can appear multiple times.
413// The name searcher looks backwards, so a later file
414// does override all earlier ones.
415//
416// CPhipps - modified to use the new wadfiles array
417//
418struct wadfile_info *wadfiles=NULL;
419
420size_t numwadfiles = 0; // CPhipps - size of the wadfiles array (dynamic, no limit)
421
422void W_Init(void)
423{
424#ifndef NO_PREDEFINED_LUMPS
425 // killough 1/31/98: add predefined lumps first
426
427 numlumps = num_predefined_lumps;
428
429 // lumpinfo will be realloced as lumps are added
430 lumpinfo = malloc(numlumps*sizeof(*lumpinfo));
431
432 memcpy(lumpinfo, predefined_lumps, numlumps*sizeof(*lumpinfo));
433 // Ty 08/29/98 - add source flag to the predefined lumps
434 {
435 int i;
436 for (i=0;i<numlumps;i++)
437 lumpinfo[i].source = source_pre;
438 }
439#else
440 // CPhipps - start with nothing
441
442 numlumps = 0; lumpinfo = malloc(0);
443#endif
444
445 { // CPhipps - new wadfiles array used
446 // open all the files, load headers, and count lumps
447 int i;
448 for (i=0; (size_t)i<numwadfiles; i++)
449 W_AddFile(wadfiles[i].name, wadfiles[i].src);
450 }
451 if (!numlumps)
452 I_Error ("W_Init: No files found");
453
454 //jff 1/23/98
455 // get all the sprites and flats into one marked block each
456 // killough 1/24/98: change interface to use M_START/M_END explicitly
457 // killough 4/17/98: Add namespace tags to each entry
458
459 W_CoalesceMarkedResource("S_START", "S_END", ns_sprites);
460 W_CoalesceMarkedResource("F_START", "F_END", ns_flats);
461
462 // killough 4/4/98: add colormap markers
463 W_CoalesceMarkedResource("C_START", "C_END", ns_colormaps);
464
465 // set up caching
466 lumpcache = calloc(sizeof *lumpcache, numlumps); // killough
467
468 if (!lumpcache)
469 I_Error ("W_Init: Couldn't allocate lumpcache");
470
471 // killough 1/31/98: initialize lump hash table
472 W_InitLumpHash();
473
474#ifdef TIMEDIAG
475 // cph - allocate space for lock time diagnostics
476 locktic = malloc(sizeof(*locktic)*numlumps);
477 atexit(W_ReportLocks);
478#endif
479}
480
481//
482// W_LumpLength
483// Returns the buffer size needed to load the given lump.
484//
485int W_LumpLength (int lump)
486{
487 if (lump >= numlumps)
488 I_Error ("W_LumpLength: %i >= numlumps",lump);
489 return lumpinfo[lump].size;
490}
491
492//
493// W_ReadLump
494// Loads the lump into the given buffer,
495// which must be >= W_LumpLength().
496//
497
498void W_ReadLump(int lump, void *dest)
499{
500 lumpinfo_t *l = lumpinfo + lump;
501
502#ifdef RANGECHECK
503 if (lump >= numlumps)
504 I_Error ("W_ReadLump: %i >= numlumps",lump);
505#endif
506
507#ifndef NO_PREDEFINED_LUMPS
508 if (l->data) // killough 1/31/98: predefined lump data
509 memcpy(dest, l->data, l->size);
510 else
511#endif
512 {
513 int c;
514
515 // killough 1/31/98: Reload hack (-wart) removed
516
517 lseek(l->handle, l->position, SEEK_SET);
518 c = read(l->handle, dest, l->size);
519 if (c < l->size)
520 I_Error("W_ReadLump: only read %i of %i on lump %i", c, l->size, lump);
521 }
522}
523
524//
525// W_CacheLumpNum
526/*
527 * killough 4/25/98: simplified
528 * CPhipps - modified for new lump locking scheme
529 * returns a const*
530 */
531
532void * (W_CacheLumpNum)(int lump, unsigned short locks)
533{
534#ifdef RANGECHECK
535 if ((unsigned)lump >= (unsigned)numlumps)
536 I_Error ("W_CacheLumpNum: %i >= numlumps",lump);
537#endif
538
539 if (!lumpcache[lump]) // read the lump in
540 W_ReadLump(lump, Z_Malloc(W_LumpLength(lump), PU_CACHE, &lumpcache[lump]));
541
542 /* cph - if wasn't locked but now is, tell z_zone to hold it */
543 if (!lumpinfo[lump].locks && locks) {
544 Z_ChangeTag(lumpcache[lump],PU_STATIC);
545#ifdef TIMEDIAG
546 locktic[lump] = gametic;
547#endif
548 }
549 lumpinfo[lump].locks += locks;
550
551#ifdef SIMPLECHECKS
552 if (!((lumpinfo[lump].locks+1) & 0xf))
553 printf("W_CacheLumpNum: High lock on %s (%d)\n",
554 lumpinfo[lump].name, lumpinfo[lump].locks);
555#endif
556
557 // CPhipps - if not locked, can't give you a pointer
558 return (locks ? lumpcache[lump] : NULL);
559}
560
561/* cph -
562 * W_CacheLumpNumPadded
563 *
564 * Caches a lump and pads the memory following it.
565 * The thing returned is *only* guaranteed to be padded if
566 * the lump isn't already cached (otherwise, you get whatever is
567 * currently cached, which if it was cached by a previous call
568 * to this will also be padded)
569 */
570
571void * W_CacheLumpNumPadded(int lump, size_t len, unsigned char pad)
572{
573 const int locks = 1;
574#ifdef RANGECHECK
575 if ((unsigned)lump >= (unsigned)numlumps)
576 I_Error ("W_CacheLumpNum: %i >= numlumps",lump);
577#endif
578
579 if (!lumpcache[lump]) { /* read the lump in */
580 size_t lumplen = W_LumpLength(lump);
581 unsigned char* p;
582 W_ReadLump(lump, p = Z_Malloc(len, PU_CACHE, &lumpcache[lump]));
583 memset(p+lumplen, pad, len-lumplen);
584 }
585
586 /* cph - if wasn't locked but now is, tell z_zone to hold it */
587 if (!lumpinfo[lump].locks && locks) {
588 Z_ChangeTag(lumpcache[lump],PU_STATIC);
589#ifdef TIMEDIAG
590 locktic[lump] = gametic;
591#endif
592 }
593 lumpinfo[lump].locks += locks;
594
595#ifdef SIMPLECHECKS
596 if (!((lumpinfo[lump].locks+1) & 0xf))
597 printf("W_CacheLumpNum: High lock on %s (%d)\n",
598 lumpinfo[lump].name, lumpinfo[lump].locks);
599#endif
600
601 return lumpcache[lump];
602}
603
604//
605// W_UnlockLumpNum
606//
607// CPhipps - this changes (should reduce) the number of locks on a lump
608
609void (W_UnlockLumpNum)(int lump, signed short unlocks)
610{
611#ifdef SIMPLECHECKS
612 if ((signed short)lumpinfo[lump].locks < unlocks)
613 printf("W_UnlockLumpNum: Excess unlocks on %s (%d-%d)\n",
614 lumpinfo[lump].name, lumpinfo[lump].locks, unlocks);
615#endif
616 lumpinfo[lump].locks -= unlocks;
617 // cph - Note: must only tell z_zone to make purgeable if currently locked,
618 // else it might already have been purged
619 if (unlocks && !lumpinfo[lump].locks)
620 Z_ChangeTag(lumpcache[lump], PU_CACHE);
621}
622
623// W_CacheLumpName macroized in w_wad.h -- killough
624
625#ifndef NO_PREDEFINED_LUMPS
626// WritePredefinedLumpWad
627// Args: Filename - string with filename to write to
628// Returns: void
629//
630// If the user puts a -dumplumps switch on the command line, we will
631// write all those predefined lumps above out into a pwad. User
632// supplies the pwad name.
633//
634// killough 4/22/98: make endian-independent, remove tab chars
635void WritePredefinedLumpWad(const char *filename)
636{
637 int handle; // for file open
638 char filenam[256]; // we may have to add ".wad" to the name they pass
639
640 if (!filename || !*filename) // check for null pointer or empty name
641 return; // early return
642
643 AddDefaultExtension(strcpy(filenam, filename), ".wad");
644
645 // The following code writes a PWAD from the predefined lumps array
646 // How to write a PWAD will not be explained here.
647#ifdef _MSC_VER // proff: In Visual C open is defined a bit different
648 if ( (handle = open (filenam, O_RDWR | O_CREAT | O_BINARY, _S_IWRITE|_S_IREAD)) != -1)
649#else
650 if ( (handle = open (filenam, O_RDWR | O_CREAT | O_BINARY, S_IWUSR|S_IRUSR)) != -1)
651#endif
652 {
653 wadinfo_t header = {"PWAD"};
654 size_t filepos = sizeof(wadinfo_t) + num_predefined_lumps * sizeof(filelump_t);
655 int i;
656
657 header.numlumps = LONG(num_predefined_lumps);
658 header.infotableofs = LONG(sizeof(header));
659
660 // write header
661 write(handle, &header, sizeof(header));
662
663 // write directory
664 for (i=0;(size_t)i<num_predefined_lumps;i++)
665 {
666 filelump_t fileinfo = {0};
667 fileinfo.filepos = LONG(filepos);
668 fileinfo.size = LONG(predefined_lumps[i].size);
669 strncpy(fileinfo.name, predefined_lumps[i].name, 8);
670 write(handle, &fileinfo, sizeof(fileinfo));
671 filepos += predefined_lumps[i].size;
672 }
673
674 // write lumps
675 for (i=0;(size_t)i<num_predefined_lumps;i++)
676 write(handle, predefined_lumps[i].data, predefined_lumps[i].size);
677
678 close(handle);
679 I_Error("WritePredefinedLumpWad: Predefined lumps wad, %s written", filename);
680 }
681 I_Error("WritePredefinedLumpWad: Can't open predefined lumps wad %s for output", filename);
682}
683#endif
diff --git a/apps/plugins/doom/w_wad.h b/apps/plugins/doom/w_wad.h
new file mode 100644
index 0000000000..f505f42cb7
--- /dev/null
+++ b/apps/plugins/doom/w_wad.h
@@ -0,0 +1,164 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION:
28 * WAD I/O functions.
29 *
30 *-----------------------------------------------------------------------------*/
31
32
33#ifndef __W_WAD__
34#define __W_WAD__
35
36#ifdef __GNUG__
37#pragma interface
38#endif
39
40#include "m_fixed.h"
41
42//
43// TYPES
44//
45
46typedef struct
47{
48 char identification[4]; // Should be "IWAD" or "PWAD".
49 int numlumps;
50 int infotableofs;
51} wadinfo_t;
52
53typedef struct
54{
55 int filepos;
56 int size;
57 char name[8];
58} filelump_t;
59
60#ifndef ALL_IN_ONE
61
62// NO_PREDEFINED_LUMPS causes none of the predefined lumps in info.c to be
63// included, and removes all extra code which is only there for them
64// Saves a little memory normally, lots if any were overridden, and makes
65// the executable smaller
66#define NO_PREDEFINED_LUMPS
67
68#endif
69
70//
71// WADFILE I/O related stuff.
72//
73
74// CPhipps - defined enum in wider scope
75// Ty 08/29/98 - add source field to identify where this lump came from
76typedef enum {
77 // CPhipps - define elements in order of 'how new/unusual'
78 source_iwad=0, // iwad file load
79 source_pre, // predefined lump
80 source_auto_load, // lump auto-loaded by config file
81 source_pwad, // pwad file load
82 source_lmp, // lmp file load
83 source_net // CPhipps
84} wad_source_t;
85
86typedef struct
87{
88 // WARNING: order of some fields important (see info.c).
89
90 char name[8];
91 int size;
92#ifndef NO_PREDEFINED_LUMPS
93 const void *data; // killough 1/31/98: points to predefined lump data
94#endif
95
96 // killough 1/31/98: hash table fields, used for ultra-fast hash table lookup
97 int index, next;
98
99 // killough 4/17/98: namespace tags, to prevent conflicts between resources
100 enum {
101 ns_global=0,
102 ns_sprites,
103 ns_flats,
104 ns_colormaps
105 } namespace;
106
107 int handle;
108 int position;
109 unsigned int locks; // CPhipps - wad lump locking
110 wad_source_t source;
111} lumpinfo_t;
112
113// killough 1/31/98: predefined lumps
114extern const size_t num_predefined_lumps;
115extern const lumpinfo_t predefined_lumps[];
116
117extern void **lumpcache;
118extern lumpinfo_t *lumpinfo;
119extern int numlumps;
120
121// CPhipps - changed wad init
122// We _must_ have the wadfiles[] the same as those actually loaded, so there
123// is no point having these separate entities. This belongs here.
124struct wadfile_info {
125 const char* name;
126 wad_source_t src;
127};
128
129extern struct wadfile_info *wadfiles;
130
131extern size_t numwadfiles; // CPhipps - size of the wadfiles array
132
133void W_Init(void); // CPhipps - uses the above array
134
135// killough 4/17/98: if W_CheckNumForName() called with only
136// one argument, pass ns_global as the default namespace
137
138#define W_CheckNumForName(name) (W_CheckNumForName)(name, ns_global)
139int (W_CheckNumForName)(const char* name, int); // killough 4/17/98
140int W_GetNumForName (const char* name);
141int W_LumpLength (int lump);
142void W_ReadLump (int lump, void *dest);
143// CPhipps - modified for 'new' lump locking
144void* W_CacheLumpNum (int lump, unsigned short locks);
145void W_UnlockLumpNum(int lump, signed short unlocks);
146
147/* cph - special version to return lump with padding, for sound lumps */
148void * W_CacheLumpNumPadded(int lump, size_t len, unsigned char pad);
149
150// CPhipps - convenience macros
151#define W_CacheLumpNum(num) (W_CacheLumpNum)((num),1)
152#define W_CacheLumpName(name) W_CacheLumpNum (W_GetNumForName(name))
153
154#define W_UnlockLumpNum(num) (W_UnlockLumpNum)((num),1)
155#define W_UnlockLumpName(name) W_UnlockLumpNum (W_GetNumForName(name))
156
157char *AddDefaultExtension(char *, const char *); // killough 1/18/98
158void ExtractFileBase(const char *, char *); // killough
159unsigned W_LumpNameHash(const char *s); // killough 1/31/98
160
161// Function to write all predefined lumps to a PWAD if requested
162extern void WritePredefinedLumpWad(const char *filename); // jff 5/6/98
163
164#endif
diff --git a/apps/plugins/doom/wi_stuff.c b/apps/plugins/doom/wi_stuff.c
new file mode 100644
index 0000000000..3d14d088d5
--- /dev/null
+++ b/apps/plugins/doom/wi_stuff.c
@@ -0,0 +1,1989 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION:
28 * Intermission screens.
29 *
30 *-----------------------------------------------------------------------------
31 */
32
33#include "doomstat.h"
34#include "m_random.h"
35#include "w_wad.h"
36#include "g_game.h"
37#include "r_main.h"
38#include "v_video.h"
39#include "wi_stuff.h"
40#include "s_sound.h"
41#include "sounds.h"
42#include "m_swap.h"
43#include "r_draw.h"
44
45//
46// Data needed to add patches to full screen intermission pics.
47// Patches are statistics messages, and animations.
48// Loads of by-pixel layout and placement, offsets etc.
49//
50
51//
52// Different vetween registered DOOM (1994) and
53// Ultimate DOOM - Final edition (retail, 1995?).
54// This is supposedly ignored for commercial
55// release (aka DOOM II), which had 34 maps
56// in one episode. So there.
57#define NUMEPISODES 4
58#define NUMMAPS 9
59
60
61// Not used
62// in tics
63//U #define PAUSELEN (TICRATE*2)
64//U #define SCORESTEP 100
65//U #define ANIMPERIOD 32
66// pixel distance from "(YOU)" to "PLAYER N"
67//U #define STARDIST 10
68//U #define WK 1
69
70
71// GLOBAL LOCATIONS
72#define WI_TITLEY 2
73#define WI_SPACINGY 33
74
75// SINGLE-PLAYER STUFF
76#define SP_STATSX 50
77#define SP_STATSY 50
78
79#define SP_TIMEX 8
80// proff/nicolas 09/20/98 -- changed for hi-res
81#define SP_TIMEY 160
82//#define SP_TIMEY (SCREENHEIGHT-32)
83
84
85// NET GAME STUFF
86#define NG_STATSY 50
87#define NG_STATSX (32 + V_NamePatchWidth(star)/2 + 32*!dofrags)
88
89#define NG_SPACINGX 64
90
91
92// Used to display the frags matrix at endgame
93// DEATHMATCH STUFF
94#define DM_MATRIXX 42
95#define DM_MATRIXY 68
96
97#define DM_SPACINGX 40
98
99#define DM_TOTALSX 269
100
101#define DM_KILLERSX 10
102#define DM_KILLERSY 100
103#define DM_VICTIMSX 5
104#define DM_VICTIMSY 50
105
106
107// These animation variables, structures, etc. are used for the
108// DOOM/Ultimate DOOM intermission screen animations. This is
109// totally different from any sprite or texture/flat animations
110typedef enum
111{
112 ANIM_ALWAYS, // determined by patch entry
113 ANIM_RANDOM, // occasional
114 ANIM_LEVEL // continuous
115} animenum_t;
116
117typedef struct
118{
119 int x; // x/y coordinate pair structure
120 int y;
121} point_t;
122
123
124//
125// Animation.
126// There is another anim_t used in p_spec.
127//
128typedef struct
129{
130 animenum_t type;
131
132 // period in tics between animations
133 int period;
134
135 // number of animation frames
136 int nanims;
137
138 // location of animation
139 point_t loc;
140
141 // ALWAYS: n/a,
142 // RANDOM: period deviation (<256),
143 // LEVEL: level
144 int data1;
145
146 // ALWAYS: n/a,
147 // RANDOM: random base period,
148 // LEVEL: n/a
149 int data2;
150
151 /* actual graphics for frames of animations
152 * cphipps - const
153 */
154 const patch_t* p[3];
155
156 // following must be initialized to zero before use!
157
158 // next value of bcnt (used in conjunction with period)
159 int nexttic;
160
161 // last drawn animation frame
162 int lastdrawn;
163
164 // next frame number to animate
165 int ctr;
166
167 // used by RANDOM and LEVEL when animating
168 int state;
169} anim_t;
170
171
172static point_t lnodes[NUMEPISODES][NUMMAPS] =
173 {
174 // Episode 0 World Map
175 {
176 { 185, 164 }, // location of level 0 (CJ)
177 { 148, 143 }, // location of level 1 (CJ)
178 { 69, 122 }, // location of level 2 (CJ)
179 { 209, 102 }, // location of level 3 (CJ)
180 { 116, 89 }, // location of level 4 (CJ)
181 { 166, 55 }, // location of level 5 (CJ)
182 { 71, 56 }, // location of level 6 (CJ)
183 { 135, 29 }, // location of level 7 (CJ)
184 { 71, 24 } // location of level 8 (CJ)
185 },
186
187 // Episode 1 World Map should go here
188 {
189 { 254, 25 }, // location of level 0 (CJ)
190 { 97, 50 }, // location of level 1 (CJ)
191 { 188, 64 }, // location of level 2 (CJ)
192 { 128, 78 }, // location of level 3 (CJ)
193 { 214, 92 }, // location of level 4 (CJ)
194 { 133, 130 }, // location of level 5 (CJ)
195 { 208, 136 }, // location of level 6 (CJ)
196 { 148, 140 }, // location of level 7 (CJ)
197 { 235, 158 } // location of level 8 (CJ)
198 },
199
200 // Episode 2 World Map should go here
201 {
202 { 156, 168 }, // location of level 0 (CJ)
203 { 48, 154 }, // location of level 1 (CJ)
204 { 174, 95 }, // location of level 2 (CJ)
205 { 265, 75 }, // location of level 3 (CJ)
206 { 130, 48 }, // location of level 4 (CJ)
207 { 279, 23 }, // location of level 5 (CJ)
208 { 198, 48 }, // location of level 6 (CJ)
209 { 140, 25 }, // location of level 7 (CJ)
210 { 281, 136 } // location of level 8 (CJ)
211 }
212
213 };
214
215
216//
217// Animation locations for episode 0 (1).
218// Using patches saves a lot of space,
219// as they replace 320x200 full screen frames.
220//
221static anim_t epsd0animinfo[] =
222 {
223 { ANIM_ALWAYS, TICRATE/3, 3, { 224, 104 }, 0, 0, { 0, 0, 0 }, 0, 0, 0, 0 },
224 { ANIM_ALWAYS, TICRATE/3, 3, { 184, 160 }, 0, 0, { 0, 0, 0 }, 0, 0, 0, 0 },
225 { ANIM_ALWAYS, TICRATE/3, 3, { 112, 136 }, 0, 0, { 0, 0, 0 }, 0, 0, 0, 0 },
226 { ANIM_ALWAYS, TICRATE/3, 3, { 72, 112 }, 0, 0, { 0, 0, 0 }, 0, 0, 0, 0 },
227 { ANIM_ALWAYS, TICRATE/3, 3, { 88, 96 }, 0, 0, { 0, 0, 0 }, 0, 0, 0, 0 },
228 { ANIM_ALWAYS, TICRATE/3, 3, { 64, 48 }, 0, 0, { 0, 0, 0 }, 0, 0, 0, 0 },
229 { ANIM_ALWAYS, TICRATE/3, 3, { 192, 40 }, 0, 0, { 0, 0, 0 }, 0, 0, 0, 0 },
230 { ANIM_ALWAYS, TICRATE/3, 3, { 136, 16 }, 0, 0, { 0, 0, 0 }, 0, 0, 0, 0 },
231 { ANIM_ALWAYS, TICRATE/3, 3, { 80, 16 }, 0, 0, { 0, 0, 0 }, 0, 0, 0, 0 },
232 { ANIM_ALWAYS, TICRATE/3, 3, { 64, 24 }, 0, 0, { 0, 0, 0 }, 0, 0, 0, 0 }
233 };
234
235static anim_t epsd1animinfo[] =
236 {
237 { ANIM_LEVEL, TICRATE/3, 1, { 128, 136 }, 1, 0, { 0, 0, 0 }, 0, 0, 0, 0 },
238 { ANIM_LEVEL, TICRATE/3, 1, { 128, 136 }, 2, 0, { 0, 0, 0 }, 0, 0, 0, 0 },
239 { ANIM_LEVEL, TICRATE/3, 1, { 128, 136 }, 3, 0, { 0, 0, 0 }, 0, 0, 0, 0 },
240 { ANIM_LEVEL, TICRATE/3, 1, { 128, 136 }, 4, 0, { 0, 0, 0 }, 0, 0, 0, 0 },
241 { ANIM_LEVEL, TICRATE/3, 1, { 128, 136 }, 5, 0, { 0, 0, 0 }, 0, 0, 0, 0 },
242 { ANIM_LEVEL, TICRATE/3, 1, { 128, 136 }, 6, 0, { 0, 0, 0 }, 0, 0, 0, 0 },
243 { ANIM_LEVEL, TICRATE/3, 1, { 128, 136 }, 7, 0, { 0, 0, 0 }, 0, 0, 0, 0 },
244 { ANIM_LEVEL, TICRATE/3, 3, { 192, 144 }, 8, 0, { 0, 0, 0 }, 0, 0, 0, 0 },
245 { ANIM_LEVEL, TICRATE/3, 1, { 128, 136 }, 8, 0, { 0, 0, 0 }, 0, 0, 0, 0 }
246 };
247
248static anim_t epsd2animinfo[] =
249 {
250 { ANIM_ALWAYS, TICRATE/3, 3, { 104, 168 }, 0, 0, { 0, 0, 0 }, 0, 0, 0, 0 },
251 { ANIM_ALWAYS, TICRATE/3, 3, { 40, 136 }, 0, 0, { 0, 0, 0 }, 0, 0, 0, 0 },
252 { ANIM_ALWAYS, TICRATE/3, 3, { 160, 96 }, 0, 0, { 0, 0, 0 }, 0, 0, 0, 0 },
253 { ANIM_ALWAYS, TICRATE/3, 3, { 104, 80 }, 0, 0, { 0, 0, 0 }, 0, 0, 0, 0 },
254 { ANIM_ALWAYS, TICRATE/3, 3, { 120, 32 }, 0, 0, { 0, 0, 0 }, 0, 0, 0, 0 },
255 { ANIM_ALWAYS, TICRATE/4, 3, { 40, 0 }, 0, 0, { 0, 0, 0 }, 0, 0, 0, 0 }
256 };
257
258static int NUMANIMS[NUMEPISODES] =
259 {
260 sizeof(epsd0animinfo)/sizeof(anim_t),
261 sizeof(epsd1animinfo)/sizeof(anim_t),
262 sizeof(epsd2animinfo)/sizeof(anim_t)
263 };
264
265static anim_t *anims[NUMEPISODES] =
266 {
267 epsd0animinfo,
268 epsd1animinfo,
269 epsd2animinfo
270 };
271
272
273//
274// GENERAL DATA
275//
276
277//
278// Locally used stuff.
279//
280#define FB 0
281
282
283// States for single-player
284#define SP_KILLS 0
285#define SP_ITEMS 2
286#define SP_SECRET 4
287#define SP_FRAGS 6
288#define SP_TIME 8
289#define SP_PAR ST_TIME
290
291#define SP_PAUSE 1
292
293// in seconds
294#define SHOWNEXTLOCDELAY 4
295//#define SHOWLASTLOCDELAY SHOWNEXTLOCDELAY
296
297
298// used to accelerate or skip a stage
299int acceleratestage; // killough 3/28/98: made global
300
301// wbs->pnum
302static int me;
303
304// specifies current state
305static stateenum_t state;
306
307// contains information passed into intermission
308static wbstartstruct_t* wbs;
309
310static wbplayerstruct_t* plrs; // wbs->plyr[]
311
312// used for general timing
313static int cnt;
314
315// used for timing of background animation
316static int bcnt;
317
318// signals to refresh everything for one frame
319static int firstrefresh;
320
321static int cnt_time;
322static int cnt_total_time;
323static int cnt_par;
324static int cnt_pause;
325
326
327//
328// GRAPHICS
329//
330
331// You Are Here graphic
332static const char* yah[2] = { "WIURH0", "WIURH1" };
333
334// splat
335static const char* splat = "WISPLAT";
336
337// %, : graphics
338static const char percent[] = {"WIPCNT"};
339static const char colon[] = {"WICOLON"};
340
341// 0-9 graphic
342static const patch_t * num[10];
343
344// minus sign
345static const char wiminus[] = {"WIMINUS"};
346
347// "Finished!" graphics
348static const char finished[] = {"WIF"};
349
350// "Entering" graphic
351static const char entering[] = {"WIENTER"};
352
353// "secret"
354static const char sp_secret[] = {"WISCRT2"};
355
356// "Kills", "Scrt", "Items", "Frags"
357static const char kills[] = {"WIOSTK"};
358static const char secret[] = {"WIOSTS"};
359static const char items[] = {"WIOSTI"};
360static const char frags[] = {"WIFRGS"};
361
362// Time sucks.
363static const char time1[] = {"WITIME"};
364static const char par[] = {"WIPAR"};
365static const char sucks[] = {"WISUCKS"};
366
367// "killers", "victims"
368static const char killers[] = {"WIKILRS"};
369static const char victims[] = {"WIVCTMS"};
370
371// "Total", your face, your dead face
372static const char total[] = {"WIMSTT"};
373static const char star[] = {"STFST01"};
374static const char bstar[] = {"STFDEAD0"};
375
376// "red P[1..MAXPLAYERS]"
377static const char facebackp[] = {"STPB0"};
378
379
380//
381// CODE
382//
383
384static void WI_endDeathmatchStats(void);
385static void WI_endNetgameStats(void);
386void WI_unloadData(void);
387#define WI_endStats WI_endNetgameStats
388
389/* ====================================================================
390 * WI_levelNameLump
391 * Purpore: Returns the name of the graphic lump containing the name of
392 * the given level.
393 * Args: Episode and level, and buffer (must by 9 chars) to write to
394 * Returns: void
395 */
396void WI_levelNameLump(int epis, int map, char* buf, int bsize)
397{
398 if (gamemode == commercial) {
399 snprintf(buf, bsize,"CWILV%s%d",(map/10>0?"":"0"), map); //ANOTHER ROCKHACK "CWILV%2.2d"
400 //snprintf(buf,bsize, "CWILV%2.2d", map);
401 } else {
402 snprintf(buf,bsize, "WILV%d%d", epis, map);
403 }
404}
405
406// ====================================================================
407// WI_slamBackground
408// Purpose: Put the full-screen background up prior to patches
409// Args: none
410// Returns: void
411//
412static void WI_slamBackground(void)
413{
414 char name[9]; // limited to 8 characters
415
416 if (gamemode == commercial || (gamemode == retail && wbs->epsd == 3))
417 strcpy(name, "INTERPIC");
418 else
419 snprintf(name, sizeof(name), "WIMAP%d", wbs->epsd);
420
421 // background
422 V_DrawNamePatch(0, 0, FB, name, CR_DEFAULT, VPT_STRETCH);
423}
424
425// ====================================================================
426// WI_Responder
427// Purpose: Draw animations on intermission background screen
428// Args: ev -- event pointer, not actually used here.
429// Returns: False -- dummy routine
430//
431// The ticker is used to detect keys
432// because of timing issues in netgames.
433boolean WI_Responder(event_t* ev)
434{
435 (void)ev;
436 return false;
437}
438
439// ====================================================================
440// WI_drawLF
441// Purpose: Draw the "Finished" level name before showing stats
442// Args: none
443// Returns: void
444//
445void WI_drawLF(void)
446{
447 int y = WI_TITLEY;
448 char lname[9];
449
450 // draw <LevelName>
451 /* cph - get the graphic lump name and use it */
452 WI_levelNameLump(wbs->epsd, wbs->last, lname, sizeof(lname));
453 // CPhipps - patch drawing updated
454 V_DrawNamePatch((320 - V_NamePatchWidth(lname))/2, y,
455 FB, lname, CR_DEFAULT, VPT_STRETCH);
456
457 // draw "Finished!"
458 y += (5*V_NamePatchHeight(lname))/4;
459
460 // CPhipps - patch drawing updated
461 V_DrawNamePatch((320 - V_NamePatchWidth(finished))/2, y,
462 FB, finished, CR_DEFAULT, VPT_STRETCH);
463}
464
465// ====================================================================
466// WI_drawEL
467// Purpose: Draw introductory "Entering" and level name
468// Args: none
469// Returns: void
470//
471void WI_drawEL(void)
472{
473 int y = WI_TITLEY;
474 char lname[9];
475
476 /* cph - get the graphic lump name */
477 WI_levelNameLump(wbs->epsd, wbs->next, lname, sizeof(lname));
478
479 // draw "Entering"
480 // CPhipps - patch drawing updated
481 V_DrawNamePatch((320 - V_NamePatchWidth(entering))/2,
482 y, FB, entering, CR_DEFAULT, VPT_STRETCH);
483
484 // draw level
485 y += (5*V_NamePatchHeight(lname))/4;
486
487 // CPhipps - patch drawing updated
488 V_DrawNamePatch((320 - V_NamePatchWidth(lname))/2, y, FB,
489 lname, CR_DEFAULT, VPT_STRETCH);
490}
491
492
493/* ====================================================================
494 * WI_drawOnLnode
495 * Purpose: Draw patches at a location based on episode/map
496 * Args: n -- index to map# within episode
497 * c[] -- array of names of patches to be drawn
498 * Returns: void
499 */
500void
501WI_drawOnLnode // draw stuff at a location by episode/map#
502( int n,
503 const char* const c[] )
504{
505 int i;
506 boolean fits = false;
507
508 i = 0;
509 do
510 {
511 int left;
512 int top;
513 int right;
514 int bottom;
515 int lump = W_GetNumForName(c[i]);
516 const patch_t* p = W_CacheLumpNum(lump);
517
518 left = lnodes[wbs->epsd][n].x - SHORT(p->leftoffset);
519 top = lnodes[wbs->epsd][n].y - SHORT(p->topoffset);
520 right = left + SHORT(p->width);
521 bottom = top + SHORT(p->height);
522 W_UnlockLumpNum(lump);
523
524 if (left >= 0
525 && right < 320
526 && top >= 0
527 && bottom < 200)
528 {
529 fits = true;
530 }
531 else
532 {
533 i++;
534 }
535 } while (!fits && i!=2);
536
537 if (fits && i<2)
538 {
539 // CPhipps - patch drawing updated
540 V_DrawNamePatch(lnodes[wbs->epsd][n].x, lnodes[wbs->epsd][n].y,
541 FB, c[i], CR_DEFAULT, VPT_STRETCH);
542 }
543 else
544 {
545 // DEBUG
546 //jff 8/3/98 use logical output routine
547 printf("Could not place patch on level %d", n+1);
548 }
549}
550
551
552// ====================================================================
553// WI_initAnimatedBack
554// Purpose: Initialize pointers and styles for background animation
555// Args: none
556// Returns: void
557//
558void WI_initAnimatedBack(void)
559{
560 int i;
561 anim_t* a;
562
563 if (gamemode == commercial) // no animation for DOOM2
564 return;
565
566 if (wbs->epsd > 2)
567 return;
568
569 for (i=0;i<NUMANIMS[wbs->epsd];i++)
570 {
571 a = &anims[wbs->epsd][i];
572
573 // init variables
574 a->ctr = -1;
575
576 // specify the next time to draw it
577 if (a->type == ANIM_ALWAYS)
578 a->nexttic = bcnt + 1 + (M_Random()%a->period);
579 else
580 if (a->type == ANIM_RANDOM)
581 a->nexttic = bcnt + 1 + a->data2+(M_Random()%a->data1);
582 else
583 if (a->type == ANIM_LEVEL)
584 a->nexttic = bcnt + 1;
585 }
586}
587
588
589// ====================================================================
590// WI_updateAnimatedBack
591// Purpose: Figure out what animation we do on this iteration
592// Args: none
593// Returns: void
594//
595void WI_updateAnimatedBack(void)
596{
597 int i;
598 anim_t* a;
599
600 if (gamemode == commercial)
601 return;
602
603 if (wbs->epsd > 2)
604 return;
605
606 for (i=0;i<NUMANIMS[wbs->epsd];i++)
607 {
608 a = &anims[wbs->epsd][i];
609
610 if (bcnt == a->nexttic)
611 {
612 switch (a->type)
613 {
614 case ANIM_ALWAYS:
615 if (++a->ctr >= a->nanims) a->ctr = 0;
616 a->nexttic = bcnt + a->period;
617 break;
618
619 case ANIM_RANDOM:
620 a->ctr++;
621 if (a->ctr == a->nanims)
622 {
623 a->ctr = -1;
624 a->nexttic = bcnt+a->data2+(M_Random()%a->data1);
625 }
626 else
627 a->nexttic = bcnt + a->period;
628 break;
629
630 case ANIM_LEVEL:
631 // gawd-awful hack for level anims
632 if (!(state == StatCount && i == 7)
633 && wbs->next == a->data1)
634 {
635 a->ctr++;
636 if (a->ctr == a->nanims) a->ctr--;
637 a->nexttic = bcnt + a->period;
638 }
639 break;
640 }
641 }
642 }
643}
644
645
646// ====================================================================
647// WI_drawAnimatedBack
648// Purpose: Actually do the animation (whew!)
649// Args: none
650// Returns: void
651//
652void WI_drawAnimatedBack(void)
653{
654 int i;
655 anim_t* a;
656
657 if (gamemode==commercial) //jff 4/25/98 Someone forgot commercial an enum
658 return;
659
660 if (wbs->epsd > 2)
661 return;
662
663 for (i=0 ; i<NUMANIMS[wbs->epsd] ; i++)
664 {
665 a = &anims[wbs->epsd][i];
666
667 if (a->ctr >= 0)
668 // CPhipps - patch drawing updated
669 V_DrawMemPatch(a->loc.x, a->loc.y, FB, a->p[a->ctr], CR_DEFAULT, VPT_STRETCH);
670 }
671}
672
673
674// ====================================================================
675// WI_drawNum
676// Purpose: Draws a number. If digits > 0, then use that many digits
677// minimum, otherwise only use as many as necessary
678// Args: x, y -- location
679// n -- the number to be drawn
680// digits -- number of digits minimum or zero
681// Returns: new x position after drawing (note we are going to the left)
682// CPhipps - static
683static int WI_drawNum (int x, int y, int n, int digits)
684{
685 int fontwidth = SHORT(num[0]->width);
686 int neg;
687 int temp;
688
689 if (digits < 0)
690 {
691 if (!n)
692 {
693 // make variable-length zeros 1 digit long
694 digits = 1;
695 }
696 else
697 {
698 // figure out # of digits in #
699 digits = 0;
700 temp = n;
701
702 while (temp)
703 {
704 temp /= 10;
705 digits++;
706 }
707 }
708 }
709
710 neg = n < 0;
711 if (neg)
712 n = -n;
713
714 // if non-number, do not draw it
715 if (n == 1994)
716 return 0;
717
718 // draw the new number
719 while (digits--)
720 {
721 x -= fontwidth;
722 // CPhipps - patch drawing updated
723 V_DrawMemPatch(x, y, FB, num[ n % 10 ], CR_DEFAULT, VPT_STRETCH);
724 n /= 10;
725 }
726
727 // draw a minus sign if necessary
728 if (neg)
729 // CPhipps - patch drawing updated
730 V_DrawNamePatch(x-=8, y, FB, wiminus, CR_DEFAULT, VPT_STRETCH);
731
732 return x;
733}
734
735
736// ====================================================================
737// WI_drawPercent
738// Purpose: Draws a percentage, really just a call to WI_drawNum
739// after putting a percent sign out there
740// Args: x, y -- location
741// p -- the percentage value to be drawn, no negatives
742// Returns: void
743// CPhipps - static
744static void WI_drawPercent(int x, int y, int p)
745{
746 if (p < 0)
747 return;
748
749 // CPhipps - patch drawing updated
750 V_DrawNamePatch(x, y, FB, percent, CR_DEFAULT, VPT_STRETCH);
751 WI_drawNum(x, y, p, -1);
752}
753
754
755// ====================================================================
756// WI_drawTime
757// Purpose: Draws the level completion time or par time, or "Sucks"
758// if 1 hour or more
759// Args: x, y -- location
760// t -- the time value to be drawn
761// Returns: void
762//
763// CPhipps - static
764// - largely rewritten to display hours and use slightly better algorithm
765
766static void WI_drawTime(int x, int y, int t)
767{
768 int n;
769
770 if (t<0)
771 return;
772
773 if (t < 100*60*60)
774 for(;;) {
775 n = t % 60;
776 t /= 60;
777 x = WI_drawNum(x, y, n, (t || n>9) ? 2 : 1) - V_NamePatchWidth(colon);
778
779 // draw
780 if (t)
781 // CPhipps - patch drawing updated
782 V_DrawNamePatch(x, y, FB, colon, CR_DEFAULT, VPT_STRETCH);
783 else break;
784 }
785 else // "sucks" (maybe should be "addicted", even I've never had a 100 hour game ;)
786 V_DrawNamePatch(x - V_NamePatchWidth(sucks),
787 y, FB, sucks, CR_DEFAULT, VPT_STRETCH);
788}
789
790
791// ====================================================================
792// WI_End
793// Purpose: Unloads data structures (inverse of WI_Start)
794// Args: none
795// Returns: void
796//
797void WI_End(void)
798{
799 WI_unloadData();
800
801 if (deathmatch)
802 WI_endDeathmatchStats();
803 else if (netgame)
804 WI_endNetgameStats();
805 else
806 WI_endStats();
807}
808
809
810// ====================================================================
811// WI_initNoState
812// Purpose: Clear state, ready for end of level activity
813// Args: none
814// Returns: void
815//
816void WI_initNoState(void)
817{
818 state = NoState;
819 acceleratestage = 0;
820 cnt = 10;
821}
822
823
824// ====================================================================
825// WI_drawTimeStats
826// Purpose: Put the times on the screen
827// Args: time, total time, par time, in seconds
828// Returns: void
829//
830// cph - pulled from WI_drawStats below
831
832static void WI_drawTimeStats(int cnt_time, int cnt_total_time, int cnt_par)
833{
834 V_DrawNamePatch(SP_TIMEX, SP_TIMEY, FB, time1, CR_DEFAULT, VPT_STRETCH);
835 WI_drawTime(320/2 - SP_TIMEX, SP_TIMEY, cnt_time);
836
837 V_DrawNamePatch(SP_TIMEX, (SP_TIMEY+200)/2, FB, total, CR_DEFAULT, VPT_STRETCH);
838 WI_drawTime(320/2 - SP_TIMEX, (SP_TIMEY+200)/2, cnt_total_time);
839
840 // Ty 04/11/98: redid logic: should skip only if with pwad but
841 // without deh patch
842 // killough 2/22/98: skip drawing par times on pwads
843 // Ty 03/17/98: unless pars changed with deh patch
844
845 if (!(modifiedgame)) //&& !deh_pars))
846 {
847 if (wbs->epsd < 3)
848 {
849 V_DrawNamePatch(320/2 + SP_TIMEX, SP_TIMEY, FB, par, CR_DEFAULT, VPT_STRETCH);
850 WI_drawTime(320 - SP_TIMEX, SP_TIMEY, cnt_par);
851 }
852 }
853}
854
855// ====================================================================
856// WI_updateNoState
857// Purpose: Cycle until end of level activity is done
858// Args: none
859// Returns: void
860//
861void WI_updateNoState(void)
862{
863
864 WI_updateAnimatedBack();
865
866 if (!--cnt)
867 G_WorldDone();
868}
869
870static boolean snl_pointeron = false;
871
872
873
874// ====================================================================
875// WI_initShowNextLoc
876// Purpose: Prepare to show the next level's location
877// Args: none
878// Returns: void
879//
880void WI_initShowNextLoc(void)
881{
882 if ((gamemode != commercial) && (gamemap == 8)) {
883 G_WorldDone();
884 return;
885 }
886
887 state = ShowNextLoc;
888 acceleratestage = 0;
889 cnt = SHOWNEXTLOCDELAY * TICRATE;
890
891 WI_initAnimatedBack();
892}
893
894// ====================================================================
895// WI_updateShowNextLoc
896// Purpose: Prepare to show the next level's location
897// Args: none
898// Returns: void
899//
900void WI_updateShowNextLoc(void)
901{
902 WI_updateAnimatedBack();
903
904 if (!--cnt || acceleratestage)
905 WI_initNoState();
906 else
907 snl_pointeron = (cnt & 31) < 20;
908}
909
910
911// ====================================================================
912// WI_drawShowNextLoc
913// Purpose: Show the next level's location on animated backgrounds
914// Args: none
915// Returns: void
916//
917void WI_drawShowNextLoc(void)
918{
919 int i;
920 int last;
921
922 WI_slamBackground();
923
924 // draw animated background
925 WI_drawAnimatedBack();
926
927 if ( gamemode != commercial)
928 {
929 if (wbs->epsd > 2)
930 {
931 WI_drawEL(); // "Entering..." if not E1 or E2
932 return;
933 }
934
935 last = (wbs->last == 8) ? wbs->next - 1 : wbs->last;
936
937 // draw a splat on taken cities.
938 for (i=0 ; i<=last ; i++)
939 WI_drawOnLnode(i, &splat);
940
941 // splat the secret level?
942 if (wbs->didsecret)
943 WI_drawOnLnode(8, &splat);
944
945 // draw flashing ptr
946 if (snl_pointeron)
947 WI_drawOnLnode(wbs->next, yah);
948 }
949
950 // draws which level you are entering..
951 if ( (gamemode != commercial)
952 || wbs->next != 30) // check for MAP30 end game
953 WI_drawEL();
954}
955
956// ====================================================================
957// WI_drawNoState
958// Purpose: Draw the pointer and next location
959// Args: none
960// Returns: void
961//
962void WI_drawNoState(void)
963{
964 snl_pointeron = true;
965 WI_drawShowNextLoc();
966}
967
968
969// ====================================================================
970// WI_fragSum
971// Purpose: Calculate frags for this player based on the current totals
972// of all the other players. Subtract self-frags.
973// Args: playernum -- the player to be calculated
974// Returns: the total frags for this player
975//
976int WI_fragSum(int playernum)
977{
978 int i;
979 int frags = 0;
980
981 for (i=0 ; i<MAXPLAYERS ; i++)
982 {
983 if (playeringame[i] // is this player playing?
984 && i!=playernum) // and it's not the player we're calculating
985 {
986 frags += plrs[playernum].frags[i];
987 }
988 }
989
990
991 // JDC hack - negative frags.
992 frags -= plrs[playernum].frags[playernum];
993
994 return frags;
995}
996
997
998static int dm_state;
999// CPhipps - short, dynamically allocated
1000static short int **dm_frags; // frags matrix
1001static short int *dm_totals; // totals by player
1002
1003// ====================================================================
1004// WI_initDeathmatchStats
1005// Purpose: Set up to display DM stats at end of level. Calculate
1006// frags for all players.
1007// Args: none
1008// Returns: void
1009//
1010void WI_initDeathmatchStats(void)
1011{
1012 int i; // looping variables
1013
1014 // CPhipps - allocate data structures needed
1015 dm_frags = calloc(MAXPLAYERS, sizeof(*dm_frags));
1016 dm_totals = calloc(MAXPLAYERS, sizeof(*dm_totals));
1017
1018 state = StatCount; // We're doing stats
1019 acceleratestage = 0;
1020 dm_state = 1; // count how many times we've done a complete stat
1021
1022 cnt_pause = TICRATE;
1023
1024 for (i=0 ; i<MAXPLAYERS ; i++)
1025 {
1026 if (playeringame[i])
1027 {
1028 // CPhipps - allocate frags line
1029 dm_frags[i] = calloc(MAXPLAYERS, sizeof(**dm_frags)); // set all counts to zero
1030
1031 dm_totals[i] = 0;
1032 }
1033 }
1034 WI_initAnimatedBack();
1035}
1036
1037
1038// ====================================================================
1039// CPhipps - WI_endDeathmatchStats
1040// Purpose: Deallocate dynamically allocated DM stats data
1041// Args: none
1042// Returns: void
1043//
1044
1045void WI_endDeathmatchStats(void)
1046{
1047 int i;
1048 for (i=0; i<MAXPLAYERS; i++)
1049 free(dm_frags[i]);
1050
1051 free(dm_frags); free(dm_totals);
1052}
1053
1054// ====================================================================
1055// WI_updateDeathmatchStats
1056// Purpose: Advance Deathmatch stats screen animation. Calculate
1057// frags for all players. Lots of noise and drama around
1058// the presentation.
1059// Args: none
1060// Returns: void
1061//
1062void WI_updateDeathmatchStats(void)
1063{
1064 int i;
1065 int j;
1066
1067 boolean stillticking;
1068
1069 WI_updateAnimatedBack();
1070
1071 if (acceleratestage && dm_state != 4) // still ticking
1072 {
1073 acceleratestage = 0;
1074
1075 for (i=0 ; i<MAXPLAYERS ; i++)
1076 {
1077 if (playeringame[i])
1078 {
1079 for (j=0 ; j<MAXPLAYERS ; j++)
1080 if (playeringame[j])
1081 dm_frags[i][j] = plrs[i].frags[j];
1082
1083 dm_totals[i] = WI_fragSum(i);
1084 }
1085 }
1086
1087
1088 S_StartSound(0, sfx_barexp); // bang
1089 dm_state = 4; // we're done with all 4 (or all we have to do)
1090 }
1091
1092
1093 if (dm_state == 2)
1094 {
1095 if (!(bcnt&3))
1096 S_StartSound(0, sfx_pistol); // noise while counting
1097
1098 stillticking = false;
1099
1100 for (i=0 ; i<MAXPLAYERS ; i++)
1101 {
1102 if (playeringame[i])
1103 {
1104 for (j=0 ; j<MAXPLAYERS ; j++)
1105 {
1106 if (playeringame[j]
1107 && dm_frags[i][j] != plrs[i].frags[j])
1108 {
1109 if (plrs[i].frags[j] < 0)
1110 dm_frags[i][j]--;
1111 else
1112 dm_frags[i][j]++;
1113
1114 if (dm_frags[i][j] > 999) // Ty 03/17/98 3-digit frag count
1115 dm_frags[i][j] = 999;
1116
1117 if (dm_frags[i][j] < -999)
1118 dm_frags[i][j] = -999;
1119
1120 stillticking = true;
1121 }
1122 }
1123 dm_totals[i] = WI_fragSum(i);
1124
1125 if (dm_totals[i] > 999)
1126 dm_totals[i] = 999;
1127
1128 if (dm_totals[i] < -999)
1129 dm_totals[i] = -999; // Ty 03/17/98 end 3-digit frag count
1130 }
1131 }
1132
1133 if (!stillticking)
1134 {
1135 S_StartSound(0, sfx_barexp);
1136 dm_state++;
1137 }
1138 }
1139 else if (dm_state == 4)
1140 {
1141 if (acceleratestage)
1142 {
1143 S_StartSound(0, sfx_slop);
1144
1145 if ( gamemode == commercial)
1146 WI_initNoState();
1147 else
1148 WI_initShowNextLoc();
1149 }
1150 }
1151 else if (dm_state & 1)
1152 {
1153 if (!--cnt_pause)
1154 {
1155 dm_state++;
1156 cnt_pause = TICRATE;
1157 }
1158 }
1159}
1160
1161
1162// ====================================================================
1163// WI_drawDeathmatchStats
1164// Purpose: Draw the stats on the screen in a matrix
1165// Args: none
1166// Returns: void
1167//
1168// proff/nicolas 09/20/98 -- changed for hi-res
1169// CPhipps - patch drawing updated
1170void WI_drawDeathmatchStats(void)
1171{
1172 int i;
1173 int j;
1174 int x;
1175 int y;
1176 int w;
1177
1178 int lh; // line height
1179 int halfface = V_NamePatchWidth(facebackp)/2;
1180
1181 lh = WI_SPACINGY;
1182
1183 WI_slamBackground();
1184
1185 // draw animated background
1186 WI_drawAnimatedBack();
1187 WI_drawLF();
1188
1189 // draw stat titles (top line)
1190 V_DrawNamePatch(DM_TOTALSX-V_NamePatchWidth(total)/2,
1191 DM_MATRIXY-WI_SPACINGY+10, FB, total, CR_DEFAULT, VPT_STRETCH);
1192
1193 V_DrawNamePatch(DM_KILLERSX, DM_KILLERSY, FB, killers, CR_DEFAULT, VPT_STRETCH);
1194 V_DrawNamePatch(DM_VICTIMSX, DM_VICTIMSY, FB, victims, CR_DEFAULT, VPT_STRETCH);
1195
1196 // draw P?
1197 x = DM_MATRIXX + DM_SPACINGX;
1198 y = DM_MATRIXY;
1199
1200 for (i=0 ; i<MAXPLAYERS ; i++)
1201 {
1202 if (playeringame[i]) {
1203 //int trans = playernumtotrans[i];
1204 V_DrawNamePatch(x-halfface, DM_MATRIXY - WI_SPACINGY,
1205 FB, facebackp, i ? CR_LIMIT+i : CR_DEFAULT,
1206 VPT_STRETCH | (i ? VPT_TRANS : 0));
1207 V_DrawNamePatch(DM_MATRIXX-halfface, y,
1208 FB, facebackp, i ? CR_LIMIT+i : CR_DEFAULT,
1209 VPT_STRETCH | (i ? VPT_TRANS : 0));
1210
1211 if (i == me)
1212 {
1213 V_DrawNamePatch(x-halfface, DM_MATRIXY - WI_SPACINGY,
1214 FB, bstar, CR_DEFAULT, VPT_STRETCH);
1215 V_DrawNamePatch(DM_MATRIXX-halfface, y,
1216 FB, star, CR_DEFAULT, VPT_STRETCH);
1217 }
1218 }
1219 x += DM_SPACINGX;
1220 y += WI_SPACINGY;
1221 }
1222
1223 // draw stats
1224 y = DM_MATRIXY+10;
1225 w = SHORT(num[0]->width);
1226
1227 for (i=0 ; i<MAXPLAYERS ; i++)
1228 {
1229 x = DM_MATRIXX + DM_SPACINGX;
1230
1231 if (playeringame[i])
1232 {
1233 for (j=0 ; j<MAXPLAYERS ; j++)
1234 {
1235 if (playeringame[j])
1236 WI_drawNum(x+w, y, dm_frags[i][j], 2);
1237
1238 x += DM_SPACINGX;
1239 }
1240 WI_drawNum(DM_TOTALSX+w, y, dm_totals[i], 2);
1241 }
1242 y += WI_SPACINGY;
1243 }
1244}
1245
1246
1247//
1248// Note: The term "Netgame" means a coop game
1249//
1250static short *cnt_kills;
1251static short *cnt_items;
1252static short *cnt_secret;
1253static short *cnt_frags;
1254static int dofrags;
1255static int ng_state;
1256
1257// ====================================================================
1258// CPhipps - WI_endNetgameStats
1259// Purpose: Clean up coop game stats
1260// Args: none
1261// Returns: void
1262//
1263static void WI_endNetgameStats(void)
1264{
1265 free(cnt_frags);
1266 free(cnt_secret);
1267 free(cnt_items);
1268 free(cnt_kills);
1269}
1270
1271// ====================================================================
1272// WI_initNetgameStats
1273// Purpose: Prepare for coop game stats
1274// Args: none
1275// Returns: void
1276//
1277void WI_initNetgameStats(void)
1278{
1279 int i;
1280
1281 state = StatCount;
1282 acceleratestage = 0;
1283 ng_state = 1;
1284
1285 cnt_pause = TICRATE;
1286
1287 // CPhipps - allocate these dynamically, blank with calloc
1288 cnt_kills = calloc(MAXPLAYERS, sizeof(*cnt_kills));
1289 cnt_items = calloc(MAXPLAYERS, sizeof(*cnt_items));
1290 cnt_secret= calloc(MAXPLAYERS, sizeof(*cnt_secret));
1291 cnt_frags = calloc(MAXPLAYERS, sizeof(*cnt_frags));
1292
1293 for (i=0 ; i<MAXPLAYERS ; i++)
1294 if (playeringame[i])
1295 dofrags += WI_fragSum(i);
1296
1297 dofrags = !!dofrags; // set to true or false - did we have frags?
1298
1299 WI_initAnimatedBack();
1300}
1301
1302
1303// ====================================================================
1304// WI_updateNetgameStats
1305// Purpose: Calculate coop stats as we display them with noise and fury
1306// Args: none
1307// Returns: void
1308// Comment: This stuff sure is complicated for what it does
1309//
1310void WI_updateNetgameStats(void)
1311{
1312 int i;
1313 int fsum;
1314
1315 boolean stillticking;
1316
1317 WI_updateAnimatedBack();
1318
1319 if (acceleratestage && ng_state != 10)
1320 {
1321 acceleratestage = 0;
1322
1323 for (i=0 ; i<MAXPLAYERS ; i++)
1324 {
1325 if (!playeringame[i])
1326 continue;
1327
1328 cnt_kills[i] = (plrs[i].skills * 100) / wbs->maxkills;
1329 cnt_items[i] = (plrs[i].sitems * 100) / wbs->maxitems;
1330
1331 // killough 2/22/98: Make secrets = 100% if maxsecret = 0:
1332 cnt_secret[i] = wbs->maxsecret ?
1333 (plrs[i].ssecret * 100) / wbs->maxsecret : 100;
1334 if (dofrags)
1335 cnt_frags[i] = WI_fragSum(i); // we had frags
1336 }
1337 S_StartSound(0, sfx_barexp); // bang
1338 ng_state = 10;
1339 }
1340
1341 if (ng_state == 2)
1342 {
1343 if (!(bcnt&3))
1344 S_StartSound(0, sfx_pistol); // pop
1345
1346 stillticking = false;
1347
1348 for (i=0 ; i<MAXPLAYERS ; i++)
1349 {
1350 if (!playeringame[i])
1351 continue;
1352
1353 cnt_kills[i] += 2;
1354
1355 if (cnt_kills[i] >= (plrs[i].skills * 100) / wbs->maxkills)
1356 cnt_kills[i] = (plrs[i].skills * 100) / wbs->maxkills;
1357 else
1358 stillticking = true; // still got stuff to tally
1359 }
1360
1361 if (!stillticking)
1362 {
1363 S_StartSound(0, sfx_barexp);
1364 ng_state++;
1365 }
1366 }
1367 else if (ng_state == 4)
1368 {
1369 if (!(bcnt&3))
1370 S_StartSound(0, sfx_pistol);
1371
1372 stillticking = false;
1373
1374 for (i=0 ; i<MAXPLAYERS ; i++)
1375 {
1376 if (!playeringame[i])
1377 continue;
1378
1379 cnt_items[i] += 2;
1380 if (cnt_items[i] >= (plrs[i].sitems * 100) / wbs->maxitems)
1381 cnt_items[i] = (plrs[i].sitems * 100) / wbs->maxitems;
1382 else
1383 stillticking = true;
1384 }
1385
1386 if (!stillticking)
1387 {
1388 S_StartSound(0, sfx_barexp);
1389 ng_state++;
1390 }
1391 }
1392 else if (ng_state == 6)
1393 {
1394 if (!(bcnt&3))
1395 S_StartSound(0, sfx_pistol);
1396
1397 stillticking = false;
1398
1399 for (i=0 ; i<MAXPLAYERS ; i++)
1400 {
1401 if (!playeringame[i])
1402 continue;
1403
1404 cnt_secret[i] += 2;
1405
1406 // killough 2/22/98: Make secrets = 100% if maxsecret = 0:
1407
1408 if (cnt_secret[i] >= (wbs->maxsecret ? (plrs[i].ssecret * 100) / wbs->maxsecret : compatibility_level < lxdoom_1_compatibility ? 0 : 100))
1409 cnt_secret[i] = wbs->maxsecret ? (plrs[i].ssecret * 100) / wbs->maxsecret : 100;
1410 else
1411 stillticking = true;
1412 }
1413
1414 if (!stillticking)
1415 {
1416 S_StartSound(0, sfx_barexp);
1417 ng_state += 1 + 2*!dofrags;
1418 }
1419 }
1420 else if (ng_state == 8)
1421 {
1422 if (!(bcnt&3))
1423 S_StartSound(0, sfx_pistol);
1424
1425 stillticking = false;
1426
1427 for (i=0 ; i<MAXPLAYERS ; i++)
1428 {
1429 if (!playeringame[i])
1430 continue;
1431
1432 cnt_frags[i] += 1;
1433
1434 if (cnt_frags[i] >= (fsum = WI_fragSum(i)))
1435 cnt_frags[i] = fsum;
1436 else
1437 stillticking = true;
1438 }
1439
1440 if (!stillticking)
1441 {
1442 S_StartSound(0, sfx_pldeth);
1443 ng_state++;
1444 }
1445 }
1446 else if (ng_state == 10)
1447 {
1448 if (acceleratestage)
1449 {
1450 S_StartSound(0, sfx_sgcock);
1451 if ( gamemode == commercial )
1452 WI_initNoState();
1453 else
1454 WI_initShowNextLoc();
1455 }
1456 }
1457 else if (ng_state & 1)
1458 {
1459 if (!--cnt_pause)
1460 {
1461 ng_state++;
1462 cnt_pause = TICRATE;
1463 }
1464 }
1465}
1466
1467
1468// ====================================================================
1469// WI_drawNetgameStats
1470// Purpose: Put the coop stats on the screen
1471// Args: none
1472// Returns: void
1473//
1474// proff/nicolas 09/20/98 -- changed for hi-res
1475// CPhipps - patch drawing updated
1476void WI_drawNetgameStats(void)
1477{
1478 int i;
1479 int x;
1480 int y;
1481 int pwidth = V_NamePatchWidth(percent);
1482 int fwidth = V_NamePatchWidth(facebackp);
1483
1484 WI_slamBackground();
1485
1486 // draw animated background
1487 WI_drawAnimatedBack();
1488
1489 WI_drawLF();
1490
1491 // draw stat titles (top line)
1492 V_DrawNamePatch(NG_STATSX+NG_SPACINGX-V_NamePatchWidth(kills),
1493 NG_STATSY, FB, kills, CR_DEFAULT, VPT_STRETCH);
1494
1495 V_DrawNamePatch(NG_STATSX+2*NG_SPACINGX-V_NamePatchWidth(items),
1496 NG_STATSY, FB, items, CR_DEFAULT, VPT_STRETCH);
1497
1498 V_DrawNamePatch(NG_STATSX+3*NG_SPACINGX-V_NamePatchWidth(secret),
1499 NG_STATSY, FB, secret, CR_DEFAULT, VPT_STRETCH);
1500
1501 if (dofrags)
1502 V_DrawNamePatch(NG_STATSX+4*NG_SPACINGX-V_NamePatchWidth(frags),
1503 NG_STATSY, FB, frags, CR_DEFAULT, VPT_STRETCH);
1504
1505 // draw stats
1506 y = NG_STATSY + V_NamePatchHeight(kills);
1507
1508 for (i=0 ; i<MAXPLAYERS ; i++)
1509 {
1510 //int trans = playernumtotrans[i];
1511 if (!playeringame[i])
1512 continue;
1513
1514 x = NG_STATSX;
1515 V_DrawNamePatch(x-fwidth, y, FB, facebackp,
1516 i ? CR_LIMIT+i : CR_DEFAULT,
1517 VPT_STRETCH | (i ? VPT_TRANS : 0));
1518
1519 if (i == me)
1520 V_DrawNamePatch(x-fwidth, y, FB, star, CR_DEFAULT, VPT_STRETCH);
1521
1522 x += NG_SPACINGX;
1523 WI_drawPercent(x-pwidth, y+10, cnt_kills[i]); x += NG_SPACINGX;
1524 WI_drawPercent(x-pwidth, y+10, cnt_items[i]); x += NG_SPACINGX;
1525 WI_drawPercent(x-pwidth, y+10, cnt_secret[i]); x += NG_SPACINGX;
1526
1527 if (dofrags)
1528 WI_drawNum(x, y+10, cnt_frags[i], -1);
1529
1530 y += WI_SPACINGY;
1531 }
1532
1533 if (y <= SP_TIMEY)
1534 // cph - show times in coop on the entering screen
1535 WI_drawTimeStats(plrs[me].stime / TICRATE, wbs->totaltimes / TICRATE, wbs->partime / TICRATE);
1536}
1537
1538static int sp_state;
1539
1540// ====================================================================
1541// WI_initStats
1542// Purpose: Get ready for single player stats
1543// Args: none
1544// Returns: void
1545// Comment: Seems like we could do all these stats in a more generic
1546// set of routines that weren't duplicated for dm, coop, sp
1547//
1548void WI_initStats(void)
1549{
1550 state = StatCount;
1551 acceleratestage = 0;
1552 sp_state = 1;
1553
1554 // CPhipps - allocate (awful code, I know, but saves changing it all) and initialise
1555 *(cnt_kills = malloc(sizeof(*cnt_kills))) =
1556 *(cnt_items = malloc(sizeof(*cnt_items))) =
1557 *(cnt_secret= malloc(sizeof(*cnt_secret))) = -1;
1558 cnt_time = cnt_par = cnt_total_time = -1;
1559 cnt_pause = TICRATE;
1560
1561 WI_initAnimatedBack();
1562}
1563
1564// ====================================================================
1565// WI_updateStats
1566// Purpose: Calculate solo stats
1567// Args: none
1568// Returns: void
1569//
1570void WI_updateStats(void)
1571{
1572 WI_updateAnimatedBack();
1573
1574 if (acceleratestage && sp_state != 10)
1575 {
1576 acceleratestage = 0;
1577 cnt_kills[0] = (plrs[me].skills * 100) / wbs->maxkills;
1578 cnt_items[0] = (plrs[me].sitems * 100) / wbs->maxitems;
1579
1580 // killough 2/22/98: Make secrets = 100% if maxsecret = 0:
1581 cnt_secret[0] = (wbs->maxsecret ?
1582 (plrs[me].ssecret * 100) / wbs->maxsecret : 100);
1583
1584 cnt_total_time = wbs->totaltimes / TICRATE;
1585 cnt_time = plrs[me].stime / TICRATE;
1586 cnt_par = wbs->partime / TICRATE;
1587 S_StartSound(0, sfx_barexp);
1588 sp_state = 10;
1589 }
1590
1591 if (sp_state == 2)
1592 {
1593 cnt_kills[0] += 2;
1594
1595 if (!(bcnt&3))
1596 S_StartSound(0, sfx_pistol);
1597
1598 if (cnt_kills[0] >= (plrs[me].skills * 100) / wbs->maxkills)
1599 {
1600 cnt_kills[0] = (plrs[me].skills * 100) / wbs->maxkills;
1601 S_StartSound(0, sfx_barexp);
1602 sp_state++;
1603 }
1604 }
1605 else if (sp_state == 4)
1606 {
1607 cnt_items[0] += 2;
1608
1609 if (!(bcnt&3))
1610 S_StartSound(0, sfx_pistol);
1611
1612 if (cnt_items[0] >= (plrs[me].sitems * 100) / wbs->maxitems)
1613 {
1614 cnt_items[0] = (plrs[me].sitems * 100) / wbs->maxitems;
1615 S_StartSound(0, sfx_barexp);
1616 sp_state++;
1617 }
1618 }
1619 else if (sp_state == 6)
1620 {
1621 cnt_secret[0] += 2;
1622
1623 if (!(bcnt&3))
1624 S_StartSound(0, sfx_pistol);
1625
1626 // killough 2/22/98: Make secrets = 100% if maxsecret = 0:
1627 if ((!wbs->maxsecret && compatibility_level < lxdoom_1_compatibility) ||
1628 cnt_secret[0] >= (wbs->maxsecret ?
1629 (plrs[me].ssecret * 100) / wbs->maxsecret : 100))
1630 {
1631 cnt_secret[0] = (wbs->maxsecret ?
1632 (plrs[me].ssecret * 100) / wbs->maxsecret : 100);
1633 S_StartSound(0, sfx_barexp);
1634 sp_state++;
1635 }
1636 }
1637 else if (sp_state == 8)
1638 {
1639 if (!(bcnt&3))
1640 S_StartSound(0, sfx_pistol);
1641
1642 cnt_time += 3;
1643
1644 if (cnt_time >= plrs[me].stime / TICRATE)
1645 cnt_time = plrs[me].stime / TICRATE;
1646
1647 cnt_total_time += 3;
1648
1649 if (cnt_total_time >= wbs->totaltimes / TICRATE)
1650 cnt_total_time = wbs->totaltimes / TICRATE;
1651
1652 cnt_par += 3;
1653
1654 if (cnt_par >= wbs->partime / TICRATE)
1655 {
1656 cnt_par = wbs->partime / TICRATE;
1657
1658 if ((cnt_time >= plrs[me].stime / TICRATE) && (compatibility_level < lxdoom_1_compatibility || cnt_total_time >= wbs->totaltimes / TICRATE))
1659 {
1660 S_StartSound(0, sfx_barexp);
1661 sp_state++;
1662 }
1663 }
1664 }
1665 else if (sp_state == 10)
1666 {
1667 if (acceleratestage)
1668 {
1669 S_StartSound(0, sfx_sgcock);
1670
1671 if (gamemode == commercial)
1672 WI_initNoState();
1673 else
1674 WI_initShowNextLoc();
1675 }
1676 }
1677 else if (sp_state & 1)
1678 {
1679 if (!--cnt_pause)
1680 {
1681 sp_state++;
1682 cnt_pause = TICRATE;
1683 }
1684 }
1685}
1686
1687
1688// ====================================================================
1689// WI_drawStats
1690// Purpose: Put the solo stats on the screen
1691// Args: none
1692// Returns: void
1693//
1694// proff/nicolas 09/20/98 -- changed for hi-res
1695// CPhipps - patch drawing updated
1696void WI_drawStats(void)
1697{
1698 // line height
1699 int lh;
1700
1701 lh = (3*SHORT(num[0]->height))/2;
1702
1703 WI_slamBackground();
1704
1705 // draw animated background
1706 WI_drawAnimatedBack();
1707
1708 WI_drawLF();
1709
1710 V_DrawNamePatch(SP_STATSX, SP_STATSY, FB, kills, CR_DEFAULT, VPT_STRETCH);
1711 WI_drawPercent(320 - SP_STATSX, SP_STATSY, cnt_kills[0]);
1712
1713 V_DrawNamePatch(SP_STATSX, SP_STATSY+lh, FB, items, CR_DEFAULT, VPT_STRETCH);
1714 WI_drawPercent(320 - SP_STATSX, SP_STATSY+lh, cnt_items[0]);
1715
1716 V_DrawNamePatch(SP_STATSX, SP_STATSY+2*lh, FB, sp_secret, CR_DEFAULT, VPT_STRETCH);
1717 WI_drawPercent(320 - SP_STATSX, SP_STATSY+2*lh, cnt_secret[0]);
1718
1719 WI_drawTimeStats(cnt_time, cnt_total_time, cnt_par);
1720}
1721
1722// ====================================================================
1723// WI_checkForAccelerate
1724// Purpose: See if the player has hit either the attack or use key
1725// or mouse button. If so we set acceleratestage to 1 and
1726// all those display routines above jump right to the end.
1727// Args: none
1728// Returns: void
1729//
1730void WI_checkForAccelerate(void)
1731{
1732 int i;
1733 player_t *player;
1734
1735 // check for button presses to skip delays
1736 for (i=0, player = players ; i<MAXPLAYERS ; i++, player++)
1737 {
1738 if (playeringame[i])
1739 {
1740 if (player->cmd.buttons & BT_ATTACK)
1741 {
1742 if (!player->attackdown)
1743 acceleratestage = 1;
1744 player->attackdown = true;
1745 }
1746 else
1747 player->attackdown = false;
1748
1749 if (player->cmd.buttons & BT_USE)
1750 {
1751 if (!player->usedown)
1752 acceleratestage = 1;
1753 player->usedown = true;
1754 }
1755 else
1756 player->usedown = false;
1757 }
1758 }
1759}
1760
1761// ====================================================================
1762// WI_Ticker
1763// Purpose: Do various updates every gametic, for stats, animation,
1764// checking that intermission music is running, etc.
1765// Args: none
1766// Returns: void
1767//
1768void WI_Ticker(void)
1769{
1770 // counter for general background animation
1771 bcnt++;
1772
1773 if (bcnt == 1)
1774 {
1775 // intermission music
1776 if ( gamemode == commercial )
1777 S_ChangeMusic(mus_dm2int, true);
1778 else
1779 S_ChangeMusic(mus_inter, true);
1780 }
1781
1782 WI_checkForAccelerate();
1783
1784 switch (state)
1785 {
1786 case StatCount:
1787 if (deathmatch) WI_updateDeathmatchStats();
1788 else if (netgame) WI_updateNetgameStats();
1789 else WI_updateStats();
1790 break;
1791
1792 case ShowNextLoc:
1793 WI_updateShowNextLoc();
1794 break;
1795
1796 case NoState:
1797 WI_updateNoState();
1798 break;
1799 }
1800}
1801
1802/* ====================================================================
1803 * WI_loadData
1804 * Purpose: Initialize intermission data such as background graphics,
1805 * patches, map names, etc.
1806 * Args: none
1807 * Returns: void
1808 *
1809 * CPhipps - modified for new wad lump handling.
1810 * - no longer preload most graphics, other funcs can use
1811 * them by name
1812 */
1813
1814void WI_loadData(void)
1815{
1816 int i;
1817 int j;
1818 char name[9]; // limited to 8 characters
1819 anim_t* a;
1820
1821 if (gamemode != commercial)
1822 {
1823 if (wbs->epsd < 3)
1824 {
1825 for (j=0;j<NUMANIMS[wbs->epsd];j++)
1826 {
1827 a = &anims[wbs->epsd][j];
1828 for (i=0;i<a->nanims;i++)
1829 {
1830 // MONDO HACK!
1831 if (wbs->epsd != 1 || j != 8)
1832 {
1833 // animations
1834 snprintf(name, sizeof(name),"WIA%d%s%d%s%d", wbs->epsd, (j/10>0?"":"0"), j,(i/10>0?"":"0"), i); //ANOTHER ROCKHACK
1835 //snprintf(name, sizeof(name),"WIA%d%.2d%.2d", wbs->epsd, j, i);
1836 a->p[i] = W_CacheLumpName(name);
1837 }
1838 else
1839 {
1840 // HACK ALERT!
1841 a->p[i] = anims[1][4].p[i];
1842 }
1843 }
1844 }
1845 }
1846 }
1847
1848 for (i=0;i<10;i++)
1849 {
1850 // numbers 0-9
1851 snprintf(name,sizeof(name),"WINUM%d", i);
1852 num[i] = W_CacheLumpName(name);
1853 }
1854}
1855
1856// ====================================================================
1857// WI_unloadData
1858// Purpose: Free up the space allocated during WI_loadData
1859// Args: none
1860// Returns: void
1861//
1862// CPhipps - reverse of WI_loadData, goes through the same lumps, but unlocking
1863void WI_unloadData(void)
1864{
1865 int i,j;
1866 char name[9]; // limited to 8 characters
1867
1868 // cph - unlock gamemode dependent stuff here
1869 if (gamemode != commercial) {
1870 if (wbs->epsd < 3) {
1871 for (j=0;j<NUMANIMS[wbs->epsd];j++) {
1872 anim_t* a = &anims[wbs->epsd][j];
1873 for (i=0; i<a->nanims; i++) {
1874 // MONDO HACK!
1875 if (wbs->epsd != 1 || j != 8) {
1876 // animations
1877 snprintf(name, sizeof(name),"WIA%d%s%d%s%d", wbs->epsd, (j/10>0?"":"0"), j,(i/10>0?"":"0"), i); //ANOTHER ROCKHACK
1878 //snprintf(name,sizeof(name), "WIA%d%.2d%.2d", wbs->epsd, j, i);
1879 W_UnlockLumpName(name);
1880 }
1881 }
1882 }
1883 }
1884 }
1885
1886 for (i=0;i<10;i++) {
1887 // numbers 0-9
1888 snprintf(name, sizeof(name),"WINUM%d", i);
1889 W_UnlockLumpName(name);
1890 }
1891}
1892
1893
1894// ====================================================================
1895// WI_Drawer
1896// Purpose: Call the appropriate stats drawing routine depending on
1897// what kind of game is being played (DM, coop, solo)
1898// Args: none
1899// Returns: void
1900//
1901void WI_Drawer (void)
1902{
1903 switch (state)
1904 {
1905 case StatCount:
1906 if (deathmatch)
1907 WI_drawDeathmatchStats();
1908 else if (netgame)
1909 WI_drawNetgameStats();
1910 else
1911 WI_drawStats();
1912 break;
1913
1914 case ShowNextLoc:
1915 WI_drawShowNextLoc();
1916 break;
1917
1918 case NoState:
1919 WI_drawNoState();
1920 break;
1921 }
1922}
1923
1924// ====================================================================
1925// WI_initVariables
1926// Purpose: Initialize the intermission information structure
1927// Note: wbstartstruct_t is defined in d_player.h
1928// Args: wbstartstruct -- pointer to the structure with the data
1929// Returns: void
1930//
1931void WI_initVariables(wbstartstruct_t* wbstartstruct)
1932{
1933
1934 wbs = wbstartstruct;
1935
1936#ifdef RANGECHECKING
1937 if (gamemode != commercial)
1938 {
1939 if ( gamemode == retail )
1940 RNGCHECK(wbs->epsd, 0, 3);
1941 else
1942 RNGCHECK(wbs->epsd, 0, 2);
1943 }
1944 else
1945 {
1946 RNGCHECK(wbs->last, 0, 8);
1947 RNGCHECK(wbs->next, 0, 8);
1948 }
1949 RNGCHECK(wbs->pnum, 0, MAXPLAYERS);
1950 RNGCHECK(wbs->pnum, 0, MAXPLAYERS);
1951#endif
1952
1953 acceleratestage = 0;
1954 cnt = bcnt = 0;
1955 firstrefresh = 1;
1956 me = wbs->pnum;
1957 plrs = wbs->plyr;
1958
1959 if (!wbs->maxkills)
1960 wbs->maxkills = 1; // probably only useful in MAP30
1961
1962 if (!wbs->maxitems)
1963 wbs->maxitems = 1;
1964
1965 if ( gamemode != retail )
1966 if (wbs->epsd > 2)
1967 wbs->epsd -= 3;
1968}
1969
1970// ====================================================================
1971// WI_Start
1972// Purpose: Call the various init routines
1973// Note: wbstartstruct_t is defined in d_player.h
1974// Args: wbstartstruct -- pointer to the structure with the
1975// intermission data
1976// Returns: void
1977//
1978void WI_Start(wbstartstruct_t* wbstartstruct)
1979{
1980 WI_initVariables(wbstartstruct);
1981 WI_loadData();
1982
1983 if (deathmatch)
1984 WI_initDeathmatchStats();
1985 else if (netgame)
1986 WI_initNetgameStats();
1987 else
1988 WI_initStats();
1989}
diff --git a/apps/plugins/doom/wi_stuff.h b/apps/plugins/doom/wi_stuff.h
new file mode 100644
index 0000000000..72c1d32d07
--- /dev/null
+++ b/apps/plugins/doom/wi_stuff.h
@@ -0,0 +1,62 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION:
28 * Intermission screens.
29 *
30 *-----------------------------------------------------------------------------*/
31
32#ifndef __WI_STUFF__
33#define __WI_STUFF__
34
35//#include "v_video.h"
36
37#include "doomdef.h"
38
39// States for the intermission
40
41typedef enum
42{
43 NoState = -1,
44 StatCount,
45 ShowNextLoc
46
47} stateenum_t;
48
49// Called by main loop, animate the intermission.
50void WI_Ticker (void);
51
52// Called by main loop,
53// draws the intermission directly into the screen buffer.
54void WI_Drawer (void);
55
56// Setup for an intermission screen.
57void WI_Start(wbstartstruct_t* wbstartstruct);
58
59// Release intermission screen memory
60void WI_End(void);
61
62#endif
diff --git a/apps/plugins/doom/z_bmalloc.c b/apps/plugins/doom/z_bmalloc.c
new file mode 100644
index 0000000000..47a9b4f892
--- /dev/null
+++ b/apps/plugins/doom/z_bmalloc.c
@@ -0,0 +1,117 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION:
28 * This is designed to be a fast allocator for small, regularly used block sizes
29 *-----------------------------------------------------------------------------
30 */
31#include "doomtype.h"
32#include "z_zone.h"
33#include "z_bmalloc.h"
34#include "i_system.h"
35#include "rockmacros.h"
36
37typedef struct bmalpool_s {
38 struct bmalpool_s *nextpool;
39 size_t blocks;
40 byte used[0];
41} bmalpool_t;
42
43inline static void* getelem(bmalpool_t *p, size_t size, size_t n)
44{
45 return (((byte*)p) + sizeof(bmalpool_t) + sizeof(byte)*(p->blocks) + size*n);
46}
47
48inline static int iselem(const bmalpool_t *pool, size_t size, const void* p)
49{
50 // CPhipps - need portable # of bytes between pointers
51 int dif = (const char*)p - (const char*)pool;
52
53 dif -= sizeof(bmalpool_t);
54 dif -= pool->blocks;
55 if (dif<0) return -1;
56 dif /= size;
57 return (((size_t)dif >= pool->blocks) ? -1 : dif);
58}
59
60enum { unused_block = 0, used_block = 1};
61
62void* Z_BMalloc(struct block_memory_alloc_s *pzone)
63{
64 register bmalpool_t **pool = (bmalpool_t **)&(pzone->firstpool);
65 while (*pool != NULL) {
66 byte *p = memchr((*pool)->used, unused_block, (*pool)->blocks); // Scan for unused marker
67 if (p) {
68 int n = p - (*pool)->used;
69#ifdef SIMPLECHECKS
70 if ((n<0) || ((size_t)n>=(*pool)->blocks))
71 I_Error("Z_BMalloc: memchr returned pointer outside of array");
72#endif
73 (*pool)->used[n] = used_block;
74 return getelem(*pool, pzone->size, n);
75 } else
76 pool = &((*pool)->nextpool);
77 }
78 {
79 // Nothing available, must allocate a new pool
80 bmalpool_t *newpool;
81
82 // CPhipps: Allocate new memory, initialised to 0
83
84 *pool = newpool = Z_Calloc(sizeof(*newpool) + (sizeof(byte) + pzone->size)*(pzone->perpool),
85 1, pzone->tag, NULL);
86 newpool->nextpool = NULL; // NULL = (void*)0 so this is redundant
87
88 // Return element 0 from this pool to satisfy the request
89 newpool->used[0] = used_block;
90 newpool->blocks = pzone->perpool;
91 return getelem(newpool, pzone->size, 0);
92 }
93}
94
95void Z_BFree(struct block_memory_alloc_s *pzone, void* p)
96{
97 register bmalpool_t **pool = (bmalpool_t**)&(pzone->firstpool);
98
99 while (*pool != NULL) {
100 int n = iselem(*pool, pzone->size, p);
101 if (n >= 0) {
102#ifdef SIMPLECHECKS
103 if ((*pool)->used[n] == unused_block)
104 I_Error("Z_BFree: Refree in zone %s", pzone->desc);
105#endif
106 (*pool)->used[n] = unused_block;
107 if (memchr(((*pool)->used), used_block, (*pool)->blocks) == NULL) {
108 // Block is all unused, can be freed
109 bmalpool_t *oldpool = *pool;
110 *pool = (*pool)->nextpool;
111 Z_Free(oldpool);
112 }
113 return;
114 } else pool = &((*pool)->nextpool);
115 }
116 I_Error("Z_BFree: Free not in zone %s", pzone->desc);
117}
diff --git a/apps/plugins/doom/z_bmalloc.h b/apps/plugins/doom/z_bmalloc.h
new file mode 100644
index 0000000000..0c454fcff9
--- /dev/null
+++ b/apps/plugins/doom/z_bmalloc.h
@@ -0,0 +1,51 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION:
28 * Block memory allocator
29 * This is designed to be a fast allocator for small, regularly used block sizes
30 *-----------------------------------------------------------------------------*/
31#include "rockmacros.h"
32
33struct block_memory_alloc_s {
34 void *firstpool;
35 size_t size;
36 size_t perpool;
37 int tag;
38 const char *desc;
39};
40
41#define DECLARE_BLOCK_MEMORY_ALLOC_ZONE(name) extern struct block_memory_alloc_s name
42#define IMPLEMENT_BLOCK_MEMORY_ALLOC_ZONE(name, size, tag, num, desc) \
43struct block_memory_alloc_s name = { NULL, size, num, tag, desc}
44#define NULL_BLOCK_MEMORY_ALLOC_ZONE(name) name.firstpool = NULL
45
46void* Z_BMalloc(struct block_memory_alloc_s *pzone);
47
48inline static void* Z_BCalloc(struct block_memory_alloc_s *pzone)
49{ void *p = Z_BMalloc(pzone); memset(p,0,pzone->size); return p; }
50
51void Z_BFree(struct block_memory_alloc_s *pzone, void* p);
diff --git a/apps/plugins/doom/z_zone.c b/apps/plugins/doom/z_zone.c
new file mode 100644
index 0000000000..036c995743
--- /dev/null
+++ b/apps/plugins/doom/z_zone.c
@@ -0,0 +1,666 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION:
28 * Zone Memory Allocation. Neat.
29 *
30 * Neat enough to be rewritten by Lee Killough...
31 *
32 * Must not have been real neat :)
33 *
34 * Made faster and more general, and added wrappers for all of Doom's
35 * memory allocation functions, including malloc() and similar functions.
36 * Added line and file numbers, in case of error. Added performance
37 * statistics and tunables.
38 *-----------------------------------------------------------------------------
39 */
40
41#include "z_zone.h"
42#include "z_bmalloc.h"
43#include "doomdef.h"
44#include "i_system.h"
45#include "rockmacros.h"
46#include "m_argv.h"
47
48// Tunables
49
50// Alignment of zone memory (benefit may be negated by HEADER_SIZE, CHUNK_SIZE)
51#define CACHE_ALIGN 32
52
53// Minimum chunk size at which blocks are allocated
54#define CHUNK_SIZE 32
55
56// Minimum size a block must be to become part of a split
57#define MIN_BLOCK_SPLIT (1024)
58
59// Minimum RAM machine is assumed to have
60/* cph - Select zone size. 6megs is usable, but with the SDL version
61 * storing sounds in the zone, 8 is more sensible */
62#define MIN_RAM (8*1024*1024)
63
64// Amount to subtract when retrying failed attempts to allocate initial pool
65#define RETRY_AMOUNT (256*1024)
66
67// signature for block header
68#define ZONEID 0x931d4a11
69
70// Number of mallocs & frees kept in history buffer (must be a power of 2)
71#define ZONE_HISTORY 4
72
73// End Tunables
74
75typedef struct memblock {
76
77#ifdef ZONEIDCHECK
78 unsigned id;
79#endif
80
81 struct memblock *next,*prev;
82 size_t size;
83 void **user;
84 unsigned char tag,vm;
85
86#ifdef INSTRUMENTED
87 unsigned short extra;
88 const char *file;
89 int line;
90#endif
91
92} memblock_t;
93
94/* size of block header
95 * cph - base on sizeof(memblock_t), which can be larger than CHUNK_SIZE on
96 * 64bit architectures */
97static const size_t HEADER_SIZE IDATA_ATTR= (sizeof(memblock_t)+CHUNK_SIZE-1) & ~(CHUNK_SIZE-1);
98
99static memblock_t *rover IBSS_ATTR; // roving pointer to memory blocks
100static memblock_t *zone IBSS_ATTR; // pointer to first block
101static memblock_t *zonebase IBSS_ATTR; // pointer to entire zone memory
102static size_t zonebase_size IBSS_ATTR; // zone memory allocated size
103
104#ifdef INSTRUMENTED
105
106// statistics for evaluating performance
107static size_t free_memory;
108static size_t active_memory;
109static size_t purgable_memory;
110static size_t inactive_memory;
111static size_t virtual_memory;
112
113static void Z_PrintStats(void) // Print allocation statistics
114{
115 unsigned long total_memory = free_memory + active_memory +
116 purgable_memory + inactive_memory +
117 virtual_memory;
118 double s = 100.0 / total_memory;
119
120 doom_printf("%-5u\t%6.01f%%\tstatic\n"
121 "%-5u\t%6.01f%%\tpurgable\n"
122 "%-5u\t%6.01f%%\tfree\n"
123 "%-5u\t%6.01f%%\tfragmentary\n"
124 "%-5u\t%6.01f%%\tvirtual\n"
125 "%-5lu\t\ttotal\n",
126 active_memory,
127 active_memory*s,
128 purgable_memory,
129 purgable_memory*s,
130 free_memory,
131 free_memory*s,
132 inactive_memory,
133 inactive_memory*s,
134 virtual_memory,
135 virtual_memory*s,
136 total_memory
137 );
138}
139
140#ifdef HEAPDUMP
141void W_PrintLump(FILE* fp, void* p);
142
143void Z_DumpMemory(void)
144{
145 static int dump;
146 memblock_t* block = zone;
147 char buf[80];
148 FILE* fp;
149 size_t total_cache = 0, total_free = 0, total_malloc = 0;
150
151 sprintf(buf, "memdump.%d", dump++);
152 fp = fopen(buf, "w");
153 do {
154 switch (block->tag) {
155 case PU_FREE:
156 fprintf(fp, "free %d\n", block->size);
157 total_free += block->size;
158 break;
159 case PU_CACHE:
160 fprintf(fp, "cache %s:%d:%d\n", block->file, block->line, block->size);
161 total_cache += block->size;
162 break;
163 case PU_LEVEL:
164 fprintf(fp, "level %s:%d:%d\n", block->file, block->line, block->size);
165 total_malloc += block->size;
166 break;
167 default:
168 fprintf(fp, "malloc %s:%d:%d", block->file, block->line, block->size);
169 total_malloc += block->size;
170 if (!strcmp(block->file,"w_wad.c")) W_PrintLump(fp, (char*)block + HEADER_SIZE);
171 fputc('\n', fp);
172 break;
173 }
174 block=block->next;
175 } while (block != zone);
176 fprintf(fp, "malloc %d, cache %d, free %d, total %d\n",
177 total_malloc, total_cache, total_free,
178 total_malloc + total_cache + total_free);
179 fclose(fp);
180}
181#endif
182#endif
183
184#ifdef INSTRUMENTED
185
186// killough 4/26/98: Add history information
187
188enum {malloc_history, free_history, NUM_HISTORY_TYPES};
189
190static const char *file_history[NUM_HISTORY_TYPES][ZONE_HISTORY];
191static int line_history[NUM_HISTORY_TYPES][ZONE_HISTORY];
192static int history_index[NUM_HISTORY_TYPES];
193static const char *const desc[NUM_HISTORY_TYPES] = {"malloc()'s", "free()'s"};
194
195void Z_DumpHistory(char *buf)
196{
197 int i,j;
198 char s[1024];
199 strcat(buf,"\n");
200 for (i=0;i<NUM_HISTORY_TYPES;i++)
201 {
202 sprintf(s,"\nLast several %s:\n\n", desc[i]);
203 strcat(buf,s);
204 for (j=0; j<ZONE_HISTORY; j++)
205 {
206 int k = (history_index[i]-j-1) & (ZONE_HISTORY-1);
207 if (file_history[i][k])
208 {
209 sprintf(s, "File: %s, Line: %d\n", file_history[i][k],
210 line_history[i][k]);
211 strcat(buf,s);
212 }
213 }
214 }
215}
216#else
217
218void Z_DumpHistory(char *buf)
219{
220 (void)buf;
221}
222
223#endif
224
225void Z_Close(void)
226{
227// (free)(zonebase);
228 zone = rover = zonebase = NULL;
229}
230
231void Z_Init(void)
232{
233 unsigned int size;
234#ifdef INSTRUMENTED
235 if (!(HEADER_SIZE >= sizeof(memblock_t) && MIN_RAM > LEAVE_ASIDE))
236 I_Error("Z_Init: Sanity check failed");
237#endif
238
239// atexit(Z_Close); // exit handler
240
241 // Allocate the memory
242
243 zonebase=rb->plugin_get_audio_buffer(&size);
244 size-=2*(HEADER_SIZE + CACHE_ALIGN); // Leave space for header and CACHE_ALIGN
245 size = (size+CHUNK_SIZE-1) & ~(CHUNK_SIZE-1); // round to chunk size
246 size += HEADER_SIZE + CACHE_ALIGN;
247
248 zonebase_size=size;
249
250 printf("Z_Init: Allocated %dKb zone memory\n", (long unsigned)size >> 10);
251
252 // Align on cache boundary
253
254 zone = (memblock_t *) ((char *) zonebase + CACHE_ALIGN -
255 ((unsigned) zonebase & (CACHE_ALIGN-1)));
256
257 rover = zone; // Rover points to base of zone mem
258 zone->next = zone->prev = zone; // Single node
259 zone->size = size; // All memory in one block
260 zone->tag = PU_FREE; // A free block
261 zone->vm = 0;
262
263#ifdef ZONEIDCHECK
264 zone->id = 0;
265#endif
266
267#ifdef INSTRUMENTED
268 free_memory = size;
269 inactive_memory = zonebase_size - size;
270 active_memory = purgable_memory = virtual_memory = 0;
271#endif
272}
273
274/* Z_Malloc
275 * You can pass a NULL user if the tag is < PU_PURGELEVEL.
276 *
277 * cph - the algorithm here was a very simple first-fit round-robin
278 * one - just keep looping around, freeing everything we can until
279 * we get a large enough space
280 *
281 * This has been changed now; we still do the round-robin first-fit,
282 * but we only free the blocks we actually end up using; we don't
283 * free all the stuff we just pass on the way.
284 */
285
286void *(Z_Malloc)(size_t size, int tag, void **user
287#ifdef INSTRUMENTED
288 , const char *file, int line
289#endif
290 )
291{
292 register memblock_t *block;
293 memblock_t *start, *first_of_free;
294 register size_t contig_free;
295
296#ifdef INSTRUMENTED
297 size_t size_orig = size;
298#ifdef CHECKHEAP
299 Z_CheckHeap();
300#endif
301
302 file_history[malloc_history][history_index[malloc_history]] = file;
303 line_history[malloc_history][history_index[malloc_history]++] = line;
304 history_index[malloc_history] &= ZONE_HISTORY-1;
305#endif
306
307#ifdef ZONEIDCHECK
308 if (tag >= PU_PURGELEVEL && !user)
309 I_Error ("Z_Malloc: An owner is required for purgable blocks"
310#ifdef INSTRUMENTED
311 "Source: %s:%d", file, line
312#endif
313 );
314#endif
315
316 if (!size)
317 return user ? *user = NULL : NULL; // malloc(0) returns NULL
318
319 size = (size+CHUNK_SIZE-1) & ~(CHUNK_SIZE-1); // round to chunk size
320
321 block = rover;
322
323 if (block->prev->tag == PU_FREE)
324 block = block->prev;
325
326 start = block;
327 first_of_free = NULL; contig_free = 0;
328
329 do {
330 /* If we just wrapped, we're not contiguous with the previous block */
331 if (block == zone) contig_free = 0;
332
333 if (block->tag < PU_PURGELEVEL && block->tag != PU_FREE) {
334 /* Not free(able), so no free space here */
335 contig_free = 0;
336 } else {
337 /* Add to contiguous chunk of free space */
338 if (!contig_free) first_of_free = block;
339 contig_free += block->size;
340
341 /* First fit */
342 if (contig_free >= size)
343 break;
344 }
345 }
346 while ((block = block->next) != start); // detect cycles as failure
347
348 if (contig_free >= size) {
349 /* We have a block of free(able) memory on the heap which will suffice */
350 block = first_of_free;
351
352 /* If the previous block is adjacent and free, step back and include it */
353 if (block != zone && block->prev->tag == PU_FREE)
354 block = block->prev;
355
356 /* Free current block if needed */
357 if (block->tag != PU_FREE) Z_Free((char *) block + HEADER_SIZE);
358
359 /* Note: guaranteed that block->prev is either
360 * not free or not contiguous
361 *
362 * At every step, block->next must be not free, else it would
363 * have been merged with our block
364 * No range check needed because we know it works by the previous loop */
365 while (block->size < size)
366 Z_Free((char *)(block->next) + HEADER_SIZE);
367
368 /* Now, carve up the block */
369 {
370 size_t extra = block->size - size;
371 if (extra >= MIN_BLOCK_SPLIT + HEADER_SIZE) {
372 memblock_t *newb = (memblock_t *)((char *) block +
373 HEADER_SIZE + size);
374
375 (newb->next = block->next)->prev = newb;
376 (newb->prev = block)->next = newb; // Split up block
377 block->size = size;
378 newb->size = extra - HEADER_SIZE;
379 newb->tag = PU_FREE;
380 newb->vm = 0;
381
382#ifdef INSTRUMENTED
383 inactive_memory += HEADER_SIZE;
384 free_memory -= HEADER_SIZE;
385#endif
386 }
387
388 rover = block->next; // set roving pointer for next search
389
390#ifdef INSTRUMENTED
391 inactive_memory += block->extra = block->size - size_orig;
392 if (tag >= PU_PURGELEVEL)
393 purgable_memory += size_orig;
394 else
395 active_memory += size_orig;
396 free_memory -= block->size;
397#endif
398 }
399 } else { // We don't have enough contiguous free blocks
400 I_Error ("Z_Malloc: Failure trying to allocate %d bytes",(unsigned long) size);
401 rb->sleep(300);
402 }
403
404#ifdef INSTRUMENTED
405 block->file = file;
406 block->line = line;
407#endif
408
409#ifdef ZONEIDCHECK
410 block->id = ZONEID; // signature required in block header
411#endif
412 block->tag = tag; // tag
413 block->user = user; // user
414 block = (memblock_t *)((char *) block + HEADER_SIZE);
415 if (user) // if there is a user
416 *user = block; // set user to point to new block
417
418#ifdef INSTRUMENTED
419 Z_PrintStats(); // print memory allocation stats
420 // scramble memory -- weed out any bugs
421 memset(block, gametic & 0xff, size);
422#endif
423 return block;
424}
425
426void (Z_Free)(void *p
427#ifdef INSTRUMENTED
428 , const char *file, int line
429#endif
430 )
431{
432#ifdef INSTRUMENTED
433#ifdef CHECKHEAP
434 Z_CheckHeap();
435#endif
436 file_history[free_history][history_index[free_history]] = file;
437 line_history[free_history][history_index[free_history]++] = line;
438 history_index[free_history] &= ZONE_HISTORY-1;
439#endif
440
441 if (p)
442 {
443 memblock_t *other, *block = (memblock_t *)((char *) p - HEADER_SIZE);
444
445#ifdef ZONEIDCHECK
446 if (block->id != ZONEID)
447 I_Error("Z_Free: freed a pointer without ZONEID"
448#ifdef INSTRUMENTED
449 "\nSource: %s:%d"
450 "\nSource of malloc: %s:%d"
451 , file, line, block->file, block->line
452#endif
453 );
454 block->id = 0; // Nullify id so another free fails
455#endif
456
457#ifdef INSTRUMENTED
458 /* scramble memory -- weed out any bugs */
459 memset(p, gametic & 0xff, block->size);
460#endif
461
462 if (block->user) // Nullify user if one exists
463 *block->user = NULL;
464
465 {
466
467#ifdef INSTRUMENTED
468 free_memory += block->size;
469 inactive_memory -= block->extra;
470 if (block->tag >= PU_PURGELEVEL)
471 purgable_memory -= block->size - block->extra;
472 else
473 active_memory -= block->size - block->extra;
474#endif
475
476 block->tag = PU_FREE; // Mark block freed
477
478 if (block != zone)
479 {
480 other = block->prev; // Possibly merge with previous block
481 if (other->tag == PU_FREE)
482 {
483 if (rover == block) // Move back rover if it points at block
484 rover = other;
485 (other->next = block->next)->prev = other;
486 other->size += block->size + HEADER_SIZE;
487 block = other;
488
489#ifdef INSTRUMENTED
490 inactive_memory -= HEADER_SIZE;
491 free_memory += HEADER_SIZE;
492#endif
493 }
494 }
495
496 other = block->next; // Possibly merge with next block
497 if (other->tag == PU_FREE && other != zone)
498 {
499 if (rover == other) // Move back rover if it points at next block
500 rover = block;
501 (block->next = other->next)->prev = block;
502 block->size += other->size + HEADER_SIZE;
503
504#ifdef INSTRUMENTED
505 inactive_memory -= HEADER_SIZE;
506 free_memory += HEADER_SIZE;
507#endif
508 }
509 }
510
511#ifdef INSTRUMENTED
512 Z_PrintStats(); // print memory allocation stats
513#endif
514 }
515}
516
517void (Z_FreeTags)(int lowtag, int hightag
518#ifdef INSTRUMENTED
519 , const char *file, int line
520#endif
521 )
522{
523 /* cph - move rover to start of zone; we like to encourage static
524 * data to stay in one place, at the start of the heap
525 */
526 memblock_t *block = rover = zone;
527
528#ifdef HEAPDUMP
529 Z_DumpMemory();
530#endif
531
532 if (lowtag <= PU_FREE)
533 lowtag = PU_FREE+1;
534
535 do // Scan through list, searching for tags in range
536 if (block->tag >= lowtag && block->tag <= hightag)
537 {
538 memblock_t *prev = block->prev, *cur = block;
539#ifdef INSTRUMENTED
540 (Z_Free)((char *) block + HEADER_SIZE, file, line);
541#else
542 (Z_Free)((char *) block + HEADER_SIZE);
543#endif
544 /* cph - be more careful here, we were skipping blocks!
545 * If the current block was not merged with the previous,
546 * cur is still a valid pointer, prev->next == cur, and cur is
547 * already free so skip to the next.
548 * If the current block was merged with the previous,
549 * the next block to analyse is prev->next.
550 * Note that the while() below does the actual step forward
551 */
552 block = (prev->next == cur) ? cur : prev;
553 }
554 while ((block=block->next) != zone);
555}
556
557void (Z_ChangeTag)(void *ptr, int tag
558#ifdef INSTRUMENTED
559 , const char *file, int line
560#endif
561 )
562{
563 memblock_t *block = (memblock_t *)((char *) ptr - HEADER_SIZE);
564
565#ifdef INSTRUMENTED
566#ifdef CHECKHEAP
567 Z_CheckHeap();
568#endif
569#endif
570
571#ifdef ZONEIDCHECK
572 if (block->id != ZONEID)
573 I_Error ("Z_ChangeTag: freed a pointer without ZONEID"
574#ifdef INSTRUMENTED
575 "\nSource: %s:%d"
576 "\nSource of malloc: %s:%d"
577 , file, line, block->file, block->line
578#endif
579 );
580
581 if (tag >= PU_PURGELEVEL && !block->user)
582 I_Error ("Z_ChangeTag: an owner is required for purgable blocks\n"
583#ifdef INSTRUMENTED
584 "Source: %s:%d"
585 "\nSource of malloc: %s:%d"
586 , file, line, block->file, block->line
587#endif
588 );
589
590#endif // ZONEIDCHECK
591
592 {
593#ifdef INSTRUMENTED
594 if (block->tag < PU_PURGELEVEL && tag >= PU_PURGELEVEL)
595 {
596 active_memory -= block->size - block->extra;
597 purgable_memory += block->size - block->extra;
598 }
599 else
600 if (block->tag >= PU_PURGELEVEL && tag < PU_PURGELEVEL)
601 {
602 active_memory += block->size - block->extra;
603 purgable_memory -= block->size - block->extra;
604 }
605#endif
606 }
607 block->tag = tag;
608}
609
610void *(Z_Realloc)(void *ptr, size_t n, int tag, void **user
611#ifdef INSTRUMENTED
612 , const char *file, int line
613#endif
614 )
615{
616 void *p = (Z_Malloc)(n, tag, user DA(file, line));
617 if (ptr)
618 {
619 memblock_t *block = (memblock_t *)((char *) ptr - HEADER_SIZE);
620 memcpy(p, ptr, n <= block->size ? n : block->size);
621 (Z_Free)(ptr DA(file, line));
622 if (user) // in case Z_Free nullified same user
623 *user=p;
624 }
625 return p;
626}
627
628void *(Z_Calloc)(size_t n1, size_t n2, int tag, void **user
629#ifdef INSTRUMENTED
630 , const char *file, int line
631#endif
632 )
633{
634 return
635 (n1*=n2) ? memset((Z_Malloc)(n1, tag, user DA(file, line)), 0, n1) : NULL;
636}
637
638char *(Z_Strdup)(const char *s, int tag, void **user
639#ifdef INSTRUMENTED
640 , const char *file, int line
641#endif
642 )
643{
644 return strcpy((Z_Malloc)(strlen(s)+1, tag, user DA(file, line)), s);
645}
646
647void (Z_CheckHeap)(
648#ifdef INSTRUMENTED
649 const char *file, int line
650#endif
651)
652{
653 memblock_t *block = zone; // Start at base of zone mem
654 do // Consistency check (last node treated special)
655 if ((block->next != zone &&
656 (memblock_t *)((char *) block+HEADER_SIZE+block->size) != block->next)
657 || block->next->prev != block || block->prev->next != block)
658 I_Error("Z_ChkHp: B size %d touch %d\n", block+HEADER_SIZE+block->size, block->next
659#ifdef INSTRUMENTED
660 "Source: %s:%d"
661 "\nSource of offending block: %s:%d"
662 , file, line, block->file, block->line
663#endif
664 );
665 while ((block=block->next) != zone);
666}
diff --git a/apps/plugins/doom/z_zone.h b/apps/plugins/doom/z_zone.h
new file mode 100644
index 0000000000..6ab9bba106
--- /dev/null
+++ b/apps/plugins/doom/z_zone.h
@@ -0,0 +1,117 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION:
28 * Zone Memory Allocation, perhaps NeXT ObjectiveC inspired.
29 * Remark: this was the only stuff that, according
30 * to John Carmack, might have been useful for
31 * Quake.
32 *
33 * Rewritten by Lee Killough, though, since it was not efficient enough.
34 *
35 *---------------------------------------------------------------------*/
36
37#ifndef __Z_ZONE__
38#define __Z_ZONE__
39
40#ifndef __GNUC__
41#define __attribute__(x)
42#endif
43
44// Include system definitions so that prototypes become
45// active before macro replacements below are in effect.
46
47#include "plugin.h"
48
49// ZONE MEMORY
50// PU - purge tags.
51
52enum {PU_FREE, PU_STATIC, PU_SOUND, PU_MUSIC, PU_LEVEL, PU_LEVSPEC, PU_CACHE,
53 /* Must always be last -- killough */ PU_MAX};
54
55#define PU_PURGELEVEL PU_CACHE /* First purgable tag's level */
56
57#ifdef INSTRUMENTED
58#define DA(x,y) ,x,y
59#define DAC(x,y) x,y
60#else
61#define DA(x,y)
62#define DAC(x,y) void
63#endif
64
65void *(Z_Malloc)(size_t size, int tag, void **ptr DA(const char *, int));
66void (Z_Free)(void *ptr DA(const char *, int));
67void (Z_FreeTags)(int lowtag, int hightag DA(const char *, int));
68void (Z_ChangeTag)(void *ptr, int tag DA(const char *, int));
69void (Z_Init)(void);
70void Z_Close(void);
71void *(Z_Calloc)(size_t n, size_t n2, int tag, void **user DA(const char *, int));
72void *(Z_Realloc)(void *p, size_t n, int tag, void **user DA(const char *, int));
73char *(Z_Strdup)(const char *s, int tag, void **user DA(const char *, int));
74void (Z_CheckHeap)(DAC(const char *,int)); // killough 3/22/98: add file/line info
75void Z_DumpHistory(char *);
76
77#ifdef INSTRUMENTED
78/* cph - save space if not debugging, don't require file
79 * and line to memory calls */
80#define Z_Free(a) (Z_Free) (a, __FILE__,__LINE__)
81#define Z_FreeTags(a,b) (Z_FreeTags) (a,b, __FILE__,__LINE__)
82#define Z_ChangeTag(a,b) (Z_ChangeTag)(a,b, __FILE__,__LINE__)
83#define Z_Malloc(a,b,c) (Z_Malloc) (a,b,c, __FILE__,__LINE__)
84#define Z_Strdup(a,b,c) (Z_Strdup) (a,b,c, __FILE__,__LINE__)
85#define Z_Calloc(a,b,c,d) (Z_Calloc) (a,b,c,d,__FILE__,__LINE__)
86#define Z_Realloc(a,b,c,d) (Z_Realloc) (a,b,c,d,__FILE__,__LINE__)
87#define Z_CheckHeap() (Z_CheckHeap)(__FILE__,__LINE__)
88#endif
89
90/* cphipps 2001/11/18 -
91 * If we're using memory mapped file access to WADs, we won't need to maintain
92 * our own heap. So we *could* let "normal" malloc users use the libc malloc
93 * directly, for efficiency. Except we do need a wrapper to handle out of memory
94 * errors... damn, ok, we'll leave it for now.
95 */
96
97#undef malloc
98#undef free
99#undef realloc
100#undef calloc
101#undef strdup
102
103#define malloc(n) Z_Malloc(n,PU_STATIC,0)
104#define free(p) Z_Free(p)
105#define realloc(p,n) Z_Realloc(p,n,PU_STATIC,0)
106#define calloc(n1,n2) Z_Calloc(n1,n2,PU_STATIC,0)
107#undef strdup
108
109char *strdup(const char *s);
110
111#define strdup(s) Z_Strdup(s,PU_STATIC,0)
112
113void Z_ZoneHistory(char *);
114
115extern size_t zone_size;
116
117#endif