1
0
Fork 0
forked from len0rd/rockbox

Patch #2969 - Doom! Currently only working on the H300.

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@9312 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Dave Chapman 2006-03-28 15:44:01 +00:00
parent fff7d6157d
commit 47f4a458d6
130 changed files with 65584 additions and 1 deletions

View file

@ -67,6 +67,8 @@
#include "bmp.h" #include "bmp.h"
#endif #endif
#include "backdrop.h"
#ifdef HAVE_REMOTE_LCD #ifdef HAVE_REMOTE_LCD
#include "lcd-remote.h" #include "lcd-remote.h"
#endif #endif
@ -409,6 +411,10 @@ static const struct plugin_api rockbox_api = {
i2c_end, i2c_end,
i2c_write, i2c_write,
#endif #endif
vsnprintf,
memchr,
load_main_backdrop
}; };
int plugin_load(const char* plugin, void* parameter) int plugin_load(const char* plugin, void* parameter)

View file

@ -29,6 +29,7 @@
#define MEM 2 #define MEM 2
#endif #endif
#include <stdarg.h>
#include <stdbool.h> #include <stdbool.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@ -101,7 +102,7 @@
#define PLUGIN_MAGIC 0x526F634B /* RocK */ #define PLUGIN_MAGIC 0x526F634B /* RocK */
/* increase this every time the api struct changes */ /* increase this every time the api struct changes */
#define PLUGIN_API_VERSION 16 #define PLUGIN_API_VERSION 17
/* update this to latest version if a change to the api struct breaks /* update this to latest version if a change to the api struct breaks
backwards compatibility (and please take the opportunity to sort in any backwards compatibility (and please take the opportunity to sort in any
@ -479,6 +480,10 @@ struct plugin_api {
void (*i2c_end)(void); void (*i2c_end)(void);
int (*i2c_write)(int address, unsigned char* buf, int count ); int (*i2c_write)(int address, unsigned char* buf, int count );
#endif #endif
int (*vsnprintf)(char *buf, int size, const char *fmt, va_list ap);
void *(*memchr)(const void *s1, int c, size_t n);
bool (*load_main_backdrop)(char* filename);
}; };
/* plugin header */ /* plugin header */

View file

@ -84,6 +84,11 @@ ifneq (,$(strip $(foreach tgt,IPOD_VIDEO IPOD_NANO IPOD_COLOR IRIVER \
SUBDIRS += pacbox SUBDIRS += pacbox
endif endif
# Build Doom for the H300 and color ipods
ifneq (,$(strip $(foreach tgt, IRIVER_H300 IPOD_NANO IPOD_COLOR IPOD_VIDEO,$(findstring $(tgt),$(TARGET)))))
SUBDIRS += doom
endif
.PHONY: $(SUBDIRS) .PHONY: $(SUBDIRS)
all: $(BUILDDIR)/libplugin.a $(ROCKS) $(SUBDIRS) $(DEPFILE) all: $(BUILDDIR)/libplugin.a $(ROCKS) $(SUBDIRS) $(DEPFILE)

View file

@ -0,0 +1,47 @@
Changelog:
Fixed Nightmare mode
Fixed end game
Fixed quit crash
Added more prboom rendering code -> speedup
expanded rendering code -> speedup
Rewrote lowquality renderer and moved option to loader -> adds 1 fps to speed
Changed Default Keys:
DOOM PLAYER
------ ------
UP REC
DOWN DOWN
LEFT LEFT
RIGHT RIGHT
SHOOT MODE
OPEN DOWN
ESC ON
ENTER SELECT
WEAPON OFF
Menu Keys now work independent of ingame keys
All code reformatted and warnings reduced (only 6 now)
New Menu code to select options and Base game
doom shareware doom1.wad
doom registered doom.wad
doom retail (ultimate doom) doomu.wad
doom 2 doom2.wad
plutonia plutonia.wad
tnt tnt.wad
Doom directory is now /games/doom/
Disabled mouse calls -> speedup
Finally have the right timer. -> run is actually usable now
Added a timedemo option for speed testing, only runs with doom shareware,
Ultimate doom, or registered doom saves timedemo information in /games/doom/timedemo.txt
Merged Paul's Ipod changes, hopefully it works now
Added addon code so that additional wadfiles can be added to the startup.
# Version 0.8
Extended the addon code to automatically search for wads in /games/doom/addons/
Changed the memory allocation to use doom's block allocator exclusively this can
be used in other plugins that need malloc, realloc, and calloc (include z_zone.c, z_zone.h)
Included linuxstb's code for the Ipod
Redid the sound code partially from prboom
-> caches all sound at startup
-> helped reduce the number of pauses in the game
All new renderer from prboom -> translucent sprites, dynamic palettes FASTER
more wads work properly (no more graphical errors in halflife)

145
apps/plugins/doom/Makefile Normal file
View file

@ -0,0 +1,145 @@
################################################################
#
# $Id$
#
# $Log$
# Revision 1.1 2006/03/28 15:44:01 dave
# Patch #2969 - Doom! Currently only working on the H300.
#
#
INCLUDES = -I$(APPSDIR) -I.. -I. -I$(FIRMDIR)/include -I$(FIRMDIR)/export \
-I$(FIRMDIR)/common -I$(FIRMDIR)/drivers -I$(OUTDIR) -I$(BUILDDIR)
CFLAGS = $(GCCOPTS) $(INCLUDES) $(TARGET) $(EXTRA_DEFINES) \
-DTARGET_ID=$(TARGET_ID) -DMEM=${MEMORYSIZE} -DPLUGIN \
-Wno-strict-prototypes -O2
ifdef APPEXTRA
INCLUDES += $(patsubst %,-I$(APPSDIR)/%,$(subst :, ,$(APPEXTRA)))
endif
ifneq (,$(strip $(foreach tgt,IPOD_NANO IPOD_COLOR IPOD_VIDEO,$(findstring $(tgt),$(TARGET)))))
ifndef SIMVER
CFLAGS += -mstructure-size-boundary=8
endif
else
ifndef SIMVER
CFLAGS += -D__BIG_ENDIAN__
endif
endif
LINKFILE := $(OBJDIR)/link.lds
DEPFILE = $(OBJDIR)/dep-doom
SRC = info.c doomdef.c doomstat.c dstrings.c tables.c \
f_finale.c f_wipe.c d_net.c d_items.c g_game.c m_menu.c m_argv.c \
m_cheat.c m_random.c am_map.c p_ceilng.c p_doors.c p_genlin.c \
p_enemy.c p_floor.c p_inter.c p_lights.c p_map.c p_maputl.c p_plats.c \
p_pspr.c p_setup.c p_sight.c p_spec.c p_switch.c p_mobj.c p_telept.c \
p_tick.c p_saveg.c p_user.c r_bsp.c r_data.c r_draw.c r_main.c \
r_plane.c r_segs.c r_sky.c r_things.c wi_stuff.c v_video.c st_lib.c \
st_stuff.c hu_stuff.c hu_lib.c s_sound.c z_zone.c z_bmalloc.c sounds.c \
d_main.c m_misc.c m_bbox.c i_system.c i_sound.c i_video.c \
w_wad.c rockdoom.c
# fixmath2.S
SOURCES = $(SRC)
OBJS := $(SRC:%.c=$(OBJDIR)/%.o)
#OBJS2 := $(SRC:%.c=$(OBJDIR)/%.o)
#OBJS = $(patsubst %.S, $(OBJDIR)/%.o, $(OBJS2))
DIRS = .
ifndef SIMVER
ifneq (,$(findstring RECORDER,$(TARGET))) ## Archos recorder targets
LDS := archos.lds
OUTPUT = $(OUTDIR)/doom.ovl
else ## iRiver target
LDS := ../plugin.lds
OUTPUT = $(OUTDIR)/doom.rock
endif
else ## simulators
OUTPUT = $(OUTDIR)/doom.rock
endif
all: $(OUTPUT)
ifndef SIMVER
$(OBJDIR)/doom.elf: $(OBJS) $(LINKFILE)
@echo "LD "`basename $@`
@$(CC) $(GCCOPTS) $(LDFLAGS) -nostdlib -o $@ $(OBJS) -L$(BUILDDIR) -lplugin -lgcc\
-T$(LINKFILE) -Wl,-Map,$(OBJDIR)/doom.map
$(OUTPUT): $(OBJDIR)/doom.elf
@echo "OBJCOPY "`basename $@`
@$(OC) -O binary $< $@
else
ifeq ($(SIMVER), x11)
###################################################
# This is the X11 simulator version
$(OUTPUT): $(OBJS)
@echo "LD $@"
@$(CC) $(CFLAGS) -shared $(OBJS) -L$(BUILDDIR) -lplugin -o $@
ifeq ($(findstring CYGWIN,$(UNAME)),CYGWIN)
# 'x' must be kept or you'll have "Win32 error 5"
# $ fgrep 5 /usr/include/w32api/winerror.h | head -1
# #define ERROR_ACCESS_DENIED 5L
else
@chmod -x $@
endif
else # end of x11-simulator
ifeq ($(SIMVER), sdl)
###################################################
# This is the sdl simulator version
$(OUTPUT): $(OBJS)
@echo "LD $@"
@$(CC) $(CFLAGS) -shared $(OBJS) -L$(BUILDDIR) -lplugin -o $@
ifeq ($(findstring CYGWIN,$(UNAME)),CYGWIN)
# 'x' must be kept or you'll have "Win32 error 5"
# $ fgrep 5 /usr/include/w32api/winerror.h | head -1
# #define ERROR_ACCESS_DENIED 5L
else
@chmod -x $@
endif
else # end of sdl-simulator
###################################################
# This is the win32 simulator version
DLLTOOLFLAGS = --export-all
DLLWRAPFLAGS = -s --entry _DllMain@12 --target=i386-mingw32 -mno-cygwin
$(OUTPUT): $(OBJS)
@echo "DLL "`basename $@`
@$(DLLTOOL) $(DLLTOOLFLAGS) -z $(OBJDIR)/$*.def $(OBJS)
@$(DLLWRAP) $(DLLWRAPFLAGS) --def $(OBJDIR)/$*.def $(OBJS) \
$(BUILDDIR)/libplugin.a -o $@
ifeq ($(findstring CYGWIN,$(UNAME)),CYGWIN)
# 'x' must be kept or you'll have "Win32 error 5"
# $ fgrep 5 /usr/include/w32api/winerror.h | head -1
# #define ERROR_ACCESS_DENIED 5L
else
@chmod -x $@
endif
endif # end of win32-simulator
endif
endif # end of simulator section
include $(TOOLSDIR)/make.inc
# MEMORYSIZE should be passed on to this makefile with the chosen memory size
# given in number of MB
$(LINKFILE): $(LDS)
@echo "build "`basename $@`
@cat $< | $(CC) -DMEMORYSIZE=$(MEMORYSIZE) $(INCLUDES) $(TARGET) $(DEFINES) \
-E -P - >$@
clean:
@echo "cleaning doom"
@rm -rf $(OBJDIR)/doom
@rm -f $(OBJDIR)/doom.* $(DEPFILE)
-include $(DEPFILE)

1702
apps/plugins/doom/am_map.c Normal file

File diff suppressed because it is too large Load diff

106
apps/plugins/doom/am_map.h Normal file
View file

@ -0,0 +1,106 @@
/* Emacs style mode select -*- C++ -*-
*-----------------------------------------------------------------------------
*
*
* PrBoom a Doom port merged with LxDoom and LSDLDoom
* based on BOOM, a modified and improved DOOM engine
* Copyright (C) 1999 by
* id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
* Copyright (C) 1999-2000 by
* Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* DESCRIPTION:
* AutoMap module.
*
*-----------------------------------------------------------------------------*/
#ifndef __AMMAP_H__
#define __AMMAP_H__
#include "d_event.h"
#include "m_fixed.h"
// Used by ST StatusBar stuff.
#define AM_MSGHEADER (('a'<<24)+('m'<<16))
#define AM_MSGENTERED (AM_MSGHEADER | ('e'<<8))
#define AM_MSGEXITED (AM_MSGHEADER | ('x'<<8))
// Called by main loop.
boolean AM_Responder (event_t* ev);
// Called by main loop.
void AM_Ticker (void);
// Called by main loop,
// called instead of view drawer if automap active.
void AM_Drawer (void);
// Called to force the automap to quit
// if the level is completed while it is up.
void AM_Stop (void);
// killough 2/22/98: for saving automap information in savegame:
extern void AM_Start(void);
//jff 4/16/98 make externally available
extern void AM_clearMarks(void);
typedef struct
{
fixed_t x,y;
} mpoint_t;
extern mpoint_t *markpoints;
extern int markpointnum, markpointnum_max;
// end changes -- killough 2/22/98
// killough 5/2/98: moved from m_misc.c
//jff 1/7/98 automap colors added
extern int mapcolor_back; // map background
extern int mapcolor_grid; // grid lines color
extern int mapcolor_wall; // normal 1s wall color
extern int mapcolor_fchg; // line at floor height change color
extern int mapcolor_cchg; // line at ceiling height change color
extern int mapcolor_clsd; // line at sector with floor=ceiling color
extern int mapcolor_rkey; // red key color
extern int mapcolor_bkey; // blue key color
extern int mapcolor_ykey; // yellow key color
extern int mapcolor_rdor; // red door color (diff from keys to allow option)
extern int mapcolor_bdor; // blue door color (of enabling one not other)
extern int mapcolor_ydor; // yellow door color
extern int mapcolor_tele; // teleporter line color
extern int mapcolor_secr; // secret sector boundary color
//jff 4/23/98
extern int mapcolor_exit; // exit line
extern int mapcolor_unsn; // computer map unseen line color
extern int mapcolor_flat; // line with no floor/ceiling changes
extern int mapcolor_sprt; // general sprite color
extern int mapcolor_item; // item sprite color
extern int mapcolor_frnd; // friendly sprite color
extern int mapcolor_hair; // crosshair color
extern int mapcolor_sngl; // single player arrow color
extern int mapcolor_plyr[4]; // colors for players in multiplayer
extern int mapcolor_me; // consoleplayer's chosen colour
//jff 3/9/98
extern int map_secret_after; // secrets do not appear til after bagged
#endif

View file

@ -0,0 +1,705 @@
/* Emacs style mode select -*- C++ -*-
*-----------------------------------------------------------------------------
*
*
* PrBoom a Doom port merged with LxDoom and LSDLDoom
* based on BOOM, a modified and improved DOOM engine
* Copyright (C) 1999 by
* id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
* Copyright (C) 1999-2000 by
* Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* DESCRIPTION:
* Printed strings for translation.
* English language support (default).
* See dstrings.h for suggestions about foreign language BEX support
*
*-----------------------------------------------------------------------------*/
#ifndef __D_ENGLSH__
#define __D_ENGLSH__
/* d_main.c */
#define D_DEVSTR "Development mode ON.\n"
#define D_CDROM "CD-ROM Version: default.cfg from c:\\doomdata\n"
/* m_menu.c */
#define PRESSKEY "press a key."
#define PRESSYN "press y or n."
#define QUITMSG "are you sure you want to\nquit this great game?"
#define LOADNET "you can't do load while in a net game!\n\n"PRESSKEY
#define QLOADNET "you can't quickload during a netgame!\n\n"PRESSKEY
#define QSAVESPOT "you haven't picked a quicksave slot yet!\n\n"PRESSKEY
#define SAVEDEAD "you can't save if you aren't playing!\n\n"PRESSKEY
#define QSPROMPT "quicksave over your game named\n\n'%s'?\n\n"PRESSYN
#define QLPROMPT "do you want to quickload the game named\n\n'%s'?\n\n"PRESSYN
#define NEWGAME \
"you can't start a new game\n"\
"while in a network game.\n\n"PRESSKEY
#define NIGHTMARE \
"are you sure? this skill level\n"\
"isn't even remotely fair.\n\n"PRESSYN
#define SWSTRING \
"this is the shareware version of doom.\n\n"\
"you need to order the entire trilogy.\n\n"PRESSKEY
#define MSGOFF "Messages OFF"
#define MSGON "Messages ON"
#define NETEND "you can't end a netgame!\n\n"PRESSKEY
#define ENDGAME "are you sure you want to end the game?\n\n"PRESSYN
#define RESTARTLEVEL "restart the level?\n\n"PRESSYN
#define DOSY "(press y to quit)"
#define DETAILHI "High detail"
#define DETAILLO "Low detail"
#define GAMMALVL0 "Gamma correction OFF"
#define GAMMALVL1 "Gamma correction level 1"
#define GAMMALVL2 "Gamma correction level 2"
#define GAMMALVL3 "Gamma correction level 3"
#define GAMMALVL4 "Gamma correction level 4"
#define EMPTYSTRING "empty slot"
/* p_inter.c */
#define GOTARMOR "Picked up the armor."
#define GOTMEGA "Picked up the MegaArmor!"
#define GOTHTHBONUS "Picked up a health bonus."
#define GOTARMBONUS "Picked up an armor bonus."
#define GOTSTIM "Picked up a stimpack."
#define GOTMEDINEED "Picked up a medikit that you REALLY need!"
#define GOTMEDIKIT "Picked up a medikit."
#define GOTSUPER "Supercharge!"
#define GOTBLUECARD "Picked up a blue keycard."
#define GOTYELWCARD "Picked up a yellow keycard."
#define GOTREDCARD "Picked up a red keycard."
#define GOTBLUESKUL "Picked up a blue skull key."
#define GOTYELWSKUL "Picked up a yellow skull key."
#define GOTREDSKULL "Picked up a red skull key."
#define GOTINVUL "Invulnerability!"
#define GOTBERSERK "Berserk!"
#define GOTINVIS "Partial Invisibility"
#define GOTSUIT "Radiation Shielding Suit"
#define GOTMAP "Computer Area Map"
#define GOTVISOR "Light Amplification Visor"
#define GOTMSPHERE "MegaSphere!"
#define GOTCLIP "Picked up a clip."
#define GOTCLIPBOX "Picked up a box of bullets."
#define GOTROCKET "Picked up a rocket."
#define GOTROCKBOX "Picked up a box of rockets."
#define GOTCELL "Picked up an energy cell."
#define GOTCELLBOX "Picked up an energy cell pack."
#define GOTSHELLS "Picked up 4 shotgun shells."
#define GOTSHELLBOX "Picked up a box of shotgun shells."
#define GOTBACKPACK "Picked up a backpack full of ammo!"
#define GOTBFG9000 "You got the BFG9000! Oh, yes."
#define GOTCHAINGUN "You got the chaingun!"
#define GOTCHAINSAW "A chainsaw! Find some meat!"
#define GOTLAUNCHER "You got the rocket launcher!"
#define GOTPLASMA "You got the plasma gun!"
#define GOTSHOTGUN "You got the shotgun!"
#define GOTSHOTGUN2 "You got the super shotgun!"
/* p_doors.c */
#define PD_BLUEO "You need a blue key to activate this object"
#define PD_REDO "You need a red key to activate this object"
#define PD_YELLOWO "You need a yellow key to activate this object"
#define PD_BLUEK "You need a blue key to open this door"
#define PD_REDK "You need a red key to open this door"
#define PD_YELLOWK "You need a yellow key to open this door"
/* jff 02/05/98 Create messages specific to card and skull keys */
#define PD_BLUEC "You need a blue card to open this door"
#define PD_REDC "You need a red card to open this door"
#define PD_YELLOWC "You need a yellow card to open this door"
#define PD_BLUES "You need a blue skull to open this door"
#define PD_REDS "You need a red skull to open this door"
#define PD_YELLOWS "You need a yellow skull to open this door"
#define PD_ANY "Any key will open this door"
#define PD_ALL3 "You need all three keys to open this door"
#define PD_ALL6 "You need all six keys to open this door"
/* g_game.c */
#define GGSAVED "game saved."
/* hu_stuff.c */
#define HUSTR_MSGU "[Message unsent]"
#define HUSTR_E1M1 "E1M1: Hangar"
#define HUSTR_E1M2 "E1M2: Nuclear Plant"
#define HUSTR_E1M3 "E1M3: Toxin Refinery"
#define HUSTR_E1M4 "E1M4: Command Control"
#define HUSTR_E1M5 "E1M5: Phobos Lab"
#define HUSTR_E1M6 "E1M6: Central Processing"
#define HUSTR_E1M7 "E1M7: Computer Station"
#define HUSTR_E1M8 "E1M8: Phobos Anomaly"
#define HUSTR_E1M9 "E1M9: Military Base"
#define HUSTR_E2M1 "E2M1: Deimos Anomaly"
#define HUSTR_E2M2 "E2M2: Containment Area"
#define HUSTR_E2M3 "E2M3: Refinery"
#define HUSTR_E2M4 "E2M4: Deimos Lab"
#define HUSTR_E2M5 "E2M5: Command Center"
#define HUSTR_E2M6 "E2M6: Halls of the Damned"
#define HUSTR_E2M7 "E2M7: Spawning Vats"
#define HUSTR_E2M8 "E2M8: Tower of Babel"
#define HUSTR_E2M9 "E2M9: Fortress of Mystery"
#define HUSTR_E3M1 "E3M1: Hell Keep"
#define HUSTR_E3M2 "E3M2: Slough of Despair"
#define HUSTR_E3M3 "E3M3: Pandemonium"
#define HUSTR_E3M4 "E3M4: House of Pain"
#define HUSTR_E3M5 "E3M5: Unholy Cathedral"
#define HUSTR_E3M6 "E3M6: Mt. Erebus"
#define HUSTR_E3M7 "E3M7: Limbo"
#define HUSTR_E3M8 "E3M8: Dis"
#define HUSTR_E3M9 "E3M9: Warrens"
#define HUSTR_E4M1 "E4M1: Hell Beneath"
#define HUSTR_E4M2 "E4M2: Perfect Hatred"
#define HUSTR_E4M3 "E4M3: Sever The Wicked"
#define HUSTR_E4M4 "E4M4: Unruly Evil"
#define HUSTR_E4M5 "E4M5: They Will Repent"
#define HUSTR_E4M6 "E4M6: Against Thee Wickedly"
#define HUSTR_E4M7 "E4M7: And Hell Followed"
#define HUSTR_E4M8 "E4M8: Unto The Cruel"
#define HUSTR_E4M9 "E4M9: Fear"
#define HUSTR_1 "level 1: entryway"
#define HUSTR_2 "level 2: underhalls"
#define HUSTR_3 "level 3: the gantlet"
#define HUSTR_4 "level 4: the focus"
#define HUSTR_5 "level 5: the waste tunnels"
#define HUSTR_6 "level 6: the crusher"
#define HUSTR_7 "level 7: dead simple"
#define HUSTR_8 "level 8: tricks and traps"
#define HUSTR_9 "level 9: the pit"
#define HUSTR_10 "level 10: refueling base"
#define HUSTR_11 "level 11: 'o' of destruction!"
#define HUSTR_12 "level 12: the factory"
#define HUSTR_13 "level 13: downtown"
#define HUSTR_14 "level 14: the inmost dens"
#define HUSTR_15 "level 15: industrial zone"
#define HUSTR_16 "level 16: suburbs"
#define HUSTR_17 "level 17: tenements"
#define HUSTR_18 "level 18: the courtyard"
#define HUSTR_19 "level 19: the citadel"
#define HUSTR_20 "level 20: gotcha!"
#define HUSTR_21 "level 21: nirvana"
#define HUSTR_22 "level 22: the catacombs"
#define HUSTR_23 "level 23: barrels o' fun"
#define HUSTR_24 "level 24: the chasm"
#define HUSTR_25 "level 25: bloodfalls"
#define HUSTR_26 "level 26: the abandoned mines"
#define HUSTR_27 "level 27: monster condo"
#define HUSTR_28 "level 28: the spirit world"
#define HUSTR_29 "level 29: the living end"
#define HUSTR_30 "level 30: icon of sin"
#define HUSTR_31 "level 31: wolfenstein"
#define HUSTR_32 "level 32: grosse"
#define PHUSTR_1 "level 1: congo"
#define PHUSTR_2 "level 2: well of souls"
#define PHUSTR_3 "level 3: aztec"
#define PHUSTR_4 "level 4: caged"
#define PHUSTR_5 "level 5: ghost town"
#define PHUSTR_6 "level 6: baron's lair"
#define PHUSTR_7 "level 7: caughtyard"
#define PHUSTR_8 "level 8: realm"
#define PHUSTR_9 "level 9: abattoire"
#define PHUSTR_10 "level 10: onslaught"
#define PHUSTR_11 "level 11: hunted"
#define PHUSTR_12 "level 12: speed"
#define PHUSTR_13 "level 13: the crypt"
#define PHUSTR_14 "level 14: genesis"
#define PHUSTR_15 "level 15: the twilight"
#define PHUSTR_16 "level 16: the omen"
#define PHUSTR_17 "level 17: compound"
#define PHUSTR_18 "level 18: neurosphere"
#define PHUSTR_19 "level 19: nme"
#define PHUSTR_20 "level 20: the death domain"
#define PHUSTR_21 "level 21: slayer"
#define PHUSTR_22 "level 22: impossible mission"
#define PHUSTR_23 "level 23: tombstone"
#define PHUSTR_24 "level 24: the final frontier"
#define PHUSTR_25 "level 25: the temple of darkness"
#define PHUSTR_26 "level 26: bunker"
#define PHUSTR_27 "level 27: anti-christ"
#define PHUSTR_28 "level 28: the sewers"
#define PHUSTR_29 "level 29: odyssey of noises"
#define PHUSTR_30 "level 30: the gateway of hell"
#define PHUSTR_31 "level 31: cyberden"
#define PHUSTR_32 "level 32: go 2 it"
#define THUSTR_1 "level 1: system control"
#define THUSTR_2 "level 2: human bbq"
#define THUSTR_3 "level 3: power control"
#define THUSTR_4 "level 4: wormhole"
#define THUSTR_5 "level 5: hanger"
#define THUSTR_6 "level 6: open season"
#define THUSTR_7 "level 7: prison"
#define THUSTR_8 "level 8: metal"
#define THUSTR_9 "level 9: stronghold"
#define THUSTR_10 "level 10: redemption"
#define THUSTR_11 "level 11: storage facility"
#define THUSTR_12 "level 12: crater"
#define THUSTR_13 "level 13: nukage processing"
#define THUSTR_14 "level 14: steel works"
#define THUSTR_15 "level 15: dead zone"
#define THUSTR_16 "level 16: deepest reaches"
#define THUSTR_17 "level 17: processing area"
#define THUSTR_18 "level 18: mill"
#define THUSTR_19 "level 19: shipping/respawning"
#define THUSTR_20 "level 20: central processing"
#define THUSTR_21 "level 21: administration center"
#define THUSTR_22 "level 22: habitat"
#define THUSTR_23 "level 23: lunar mining project"
#define THUSTR_24 "level 24: quarry"
#define THUSTR_25 "level 25: baron's den"
#define THUSTR_26 "level 26: ballistyx"
#define THUSTR_27 "level 27: mount pain"
#define THUSTR_28 "level 28: heck"
#define THUSTR_29 "level 29: river styx"
#define THUSTR_30 "level 30: last call"
#define THUSTR_31 "level 31: pharaoh"
#define THUSTR_32 "level 32: caribbean"
#define HUSTR_CHATMACRO1 "I'm ready to kick butt!"
#define HUSTR_CHATMACRO2 "I'm OK."
#define HUSTR_CHATMACRO3 "I'm not looking too good!"
#define HUSTR_CHATMACRO4 "Help!"
#define HUSTR_CHATMACRO5 "You suck!"
#define HUSTR_CHATMACRO6 "Next time, scumbag..."
#define HUSTR_CHATMACRO7 "Come here!"
#define HUSTR_CHATMACRO8 "I'll take care of it."
#define HUSTR_CHATMACRO9 "Yes"
#define HUSTR_CHATMACRO0 "No"
#define HUSTR_TALKTOSELF1 "You mumble to yourself"
#define HUSTR_TALKTOSELF2 "Who's there?"
#define HUSTR_TALKTOSELF3 "You scare yourself"
#define HUSTR_TALKTOSELF4 "You start to rave"
#define HUSTR_TALKTOSELF5 "You've lost it..."
#define HUSTR_MESSAGESENT "[Message Sent]"
/* The following should NOT be changed unless it seems
* just AWFULLY necessary */
#define HUSTR_PLRGREEN "Player 1: "
#define HUSTR_PLRINDIGO "Player 2: "
#define HUSTR_PLRBROWN "Player 3: "
#define HUSTR_PLRRED "Player 4: "
#define HUSTR_KEYGREEN 'g'
#define HUSTR_KEYINDIGO 'i'
#define HUSTR_KEYBROWN 'b'
#define HUSTR_KEYRED 'r'
/* am_map.c */
#define AMSTR_FOLLOWON "Follow Mode ON"
#define AMSTR_FOLLOWOFF "Follow Mode OFF"
#define AMSTR_GRIDON "Grid ON"
#define AMSTR_GRIDOFF "Grid OFF"
#define AMSTR_MARKEDSPOT "Marked Spot"
#define AMSTR_MARKSCLEARED "All Marks Cleared"
#define AMSTR_ROTATEON "Rotate Mode ON"
#define AMSTR_ROTATEOFF "Rotate Mode OFF"
#define AMSTR_OVERLAYON "Overlay Mode ON"
#define AMSTR_OVERLAYOFF "Overlay Mode OFF"
/* st_stuff.c */
#define STSTR_MUS "Music Change"
#define STSTR_NOMUS "IMPOSSIBLE SELECTION"
#define STSTR_DQDON "Degreelessness Mode On"
#define STSTR_DQDOFF "Degreelessness Mode Off"
#define STSTR_KFAADDED "Very Happy Ammo Added"
#define STSTR_FAADDED "Ammo (no keys) Added"
#define STSTR_NCON "No Clipping Mode ON"
#define STSTR_NCOFF "No Clipping Mode OFF"
#define STSTR_BEHOLD "inVuln, Str, Inviso, Rad, Allmap, or Lite-amp"
#define STSTR_BEHOLDX "Power-up Toggled"
#define STSTR_CHOPPERS "... doesn't suck - GM"
#define STSTR_CLEV "Changing Level..."
#define STSTR_COMPON "Compatibility Mode On" /* phares */
#define STSTR_COMPOFF "Compatibility Mode Off" /* phares */
/* f_finale.c */
#define E1TEXT \
"Once you beat the big badasses and\n"\
"clean out the moon base you're supposed\n"\
"to win, aren't you? Aren't you? Where's\n"\
"your fat reward and ticket home? What\n"\
"the hell is this? It's not supposed to\n"\
"end this way!\n"\
"\n" \
"It stinks like rotten meat, but looks\n"\
"like the lost Deimos base. Looks like\n"\
"you're stuck on The Shores of Hell.\n"\
"The only way out is through.\n"\
"\n"\
"To continue the DOOM experience, play\n"\
"The Shores of Hell and its amazing\n"\
"sequel, Inferno!\n"
#define E2TEXT \
"You've done it! The hideous cyber-\n"\
"demon lord that ruled the lost Deimos\n"\
"moon base has been slain and you\n"\
"are triumphant! But ... where are\n"\
"you? You clamber to the edge of the\n"\
"moon and look down to see the awful\n"\
"truth.\n" \
"\n"\
"Deimos floats above Hell itself!\n"\
"You've never heard of anyone escaping\n"\
"from Hell, but you'll make the bastards\n"\
"sorry they ever heard of you! Quickly,\n"\
"you rappel down to the surface of\n"\
"Hell.\n"\
"\n" \
"Now, it's on to the final chapter of\n"\
"DOOM! -- Inferno."
#define E3TEXT \
"The loathsome spiderdemon that\n"\
"masterminded the invasion of the moon\n"\
"bases and caused so much death has had\n"\
"its ass kicked for all time.\n"\
"\n"\
"A hidden doorway opens and you enter.\n"\
"You've proven too tough for Hell to\n"\
"contain, and now Hell at last plays\n"\
"fair -- for you emerge from the door\n"\
"to see the green fields of Earth!\n"\
"Home at last.\n" \
"\n"\
"You wonder what's been happening on\n"\
"Earth while you were battling evil\n"\
"unleashed. It's good that no Hell-\n"\
"spawn could have come through that\n"\
"door with you ..."
#define E4TEXT \
"the spider mastermind must have sent forth\n"\
"its legions of hellspawn before your\n"\
"final confrontation with that terrible\n"\
"beast from hell. but you stepped forward\n"\
"and brought forth eternal damnation and\n"\
"suffering upon the horde as a true hero\n"\
"would in the face of something so evil.\n"\
"\n"\
"besides, someone was gonna pay for what\n"\
"happened to daisy, your pet rabbit.\n"\
"\n"\
"but now, you see spread before you more\n"\
"potential pain and gibbitude as a nation\n"\
"of demons run amok among our cities.\n"\
"\n"\
"next stop, hell on earth!"
/* after level 6, put this: */
#define C1TEXT \
"YOU HAVE ENTERED DEEPLY INTO THE INFESTED\n" \
"STARPORT. BUT SOMETHING IS WRONG. THE\n" \
"MONSTERS HAVE BROUGHT THEIR OWN REALITY\n" \
"WITH THEM, AND THE STARPORT'S TECHNOLOGY\n" \
"IS BEING SUBVERTED BY THEIR PRESENCE.\n" \
"\n"\
"AHEAD, YOU SEE AN OUTPOST OF HELL, A\n" \
"FORTIFIED ZONE. IF YOU CAN GET PAST IT,\n" \
"YOU CAN PENETRATE INTO THE HAUNTED HEART\n" \
"OF THE STARBASE AND FIND THE CONTROLLING\n" \
"SWITCH WHICH HOLDS EARTH'S POPULATION\n" \
"HOSTAGE."
/* After level 11, put this: */
#define C2TEXT \
"YOU HAVE WON! YOUR VICTORY HAS ENABLED\n" \
"HUMANKIND TO EVACUATE EARTH AND ESCAPE\n"\
"THE NIGHTMARE. NOW YOU ARE THE ONLY\n"\
"HUMAN LEFT ON THE FACE OF THE PLANET.\n"\
"CANNIBAL MUTATIONS, CARNIVOROUS ALIENS,\n"\
"AND EVIL SPIRITS ARE YOUR ONLY NEIGHBORS.\n"\
"YOU SIT BACK AND WAIT FOR DEATH, CONTENT\n"\
"THAT YOU HAVE SAVED YOUR SPECIES.\n"\
"\n"\
"BUT THEN, EARTH CONTROL BEAMS DOWN A\n"\
"MESSAGE FROM SPACE: \"SENSORS HAVE LOCATED\n"\
"THE SOURCE OF THE ALIEN INVASION. IF YOU\n"\
"GO THERE, YOU MAY BE ABLE TO BLOCK THEIR\n"\
"ENTRY. THE ALIEN BASE IS IN THE HEART OF\n"\
"YOUR OWN HOME CITY, NOT FAR FROM THE\n"\
"STARPORT.\" SLOWLY AND PAINFULLY YOU GET\n"\
"UP AND RETURN TO THE FRAY."
/* After level 20, put this: */
#define C3TEXT \
"YOU ARE AT THE CORRUPT HEART OF THE CITY,\n"\
"SURROUNDED BY THE CORPSES OF YOUR ENEMIES.\n"\
"YOU SEE NO WAY TO DESTROY THE CREATURES'\n"\
"ENTRYWAY ON THIS SIDE, SO YOU CLENCH YOUR\n"\
"TEETH AND PLUNGE THROUGH IT.\n"\
"\n"\
"THERE MUST BE A WAY TO CLOSE IT ON THE\n"\
"OTHER SIDE. WHAT DO YOU CARE IF YOU'VE\n"\
"GOT TO GO THROUGH HELL TO GET TO IT?"
/* After level 29, put this: */
#define C4TEXT \
"THE HORRENDOUS VISAGE OF THE BIGGEST\n"\
"DEMON YOU'VE EVER SEEN CRUMBLES BEFORE\n"\
"YOU, AFTER YOU PUMP YOUR ROCKETS INTO\n"\
"HIS EXPOSED BRAIN. THE MONSTER SHRIVELS\n"\
"UP AND DIES, ITS THRASHING LIMBS\n"\
"DEVASTATING UNTOLD MILES OF HELL'S\n"\
"SURFACE.\n"\
"\n"\
"YOU'VE DONE IT. THE INVASION IS OVER.\n"\
"EARTH IS SAVED. HELL IS A WRECK. YOU\n"\
"WONDER WHERE BAD FOLKS WILL GO WHEN THEY\n"\
"DIE, NOW. WIPING THE SWEAT FROM YOUR\n"\
"FOREHEAD YOU BEGIN THE LONG TREK BACK\n"\
"HOME. REBUILDING EARTH OUGHT TO BE A\n"\
"LOT MORE FUN THAN RUINING IT WAS.\n"
/* Before level 31, put this: */
#define C5TEXT \
"CONGRATULATIONS, YOU'VE FOUND THE SECRET\n"\
"LEVEL! LOOKS LIKE IT'S BEEN BUILT BY\n"\
"HUMANS, RATHER THAN DEMONS. YOU WONDER\n"\
"WHO THE INMATES OF THIS CORNER OF HELL\n"\
"WILL BE."
/* Before level 32, put this: */
#define C6TEXT \
"CONGRATULATIONS, YOU'VE FOUND THE\n"\
"SUPER SECRET LEVEL! YOU'D BETTER\n"\
"BLAZE THROUGH THIS ONE!\n"
/*** Plutonia ***/
/* after map 06 */
#define P1TEXT \
"You gloat over the steaming carcass of the\n"\
"Guardian. With its death, you've wrested\n"\
"the Accelerator from the stinking claws\n"\
"of Hell. You relax and glance around the\n"\
"room. Damn! There was supposed to be at\n"\
"least one working prototype, but you can't\n"\
"see it. The demons must have taken it.\n"\
"\n"\
"You must find the prototype, or all your\n"\
"struggles will have been wasted. Keep\n"\
"moving, keep fighting, keep killing.\n"\
"Oh yes, keep living, too."
/* after map 11 */
#define P2TEXT \
"Even the deadly Arch-Vile labyrinth could\n"\
"not stop you, and you've gotten to the\n"\
"prototype Accelerator which is soon\n"\
"efficiently and permanently deactivated.\n"\
"\n"\
"You're good at that kind of thing."
/* after map 20 */
#define P3TEXT \
"You've bashed and battered your way into\n"\
"the heart of the devil-hive. Time for a\n"\
"Search-and-Destroy mission, aimed at the\n"\
"Gatekeeper, whose foul offspring is\n"\
"cascading to Earth. Yeah, he's bad. But\n"\
"you know who's worse!\n"\
"\n"\
"Grinning evilly, you check your gear, and\n"\
"get ready to give the bastard a little Hell\n"\
"of your own making!"
/* after map 30 */
#define P4TEXT \
"The Gatekeeper's evil face is splattered\n"\
"all over the place. As its tattered corpse\n"\
"collapses, an inverted Gate forms and\n"\
"sucks down the shards of the last\n"\
"prototype Accelerator, not to mention the\n"\
"few remaining demons. You're done. Hell\n"\
"has gone back to pounding bad dead folks \n"\
"instead of good live ones. Remember to\n"\
"tell your grandkids to put a rocket\n"\
"launcher in your coffin. If you go to Hell\n"\
"when you die, you'll need it for some\n"\
"final cleaning-up ..."
/* before map 31 */
#define P5TEXT \
"You've found the second-hardest level we\n"\
"got. Hope you have a saved game a level or\n"\
"two previous. If not, be prepared to die\n"\
"aplenty. For master marines only."
/* before map 32 */
#define P6TEXT \
"Betcha wondered just what WAS the hardest\n"\
"level we had ready for ya? Now you know.\n"\
"No one gets out alive."
/*** TNT: Evilution ***/
#define T1TEXT \
"You've fought your way out of the infested\n"\
"experimental labs. It seems that UAC has\n"\
"once again gulped it down. With their\n"\
"high turnover, it must be hard for poor\n"\
"old UAC to buy corporate health insurance\n"\
"nowadays..\n"\
"\n"\
"Ahead lies the military complex, now\n"\
"swarming with diseased horrors hot to get\n"\
"their teeth into you. With luck, the\n"\
"complex still has some warlike ordnance\n"\
"laying around."
#define T2TEXT \
"You hear the grinding of heavy machinery\n"\
"ahead. You sure hope they're not stamping\n"\
"out new hellspawn, but you're ready to\n"\
"ream out a whole herd if you have to.\n"\
"They might be planning a blood feast, but\n"\
"you feel about as mean as two thousand\n"\
"maniacs packed into one mad killer.\n"\
"\n"\
"You don't plan to go down easy."
#define T3TEXT \
"The vista opening ahead looks real damn\n"\
"familiar. Smells familiar, too -- like\n"\
"fried excrement. You didn't like this\n"\
"place before, and you sure as hell ain't\n"\
"planning to like it now. The more you\n"\
"brood on it, the madder you get.\n"\
"Hefting your gun, an evil grin trickles\n"\
"onto your face. Time to take some names."
#define T4TEXT \
"Suddenly, all is silent, from one horizon\n"\
"to the other. The agonizing echo of Hell\n"\
"fades away, the nightmare sky turns to\n"\
"blue, the heaps of monster corpses start \n"\
"to evaporate along with the evil stench \n"\
"that filled the air. Jeeze, maybe you've\n"\
"done it. Have you really won?\n"\
"\n"\
"Something rumbles in the distance.\n"\
"A blue light begins to glow inside the\n"\
"ruined skull of the demon-spitter."
#define T5TEXT \
"What now? Looks totally different. Kind\n"\
"of like King Tut's condo. Well,\n"\
"whatever's here can't be any worse\n"\
"than usual. Can it? Or maybe it's best\n"\
"to let sleeping gods lie.."
#define T6TEXT \
"Time for a vacation. You've burst the\n"\
"bowels of hell and by golly you're ready\n"\
"for a break. You mutter to yourself,\n"\
"Maybe someone else can kick Hell's ass\n"\
"next time around. Ahead lies a quiet town,\n"\
"with peaceful flowing water, quaint\n"\
"buildings, and presumably no Hellspawn.\n"\
"\n"\
"As you step off the transport, you hear\n"\
"the stomp of a cyberdemon's iron shoe."
/*
* Character cast strings F_FINALE.C
*/
#define CC_ZOMBIE "ZOMBIEMAN"
#define CC_SHOTGUN "SHOTGUN GUY"
#define CC_HEAVY "HEAVY WEAPON DUDE"
#define CC_IMP "IMP"
#define CC_DEMON "DEMON"
#define CC_LOST "LOST SOUL"
#define CC_CACO "CACODEMON"
#define CC_HELL "HELL KNIGHT"
#define CC_BARON "BARON OF HELL"
#define CC_ARACH "ARACHNOTRON"
#define CC_PAIN "PAIN ELEMENTAL"
#define CC_REVEN "REVENANT"
#define CC_MANCU "MANCUBUS"
#define CC_ARCH "ARCH-VILE"
#define CC_SPIDER "THE SPIDER MASTERMIND"
#define CC_CYBER "THE CYBERDEMON"
#define CC_HERO "OUR HERO"
#endif

128
apps/plugins/doom/d_event.h Normal file
View file

@ -0,0 +1,128 @@
/* Emacs style mode select -*- C++ -*-
*-----------------------------------------------------------------------------
*
*
* PrBoom a Doom port merged with LxDoom and LSDLDoom
* based on BOOM, a modified and improved DOOM engine
* Copyright (C) 1999 by
* id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
* Copyright (C) 1999-2000 by
* Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* DESCRIPTION:
* Event information structures.
*
*-----------------------------------------------------------------------------*/
#ifndef __D_EVENT__
#define __D_EVENT__
#include "doomtype.h"
//
// Event handling.
//
// Input event types.
typedef enum
{
ev_keydown,
ev_keyup,
ev_mouse,
ev_joystick
} evtype_t;
// Event structure.
typedef struct
{
evtype_t type;
int data1; // keys / mouse/joystick buttons
int data2; // mouse/joystick x move
int data3; // mouse/joystick y move
} event_t;
typedef enum
{
ga_nothing,
ga_loadlevel,
ga_newgame,
ga_loadgame,
ga_savegame,
ga_playdemo,
ga_completed,
ga_victory,
ga_worlddone,
} gameaction_t;
//
// Button/action code definitions.
//
typedef enum
{
// Press "Fire".
BT_ATTACK = 1,
// Use button, to open doors, activate switches.
BT_USE = 2,
// Flag: game events, not really buttons.
BT_SPECIAL = 128,
BT_SPECIALMASK = 3,
// Flag, weapon change pending.
// If true, the next 4 bits hold weapon num.
BT_CHANGE = 4,
// The 4bit weapon mask and shift, convenience.
//BT_WEAPONMASK = (8+16+32),
BT_WEAPONMASK = (8+16+32+64), // extended to pick up SSG // phares
BT_WEAPONSHIFT = 3,
// Special events
BTS_LOADGAME = 0, // Loads a game
// Pause the game.
BTS_PAUSE = 1,
// Save the game at each console.
BTS_SAVEGAME = 2,
BTS_RESTARTLEVEL= 3, // Restarts the current level
// Savegame slot numbers occupy the second byte of buttons.
BTS_SAVEMASK = (4+8+16),
BTS_SAVESHIFT = 2,
} buttoncode_t;
//
// GLOBAL VARIABLES
//
#define MAXEVENTS 64
extern event_t events[MAXEVENTS];
extern int eventhead;
extern int eventtail;
extern gameaction_t gameaction;
#endif

View file

@ -0,0 +1,437 @@
// Emacs style mode select -*- C++ -*-
//-----------------------------------------------------------------------------
//
// $Id$
//
// Copyright (C) 1993-1996 by id Software, Inc.
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// DESCRIPTION:
// Printed strings, french translation.
//
//-----------------------------------------------------------------------------
#ifndef __D_FRENCH__
#define __D_FRENCH__
//
// D_Main.C
//
#define D_DEVSTR "MODE DEVELOPPEMENT ON.\n"
#define D_CDROM "VERSION CD-ROM: DEFAULT.CFG DANS C:\\DOOMDATA\n"
//
// M_Menu.C
//
#define PRESSKEY "APPUYEZ SUR UNE TOUCHE."
#define PRESSYN "APPUYEZ SUR Y OU N"
#define QUITMSG "VOUS VOULEZ VRAIMENT\nQUITTER CE SUPER JEU?"
#define LOADNET "VOUS NE POUVEZ PAS CHARGER\nUN JEU EN RESEAU!\n\n"PRESSKEY
#define QLOADNET "CHARGEMENT RAPIDE INTERDIT EN RESEAU!\n\n"PRESSKEY
#define QSAVESPOT "VOUS N'AVEZ PAS CHOISI UN EMPLACEMENT!\n\n"PRESSKEY
#define SAVEDEAD "VOUS NE POUVEZ PAS SAUVER SI VOUS NE JOUEZ "\
"PAS!\n\n"PRESSKEY
#define QSPROMPT "SAUVEGARDE RAPIDE DANS LE FICHIER \n\n'%s'?\n\n"PRESSYN
#define QLPROMPT "VOULEZ-VOUS CHARGER LA SAUVEGARDE"\
"\n\n'%s'?\n\n"PRESSYN
#define NEWGAME "VOUS NE POUVEZ PAS LANCER\n"\
"UN NOUVEAU JEU SUR RESEAU.\n\n"PRESSKEY
#define NIGHTMARE "VOUS CONFIRMEZ? CE NIVEAU EST\n"\
"VRAIMENT IMPITOYABLE!n"PRESSYN
#define SWSTRING "CECI EST UNE VERSION SHAREWARE DE DOOM.\n\n"\
"VOUS DEVRIEZ COMMANDER LA TRILOGIE COMPLETE.\n\n"PRESSKEY
#define MSGOFF "MESSAGES OFF"
#define MSGON "MESSAGES ON"
#define NETEND "VOUS NE POUVEZ PAS METTRE FIN A UN JEU SUR "\
"RESEAU!\n\n"PRESSKEY
#define ENDGAME "VOUS VOULEZ VRAIMENT METTRE FIN AU JEU?\n\n"PRESSYN
#define DOSY "(APPUYEZ SUR Y POUR REVENIR AU OS.)"
#define DETAILHI "GRAPHISMES MAXIMUM "
#define DETAILLO "GRAPHISMES MINIMUM "
#define GAMMALVL0 "CORRECTION GAMMA OFF"
#define GAMMALVL1 "CORRECTION GAMMA NIVEAU 1"
#define GAMMALVL2 "CORRECTION GAMMA NIVEAU 2"
#define GAMMALVL3 "CORRECTION GAMMA NIVEAU 3"
#define GAMMALVL4 "CORRECTION GAMMA NIVEAU 4"
#define EMPTYSTRING "EMPLACEMENT VIDE"
//
// P_inter.C
//
#define GOTARMOR "ARMURE RECUPEREE."
#define GOTMEGA "MEGA-ARMURE RECUPEREE!"
#define GOTHTHBONUS "BONUS DE SANTE RECUPERE."
#define GOTARMBONUS "BONUS D'ARMURE RECUPERE."
#define GOTSTIM "STIMPACK RECUPERE."
#define GOTMEDINEED "MEDIKIT RECUPERE. VOUS EN AVEZ VRAIMENT BESOIN!"
#define GOTMEDIKIT "MEDIKIT RECUPERE."
#define GOTSUPER "SUPERCHARGE!"
#define GOTBLUECARD "CARTE MAGNETIQUE BLEUE RECUPEREE."
#define GOTYELWCARD "CARTE MAGNETIQUE JAUNE RECUPEREE."
#define GOTREDCARD "CARTE MAGNETIQUE ROUGE RECUPEREE."
#define GOTBLUESKUL "CLEF CRANE BLEUE RECUPEREE."
#define GOTYELWSKUL "CLEF CRANE JAUNE RECUPEREE."
#define GOTREDSKULL "CLEF CRANE ROUGE RECUPEREE."
#define GOTINVUL "INVULNERABILITE!"
#define GOTBERSERK "BERSERK!"
#define GOTINVIS "INVISIBILITE PARTIELLE "
#define GOTSUIT "COMBINAISON ANTI-RADIATIONS "
#define GOTMAP "CARTE INFORMATIQUE "
#define GOTVISOR "VISEUR A AMPLIFICATION DE LUMIERE "
#define GOTMSPHERE "MEGASPHERE!"
#define GOTCLIP "CHARGEUR RECUPERE."
#define GOTCLIPBOX "BOITE DE BALLES RECUPEREE."
#define GOTROCKET "ROQUETTE RECUPEREE."
#define GOTROCKBOX "CAISSE DE ROQUETTES RECUPEREE."
#define GOTCELL "CELLULE D'ENERGIE RECUPEREE."
#define GOTCELLBOX "PACK DE CELLULES D'ENERGIE RECUPERE."
#define GOTSHELLS "4 CARTOUCHES RECUPEREES."
#define GOTSHELLBOX "BOITE DE CARTOUCHES RECUPEREE."
#define GOTBACKPACK "SAC PLEIN DE MUNITIONS RECUPERE!"
#define GOTBFG9000 "VOUS AVEZ UN BFG9000! OH, OUI!"
#define GOTCHAINGUN "VOUS AVEZ LA MITRAILLEUSE!"
#define GOTCHAINSAW "UNE TRONCONNEUSE!"
#define GOTLAUNCHER "VOUS AVEZ UN LANCE-ROQUETTES!"
#define GOTPLASMA "VOUS AVEZ UN FUSIL A PLASMA!"
#define GOTSHOTGUN "VOUS AVEZ UN FUSIL!"
#define GOTSHOTGUN2 "VOUS AVEZ UN SUPER FUSIL!"
//
// P_Doors.C
//
#define PD_BLUEO "IL VOUS FAUT UNE CLEF BLEUE"
#define PD_REDO "IL VOUS FAUT UNE CLEF ROUGE"
#define PD_YELLOWO "IL VOUS FAUT UNE CLEF JAUNE"
#define PD_BLUEK PD_BLUEO
#define PD_REDK PD_REDO
#define PD_YELLOWK PD_YELLOWO
//
// G_game.C
//
#define GGSAVED "JEU SAUVEGARDE."
//
// HU_stuff.C
//
#define HUSTR_MSGU "[MESSAGE NON ENVOYE]"
#define HUSTR_E1M1 "E1M1: HANGAR"
#define HUSTR_E1M2 "E1M2: USINE NUCLEAIRE "
#define HUSTR_E1M3 "E1M3: RAFFINERIE DE TOXINES "
#define HUSTR_E1M4 "E1M4: CENTRE DE CONTROLE "
#define HUSTR_E1M5 "E1M5: LABORATOIRE PHOBOS "
#define HUSTR_E1M6 "E1M6: TRAITEMENT CENTRAL "
#define HUSTR_E1M7 "E1M7: CENTRE INFORMATIQUE "
#define HUSTR_E1M8 "E1M8: ANOMALIE PHOBOS "
#define HUSTR_E1M9 "E1M9: BASE MILITAIRE "
#define HUSTR_E2M1 "E2M1: ANOMALIE DEIMOS "
#define HUSTR_E2M2 "E2M2: ZONE DE CONFINEMENT "
#define HUSTR_E2M3 "E2M3: RAFFINERIE"
#define HUSTR_E2M4 "E2M4: LABORATOIRE DEIMOS "
#define HUSTR_E2M5 "E2M5: CENTRE DE CONTROLE "
#define HUSTR_E2M6 "E2M6: HALLS DES DAMNES "
#define HUSTR_E2M7 "E2M7: CUVES DE REPRODUCTION "
#define HUSTR_E2M8 "E2M8: TOUR DE BABEL "
#define HUSTR_E2M9 "E2M9: FORTERESSE DU MYSTERE "
#define HUSTR_E3M1 "E3M1: DONJON DE L'ENFER "
#define HUSTR_E3M2 "E3M2: BOURBIER DU DESESPOIR "
#define HUSTR_E3M3 "E3M3: PANDEMONIUM"
#define HUSTR_E3M4 "E3M4: MAISON DE LA DOULEUR "
#define HUSTR_E3M5 "E3M5: CATHEDRALE PROFANE "
#define HUSTR_E3M6 "E3M6: MONT EREBUS"
#define HUSTR_E3M7 "E3M7: LIMBES"
#define HUSTR_E3M8 "E3M8: DIS"
#define HUSTR_E3M9 "E3M9: CLAPIERS"
#define HUSTR_1 "NIVEAU 1: ENTREE "
#define HUSTR_2 "NIVEAU 2: HALLS SOUTERRAINS "
#define HUSTR_3 "NIVEAU 3: LE FEU NOURRI "
#define HUSTR_4 "NIVEAU 4: LE FOYER "
#define HUSTR_5 "NIVEAU 5: LES EGOUTS "
#define HUSTR_6 "NIVEAU 6: LE BROYEUR "
#define HUSTR_7 "NIVEAU 7: L'HERBE DE LA MORT"
#define HUSTR_8 "NIVEAU 8: RUSES ET PIEGES "
#define HUSTR_9 "NIVEAU 9: LE PUITS "
#define HUSTR_10 "NIVEAU 10: BASE DE RAVITAILLEMENT "
#define HUSTR_11 "NIVEAU 11: LE CERCLE DE LA MORT!"
#define HUSTR_12 "NIVEAU 12: L'USINE "
#define HUSTR_13 "NIVEAU 13: LE CENTRE VILLE"
#define HUSTR_14 "NIVEAU 14: LES ANTRES PROFONDES "
#define HUSTR_15 "NIVEAU 15: LA ZONE INDUSTRIELLE "
#define HUSTR_16 "NIVEAU 16: LA BANLIEUE"
#define HUSTR_17 "NIVEAU 17: LES IMMEUBLES"
#define HUSTR_18 "NIVEAU 18: LA COUR "
#define HUSTR_19 "NIVEAU 19: LA CITADELLE "
#define HUSTR_20 "NIVEAU 20: JE T'AI EU!"
#define HUSTR_21 "NIVEAU 21: LE NIRVANA"
#define HUSTR_22 "NIVEAU 22: LES CATACOMBES "
#define HUSTR_23 "NIVEAU 23: LA GRANDE FETE "
#define HUSTR_24 "NIVEAU 24: LE GOUFFRE "
#define HUSTR_25 "NIVEAU 25: LES CHUTES DE SANG"
#define HUSTR_26 "NIVEAU 26: LES MINES ABANDONNEES "
#define HUSTR_27 "NIVEAU 27: CHEZ LES MONSTRES "
#define HUSTR_28 "NIVEAU 28: LE MONDE DE L'ESPRIT "
#define HUSTR_29 "NIVEAU 29: LA LIMITE "
#define HUSTR_30 "NIVEAU 30: L'ICONE DU PECHE "
#define HUSTR_31 "NIVEAU 31: WOLFENSTEIN"
#define HUSTR_32 "NIVEAU 32: LE MASSACRE"
#define HUSTR_CHATMACRO1 "JE SUIS PRET A LEUR EN FAIRE BAVER!"
#define HUSTR_CHATMACRO2 "JE VAIS BIEN."
#define HUSTR_CHATMACRO3 "JE N'AI PAS L'AIR EN FORME!"
#define HUSTR_CHATMACRO4 "AU SECOURS!"
#define HUSTR_CHATMACRO5 "TU CRAINS!"
#define HUSTR_CHATMACRO6 "LA PROCHAINE FOIS, MINABLE..."
#define HUSTR_CHATMACRO7 "VIENS ICI!"
#define HUSTR_CHATMACRO8 "JE VAIS M'EN OCCUPER."
#define HUSTR_CHATMACRO9 "OUI"
#define HUSTR_CHATMACRO0 "NON"
#define HUSTR_TALKTOSELF1 "VOUS PARLEZ TOUT SEUL "
#define HUSTR_TALKTOSELF2 "QUI EST LA?"
#define HUSTR_TALKTOSELF3 "VOUS VOUS FAITES PEUR "
#define HUSTR_TALKTOSELF4 "VOUS COMMENCEZ A DELIRER "
#define HUSTR_TALKTOSELF5 "VOUS ETES LARGUE..."
#define HUSTR_MESSAGESENT "[MESSAGE ENVOYE]"
// The following should NOT be changed unless it seems
// just AWFULLY necessary
#define HUSTR_PLRGREEN "VERT: "
#define HUSTR_PLRINDIGO "INDIGO: "
#define HUSTR_PLRBROWN "BRUN: "
#define HUSTR_PLRRED "ROUGE: "
#define HUSTR_KEYGREEN 'g' // french key should be "V"
#define HUSTR_KEYINDIGO 'i'
#define HUSTR_KEYBROWN 'b'
#define HUSTR_KEYRED 'r'
//
// AM_map.C
//
#define AMSTR_FOLLOWON "MODE POURSUITE ON"
#define AMSTR_FOLLOWOFF "MODE POURSUITE OFF"
#define AMSTR_GRIDON "GRILLE ON"
#define AMSTR_GRIDOFF "GRILLE OFF"
#define AMSTR_MARKEDSPOT "REPERE MARQUE "
#define AMSTR_MARKSCLEARED "REPERES EFFACES "
//
// ST_stuff.C
//
#define STSTR_MUS "CHANGEMENT DE MUSIQUE "
#define STSTR_NOMUS "IMPOSSIBLE SELECTION"
#define STSTR_DQDON "INVULNERABILITE ON "
#define STSTR_DQDOFF "INVULNERABILITE OFF"
#define STSTR_KFAADDED "ARMEMENT MAXIMUM! "
#define STSTR_FAADDED "ARMES (SAUF CLEFS) AJOUTEES"
#define STSTR_NCON "BARRIERES ON"
#define STSTR_NCOFF "BARRIERES OFF"
#define STSTR_BEHOLD " inVuln, Str, Inviso, Rad, Allmap, or Lite-amp"
#define STSTR_BEHOLDX "AMELIORATION ACTIVEE"
#define STSTR_CHOPPERS "... DOESN'T SUCK - GM"
#define STSTR_CLEV "CHANGEMENT DE NIVEAU..."
//
// F_Finale.C
//
#define E1TEXT "APRES AVOIR VAINCU LES GROS MECHANTS\n"\
"ET NETTOYE LA BASE LUNAIRE, VOUS AVEZ\n"\
"GAGNE, NON? PAS VRAI? OU EST DONC VOTRE\n"\
" RECOMPENSE ET VOTRE BILLET DE\n"\
"RETOUR? QU'EST-QUE CA VEUT DIRE?CE"\
"N'EST PAS LA FIN ESPEREE!\n"\
"\n" \
"CA SENT LA VIANDE PUTREFIEE, MAIS\n"\
"ON DIRAIT LA BASE DEIMOS. VOUS ETES\n"\
"APPAREMMENT BLOQUE AUX PORTES DE L'ENFER.\n"\
"LA SEULE ISSUE EST DE L'AUTRE COTE.\n"\
"\n"\
"POUR VIVRE LA SUITE DE DOOM, JOUEZ\n"\
"A 'AUX PORTES DE L'ENFER' ET A\n"\
"L'EPISODE SUIVANT, 'L'ENFER'!\n"
#define E2TEXT "VOUS AVEZ REUSSI. L'INFAME DEMON\n"\
"QUI CONTROLAIT LA BASE LUNAIRE DE\n"\
"DEIMOS EST MORT, ET VOUS AVEZ\n"\
"TRIOMPHE! MAIS... OU ETES-VOUS?\n"\
"VOUS GRIMPEZ JUSQU'AU BORD DE LA\n"\
"LUNE ET VOUS DECOUVREZ L'ATROCE\n"\
"VERITE.\n" \
"\n"\
"DEIMOS EST AU-DESSUS DE L'ENFER!\n"\
"VOUS SAVEZ QUE PERSONNE NE S'EN\n"\
"EST JAMAIS ECHAPPE, MAIS CES FUMIERS\n"\
"VONT REGRETTER DE VOUS AVOIR CONNU!\n"\
"VOUS REDESCENDEZ RAPIDEMENT VERS\n"\
"LA SURFACE DE L'ENFER.\n"\
"\n" \
"VOICI MAINTENANT LE CHAPITRE FINAL DE\n"\
"DOOM! -- L'ENFER."
#define E3TEXT "LE DEMON ARACHNEEN ET REPUGNANT\n"\
"QUI A DIRIGE L'INVASION DES BASES\n"\
"LUNAIRES ET SEME LA MORT VIENT DE SE\n"\
"FAIRE PULVERISER UNE FOIS POUR TOUTES.\n"\
"\n"\
"UNE PORTE SECRETE S'OUVRE. VOUS ENTREZ.\n"\
"VOUS AVEZ PROUVE QUE VOUS POUVIEZ\n"\
"RESISTER AUX HORREURS DE L'ENFER.\n"\
"IL SAIT ETRE BEAU JOUEUR, ET LORSQUE\n"\
"VOUS SORTEZ, VOUS REVOYEZ LES VERTES\n"\
"PRAIRIES DE LA TERRE, VOTRE PLANETE.\n"\
"\n"\
"VOUS VOUS DEMANDEZ CE QUI S'EST PASSE\n"\
"SUR TERRE PENDANT QUE VOUS AVEZ\n"\
"COMBATTU LE DEMON. HEUREUSEMENT,\n"\
"AUCUN GERME DU MAL N'A FRANCHI\n"\
"CETTE PORTE AVEC VOUS..."
// after level 6, put this:
#define C1TEXT "VOUS ETES AU PLUS PROFOND DE L'ASTROPORT\n" \
"INFESTE DE MONSTRES, MAIS QUELQUE CHOSE\n" \
"NE VA PAS. ILS ONT APPORTE LEUR PROPRE\n" \
"REALITE, ET LA TECHNOLOGIE DE L'ASTROPORT\n" \
"EST AFFECTEE PAR LEUR PRESENCE.\n" \
"\n"\
"DEVANT VOUS, VOUS VOYEZ UN POSTE AVANCE\n" \
"DE L'ENFER, UNE ZONE FORTIFIEE. SI VOUS\n" \
"POUVEZ PASSER, VOUS POURREZ PENETRER AU\n" \
"COEUR DE LA BASE HANTEE ET TROUVER \n" \
"L'INTERRUPTEUR DE CONTROLE QUI GARDE LA \n" \
"POPULATION DE LA TERRE EN OTAGE."
// After level 11, put this:
#define C2TEXT "VOUS AVEZ GAGNE! VOTRE VICTOIRE A PERMIS\n" \
"A L'HUMANITE D'EVACUER LA TERRE ET \n"\
"D'ECHAPPER AU CAUCHEMAR. VOUS ETES \n"\
"MAINTENANT LE DERNIER HUMAIN A LA SURFACE \n"\
"DE LA PLANETE. VOUS ETES ENTOURE DE \n"\
"MUTANTS CANNIBALES, D'EXTRATERRESTRES \n"\
"CARNIVORES ET D'ESPRITS DU MAL. VOUS \n"\
"ATTENDEZ CALMEMENT LA MORT, HEUREUX \n"\
"D'AVOIR PU SAUVER VOTRE RACE.\n"\
"MAIS UN MESSAGE VOUS PARVIENT SOUDAIN\n"\
"DE L'ESPACE: \"NOS CAPTEURS ONT LOCALISE\n"\
"LA SOURCE DE L'INVASION EXTRATERRESTRE.\n"\
"SI VOUS Y ALLEZ, VOUS POURREZ PEUT-ETRE\n"\
"LES ARRETER. LEUR BASE EST SITUEE AU COEUR\n"\
"DE VOTRE VILLE NATALE, PRES DE L'ASTROPORT.\n"\
"VOUS VOUS RELEVEZ LENTEMENT ET PENIBLEMENT\n"\
"ET VOUS REPARTEZ POUR LE FRONT."
// After level 20, put this:
#define C3TEXT "VOUS ETES AU COEUR DE LA CITE CORROMPUE,\n"\
"ENTOURE PAR LES CADAVRES DE VOS ENNEMIS.\n"\
"VOUS NE VOYEZ PAS COMMENT DETRUIRE LA PORTE\n"\
"DES CREATURES DE CE COTE. VOUS SERREZ\n"\
"LES DENTS ET PLONGEZ DANS L'OUVERTURE.\n"\
"\n"\
"IL DOIT Y AVOIR UN MOYEN DE LA FERMER\n"\
"DE L'AUTRE COTE. VOUS ACCEPTEZ DE\n"\
"TRAVERSER L'ENFER POUR LE FAIRE?"
// After level 29, put this:
#define C4TEXT "LE VISAGE HORRIBLE D'UN DEMON D'UNE\n"\
"TAILLE INCROYABLE S'EFFONDRE DEVANT\n"\
"VOUS LORSQUE VOUS TIREZ UNE SALVE DE\n"\
"ROQUETTES DANS SON CERVEAU. LE MONSTRE\n"\
"SE RATATINE, SES MEMBRES DECHIQUETES\n"\
"SE REPANDANT SUR DES CENTAINES DE\n"\
"KILOMETRES A LA SURFACE DE L'ENFER.\n"\
"\n"\
"VOUS AVEZ REUSSI. L'INVASION N'AURA.\n"\
"PAS LIEU. LA TERRE EST SAUVEE. L'ENFER\n"\
"EST ANEANTI. EN VOUS DEMANDANT OU IRONT\n"\
"MAINTENANT LES DAMNES, VOUS ESSUYEZ\n"\
"VOTRE FRONT COUVERT DE SUEUR ET REPARTEZ\n"\
"VERS LA TERRE. SA RECONSTRUCTION SERA\n"\
"BEAUCOUP PLUS DROLE QUE SA DESTRUCTION.\n"
// Before level 31, put this:
#define C5TEXT "FELICITATIONS! VOUS AVEZ TROUVE LE\n"\
"NIVEAU SECRET! IL SEMBLE AVOIR ETE\n"\
"CONSTRUIT PAR LES HUMAINS. VOUS VOUS\n"\
"DEMANDEZ QUELS PEUVENT ETRE LES\n"\
"HABITANTS DE CE COIN PERDU DE L'ENFER."
// Before level 32, put this:
#define C6TEXT "FELICITATIONS! VOUS AVEZ DECOUVERT\n"\
"LE NIVEAU SUPER SECRET! VOUS FERIEZ\n"\
"MIEUX DE FONCER DANS CELUI-LA!\n"
//
// Character cast strings F_FINALE.C
//
#define CC_ZOMBIE "ZOMBIE"
#define CC_SHOTGUN "TYPE AU FUSIL"
#define CC_HEAVY "MEC SUPER-ARME"
#define CC_IMP "DIABLOTIN"
#define CC_DEMON "DEMON"
#define CC_LOST "AME PERDUE"
#define CC_CACO "CACODEMON"
#define CC_HELL "CHEVALIER DE L'ENFER"
#define CC_BARON "BARON DE L'ENFER"
#define CC_ARACH "ARACHNOTRON"
#define CC_PAIN "ELEMENTAIRE DE LA DOULEUR"
#define CC_REVEN "REVENANT"
#define CC_MANCU "MANCUBUS"
#define CC_ARCH "ARCHI-INFAME"
#define CC_SPIDER "L'ARAIGNEE CERVEAU"
#define CC_CYBER "LE CYBERDEMON"
#define CC_HERO "NOTRE HEROS"
#endif
//-----------------------------------------------------------------------------
//
// $Log$
// Revision 1.1 2006/03/28 15:44:01 dave
// Patch #2969 - Doom! Currently only working on the H300.
//
//
//-----------------------------------------------------------------------------

138
apps/plugins/doom/d_items.c Normal file
View file

@ -0,0 +1,138 @@
/* Emacs style mode select -*- C++ -*-
*-----------------------------------------------------------------------------
*
*
* PrBoom a Doom port merged with LxDoom and LSDLDoom
* based on BOOM, a modified and improved DOOM engine
* Copyright (C) 1999 by
* id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
* Copyright (C) 1999-2000 by
* Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* DESCRIPTION:
* Something to do with weapon sprite frames. Don't ask me.
*
*-----------------------------------------------------------------------------
*/
// We are referring to sprite numbers.
#include "doomtype.h"
#include "info.h"
#ifdef __GNUG__
#pragma implementation "d_items.h"
#endif
#include "d_items.h"
//
// PSPRITE ACTIONS for waepons.
// This struct controls the weapon animations.
//
// Each entry is:
// ammo/amunition type
// upstate
// downstate
// readystate
// atkstate, i.e. attack/fire/hit frame
// flashstate, muzzle flash
//
weaponinfo_t weaponinfo[NUMWEAPONS] =
{
{
// fist
am_noammo,
S_PUNCHUP,
S_PUNCHDOWN,
S_PUNCH,
S_PUNCH1,
S_NULL
},
{
// pistol
am_clip,
S_PISTOLUP,
S_PISTOLDOWN,
S_PISTOL,
S_PISTOL1,
S_PISTOLFLASH
},
{
// shotgun
am_shell,
S_SGUNUP,
S_SGUNDOWN,
S_SGUN,
S_SGUN1,
S_SGUNFLASH1
},
{
// chaingun
am_clip,
S_CHAINUP,
S_CHAINDOWN,
S_CHAIN,
S_CHAIN1,
S_CHAINFLASH1
},
{
// missile launcher
am_misl,
S_MISSILEUP,
S_MISSILEDOWN,
S_MISSILE,
S_MISSILE1,
S_MISSILEFLASH1
},
{
// plasma rifle
am_cell,
S_PLASMAUP,
S_PLASMADOWN,
S_PLASMA,
S_PLASMA1,
S_PLASMAFLASH1
},
{
// bfg 9000
am_cell,
S_BFGUP,
S_BFGDOWN,
S_BFG,
S_BFG1,
S_BFGFLASH1
},
{
// chainsaw
am_noammo,
S_SAWUP,
S_SAWDOWN,
S_SAW,
S_SAW1,
S_NULL
},
{
// super shotgun
am_shell,
S_DSGUNUP,
S_DSGUNDOWN,
S_DSGUN,
S_DSGUN1,
S_DSGUNFLASH1
},
};

View file

@ -0,0 +1,57 @@
/* Emacs style mode select -*- C++ -*-
*-----------------------------------------------------------------------------
*
*
* PrBoom a Doom port merged with LxDoom and LSDLDoom
* based on BOOM, a modified and improved DOOM engine
* Copyright (C) 1999 by
* id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
* Copyright (C) 1999-2000 by
* Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* DESCRIPTION:
* Items: key cards, artifacts, weapon, ammunition.
*
*-----------------------------------------------------------------------------*/
#ifndef __D_ITEMS__
#define __D_ITEMS__
#include "doomdef.h"
#ifdef __GNUG__
#pragma interface
#endif
/* Weapon info: sprite frames, ammunition use. */
typedef struct
{
ammotype_t ammo;
int upstate;
int downstate;
int readystate;
int atkstate;
int flashstate;
} weaponinfo_t;
extern weaponinfo_t weaponinfo[NUMWEAPONS];
#endif

844
apps/plugins/doom/d_main.c Normal file
View file

@ -0,0 +1,844 @@
/* Emacs style mode select -*- C++ -*-
*-----------------------------------------------------------------------------
*
*
* PrBoom a Doom port merged with LxDoom and LSDLDoom
* based on BOOM, a modified and improved DOOM engine
* Copyright (C) 1999 by
* id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
* Copyright (C) 1999-2000 by
* Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* DESCRIPTION:
* DOOM main program (D_DoomMain) and game loop (D_DoomLoop),
* plus functions to determine game mode (shareware, registered),
* parse command line parameters, configure game parameters (turbo),
* and call the startup functions.
*
*-----------------------------------------------------------------------------
*/
#include "rockmacros.h"
#include "doomdef.h"
#include "doomtype.h"
#include "doomstat.h"
#include "dstrings.h"
#include "sounds.h"
#include "z_zone.h"
#include "w_wad.h"
#include "s_sound.h"
#include "v_video.h"
#include "f_finale.h"
#include "f_wipe.h"
#include "m_argv.h"
#include "m_misc.h"
#include "m_menu.h"
#include "i_system.h"
#include "i_sound.h"
#include "i_video.h"
#include "g_game.h"
#include "hu_stuff.h"
#include "wi_stuff.h"
#include "st_stuff.h"
#include "am_map.h"
#include "p_setup.h"
#include "r_draw.h"
#include "r_main.h"
#include "d_main.h"
#include "am_map.h"
#include "m_swap.h"
// CPhipps - removed wadfiles[] stuff
boolean devparm; // started game with -devparm
// jff 1/24/98 add new versions of these variables to remember command line
boolean clnomonsters; // checkparm of -nomonsters
boolean clrespawnparm; // checkparm of -respawn
boolean clfastparm; // checkparm of -fast
// jff 1/24/98 end definition of command line version of play mode switches
boolean nomonsters; // working -nomonsters
boolean respawnparm; // working -respawn
boolean fastparm; // working -fast
boolean singletics = false; // debug flag to cancel adaptiveness
boolean doomexit;
//jff 1/22/98 parms for disabling music and sound
boolean nosfxparm;
boolean nomusicparm;
//jff 4/18/98
extern boolean inhelpscreens;
skill_t startskill;
int startepisode;
int startmap;
boolean autostart;
int debugfile;
int ffmap;
boolean advancedemo;
extern boolean timingdemo, singledemo, demoplayback, fastdemo; // killough
int basetic;
void D_DoAdvanceDemo (void);
/*
* D_PostEvent - Event handling
*
* Called by I/O functions when an event is received.
* Try event handlers for each code area in turn.
* cph - in the true spirit of the Boom source, let the
* short ciruit operator madness begin!
*/
void D_PostEvent(event_t *ev)
{
/* cph - suppress all input events at game start
* FIXME: This is a lousy kludge */
if (gametic < 3) return;
M_Responder(ev) ||
(gamestate == GS_LEVEL && (
HU_Responder(ev) ||
ST_Responder(ev) ||
AM_Responder(ev)
)
) ||
G_Responder(ev);
}
//
// D_Wipe
//
// CPhipps - moved the screen wipe code from D_Display to here
// The screens to wipe between are already stored, this just does the timing
// and screen updating
static void D_Wipe(void)
{
boolean done;
int wipestart = I_GetTime () - 1;
do
{
int nowtime, tics;
do
{
//I_uSleep(5000); // CPhipps - don't thrash cpu in this loop
nowtime = I_GetTime();
tics = nowtime - wipestart;
}
while (!tics);
wipestart = nowtime;
done = wipe_ScreenWipe(0,0,SCREENWIDTH,SCREENHEIGHT,tics);
I_UpdateNoBlit();
M_Drawer(); // menu is drawn even on top of wipes
I_FinishUpdate(); // page flip or blit buffer
}
while (!done);
}
//
// D_Display
// draw current display, possibly wiping it from the previous
//
// wipegamestate can be set to -1 to force a wipe on the next draw
gamestate_t wipegamestate = GS_DEMOSCREEN;
extern boolean setsizeneeded;
extern int showMessages;
void D_Display (void)
{
static boolean isborderstate = false;
static boolean borderwillneedredraw = false;
static boolean inhelpscreensstate = false;
static gamestate_t oldgamestate = -1;
boolean wipe;
boolean viewactive = false, isborder = false;
if (nodrawers) // for comparative timing / profiling
return;
// save the current screen if about to wipe
if ((wipe = gamestate != wipegamestate))
wipe_StartScreen(0, 0, SCREENWIDTH, SCREENHEIGHT);
if (gamestate != GS_LEVEL) { // Not a level
switch (oldgamestate) {
case -1:
case GS_LEVEL:
V_SetPalette(0); // cph - use default (basic) palette
default:
break;
}
switch (gamestate) {
case GS_INTERMISSION:
WI_Drawer();
break;
case GS_FINALE:
F_Drawer();
break;
case GS_DEMOSCREEN:
D_PageDrawer();
break;
default:
break;
}
} else if (gametic != basetic) { // In a level
boolean redrawborderstuff;
HU_Erase();
if (setsizeneeded) { // change the view size if needed
R_ExecuteSetViewSize();
oldgamestate = -1; // force background redraw
}
// Work out if the player view is visible, and if there is a border
viewactive = (!(automapmode & am_active) || (automapmode & am_overlay)) && !inhelpscreens;
isborder = viewactive ? (viewheight != SCREENHEIGHT) : (!inhelpscreens && (automapmode & am_active));
if (oldgamestate != GS_LEVEL) {
R_FillBackScreen (); // draw the pattern into the back screen
redrawborderstuff = isborder;
} else {
// CPhipps -
// If there is a border, and either there was no border last time,
// or the border might need refreshing, then redraw it.
redrawborderstuff = isborder && (!isborderstate || borderwillneedredraw);
// The border may need redrawing next time if the border surrounds the screen,
// and there is a menu being displayed
borderwillneedredraw = menuactive && isborder && viewactive && (viewwidth != SCREENWIDTH);
}
if (redrawborderstuff)
R_DrawViewBorder();
// Now do the drawing
if (viewactive)
R_RenderPlayerView (&players[displayplayer]);
if (automapmode & am_active)
AM_Drawer();
ST_Drawer((viewheight != SCREENHEIGHT) || ((automapmode & am_active) && !(automapmode & am_overlay)), redrawborderstuff);
R_DrawViewBorder();
HU_Drawer();
}
inhelpscreensstate = inhelpscreens;
isborderstate = isborder;
oldgamestate = wipegamestate = gamestate;
// draw pause pic
if (paused) {
static int x;
if (!x) { // Cache results of x pos calc
int lump = W_GetNumForName("M_PAUSE");
const patch_t* p = W_CacheLumpNum(lump);
x = (320 - SHORT(p->width))/2;
W_UnlockLumpNum(lump);
}
// CPhipps - updated for new patch drawing
V_DrawNamePatch(x, (!(automapmode & am_active) || (automapmode & am_overlay))
? 4+(viewwindowy*200/SCREENHEIGHT) : 4, // cph - Must un-stretch viewwindowy
0, "M_PAUSE", CR_DEFAULT, VPT_STRETCH);
}
// menus go directly to the screen
M_Drawer(); // menu is drawn even on top of everything
D_BuildNewTiccmds();
// normal update
if (!wipe)
I_FinishUpdate (); // page flip or blit buffer
else {
// wipe update
wipe_EndScreen(0, 0, SCREENWIDTH, SCREENHEIGHT);
D_Wipe();
}
}
//
// D_DoomLoop()
//
// Not a globally visible function,
// just included for source reference,
// called by D_DoomMain, never exits.
// Manages timing and IO,
// calls all ?_Responder, ?_Ticker, and ?_Drawer,
// calls I_GetTime, I_StartFrame, and I_StartTic
//
extern boolean demorecording;
static void D_DoomLoop (void)
{
basetic = gametic;
I_SubmitSound();
while (!doomexit)
{
// frame syncronous IO operations
//I_StartFrame ();
// process one or more tics
if (singletics)
{
I_StartTic ();
G_BuildTiccmd (&netcmds[consoleplayer][maketic%BACKUPTICS]);
if (advancedemo)
D_DoAdvanceDemo ();
M_Ticker ();
G_Ticker ();
gametic++;
maketic++;
}
else
TryRunTics (); // will run at least one tic
// killough 3/16/98: change consoleplayer to displayplayer
if (players[displayplayer].mo) // cph 2002/08/10
S_UpdateSounds(players[displayplayer].mo);// move positional sounds
// Update display, next frame, with current state.
D_Display();
// Sound mixing for the buffer is snychronous.
// I_UpdateSound();
rb->yield();
}
}
//
// DEMO LOOP
//
static int demosequence; // killough 5/2/98: made static
static int pagetic;
static const char *pagename; // CPhipps - const
//
// D_PageTicker
// Handles timing for warped projection
//
void D_PageTicker(void)
{
if (--pagetic < 0)
D_AdvanceDemo();
}
//
// D_PageDrawer
//
void D_PageDrawer(void)
{
// CPhipps - updated for new patch drawing
V_DrawNamePatch(0, 0, 0, pagename, CR_DEFAULT, VPT_STRETCH);
}
//
// D_AdvanceDemo
// Called after each demo or intro demosequence finishes
//
void D_AdvanceDemo (void)
{
advancedemo = true;
}
/* killough 11/98: functions to perform demo sequences
* cphipps 10/99: constness fixes
*/
static void D_SetPageName(const char *name)
{
pagename = name;
}
static void D_DrawTitle1(const char *name)
{
S_StartMusic(mus_intro);
pagetic = (TICRATE*170)/35;
D_SetPageName(name);
}
static void D_DrawTitle2(const char *name)
{
S_StartMusic(mus_dm2ttl);
D_SetPageName(name);
}
/* killough 11/98: tabulate demo sequences
*/
static struct
{
void (*func)(const char *);
const char *name;
} const demostates[][4] =
{
{
{D_DrawTitle1, "TITLEPIC"},
{D_DrawTitle1, "TITLEPIC"},
{D_DrawTitle2, "TITLEPIC"},
{D_DrawTitle1, "TITLEPIC"},
},
{
{G_DeferedPlayDemo, "demo1"},
{G_DeferedPlayDemo, "demo1"},
{G_DeferedPlayDemo, "demo1"},
{G_DeferedPlayDemo, "demo1"},
},
{
{D_SetPageName, "CREDIT"},
{D_SetPageName, "CREDIT"},
{D_SetPageName, "CREDIT"},
{D_SetPageName, "CREDIT"},
},
{
{G_DeferedPlayDemo, "demo2"},
{G_DeferedPlayDemo, "demo2"},
{G_DeferedPlayDemo, "demo2"},
{G_DeferedPlayDemo, "demo2"},
},
{
{D_SetPageName, "HELP2"},
{D_SetPageName, "HELP2"},
{D_SetPageName, "CREDIT"},
{D_DrawTitle1, "TITLEPIC"},
},
{
{G_DeferedPlayDemo, "demo3"},
{G_DeferedPlayDemo, "demo3"},
{G_DeferedPlayDemo, "demo3"},
{G_DeferedPlayDemo, "demo3"},
},
{
{NULL,0},
{NULL,0},
{NULL,0},
{D_SetPageName, "CREDIT"},
},
{
{NULL,0},
{NULL,0},
{NULL,0},
{G_DeferedPlayDemo, "demo4"},
},
{
{NULL,0},
{NULL,0},
{NULL,0},
{NULL,0},
}
};
/*
* This cycles through the demo sequences.
* killough 11/98: made table-driven
*/
void D_DoAdvanceDemo(void)
{
players[consoleplayer].playerstate = PST_LIVE; /* not reborn */
advancedemo = usergame = paused = false;
gameaction = ga_nothing;
pagetic = TICRATE * 11; /* killough 11/98: default behavior */
gamestate = GS_DEMOSCREEN;
if (netgame && !demoplayback) {
demosequence = 0;
} else
if (!demostates[++demosequence][gamemode].func)
demosequence = 0;
demostates[demosequence][gamemode].func(demostates[demosequence][gamemode].name);
}
//
// D_StartTitle
//
void D_StartTitle (void)
{
gameaction = ga_nothing;
demosequence = -1;
D_AdvanceDemo();
}
//
// D_AddFile
//
// Rewritten by Lee Killough
//
// Ty 08/29/98 - add source parm to indicate where this came from
// CPhipps - static, const char* parameter
// - source is an enum
// - modified to allocate & use new wadfiles array
void D_AddFile (const char *file, wad_source_t source)
{
wadfiles = realloc(wadfiles, sizeof(*wadfiles)*(numwadfiles+1));
wadfiles[numwadfiles].name =
AddDefaultExtension(strcpy(malloc(strlen(file)+5), file), ".wad");
wadfiles[numwadfiles].src = source; // Ty 08/29/98
numwadfiles++;
}
//
// CheckIWAD
//
// Verify a file is indeed tagged as an IWAD
// Scan its lumps for levelnames and return gamemode as indicated
// Detect missing wolf levels in DOOM II
//
// The filename to check is passed in iwadname, the gamemode detected is
// returned in gmode, hassec returns the presence of secret levels
//
// jff 4/19/98 Add routine to test IWAD for validity and determine
// the gamemode from it. Also note if DOOM II, whether secret levels exist
// CPhipps - const char* for iwadname, made static
#if 0
static void CheckIWAD(const char *iwadname,GameMode_t *gmode,boolean *hassec)
{
if ( !fileexists (iwadname) )
{
int ud=0,rg=0,sw=0,cm=0,sc=0;
int handle;
// Identify IWAD correctly
if ( (handle = open (iwadname,O_RDONLY)) != -1)
{
wadinfo_t header;
// read IWAD header
read (handle, &header, sizeof(header));
if (!strncmp(header.identification,"IWAD",4))
{
size_t length;
filelump_t *fileinfo;
// read IWAD directory
header.numlumps = LONG(header.numlumps);
header.infotableofs = LONG(header.infotableofs);
length = header.numlumps;
fileinfo = malloc(length*sizeof(filelump_t));
lseek (handle, header.infotableofs, SEEK_SET);
read (handle, fileinfo, length*sizeof(filelump_t));
close(handle);
// scan directory for levelname lumps
while (length--)
if (fileinfo[length].name[0] == 'E' &&
fileinfo[length].name[2] == 'M' &&
fileinfo[length].name[4] == 0)
{
if (fileinfo[length].name[1] == '4')
++ud;
else if (fileinfo[length].name[1] == '3')
++rg;
else if (fileinfo[length].name[1] == '2')
++rg;
else if (fileinfo[length].name[1] == '1')
++sw;
}
else if (fileinfo[length].name[0] == 'M' &&
fileinfo[length].name[1] == 'A' &&
fileinfo[length].name[2] == 'P' &&
fileinfo[length].name[5] == 0)
{
++cm;
if (fileinfo[length].name[3] == '3')
if (fileinfo[length].name[4] == '1' ||
fileinfo[length].name[4] == '2')
++sc;
}
free(fileinfo);
}
else // missing IWAD tag in header
I_Error("CheckIWAD: IWAD tag %s not present", iwadname);
}
else // error from open call
I_Error("CheckIWAD: Can't open IWAD %s", iwadname);
// Determine game mode from levels present
// Must be a full set for whichever mode is present
// Lack of wolf-3d levels also detected here
*gmode = indetermined;
*hassec = false;
if (cm>=30)
{
*gmode = commercial;
*hassec = sc>=2;
}
else if (ud>=9)
*gmode = retail;
else if (rg>=18)
*gmode = registered;
else if (sw>=9)
*gmode = shareware;
}
else // error from access call
I_Error("CheckIWAD: IWAD %s not readable", iwadname);
}
#endif
void D_DoomMainSetup(void)
{
int p;
nomonsters = M_CheckParm ("-nomonsters");
respawnparm = M_CheckParm ("-respawn");
fastparm = M_CheckParm ("-fast");
devparm = M_CheckParm ("-devparm");
if (M_CheckParm ("-altdeath"))
deathmatch = 2;
else if (M_CheckParm ("-deathmatch"))
deathmatch = 1;
printf("Welcome to Rockdoom");
switch ( gamemode )
{
case retail:
printf ("The Ultimate DOOM Startup v%d.%d",DVERSION/100,DVERSION%100);
break;
case shareware:
printf ("DOOM Shareware Startup v%d.%d",DVERSION/100,DVERSION%100);
break;
case registered:
printf ("DOOM Registered Startup v%d.%d",DVERSION/100,DVERSION%100);
break;
case commercial:
switch (gamemission)
{
case pack_plut:
printf ("DOOM 2: Plutonia Experiment v%d.%d",DVERSION/100,DVERSION%100);
break;
case pack_tnt:
printf ("DOOM 2: TNT - Evilution v%d.%d",DVERSION/100,DVERSION%100);
break;
default:
printf ("DOOM 2: Hell on Earth v%d.%d",DVERSION/100,DVERSION%100);
break;
}
break;
default:
printf ("Public DOOM v%d.%d",DVERSION/100,DVERSION%100);
break;
}
if (devparm)
printf(D_DEVSTR);
// turbo option
if ((p=M_CheckParm ("-turbo")))
{
int scale = 200;
extern int forwardmove[2];
extern int sidemove[2];
if (p<myargc-1)
scale = atoi (myargv[p+1]);
if (scale < 10)
scale = 10;
if (scale > 400)
scale = 400;
printf ("turbo scale: %d%%\n",scale);
forwardmove[0] = forwardmove[0]*scale/100;
forwardmove[1] = forwardmove[1]*scale/100;
sidemove[0] = sidemove[0]*scale/100;
sidemove[1] = sidemove[1]*scale/100;
}
// get skill / episode / map from parms
startskill = sk_medium;
startepisode = 1;
startmap = 1;
autostart = false;
p = M_CheckParm ("-skill");
if (p && p < myargc-1)
{
startskill = myargv[p+1][0]-'1';
autostart = true;
}
p = M_CheckParm ("-episode");
if (p && p < myargc-1)
{
startepisode = myargv[p+1][0]-'0';
startmap = 1;
autostart = true;
}
p = M_CheckParm ("-warp");
if (p && p < myargc-1)
{
if (gamemode == commercial)
startmap = atoi (myargv[p+1]);
else
{
startepisode = myargv[p+1][0]-'0';
startmap = myargv[p+2][0]-'0';
}
autostart = true;
}
// CPhipps - move up netgame init
printf("D_InitNetGame: Checking for network game.\n");
D_InitNetGame();
// init subsystems
printf ("V_Init: allocate screens.\n");
V_Init ();
printf ("W_Init: Init WADfiles.\n");
W_Init();
V_InitColorTranslation(); //jff 4/24/98 load color translation lumps
// Check for -file in shareware
if (modifiedgame)
{
// These are the lumps that will be checked in IWAD,
// if any one is not present, execution will be aborted.
char name[23][8]=
{
"e2m1","e2m2","e2m3","e2m4","e2m5","e2m6","e2m7","e2m8","e2m9",
"e3m1","e3m3","e3m3","e3m4","e3m5","e3m6","e3m7","e3m8","e3m9",
"dphoof","bfgga0","heada1","cybra1","spida1d1"
};
int i;
if ( gamemode == shareware)
I_Error("\nYou cannot -file with the shareware version. Register!");
// Check for fake IWAD with right name,
// but w/o all the lumps of the registered version.
if (gamemode == registered)
for (i = 0;i < 23; i++)
if (W_CheckNumForName(name[i])<0)
I_Error("\nThis is not the registered version.");
}
// Iff additonal PWAD files are used, print modified banner
if (modifiedgame)
printf ("ATTENTION: This version of DOOM has been modified.\n");
// Check and print which version is executed.
switch ( gamemode )
{
case shareware:
case indetermined:
printf ("Shareware!\n");
break;
case registered:
case retail:
case commercial:
printf ("Commercial product - do not distribute!\n");
break;
default:
// Ouch.
break;
}
printf ("M_Init: Init miscellaneous info.\n");
M_Init ();
printf ("R_Init: Init DOOM refresh daemon - ");
R_Init ();
printf ("P_Init: Init Playloop state.\n");
P_Init ();
printf ("I_Init: Setting up machine state.\n");
I_Init ();
printf ("S_Init: Setting up sound.\n");
S_Init (snd_SfxVolume /* *8 */, snd_MusicVolume /* *8*/ );
printf ("HU_Init: Setting up heads up display.\n");
HU_Init ();
I_InitGraphics ();
printf ("ST_Init: Init status bar.\n");
ST_Init ();
// check for a driver that wants intermission stats
p = M_CheckParm ("-statcopy");
if (p && p<myargc-1)
{
// for statistics driver
extern void* statcopy;
statcopy = (void*)atoi(myargv[p+1]);
printf ("External statistics registered.\n");
}
// start the apropriate game based on parms
p = M_CheckParm ("-record");
if (p && p < myargc-1)
{
G_RecordDemo (myargv[p+1]);
autostart = true;
}
p = M_CheckParm ("-loadgame");
if (p && p < myargc-1)
G_LoadGame (atoi(myargv[p+1]), false);
if ( gameaction != ga_loadgame )
{
if (!singledemo) { /* killough 12/98 */
if (autostart || netgame)
G_InitNew (startskill, startepisode, startmap);
else
D_StartTitle (); // start up intro loop
}
}
}
//
// D_DoomMain
//
void D_DoomMain (void)
{
D_DoomMainSetup(); // get this crap off the stack
D_DoomLoop (); // never returns
}

View file

@ -0,0 +1,74 @@
/* Emacs style mode select -*- C++ -*-
*-----------------------------------------------------------------------------
*
*
* PrBoom a Doom port merged with LxDoom and LSDLDoom
* based on BOOM, a modified and improved DOOM engine
* Copyright (C) 1999 by
* id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
* Copyright (C) 1999-2000 by
* Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* DESCRIPTION:
* Main startup and splash screenstuff.
*
*-----------------------------------------------------------------------------*/
#ifndef __D_MAIN__
#define __D_MAIN__
#include "d_event.h"
#include "w_wad.h"
#include "doomdef.h"
#ifdef __GNUG__
#pragma interface
#endif
// jff make startskill globally visible
extern skill_t startskill;
//jff 1/24/98 make command line copies of play modes available
extern boolean clnomonsters; // checkparm of -nomonsters
extern boolean clrespawnparm; // checkparm of -respawn
extern boolean clfastparm; // checkparm of -fast
//jff end of external declaration of command line playmode
extern boolean nosfxparm;
extern boolean nomusicparm;
extern int ffmap;
// Called by IO functions when input is detected.
void D_PostEvent(event_t* ev);
// Demo stuff
extern boolean advancedemo;
void D_AdvanceDemo(void);
void D_DoAdvanceDemo (void);
//
// BASE LEVEL
//
void D_PageTicker(void);
void D_PageDrawer(void);
void D_StartTitle(void);
void D_DoomMain(void);
void D_AddFile (const char *file, wad_source_t source);
#endif

149
apps/plugins/doom/d_net.c Normal file
View file

@ -0,0 +1,149 @@
/* Emacs style mode select -*- C++ -*-
*-----------------------------------------------------------------------------
*
*
* PrBoom a Doom port merged with LxDoom and LSDLDoom
* based on BOOM, a modified and improved DOOM engine
* Copyright (C) 1999 by
* id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
* Copyright (C) 1999-2000 by
* Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* DESCRIPTION:
* Network client. Passes information to/from server, staying
* synchronised.
* Contains the main wait loop, waiting for network input or
* time before doing the next tic.
* Rewritten for LxDoom, but based around bits of the old code.
*
*-----------------------------------------------------------------------------
*/
#include "m_menu.h"
#include "i_system.h"
#include "i_video.h"
#include "i_sound.h"
#include "g_game.h"
#include "doomdef.h"
#include "doomstat.h"
#include "rockmacros.h"
#define NCMD_EXIT 0x80000000
#define NCMD_RETRANSMIT 0x40000000
#define NCMD_SETUP 0x20000000
#define NCMD_KILL 0x10000000 // kill game
#define NCMD_CHECKSUM 0x0fffffff
doomcom_t* doomcom;
static boolean server=0;
static int remotetic; // Tic expected from the remote
static int remotesend; // Tic expected by the remote
//
// NETWORKING
//
// gametic is the tic about to (or currently being) run
// maketic is the tick that hasn't had control made for it yet
// nettics[] has the maketics for all players
//
// a gametic cannot be run until nettics[] > gametic for all players
//
static ticcmd_t* localcmds;
ticcmd_t netcmds[MAXPLAYERS][BACKUPTICS];
int maketic;
int ticdup=1;
void G_BuildTiccmd (ticcmd_t *cmd);
void D_DoAdvanceDemo (void);
void D_InitNetGame (void)
{
int i;
doomcom = Z_Malloc(sizeof *doomcom, PU_STATIC, NULL);
doomcom->consoleplayer = 0;
doomcom->numnodes = 0; doomcom->numplayers = 1;
localcmds = netcmds[consoleplayer];
for (i=0; i<doomcom->numplayers; i++)
playeringame[i] = true;
for (; i<MAXPLAYERS; i++)
playeringame[i] = false;
consoleplayer = displayplayer = doomcom->consoleplayer;
}
void D_BuildNewTiccmds()
{
static int lastmadetic;
int newtics = I_GetTime() - lastmadetic;
lastmadetic += newtics;
while (newtics--)
{
I_StartTic();
if (maketic - gametic > BACKUPTICS/2) break;
G_BuildTiccmd(&localcmds[maketic%BACKUPTICS]);
maketic++;
}
}
//
// TryRunTics
//
extern boolean advancedemo;
void TryRunTics (void)
{
int runtics;
int entertime = I_GetTime();
// Wait for tics to run
while (1) {
D_BuildNewTiccmds();
runtics = (server ? remotetic : maketic) - gametic;
if (!runtics) {
// if (server) I_WaitForPacket(ms_to_next_tick);
// else I_uSleep(ms_to_next_tick*1000);
// rb->sleep(ms_to_next_tick);
if (I_GetTime() - entertime > 10) {
remotesend--;
// {
// char buf[sizeof(packet_header_t)+1];
// packet_set((packet_header_t *)buf, PKT_RETRANS, remotetic);
// buf[sizeof(buf)-1] = consoleplayer;
// I_SendPacket((packet_header_t *)buf, sizeof buf);
// }
M_Ticker(); return;
}
} else break;
}
while (runtics--) {
if (advancedemo)
D_DoAdvanceDemo ();
M_Ticker ();
G_Ticker ();
gametic++;
}
}

213
apps/plugins/doom/d_net.h Normal file
View file

@ -0,0 +1,213 @@
/* Emacs style mode select -*- C++ -*-
*-----------------------------------------------------------------------------
*
*
* PrBoom a Doom port merged with LxDoom and LSDLDoom
* based on BOOM, a modified and improved DOOM engine
* Copyright (C) 1999 by
* id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
* Copyright (C) 1999-2000 by
* Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* DESCRIPTION:
* Networking stuff.
*
*-----------------------------------------------------------------------------*/
#ifndef __D_NET__
#define __D_NET__
#include "d_player.h"
#ifdef __GNUG__
#pragma interface
#endif
//
// Network play related stuff.
// There is a data struct that stores network
// communication related stuff, and another
// one that defines the actual packets to
// be transmitted.
//
#define DOOMCOM_ID 0x12345678l
// Max computers/players in a game.
#define MAXNETNODES 8
// Networking and tick handling related.
#define BACKUPTICS 12
typedef enum
{
CMD_SEND = 1,
CMD_GET = 2
} command_t;
//
// Network packet data.
//
typedef struct
{
// High bit is retransmit request.
unsigned checksum;
// Only valid if NCMD_RETRANSMIT.
byte retransmitfrom;
byte starttic;
byte player;
byte numtics;
ticcmd_t cmds[BACKUPTICS];
} doomdata_t;
//
// Startup packet difference
// SG: 4/12/98
// Added so we can send more startup data to synch things like
// bobbing, recoil, etc.
// this is just mapped over the ticcmd_t array when setup packet is sent
//
// Note: the original code takes care of startskill, deathmatch, nomonsters
// respawn, startepisode, startmap
// Note: for phase 1 we need to add monsters_remember, variable_friction,
// weapon_recoil, allow_pushers, over_under, player_bobbing,
// fastparm, demo_insurance, and the rngseed
//Stick all options into bytes so we don't need to mess with bitfields
//WARNING: make sure this doesn't exceed the size of the ticcmds area!
//sizeof(ticcmd_t)*BACKUPTICS
//This is the current length of our extra stuff
//
//killough 5/2/98: this should all be replaced by calls to G_WriteOptions()
//and G_ReadOptions(), which were specifically designed to set up packets.
//By creating a separate struct and functions to read/write the options,
//you now have two functions and data to maintain instead of just one.
//If the array in g_game.c which G_WriteOptions()/G_ReadOptions() operates
//on, is too large (more than sizeof(ticcmd_t)*BACKUPTICS), it can
//either be shortened, or the net code needs to divide it up
//automatically into packets. The STARTUPLEN below is non-portable.
//There's a portable way to do it without having to know the sizes.
#define STARTUPLEN 12
typedef struct
{
byte monsters_remember;
byte variable_friction;
byte weapon_recoil;
byte allow_pushers;
byte over_under;
byte player_bobbing;
byte fastparm;
byte demo_insurance;
unsigned long rngseed;
char filler[sizeof(ticcmd_t)*BACKUPTICS-STARTUPLEN];
} startup_t;
typedef enum {
// Leave space, so low values corresponding to normal netgame setup packets can be ignored
nm_plcolour = 3,
nm_savegamename = 4,
} netmisctype_t;
typedef struct
{
netmisctype_t type;
size_t len;
byte value[sizeof(ticcmd_t)*BACKUPTICS - sizeof(netmisctype_t) - sizeof(size_t)];
} netmisc_t;
typedef struct
{
// Supposed to be DOOMCOM_ID?
long id;
// DOOM executes an int to execute commands.
short intnum;
// Communication between DOOM and the driver.
// Is CMD_SEND or CMD_GET.
short command;
// Is dest for send, set by get (-1 = no packet).
short remotenode;
// Number of bytes in doomdata to be sent
short datalength;
// Info common to all nodes.
// Console is allways node 0.
short numnodes;
// Flag: 1 = no duplication, 2-5 = dup for slow nets.
short ticdup;
// Flag: 1 = send a backup tic in every packet.
short extratics;
// Flag: 1 = deathmatch.
short deathmatch;
// Flag: -1 = new game, 0-5 = load savegame
short savegame;
short episode; // 1-3
short map; // 1-9
short skill; // 1-5
// Info specific to this node.
short consoleplayer;
short numplayers;
// These are related to the 3-display mode,
// in which two drones looking left and right
// were used to render two additional views
// on two additional computers.
// Probably not operational anymore.
// 1 = left, 0 = center, -1 = right
short angleoffset;
// 1 = drone
short drone;
// The packet data to be sent.
doomdata_t data;
} doomcom_t;
// Create any new ticcmds and broadcast to other players.
void NetUpdate (void);
// Create any new ticcmds
void D_BuildNewTiccmds (void);
// Broadcasts special packets to other players
// to notify of game exit
void D_QuitNetGame (void);
//? how many ticks to run?
void TryRunTics (void);
// CPhipps - move to header file
void D_InitNetGame (void); // This does the setup
void D_CheckNetGame(void); // This waits for game start
// CPhipps - misc info broadcast
void D_NetSendMisc(netmisctype_t type, size_t len, void* data);
// CPhipps - ask server for a wad file we need
boolean D_NetGetWad(const char* name);
#endif

View file

@ -0,0 +1,232 @@
/* Emacs style mode select -*- C++ -*-
*-----------------------------------------------------------------------------
*
*
* PrBoom a Doom port merged with LxDoom and LSDLDoom
* based on BOOM, a modified and improved DOOM engine
* Copyright (C) 1999 by
* id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
* Copyright (C) 1999-2000 by
* Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* DESCRIPTION:
* Player state structure.
*
*-----------------------------------------------------------------------------*/
#ifndef __D_PLAYER__
#define __D_PLAYER__
// The player data structure depends on a number
// of other structs: items (internal inventory),
// animation states (closely tied to the sprites
// used to represent them, unfortunately).
#include "d_items.h"
#include "p_pspr.h"
// In addition, the player is just a special
// case of the generic moving object/actor.
#include "p_mobj.h"
// Finally, for odd reasons, the player input
// is buffered within the player data struct,
// as commands per game tick.
#include "d_ticcmd.h"
#ifdef __GNUG__
#pragma interface
#endif
//
// Player states.
//
typedef enum
{
// Playing or camping.
PST_LIVE,
// Dead on the ground, view follows killer.
PST_DEAD,
// Ready to restart/respawn???
PST_REBORN
} playerstate_t;
//
// Player internal flags, for cheats and debug.
//
typedef enum
{
// No clipping, walk through barriers.
CF_NOCLIP = 1,
// No damage, no health loss.
CF_GODMODE = 2,
// Not really a cheat, just a debug aid.
CF_NOMOMENTUM = 4
} cheat_t;
//
// Extended player object info: player_t
//
typedef struct player_s
{
mobj_t* mo;
playerstate_t playerstate;
ticcmd_t cmd;
// Determine POV,
// including viewpoint bobbing during movement.
// Focal origin above r.z
fixed_t viewz;
// Base height above floor for viewz.
fixed_t viewheight;
// Bob/squat speed.
fixed_t deltaviewheight;
// bounded/scaled total momentum.
fixed_t bob;
/* killough 10/98: used for realistic bobbing (i.e. not simply overall speed)
* mo->momx and mo->momy represent true momenta experienced by player.
* This only represents the thrust that the player applies himself.
* This avoids anomolies with such things as Boom ice and conveyors.
*/
fixed_t momx, momy; // killough 10/98
// This is only used between levels,
// mo->health is used during levels.
int health;
int armorpoints;
// Armor type is 0-2.
int armortype;
// Power ups. invinc and invis are tic counters.
int powers[NUMPOWERS];
boolean cards[NUMCARDS];
boolean backpack;
// Frags, kills of other players.
int frags[MAXPLAYERS];
weapontype_t readyweapon;
// Is wp_nochange if not changing.
weapontype_t pendingweapon;
boolean weaponowned[NUMWEAPONS];
int ammo[NUMAMMO];
int maxammo[NUMAMMO];
// True if button down last tic.
int attackdown;
int usedown;
// Bit flags, for cheats and debug.
// See cheat_t, above.
int cheats;
// Refired shots are less accurate.
int refire;
// For intermission stats.
int killcount;
int itemcount;
int secretcount;
// Hint messages. // CPhipps - const
const char* message;
// For screen flashing (red or bright).
int damagecount;
int bonuscount;
// Who did damage (NULL for floors/ceilings).
mobj_t* attacker;
// So gun flashes light up areas.
int extralight;
// Current PLAYPAL, ???
// can be set to REDCOLORMAP for pain, etc.
int fixedcolormap;
// Player skin colorshift,
// 0-3 for which color to draw player.
int colormap;
// Overlay view sprites (gun, etc).
pspdef_t psprites[NUMPSPRITES];
// True if secret level has been done.
boolean didsecret;
} player_t;
//
// INTERMISSION
// Structure passed e.g. to WI_Start(wb)
//
typedef struct
{
boolean in; // whether the player is in game
// Player stats, kills, collected items etc.
int skills;
int sitems;
int ssecret;
int stime;
int frags[4];
int score; // current score on entry, modified on return
} wbplayerstruct_t;
typedef struct
{
int epsd; // episode # (0-2)
// if true, splash the secret level
boolean didsecret;
// previous and next levels, origin 0
int last;
int next;
int maxkills;
int maxitems;
int maxsecret;
int maxfrags;
// the par time
int partime;
// index of this player in game
int pnum;
wbplayerstruct_t plyr[MAXPLAYERS];
// CPhipps - total game time for completed levels so far
int totaltimes;
} wbstartstruct_t;
#endif

View file

@ -0,0 +1,92 @@
/* Emacs style mode select -*- C++ -*-
*-----------------------------------------------------------------------------
*
*
* PrBoom a Doom port merged with LxDoom and LSDLDoom
* based on BOOM, a modified and improved DOOM engine
* Copyright (C) 1999 by
* id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
* Copyright (C) 1999-2000 by
* Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* DESCRIPTION:
* MapObj data. Map Objects or mobjs are actors, entities,
* thinker, take-your-pick... anything that moves, acts, or
* suffers state changes of more or less violent nature.
*
*-----------------------------------------------------------------------------*/
#ifndef __D_THINK__
#define __D_THINK__
#ifdef __GNUG__
#pragma interface
#endif
/*
* Experimental stuff.
* To compile this as "ANSI C with classes"
* we will need to handle the various
* action functions cleanly.
*/
// killough 11/98: convert back to C instead of C++
typedef void (*actionf_t)();
//typedef void (*actionf_v)();
//typedef void (*actionf_p1)( void* );
//typedef void (*actionf_p2)( void*, void* );
/* Note: In d_deh.c you will find references to these
* wherever code pointers and function handlers exist
*/
/*
typedef union
{
actionf_p1 acp1;
actionf_v acv;
actionf_p2 acp2;
} actionf_t;
*/
/* Historically, "think_t" is yet another
* function pointer to a routine to handle
* an actor.
*/
typedef actionf_t think_t;
/* Doubly linked list of actors. */
typedef struct thinker_s
{
struct thinker_s* prev;
struct thinker_s* next;
think_t function;
/* killough 8/29/98: we maintain thinkers in several equivalence classes,
* according to various criteria, so as to allow quicker searches.
*/
struct thinker_s *cnext, *cprev; /* Next, previous thinkers in same class */
/* killough 11/98: count of how many other objects reference
* this one using pointers. Used for garbage collection.
*/
unsigned references;
} thinker_t;
#endif

View file

@ -0,0 +1,57 @@
/* Emacs style mode select -*- C++ -*-
*-----------------------------------------------------------------------------
*
*
* PrBoom a Doom port merged with LxDoom and LSDLDoom
* based on BOOM, a modified and improved DOOM engine
* Copyright (C) 1999 by
* id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
* Copyright (C) 1999-2000 by
* Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* DESCRIPTION:
* System specific interface stuff.
*
*-----------------------------------------------------------------------------*/
#ifndef __D_TICCMD__
#define __D_TICCMD__
#include "doomtype.h"
#ifdef __GNUG__
#pragma interface
#endif
/* The data sampled per tick (single player)
* and transmitted to other peers (multiplayer).
* Mainly movements/button commands per game tick,
* plus a checksum for internal state consistency.
* CPhipps - explicitely signed the elements, since they have to be signed to work right
*/
typedef struct
{
signed char forwardmove; /* *2048 for move */
signed char sidemove; /* *2048 for move */
signed short angleturn; /* <<16 for angle delta */
short consistancy; /* checks for net game */
byte chatchar;
byte buttons;
} ticcmd_t;
#endif

View file

@ -0,0 +1,187 @@
// Emacs style mode select -*- C++ -*-
//-----------------------------------------------------------------------------
//
// $Id$
//
// Copyright (C) 1993-1996 by id Software, Inc.
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// DESCRIPTION:
// all external data is defined here
// most of the data is loaded into different structures at run time
// some internal structures shared by many modules are here
//
//-----------------------------------------------------------------------------
#ifndef __DOOMDATA__
#define __DOOMDATA__
// The most basic types we use, portability.
#include "doomtype.h"
// Some global defines, that configure the game.
#include "doomdef.h"
#include "rockmacros.h"
//
// Map level types.
// The following data structures define the persistent format
// used in the lumps of the WAD files.
//
// Lump order in a map WAD: each map needs a couple of lumps
// to provide a complete scene geometry description.
enum {
ML_LABEL, // A separator, name, ExMx or MAPxx
ML_THINGS, // Monsters, items..
ML_LINEDEFS, // LineDefs, from editing
ML_SIDEDEFS, // SideDefs, from editing
ML_VERTEXES, // Vertices, edited and BSP splits generated
ML_SEGS, // LineSegs, from LineDefs split by BSP
ML_SSECTORS, // SubSectors, list of LineSegs
ML_NODES, // BSP nodes
ML_SECTORS, // Sectors, from editing
ML_REJECT, // LUT, sector-sector visibility
ML_BLOCKMAP // LUT, motion clipping, walls/grid element
};
// A single Vertex.
typedef struct {
short x,y;
} PACKEDATTR mapvertex_t;
// A SideDef, defining the visual appearance of a wall,
// by setting textures and offsets.
typedef struct {
short textureoffset;
short rowoffset;
char toptexture[8];
char bottomtexture[8];
char midtexture[8];
short sector; // Front sector, towards viewer.
} PACKEDATTR mapsidedef_t;
// A LineDef, as used for editing, and as input to the BSP builder.
typedef struct {
short v1;
short v2;
short flags;
short special;
short tag;
short sidenum[2]; // sidenum[1] will be -1 if one sided
} PACKEDATTR maplinedef_t;
//
// LineDef attributes.
//
// Solid, is an obstacle.
#define ML_BLOCKING 1
// Blocks monsters only.
#define ML_BLOCKMONSTERS 2
// Backside will not be present at all
// if not two sided.
#define ML_TWOSIDED 4
// If a texture is pegged, the texture will have
// the end exposed to air held constant at the
// top or bottom of the texture (stairs or pulled
// down things) and will move with a height change
// of one of the neighbor sectors.
// Unpegged textures allways have the first row of
// the texture at the top pixel of the line for both
// top and bottom textures (use next to windows).
// upper texture unpegged
#define ML_DONTPEGTOP 8
// lower texture unpegged
#define ML_DONTPEGBOTTOM 16
// In AutoMap: don't map as two sided: IT'S A SECRET!
#define ML_SECRET 32
// Sound rendering: don't let sound cross two of these.
#define ML_SOUNDBLOCK 64
// Don't draw on the automap at all.
#define ML_DONTDRAW 128
// Set if already seen, thus drawn in automap.
#define ML_MAPPED 256
//jff 3/21/98 Set if line absorbs use by player
//allow multiple push/switch triggers to be used on one push
#define ML_PASSUSE 512
// Sector definition, from editing.
typedef struct {
short floorheight;
short ceilingheight;
char floorpic[8];
char ceilingpic[8];
short lightlevel;
short special;
short tag;
} PACKEDATTR mapsector_t;
// SubSector, as generated by BSP.
typedef struct {
unsigned short numsegs;
unsigned short firstseg; // Index of first one; segs are stored sequentially.
} PACKEDATTR mapsubsector_t;
// LineSeg, generated by splitting LineDefs
// using partition lines selected by BSP builder.
typedef struct {
short v1;
short v2;
short angle;
short linedef;
short side;
short offset;
} PACKEDATTR mapseg_t;
// BSP node structure.
// Indicate a leaf.
#define NF_SUBSECTOR 0x8000
typedef struct {
short x; // Partition line from (x,y) to x+dx,y+dy)
short y;
short dx;
short dy;
// Bounding box for each child, clip against view frustum.
short bbox[2][4];
// If NF_SUBSECTOR its a subsector, else it's a node of another subtree.
unsigned short children[2];
} PACKEDATTR mapnode_t;
// Thing definition, position, orientation and type,
// plus skill/visibility flags and attributes.
typedef struct {
short x;
short y;
short angle;
short type;
short options;
} PACKEDATTR mapthing_t;
#endif // __DOOMDATA__

View file

@ -0,0 +1,39 @@
// Emacs style mode select -*- C++ -*-
//-----------------------------------------------------------------------------
//
// $Id$
//
// Copyright (C) 1993-1996 by id Software, Inc.
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// $Log$
// Revision 1.1 2006/03/28 15:44:01 dave
// Patch #2969 - Doom! Currently only working on the H300.
//
//
// DESCRIPTION:
// DoomDef - basic defines for DOOM, e.g. Version, game mode
// and skill level, and display parameters.
//
//-----------------------------------------------------------------------------
#ifdef __GNUG__
#pragma implementation "doomdef.h"
#endif
#include "doomdef.h"
// Location for any defines turned variables.
// None.

306
apps/plugins/doom/doomdef.h Normal file
View file

@ -0,0 +1,306 @@
/* Emacs style mode select -*- C++ -*-
*-----------------------------------------------------------------------------
*
*
* PrBoom a Doom port merged with LxDoom and LSDLDoom
* based on BOOM, a modified and improved DOOM engine
* Copyright (C) 1999 by
* id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
* Copyright (C) 1999-2000 by
* Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* DESCRIPTION:
* Internally used data structures for virtually everything,
* key definitions, lots of other stuff.
*
*-----------------------------------------------------------------------------*/
#ifndef __DOOMDEF__
#define __DOOMDEF__
// killough 4/25/98: Make gcc extensions mean nothing on other compilers
#ifndef __GNUC__
#define __attribute__(x)
#endif
//
// Global parameters/defines.
//
// DOOM version
enum { DVERSION = 110 };
// Game mode handling - identify IWAD version
// to handle IWAD dependend animations etc.
typedef enum {
shareware, // DOOM 1 shareware, E1, M9
registered, // DOOM 1 registered, E3, M27
commercial, // DOOM 2 retail, E1 M34 (DOOM 2 german edition not handled)
retail, // DOOM 1 retail, E4, M36
indetermined // Well, no IWAD found.
} GameMode_t;
// Mission packs - might be useful for TC stuff?
typedef enum {
doom, // DOOM 1
doom2, // DOOM 2
pack_tnt, // TNT mission pack
pack_plut, // Plutonia pack
none
} GameMission_t;
// Identify language to use, software localization.
typedef enum {
english,
french,
german,
unknown
} Language_t;
//
// For resize of screen, at start of game.
//
#define BASE_WIDTH 320
// It is educational but futile to change this
// scaling e.g. to 2. Drawing of status bar,
// menues etc. is tied to the scale implied
// by the graphics.
#define INV_ASPECT_RATIO 0.625 // 0.75, ideally
// killough 2/8/98: MAX versions for maximum screen sizes
// allows us to avoid the overhead of dynamic allocation
// when multiple screen sizes are supported
// proff 08/17/98: Changed for high-res
#define MAX_SCREENWIDTH 1600
#define MAX_SCREENHEIGHT 1200
#define SCREENWIDTH 320
#define SCREENHEIGHT 200
// The maximum number of players, multiplayer/networking.
#define MAXPLAYERS 4
// phares 5/14/98:
// DOOM Editor Numbers (aka doomednum in mobj_t)
#define DEN_PLAYER5 4001
#define DEN_PLAYER6 4002
#define DEN_PLAYER7 4003
#define DEN_PLAYER8 4004
// State updates, number of tics / second.
#define TICRATE 35
// The current state of the game: whether we are playing, gazing
// at the intermission screen, the game final animation, or a demo.
typedef enum {
GS_LEVEL,
GS_INTERMISSION,
GS_FINALE,
GS_DEMOSCREEN
} gamestate_t;
//
// Difficulty/skill settings/filters.
//
// Skill flags.
#define MTF_EASY 1
#define MTF_NORMAL 2
#define MTF_HARD 4
// Deaf monsters/do not react to sound.
#define MTF_AMBUSH 8
/* killough 11/98 */
#define MTF_NOTSINGLE 16
#define MTF_NOTDM 32
#define MTF_NOTCOOP 64
#define MTF_FRIEND 128
#define MTF_RESERVED 256
typedef enum {
sk_none=-1, //jff 3/24/98 create unpicked skill setting
sk_baby=0,
sk_easy,
sk_medium,
sk_hard,
sk_nightmare
} skill_t;
//
// Key cards.
//
typedef enum {
it_bluecard,
it_yellowcard,
it_redcard,
it_blueskull,
it_yellowskull,
it_redskull,
NUMCARDS
} card_t;
// The defined weapons, including a marker
// indicating user has not changed weapon.
typedef enum {
wp_fist,
wp_pistol,
wp_shotgun,
wp_chaingun,
wp_missile,
wp_plasma,
wp_bfg,
wp_chainsaw,
wp_supershotgun,
NUMWEAPONS,
wp_nochange // No pending weapon change.
} weapontype_t;
// Ammunition types defined.
typedef enum {
am_clip, // Pistol / chaingun ammo.
am_shell, // Shotgun / double barreled shotgun.
am_cell, // Plasma rifle, BFG.
am_misl, // Missile launcher.
NUMAMMO,
am_noammo // Unlimited for chainsaw / fist.
} ammotype_t;
// Power up artifacts.
typedef enum {
pw_invulnerability,
pw_strength,
pw_invisibility,
pw_ironfeet,
pw_allmap,
pw_infrared,
NUMPOWERS
} powertype_t;
// Power up durations (how many seconds till expiration).
typedef enum {
INVULNTICS = (30*TICRATE),
INVISTICS = (60*TICRATE),
INFRATICS = (120*TICRATE),
IRONTICS = (60*TICRATE)
} powerduration_t;
//
// DOOM keyboard definition.
// This is the stuff configured by Setup.Exe.
// Most key data are simple ascii (uppercased).
//
#define KEY_RIGHTARROW 0xae
#define KEY_LEFTARROW 0xac
#define KEY_UPARROW 0xad
#define KEY_DOWNARROW 0xaf
#define KEY_ESCAPE 0x1B
#define KEY_ENTER 0x0D
#define KEY_TAB 0x09
#define KEY_F1 (0x80+0x3b)
#define KEY_F2 (0x80+0x3c)
#define KEY_F3 (0x80+0x3d)
#define KEY_F4 (0x80+0x3e)
#define KEY_F5 (0x80+0x3f)
#define KEY_F6 (0x80+0x40)
#define KEY_F7 (0x80+0x41)
#define KEY_F8 (0x80+0x42)
#define KEY_F9 (0x80+0x43)
#define KEY_F10 (0x80+0x44)
#define KEY_F11 (0x80+0x57)
#define KEY_F12 (0x80+0x58)
#define KEY_BACKSPACE 0x7F
#define KEY_PAUSE 0xff
#define KEY_EQUALS 0x3d
#define KEY_MINUS 0x2d
#define KEY_RSHIFT (0x80+0x36)
#define KEY_RCTRL (0x80+0x1d)
#define KEY_RALT (0x80+0x38)
#define KEY_LALT KEY_RALT
#define KEY_CAPSLOCK 0xba // phares
// phares 3/2/98:
#define KEY_INSERT 0xd2
#define KEY_HOME 0xc7
#define KEY_PAGEUP 0xc9
#define KEY_PAGEDOWN 0xd1
#define KEY_DEL 0xc8
#define KEY_END 0xcf
#define KEY_SCROLLLOCK 0xc6
#define KEY_SPACEBAR 0x20
// phares 3/2/98
#define KEY_NUMLOCK 0xC5 // killough 3/6/98
// cph - Add the numeric keypad keys, as suggested by krose 4/22/99:
// The way numbers are assigned to keys is a mess, but it's too late to
// change that easily. At least these additions are don neatly.
// Codes 0x100-0x200 are reserved for number pad
#define KEY_KEYPAD0 (0x100 + '0')
#define KEY_KEYPAD1 (0x100 + '1')
#define KEY_KEYPAD2 (0x100 + '2')
#define KEY_KEYPAD3 (0x100 + '3')
#define KEY_KEYPAD4 (0x100 + '4')
#define KEY_KEYPAD5 (0x100 + '5')
#define KEY_KEYPAD6 (0x100 + '6')
#define KEY_KEYPAD7 (0x100 + '7')
#define KEY_KEYPAD8 (0x100 + '8')
#define KEY_KEYPAD9 (0x100 + '9')
#define KEY_KEYPADENTER (0x100 + KEY_ENTER)
#define KEY_KEYPADDIVIDE (0x100 + '/')
#define KEY_KEYPADMULTIPLY (0x100 + '*')
#define KEY_KEYPADMINUS (0x100 + '-')
#define KEY_KEYPADPLUS (0x100 + '+')
#define KEY_KEYPADPERIOD (0x100 + '.')
// phares 4/19/98:
// Defines Setup Screen groups that config variables appear in.
// Used when resetting the defaults for every item in a Setup group.
typedef enum {
ss_none,
ss_keys,
ss_weap,
ss_stat,
ss_auto,
ss_enem,
ss_mess,
ss_chat,
ss_gen, /* killough 10/98 */
ss_comp, /* killough 10/98 */
ss_max
} ss_types;
// phares 3/20/98:
//
// Player friction is variable, based on controlling
// linedefs. More friction can create mud, sludge,
// magnetized floors, etc. Less friction can create ice.
#define MORE_FRICTION_MOMENTUM 15000 // mud factor based on momentum
#define ORIG_FRICTION 0xE800 // original value
#define ORIG_FRICTION_FACTOR 2048 // original value
#endif // __DOOMDEF__

View file

@ -0,0 +1,104 @@
// Emacs style mode select -*- C++ -*-
//-----------------------------------------------------------------------------
//
// $Id$
//
// Copyright (C) 1993-1996 by id Software, Inc.
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// $Log$
// Revision 1.1 2006/03/28 15:44:01 dave
// Patch #2969 - Doom! Currently only working on the H300.
//
//
// DESCRIPTION:
// Put all global tate variables here.
//
//-----------------------------------------------------------------------------
#ifdef __GNUG__
#pragma implementation "doomstat.h"
#endif
#include "doomstat.h"
// Game Mode - identify IWAD as shareware, retail etc.
GameMode_t gamemode IDATA_ATTR= indetermined;
GameMission_t gamemission IDATA_ATTR = doom;
// Language.
Language_t language = english;
// Set if homebrew PWAD stuff has been added.
boolean modifiedgame;
//-----------------------------------------------------------------------------
// CPhipps - compatibility vars
complevel_t compatibility_level=prboom_3_compatibility, default_compatibility_level=prboom_3_compatibility;
int comp[COMP_TOTAL] IBSS_ATTR, default_comp[COMP_TOTAL]; // killough 10/98
// v1.1-like pitched sounds
int pitched_sounds=0; // killough
int default_translucency; // config file says // phares
boolean general_translucency IBSS_ATTR; // true if translucency is ok // phares
int demo_insurance, default_demo_insurance; // killough 1/16/98
int allow_pushers IDATA_ATTR = 1; // MT_PUSH Things // phares 3/10/98
int default_allow_pushers; // killough 3/1/98: make local to each game
int variable_friction IDATA_ATTR = 1; // ice & mud // phares 3/10/98
int default_variable_friction; // killough 3/1/98: make local to each game
int weapon_recoil IBSS_ATTR; // weapon recoil // phares
int default_weapon_recoil; // killough 3/1/98: make local to each game
int player_bobbing IBSS_ATTR; // whether player bobs or not // phares 2/25/98
int default_player_bobbing; // killough 3/1/98: make local to each game
int monsters_remember IBSS_ATTR; // killough 3/1/98
int default_monsters_remember;
int monster_infighting IDATA_ATTR=1; // killough 7/19/98: monster<=>monster attacks
int default_monster_infighting=1;
int monster_friction IDATA_ATTR=1; // killough 10/98: monsters affected by friction
int default_monster_friction=1;
#ifdef DOGS
int dogs, default_dogs; // killough 7/19/98: Marine's best friend :)
int dog_jumping, default_dog_jumping; // killough 10/98
#endif
// killough 8/8/98: distance friends tend to move towards players
int distfriend = 128, default_distfriend = 128;
// killough 9/8/98: whether monsters are allowed to strafe or retreat
int monster_backing IBSS_ATTR, default_monster_backing;
// killough 9/9/98: whether monsters are able to avoid hazards (e.g. crushers)
int monster_avoid_hazards IBSS_ATTR, default_monster_avoid_hazards;
// killough 9/9/98: whether monsters help friends
int help_friends IBSS_ATTR, default_help_friends;
int flashing_hom; // killough 10/98
int doom_weapon_toggles; // killough 10/98
int monkeys IBSS_ATTR, default_monkeys;
boolean nosfxparm=0;
boolean rockblock=1;

View file

@ -0,0 +1,373 @@
// Emacs style mode select -*- C++ -*-
//-----------------------------------------------------------------------------
//
// $Id$
//
// Copyright (C) 1993-1996 by id Software, Inc.
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// DESCRIPTION:
// All the global variables that store the internal state.
// Theoretically speaking, the internal state of the engine
// should be found by looking at the variables collected
// here, and every relevant module will have to include
// this header file.
// In practice, things are a bit messy.
//
//-----------------------------------------------------------------------------
#ifndef __D_STATE__
#define __D_STATE__
// We need globally shared data structures,
// for defining the global state variables.
#include "doomdata.h"
#include "d_net.h"
// We need the playr data structure as well.
#include "d_player.h"
#ifdef __GNUG__
#pragma interface
#endif
// ------------------------
// Command line parameters.
//
extern boolean nomonsters; // checkparm of -nomonsters
extern boolean respawnparm; // checkparm of -respawn
extern boolean fastparm; // checkparm of -fast
extern boolean devparm; // DEBUG: launched with -devparm
enum automapmode_e {
am_active = 1, // currently shown
am_overlay= 2, // covers the screen, i.e. not overlay mode
am_rotate = 4, // rotates to the player facing direction
am_follow = 8, // keep the player centred
am_grid =16, // show grid
};
extern enum automapmode_e automapmode; // Mode that the automap is in
// -----------------------------------------------------
// Game Mode - identify IWAD as shareware, retail etc.
//
extern GameMode_t gamemode;
extern GameMission_t gamemission;
// Set if homebrew PWAD stuff has been added.
extern boolean modifiedgame;
// CPhipps - new compatibility handling
extern complevel_t compatibility_level, default_compatibility_level;
// CPhipps - old compatibility testing flags aliased to new handling
#define compatibility (compatibility_level<=boom_compatibility_compatibility)
#define demo_compatibility (compatibility_level <= doom_demo_compatibility)
#define mbf_features (compatibility_level>=mbf_compatibility)
extern int default_translucency;
extern boolean general_translucency; // true if translucency is ok // phares
extern int demo_insurance, default_demo_insurance; // killough 4/5/98
// -------------------------------------------
// killough 10/98: compatibility vector
enum {
comp_telefrag,
comp_dropoff,
comp_vile,
comp_pain,
comp_skull,
comp_blazing,
comp_doorlight,
comp_model,
comp_god,
comp_falloff,
comp_floors,
comp_skymap,
comp_pursuit,
comp_doorstuck,
comp_staylift,
comp_zombie,
comp_stairs,
comp_infcheat,
comp_zerotags,
comp_moveblock,
comp_respawn, /* cph - this is the inverse of comp_respawnfix from eternity */
comp_sound,
COMP_NUM, /* cph - should be last in sequence */
COMP_TOTAL=32 // Some extra room for additional variables
};
extern int comp[COMP_TOTAL], default_comp[COMP_TOTAL];
extern boolean nosfxparm;
extern boolean rockblock;
// -------------------------------------------
// Language.
extern Language_t language;
// -------------------------------------------
// Selected skill type, map etc.
//
// Defaults for menu, methinks.
extern skill_t startskill;
extern int startepisode;
extern int startmap;
extern boolean autostart;
// Selected by user.
extern skill_t gameskill;
extern int gameepisode;
extern int gamemap;
// Nightmare mode flag, single player.
extern boolean respawnmonsters;
// Netgame? Only true if >1 player.
extern boolean netgame;
// Flag: true only if started as net deathmatch.
// An enum might handle altdeath/cooperative better.
extern boolean deathmatch;
// -------------------------
// Internal parameters for sound rendering.
// These have been taken from the DOS version,
// but are not (yet) supported with Linux
// (e.g. no sound volume adjustment with menu.
// These are not used, but should be (menu).
// From m_menu.c:
// Sound FX volume has default, 0 - 15
// Music volume has default, 0 - 15
// These are multiplied by 8.
extern int snd_SfxVolume; // maximum volume for sound
extern int snd_MusicVolume; // maximum volume for music
// Current music/sfx card - index useless
// w/o a reference LUT in a sound module.
// Ideally, this would use indices found
// in: /usr/include/linux/soundcard.h
extern int snd_MusicDevice;
extern int snd_SfxDevice;
// Config file? Same disclaimer as above.
extern int snd_DesiredMusicDevice;
extern int snd_DesiredSfxDevice;
// -------------------------
// Status flags for refresh.
//
// Depending on view size - no status bar?
// Note that there is no way to disable the
// status bar explicitely.
extern boolean statusbaractive;
extern boolean automapactive; // In AutoMap mode?
extern boolean menuactive; // Menu overlayed?
extern boolean paused; // Game Pause?
extern boolean viewactive;
extern boolean nodrawers;
extern boolean noblit;
extern int viewwindowx;
extern int viewwindowy;
extern int viewheight;
extern int viewwidth;
extern int scaledviewwidth;
// This one is related to the 3-screen display mode.
// ANG90 = left side, ANG270 = right
extern int viewangleoffset;
// Player taking events, and displaying.
extern int consoleplayer;
extern int displayplayer;
// -------------------------------------
// Scores, rating.
// Statistics on a given map, for intermission.
//
extern int totalkills, totallive;
extern int totalitems;
extern int totalsecret;
// Timer, for scores.
extern int levelstarttic; // gametic at level start
extern int basetic; /* killough 9/29/98: levelstarttic, adjusted */
extern int leveltime; // tics in game play for par
// --------------------------------------
// DEMO playback/recording related stuff.
// No demo, there is a human player in charge?
// Disable save/end game?
extern boolean usergame;
//?
extern boolean demoplayback;
extern boolean demorecording;
// Quit after playing a demo from cmdline.
extern boolean singledemo;
//?
extern gamestate_t gamestate;
//-----------------------------
// Internal parameters, fixed.
// These are set by the engine, and not changed
// according to user inputs. Partly load from
// WAD, partly set at startup time.
extern int gametic;
// Bookkeeping on players - state.
extern player_t players[MAXPLAYERS];
// Alive? Disconnected?
extern boolean playeringame[MAXPLAYERS];
// Player spawn spots for deathmatch.
#define MAX_DM_STARTS 10
//extern mapthing_t deathmatchstarts[MAX_DM_STARTS];
extern mapthing_t *deathmatchstarts; // killough
extern size_t num_deathmatchstarts; // killough
extern mapthing_t* deathmatch_p;
// Player spawn spots.
extern mapthing_t playerstarts[MAXPLAYERS];
// Intermission stats.
// Parameters for world map / intermission.
extern wbstartstruct_t wminfo;
// LUT of ammunition limits for each kind.
// This doubles with BackPack powerup item.
extern int maxammo[NUMAMMO];
//-----------------------------------------
// Internal parameters, used for engine.
//
// File handling stuff.
extern char basedefault[];
extern int debugfile;
// if true, load all graphics at level load
extern boolean precache;
// wipegamestate can be set to -1
// to force a wipe on the next draw
extern gamestate_t wipegamestate;
extern int mouseSensitivity;
//?
// debug flag to cancel adaptiveness
extern boolean singletics;
extern int bodyqueslot;
// Needed to store the number of the dummy sky flat.
// Used for rendering,
// as well as tracking projectiles etc.
extern int skyflatnum;
// Netgame stuff (buffers and pointers, i.e. indices).
extern doomcom_t* doomcom;
extern doomdata_t* netbuffer; // This points inside doomcom.
extern int rndindex;
extern int maketic;
extern ticcmd_t netcmds[][BACKUPTICS];
extern int ticdup;
extern int nettics[MAXNETNODES];
//-----------------------------------------------------------------------------
// v1.1-like pitched sounds
extern int pitched_sounds; // killough 2/21/98
extern int allow_pushers; // MT_PUSH Things // phares 3/10/98
extern int default_allow_pushers;
extern int variable_friction; // ice & mud // phares 3/10/98
extern int default_variable_friction;
extern int monsters_remember; // killough 3/1/98
extern int default_monsters_remember;
extern int weapon_recoil; // weapon recoil // phares
extern int default_weapon_recoil;
extern int player_bobbing; // whether player bobs or not // phares 2/25/98
extern int default_player_bobbing; // killough 3/1/98: make local to each game
#ifdef DOGS
extern int dogs, default_dogs; // killough 7/19/98: Marine's best friend :)
extern int dog_jumping, default_dog_jumping; // killough 10/98
#endif
/* killough 8/8/98: distance friendly monsters tend to stay from player */
extern int distfriend, default_distfriend;
/* killough 9/8/98: whether monsters are allowed to strafe or retreat */
extern int monster_backing, default_monster_backing;
/* killough 9/9/98: whether monsters intelligently avoid hazards */
extern int monster_avoid_hazards, default_monster_avoid_hazards;
/* killough 10/98: whether monsters are affected by friction */
extern int monster_friction, default_monster_friction;
/* killough 9/9/98: whether monsters help friends */
extern int help_friends, default_help_friends;
extern int flashing_hom; // killough 10/98
extern int doom_weapon_toggles; // killough 10/98
/* killough 7/19/98: whether monsters should fight against each other */
extern int monster_infighting, default_monster_infighting;
extern int monkeys, default_monkeys;
#endif

View file

@ -0,0 +1,85 @@
/* Emacs style mode select -*- C++ -*-
*-----------------------------------------------------------------------------
*
*
* PrBoom a Doom port merged with LxDoom and LSDLDoom
* based on BOOM, a modified and improved DOOM engine
* Copyright (C) 1999 by
* id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
* Copyright (C) 1999-2000 by
* Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* DESCRIPTION:
* Simple basic typedefs, isolated here to make it easier
* separating modules.
*
*-----------------------------------------------------------------------------*/
#ifndef __DOOMTYPE__
#define __DOOMTYPE__
#include "rockmacros.h"
#ifndef __BYTEBOOL__
#define __BYTEBOOL__
// Fixed to use builtin bool type with C++.
#ifdef __cplusplus
typedef bool boolean;
#else
//typedef enum {false, true} boolean;
//#define boolean bool
typedef enum _boolean { FALSE, TRUE } boolean;
#endif
typedef unsigned char byte;
#endif
typedef signed long long int_64_t;
typedef unsigned long long uint_64_t;
#define MAXCHAR ((char)0x7f)
#define MAXSHORT ((short)0x7fff)
// Max pos 32-bit int.
#define MAXINT ((int)0x7fffffff)
#define MAXLONG ((long)0x7fffffff)
#define MINCHAR ((char)0x80)
#define MINSHORT ((short)0x8000)
// Max negative 32-bit integer.
#define MININT ((int)0x80000000)
#define MINLONG ((long)0x80000000)
/* cph - move compatibility levels here so we can use them in d_server.c */
typedef enum {
doom_12_compatibility, /* Behave like early doom versions */
doom_demo_compatibility, /* As compatible as possible for
* playing original Doom demos */
doom_compatibility, /* Compatible with original Doom levels */
boom_compatibility_compatibility, /* Boom's compatibility mode */
boom_201_compatibility, /* Compatible with Boom v2.01 */
boom_202_compatibility, /* Compatible with Boom v2.01 */
lxdoom_1_compatibility, /* LxDoom v1.3.2+ */
mbf_compatibility, /* MBF */
prboom_1_compatibility, /* PrBoom 2.03beta? */
prboom_2_compatibility, /* PrBoom 2.1.0-2.1.1 */
prboom_3_compatibility, /* Latest PrBoom */
MAX_COMPATIBILITY_LEVEL, /* Must be last entry */
/* Aliases follow */
boom_compatibility = boom_201_compatibility, /* Alias used by G_Compatibility */
best_compatibility = prboom_3_compatibility,
} complevel_t;
#endif

View file

@ -0,0 +1,83 @@
/* Emacs style mode select -*- C++ -*-
*-----------------------------------------------------------------------------
*
*
* PrBoom a Doom port merged with LxDoom and LSDLDoom
* based on BOOM, a modified and improved DOOM engine
* Copyright (C) 1999 by
* id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
* Copyright (C) 1999-2000 by
* Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* DESCRIPTION:
* Globally defined strings.
*
*-----------------------------------------------------------------------------
*/
#ifdef __GNUG__
#pragma implementation "dstrings.h"
#endif
#include "dstrings.h"
// killough 1/18/98: remove hardcoded limit, add const:
const char *const endmsg[]=
{
// DOOM1
QUITMSG,
"please don't leave, there's more\ndemons to toast!",
"let's beat it -- this is turning\ninto a bloodbath!",
"i wouldn't leave if i were you.\ndos is much worse.",
"you're trying to say you like dos\nbetter than me, right?",
"don't leave yet -- there's a\ndemon around that corner!",
"ya know, next time you come in here\ni'm gonna toast ya.",
"go ahead and leave. see if i care.", // 1/15/98 killough
// QuitDOOM II messages
"you want to quit?\nthen, thou hast lost an eighth!",
"don't go now, there's a \ndimensional shambler waiting\nat the dos prompt!",
"get outta here and go back\nto your boring programs.",
"if i were your boss, i'd \n deathmatch ya in a minute!",
"look, bud. you leave now\nand you forfeit your body count!",
"just leave. when you come\nback, i'll be waiting with a bat.",
"you're lucky i don't smack\nyou for thinking about leaving.", // 1/15/98 killough
// FinalDOOM?
// Note that these ending "bad taste" strings were commented out
// in the original id code as the #else case of an #if 1
// Obviously they were internal playthings before the release of
// DOOM2 and were not intended for public use.
//
// Following messages commented out for now. Bad taste. // phares
// "fuck you, pussy!\nget the fuck out!",
// "you quit and i'll jizz\nin your cystholes!",
// "if you leave, i'll make\nthe lord drink my jizz.",
// "hey, ron! can we say\n'fuck' in the game?",
// "i'd leave: this is just\nmore monsters and levels.\nwhat a load.",
// "suck it down, asshole!\nyou're a fucking wimp!",
// "don't quit now! we're \nstill spending your money!",
// Internal debug. Different style, too.
"THIS IS NO MESSAGE!\nPage intentionally left blank.", // 1/15/98 killough
};
// killough 1/18/98: remove hardcoded limit and replace with var (silly hack):
const size_t NUM_QUITMESSAGES = sizeof(endmsg)/sizeof(*endmsg) - 1;

View file

@ -0,0 +1,73 @@
/* Emacs style mode select -*- C++ -*-
*-----------------------------------------------------------------------------
*
*
* PrBoom a Doom port merged with LxDoom and LSDLDoom
* based on BOOM, a modified and improved DOOM engine
* Copyright (C) 1999 by
* id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
* Copyright (C) 1999-2000 by
* Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* DESCRIPTION:
* DOOM strings, by language.
* Note: In BOOM, some new strings hav ebeen defined that are
* not found in the French version. A better approach is
* to create a BEX text-replacement file for other
* languages since any language can be supported that way
* without recompiling the program.
*
*-----------------------------------------------------------------------------*/
#ifndef __DSTRINGS__
#define __DSTRINGS__
#include "d_englsh.h"
#include "rockmacros.h"
/* Note this is not externally modifiable through DEH/BEX
* Misc. other strings.
* #define SAVEGAMENAME "boomsav" * killough 3/22/98 *
* Ty 05/04/98 - replaced with a modifiable string, see d_deh.c
*/
// Misc. other strings.
#define SAVEGAMENAME GAMEBASE"doomsav"
/*
* File locations,
* relative to current position.
* Path names are OS-sensitive.
*/
#define DEVMAPS "devmaps"
#define DEVDATA "devdata"
/* Not done in french?
* QuitDOOM messages *
* killough 1/18/98:
* replace hardcoded limit with extern var (silly hack, I know)
*/
#include <stddef.h>
extern const size_t NUM_QUITMESSAGES; /* Calculated in dstrings.c */
extern const char* const endmsg[]; /* killough 1/18/98 const added */
#endif

View file

@ -0,0 +1,682 @@
/* Emacs style mode select -*- C++ -*-
*-----------------------------------------------------------------------------
*
*
* PrBoom a Doom port merged with LxDoom and LSDLDoom
* based on BOOM, a modified and improved DOOM engine
* Copyright (C) 1999 by
* id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
* Copyright (C) 1999-2000 by
* Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* DESCRIPTION:
* Game completion, final screen animation.
*
*-----------------------------------------------------------------------------
*/
#include "doomstat.h"
#include "d_event.h"
#include "d_englsh.h"
#include "m_swap.h"
#include "v_video.h"
#include "w_wad.h"
#include "s_sound.h"
#include "sounds.h"
//#include "d_deh.h" // Ty 03/22/98 - externalizations
#include "f_finale.h" // CPhipps - hmm...
#include "rockmacros.h"
// Stage of animation:
// 0 = text, 1 = art screen, 2 = character cast
static int finalestage; // cph -
static int finalecount; // made static
static const char* finaletext; // cph -
static const char* finaleflat; // made static const
// defines for the end mission display text // phares
#define TEXTSPEED 3 // original value // phares
#define TEXTWAIT 250 // original value // phares
#define NEWTEXTSPEED 0.01f // new value // phares
#define NEWTEXTWAIT 1000 // new value // phares
// CPhipps - removed the old finale screen text message strings;
// they were commented out for ages already
// Ty 03/22/98 - ... the new s_WHATEVER extern variables are used
// in the code below instead.
void F_StartCast (void);
void F_CastTicker (void);
boolean F_CastResponder (event_t *ev);
void F_CastDrawer (void);
void WI_checkForAccelerate(void); // killough 3/28/98: used to
extern int acceleratestage; // accelerate intermission screens
static int midstage; // whether we're in "mid-stage"
//
// F_StartFinale
//
void F_StartFinale (void)
{
gameaction = ga_nothing;
gamestate = GS_FINALE;
automapmode &= ~am_active;
// killough 3/28/98: clear accelerative text flags
acceleratestage = midstage = 0;
// Okay - IWAD dependend stuff.
// This has been changed severly, and
// some stuff might have changed in the process.
switch ( gamemode )
{
// DOOM 1 - E1, E3 or E4, but each nine missions
case shareware:
case registered:
case retail:
{
S_ChangeMusic(mus_victor, true);
switch (gameepisode)
{
case 1:
finaleflat = "FLOOR4_8";
finaletext = E1TEXT;
break;
case 2:
finaleflat = "SFLR6_1";
finaletext = E2TEXT;
break;
case 3:
finaleflat = "MFLR8_4";
finaletext = E3TEXT;
break;
case 4:
finaleflat = "MFLR8_3";
finaletext = E4TEXT;
break;
default:
// Ouch.
break;
}
break;
}
// DOOM II and missions packs with E1, M34
case commercial:
{
S_ChangeMusic(mus_read_m, true);
// Ty 08/27/98 - added the gamemission logic
switch (gamemap)
{
case 6:
finaleflat = "SLIME16";
finaletext = (gamemission==pack_tnt) ? T1TEXT :
(gamemission==pack_plut) ? P1TEXT : C1TEXT;
break;
case 11:
finaleflat = "RROCK14";
finaletext = (gamemission==pack_tnt) ? T2TEXT :
(gamemission==pack_plut) ? P2TEXT : C2TEXT;
break;
case 20:
finaleflat = "RROCK07";
finaletext = (gamemission==pack_tnt) ? T3TEXT :
(gamemission==pack_plut) ? P3TEXT : C3TEXT;
break;
case 30:
finaleflat = "RROCK17";
finaletext = (gamemission==pack_tnt) ? T4TEXT :
(gamemission==pack_plut) ? P4TEXT : C4TEXT;
break;
case 15:
finaleflat = "RROCK13";
finaletext = (gamemission==pack_tnt) ? T5TEXT :
(gamemission==pack_plut) ? P5TEXT : C5TEXT;
break;
case 31:
finaleflat = "RROCK19";
finaletext = (gamemission==pack_tnt) ? T6TEXT :
(gamemission==pack_plut) ? P6TEXT : C6TEXT;
break;
default:
// Ouch.
break;
}
break;
}
// Indeterminate.
default:
S_ChangeMusic(mus_read_m, true);
finaleflat = "F_SKY1"; // Not used anywhere else.
finaletext = C1TEXT; // FIXME - other text, music?
break;
}
finalestage = 0;
finalecount = 0;
}
boolean F_Responder (event_t *event)
{
if (finalestage == 2)
return F_CastResponder (event);
return false;
}
// Get_TextSpeed() returns the value of the text display speed // phares
// Rewritten to allow user-directed acceleration -- killough 3/28/98
static float Get_TextSpeed(void)
{
return midstage ? NEWTEXTSPEED : (midstage=acceleratestage) ?
acceleratestage=0, NEWTEXTSPEED : TEXTSPEED;
}
//
// F_Ticker
//
// killough 3/28/98: almost totally rewritten, to use
// player-directed acceleration instead of constant delays.
// Now the player can accelerate the text display by using
// the fire/use keys while it is being printed. The delay
// automatically responds to the user, and gives enough
// time to read.
//
// killough 5/10/98: add back v1.9 demo compatibility
//
void F_Ticker(void)
{
int i;
if (!demo_compatibility)
WI_checkForAccelerate(); // killough 3/28/98: check for acceleration
else
if (gamemode == commercial && finalecount > 50) // check for skipping
for (i=0; i<MAXPLAYERS; i++)
if (players[i].cmd.buttons)
goto next_level; // go on to the next level
// advance animation
finalecount++;
if (finalestage == 2)
F_CastTicker();
if (!finalestage)
{
float speed = demo_compatibility ? TEXTSPEED : Get_TextSpeed();
/* killough 2/28/98: changed to allow acceleration */
if (finalecount > strlen(finaletext)*speed +
(midstage ? NEWTEXTWAIT : TEXTWAIT) ||
(midstage && acceleratestage)) {
if (gamemode != commercial) // Doom 1 / Ultimate Doom episode end
{ // with enough time, it's automatic
finalecount = 0;
finalestage = 1;
wipegamestate = -1; // force a wipe
if (gameepisode == 3)
S_StartMusic(mus_bunny);
}
else // you must press a button to continue in Doom 2
if (!demo_compatibility && midstage)
{
next_level:
if (gamemap == 30)
F_StartCast(); // cast of Doom 2 characters
else
gameaction = ga_worlddone; // next level, e.g. MAP07
}
}
}
}
//
// F_TextWrite
//
// This program displays the background and text at end-mission // phares
// text time. It draws both repeatedly so that other displays, // |
// like the main menu, can be drawn over it dynamically and // V
// erased dynamically. The TEXTSPEED constant is changed into
// the Get_TextSpeed function so that the speed of writing the // ^
// text can be increased, and there's still time to read what's // |
// written. // phares
// CPhipps - reformatted
#include "hu_stuff.h"
extern patchnum_t hu_font[HU_FONTSIZE];
void F_TextWrite (void)
{
V_DrawBackground(finaleflat, 0);
{ // draw some of the text onto the screen
int cx = 10;
int cy = 10;
const char* ch = finaletext; // CPhipps - const
int count = (int)((float)(finalecount - 10)/Get_TextSpeed()); // phares
int w;
if (count < 0)
count = 0;
for ( ; count ; count-- ) {
int c = *ch++;
if (!c)
break;
if (c == '\n') {
cx = 10;
cy += 11;
continue;
}
c = toupper(c) - HU_FONTSTART;
if (c < 0 || c> HU_FONTSIZE) {
cx += 4;
continue;
}
w = SHORT (hu_font[c].width);
if (cx+w > SCREENWIDTH)
break;
// CPhipps - patch drawing updated
V_DrawNumPatch(cx, cy, 0, hu_font[c].lumpnum, CR_DEFAULT, VPT_STRETCH);
cx+=w;
}
}
}
//
// Final DOOM 2 animation
// Casting by id Software.
// in order of appearance
//
typedef struct
{
const char *name; // CPhipps - const**
mobjtype_t type;
} castinfo_t;
#define MAX_CASTORDER 18 /* Ty - hard coded for now */
static const castinfo_t castorder[] = { // CPhipps - static const, initialised here
{ CC_ZOMBIE, MT_POSSESSED },
{ CC_SHOTGUN, MT_SHOTGUY },
{ CC_HEAVY, MT_CHAINGUY },
{ CC_IMP, MT_TROOP },
{ CC_DEMON, MT_SERGEANT },
{ CC_LOST, MT_SKULL },
{ CC_CACO, MT_HEAD },
{ CC_HELL, MT_KNIGHT },
{ CC_BARON, MT_BRUISER },
{ CC_ARACH, MT_BABY },
{ CC_PAIN, MT_PAIN },
{ CC_REVEN, MT_UNDEAD },
{ CC_MANCU, MT_FATSO },
{ CC_ARCH, MT_VILE },
{ CC_SPIDER, MT_SPIDER },
{ CC_CYBER, MT_CYBORG },
{ CC_HERO, MT_PLAYER },
{ NULL, 0}
};
int castnum;
int casttics;
state_t* caststate;
boolean castdeath;
int castframes;
int castonmelee;
boolean castattacking;
//
// F_StartCast
//
extern gamestate_t wipegamestate;
void F_StartCast (void)
{
wipegamestate = -1; // force a screen wipe
castnum = 0;
caststate = &states[mobjinfo[castorder[castnum].type].seestate];
casttics = caststate->tics;
castdeath = false;
finalestage = 2;
castframes = 0;
castonmelee = 0;
castattacking = false;
S_ChangeMusic(mus_evil, true);
}
//
// F_CastTicker
//
void F_CastTicker (void)
{
int st;
int sfx;
if (--casttics > 0)
return; // not time to change state yet
if (caststate->tics == -1 || caststate->nextstate == S_NULL)
{
// switch from deathstate to next monster
castnum++;
castdeath = false;
if (castorder[castnum].name == NULL)
castnum = 0;
if (mobjinfo[castorder[castnum].type].seesound)
S_StartSound (NULL, mobjinfo[castorder[castnum].type].seesound);
caststate = &states[mobjinfo[castorder[castnum].type].seestate];
castframes = 0;
}
else
{
// just advance to next state in animation
if (caststate == &states[S_PLAY_ATK1])
goto stopattack; // Oh, gross hack!
st = caststate->nextstate;
caststate = &states[st];
castframes++;
// sound hacks....
switch (st)
{
case S_PLAY_ATK1: sfx = sfx_dshtgn; break;
case S_POSS_ATK2: sfx = sfx_pistol; break;
case S_SPOS_ATK2: sfx = sfx_shotgn; break;
case S_VILE_ATK2: sfx = sfx_vilatk; break;
case S_SKEL_FIST2: sfx = sfx_skeswg; break;
case S_SKEL_FIST4: sfx = sfx_skepch; break;
case S_SKEL_MISS2: sfx = sfx_skeatk; break;
case S_FATT_ATK8:
case S_FATT_ATK5:
case S_FATT_ATK2: sfx = sfx_firsht; break;
case S_CPOS_ATK2:
case S_CPOS_ATK3:
case S_CPOS_ATK4: sfx = sfx_shotgn; break;
case S_TROO_ATK3: sfx = sfx_claw; break;
case S_SARG_ATK2: sfx = sfx_sgtatk; break;
case S_BOSS_ATK2:
case S_BOS2_ATK2:
case S_HEAD_ATK2: sfx = sfx_firsht; break;
case S_SKULL_ATK2: sfx = sfx_sklatk; break;
case S_SPID_ATK2:
case S_SPID_ATK3: sfx = sfx_shotgn; break;
case S_BSPI_ATK2: sfx = sfx_plasma; break;
case S_CYBER_ATK2:
case S_CYBER_ATK4:
case S_CYBER_ATK6: sfx = sfx_rlaunc; break;
case S_PAIN_ATK3: sfx = sfx_sklatk; break;
default: sfx = 0; break;
}
if (sfx)
S_StartSound (NULL, sfx);
}
if (castframes == 12)
{
// go into attack frame
castattacking = true;
if (castonmelee)
caststate=&states[mobjinfo[castorder[castnum].type].meleestate];
else
caststate=&states[mobjinfo[castorder[castnum].type].missilestate];
castonmelee ^= 1;
if (caststate == &states[S_NULL])
{
if (castonmelee)
caststate=
&states[mobjinfo[castorder[castnum].type].meleestate];
else
caststate=
&states[mobjinfo[castorder[castnum].type].missilestate];
}
}
if (castattacking)
{
if (castframes == 24
|| caststate == &states[mobjinfo[castorder[castnum].type].seestate] )
{
stopattack:
castattacking = false;
castframes = 0;
caststate = &states[mobjinfo[castorder[castnum].type].seestate];
}
}
casttics = caststate->tics;
if (casttics == -1)
casttics = 15;
}
//
// F_CastResponder
//
boolean F_CastResponder (event_t* ev)
{
if (ev->type != ev_keydown)
return false;
if (castdeath)
return true; // already in dying frames
// go into death frame
castdeath = true;
caststate = &states[mobjinfo[castorder[castnum].type].deathstate];
casttics = caststate->tics;
castframes = 0;
castattacking = false;
if (mobjinfo[castorder[castnum].type].deathsound)
S_StartSound (NULL, mobjinfo[castorder[castnum].type].deathsound);
return true;
}
static void F_CastPrint (const char* text) // CPhipps - static, const char*
{
const char* ch; // CPhipps - const
int c;
int cx;
int w;
int width;
// find width
ch = text;
width = 0;
while (ch)
{
c = *ch++;
if (!c)
break;
c = toupper(c) - HU_FONTSTART;
if (c < 0 || c> HU_FONTSIZE)
{
width += 4;
continue;
}
w = SHORT (hu_font[c].width);
width += w;
}
// draw it
cx = 160-width/2;
ch = text;
while (ch)
{
c = *ch++;
if (!c)
break;
c = toupper(c) - HU_FONTSTART;
if (c < 0 || c> HU_FONTSIZE)
{
cx += 4;
continue;
}
w = SHORT (hu_font[c].width);
// CPhipps - patch drawing updated
V_DrawNumPatch(cx, 180, 0, hu_font[c].lumpnum, CR_DEFAULT, VPT_STRETCH);
cx+=w;
}
}
//
// F_CastDrawer
//
void V_DrawPatchFlipped (int x, int y, int scrn, patch_t *patch);
void F_CastDrawer (void)
{
spritedef_t* sprdef;
spriteframe_t* sprframe;
int lump;
boolean flip;
// erase the entire screen to a background
V_DrawNamePatch(0,0,0, "BOSSBACK", CR_DEFAULT, VPT_STRETCH); // Ty 03/30/98 bg texture extern
F_CastPrint (castorder[castnum].name);
// draw the current frame in the middle of the screen
sprdef = &sprites[caststate->sprite];
sprframe = &sprdef->spriteframes[ caststate->frame & FF_FRAMEMASK];
lump = sprframe->lump[0];
flip = (boolean)sprframe->flip[0];
// CPhipps - patch drawing updated
V_DrawNumPatch(160, 170, 0, lump+firstspritelump, CR_DEFAULT,
VPT_STRETCH | (flip ? VPT_FLIP : 0));
}
//
// F_BunnyScroll
//
static const char pfub2[] = { "PFUB2" };
static const char pfub1[] = { "PFUB1" };
static void F_BunnyScroll (void)
{
char name[10];
int stage;
static int laststage;
V_MarkRect (0, 0, SCREENWIDTH, SCREENHEIGHT);
{
int scrolled = 320 - (finalecount-230)/2;
if (scrolled <= 0) {
V_DrawNamePatch(0, 0, 0, pfub2, CR_DEFAULT, VPT_STRETCH);
} else if (scrolled >= 320) {
V_DrawNamePatch(0, 0, 0, pfub1, CR_DEFAULT, VPT_STRETCH);
} else {
#define SCRN 2
int realscrolled = (SCREENWIDTH * scrolled) / 320;
V_AllocScreen(SCRN);
V_DrawNamePatch(0, 0, SCRN, pfub2, CR_DEFAULT, VPT_STRETCH);
V_CopyRect(realscrolled, 0, SCRN, SCREENWIDTH-realscrolled, SCREENHEIGHT, 0, 0, 0, VPT_NONE);
V_DrawNamePatch(0, 0, SCRN, pfub1, CR_DEFAULT, VPT_STRETCH);
V_CopyRect(0, 0, SCRN, realscrolled, SCREENHEIGHT, SCREENWIDTH-realscrolled, 0, 0, VPT_NONE);
V_FreeScreen(SCRN);
}
}
if (finalecount < 1130)
return;
if (finalecount < 1180)
{
// CPhipps - patch drawing updated
V_DrawNamePatch((320-13*8)/2, (200-8*8)/2,0, "END0", CR_DEFAULT, VPT_STRETCH);
laststage = 0;
return;
}
stage = (finalecount-1180) / 5;
if (stage > 6)
stage = 6;
if (stage > laststage)
{
S_StartSound (NULL, sfx_pistol);
laststage = stage;
}
snprintf (name,sizeof(name), "END%i",stage);
// CPhipps - patch drawing updated
V_DrawNamePatch((320-13*8)/2, (200-8*8)/2, 0, name, CR_DEFAULT, VPT_STRETCH);
}
//
// F_Drawer
//
void F_Drawer (void)
{
if (finalestage == 2)
{
F_CastDrawer ();
return;
}
if (!finalestage)
F_TextWrite ();
else
{
switch (gameepisode)
{
// CPhipps - patch drawing updated
case 1:
if ( gamemode == retail )
V_DrawNamePatch(0, 0, 0, "CREDIT", CR_DEFAULT, VPT_STRETCH);
else
V_DrawNamePatch(0, 0, 0, "HELP2", CR_DEFAULT, VPT_STRETCH);
break;
case 2:
V_DrawNamePatch(0, 0, 0, "VICTORY2", CR_DEFAULT, VPT_STRETCH);
break;
case 3:
F_BunnyScroll ();
break;
case 4:
V_DrawNamePatch(0, 0, 0, "ENDPIC", CR_DEFAULT, VPT_STRETCH);
break;
}
}
}

View file

@ -0,0 +1,54 @@
/* Emacs style mode select -*- C++ -*-
*-----------------------------------------------------------------------------
*
*
* PrBoom a Doom port merged with LxDoom and LSDLDoom
* based on BOOM, a modified and improved DOOM engine
* Copyright (C) 1999 by
* id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
* Copyright (C) 1999-2000 by
* Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* DESCRIPTION:
* Related to f_finale.c, which is called at the end of a level
*
*-----------------------------------------------------------------------------*/
#ifndef __F_FINALE__
#define __F_FINALE__
#include "doomtype.h"
#include "d_event.h"
/*
* FINALE
*/
/* Called by main loop. */
boolean F_Responder (event_t* ev);
/* Called by main loop. */
void F_Ticker (void);
/* Called by main loop. */
void F_Drawer (void);
void F_StartFinale (void);
#endif

193
apps/plugins/doom/f_wipe.c Normal file
View file

@ -0,0 +1,193 @@
/* Emacs style mode select -*- C++ -*-
*-----------------------------------------------------------------------------
*
*
* PrBoom a Doom port merged with LxDoom and LSDLDoom
* based on BOOM, a modified and improved DOOM engine
* Copyright (C) 1999 by
* id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
* Copyright (C) 1999-2000 by
* Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* DESCRIPTION:
* Mission begin melt/wipe screen special effect.
*
*-----------------------------------------------------------------------------
*/
#include "rockmacros.h"
#include "z_zone.h"
#include "doomdef.h"
#include "i_video.h"
#include "v_video.h"
#include "m_random.h"
#include "f_wipe.h"
//
// SCREEN WIPE PACKAGE
//
// CPhipps - macros for the source and destination screens
#define SRC_SCR 2
#define DEST_SCR 3
static byte *wipe_scr_start;
static byte *wipe_scr_end;
static byte *wipe_scr;
static void wipe_shittyColMajorXform(short *array, int width, int height)
{
short *dest = Z_Malloc(width*height*sizeof(short), PU_STATIC, 0);
int x, y;
for(y=0;y<height;y++)
for(x=0;x<width;x++)
dest[x*height+y] = array[y*width+x];
memcpy(array, dest, width*height*sizeof(short));
Z_Free(dest);
}
static int *y;
static int wipe_initMelt(int width, int height, int ticks)
{
(void)ticks;
int i;
// copy start screen to main screen
memcpy(wipe_scr, wipe_scr_start, width*height);
// makes this wipe faster (in theory)
// to have stuff in column-major format
wipe_shittyColMajorXform((short*)wipe_scr_start, width/2, height);
wipe_shittyColMajorXform((short*)wipe_scr_end, width/2, height);
// setup initial column positions (y<0 => not ready to scroll yet)
y = (int *) malloc(width*sizeof(int));
y[0] = -(M_Random()%16);
for (i=1;i<width;i++)
{
int r = (M_Random()%3) - 1;
y[i] = y[i-1] + r;
if (y[i] > 0)
y[i] = 0;
else
if (y[i] == -16)
y[i] = -15;
}
return 0;
}
static int wipe_doMelt(int width, int height, int ticks)
{
boolean done = true;
int i;
width /= 2;
while (ticks--)
for (i=0;i<width;i++)
if (y[i]<0)
{
y[i]++;
done = false;
}
else
if (y[i] < height)
{
short *s, *d;
int j, dy, idx;
dy = (y[i] < 16) ? y[i]+1 : 8;
if (y[i]+dy >= height)
dy = height - y[i];
s = &((short *)wipe_scr_end)[i*height+y[i]];
d = &((short *)wipe_scr)[y[i]*width+i];
idx = 0;
for (j=dy;j;j--)
{
d[idx] = *(s++);
idx += width;
}
y[i] += dy;
s = &((short *)wipe_scr_start)[i*height];
d = &((short *)wipe_scr)[y[i]*width+i];
idx = 0;
for (j=height-y[i];j;j--)
{
d[idx] = *(s++);
idx += width;
}
done = false;
}
return done;
}
// CPhipps - modified to allocate and deallocate screens[2 to 3] as needed, saving memory
static int wipe_exitMelt(int width, int height, int ticks)
{
(void)width;
(void)height;
(void)ticks;
free(y);
free(wipe_scr_start);
free(wipe_scr_end);
// Paranoia
y = NULL;
wipe_scr_start = wipe_scr_end = screens[SRC_SCR] = screens[DEST_SCR] = NULL;
return 0;
}
int wipe_StartScreen(int x, int y, int width, int height)
{
wipe_scr_start = screens[SRC_SCR] = malloc(SCREENWIDTH * SCREENHEIGHT);
V_CopyRect(x, y, 0, width, height, x, y, SRC_SCR, VPT_NONE ); // Copy start screen to buffer
return 0;
}
int wipe_EndScreen(int x, int y, int width, int height)
{
wipe_scr_end = screens[DEST_SCR] = malloc(SCREENWIDTH * SCREENHEIGHT);
V_CopyRect(x, y, 0, width, height, x, y, DEST_SCR, VPT_NONE); // Copy end screen to buffer
V_CopyRect(x, y, SRC_SCR, width, height, x, y, 0 , VPT_NONE); // restore start screen
return 0;
}
// killough 3/5/98: reformatted and cleaned up
int wipe_ScreenWipe(int x, int y, int width, int height, int ticks)
{
(void)x;
(void)y;
static boolean go; // when zero, stop the wipe
if (!go) // initial stuff
{
go = 1;
wipe_scr = screens[0];
wipe_initMelt(width, height, ticks);
}
V_MarkRect(0, 0, width, height); // do a piece of wipe-in
if (wipe_doMelt(width, height, ticks)) // final stuff
{
wipe_exitMelt(width, height, ticks);
go = 0;
}
return !go;
}

View file

@ -0,0 +1,43 @@
/* Emacs style mode select -*- C++ -*-
*-----------------------------------------------------------------------------
*
*
* PrBoom a Doom port merged with LxDoom and LSDLDoom
* based on BOOM, a modified and improved DOOM engine
* Copyright (C) 1999 by
* id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
* Copyright (C) 1999-2000 by
* Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* DESCRIPTION:
* Mission start screen wipe/melt, special effects.
*
*-----------------------------------------------------------------------------*/
#ifndef __F_WIPE_H__
#define __F_WIPE_H__
/*
* SCREEN WIPE PACKAGE
*/
int wipe_ScreenWipe (int x, int y, int width, int height, int ticks);
int wipe_StartScreen(int x, int y, int width, int height);
int wipe_EndScreen (int x, int y, int width, int height);
#endif

2818
apps/plugins/doom/g_game.c Normal file

File diff suppressed because it is too large Load diff

192
apps/plugins/doom/g_game.h Normal file
View file

@ -0,0 +1,192 @@
/* Emacs style mode select -*- C++ -*-
*-----------------------------------------------------------------------------
*
*
* PrBoom a Doom port merged with LxDoom and LSDLDoom
* based on BOOM, a modified and improved DOOM engine
* Copyright (C) 1999 by
* id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
* Copyright (C) 1999-2000 by
* Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* DESCRIPTION: Main game control interface.
*-----------------------------------------------------------------------------*/
#ifndef __G_GAME__
#define __G_GAME__
#include "doomdef.h"
#include "d_event.h"
#include "d_ticcmd.h"
//
// GAME
//
// killough 5/2/98: number of bytes reserved for saving options
#define GAME_OPTION_SIZE 64
boolean G_Responder(event_t *ev);
boolean G_CheckDemoStatus(void);
boolean G_CheckDemoStatus(void);
void G_DeathMatchSpawnPlayer(int playernum);
void G_InitNew(skill_t skill, int episode, int map);
void G_DeferedInitNew(skill_t skill, int episode, int map);
void G_DeferedPlayDemo(const char *demo); // CPhipps - const
void G_LoadGame(int slot, boolean is_command); // killough 5/15/98
void G_ForcedLoadGame(void); // killough 5/15/98: forced loadgames
void G_DoLoadGame(void);
void G_SaveGame(int slot, char *description); // Called by M_Responder.
void G_BeginRecording(void);
// CPhipps - const on these string params
void G_RecordDemo(const char *name); // Only called by startup code.
void G_PlayDemo(const char *name);
void G_TimeDemo(const char *name);
void G_ExitLevel(void);
void G_SecretExitLevel(void);
void G_WorldDone(void);
void G_EndGame(void); /* cph - make m_menu.c call a G_* function for this */
void G_Ticker(void);
void G_ReloadDefaults(void); // killough 3/1/98: loads game defaults
void G_SaveGameName(char *, size_t, int, boolean); /* killough 3/22/98: sets savegame filename */
void G_SetFastParms(int); // killough 4/10/98: sets -fast parameters
void G_DoNewGame(void);
void G_DoReborn(int playernum);
void G_DoPlayDemo(void);
void G_DoCompleted(void);
void G_ReadDemoTiccmd(ticcmd_t *cmd);
void G_WriteDemoTiccmd(ticcmd_t *cmd);
void G_DoWorldDone(void);
void G_Compatibility(void);
const byte *G_ReadOptions(const byte *demo_p); /* killough 3/1/98 - cph: const byte* */
byte *G_WriteOptions(byte *demo_p); // killough 3/1/98
void G_PlayerReborn(int player);
void G_InitNew(skill_t skill, int episode, int map);
void G_RestartLevel(void); // CPhipps - menu involked level restart
void G_DoLoadGame(void);
void G_DoVictory(void);
void G_BuildTiccmd (ticcmd_t* cmd); // CPhipps - move decl to header
void G_ChangedPlayerColour(int pn, int cl); // CPhipps - On-the-fly player colour changing
void G_MakeSpecialEvent(buttoncode_t bc, ...); /* cph - new event stuff */
// killough 1/18/98: Doom-style printf; killough 4/25/98: add gcc attributes
// CPhipps - renames to doom_printf to avoid name collision with glibc
void doom_printf(const char *, ...) __attribute__((format(printf,1,2)));
// killough 5/2/98: moved from m_misc.c:
extern int key_right;
extern int key_left;
extern int key_up;
extern int key_down;
extern int key_menu_right; // phares 3/7/98
extern int key_menu_left; // |
extern int key_menu_up; // V
extern int key_menu_down;
extern int key_menu_backspace; // ^
extern int key_menu_escape; // |
extern int key_menu_enter; // phares 3/7/98
extern int key_strafeleft;
extern int key_straferight;
extern int key_fire;
extern int key_use;
extern int key_strafe;
extern int key_speed;
extern int key_escape; // phares
extern int key_savegame; // |
extern int key_loadgame; // V
extern int key_autorun;
extern int key_reverse;
extern int key_zoomin;
extern int key_zoomout;
extern int key_chat;
extern int key_backspace;
extern int key_enter;
extern int key_help;
extern int key_soundvolume;
extern int key_hud;
extern int key_quicksave;
extern int key_endgame;
extern int key_messages;
extern int key_quickload;
extern int key_quit;
extern int key_gamma;
extern int key_spy;
extern int key_pause;
extern int key_setup;
extern int key_forward;
extern int key_leftturn;
extern int key_rightturn;
extern int key_backward;
extern int key_weapon;
extern int key_weapontoggle;
extern int key_weapon1;
extern int key_weapon2;
extern int key_weapon3;
extern int key_weapon4;
extern int key_weapon5;
extern int key_weapon6;
extern int key_weapon7;
extern int key_weapon8;
extern int key_weapon9;
extern int destination_keys[MAXPLAYERS];
extern int key_map_right;
extern int key_map_left;
extern int key_map_up;
extern int key_map_down;
extern int key_map_zoomin;
extern int key_map_zoomout;
extern int key_map;
extern int key_map_gobig;
extern int key_map_follow;
extern int key_map_mark; // ^
extern int key_map_clear; // |
extern int key_map_grid; // phares
extern int key_map_rotate; // cph - map rotation
extern int key_map_overlay;// cph - map overlay
extern int key_screenshot; // killough 2/22/98 -- add key for screenshot
extern int autorun; // always running? // phares
extern int joybfire;
extern int joybuse;
extern int joybstrafe;
extern int joybspeed;
extern int mousebfire;
extern int mousebstrafe;
extern int mousebforward;
extern int defaultskill; //jff 3/24/98 default skill
extern boolean haswolflevels; //jff 4/18/98 wolf levels present
extern int bodyquesize; // killough 2/8/98: adustable corpse limit
// killough 5/2/98: moved from d_deh.c:
// Par times (new item with BOOM) - from g_game.c
extern int pars[4][10]; // hardcoded array size
extern int cpars[32]; // hardcoded array size
// CPhipps - Make savedesciption visible in wider scope
#define SAVEDESCLEN 32
extern char savedescription[SAVEDESCLEN]; // Description to save in savegame
/* cph - compatibility level strings */
extern const char * comp_lev_str[];
#endif

770
apps/plugins/doom/hu_lib.c Normal file
View file

@ -0,0 +1,770 @@
/* Emacs style mode select -*- C++ -*-
*-----------------------------------------------------------------------------
*
*
* PrBoom a Doom port merged with LxDoom and LSDLDoom
* based on BOOM, a modified and improved DOOM engine
* Copyright (C) 1999 by
* id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
* Copyright (C) 1999-2000 by
* Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* DESCRIPTION: heads-up text and input code
*
*-----------------------------------------------------------------------------
*/
#include "doomdef.h"
#include "doomstat.h"
#include "v_video.h"
#include "m_swap.h"
#include "hu_lib.h"
#include "hu_stuff.h"
#include "r_main.h"
#include "r_draw.h"
#include "rockmacros.h"
// boolean : whether the screen is always erased
#define noterased viewwindowx
extern int key_backspace; // phares
extern int key_enter; // phares
//
// not used currently
// code to initialize HUlib would go here if needed
//
void HUlib_init(void)
{
}
////////////////////////////////////////////////////////
//
// Basic text line widget
//
////////////////////////////////////////////////////////
//
// HUlib_clearTextLine()
//
// Blank the internal text line in a hu_textline_t widget
//
// Passed a hu_textline_t, returns nothing
//
void HUlib_clearTextLine(hu_textline_t* t)
{
t->linelen = // killough 1/23 98: support multiple lines
t->len = 0;
t->l[0] = 0;
t->needsupdate = true;
}
//
// HUlib_initTextLine()
//
// Initialize a hu_textline_t widget. Set the position, font, start char
// of the font, and color range to be used.
//
// Passed a hu_textline_t, and the values used to initialize
// Returns nothing
//
void HUlib_initTextLine(hu_textline_t* t, int x, int y,
const patchnum_t* f, int sc, int cm )
//jff 2/16/98 add color range parameter
{
t->x = x;
t->y = y;
t->f = f;
t->sc = sc;
t->cm = cm;
HUlib_clearTextLine(t);
}
//
// HUlib_addCharToTextLine()
//
// Adds a character at the end of the text line in a hu_textline_t widget
//
// Passed the hu_textline_t and the char to add
// Returns false if already at length limit, true if the character added
//
boolean HUlib_addCharToTextLine
( hu_textline_t* t,
char ch )
{
// killough 1/23/98 -- support multiple lines
if (t->linelen == HU_MAXLINELENGTH)
return false;
else
{
t->linelen++;
if (ch == '\n')
t->linelen=0;
t->l[t->len++] = ch;
t->l[t->len] = 0;
t->needsupdate = 4;
return true;
}
}
//
// HUlib_delCharFromTextLine()
//
// Deletes a character at the end of the text line in a hu_textline_t widget
//
// Passed the hu_textline_t
// Returns false if already empty, true if the character deleted
//
boolean HUlib_delCharFromTextLine(hu_textline_t* t)
{
if (!t->len) return false;
else
{
t->l[--t->len] = 0;
t->needsupdate = 4;
return true;
}
}
//
// HUlib_drawTextLine()
//
// Draws a hu_textline_t widget
//
// Passed the hu_textline_t and flag whether to draw a cursor
// Returns nothing
//
void HUlib_drawTextLine
( hu_textline_t* l,
boolean drawcursor )
{
int i;
int w;
int x;
unsigned char c;
int oc = l->cm; //jff 2/17/98 remember default color
int y = l->y; // killough 1/18/98 -- support multiple lines
// draw the new stuff
x = l->x;
for (i=0;i<l->len;i++)
{
c = toupper(l->l[i]); //jff insure were not getting a cheap toupper conv.
if (c=='\n') // killough 1/18/98 -- support multiple lines
x=0,y+=8;
else if (c=='\t') // killough 1/23/98 -- support tab stops
x=x-x%80+80;
else if (c=='\x1b') //jff 2/17/98 escape code for color change
{ //jff 3/26/98 changed to actual escape char
if (++i<l->len)
if (l->l[i]>='0' && l->l[i]<='9')
l->cm = l->l[i]-'0';
}
else if (c != ' ' && c >= l->sc && c <= 127)
{
w = SHORT(l->f[c - l->sc].width);
if (x+w > BASE_WIDTH)
break;
// killough 1/18/98 -- support multiple lines:
// CPhipps - patch drawing updated
V_DrawNumPatch(x, y, FG, l->f[c - l->sc].lumpnum, l->cm, VPT_TRANS | VPT_STRETCH);
x += w;
}
else
{
x += 4;
if (x >= BASE_WIDTH)
break;
}
}
l->cm = oc; //jff 2/17/98 restore original color
// draw the cursor if requested
if (drawcursor && x + SHORT(l->f['_' - l->sc].width) <= BASE_WIDTH)
{
// killough 1/18/98 -- support multiple lines
// CPhipps - patch drawing updated
V_DrawNumPatch(x, y, FG, l->f['_' - l->sc].lumpnum, CR_DEFAULT, VPT_NONE | VPT_STRETCH);
}
}
//
// HUlib_eraseTextLine()
//
// Erases a hu_textline_t widget when screen border is behind text
// Sorta called by HU_Erase and just better darn get things straight
//
// Passed the hu_textline_t
// Returns nothing
//
void HUlib_eraseTextLine(hu_textline_t* l)
{
int lh;
int y;
int yoffset;
// Only erases when NOT in automap and the screen is reduced,
// and the text must either need updating or refreshing
// (because of a recent change back from the automap)
if (!(automapmode & am_active) && viewwindowx && l->needsupdate)
{
lh = SHORT(l->f[0].height) + 1;
for (y=l->y,yoffset=y*SCREENWIDTH ; y<l->y+lh ; y++,yoffset+=SCREENWIDTH)
{
if (y < viewwindowy || y >= viewwindowy + viewheight)
R_VideoErase(yoffset, SCREENWIDTH); // erase entire line
else
{
// erase left border
R_VideoErase(yoffset, viewwindowx);
// erase right border
R_VideoErase(yoffset + viewwindowx + viewwidth, viewwindowx);
}
}
}
if (l->needsupdate) l->needsupdate--;
}
////////////////////////////////////////////////////////
//
// Player message widget (up to 4 lines of text)
//
////////////////////////////////////////////////////////
//
// HUlib_initSText()
//
// Initialize a hu_stext_t widget. Set the position, number of lines, font,
// start char of the font, and color range to be used, and whether enabled.
//
// Passed a hu_stext_t, and the values used to initialize
// Returns nothing
//
void HUlib_initSText
( hu_stext_t* s,
int x,
int y,
int h,
const patchnum_t* font,
int startchar,
int cm, //jff 2/16/98 add color range parameter
boolean* on )
{
int i;
s->h = h;
s->on = on;
s->laston = true;
s->cl = 0;
for (i=0;i<h;i++)
HUlib_initTextLine
(
&s->l[i],
x,
y - i*(SHORT(font[0].height)+1),
font,
startchar,
cm
);
}
//
// HUlib_addLineToSText()
//
// Adds a blank line to a hu_stext_t widget
//
// Passed a hu_stext_t
// Returns nothing
//
void HUlib_addLineToSText(hu_stext_t* s)
{
int i;
// add a clear line
if (++s->cl == s->h)
s->cl = 0;
HUlib_clearTextLine(&s->l[s->cl]);
// everything needs updating
for (i=0 ; i<s->h ; i++)
s->l[i].needsupdate = 4;
}
//
// HUlib_addMessageToSText()
//
// Adds a message line with prefix to a hu_stext_t widget
//
// Passed a hu_stext_t, the prefix string, and a message string
// Returns nothing
//
void HUlib_addMessageToSText(hu_stext_t* s, const char* prefix, const char* msg)
{
HUlib_addLineToSText(s);
if (prefix)
while (*prefix)
HUlib_addCharToTextLine(&s->l[s->cl], *(prefix++));
while (*msg)
HUlib_addCharToTextLine(&s->l[s->cl], *(msg++));
}
//
// HUlib_drawSText()
//
// Displays a hu_stext_t widget
//
// Passed a hu_stext_t
// Returns nothing
//
void HUlib_drawSText(hu_stext_t* s)
{
int i, idx;
hu_textline_t *l;
if (!*s->on)
return; // if not on, don't draw
// draw everything
for (i=0 ; i<s->h ; i++)
{
idx = s->cl - i;
if (idx < 0)
idx += s->h; // handle queue of lines
l = &s->l[idx];
// need a decision made here on whether to skip the draw
HUlib_drawTextLine(l, false); // no cursor, please
}
}
//
// HUlib_eraseSText()
//
// Erases a hu_stext_t widget, when the screen is not fullsize
//
// Passed a hu_stext_t
// Returns nothing
//
void HUlib_eraseSText(hu_stext_t* s)
{
int i;
for (i=0 ; i<s->h ; i++)
{
if (s->laston && !*s->on)
s->l[i].needsupdate = 4;
HUlib_eraseTextLine(&s->l[i]);
}
s->laston = *s->on;
}
////////////////////////////////////////////////////////
//
// Scrolling message review widget
//
// jff added 2/26/98
//
////////////////////////////////////////////////////////
//
// HUlib_initMText()
//
// Initialize a hu_mtext_t widget. Set the position, width, number of lines,
// font, start char of the font, color range, background font, and whether
// enabled.
//
// Passed a hu_mtext_t, and the values used to initialize
// Returns nothing
//
void HUlib_initMText(hu_mtext_t *m, int x, int y, int w, int h,
const patchnum_t* font, int startchar, int cm,
const patchnum_t* bgfont, boolean *on)
{
int i;
m->nl = 0;
m->nr = 0;
m->cl = -1; //jff 4/28/98 prepare for pre-increment
m->x = x;
m->y = y;
m->w = w;
m->h = h;
m->bg = bgfont;
m->on = on;
for (i=0;i<HU_MAXMESSAGES;i++)
{
HUlib_initTextLine
(
&m->l[i],
x,
y + (hud_list_bgon? i+1 : i)*HU_REFRESHSPACING,
font,
startchar,
cm
);
}
}
//
// HUlib_addLineToMText()
//
// Adds a blank line to a hu_mtext_t widget
//
// Passed a hu_mtext_t
// Returns nothing
//
void HUlib_addLineToMText(hu_mtext_t* m)
{
// add a clear line
if (++m->cl == hud_msg_lines)
m->cl = 0;
HUlib_clearTextLine(&m->l[m->cl]);
if (m->nl<hud_msg_lines)
m->nl++;
// needs updating
m->l[m->cl].needsupdate = 4;
}
//
// HUlib_addMessageToMText()
//
// Adds a message line with prefix to a hu_mtext_t widget
//
// Passed a hu_mtext_t, the prefix string, and a message string
// Returns nothing
//
void HUlib_addMessageToMText(hu_mtext_t* m, const char* prefix, const char* msg)
{
HUlib_addLineToMText(m);
if (prefix)
while (*prefix)
HUlib_addCharToTextLine(&m->l[m->cl], *(prefix++));
while (*msg)
HUlib_addCharToTextLine(&m->l[m->cl], *(msg++));
}
//
// HUlib_drawMBg()
//
// Draws a background box which the message display review widget can
// display over
//
// Passed position, width, height, and the background patches
// Returns nothing
//
void HUlib_drawMBg
( int x,
int y,
int w,
int h,
const patchnum_t* bgp
)
{
int xs = bgp[0].width;
int ys = bgp[0].height;
int i,j;
// CPhipps - patch drawing updated
// top rows
V_DrawNumPatch(x, y, FG, bgp[0].lumpnum, CR_DEFAULT, VPT_STRETCH); // ul
for (j=x+xs;j<x+w-xs;j+=xs) // uc
V_DrawNumPatch(j, y, FG, bgp[1].lumpnum, CR_DEFAULT, VPT_STRETCH);
V_DrawNumPatch(j, y, FG, bgp[2].lumpnum, CR_DEFAULT, VPT_STRETCH); // ur
// middle rows
for (i=y+ys;i<y+h-ys;i+=ys)
{
V_DrawNumPatch(x, i, FG, bgp[3].lumpnum, CR_DEFAULT, VPT_STRETCH); // cl
for (j=x+xs;j<x+w-xs;j+=xs) // cc
V_DrawNumPatch(j, i, FG, bgp[4].lumpnum, CR_DEFAULT, VPT_STRETCH);
V_DrawNumPatch(j, i, FG, bgp[5].lumpnum, CR_DEFAULT, VPT_STRETCH); // cr
}
// bottom row
V_DrawNumPatch(x, i, FG, bgp[6].lumpnum, CR_DEFAULT, VPT_STRETCH); // ll
for (j=x+xs;j<x+w-xs;j+=xs) // lc
V_DrawNumPatch(j, i, FG, bgp[7].lumpnum, CR_DEFAULT, VPT_STRETCH);
V_DrawNumPatch(j, i, FG, bgp[8].lumpnum, CR_DEFAULT, VPT_STRETCH); // lr
}
//
// HUlib_drawMText()
//
// Displays a hu_mtext_t widget
//
// Passed a hu_mtext_t
// Returns nothing
//
void HUlib_drawMText(hu_mtext_t* m)
{
int i, idx, y;
hu_textline_t *l;
if (!*m->on)
return; // if not on, don't draw
// draw everything
if (hud_list_bgon)
HUlib_drawMBg(m->x,m->y,m->w,m->h,m->bg);
y = m->y + HU_REFRESHSPACING;
for (i=0 ; i<m->nl ; i++)
{
idx = m->cl - i;
if (idx < 0)
idx += m->nl; // handle queue of lines
l = &m->l[idx];
if (hud_list_bgon)
{
l->x = m->x + 4;
l->y = m->y + (i+1)*HU_REFRESHSPACING;
}
else
{
l->x = m->x;
l->y = m->y + i*HU_REFRESHSPACING;
}
// need a decision made here on whether to skip the draw
HUlib_drawTextLine(l, false); // no cursor, please
}
}
//
// HUlib_eraseMBg()
//
// Erases background behind hu_mtext_t widget, when the screen is not fullsize
//
// Passed a hu_mtext_t
// Returns nothing
//
static void HUlib_eraseMBg(hu_mtext_t* m)
{
int lh;
int y;
int yoffset;
// Only erases when NOT in automap and the screen is reduced,
// and the text must either need updating or refreshing
// (because of a recent change back from the automap)
if (!(automapmode & am_active) && viewwindowx)
{
lh = SHORT(m->l[0].f[0].height) + 1;
for (y=m->y,yoffset=y*SCREENWIDTH ; y<m->y+lh*(hud_msg_lines+2) ; y++,yoffset+=SCREENWIDTH)
{
if (y < viewwindowy || y >= viewwindowy + viewheight)
R_VideoErase(yoffset, SCREENWIDTH); // erase entire line
else
{
// erase left border
R_VideoErase(yoffset, viewwindowx);
// erase right border
R_VideoErase(yoffset + viewwindowx + viewwidth, viewwindowx);
}
}
}
}
//
// HUlib_eraseMText()
//
// Erases a hu_mtext_t widget, when the screen is not fullsize
//
// Passed a hu_mtext_t
// Returns nothing
//
void HUlib_eraseMText(hu_mtext_t* m)
{
int i;
if (hud_list_bgon)
HUlib_eraseMBg(m);
for (i=0 ; i< m->nl ; i++)
{
m->l[i].needsupdate = 4;
HUlib_eraseTextLine(&m->l[i]);
}
}
////////////////////////////////////////////////////////
//
// Interactive text entry widget
//
////////////////////////////////////////////////////////
//
// HUlib_initIText()
//
// Initialize a hu_itext_t widget. Set the position, font,
// start char of the font, color range, and whether enabled.
//
// Passed a hu_itext_t, and the values used to initialize
// Returns nothing
//
void HUlib_initIText
( hu_itext_t* it,
int x,
int y,
const patchnum_t* font,
int startchar,
int cm, //jff 2/16/98 add color range parameter
boolean* on )
{
it->lm = 0; // default left margin is start of text
it->on = on;
it->laston = true;
HUlib_initTextLine(&it->l, x, y, font, startchar, cm);
}
// The following deletion routines adhere to the left margin restriction
//
// HUlib_delCharFromIText()
//
// Deletes a character at the end of the text line in a hu_itext_t widget
//
// Passed the hu_itext_t
// Returns nothing
//
void HUlib_delCharFromIText(hu_itext_t* it)
{
if (it->l.len != it->lm)
HUlib_delCharFromTextLine(&it->l);
}
//
// HUlib_eraseLineFromIText()
//
// Deletes all characters from a hu_itext_t widget
//
// Passed the hu_itext_t
// Returns nothing
//
void HUlib_eraseLineFromIText(hu_itext_t* it)
{
while (it->lm != it->l.len)
HUlib_delCharFromTextLine(&it->l);
}
//
// HUlib_resetIText()
//
// Deletes all characters from a hu_itext_t widget
// Resets left margin as well
//
// Passed the hu_itext_t
// Returns nothing
//
void HUlib_resetIText(hu_itext_t* it)
{
it->lm = 0;
HUlib_clearTextLine(&it->l);
}
//
// HUlib_addPrefixToIText()
//
// Adds a prefix string passed to a hu_itext_t widget
// Sets left margin to length of string added
//
// Passed the hu_itext_t and the prefix string
// Returns nothing
//
void HUlib_addPrefixToIText
( hu_itext_t* it,
char* str )
{
while (*str)
HUlib_addCharToTextLine(&it->l, *(str++));
it->lm = it->l.len;
}
//
// HUlib_keyInIText()
//
// Wrapper function for handling general keyed input.
//
// Passed the hu_itext_t and the char input
// Returns true if it ate the key
//
boolean HUlib_keyInIText
( hu_itext_t* it,
unsigned char ch )
{
if (ch >= ' ' && ch <= '_')
HUlib_addCharToTextLine(&it->l, (char) ch);
else if (ch == key_backspace) // phares
HUlib_delCharFromIText(it);
else if (ch != key_enter) // phares
return false; // did not eat key
return true; // ate the key
}
//
// HUlib_drawIText()
//
// Displays a hu_itext_t widget
//
// Passed the hu_itext_t
// Returns nothing
//
void HUlib_drawIText(hu_itext_t* it)
{
hu_textline_t *l = &it->l;
if (!*it->on)
return;
HUlib_drawTextLine(l, true); // draw the line w/ cursor
}
//
// HUlib_eraseIText()
//
// Erases a hu_itext_t widget when the screen is not fullsize
//
// Passed the hu_itext_t
// Returns nothing
//
void HUlib_eraseIText(hu_itext_t* it)
{
if (it->laston && !*it->on)
it->l.needsupdate = 4;
HUlib_eraseTextLine(&it->l);
it->laston = *it->on;
}

264
apps/plugins/doom/hu_lib.h Normal file
View file

@ -0,0 +1,264 @@
/* Emacs style mode select -*- C++ -*-
*-----------------------------------------------------------------------------
*
*
* PrBoom a Doom port merged with LxDoom and LSDLDoom
* based on BOOM, a modified and improved DOOM engine
* Copyright (C) 1999 by
* id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
* Copyright (C) 1999-2000 by
* Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* DESCRIPTION: none
*
*-----------------------------------------------------------------------------*/
#ifndef __HULIB__
#define __HULIB__
// We are referring to patches.
#include "r_defs.h"
#include "v_video.h" //jff 2/16/52 include color range defs
/* background and foreground screen numbers
* different from other modules. */
#define BG 1
#define FG 0
/* font stuff
* #define HU_CHARERASE KEYD_BACKSPACE / not used / phares
*/
#define HU_MAXLINES 4
#define HU_MAXLINELENGTH 80
#define HU_REFRESHSPACING 8 /*jff 2/26/98 space lines in text refresh widget*/
/*jff 2/26/98 maximum number of messages allowed in refresh list */
#define HU_MAXMESSAGES 16
/*
* Typedefs of widgets
*/
/* Text Line widget
* (parent of Scrolling Text and Input Text widgets) */
typedef struct
{
// left-justified position of scrolling text window
int x;
int y;
const patchnum_t* f; // font
int sc; // start character
//const char *cr; //jff 2/16/52 output color range
// Proff - Made this an int again. Needed for OpenGL
int cm; //jff 2/16/52 output color range
// killough 1/23/98: Support multiple lines:
#define MAXLINES 25
int linelen;
char l[HU_MAXLINELENGTH*MAXLINES+1]; // line of text
int len; // current line length
// whether this line needs to be udpated
int needsupdate;
} hu_textline_t;
// Scrolling Text window widget
// (child of Text Line widget)
typedef struct
{
hu_textline_t l[HU_MAXLINES]; // text lines to draw
int h; // height in lines
int cl; // current line number
// pointer to boolean stating whether to update window
boolean* on;
boolean laston; // last value of *->on.
} hu_stext_t;
//jff 2/26/98 new widget to display last hud_msg_lines of messages
// Message refresh window widget
typedef struct
{
hu_textline_t l[HU_MAXMESSAGES]; // text lines to draw
int nl; // height in lines
int nr; // total height in rows
int cl; // current line number
int x,y,w,h; // window position and size
const patchnum_t *bg; // patches for background
// pointer to boolean stating whether to update window
boolean* on;
boolean laston; // last value of *->on.
} hu_mtext_t;
// Input Text Line widget
// (child of Text Line widget)
typedef struct
{
hu_textline_t l; // text line to input on
// left margin past which I am not to delete characters
int lm;
// pointer to boolean stating whether to update window
boolean* on;
boolean laston; // last value of *->on;
} hu_itext_t;
//
// Widget creation, access, and update routines
//
// initializes heads-up widget library
void HUlib_init(void);
//
// textline code
//
// clear a line of text
void HUlib_clearTextLine(hu_textline_t *t);
void HUlib_initTextLine
(
hu_textline_t *t,
int x,
int y,
const patchnum_t *f,
int sc,
int cm //jff 2/16/98 add color range parameter
);
// returns success
boolean HUlib_addCharToTextLine(hu_textline_t *t, char ch);
// returns success
boolean HUlib_delCharFromTextLine(hu_textline_t *t);
// draws tline
void HUlib_drawTextLine(hu_textline_t *l, boolean drawcursor);
// erases text line
void HUlib_eraseTextLine(hu_textline_t *l);
//
// Scrolling Text window widget routines
//
// initialize an stext widget
void HUlib_initSText
( hu_stext_t* s,
int x,
int y,
int h,
const patchnum_t* font,
int startchar,
int cm, //jff 2/16/98 add color range parameter
boolean* on );
// add a new line
void HUlib_addLineToSText(hu_stext_t* s);
// add a text message to an stext widget
void HUlib_addMessageToSText(hu_stext_t* s, const char* prefix, const char* msg);
// draws stext
void HUlib_drawSText(hu_stext_t* s);
// erases all stext lines
void HUlib_eraseSText(hu_stext_t* s);
//jff 2/26/98 message refresh widget
// initialize refresh text widget
void HUlib_initMText(hu_mtext_t *m, int x, int y, int w, int h, const patchnum_t* font,
int startchar, int cm, const patchnum_t* bgfont, boolean *on);
//jff 2/26/98 message refresh widget
// add a text line to refresh text widget
void HUlib_addLineToMText( hu_mtext_t* m );
//jff 2/26/98 message refresh widget
// add a text message to refresh text widget
void HUlib_addMessageToMText(hu_mtext_t* m, const char* prefix, const char* msg);
//jff 2/26/98 new routine to display a background on which
// the list of last hud_msg_lines are displayed
void HUlib_drawMBg
( int x,
int y,
int w,
int h,
const patchnum_t* bgp
);
//jff 2/26/98 message refresh widget
// draws mtext
void HUlib_drawMText(hu_mtext_t* m);
//jff 4/28/98 erases behind message list
void HUlib_eraseMText(hu_mtext_t* m);
// Input Text Line widget routines
void HUlib_initIText
( hu_itext_t* it,
int x,
int y,
const patchnum_t* font,
int startchar,
int cm, //jff 2/16/98 add color range parameter
boolean* on );
// enforces left margin
void HUlib_delCharFromIText(hu_itext_t* it);
// enforces left margin
void HUlib_eraseLineFromIText(hu_itext_t* it);
// resets line and left margin
void HUlib_resetIText(hu_itext_t* it);
// left of left-margin
void HUlib_addPrefixToIText
( hu_itext_t* it,
char* str );
// whether eaten
boolean HUlib_keyInIText
( hu_itext_t* it,
unsigned char ch );
void HUlib_drawIText(hu_itext_t* it);
// erases all itext lines
void HUlib_eraseIText(hu_itext_t* it);
#endif

1753
apps/plugins/doom/hu_stuff.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,92 @@
/* Emacs style mode select -*- C++ -*-
*-----------------------------------------------------------------------------
*
*
* PrBoom a Doom port merged with LxDoom and LSDLDoom
* based on BOOM, a modified and improved DOOM engine
* Copyright (C) 1999 by
* id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
* Copyright (C) 1999-2000 by
* Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* DESCRIPTION: Head up display
*
*-----------------------------------------------------------------------------*/
#ifndef __HU_STUFF_H__
#define __HU_STUFF_H__
#include "d_event.h"
/*
* Globally visible constants.
*/
#define HU_FONTSTART '!' /* the first font characters */
#define HU_FONTEND (0x7f) /*jff 2/16/98 '_' the last font characters */
/* Calculate # of glyphs in font. */
#define HU_FONTSIZE (HU_FONTEND - HU_FONTSTART + 1)
#define HU_BROADCAST 5
/*#define HU_MSGREFRESH KEYD_ENTER phares */
#define HU_MSGX 0
#define HU_MSGY 0
#define HU_MSGWIDTH 64 /* in characters */
#define HU_MSGHEIGHT 1 /* in lines */
#define HU_MSGTIMEOUT (4*TICRATE)
/*
* Heads up text
*/
void HU_Init(void);
void HU_Start(void);
boolean HU_Responder(event_t* ev);
void HU_Ticker(void);
void HU_Drawer(void);
char HU_dequeueChatChar(void);
void HU_Erase(void);
/* killough 5/2/98: moved from m_misc.c: */
/* jff 2/16/98 hud supported automap colors added */
extern int hudcolor_titl; /* color range of automap level title */
extern int hudcolor_xyco; /* color range of new coords on automap */
/* jff 2/16/98 hud text colors, controls added */
extern int hudcolor_mesg; /* color range of scrolling messages */
extern int hudcolor_chat; /* color range of chat lines */
/* jff 2/26/98 hud message list color and background enable */
extern int hudcolor_list; /* color of list of past messages */
extern int hud_list_bgon; /* solid window background for list of messages */
extern int hud_msg_lines; /* number of message lines in window up to 16 */
extern int hud_distributed; /* whether hud is all in lower left or distributed */
/* jff 2/23/98 hud is currently displayed */
extern int hud_displayed; /* hud is displayed */
/* jff 2/18/98 hud/status control */
extern int hud_active; /* hud mode 0=off, 1=small, 2=full */
extern int hud_nosecrets; /* status does not list secrets/items/kills */
extern char* mapnames[];
extern char* mapnames2[];
extern char* mapnamesp[];
extern char* mapnamest[];
#endif

607
apps/plugins/doom/i_sound.c Normal file
View file

@ -0,0 +1,607 @@
/* Emacs style mode select -*- C++ -*-
*-----------------------------------------------------------------------------
*
*
* PrBoom a Doom port merged with LxDoom and LSDLDoom
* based on BOOM, a modified and improved DOOM engine
* Copyright (C) 1999 by
* id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
* Copyright (C) 1999-2000 by
* Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* DESCRIPTION:
* System interface for sound.
*
*-----------------------------------------------------------------------------
*/
#include "z_zone.h"
#include "i_system.h"
#include "i_sound.h"
#include "m_argv.h"
#include "m_misc.h"
#include "w_wad.h"
#include "m_swap.h"
#include "d_main.h"
#include "doomdef.h"
#include "rockmacros.h"
// The number of internal mixing channels,
// the samples calculated for each mixing step,
// the size of the 16bit, 2 hardware channel (stereo)
// mixing buffer, and the samplerate of the raw data.
// Needed for calling the actual sound output.
#define SAMPLECOUNT 512
#define NUM_CHANNELS 16
// It is 2 for 16bit, and 2 for two channels.
#define BUFMUL 4
#define MIXBUFFERSIZE (SAMPLECOUNT*BUFMUL)
#define SAMPLERATE 11025 // 44100 22050 11025
#define SAMPLESIZE 2 // 16bit
// The global mixing buffer.
// Basically, samples from all active internal channels
// are modifed and added, and stored in the buffer
// that is submitted to the audio device.
signed short mixbuffer[MIXBUFFERSIZE];
typedef struct {
// SFX id of the playing sound effect.
// Used to catch duplicates (like chainsaw).
int id;
// The channel step amount...
unsigned int step;
// ... and a 0.16 bit remainder of last step.
unsigned int stepremainder;
unsigned int samplerate;
// The channel data pointers, start and end.
const unsigned char* data;
const unsigned char* enddata;
// Time/gametic that the channel started playing,
// used to determine oldest, which automatically
// has lowest priority.
// In case number of active sounds exceeds
// available channels.
int starttime;
// Hardware left and right channel volume lookup.
int *leftvol_lookup;
int *rightvol_lookup;
} channel_info_t;
channel_info_t channelinfo[NUM_CHANNELS];
int *vol_lookup; // Volume lookups.
int steptable[256]; // Pitch to stepping lookup. (Not setup properly right now)
//
// This function loads the sound data from the WAD lump for single sound.
// It is used to cache all the sounddata at startup.
//
void* getsfx( const char* sfxname )
{
unsigned char* sfx;
unsigned char* paddedsfx;
int size;
char name[20];
int sfxlump;
// Get the sound data from the WAD, allocate lump
// in zone memory.
snprintf(name, sizeof(name), "ds%s", sfxname);
// Now, there is a severe problem with the sound handling, in it is not
// (yet/anymore) gamemode aware. That means, sounds from DOOM II will be
// requested even with DOOM shareware.
// The sound list is wired into sounds.c, which sets the external variable.
// I do not do runtime patches to that variable. Instead, we will use a
// default sound for replacement.
if ( W_CheckNumForName(name) == -1 )
sfxlump = W_GetNumForName("dspistol");
else
sfxlump = W_GetNumForName(name);
size = W_LumpLength( sfxlump );
sfx = (unsigned char*)W_CacheLumpNum( sfxlump);
paddedsfx = (unsigned char*)malloc( size ); // Allocate from memory.
memcpy(paddedsfx, sfx, size ); // Now copy and pad.
W_UnlockLumpNum(sfxlump); // Remove the cached lump.
return (void *) (paddedsfx); // Return allocated data.
}
/* cph
* stopchan
* Stops a sound
*/
static void stopchan(int i)
{
channelinfo[i].data=NULL;
}
//
// This function adds a sound to the
// list of currently active sounds,
// which is maintained as a given number
// (eight, usually) of internal channels.
// Returns a handle.
//
int addsfx( int sfxid, int channel)
{
stopchan(channel);
// We will handle the new SFX.
// Set pointer to raw data.
{
int lump = S_sfx[sfxid].lumpnum;
size_t len = W_LumpLength(lump);
/* Find padded length */
len -= 8;
channelinfo[channel].data = S_sfx[sfxid].data;
/* Set pointer to end of raw data. */
channelinfo[channel].enddata = channelinfo[channel].data + len - 1;
channelinfo[channel].samplerate = (channelinfo[channel].data[3]<<8)+channelinfo[channel].data[2];
channelinfo[channel].data += 8; /* Skip header */
}
channelinfo[channel].stepremainder = 0;
// Should be gametic, I presume.
channelinfo[channel].starttime = gametic;
// Preserve sound SFX id,
// e.g. for avoiding duplicates of chainsaw.
channelinfo[channel].id = sfxid;
return channel;
}
static void updateSoundParams(int handle, int volume, int seperation, int pitch)
{
int rightvol;
int leftvol;
int slot = handle;
int step = steptable[pitch];
#ifdef RANGECHECK
if (handle>=NUM_CHANNELS)
I_Error("I_UpdateSoundParams: handle out of range");
#endif
// Set stepping
// MWM 2000-12-24: Calculates proportion of channel samplerate
// to global samplerate for mixing purposes.
// Patched to shift left *then* divide, to minimize roundoff errors
// as well as to use SAMPLERATE as defined above, not to assume 11025 Hz
if (pitched_sounds)
channelinfo[slot].step = step + (((channelinfo[slot].samplerate<<16)/SAMPLERATE)-65536);
else
channelinfo[slot].step = ((channelinfo[slot].samplerate<<16)/SAMPLERATE);
// Separation, that is, orientation/stereo.
// range is: 1 - 256
seperation += 1;
// Per left/right channel.
// x^2 seperation,
// adjust volume properly.
leftvol = volume - ((volume*seperation*seperation) >> 16);
seperation = seperation - 257;
rightvol= volume - ((volume*seperation*seperation) >> 16);
// Sanity check, clamp volume.
if (rightvol < 0 || rightvol > 127)
I_Error("rightvol out of bounds");
if (leftvol < 0 || leftvol > 127)
I_Error("leftvol out of bounds");
// Get the proper lookup table piece
// for this volume level???
channelinfo[slot].leftvol_lookup = &vol_lookup[leftvol*256];
channelinfo[slot].rightvol_lookup = &vol_lookup[rightvol*256];
}
void I_UpdateSoundParams(int handle, int volume, int seperation, int pitch)
{
updateSoundParams(handle, volume, seperation, pitch);
}
//
// SFX API
// Note: this was called by S_Init.
// However, whatever they did in the
// old DPMS based DOS version, this
// were simply dummies in the Linux
// version.
// See soundserver initdata().
//
void I_SetChannels()
{
// Init internal lookups (raw data, mixing buffer, channels).
// This function sets up internal lookups used during
// the mixing process.
int i;
int j;
int* steptablemid = steptable + 128;
// Okay, reset internal mixing channels to zero.
for (i=0; i<NUM_CHANNELS; i++)
memset(&channelinfo[i],0,sizeof(channel_info_t));
// This table provides step widths for pitch parameters.
for (i=-128 ; i<128 ; i++)
steptablemid[i]=2;
// steptablemid[i] = (int)(pow(1.2, ((double)i/(64.0*SAMPLERATE/11025)))*65536.0);
// Generates volume lookup tables
// which also turn the unsigned samples
// into signed samples.
for (i=0 ; i<128 ; i++)
for (j=0 ; j<256 ; j++)
vol_lookup[i*256+j] = 3*(i*(j-128)*256)/191;
}
void I_SetSfxVolume(int volume)
{
// Identical to DOS.
// Basically, this should propagate
// the menu/config file setting
// to the state variable used in
// the mixing.
snd_SfxVolume = volume;
}
// MUSIC API - dummy. Some code from DOS version.
void I_SetMusicVolume(int volume)
{
// Internal state variable.
snd_MusicVolume = volume;
// Now set volume on output device.
// Whatever( snd_MusciVolume );
}
//
// Retrieve the raw data lump index
// for a given SFX name.
//
int I_GetSfxLumpNum(sfxinfo_t* sfx)
{
char namebuf[9];
snprintf(namebuf, sizeof(namebuf), "ds%s", sfx->name);
return W_GetNumForName(namebuf);
}
//
// Starting a sound means adding it
// to the current list of active sounds
// in the internal channels.
// As the SFX info struct contains
// e.g. a pointer to the raw data,
// it is ignored.
// As our sound handling does not handle
// priority, it is ignored.
// Pitching (that is, increased speed of playback)
// is set, but currently not used by mixing.
//
int I_StartSound(int id, int channel, int vol, int sep, int pitch, int priority)
{
(void)priority;
int handle;
// Returns a handle (not used).
handle = addsfx(id,channel);
#ifdef RANGECHECK
if (handle>=NUM_CHANNELS)
I_Error("I_StartSound: handle out of range");
#endif
updateSoundParams(handle, vol, sep, pitch);
return handle;
}
void I_StopSound (int handle)
{
#ifdef RANGECHECK
if (handle>=NUM_CHANNELS)
I_Error("I_StopSound: handle out of range");
#endif
stopchan(handle);
}
int I_SoundIsPlaying(int handle)
{
#ifdef RANGECHECK
if (handle>=NUM_CHANNELS)
I_Error("I_SoundIsPlaying: handle out of range");
#endif
return channelinfo[handle].data != NULL;
}
//
// This function loops all active (internal) sound
// channels, retrieves a given number of samples
// from the raw sound data, modifies it according
// to the current (internal) channel parameters,
// mixes the per channel samples into the given
// mixing buffer, and clamping it to the allowed
// range.
//
// This function currently supports only 16bit.
//
bool swap=0;
bool lastswap=1;
// Pointers in global mixbuffer, left, right, end.
signed short* leftout;
signed short* rightout;
signed short* leftend;
void I_UpdateSound( void )
{
// Mix current sound data.
// Data, from raw sound, for right and left.
register unsigned char sample;
register int dl;
register int dr;
// Step in mixbuffer, left and right, thus two.
int step;
// Mixing channel index.
int chan;
if(lastswap==swap)
return;
lastswap=swap;
// Left and right channel
// are in global mixbuffer, alternating.
leftout = (swap ? mixbuffer : mixbuffer + SAMPLECOUNT*2);
rightout = (swap ? mixbuffer : mixbuffer + SAMPLECOUNT*2)+1;
step = 2;
// Determine end, for left channel only
// (right channel is implicit).
leftend = (swap ? mixbuffer : mixbuffer + SAMPLECOUNT*2) + SAMPLECOUNT*step;
// Mix sounds into the mixing buffer.
// Loop over step*SAMPLECOUNT,
// that is 512 values for two channels.
while (leftout != leftend)
{
// Reset left/right value.
dl = 0;
dr = 0;
// Love thy L2 chache - made this a loop.
// Now more channels could be set at compile time
// as well. Thus loop those channels.
for ( chan = 0; chan < NUM_CHANNELS; chan++ )
{
// Check channel, if active.
if (channelinfo[chan].data)
{
// Get the raw data from the channel.
sample = (((unsigned int)channelinfo[chan].data[0] * (0x10000 - channelinfo[chan].stepremainder))
+ ((unsigned int)channelinfo[chan].data[1] * (channelinfo[chan].stepremainder))) >> 16;
// Add left and right part
// for this channel (sound)
// to the current data.
// Adjust volume accordingly.
dl += channelinfo[chan].leftvol_lookup[sample];
dr += channelinfo[chan].rightvol_lookup[sample];
// Increment index ???
channelinfo[chan].stepremainder += channelinfo[chan].step;
// MSB is next sample???
channelinfo[chan].data += channelinfo[chan].stepremainder >> 16;
// Limit to LSB???
channelinfo[chan].stepremainder &= 0xffff;
// Check whether we are done.
if (channelinfo[chan].data >= channelinfo[chan].enddata)
stopchan(chan);
}
}
// Clamp to range. Left hardware channel.
// Has been char instead of short.
// if (dl > 127) *leftout = 127;
// else if (dl < -128) *leftout = -128;
// else *leftout = dl;
if (dl > 0x7fff)
*leftout = 0x7fff;
else if (dl < -0x8000)
*leftout = -0x8000;
else
*leftout = (signed short)dl;
// Same for right hardware channel.
if (dr > 0x7fff)
*rightout = 0x7fff;
else if (dr < -0x8000)
*rightout = -0x8000;
else
*rightout = (signed short)dr;
// Increment current pointers in mixbuffer.
leftout += step;
rightout += step;
}
}
//
// This would be used to write out the mixbuffer
// during each game loop update.
// Updates sound buffer and audio device at runtime.
// It is called during Timer interrupt with SNDINTR.
// Mixing now done synchronous, and
// only output be done asynchronous?
//
void get_more(unsigned char** start, size_t* size)
{
// This code works fine, the only problem is that doom runs slower then the sound
// updates (sometimes). This code forces the update if the sound hasn't been
// remixed.
if(lastswap!=swap)
I_UpdateSound(); // Force sound update (We don't want stutters)
*start = (unsigned char*)((swap ? mixbuffer : mixbuffer + SAMPLECOUNT*2));
*size = SAMPLECOUNT*2*sizeof(short);
swap=!swap;
}
void I_SubmitSound(void)
{
if (nosfxparm)
return;
#if !defined(SIMULATOR)
rb->pcm_play_data(&get_more, NULL, 0);
#endif
}
void I_ShutdownSound(void)
{
#if !defined(SIMULATOR)
rb->pcm_play_stop();
rb->pcm_set_frequency(44100); // 44100
#endif
}
void I_InitSound()
{
int i;
// Initialize external data (all sounds) at start, keep static.
printf( "I_InitSound: ");
#if !defined(SIMULATOR)
rb->pcm_play_stop();
rb->pcm_set_frequency(SAMPLERATE);
#endif
vol_lookup=malloc(128*256*sizeof(int));
for (i=1 ; i<NUMSFX ; i++)
{
if (!S_sfx[i].link) // Alias? Example is the chaingun sound linked to pistol.
S_sfx[i].data = getsfx( S_sfx[i].name); // Load data from WAD file.
else
S_sfx[i].data = S_sfx[i].link->data; // Previously loaded already?
}
printf( " pre-cached all sound data\n");
// Now initialize mixbuffer with zero.
for ( i = 0; i< MIXBUFFERSIZE; i++ )
mixbuffer[i] = 0;
// Finished initialization.
printf("I_InitSound: sound module ready\n");
}
//
// MUSIC API.
// Still no music done.
// Remains. Dummies.
//
void I_InitMusic(void) {
}
void I_ShutdownMusic(void) {
}
static int looping=0;
static int musicdies=-1;
void I_PlaySong(int handle, int looping)
{
// UNUSED.
handle = looping = 0;
musicdies = gametic + TICRATE*30;
}
void I_PauseSong (int handle)
{
// UNUSED.
handle = 0;
}
void I_ResumeSong (int handle)
{
// UNUSED.
handle = 0;
}
void I_StopSong(int handle)
{
// UNUSED.
handle = 0;
looping = 0;
musicdies = 0;
}
void I_UnRegisterSong(int handle)
{
// UNUSED.
handle = 0;
}
int I_RegisterSong(const void *data)
{
// UNUSED.
data = NULL;
return 1;
}
// Is the song playing?
int I_QrySongPlaying(int handle)
{
// UNUSED.
handle = 0;
return looping || musicdies > gametic;
}
// Interrupt handler.
void I_HandleSoundTimer( int ignore )
{
(void)ignore;
}
// Get the interrupt. Set duration in millisecs.
int I_SoundSetTimer( int duration_of_tick )
{
(void)duration_of_tick;
// Error is -1.
return 0;
}
// Remove the interrupt. Set duration to zero.
void I_SoundDelTimer(void)
{
}

126
apps/plugins/doom/i_sound.h Normal file
View file

@ -0,0 +1,126 @@
// Emacs style mode select -*- C++ -*-
//-----------------------------------------------------------------------------
//
// $Id$
//
// Copyright (C) 1993-1996 by id Software, Inc.
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
//
// DESCRIPTION:
// System interface, sound.
//
//-----------------------------------------------------------------------------
#ifndef __I_SOUND__
#define __I_SOUND__
#include "doomdef.h"
// UNIX hack, to be removed.
#ifdef SNDSERV
extern FILE* sndserver;
extern char* sndserver_filename;
#endif
#include "doomstat.h"
#include "sounds.h"
// Init at program start...
void I_InitSound(void);
// ... update sound buffer and audio device at runtime...
void I_UpdateSound(void);
void I_SubmitSound(void);
// ... shut down and relase at program termination.
void I_ShutdownSound(void);
//
// SFX I/O
//
// Initialize channels?
void I_SetChannels(void);
// Get raw data lump index for sound descriptor.
int I_GetSfxLumpNum (sfxinfo_t* sfxinfo );
// Starts a sound in a particular sound channel.
int
I_StartSound
( int id,
int vol,
int cnum,
int sep,
int pitch,
int priority );
// Stops a sound channel.
void I_StopSound(int handle);
// Called by S_*() functions
// to see if a channel is still playing.
// Returns 0 if no longer playing, 1 if playing.
int I_SoundIsPlaying(int handle);
// Updates the volume, separation,
// and pitch of a sound channel.
void
I_UpdateSoundParams
( int handle,
int vol,
int sep,
int pitch );
//
// MUSIC I/O
//
void I_InitMusic(void);
void I_ShutdownMusic(void);
// Volume.
void I_SetMusicVolume(int volume);
// PAUSE game handling.
void I_PauseSong(int handle);
void I_ResumeSong(int handle);
// Registers a song handle to song data.
int I_RegisterSong(const void *data);
// Called by anything that wishes to start music.
// plays a song, and when the song is done,
// starts playing it again in an endless loop.
// Horrible thing to do, considering.
void
I_PlaySong
( int handle,
int looping );
// Stops a song over 3 seconds.
void I_StopSong(int handle);
// See above (register), then think backwards
void I_UnRegisterSong(int handle);
#endif
//-----------------------------------------------------------------------------
//
// $Log$
// Revision 1.1 2006/03/28 15:44:01 dave
// Patch #2969 - Doom! Currently only working on the H300.
//
//
//-----------------------------------------------------------------------------

View file

@ -0,0 +1,134 @@
// Emacs style mode select -*- C++ -*-
//-----------------------------------------------------------------------------
//
// $Id$
//
// Copyright (C) 1993-1996 by id Software, Inc.
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// $Log$
// Revision 1.1 2006/03/28 15:44:01 dave
// Patch #2969 - Doom! Currently only working on the H300.
//
//
// DESCRIPTION:
//
//-----------------------------------------------------------------------------
#include "doomdef.h"
#include "m_misc.h"
#include "i_video.h"
#include "i_sound.h"
#include "d_net.h"
#include "g_game.h"
#include "z_zone.h"
#ifdef __GNUG__
#pragma implementation "i_system.h"
#endif
#include "i_system.h"
#include "rockmacros.h"
//
// I_GetTime
// returns time in 1/35th second tics
//
#if (CONFIG_CPU != PP5020)
volatile unsigned int doomtimer=0;
void doomtime(void)
{
doomtimer++;
}
#endif
int I_GetTime (void)
{
#ifdef SIMULATOR
#if HZ==100
return ((7*(*rb->current_tick))/20);
#else
#error FIX - I assumed HZ was 100
#endif
#else
#if (CONFIG_CPU == PP5020)
return (USEC_TIMER * 7)/200000;
#else
return doomtimer;
#endif
#endif
}
//
// I_Init
//
// I was looking into this and comparing the speed versus Prboom
// Turns out they are running the game much slower then I thought the game was
// played. This explains why run was unusable other then through straight stretches
// The game is much slower now (in terms of game speed).
void I_Init (void)
{
#if (CONFIG_CPU != PP5020) && !defined(SIMULATOR)
rb->timer_register(1, NULL, CPU_FREQ/TICRATE, 1, doomtime);
#endif
I_InitSound();
}
//
// I_Quit
//
extern boolean doomexit;
void I_Quit (void)
{
I_ShutdownSound();
I_ShutdownMusic();
I_ShutdownGraphics();
#if (CONFIG_CPU != PP5020) && !defined(SIMULATOR)
rb->timer_unregister();
#endif
doomexit=1;
}
void I_WaitVBL(int count)
{
rb->sleep(count);
}
//
// I_Error
//
extern boolean demorecording;
void I_Error (char *error, ...)
{
char p_buf[50];
va_list ap;
va_start(ap, error);
vsnprintf(p_buf,sizeof(p_buf), error, ap);
va_end(ap);
printf("%s",p_buf);
// Shutdown. Here might be other errors.
if (demorecording)
G_CheckDemoStatus();
/*
I_ShutdownGraphics();
*/
I_Quit();
rb->sleep(HZ*2);
}

View file

@ -0,0 +1,65 @@
// Emacs style mode select -*- C++ -*-
//-----------------------------------------------------------------------------
//
// $Id$
//
// Copyright (C) 1993-1996 by id Software, Inc.
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// DESCRIPTION:
// System specific interface stuff.
//
//-----------------------------------------------------------------------------
#ifndef __I_SYSTEM__
#define __I_SYSTEM__
#include "d_ticcmd.h"
#include "d_event.h"
#ifdef __GNUG__
#pragma interface
#endif
// Called by DoomMain.
void I_Init (void);
// Called by D_DoomLoop,
// returns current time in tics.
int I_GetTime (void);
//
// Called by D_DoomLoop,
// called before processing any tics in a frame
// (just after displaying a frame).
// Time consuming syncronous operations
// are performed here (joystick reading).
// Can call D_PostEvent.
//
void I_StartFrame (void);
//
// Called by D_DoomLoop,
// called before processing each tic in a frame.
// Quick syncronous operations are performed here.
// Can call D_PostEvent.
void I_StartTic (void);
// Called by M_Responder when quit is selected.
// Clean exit, displays sell blurb.
void I_Quit (void);
void I_Error (char *error, ...);
#endif

454
apps/plugins/doom/i_video.c Normal file
View file

@ -0,0 +1,454 @@
/* Emacs style mode select -*- C++ -*-
*-----------------------------------------------------------------------------
*
* $Id$
*
* Copyright (C) 1993-1996 by id Software, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* $Log$
* Revision 1.1 2006/03/28 15:44:01 dave
* Patch #2969 - Doom! Currently only working on the H300.
*
*
* DESCRIPTION:
* DOOM graphics and buttons. H300 Port by Karl Kurbjun
* IPOD port by Dave Chapman and Paul Louden
* Additional work by Thom Johansen
*
*-----------------------------------------------------------------------------
*/
#include "doomstat.h"
#include "i_system.h"
#include "v_video.h"
#include "m_argv.h"
#include "d_main.h"
#include "doomdef.h"
#include "rockmacros.h"
static fb_data palette[256] IBSS_ATTR;
static fb_data *paldata=NULL;
#if !defined(CPU_COLDFIRE) || defined(SIMULATOR)
/*
This code is credit to the IDOOM port. It is not used for the H300, but
serves as a good reference point for other targets.
*/
static fb_data * xtable = 0;
static fb_data * ytable1 = 0;
static fb_data * ytable2 = 0;
#define FLOOR4(a) \
(( a >> 2) << 2)
static int video_w, video_h;
static void genscalexytable(void)
{
// shall we use uint8_t intead of ints?
int y = video_h-1;
int x = video_w-1;
int i = 1 + (x>y?x:y);
xtable = malloc(sizeof(int)*video_w );
ytable1 = malloc(sizeof(int)*video_h );
ytable2 = malloc(sizeof(int)*video_h );
while(i--)
{
if(y>=0)
{
ytable1[y] = ((y*SCREENHEIGHT) / video_h) * SCREENWIDTH;
ytable2[y] = y*video_w;
y--;
}
if(x>=0)
{
xtable[x] = (x*SCREENWIDTH) / video_w;
x--;
}
}
}
#endif
//
// I_ShutdownGraphics (NOT USED)
//
void I_ShutdownGraphics(void)
{
}
//
// I_StartFrame (NOT USED)
//
void I_StartFrame (void)
{
}
//
// I_GetEvent (NOT USED)
//
void I_GetEvent(void)
{
}
//
// I_StartTic
//
#if CONFIG_KEYPAD == IPOD_4G_PAD
//#define DOOMBUTTON_SCROLLWHEEL
#define DOOMBUTTON_UP BUTTON_MENU
#define DOOMBUTTON_WEAPON BUTTON_SELECT
#define DOOMBUTTON_LEFT BUTTON_LEFT
#define DOOMBUTTON_RIGHT BUTTON_RIGHT
#define DOOMBUTTON_SHOOT BUTTON_PLAY
#define DOOMBUTTON_ENTER BUTTON_SELECT
#define DOOMBUTTON_OPEN BUTTON_MENU
#else
#define DOOMBUTTON_UP BUTTON_UP
#define DOOMBUTTON_DOWN BUTTON_DOWN
#define DOOMBUTTON_LEFT BUTTON_LEFT
#define DOOMBUTTON_RIGHT BUTTON_RIGHT
#define DOOMBUTTON_SHOOT BUTTON_REC
#define DOOMBUTTON_OPEN BUTTON_MODE
#define DOOMBUTTON_ESC BUTTON_OFF
#define DOOMBUTTON_ENTER BUTTON_SELECT
#define DOOMBUTTON_WEAPON BUTTON_ON
#endif
int getkey(event_t * event)
{
// Same button handling as rockboy
static unsigned int oldbuttonstate = 0, newbuttonstate=0;
static int released, pressed;
#if CONFIG_KEYPAD == IRIVER_H300_PAD
static unsigned int holdbutton=0;
static int hswitch=0;
if (rb->button_hold()&~holdbutton)
{
if(hswitch==0)
{
event->type = ev_keydown;
hswitch=1;
}
else
{
event->type = ev_keyup;
hswitch=0;
}
event->data1=KEY_RSHIFT;
D_PostEvent(event);
}
holdbutton=rb->button_hold();
#endif
newbuttonstate = rb->button_status();
released = ~newbuttonstate & oldbuttonstate;
pressed = newbuttonstate & ~oldbuttonstate;
oldbuttonstate = newbuttonstate;
if(released)
{
event->type = ev_keyup;
if(released & DOOMBUTTON_LEFT)
{
event->data1=KEY_LEFTARROW;
D_PostEvent(event);
}
if(released & DOOMBUTTON_RIGHT)
{
event->data1=KEY_RIGHTARROW;
D_PostEvent(event);
}
#ifdef DOOMBUTTON_DOWN
if(released & DOOMBUTTON_DOWN)
{
event->data1=KEY_DOWNARROW;
D_PostEvent(event);
}
#endif
if(released & DOOMBUTTON_UP)
{
event->data1=KEY_UPARROW;
D_PostEvent(event);
}
if(released & DOOMBUTTON_SHOOT)
{
event->data1=KEY_RCTRL;
D_PostEvent(event);
}
if(released & DOOMBUTTON_OPEN)
{
event->data1=' ';
D_PostEvent(event);
}
#ifdef DOOMBUTTON_ESC
if(released & DOOMBUTTON_ESC)
{
event->data1=KEY_ESCAPE;
D_PostEvent(event);
}
#endif
#ifdef DOOMBUTTON_ENTER
if(released & DOOMBUTTON_ENTER)
{
event->data1=KEY_ENTER;
D_PostEvent(event);
}
#endif
#ifdef DOOMBUTTON_WEAPON
if(released & DOOMBUTTON_WEAPON)
{
event->data1 ='w';
D_PostEvent(event);
}
#endif
}
if(pressed)
{
event->type = ev_keydown;
if(pressed & DOOMBUTTON_LEFT)
{
event->data1=KEY_LEFTARROW;
D_PostEvent(event);
}
if(pressed & DOOMBUTTON_RIGHT)
{
event->data1=KEY_RIGHTARROW;
D_PostEvent(event);
}
#ifdef DOOMBUTTON_DOWN
if(pressed & DOOMBUTTON_DOWN)
{
event->data1=KEY_DOWNARROW;
D_PostEvent(event);
}
#endif
if(pressed & DOOMBUTTON_UP)
{
event->data1=KEY_UPARROW;
D_PostEvent(event);
}
if(pressed & DOOMBUTTON_SHOOT)
{
event->data1=KEY_RCTRL;
D_PostEvent(event);
}
if(pressed & DOOMBUTTON_OPEN)
{
event->data1=' ';
D_PostEvent(event);
}
#ifdef DOOMBUTTON_ESC
if(pressed & DOOMBUTTON_ESC)
{
event->data1=KEY_ESCAPE;
D_PostEvent(event);
}
#endif
#ifdef DOOMBUTTON_ENTER
if(pressed & DOOMBUTTON_ENTER)
{
event->data1=KEY_ENTER;
D_PostEvent(event);
}
#endif
#ifdef DOOMBUTTON_WEAPON
if(pressed & DOOMBUTTON_WEAPON)
{
event->data1='w';
D_PostEvent(event);
}
#endif
}
if(pressed || released)
return 1;
else
return 0;
}
event_t event;
void I_StartTic (void)
{
getkey(&event);
}
///////////////////////////////////////////////////////////
// Palette stuff.
//
static void I_UploadNewPalette(int pal)
{
// This is used to replace the current 256 colour cmap with a new one
// Used by 256 colour PseudoColor modes
static int cachedgamma;
static size_t num_pals;
if ((paldata == NULL) || (cachedgamma != usegamma)) {
int lump = W_GetNumForName("PLAYPAL");
const byte *pall = W_CacheLumpNum(lump);
register const byte *const gtable = gammatable[cachedgamma = usegamma];
register int i;
num_pals = W_LumpLength(lump) / (3*256);
num_pals *= 256;
if (!paldata) {
// First call - allocate and prepare colour array
paldata = malloc(sizeof(*paldata)*num_pals);
}
// set the colormap entries
for (i=0 ; (size_t)i<num_pals ; i++) {
int r = gtable[pall[0]];
int g = gtable[pall[1]];
int b = gtable[pall[2]];
pall+=3;
paldata[i] = LCD_RGBPACK(r,g,b);
}
W_UnlockLumpNum(lump);
num_pals/=256;
}
#ifdef RANGECHECK
if ((size_t)pal >= num_pals)
I_Error("I_UploadNewPalette: Palette number out of range (%d>=%d)",
pal, num_pals);
#endif
memcpy(palette,paldata+256*pal,256*sizeof(fb_data));
}
//
// I_UpdateNoBlit
//
void I_UpdateNoBlit (void)
{
}
//
// I_FinishUpdate
//
void I_FinishUpdate (void)
{
#if defined(CPU_COLDFIRE) && !defined(SIMULATOR)
/*
Faster screen update than the lookuptables -> I'm wasting 7 pixels of width
though. This code also doesn't use the framebuffer so rockbox's drawing
functions will not work on top of the doom drawing.
*/
// Start the write
*(volatile unsigned short *) 0xf0000000 = 0x21; // register
*(volatile unsigned short *) 0xf0000002 = 0; // value
*(volatile unsigned short *) 0xf0000000 = 0x22; // GRAM
unsigned char *screenptr=screens[0];
int wcnt=0, hcnt=0;
*(volatile unsigned short *) 0xf0000002 = 0;
*(volatile unsigned short *) 0xf0000002 = 0;
*(volatile unsigned short *) 0xf0000002 = 0;
while(hcnt<LCD_HEIGHT)
{
while(wcnt<LCD_WIDTH-7)
{
if((wcnt&0x01))
screenptr++; // Skip every so many pixels in Doom buffer
*(volatile unsigned short *)0xf0000002 = palette[*screenptr];
screenptr++;
wcnt++;
}
screenptr++;
// move on past those 7 pixels
*(volatile unsigned short *) 0xf0000002 = 0;
*(volatile unsigned short *) 0xf0000002 = 0;
*(volatile unsigned short *) 0xf0000002 = 0;
*(volatile unsigned short *) 0xf0000002 = 0;
*(volatile unsigned short *) 0xf0000002 = 0;
*(volatile unsigned short *) 0xf0000002 = 0;
*(volatile unsigned short *) 0xf0000002 = 0;
wcnt=0;
hcnt++;
if((hcnt&0x07)==0x07)
screenptr+=SCREENWIDTH; // Skip every 7th line
}
#else
// The IDOOM code for screen updates
unsigned char paletteIndex;
int x, y;
for (y = 0; y < video_h; y++)
{
for (x = 0; x < video_w; x++)
{
#if LCD_HEIGHT >= SCREENHEIGHT
paletteIndex = screens[0][((y*SCREENHEIGHT) / video_h)
* SCREENWIDTH + x];
rb->lcd_framebuffer[y * video_w + x] = palette[paletteIndex];
#else
paletteIndex = screens[0][ytable1[y] +xtable[x]];
rb->lcd_framebuffer[x + ytable2[y]] = palette[paletteIndex];
#endif
}
}
rb->lcd_update();
#endif
}
//
// I_ReadScreen
//
void I_ReadScreen (byte* scr)
{
memcpy (scr, screens[0], SCREENWIDTH*SCREENHEIGHT);
}
//
// I_SetPalette
//
void I_SetPalette (int pal)
{
I_UploadNewPalette(pal);
}
//
// I_InitGraphics
//
void I_InitGraphics(void)
{
static int firsttime=1;
if (!firsttime)
return;
firsttime = 0;
printf("Starting Graphics engine\n");
/* Note: The other screens are initialized later */
screens[0] = malloc (SCREENWIDTH * SCREENHEIGHT * sizeof(unsigned char));
#if defined(CPU_COLDFIRE) && !defined(SIMULATOR)
coldfire_set_macsr(EMAC_FRACTIONAL | EMAC_SATURATE);
#else
video_h = LCD_HEIGHT;
video_w = FLOOR4(LCD_WIDTH); // From IDOOM, the width has to be a multiple of 4
genscalexytable();
#endif
}

View file

@ -0,0 +1,56 @@
// Emacs style mode select -*- C++ -*-
//-----------------------------------------------------------------------------
//
// $Id$
//
// Copyright (C) 1993-1996 by id Software, Inc.
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// DESCRIPTION:
// System specific interface stuff.
//
//-----------------------------------------------------------------------------
#ifndef __I_VIDEO__
#define __I_VIDEO__
#include "doomtype.h"
#include "rockmacros.h"
#ifdef __GNUG__
#pragma interface
#endif
// Called by D_DoomMain,
// determines the hardware configuration
// and sets up the video mode
void I_InitGraphics (void);
void I_ShutdownGraphics(void);
// Takes full 8 bit values.
void I_SetPalette (int pal);
void I_UpdateNoBlit (void);
void I_FinishUpdate (void) ICODE_ATTR;
// Wait for vertical retrace or pause a bit.
void I_WaitVBL(int count);
void I_ReadScreen (byte* scr);
#endif

5185
apps/plugins/doom/info.c Normal file

File diff suppressed because it is too large Load diff

1454
apps/plugins/doom/info.h Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,53 @@
/* Emacs style mode select -*- C++ -*-
*-----------------------------------------------------------------------------
*
*
* PrBoom a Doom port merged with LxDoom and LSDLDoom
* based on BOOM, a modified and improved DOOM engine
* Copyright (C) 1999 by
* id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
* Copyright (C) 1999-2000 by
* Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* DESCRIPTION:
* Some argument handling.
*
*-----------------------------------------------------------------------------*/
#include "rockmacros.h"
#include "m_argv.h"
int myargc;
char** myargv;
//
// M_CheckParm
// Checks for the given parameter
// in the program's command line arguments.
// Returns the argument number (1 to argc-1)
// or 0 if not present
//
int M_CheckParm(const char *check)
{
signed int i = myargc;
while (--i>0)
if (!strcasecmp(check, myargv[i]))
return i;
return 0;
}

View file

@ -0,0 +1,45 @@
/* Emacs style mode select -*- C++ -*-
*-----------------------------------------------------------------------------
*
*
* PrBoom a Doom port merged with LxDoom and LSDLDoom
* based on BOOM, a modified and improved DOOM engine
* Copyright (C) 1999 by
* id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
* Copyright (C) 1999-2000 by
* Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* DESCRIPTION:
* Argument handling.
*
*-----------------------------------------------------------------------------*/
#ifndef __M_ARGV__
#define __M_ARGV__
//
// MISC
//
extern int myargc;
extern char** myargv;
/* Returns the position of the given parameter in the arg list (0 if not found). */
int M_CheckParm(const char *check);
#endif

View file

@ -0,0 +1,58 @@
/* Emacs style mode select -*- C++ -*-
*-----------------------------------------------------------------------------
*
*
* PrBoom a Doom port merged with LxDoom and LSDLDoom
* based on BOOM, a modified and improved DOOM engine
* Copyright (C) 1999 by
* id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
* Copyright (C) 1999-2000 by
* Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* DESCRIPTION:
* Main loop menu stuff.
* Random number LUT.
* Default Config File.
* PCX Screenshots.
*
*-----------------------------------------------------------------------------*/
#ifdef __GNUG__
#pragma implementation "m_bbox.h"
#endif
#include "m_bbox.h"
#include "rockmacros.h"
void M_ClearBox (fixed_t *box)
{
box[BOXTOP] = box[BOXRIGHT] = MININT;
box[BOXBOTTOM] = box[BOXLEFT] = MAXINT;
}
void M_AddToBox(fixed_t* box,fixed_t x,fixed_t y)
{
if (x<box[BOXLEFT])
box[BOXLEFT] = x;
else if (x>box[BOXRIGHT])
box[BOXRIGHT] = x;
if (y<box[BOXBOTTOM])
box[BOXBOTTOM] = y;
else if (y>box[BOXTOP])
box[BOXTOP] = y;
}

View file

@ -0,0 +1,54 @@
/* Emacs style mode select -*- C++ -*-
*-----------------------------------------------------------------------------
*
*
* PrBoom a Doom port merged with LxDoom and LSDLDoom
* based on BOOM, a modified and improved DOOM engine
* Copyright (C) 1999 by
* id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
* Copyright (C) 1999-2000 by
* Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* DESCRIPTION:
* Simple bounding box datatype and functions.
*
*-----------------------------------------------------------------------------*/
#ifndef __M_BBOX__
#define __M_BBOX__
#include <limits.h>
#include "m_fixed.h"
/* Bounding box coordinate storage. */
enum
{
BOXTOP,
BOXBOTTOM,
BOXLEFT,
BOXRIGHT
}; /* bbox coordinates */
/* Bounding box functions. */
void M_ClearBox(fixed_t* box);
void M_AddToBox(fixed_t* box,fixed_t x,fixed_t y);
#endif

104
apps/plugins/doom/m_cheat.c Normal file
View file

@ -0,0 +1,104 @@
// Emacs style mode select -*- C++ -*-
//-----------------------------------------------------------------------------
//
// $Id$
//
// Copyright (C) 1993-1996 by id Software, Inc.
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// $Log$
// Revision 1.1 2006/03/28 15:44:01 dave
// Patch #2969 - Doom! Currently only working on the H300.
//
//
// DESCRIPTION:
// Cheat sequence checking.
//
//-----------------------------------------------------------------------------
#include "m_cheat.h"
//
// CHEAT SEQUENCE PACKAGE
//
static int firsttime = 1;
static unsigned char cheat_xlate_table[20];
//
// Called in st_stuff module, which handles the input.
// Returns a 1 if the cheat was successful, 0 if failed.
//
int
cht_CheckCheat
( cheatseq_t* cht,
char key )
{
int i;
int rc = 0;
if (firsttime)
{
firsttime = 0;
for (i=0;i<256;i++)
cheat_xlate_table[i] = SCRAMBLE(i);
}
if (!cht->p)
cht->p = cht->sequence; // initialize if first time
if (*cht->p == 0)
*(cht->p++) = key;
else if
(cheat_xlate_table[(unsigned char)key] == *cht->p)
cht->p++;
else
cht->p = cht->sequence;
if (*cht->p == 1)
cht->p++;
else if (*cht->p == 0xff) // end of sequence character
{
cht->p = cht->sequence;
rc = 1;
}
return rc;
}
void
cht_GetParam
( cheatseq_t* cht,
char* buffer )
{
unsigned char *p, c;
p = cht->sequence;
while (*(p++) != 1)
;
do
{
c = *p;
*(buffer++) = c;
*(p++) = 0;
}
while (c && *p!=0xff );
if (*p==0xff)
*buffer = 0;
}

View file

@ -0,0 +1,63 @@
// Emacs style mode select -*- C++ -*-
//-----------------------------------------------------------------------------
//
// $Id$
//
// Copyright (C) 1993-1996 by id Software, Inc.
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// DESCRIPTION:
// Cheat code checking.
//
//-----------------------------------------------------------------------------
#ifndef __M_CHEAT__
#define __M_CHEAT__
//
// CHEAT SEQUENCE PACKAGE
//
#define SCRAMBLE(a) \
((((a)&1)<<7) + (((a)&2)<<5) + ((a)&4) + (((a)&8)<<1) \
+ (((a)&16)>>1) + ((a)&32) + (((a)&64)>>5) + (((a)&128)>>7))
typedef struct
{
unsigned char* sequence;
unsigned char* p;
}
cheatseq_t;
int
cht_CheckCheat
( cheatseq_t* cht,
char key );
void
cht_GetParam
( cheatseq_t* cht,
char* buffer );
#endif
//-----------------------------------------------------------------------------
//
// $Log$
// Revision 1.1 2006/03/28 15:44:01 dave
// Patch #2969 - Doom! Currently only working on the H300.
//
//
//-----------------------------------------------------------------------------

View file

@ -0,0 +1,94 @@
// Emacs style mode select -*- C++ -*-
//-----------------------------------------------------------------------------
//
// $Id$
//
// Copyright (C) 1993-1996 by id Software, Inc.
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// DESCRIPTION:
// Fixed point arithemtics, implementation.
//
//-----------------------------------------------------------------------------
#ifndef __M_FIXED__
#define __M_FIXED__
#ifdef __GNUG__
#pragma interface
#endif
#include "doomtype.h"
#include "rockmacros.h"
//
// Fixed point, 32bit as 16.16.
//
#define FRACBITS 16
#define FRACUNIT (1<<FRACBITS)
#define D_abs(x) ({fixed_t _t = (x), _s = _t >> (8*sizeof _t-1); (_t^_s)-_s;})
typedef int fixed_t;
inline static int FixedMul( int a, int b )
{
#if defined(CPU_COLDFIRE) && !defined(SIMULATOR)
// Code contributed by Thom Johansen
register int result;
asm volatile (
"mac.l %[x],%[y],%%acc0 \n" /* multiply */
"move.l %[y],%%d2 \n"
"mulu.l %[x],%%d2 \n" /* get lower half, avoid emac stall */
"movclr.l %%acc0,%[result] \n" /* get higher half */
"moveq.l #15,%%d1 \n"
"asl.l %%d1,%[result] \n" /* hi <<= 15, plus one free */
"moveq.l #16,%%d1 \n"
"lsr.l %%d1,%%d2 \n" /* (unsigned)lo >>= 16 */
"or.l %%d2 ,%[result] \n" /* combine result */
: /* outputs */
[result]"=&d"(result)
: /* inputs */
[x] "d" (a),
[y] "d" (b)
: /* clobbers */
"d1", "d2"
);
return result;
#else
return (fixed_t)((long long) a*b >> FRACBITS);
#endif
}
inline static fixed_t FixedDiv( fixed_t a, fixed_t b )
{
return (D_abs(a)>>14) >= D_abs(b) ? ((a^b)>>31) ^ MAXINT :
(fixed_t)(((long long) a << FRACBITS) / b);
}
/* CPhipps -
* FixedMod - returns a % b, guaranteeing 0<=a<b
* (notice that the C standard for % does not guarantee this)
*/
inline static fixed_t FixedMod(fixed_t a, fixed_t b)
{
if (b & (b-1)) {
fixed_t r = a % b;
return ((r<0) ? r+b : r);
} else
return (a & (b-1));
}
#endif

1848
apps/plugins/doom/m_menu.c Normal file

File diff suppressed because it is too large Load diff

121
apps/plugins/doom/m_menu.h Normal file
View file

@ -0,0 +1,121 @@
// Emacs style mode select -*- C++ -*-
//-----------------------------------------------------------------------------
//
// $Id$
//
// Copyright (C) 1993-1996 by id Software, Inc.
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// DESCRIPTION:
// Menu widget stuff, episode selection and such.
//
//-----------------------------------------------------------------------------
#ifndef __M_MENU__
#define __M_MENU__
#include "d_event.h"
//
// MENUS
//
// Called by main loop,
// saves config file and calls I_Quit when user exits.
// Even when the menu is not displayed,
// this can resize the view and change game parameters.
// Does all the real work of the menu interaction.
boolean M_Responder (event_t *ev);
// Called by main loop,
// only used for menu (skull cursor) animation.
void M_Ticker (void);
// Called by main loop,
// draws the menus directly into the screen buffer.
void M_Drawer (void);
// Called by D_DoomMain,
// loads the config file.
void M_Init (void);
// Called by intro code to force menu up upon a keypress,
// does nothing if menu is already up.
void M_StartControlPanel (void);
/****************************
*
* The setup_group enum is used to show which 'groups' keys fall into so
* that you can bind a key differently in each 'group'.
*/
typedef enum {
m_null, // Has no meaning; not applicable
m_scrn, // A key can not be assigned to more than one action
m_map, // in the same group. A key can be assigned to one
m_menu, // action in one group, and another action in another.
} setup_group;
/****************************
*
* phares 4/17/98:
* State definition for each item.
* This is the definition of the structure for each setup item. Not all
* fields are used by all items.
*
* A setup screen is defined by an array of these items specific to
* that screen.
*
* killough 11/98:
*
* Restructured to allow simpler table entries,
* and to Xref with defaults[] array in m_misc.c.
* Moved from m_menu.c to m_menu.h so that m_misc.c can use it.
*/
typedef struct setup_menu_s
{
const char *m_text; /* text to display */
int m_flags; /* phares 4/17/98: flag bits S_* (defined above) */
setup_group m_group; /* Group */
short m_x; /* screen x position (left is 0) */
short m_y; /* screen y position (top is 0) */
union /* killough 11/98: The first field is a union of several types */
{
const void *var; /* generic variable */
int *m_key; /* key value, or 0 if not shown */
const char *name; /* name */
struct default_s *def; /* default[] table entry */
struct setup_menu_s *menu; /* next or prev menu */
} var;
int *m_mouse; /* mouse button value, or 0 if not shown */
int *m_joy; /* joystick button value, or 0 if not shown */
void (*action)(void); /* killough 10/98: function to call after changing */
} setup_menu_t;
#endif
//-----------------------------------------------------------------------------
//
// $Log$
// Revision 1.1 2006/03/28 15:44:01 dave
// Patch #2969 - Doom! Currently only working on the H300.
//
//
//-----------------------------------------------------------------------------

1077
apps/plugins/doom/m_misc.c Normal file

File diff suppressed because it is too large Load diff

112
apps/plugins/doom/m_misc.h Normal file
View file

@ -0,0 +1,112 @@
/* Emacs style mode select -*- C++ -*-
*-----------------------------------------------------------------------------
*
*
* PrBoom a Doom port merged with LxDoom and LSDLDoom
* based on BOOM, a modified and improved DOOM engine
* Copyright (C) 1999 by
* id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
* Copyright (C) 1999-2000 by
* Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* DESCRIPTION:
* External non-system-specific stuff, like storing config settings,
* simple file handling, and saving screnshots.
*
*-----------------------------------------------------------------------------*/
#ifndef __M_MISC__
#define __M_MISC__
#include "doomtype.h"
//
// MISC
//
boolean M_WriteFile (char const* name,void* source,int length);
int M_ReadFile (char const* name,byte** buffer);
void M_ScreenShot (void);
void M_DoScreenShot (const char*); // cph
void M_LoadDefaults (void);
void M_SaveDefaults (void);
int M_DrawText (int x,int y,boolean direct,char* string);
struct default_s *M_LookupDefault(const char *name); /* killough 11/98 */
// phares 4/21/98:
// Moved from m_misc.c so m_menu.c could see it.
// CPhipps - struct to hold a value in a config file
// Cannot be a union, as it must be initialised
typedef struct default_s
{
const char* name;
/* cph -
* The location struct holds the pointer to the variable holding the
* setting. For int's we do nothing special.
* For strings, the string is actually stored on our heap with Z_Strdup()
* BUT we don't want the rest of the program to be able to modify them,
* so we declare it const. It's not really const though, and m_misc.c and
* m_menu.c cast it back when they need to change it. Possibly this is
* more trouble than it's worth.
*/
struct {
int* pi;
const char** ppsz;
} location;
struct {
int i;
const char* psz;
} defaultvalue; // CPhipps - default value
// Limits (for an int)
int minvalue; // jff 3/3/98 minimum allowed value
int maxvalue; // jff 3/3/98 maximum allowed value
enum {
def_none, // Dummy entry
def_str, // A string
def_int, // Integer
def_hex, // Integer (write in hex)
def_bool = def_int, // Boolean
def_key = def_hex, // Key code (byte)
def_mouseb = def_int,// Mouse button
def_colour = def_hex // Colour (256 colour palette entry)
} type; // CPhipps - type of entry
int setupscreen; // phares 4/19/98: setup screen where this appears
int *current; /* cph - MBF-like pointer to current value */
// cph - removed the help strings from the config file
// const char* help; // jff 3/3/98 description of parameter
// CPhipps - remove unused "lousy hack" code
struct setup_menu_s *setup_menu; /* Xref to setup menu item, if any */
} default_t;
#define IS_STRING(dv) ((dv).type == def_str)
// CPhipps - What is the max. key code that X will send us?
#define MAX_KEY 65536
#define MAX_MOUSEB 2
#define UL (-123456789) /* magic number for no min or max for parameter */
#endif

View file

@ -0,0 +1,136 @@
/* Emacs style mode select -*- C++ -*-
*-----------------------------------------------------------------------------
*
*
* PrBoom a Doom port merged with LxDoom and LSDLDoom
* based on BOOM, a modified and improved DOOM engine
* Copyright (C) 1999 by
* id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
* Copyright (C) 1999-2000 by
* Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* DESCRIPTION:
* Random number LUT.
*
* 1/19/98 killough: Rewrote random number generator for better randomness,
* while at the same time maintaining demo sync and backward compatibility.
*
* 2/16/98 killough: Made each RNG local to each control-equivalent block,
* to reduce the chances of demo sync problems.
*
*-----------------------------------------------------------------------------*/
#include "doomstat.h"
#include "m_random.h"
//
// M_Random
// Returns a 0-255 number
//
static const unsigned char rndtable[256] = { // 1/19/98 killough -- made const
0, 8, 109, 220, 222, 241, 149, 107, 75, 248, 254, 140, 16, 66 ,
74, 21, 211, 47, 80, 242, 154, 27, 205, 128, 161, 89, 77, 36 ,
95, 110, 85, 48, 212, 140, 211, 249, 22, 79, 200, 50, 28, 188 ,
52, 140, 202, 120, 68, 145, 62, 70, 184, 190, 91, 197, 152, 224 ,
149, 104, 25, 178, 252, 182, 202, 182, 141, 197, 4, 81, 181, 242 ,
145, 42, 39, 227, 156, 198, 225, 193, 219, 93, 122, 175, 249, 0 ,
175, 143, 70, 239, 46, 246, 163, 53, 163, 109, 168, 135, 2, 235 ,
25, 92, 20, 145, 138, 77, 69, 166, 78, 176, 173, 212, 166, 113 ,
94, 161, 41, 50, 239, 49, 111, 164, 70, 60, 2, 37, 171, 75 ,
136, 156, 11, 56, 42, 146, 138, 229, 73, 146, 77, 61, 98, 196 ,
135, 106, 63, 197, 195, 86, 96, 203, 113, 101, 170, 247, 181, 113 ,
80, 250, 108, 7, 255, 237, 129, 226, 79, 107, 112, 166, 103, 241 ,
24, 223, 239, 120, 198, 58, 60, 82, 128, 3, 184, 66, 143, 224 ,
145, 224, 81, 206, 163, 45, 63, 90, 168, 114, 59, 33, 159, 95 ,
28, 139, 123, 98, 125, 196, 15, 70, 194, 253, 54, 14, 109, 226 ,
71, 17, 161, 93, 186, 87, 244, 138, 20, 52, 123, 251, 26, 36 ,
17, 46, 52, 231, 232, 76, 31, 221, 84, 37, 216, 165, 212, 106 ,
197, 242, 98, 43, 39, 175, 254, 145, 190, 84, 118, 222, 187, 136 ,
120, 163, 236, 249
};
rng_t rng; // the random number state
unsigned long rngseed = 1993; // killough 3/26/98: The seed
int P_Random(pr_class_t pr_class)
{
// killough 2/16/98: We always update both sets of random number
// generators, to ensure repeatability if the demo_compatibility
// flag is changed while the program is running. Changing the
// demo_compatibility flag does not change the sequences generated,
// only which one is selected from.
//
// All of this RNG stuff is tricky as far as demo sync goes --
// it's like playing with explosives :) Lee
int compat = pr_class == pr_misc ?
(rng.prndindex = (rng.prndindex + 1) & 255) :
(rng. rndindex = (rng. rndindex + 1) & 255) ;
unsigned long boom;
// killough 3/31/98:
// If demo sync insurance is not requested, use
// much more unstable method by putting everything
// except pr_misc into pr_all_in_one
if (pr_class != pr_misc && !demo_insurance) // killough 3/31/98
pr_class = pr_all_in_one;
boom = rng.seed[pr_class];
// killough 3/26/98: add pr_class*2 to addend
rng.seed[pr_class] = boom * 1664525ul + 221297ul + pr_class*2;
if (demo_compatibility)
return rndtable[compat];
boom >>= 20;
/* killough 3/30/98: use gametic-levelstarttic to shuffle RNG
* killough 3/31/98: but only if demo insurance requested,
* since it's unnecessary for random shuffling otherwise
* killough 9/29/98: but use basetic now instead of levelstarttic
* cph - DEMOSYNC - this change makes MBF demos work,
* but does it break Boom ones?
*/
if (demo_insurance)
boom += (gametic-basetic)*7;
return boom & 255;
}
// Initialize all the seeds
//
// This initialization method is critical to maintaining demo sync.
// Each seed is initialized according to its class, so if new classes
// are added they must be added to end of pr_class_t list. killough
//
void M_ClearRandom (void)
{
int i;
unsigned long seed = rngseed*2+1; // add 3/26/98: add rngseed
for (i=0; i<NUMPRCLASS; i++) // go through each pr_class and set
rng.seed[i] = seed *= 69069ul; // each starting seed differently
rng.prndindex = rng.rndindex = 0; // clear two compatibility indices
}

View file

@ -0,0 +1,148 @@
/* Emacs style mode select -*- C++ -*-
*-----------------------------------------------------------------------------
*
*
* PrBoom a Doom port merged with LxDoom and LSDLDoom
* based on BOOM, a modified and improved DOOM engine
* Copyright (C) 1999 by
* id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
* Copyright (C) 1999-2000 by
* Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* DESCRIPTION:
* Functions to return random numbers.
*
*-----------------------------------------------------------------------------*/
#ifndef __M_RANDOM__
#define __M_RANDOM__
#include "doomtype.h"
// killough 1/19/98: rewritten to use to use a better random number generator
// in the new engine, although the old one is available for compatibility.
// killough 2/16/98:
//
// Make every random number generator local to each control-equivalent block.
// Critical for demo sync. Changing the order of this list breaks all previous
// versions' demos. The random number generators are made local to reduce the
// chances of sync problems. In Doom, if a single random number generator call
// was off, it would mess up all random number generators. This reduces the
// chances of it happening by making each RNG local to a control flow block.
//
// Notes to developers: if you want to reduce your demo sync hassles, follow
// this rule: for each call to P_Random you add, add a new class to the enum
// type below for each block of code which calls P_Random. If two calls to
// P_Random are not in "control-equivalent blocks", i.e. there are any cases
// where one is executed, and the other is not, put them in separate classes.
//
// Keep all current entries in this list the same, and in the order
// indicated by the #'s, because they're critical for preserving demo
// sync. Do not remove entries simply because they become unused later.
typedef enum {
pr_skullfly, // #1
pr_damage, // #2
pr_crush, // #3
pr_genlift, // #4
pr_killtics, // #5
pr_damagemobj, // #6
pr_painchance, // #7
pr_lights, // #8
pr_explode, // #9
pr_respawn, // #10
pr_lastlook, // #11
pr_spawnthing, // #12
pr_spawnpuff, // #13
pr_spawnblood, // #14
pr_missile, // #15
pr_shadow, // #16
pr_plats, // #17
pr_punch, // #18
pr_punchangle, // #19
pr_saw, // #20
pr_plasma, // #21
pr_gunshot, // #22
pr_misfire, // #23
pr_shotgun, // #24
pr_bfg, // #25
pr_slimehurt, // #26
pr_dmspawn, // #27
pr_missrange, // #28
pr_trywalk, // #29
pr_newchase, // #30
pr_newchasedir, // #31
pr_see, // #32
pr_facetarget, // #33
pr_posattack, // #34
pr_sposattack, // #35
pr_cposattack, // #36
pr_spidrefire, // #37
pr_troopattack, // #38
pr_sargattack, // #39
pr_headattack, // #40
pr_bruisattack, // #41
pr_tracer, // #42
pr_skelfist, // #43
pr_scream, // #44
pr_brainscream, // #45
pr_cposrefire, // #46
pr_brainexp, // #47
pr_spawnfly, // #48
pr_misc, // #49
pr_all_in_one, // #50
/* CPhipps - new entries from MBF, mostly unused for now */
pr_opendoor, // #51
pr_targetsearch, // #52
pr_friends, // #53
pr_threshold, // #54
pr_skiptarget, // #55
pr_enemystrafe, // #56
pr_avoidcrush, // #57
pr_stayonlift, // #58
pr_helpfriend, // #59
pr_dropoff, // #60
pr_randomjump, // #61
pr_defect, // #62 // Start new entries -- add new entries below
// End of new entries
NUMPRCLASS // MUST be last item in list
} pr_class_t;
// The random number generator's state.
typedef struct {
unsigned long seed[NUMPRCLASS]; // Each block's random seed
int rndindex, prndindex; // For compatibility support
} rng_t;
extern rng_t rng; // The rng's state
extern unsigned long rngseed; // The starting seed (not part of state)
// Returns a number from 0 to 255,
#define M_Random() P_Random(pr_misc)
// As M_Random, but used by the play simulation.
int P_Random(pr_class_t);
// Fix randoms for demos.
void M_ClearRandom(void);
#endif

104
apps/plugins/doom/m_swap.h Normal file
View file

@ -0,0 +1,104 @@
/* Emacs style mode select -*- C++ -*-
*-----------------------------------------------------------------------------
*
*
* PrBoom a Doom port merged with LxDoom and LSDLDoom
* based on BOOM, a modified and improved DOOM engine
* Copyright (C) 1999 by
* id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
* Copyright (C) 1999-2000 by
* Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* DESCRIPTION:
* Endianess handling, swapping 16bit and 32bit.
*
*-----------------------------------------------------------------------------*/
#ifndef __M_SWAP__
#define __M_SWAP__
#ifdef __GNUG__
#pragma interface
#endif
/* Endianess handling. */
/* cph - First the macros to do the actual byte swapping */
/* leban
* rather than continue the confusing tradition of redefining the
* stardard macro, we now present the doom_ntoh and doom_hton macros....
* might as well use the xdoom macros.
*/
#ifndef doom_swap_l
#define doom_swap_l(x) \
((long int)((((unsigned long int)(x) & 0x000000ffU) << 24) | \
(((unsigned long int)(x) & 0x0000ff00U) << 8) | \
(((unsigned long int)(x) & 0x00ff0000U) >> 8) | \
(((unsigned long int)(x) & 0xff000000U) >> 24)))
#endif
#ifndef doom_swap_s
#define doom_swap_s(x) \
((short int)((((unsigned short int)(x) & 0x00ff) << 8) | \
(((unsigned short int)(x) & 0xff00) >> 8)))
#endif
/* Macros are named doom_XtoYT, where
* X is thing to convert from, Y is thing to convert to, chosen from
* n for network, h for host (i.e our machine's), w for WAD (Doom data files)
* and T is the type, l or s for long or short
*
* CPhipps - all WADs and network packets will be little endian for now
* Use separate macros so network could be converted to big-endian later.
*/
#ifdef __BIG_ENDIAN__
#define doom_wtohl(x) doom_swap_l(x)
#define doom_htowl(x) doom_swap_l(x)
#define doom_wtohs(x) doom_swap_s(x)
#define doom_htows(x) doom_swap_s(x)
#define doom_ntohl(x) doom_swap_l(x)
#define doom_htonl(x) doom_swap_l(x)
#define doom_ntohs(x) doom_swap_s(x)
#define doom_htons(x) doom_swap_s(x)
#else
#define doom_wtohl(x) (long int)(x)
#define doom_htowl(x) (long int)(x)
#define doom_wtohs(x) (short int)(x)
#define doom_htows(x) (short int)(x)
#define doom_ntohl(x) (long int)(x)
#define doom_htonl(x) (long int)(x)
#define doom_ntohs(x) (short int)(x)
#define doom_htons(x) (short int)(x)
#endif
/* CPhipps - Boom's old LONG and SHORT endianness macros are for WAD stuff */
#define LONG(x) doom_wtohl(x)
#define SHORT(x) doom_htows(x)
#endif

View file

@ -0,0 +1,468 @@
/* Emacs style mode select -*- C++ -*-
*-----------------------------------------------------------------------------
*
*
* PrBoom a Doom port merged with LxDoom and LSDLDoom
* based on BOOM, a modified and improved DOOM engine
* Copyright (C) 1999 by
* id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
* Copyright (C) 1999-2000 by
* Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* DESCRIPTION:
* Ceiling aninmation (lowering, crushing, raising)
*
*-----------------------------------------------------------------------------*/
#include "doomstat.h"
#include "r_main.h"
#include "p_spec.h"
#include "p_tick.h"
#include "s_sound.h"
#include "sounds.h"
#include "z_zone.h"
#include "doomdef.h"
#define PU_LEVSPEC 51 // a special thinker in a level
#include "rockmacros.h"
// the list of ceilings moving currently, including crushers
ceilinglist_t *activeceilings;
/////////////////////////////////////////////////////////////////
//
// Ceiling action routine and linedef type handler
//
/////////////////////////////////////////////////////////////////
//
// T_MoveCeiling
//
// Action routine that moves ceilings. Called once per tick.
//
// Passed a ceiling_t structure that contains all the info about the move.
// see P_SPEC.H for fields. No return.
//
// jff 02/08/98 all cases with labels beginning with gen added to support
// generalized line type behaviors.
//
void T_MoveCeiling (ceiling_t* ceiling)
{
result_e res;
switch(ceiling->direction)
{
case 0:
// If ceiling in stasis, do nothing
break;
case 1:
// Ceiling is moving up
res = T_MovePlane
(
ceiling->sector,
ceiling->speed,
ceiling->topheight,
false,
1,
ceiling->direction
);
// if not a silent crusher, make moving sound
if (!(leveltime&7))
{
switch(ceiling->type)
{
case silentCrushAndRaise:
case genSilentCrusher:
break;
default:
S_StartSound((mobj_t *)&ceiling->sector->soundorg,sfx_stnmov);
break;
}
}
// handle reaching destination height
if (res == pastdest)
{
switch(ceiling->type)
{
// plain movers are just removed
case raiseToHighest:
case genCeiling:
P_RemoveActiveCeiling(ceiling);
break;
// movers with texture change, change the texture then get removed
case genCeilingChgT:
case genCeilingChg0:
ceiling->sector->special = ceiling->newspecial;
//jff 3/14/98 transfer old special field as well
ceiling->sector->oldspecial = ceiling->oldspecial;
case genCeilingChg:
ceiling->sector->ceilingpic = ceiling->texture;
P_RemoveActiveCeiling(ceiling);
break;
// crushers reverse direction at the top
case silentCrushAndRaise:
S_StartSound((mobj_t *)&ceiling->sector->soundorg,sfx_pstop);
case genSilentCrusher:
case genCrusher:
case fastCrushAndRaise:
case crushAndRaise:
ceiling->direction = -1;
break;
default:
break;
}
}
break;
case -1:
// Ceiling moving down
res = T_MovePlane
(
ceiling->sector,
ceiling->speed,
ceiling->bottomheight,
ceiling->crush,
1,
ceiling->direction
);
// if not silent crusher type make moving sound
if (!(leveltime&7))
{
switch(ceiling->type)
{
case silentCrushAndRaise:
case genSilentCrusher:
break;
default:
S_StartSound((mobj_t *)&ceiling->sector->soundorg,sfx_stnmov);
}
}
// handle reaching destination height
if (res == pastdest)
{
switch(ceiling->type)
{
// 02/09/98 jff change slow crushers' speed back to normal
// start back up
case genSilentCrusher:
case genCrusher:
if (ceiling->oldspeed<CEILSPEED*3)
ceiling->speed = ceiling->oldspeed;
ceiling->direction = 1; //jff 2/22/98 make it go back up!
break;
// make platform stop at bottom of all crusher strokes
// except generalized ones, reset speed, start back up
case silentCrushAndRaise:
S_StartSound((mobj_t *)&ceiling->sector->soundorg,sfx_pstop);
case crushAndRaise:
ceiling->speed = CEILSPEED;
case fastCrushAndRaise:
ceiling->direction = 1;
break;
// in the case of ceiling mover/changer, change the texture
// then remove the active ceiling
case genCeilingChgT:
case genCeilingChg0:
ceiling->sector->special = ceiling->newspecial;
//jff add to fix bug in special transfers from changes
ceiling->sector->oldspecial = ceiling->oldspecial;
case genCeilingChg:
ceiling->sector->ceilingpic = ceiling->texture;
P_RemoveActiveCeiling(ceiling);
break;
// all other case, just remove the active ceiling
case lowerAndCrush:
case lowerToFloor:
case lowerToLowest:
case lowerToMaxFloor:
case genCeiling:
P_RemoveActiveCeiling(ceiling);
break;
default:
break;
}
}
else // ( res != pastdest )
{
// handle the crusher encountering an obstacle
if (res == crushed)
{
switch(ceiling->type)
{
//jff 02/08/98 slow down slow crushers on obstacle
case genCrusher:
case genSilentCrusher:
if (ceiling->oldspeed < CEILSPEED*3)
ceiling->speed = CEILSPEED / 8;
break;
case silentCrushAndRaise:
case crushAndRaise:
case lowerAndCrush:
ceiling->speed = CEILSPEED / 8;
break;
default:
break;
}
}
}
break;
}
}
//
// EV_DoCeiling
//
// Move a ceiling up/down or start a crusher
//
// Passed the linedef activating the function and the type of function desired
// returns true if a thinker started
//
int EV_DoCeiling
( line_t* line,
ceiling_e type )
{
int secnum;
int rtn;
sector_t* sec;
ceiling_t* ceiling;
secnum = -1;
rtn = 0;
// Reactivate in-stasis ceilings...for certain types.
// This restarts a crusher after it has been stopped
switch(type)
{
case fastCrushAndRaise:
case silentCrushAndRaise:
case crushAndRaise:
//jff 4/5/98 return if activated
rtn = P_ActivateInStasisCeiling(line);
default:
break;
}
// affects all sectors with the same tag as the linedef
while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0)
{
sec = &sectors[secnum];
// if ceiling already moving, don't start a second function on it
if (P_SectorActive(ceiling_special,sec)) //jff 2/22/98
continue;
// create a new ceiling thinker
rtn = 1;
ceiling = Z_Malloc (sizeof(*ceiling), PU_LEVSPEC, 0);
P_AddThinker (&ceiling->thinker);
sec->ceilingdata = ceiling; //jff 2/22/98
ceiling->thinker.function = T_MoveCeiling;
ceiling->sector = sec;
ceiling->crush = false;
// setup ceiling structure according to type of function
switch(type)
{
case fastCrushAndRaise:
ceiling->crush = true;
ceiling->topheight = sec->ceilingheight;
ceiling->bottomheight = sec->floorheight + (8*FRACUNIT);
ceiling->direction = -1;
ceiling->speed = CEILSPEED * 2;
break;
case silentCrushAndRaise:
case crushAndRaise:
ceiling->crush = true;
ceiling->topheight = sec->ceilingheight;
case lowerAndCrush:
case lowerToFloor:
ceiling->bottomheight = sec->floorheight;
if (type != lowerToFloor)
ceiling->bottomheight += 8*FRACUNIT;
ceiling->direction = -1;
ceiling->speed = CEILSPEED;
break;
case raiseToHighest:
ceiling->topheight = P_FindHighestCeilingSurrounding(sec);
ceiling->direction = 1;
ceiling->speed = CEILSPEED;
break;
case lowerToLowest:
ceiling->bottomheight = P_FindLowestCeilingSurrounding(sec);
ceiling->direction = -1;
ceiling->speed = CEILSPEED;
break;
case lowerToMaxFloor:
ceiling->bottomheight = P_FindHighestFloorSurrounding(sec);
ceiling->direction = -1;
ceiling->speed = CEILSPEED;
break;
default:
break;
}
// add the ceiling to the active list
ceiling->tag = sec->tag;
ceiling->type = type;
P_AddActiveCeiling(ceiling);
}
return rtn;
}
//////////////////////////////////////////////////////////////////////
//
// Active ceiling list primitives
//
/////////////////////////////////////////////////////////////////////
// jff 2/22/98 - modified Lee's plat code to work for ceilings
//
// The following were all rewritten by Lee Killough
// to use the new structure which places no limits
// on active ceilings. It also avoids spending as much
// time searching for active ceilings. Previously a
// fixed-size array was used, with NULL indicating
// empty entries, while now a doubly-linked list
// is used.
//
// P_ActivateInStasisCeiling()
//
// Reactivates all stopped crushers with the right tag
//
// Passed the line reactivating the crusher
// Returns true if a ceiling reactivated
//
//jff 4/5/98 return if activated
int P_ActivateInStasisCeiling(line_t *line)
{
ceilinglist_t *cl;
int rtn=0;
for (cl=activeceilings; cl; cl=cl->next)
{
ceiling_t *ceiling = cl->ceiling;
if (ceiling->tag == line->tag && ceiling->direction == 0)
{
ceiling->direction = ceiling->olddirection;
ceiling->thinker.function = T_MoveCeiling;
//jff 4/5/98 return if activated
rtn=1;
}
}
return rtn;
}
//
// EV_CeilingCrushStop()
//
// Stops all active ceilings with the right tag
//
// Passed the linedef stopping the ceilings
// Returns true if a ceiling put in stasis
//
int EV_CeilingCrushStop(line_t* line)
{
int rtn=0;
ceilinglist_t *cl;
for (cl=activeceilings; cl; cl=cl->next)
{
ceiling_t *ceiling = cl->ceiling;
if (ceiling->direction != 0 && ceiling->tag == line->tag)
{
ceiling->olddirection = ceiling->direction;
ceiling->direction = 0;
ceiling->thinker.function = NULL;
rtn=1;
}
}
return rtn;
}
//
// P_AddActiveCeiling()
//
// Adds a ceiling to the head of the list of active ceilings
//
// Passed the ceiling motion structure
// Returns nothing
//
void P_AddActiveCeiling(ceiling_t* ceiling)
{
ceilinglist_t *list = malloc(sizeof *list);
list->ceiling = ceiling;
ceiling->list = list;
if ((list->next = activeceilings))
list->next->prev = &list->next;
list->prev = &activeceilings;
activeceilings = list;
}
//
// P_RemoveActiveCeiling()
//
// Removes a ceiling from the list of active ceilings
//
// Passed the ceiling motion structure
// Returns nothing
//
void P_RemoveActiveCeiling(ceiling_t* ceiling)
{
ceilinglist_t *list = ceiling->list;
ceiling->sector->ceilingdata = NULL; //jff 2/22/98
P_RemoveThinker(&ceiling->thinker);
if ((*list->prev = list->next))
list->next->prev = list->prev;
free(list);
}
//
// P_RemoveAllActiveCeilings()
//
// Removes all ceilings from the active ceiling list
//
// Passed nothing, returns nothing
//
void P_RemoveAllActiveCeilings(void)
{
while (activeceilings)
{
ceilinglist_t *next = activeceilings->next;
free(activeceilings);
activeceilings = next;
}
}

672
apps/plugins/doom/p_doors.c Normal file
View file

@ -0,0 +1,672 @@
/* Emacs style mode select -*- C++ -*-
*-----------------------------------------------------------------------------
*
*
* PrBoom a Doom port merged with LxDoom and LSDLDoom
* based on BOOM, a modified and improved DOOM engine
* Copyright (C) 1999 by
* id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
* Copyright (C) 1999-2000 by
* Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* DESCRIPTION:
* Door animation code (opening/closing)
*
*-----------------------------------------------------------------------------*/
#include "doomstat.h"
#include "p_spec.h"
#include "p_tick.h"
#include "s_sound.h"
#include "sounds.h"
#include "r_main.h"
#include "dstrings.h"
//#include "d_deh.h" // Ty 03/27/98 - externalized
#include "rockmacros.h"
///////////////////////////////////////////////////////////////
//
// Door action routines, called once per tick
//
///////////////////////////////////////////////////////////////
//
// T_VerticalDoor
//
// Passed a door structure containing all info about the door.
// See P_SPEC.H for fields.
// Returns nothing.
//
// jff 02/08/98 all cases with labels beginning with gen added to support
// generalized line type behaviors.
void T_VerticalDoor (vldoor_t* door)
{
result_e res;
// Is the door waiting, going up, or going down?
switch(door->direction)
{
case 0:
// Door is waiting
if (!--door->topcountdown) // downcount and check
{
switch(door->type)
{
case blazeRaise:
case genBlazeRaise:
door->direction = -1; // time to go back down
S_StartSound((mobj_t *)&door->sector->soundorg,sfx_bdcls);
break;
case normal:
case genRaise:
door->direction = -1; // time to go back down
S_StartSound((mobj_t *)&door->sector->soundorg,sfx_dorcls);
break;
case close30ThenOpen:
case genCdO:
door->direction = 1; // time to go back up
S_StartSound((mobj_t *)&door->sector->soundorg,sfx_doropn);
break;
case genBlazeCdO:
door->direction = 1; // time to go back up
S_StartSound((mobj_t *)&door->sector->soundorg,sfx_bdopn);
break;
default:
break;
}
}
break;
case 2:
// Special case for sector type door that opens in 5 mins
if (!--door->topcountdown) // 5 minutes up?
{
switch(door->type)
{
case raiseIn5Mins:
door->direction = 1; // time to raise then
door->type = normal; // door acts just like normal 1 DR door now
S_StartSound((mobj_t *)&door->sector->soundorg,sfx_doropn);
break;
default:
break;
}
}
break;
case -1:
// Door is moving down
res = T_MovePlane
(
door->sector,
door->speed,
door->sector->floorheight,
false,
1,
door->direction
);
/* killough 10/98: implement gradual lighting effects */
if (door->lighttag && door->topheight - door->sector->floorheight)
EV_LightTurnOnPartway(door->line,
FixedDiv(door->sector->ceilingheight -
door->sector->floorheight,
door->topheight -
door->sector->floorheight));
// handle door reaching bottom
if (res == pastdest)
{
switch(door->type)
{
// regular open and close doors are all done, remove them
case blazeRaise:
case blazeClose:
case genBlazeRaise:
case genBlazeClose:
door->sector->ceilingdata = NULL; //jff 2/22/98
P_RemoveThinker (&door->thinker); // unlink and free
// killough 4/15/98: remove double-closing sound of blazing doors
if (comp[comp_blazing])
S_StartSound((mobj_t *)&door->sector->soundorg,sfx_bdcls);
break;
case normal:
case p_close:
case genRaise:
case genClose:
door->sector->ceilingdata = NULL; //jff 2/22/98
P_RemoveThinker (&door->thinker); // unlink and free
break;
// close then open doors start waiting
case close30ThenOpen:
door->direction = 0;
door->topcountdown = TICRATE*30;
break;
case genCdO:
case genBlazeCdO:
door->direction = 0;
door->topcountdown = door->topwait; // jff 5/8/98 insert delay
break;
default:
break;
}
}
/* jff 1/31/98 turn lighting off in tagged sectors of manual doors
* killough 10/98: replaced with gradual lighting code
*/
else if (res == crushed) // handle door meeting obstruction on way down
{
switch(door->type)
{
case genClose:
case genBlazeClose:
case blazeClose:
case p_close: // Close types do not bounce, merely wait
break;
case blazeRaise:
case genBlazeRaise:
door->direction = 1;
if (!comp[comp_blazing]) {
S_StartSound((mobj_t *)&door->sector->soundorg,sfx_bdopn);
break;
}
default: // other types bounce off the obstruction
door->direction = 1;
S_StartSound((mobj_t *)&door->sector->soundorg,sfx_doropn);
break;
}
}
break;
case 1:
// Door is moving up
res = T_MovePlane
(
door->sector,
door->speed,
door->topheight,
false,
1,
door->direction
);
/* killough 10/98: implement gradual lighting effects */
if (door->lighttag && door->topheight - door->sector->floorheight)
EV_LightTurnOnPartway(door->line,
FixedDiv(door->sector->ceilingheight -
door->sector->floorheight,
door->topheight -
door->sector->floorheight));
// handle door reaching the top
if (res == pastdest)
{
switch(door->type)
{
case blazeRaise: // regular open/close doors start waiting
case normal:
case genRaise:
case genBlazeRaise:
door->direction = 0; // wait at top with delay
door->topcountdown = door->topwait;
break;
case close30ThenOpen: // close and close/open doors are done
case blazeOpen:
case p_open:
case genBlazeOpen:
case genOpen:
case genCdO:
case genBlazeCdO:
door->sector->ceilingdata = NULL; //jff 2/22/98
P_RemoveThinker (&door->thinker); // unlink and free
break;
default:
break;
}
/* jff 1/31/98 turn lighting on in tagged sectors of manual doors
* killough 10/98: replaced with gradual lighting code */
}
break;
}
}
///////////////////////////////////////////////////////////////
//
// Door linedef handlers
//
///////////////////////////////////////////////////////////////
//
// EV_DoLockedDoor
//
// Handle opening a tagged locked door
//
// Passed the line activating the door, the type of door,
// and the thing that activated the line
// Returns true if a thinker created
//
int EV_DoLockedDoor
( line_t* line,
vldoor_e type,
mobj_t* thing )
{
player_t* p;
// only players can open locked doors
p = thing->player;
if (!p)
return 0;
// check type of linedef, and if key is possessed to open it
switch(line->special)
{
case 99: // Blue Lock
case 133:
if (!p->cards[it_bluecard] && !p->cards[it_blueskull])
{
p->message = PD_BLUEO; // Ty 03/27/98 - externalized
S_StartSound(p->mo,sfx_oof); // killough 3/20/98
return 0;
}
break;
case 134: // Red Lock
case 135:
if (!p->cards[it_redcard] && !p->cards[it_redskull])
{
p->message = PD_REDO; // Ty 03/27/98 - externalized
S_StartSound(p->mo,sfx_oof); // killough 3/20/98
return 0;
}
break;
case 136: // Yellow Lock
case 137:
if (!p->cards[it_yellowcard] && !p->cards[it_yellowskull])
{
p->message = PD_YELLOWO; // Ty 03/27/98 - externalized
S_StartSound(p->mo,sfx_oof); // killough 3/20/98
return 0;
}
break;
}
// got the key, so open the door
return EV_DoDoor(line,type);
}
//
// EV_DoDoor
//
// Handle opening a tagged door
//
// Passed the line activating the door and the type of door
// Returns true if a thinker created
//
int EV_DoDoor
( line_t* line,
vldoor_e type )
{
int secnum,rtn;
sector_t* sec;
vldoor_t* door;
secnum = -1;
rtn = 0;
// open all doors with the same tag as the activating line
while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0)
{
sec = &sectors[secnum];
// if the ceiling already moving, don't start the door action
if (P_SectorActive(ceiling_special,sec)) //jff 2/22/98
continue;
// new door thinker
rtn = 1;
door = Z_Malloc (sizeof(*door), PU_LEVSPEC, 0);
P_AddThinker (&door->thinker);
sec->ceilingdata = door; //jff 2/22/98
door->thinker.function = T_VerticalDoor;
door->sector = sec;
door->type = type;
door->topwait = VDOORWAIT;
door->speed = VDOORSPEED;
door->line = line; // jff 1/31/98 remember line that triggered us
door->lighttag = 0; /* killough 10/98: no light effects with tagged doors */
// setup door parameters according to type of door
switch(type)
{
case blazeClose:
door->topheight = P_FindLowestCeilingSurrounding(sec);
door->topheight -= 4*FRACUNIT;
door->direction = -1;
door->speed = VDOORSPEED * 4;
S_StartSound((mobj_t *)&door->sector->soundorg,sfx_bdcls);
break;
case p_close:
door->topheight = P_FindLowestCeilingSurrounding(sec);
door->topheight -= 4*FRACUNIT;
door->direction = -1;
S_StartSound((mobj_t *)&door->sector->soundorg,sfx_dorcls);
break;
case close30ThenOpen:
door->topheight = sec->ceilingheight;
door->direction = -1;
S_StartSound((mobj_t *)&door->sector->soundorg,sfx_dorcls);
break;
case blazeRaise:
case blazeOpen:
door->direction = 1;
door->topheight = P_FindLowestCeilingSurrounding(sec);
door->topheight -= 4*FRACUNIT;
door->speed = VDOORSPEED * 4;
if (door->topheight != sec->ceilingheight)
S_StartSound((mobj_t *)&door->sector->soundorg,sfx_bdopn);
break;
case normal:
case p_open:
door->direction = 1;
door->topheight = P_FindLowestCeilingSurrounding(sec);
door->topheight -= 4*FRACUNIT;
if (door->topheight != sec->ceilingheight)
S_StartSound((mobj_t *)&door->sector->soundorg,sfx_doropn);
break;
default:
break;
}
}
return rtn;
}
//
// EV_VerticalDoor
//
// Handle opening a door manually, no tag value
//
// Passed the line activating the door and the thing activating it
// Returns true if a thinker created
//
// jff 2/12/98 added int return value, fixed all returns
//
int EV_VerticalDoor
( line_t* line,
mobj_t* thing )
{
player_t* player;
int secnum;
sector_t* sec;
vldoor_t* door;
// Check for locks
player = thing->player;
switch(line->special)
{
case 26: // Blue Lock
case 32:
if ( !player )
return 0;
if (!player->cards[it_bluecard] && !player->cards[it_blueskull])
{
player->message = PD_BLUEK; // Ty 03/27/98 - externalized
S_StartSound(player->mo,sfx_oof); // killough 3/20/98
return 0;
}
break;
case 27: // Yellow Lock
case 34:
if ( !player )
return 0;
if (!player->cards[it_yellowcard] && !player->cards[it_yellowskull])
{
player->message = PD_YELLOWK; // Ty 03/27/98 - externalized
S_StartSound(player->mo,sfx_oof); // killough 3/20/98
return 0;
}
break;
case 28: // Red Lock
case 33:
if ( !player )
return 0;
if (!player->cards[it_redcard] && !player->cards[it_redskull])
{
player->message = PD_REDK; // Ty 03/27/98 - externalized
S_StartSound(player->mo,sfx_oof); // killough 3/20/98
return 0;
}
break;
default:
break;
}
// if the wrong side of door is pushed, give oof sound
if (line->sidenum[1]==-1) // killough
{
S_StartSound(player->mo,sfx_oof); // killough 3/20/98
return 0;
}
// get the sector on the second side of activating linedef
sec = sides[line->sidenum[1]].sector;
secnum = sec-sectors;
/* if door already has a thinker, use it
* cph 2001/04/05 -
* Ok, this is a disaster area. We're assuming that sec->ceilingdata
* is a vldoor_t! What if this door is controlled by both DR lines
* and by switches? I don't know how to fix that.
* Secondly, original Doom didn't distinguish floor/lighting/ceiling
* actions, so we need to do the same in demo compatibility mode.
*/
door = sec->ceilingdata;
if (demo_compatibility) {
if (!door) door = sec->floordata;
if (!door) door = sec->lightingdata;
}
if (door)
{
switch(line->special)
{
case 1: // only for "raise" doors, not "open"s
case 26:
case 27:
case 28:
case 117:
if (door->direction == -1)
door->direction = 1; // go back up
else
{
if (!thing->player)
return 0; // JDC: bad guys never close doors
door->direction = -1; // start going down immediately
}
return 1;
}
}
// emit proper sound
switch(line->special)
{
case 117: // blazing door raise
case 118: // blazing door open
S_StartSound((mobj_t *)&sec->soundorg,sfx_bdopn);
break;
case 1: // normal door sound
case 31:
S_StartSound((mobj_t *)&sec->soundorg,sfx_doropn);
break;
default: // locked door sound
S_StartSound((mobj_t *)&sec->soundorg,sfx_doropn);
break;
}
// new door thinker
door = Z_Malloc (sizeof(*door), PU_LEVSPEC, 0);
P_AddThinker (&door->thinker);
sec->ceilingdata = door; //jff 2/22/98
door->thinker.function = T_VerticalDoor;
door->sector = sec;
door->direction = 1;
door->speed = VDOORSPEED;
door->topwait = VDOORWAIT;
door->line = line; // jff 1/31/98 remember line that triggered us
/* killough 10/98: use gradual lighting changes if nonzero tag given */
door->lighttag = comp[comp_doorlight] ? 0 : line->tag;
// set the type of door from the activating linedef type
switch(line->special)
{
case 1:
case 26:
case 27:
case 28:
door->type = normal;
break;
case 31:
case 32:
case 33:
case 34:
door->type = p_open;
line->special = 0;
break;
case 117: // blazing door raise
door->type = blazeRaise;
door->speed = VDOORSPEED*4;
break;
case 118: // blazing door open
door->type = blazeOpen;
line->special = 0;
door->speed = VDOORSPEED*4;
break;
default:
door->lighttag = 0; // killough 10/98
break;
}
// find the top and bottom of the movement range
door->topheight = P_FindLowestCeilingSurrounding(sec);
door->topheight -= 4*FRACUNIT;
return 1;
}
///////////////////////////////////////////////////////////////
//
// Sector type door spawners
//
///////////////////////////////////////////////////////////////
//
// P_SpawnDoorCloseIn30()
//
// Spawn a door that closes after 30 seconds (called at level init)
//
// Passed the sector of the door, whose type specified the door action
// Returns nothing
//
void P_SpawnDoorCloseIn30 (sector_t* sec)
{
vldoor_t* door;
door = Z_Malloc ( sizeof(*door), PU_LEVSPEC, 0);
P_AddThinker (&door->thinker);
sec->ceilingdata = door; //jff 2/22/98
sec->special = 0;
door->thinker.function = T_VerticalDoor;
door->sector = sec;
door->direction = 0;
door->type = normal;
door->speed = VDOORSPEED;
door->topcountdown = 30 * 35;
door->line = NULL; // jff 1/31/98 remember line that triggered us
door->lighttag = 0; /* killough 10/98: no lighting changes */
}
//
// P_SpawnDoorRaiseIn5Mins()
//
// Spawn a door that opens after 5 minutes (called at level init)
//
// Passed the sector of the door, whose type specified the door action
// Returns nothing
//
void P_SpawnDoorRaiseIn5Mins
( sector_t* sec,
int secnum )
{
(void)secnum;
vldoor_t* door;
door = Z_Malloc ( sizeof(*door), PU_LEVSPEC, 0);
P_AddThinker (&door->thinker);
sec->ceilingdata = door; //jff 2/22/98
sec->special = 0;
door->thinker.function = T_VerticalDoor;
door->sector = sec;
door->direction = 2;
door->type = raiseIn5Mins;
door->speed = VDOORSPEED;
door->topheight = P_FindLowestCeilingSurrounding(sec);
door->topheight -= 4*FRACUNIT;
door->topwait = VDOORWAIT;
door->topcountdown = 5 * 60 * 35;
door->line = NULL; // jff 1/31/98 remember line that triggered us
door->lighttag = 0; /* killough 10/98: no lighting changes */
}

2623
apps/plugins/doom/p_enemy.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,50 @@
/* Emacs style mode select -*- C++ -*-
*-----------------------------------------------------------------------------
*
*
* PrBoom a Doom port merged with LxDoom and LSDLDoom
* based on BOOM, a modified and improved DOOM engine
* Copyright (C) 1999 by
* id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
* Copyright (C) 1999-2000 by
* Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* DESCRIPTION:
* Enemy thinking, AI.
* Action Pointer Functions
* that are associated with states/frames.
*
*-----------------------------------------------------------------------------*/
#ifndef __P_ENEMY__
#define __P_ENEMY__
#include "p_mobj.h"
void P_NoiseAlert (mobj_t *target, mobj_t *emmiter);
void P_SpawnBrainTargets(void); /* killough 3/26/98: spawn icon landings */
/* proff 11/22/98: Andy Baker's stealth monsters */
void P_BecomeVisible (mobj_t *actor);
void P_IncreaseVisibility (mobj_t *actor);
void P_DecreaseVisibility (mobj_t *actor);
extern struct brain_s { /* killough 3/26/98: global state of boss brain */
int easy, targeton;
} brain;
#endif // __P_ENEMY__

1035
apps/plugins/doom/p_floor.c Normal file

File diff suppressed because it is too large Load diff

1154
apps/plugins/doom/p_genlin.c Normal file

File diff suppressed because it is too large Load diff

904
apps/plugins/doom/p_inter.c Normal file
View file

@ -0,0 +1,904 @@
/* Emacs style mode select -*- C++ -*-
*-----------------------------------------------------------------------------
*
*
* PrBoom a Doom port merged with LxDoom and LSDLDoom
* based on BOOM, a modified and improved DOOM engine
* Copyright (C) 1999 by
* id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
* Copyright (C) 1999-2000 by
* Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* DESCRIPTION:
* Handling interactions (i.e., collisions).
*
*-----------------------------------------------------------------------------*/
#include "doomstat.h"
#include "dstrings.h"
#include "m_random.h"
#include "am_map.h"
#include "r_main.h"
#include "s_sound.h"
#include "sounds.h"
//#include "d_deh.h" // Ty 03/22/98 - externalized strings
#include "p_tick.h"
#include "i_system.h"
#include "p_inter.h"
#include "p_enemy.h"
#ifdef __GNUG__
#pragma implementation "p_inter.h"
#endif
#include "p_inter.h"
#define BONUSADD 6
// Ty 03/07/98 - add deh externals
// Maximums and such were hardcoded values. Need to externalize those for
// dehacked support (and future flexibility). Most var names came from the key
// strings used in dehacked.
int initial_health = 100;
int initial_bullets = 50;
int maxhealth = 100; // was MAXHEALTH as a #define, used only in this module
int max_armor = 200;
int green_armor_class = 1; // these are involved with armortype below
int blue_armor_class = 2;
int max_soul = 200;
int soul_health = 100;
int mega_health = 200;
int god_health = 100; // these are used in cheats (see st_stuff.c)
int idfa_armor = 200;
int idfa_armor_class = 2;
// not actually used due to pairing of cheat_k and cheat_fa
int idkfa_armor = 200;
int idkfa_armor_class = 2;
int bfgcells = 40; // used in p_pspr.c
// Ty 03/07/98 - end deh externals
// a weapon is found with two clip loads,
// a big item has five clip loads
int maxammo[NUMAMMO] = {200, 50, 300, 50};
int clipammo[NUMAMMO] = { 10, 4, 20, 1};
//
// GET STUFF
//
//
// P_GiveAmmo
// Num is the number of clip loads,
// not the individual count (0= 1/2 clip).
// Returns false if the ammo can't be picked up at all
//
boolean P_GiveAmmo(player_t *player, ammotype_t ammo, int num)
{
int oldammo;
if (ammo == am_noammo)
return false;
#ifdef RANGECHECK
if (ammo < 0 || ammo > NUMAMMO)
I_Error ("P_GiveAmmo: bad type %i", ammo);
#endif
if ( player->ammo[ammo] == player->maxammo[ammo] )
return false;
if (num)
num *= clipammo[ammo];
else
num = clipammo[ammo]/2;
// give double ammo in trainer mode, you'll need in nightmare
if (gameskill == sk_baby || gameskill == sk_nightmare)
num <<= 1;
oldammo = player->ammo[ammo];
player->ammo[ammo] += num;
if (player->ammo[ammo] > player->maxammo[ammo])
player->ammo[ammo] = player->maxammo[ammo];
// If non zero ammo, don't change up weapons, player was lower on purpose.
if (oldammo)
return true;
// We were down to zero, so select a new weapon.
// Preferences are not user selectable.
switch (ammo)
{
case am_clip:
if (player->readyweapon == wp_fist) {
if (player->weaponowned[wp_chaingun])
player->pendingweapon = wp_chaingun;
else
player->pendingweapon = wp_pistol;
}
break;
case am_shell:
if (player->readyweapon == wp_fist || player->readyweapon == wp_pistol)
if (player->weaponowned[wp_shotgun])
player->pendingweapon = wp_shotgun;
break;
case am_cell:
if (player->readyweapon == wp_fist || player->readyweapon == wp_pistol)
if (player->weaponowned[wp_plasma])
player->pendingweapon = wp_plasma;
break;
case am_misl:
if (player->readyweapon == wp_fist)
if (player->weaponowned[wp_missile])
player->pendingweapon = wp_missile;
default:
break;
}
return true;
}
//
// P_GiveWeapon
// The weapon name may have a MF_DROPPED flag ored in.
//
boolean P_GiveWeapon(player_t *player, weapontype_t weapon, boolean dropped)
{
boolean gaveammo;
boolean gaveweapon;
if (netgame && deathmatch!=2 && !dropped)
{
// leave placed weapons forever on net games
if (player->weaponowned[weapon])
return false;
player->bonuscount += BONUSADD;
player->weaponowned[weapon] = true;
P_GiveAmmo(player, weaponinfo[weapon].ammo, deathmatch ? 5 : 2);
player->pendingweapon = weapon;
/* cph 20028/10 - for old-school DM addicts, allow old behavior
* where only consoleplayer's pickup sounds are heard */
if (!comp[comp_sound] || player == &players[consoleplayer])
S_StartSound (player->mo, sfx_wpnup|PICKUP_SOUND); // killough 4/25/98
return false;
}
if (weaponinfo[weapon].ammo != am_noammo)
{
// give one clip with a dropped weapon,
// two clips with a found weapon
gaveammo = P_GiveAmmo (player, weaponinfo[weapon].ammo, dropped ? 1 : 2);
}
else
gaveammo = false;
if (player->weaponowned[weapon])
gaveweapon = false;
else
{
gaveweapon = true;
player->weaponowned[weapon] = true;
player->pendingweapon = weapon;
}
return gaveweapon || gaveammo;
}
//
// P_GiveBody
// Returns false if the body isn't needed at all
//
boolean P_GiveBody(player_t *player, int num)
{
if (player->health >= maxhealth)
return false; // Ty 03/09/98 externalized MAXHEALTH to maxhealth
player->health += num;
if (player->health > maxhealth)
player->health = maxhealth;
player->mo->health = player->health;
return true;
}
//
// P_GiveArmor
// Returns false if the armor is worse
// than the current armor.
//
boolean P_GiveArmor(player_t *player, int armortype)
{
int hits = armortype*100;
if (player->armorpoints >= hits)
return false; // don't pick up
player->armortype = armortype;
player->armorpoints = hits;
return true;
}
//
// P_GiveCard
//
void P_GiveCard(player_t *player, card_t card)
{
if (player->cards[card])
return;
player->bonuscount = BONUSADD;
player->cards[card] = 1;
}
//
// P_GivePower
//
// Rewritten by Lee Killough
//
boolean P_GivePower(player_t *player, int power)
{
static const int tics[NUMPOWERS] = {
INVULNTICS, 1 /* strength */, INVISTICS,
IRONTICS, 1 /* allmap */, INFRATICS,
};
switch (power)
{
case pw_invisibility:
player->mo->flags |= MF_SHADOW;
break;
case pw_allmap:
if (player->powers[pw_allmap])
return false;
break;
case pw_strength:
P_GiveBody(player,100);
break;
}
// Unless player has infinite duration cheat, set duration (killough)
if (player->powers[power] >= 0)
player->powers[power] = tics[power];
return true;
}
//
// P_TouchSpecialThing
//
void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher)
{
player_t *player;
int i;
int sound;
fixed_t delta = special->z - toucher->z;
if (delta > toucher->height || delta < -8*FRACUNIT)
return; // out of reach
sound = sfx_itemup;
player = toucher->player;
// Dead thing touching.
// Can happen with a sliding player corpse.
if (toucher->health <= 0)
return;
// Identify by sprite.
switch (special->sprite)
{
// armor
case SPR_ARM1:
if (!P_GiveArmor (player, green_armor_class))
return;
player->message = GOTARMOR; // Ty 03/22/98 - externalized
break;
case SPR_ARM2:
if (!P_GiveArmor (player, blue_armor_class))
return;
player->message = GOTMEGA; // Ty 03/22/98 - externalized
break;
// bonus items
case SPR_BON1:
player->health++; // can go over 100%
if (player->health > (maxhealth * 2))
player->health = (maxhealth * 2);
player->mo->health = player->health;
player->message = GOTHTHBONUS; // Ty 03/22/98 - externalized
break;
case SPR_BON2:
player->armorpoints++; // can go over 100%
if (player->armorpoints > max_armor)
player->armorpoints = max_armor;
if (!player->armortype)
player->armortype = green_armor_class;
player->message = GOTARMBONUS; // Ty 03/22/98 - externalized
break;
case SPR_SOUL:
player->health += soul_health;
if (player->health > max_soul)
player->health = max_soul;
player->mo->health = player->health;
player->message = GOTSUPER; // Ty 03/22/98 - externalized
sound = sfx_getpow;
break;
case SPR_MEGA:
if (gamemode != commercial)
return;
player->health = mega_health;
player->mo->health = player->health;
P_GiveArmor (player,blue_armor_class);
player->message = GOTMSPHERE; // Ty 03/22/98 - externalized
sound = sfx_getpow;
break;
// cards
// leave cards for everyone
case SPR_BKEY:
if (!player->cards[it_bluecard])
player->message = GOTBLUECARD; // Ty 03/22/98 - externalized
P_GiveCard (player, it_bluecard);
if (!netgame)
break;
return;
case SPR_YKEY:
if (!player->cards[it_yellowcard])
player->message = GOTYELWCARD; // Ty 03/22/98 - externalized
P_GiveCard (player, it_yellowcard);
if (!netgame)
break;
return;
case SPR_RKEY:
if (!player->cards[it_redcard])
player->message = GOTREDCARD; // Ty 03/22/98 - externalized
P_GiveCard (player, it_redcard);
if (!netgame)
break;
return;
case SPR_BSKU:
if (!player->cards[it_blueskull])
player->message = GOTBLUESKUL; // Ty 03/22/98 - externalized
P_GiveCard (player, it_blueskull);
if (!netgame)
break;
return;
case SPR_YSKU:
if (!player->cards[it_yellowskull])
player->message = GOTYELWSKUL; // Ty 03/22/98 - externalized
P_GiveCard (player, it_yellowskull);
if (!netgame)
break;
return;
case SPR_RSKU:
if (!player->cards[it_redskull])
player->message = GOTREDSKULL; // Ty 03/22/98 - externalized
P_GiveCard (player, it_redskull);
if (!netgame)
break;
return;
// medikits, heals
case SPR_STIM:
if (!P_GiveBody (player, 10))
return;
player->message = GOTSTIM; // Ty 03/22/98 - externalized
break;
case SPR_MEDI:
if (!P_GiveBody (player, 25))
return;
if (player->health < 50) // cph - 25 + the 25 just added, thanks to Quasar for reporting this bug
player->message = GOTMEDINEED; // Ty 03/22/98 - externalized
else
player->message = GOTMEDIKIT; // Ty 03/22/98 - externalized
break;
// power ups
case SPR_PINV:
if (!P_GivePower (player, pw_invulnerability))
return;
player->message = GOTINVUL; // Ty 03/22/98 - externalized
sound = sfx_getpow;
break;
case SPR_PSTR:
if (!P_GivePower (player, pw_strength))
return;
player->message = GOTBERSERK; // Ty 03/22/98 - externalized
if (player->readyweapon != wp_fist)
player->pendingweapon = wp_fist;
sound = sfx_getpow;
break;
case SPR_PINS:
if (!P_GivePower (player, pw_invisibility))
return;
player->message = GOTINVIS; // Ty 03/22/98 - externalized
sound = sfx_getpow;
break;
case SPR_SUIT:
if (!P_GivePower (player, pw_ironfeet))
return;
player->message = GOTSUIT; // Ty 03/22/98 - externalized
sound = sfx_getpow;
break;
case SPR_PMAP:
if (!P_GivePower (player, pw_allmap))
return;
player->message = GOTMAP; // Ty 03/22/98 - externalized
sound = sfx_getpow;
break;
case SPR_PVIS:
if (!P_GivePower (player, pw_infrared))
return;
player->message = GOTVISOR; // Ty 03/22/98 - externalized
sound = sfx_getpow;
break;
// ammo
case SPR_CLIP:
if (special->flags & MF_DROPPED)
{
if (!P_GiveAmmo (player,am_clip,0))
return;
}
else
{
if (!P_GiveAmmo (player,am_clip,1))
return;
}
player->message = GOTCLIP; // Ty 03/22/98 - externalized
break;
case SPR_AMMO:
if (!P_GiveAmmo (player, am_clip,5))
return;
player->message = GOTCLIPBOX; // Ty 03/22/98 - externalized
break;
case SPR_ROCK:
if (!P_GiveAmmo (player, am_misl,1))
return;
player->message = GOTROCKET; // Ty 03/22/98 - externalized
break;
case SPR_BROK:
if (!P_GiveAmmo (player, am_misl,5))
return;
player->message = GOTROCKBOX; // Ty 03/22/98 - externalized
break;
case SPR_CELL:
if (!P_GiveAmmo (player, am_cell,1))
return;
player->message = GOTCELL; // Ty 03/22/98 - externalized
break;
case SPR_CELP:
if (!P_GiveAmmo (player, am_cell,5))
return;
player->message = GOTCELLBOX; // Ty 03/22/98 - externalized
break;
case SPR_SHEL:
if (!P_GiveAmmo (player, am_shell,1))
return;
player->message = GOTSHELLS; // Ty 03/22/98 - externalized
break;
case SPR_SBOX:
if (!P_GiveAmmo (player, am_shell,5))
return;
player->message = GOTSHELLBOX; // Ty 03/22/98 - externalized
break;
case SPR_BPAK:
if (!player->backpack)
{
for (i=0 ; i<NUMAMMO ; i++)
player->maxammo[i] *= 2;
player->backpack = true;
}
for (i=0 ; i<NUMAMMO ; i++)
P_GiveAmmo (player, i, 1);
player->message = GOTBACKPACK; // Ty 03/22/98 - externalized
break;
// weapons
case SPR_BFUG:
if (!P_GiveWeapon (player, wp_bfg, false) )
return;
player->message = GOTBFG9000; // Ty 03/22/98 - externalized
sound = sfx_wpnup;
break;
case SPR_MGUN:
if (!P_GiveWeapon (player, wp_chaingun, (special->flags&MF_DROPPED)!=0) )
return;
player->message = GOTCHAINGUN; // Ty 03/22/98 - externalized
sound = sfx_wpnup;
break;
case SPR_CSAW:
if (!P_GiveWeapon (player, wp_chainsaw, false) )
return;
player->message = GOTCHAINSAW; // Ty 03/22/98 - externalized
sound = sfx_wpnup;
break;
case SPR_LAUN:
if (!P_GiveWeapon (player, wp_missile, false) )
return;
player->message = GOTLAUNCHER; // Ty 03/22/98 - externalized
sound = sfx_wpnup;
break;
case SPR_PLAS:
if (!P_GiveWeapon (player, wp_plasma, false) )
return;
player->message = GOTPLASMA; // Ty 03/22/98 - externalized
sound = sfx_wpnup;
break;
case SPR_SHOT:
if (!P_GiveWeapon (player, wp_shotgun, (special->flags&MF_DROPPED)!=0 ) )
return;
player->message = GOTSHOTGUN; // Ty 03/22/98 - externalized
sound = sfx_wpnup;
break;
case SPR_SGN2:
if (!P_GiveWeapon(player, wp_supershotgun, (special->flags&MF_DROPPED)!=0))
return;
player->message = GOTSHOTGUN2; // Ty 03/22/98 - externalized
sound = sfx_wpnup;
break;
default:
I_Error ("P_SpecialThing: Unknown gettable thing");
}
if (special->flags & MF_COUNTITEM)
player->itemcount++;
P_RemoveMobj (special);
player->bonuscount += BONUSADD;
/* cph 20028/10 - for old-school DM addicts, allow old behavior
* where only consoleplayer's pickup sounds are heard */
if (!comp[comp_sound] || player == &players[consoleplayer])
S_StartSound (player->mo, sound | PICKUP_SOUND); // killough 4/25/98
}
//
// KillMobj
//
// killough 11/98: make static
static void P_KillMobj(mobj_t *source, mobj_t *target)
{
mobjtype_t item;
mobj_t *mo;
target->flags &= ~(MF_SHOOTABLE|MF_FLOAT|MF_SKULLFLY);
if (target->type != MT_SKULL)
target->flags &= ~MF_NOGRAVITY;
target->flags |= MF_CORPSE|MF_DROPOFF;
target->height >>= 2;
if (!((target->flags ^ MF_COUNTKILL) & (MF_FRIEND | MF_COUNTKILL)))
totallive--;
if (source && source->player)
{
// count for intermission
if (target->flags & MF_COUNTKILL)
source->player->killcount++;
if (target->player)
source->player->frags[target->player-players]++;
}
else
if (target->flags & MF_COUNTKILL) { /* Add to kills tally */
if ((compatibility_level < lxdoom_1_compatibility) || !netgame) {
if (!netgame)
// count all monster deaths,
// even those caused by other monsters
players[0].killcount++;
} else
if (!deathmatch) {
// try and find a player to give the kill to, otherwise give the
// kill to a random player. this fixes the missing monsters bug
// in coop - rain
// CPhipps - not a bug as such, but certainly an inconsistency.
if (target->lastenemy && target->lastenemy->health > 0
&& target->lastenemy->player) // Fighting a player
target->lastenemy->player->killcount++;
else {
// cph - randomely choose a player in the game to be credited
// and do it uniformly between the active players
unsigned int activeplayers = 0, player, i;
for (player = 0; player<MAXPLAYERS; player++)
if (playeringame[player])
activeplayers++;
if (activeplayers) {
player = P_Random(pr_friends) % activeplayers;
for (i=0; i<MAXPLAYERS; i++)
if (playeringame[i])
if (!player--)
players[i].killcount++;
}
}
}
}
if (target->player)
{
// count environment kills against you
if (!source)
target->player->frags[target->player-players]++;
target->flags &= ~MF_SOLID;
target->player->playerstate = PST_DEAD;
P_DropWeapon (target->player);
if (target->player == &players[consoleplayer] && (automapmode & am_active))
AM_Stop(); // don't die in auto map; switch view prior to dying
}
if (target->health < -target->info->spawnhealth && target->info->xdeathstate)
P_SetMobjState (target, target->info->xdeathstate);
else
P_SetMobjState (target, target->info->deathstate);
target->tics -= P_Random(pr_killtics)&3;
if (target->tics < 1)
target->tics = 1;
// Drop stuff.
// This determines the kind of object spawned
// during the death frame of a thing.
switch (target->type)
{
case MT_WOLFSS:
case MT_POSSESSED:
item = MT_CLIP;
break;
case MT_SHOTGUY:
item = MT_SHOTGUN;
break;
case MT_CHAINGUY:
item = MT_CHAINGUN;
break;
default:
return;
}
mo = P_SpawnMobj (target->x,target->y,ONFLOORZ, item);
mo->flags |= MF_DROPPED; // special versions of items
}
//
// P_DamageMobj
// Damages both enemies and players
// "inflictor" is the thing that caused the damage
// creature or missile, can be NULL (slime, etc)
// "source" is the thing to target after taking damage
// creature or NULL
// Source and inflictor are the same for melee attacks.
// Source can be NULL for slime, barrel explosions
// and other environmental stuff.
//
void P_DamageMobj(mobj_t *target,mobj_t *inflictor, mobj_t *source, int damage)
{
player_t *player;
boolean justhit; /* killough 11/98 */
/* killough 8/31/98: allow bouncers to take damage */
if (!(target->flags & (MF_SHOOTABLE | MF_BOUNCES)))
return; // shouldn't happen...
if (target->health <= 0)
return;
/* proff 11/22/98: Andy Baker's Stealth monsters */
if (target->flags & MF_STEALTH)
P_BecomeVisible(target);
if (target->flags & MF_SKULLFLY)
target->momx = target->momy = target->momz = 0;
player = target->player;
if (player && gameskill == sk_baby)
damage >>= 1; // take half damage in trainer mode
// Some close combat weapons should not
// inflict thrust and push the victim out of reach,
// thus kick away unless using the chainsaw.
if (inflictor && !(target->flags & MF_NOCLIP) &&
(!source || !source->player ||
source->player->readyweapon != wp_chainsaw))
{
unsigned ang = R_PointToAngle2 (inflictor->x, inflictor->y,
target->x, target->y);
fixed_t thrust = damage*(FRACUNIT>>3)*100/target->info->mass;
// make fall forwards sometimes
if ( damage < 40 && damage > target->health
&& target->z - inflictor->z > 64*FRACUNIT
&& P_Random(pr_damagemobj) & 1)
{
ang += ANG180;
thrust *= 4;
}
ang >>= ANGLETOFINESHIFT;
target->momx += FixedMul (thrust, finecosine[ang]);
target->momy += FixedMul (thrust, finesine[ang]);
/* killough 11/98: thrust objects hanging off ledges */
if (target->intflags & MIF_FALLING && target->gear >= MAXGEAR)
target->gear = 0;
}
// player specific
if (player)
{
// end of game hell hack
if (target->subsector->sector->special == 11 && damage >= target->health)
damage = target->health - 1;
// Below certain threshold,
// ignore damage in GOD mode, or with INVUL power.
// killough 3/26/98: make god mode 100% god mode in non-compat mode
if ((damage < 1000 || (!comp[comp_god] && (player->cheats&CF_GODMODE))) &&
(player->cheats&CF_GODMODE || player->powers[pw_invulnerability]))
return;
if (player->armortype)
{
int saved = player->armortype == 1 ? damage/3 : damage/2;
if (player->armorpoints <= saved)
{
// armor is used up
saved = player->armorpoints;
player->armortype = 0;
}
player->armorpoints -= saved;
damage -= saved;
}
player->health -= damage; // mirror mobj health here for Dave
if (player->health < 0)
player->health = 0;
player->attacker = source;
player->damagecount += damage; // add damage after armor / invuln
if (player->damagecount > 100)
player->damagecount = 100; // teleport stomp does 10k points...
}
// do the damage
target->health -= damage;
if (target->health <= 0)
{
P_KillMobj (source, target);
return;
}
// killough 9/7/98: keep track of targets so that friends can help friends
if (mbf_features)
{
/* If target is a player, set player's target to source,
* so that a friend can tell who's hurting a player
*/
if (player)
P_SetTarget(&target->target, source);
/* killough 9/8/98:
* If target's health is less than 50%, move it to the front of its list.
* This will slightly increase the chances that enemies will choose to
* "finish it off", but its main purpose is to alert friends of danger.
*/
if (target->health*2 < target->info->spawnhealth)
{
thinker_t *cap = &thinkerclasscap[target->flags & MF_FRIEND ?
th_friends : th_enemies];
(target->thinker.cprev->cnext = target->thinker.cnext)->cprev =
target->thinker.cprev;
(target->thinker.cnext = cap->cnext)->cprev = &target->thinker;
(target->thinker.cprev = cap)->cnext = &target->thinker;
}
}
if ((justhit = (P_Random (pr_painchance) < target->info->painchance &&
!(target->flags & MF_SKULLFLY)))) //killough 11/98: see below
P_SetMobjState(target, target->info->painstate);
target->reactiontime = 0; // we're awake now...
/* killough 9/9/98: cleaned up, made more consistent: */
if (source && source != target && source->type != MT_VILE &&
(!target->threshold || target->type == MT_VILE) &&
((source->flags ^ target->flags) & MF_FRIEND ||
monster_infighting ||
!mbf_features))
{
/* if not intent on another player, chase after this one
*
* killough 2/15/98: remember last enemy, to prevent
* sleeping early; 2/21/98: Place priority on players
* killough 9/9/98: cleaned up, made more consistent:
*/
if (!target->lastenemy || target->lastenemy->health <= 0 ||
(!mbf_features ?
!target->lastenemy->player :
!((target->flags ^ target->lastenemy->flags) & MF_FRIEND) &&
target->target != source)) // remember last enemy - killough
P_SetTarget(&target->lastenemy, target->target);
P_SetTarget(&target->target, source); // killough 11/98
target->threshold = BASETHRESHOLD;
if (target->state == &states[target->info->spawnstate]
&& target->info->seestate != S_NULL)
P_SetMobjState (target, target->info->seestate);
}
/* killough 11/98: Don't attack a friend, unless hit by that friend. */
if (justhit && (target->target == source || !target->target ||
!(target->flags & target->target->flags & MF_FRIEND)))
target->flags |= MF_JUSTHIT; // fight back!
}

View file

@ -0,0 +1,77 @@
/* Emacs style mode select -*- C++ -*-
*-----------------------------------------------------------------------------
*
*
* PrBoom a Doom port merged with LxDoom and LSDLDoom
* based on BOOM, a modified and improved DOOM engine
* Copyright (C) 1999 by
* id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
* Copyright (C) 1999-2000 by
* Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* DESCRIPTION:
* Thing events, and dehacked specified numbers controlling them.
*
*-----------------------------------------------------------------------------*/
#ifndef __P_INTER__
#define __P_INTER__
#include "d_player.h"
#include "p_mobj.h"
#ifdef __GNUG__
#pragma interface
#endif
/* Ty 03/09/98 Moved to an int in p_inter.c for deh and externalization */
#define MAXHEALTH 100//maxhealth
/* follow a player exlusively for 3 seconds */
#define BASETHRESHOLD (100)
boolean P_GivePower(player_t *, int);
void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher);
void P_DamageMobj(mobj_t *target,mobj_t *inflictor,mobj_t *source,int damage);
/* killough 5/2/98: moved from d_deh.c, g_game.c, m_misc.c, others: */
extern int god_health; /* Ty 03/09/98 - deh support, see also p_inter.c */
extern int idfa_armor;
extern int idfa_armor_class;
extern int idkfa_armor;
extern int idkfa_armor_class; /* Ty - end */
/* Ty 03/13/98 - externalized initial settings for respawned player */
extern int initial_health;
extern int initial_bullets;
extern int maxhealth;
extern int max_armor;
extern int green_armor_class;
extern int blue_armor_class;
extern int max_soul;
extern int soul_health;
extern int mega_health;
extern int god_health;
extern int idfa_armor;
extern int idfa_armor_class;
extern int idkfa_armor;
extern int idkfa_armor_class;
extern int bfgcells;
extern int maxammo[], clipammo[];
#endif

View file

@ -0,0 +1,437 @@
/* Emacs style mode select -*- C++ -*-
*-----------------------------------------------------------------------------
*
*
* PrBoom a Doom port merged with LxDoom and LSDLDoom
* based on BOOM, a modified and improved DOOM engine
* Copyright (C) 1999 by
* id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
* Copyright (C) 1999-2000 by
* Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* DESCRIPTION:
* Action routines for lighting thinkers
* Spawn sector based lighting effects.
* Handle lighting linedef types
*
*-----------------------------------------------------------------------------*/
#include "doomstat.h" //jff 5/18/98
#include "doomdef.h"
#include "m_random.h"
#include "r_main.h"
#include "p_spec.h"
#include "p_tick.h"
//////////////////////////////////////////////////////////
//
// Lighting action routines, called once per tick
//
//////////////////////////////////////////////////////////
//
// T_FireFlicker()
//
// Firelight flicker action routine, called once per tick
//
// Passed a fireflicker_t structure containing light levels and timing
// Returns nothing
//
void T_FireFlicker (fireflicker_t* flick)
{
int amount;
if (--flick->count)
return;
amount = (P_Random(pr_lights)&3)*16;
if (flick->sector->lightlevel - amount < flick->minlight)
flick->sector->lightlevel = flick->minlight;
else
flick->sector->lightlevel = flick->maxlight - amount;
flick->count = 4;
}
//
// T_LightFlash()
//
// Broken light flashing action routine, called once per tick
//
// Passed a lightflash_t structure containing light levels and timing
// Returns nothing
//
void T_LightFlash (lightflash_t* flash)
{
if (--flash->count)
return;
if (flash->sector->lightlevel == flash->maxlight)
{
flash-> sector->lightlevel = flash->minlight;
flash->count = (P_Random(pr_lights)&flash->mintime)+1;
}
else
{
flash-> sector->lightlevel = flash->maxlight;
flash->count = (P_Random(pr_lights)&flash->maxtime)+1;
}
}
//
// T_StrobeFlash()
//
// Strobe light flashing action routine, called once per tick
//
// Passed a strobe_t structure containing light levels and timing
// Returns nothing
//
void T_StrobeFlash (strobe_t* flash)
{
if (--flash->count)
return;
if (flash->sector->lightlevel == flash->minlight)
{
flash-> sector->lightlevel = flash->maxlight;
flash->count = flash->brighttime;
}
else
{
flash-> sector->lightlevel = flash->minlight;
flash->count =flash->darktime;
}
}
//
// T_Glow()
//
// Glowing light action routine, called once per tick
//
// Passed a glow_t structure containing light levels and timing
// Returns nothing
//
void T_Glow(glow_t* g)
{
switch(g->direction)
{
case -1:
// light dims
g->sector->lightlevel -= GLOWSPEED;
if (g->sector->lightlevel <= g->minlight)
{
g->sector->lightlevel += GLOWSPEED;
g->direction = 1;
}
break;
case 1:
// light brightens
g->sector->lightlevel += GLOWSPEED;
if (g->sector->lightlevel >= g->maxlight)
{
g->sector->lightlevel -= GLOWSPEED;
g->direction = -1;
}
break;
}
}
//////////////////////////////////////////////////////////
//
// Sector lighting type spawners
//
// After the map has been loaded, each sector is scanned
// for specials that spawn thinkers
//
//////////////////////////////////////////////////////////
//
// P_SpawnFireFlicker()
//
// Spawns a fire flicker lighting thinker
//
// Passed the sector that spawned the thinker
// Returns nothing
//
void P_SpawnFireFlicker (sector_t* sector)
{
fireflicker_t* flick;
// Note that we are resetting sector attributes.
// Nothing special about it during gameplay.
sector->special &= ~31; //jff 3/14/98 clear non-generalized sector type
flick = Z_Malloc ( sizeof(*flick), PU_LEVSPEC, 0);
P_AddThinker (&flick->thinker);
flick->thinker.function = T_FireFlicker;
flick->sector = sector;
flick->maxlight = sector->lightlevel;
flick->minlight = P_FindMinSurroundingLight(sector,sector->lightlevel)+16;
flick->count = 4;
}
//
// P_SpawnLightFlash()
//
// Spawns a broken light flash lighting thinker
//
// Passed the sector that spawned the thinker
// Returns nothing
//
void P_SpawnLightFlash (sector_t* sector)
{
lightflash_t* flash;
// nothing special about it during gameplay
sector->special &= ~31; //jff 3/14/98 clear non-generalized sector type
flash = Z_Malloc ( sizeof(*flash), PU_LEVSPEC, 0);
P_AddThinker (&flash->thinker);
flash->thinker.function = T_LightFlash;
flash->sector = sector;
flash->maxlight = sector->lightlevel;
flash->minlight = P_FindMinSurroundingLight(sector,sector->lightlevel);
flash->maxtime = 64;
flash->mintime = 7;
flash->count = (P_Random(pr_lights)&flash->maxtime)+1;
}
//
// P_SpawnStrobeFlash
//
// Spawns a blinking light thinker
//
// Passed the sector that spawned the thinker, speed of blinking
// and whether blinking is to by syncrhonous with other sectors
//
// Returns nothing
//
void P_SpawnStrobeFlash
( sector_t* sector,
int fastOrSlow,
int inSync )
{
strobe_t* flash;
flash = Z_Malloc ( sizeof(*flash), PU_LEVSPEC, 0);
P_AddThinker (&flash->thinker);
flash->sector = sector;
flash->darktime = fastOrSlow;
flash->brighttime = STROBEBRIGHT;
flash->thinker.function = T_StrobeFlash;
flash->maxlight = sector->lightlevel;
flash->minlight = P_FindMinSurroundingLight(sector, sector->lightlevel);
if (flash->minlight == flash->maxlight)
flash->minlight = 0;
// nothing special about it during gameplay
sector->special &= ~31; //jff 3/14/98 clear non-generalized sector type
if (!inSync)
flash->count = (P_Random(pr_lights)&7)+1;
else
flash->count = 1;
}
//
// P_SpawnGlowingLight()
//
// Spawns a glowing light (smooth oscillation from min to max) thinker
//
// Passed the sector that spawned the thinker
// Returns nothing
//
void P_SpawnGlowingLight(sector_t* sector)
{
glow_t* g;
g = Z_Malloc( sizeof(*g), PU_LEVSPEC, 0);
P_AddThinker(&g->thinker);
g->sector = sector;
g->minlight = P_FindMinSurroundingLight(sector,sector->lightlevel);
g->maxlight = sector->lightlevel;
g->thinker.function = T_Glow;
g->direction = -1;
sector->special &= ~31; //jff 3/14/98 clear non-generalized sector type
}
//////////////////////////////////////////////////////////
//
// Linedef lighting function handlers
//
//////////////////////////////////////////////////////////
//
// EV_StartLightStrobing()
//
// Start strobing lights (usually from a trigger)
//
// Passed the line that activated the strobing
// Returns true
//
// jff 2/12/98 added int return value, fixed return
//
int EV_StartLightStrobing(line_t* line)
{
int secnum;
sector_t* sec;
secnum = -1;
// start lights strobing in all sectors tagged same as line
while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0)
{
sec = &sectors[secnum];
// if already doing a lighting function, don't start a second
if (P_SectorActive(lighting_special,sec)) //jff 2/22/98
continue;
P_SpawnStrobeFlash (sec,SLOWDARK, 0);
}
return 1;
}
//
// EV_TurnTagLightsOff()
//
// Turn line's tagged sector's lights to min adjacent neighbor level
//
// Passed the line that activated the lights being turned off
// Returns true
//
// jff 2/12/98 added int return value, fixed return
//
int EV_TurnTagLightsOff(line_t* line)
{
int j;
// search sectors for those with same tag as activating line
// killough 10/98: replaced inefficient search with fast search
for (j = -1; (j = P_FindSectorFromLineTag(line,j)) >= 0;)
{
sector_t *sector = sectors + j, *tsec;
int i, min = sector->lightlevel;
// find min neighbor light level
for (i = 0;i < sector->linecount; i++)
if ((tsec = getNextSector(sector->lines[i], sector)) &&
tsec->lightlevel < min)
min = tsec->lightlevel;
sector->lightlevel = min;
}
return 1;
}
//
// EV_LightTurnOn()
//
// Turn sectors tagged to line lights on to specified or max neighbor level
//
// Passed the activating line, and a level to set the light to
// If level passed is 0, the maximum neighbor lighting is used
// Returns true
//
// jff 2/12/98 added int return value, fixed return
//
int EV_LightTurnOn(line_t *line, int bright)
{
int i;
// search all sectors for ones with same tag as activating line
// killough 10/98: replace inefficient search with fast search
for (i = -1; (i = P_FindSectorFromLineTag(line,i)) >= 0;)
{
sector_t *temp, *sector = sectors+i;
int j, tbright = bright; //jff 5/17/98 search for maximum PER sector
// bright = 0 means to search for highest light level surrounding sector
if (!bright)
for (j = 0;j < sector->linecount; j++)
if ((temp = getNextSector(sector->lines[j],sector)) &&
temp->lightlevel > tbright)
tbright = temp->lightlevel;
sector->lightlevel = tbright;
//jff 5/17/98 unless compatibility optioned
//then maximum near ANY tagged sector
if (comp[comp_model])
bright = tbright;
}
return 1;
}
/* killough 10/98:
*
* EV_LightTurnOnPartway()
*
* Turn sectors tagged to line lights on to specified or max neighbor level
*
* Passed the activating line, and a light level fraction between 0 and 1.
* Sets the light to min on 0, max on 1, and interpolates in-between.
* Used for doors with gradual lighting effects.
*
* Returns true
*/
int EV_LightTurnOnPartway(line_t *line, fixed_t level)
{
int i;
if (level < 0) // clip at extremes
level = 0;
if (level > FRACUNIT)
level = FRACUNIT;
// search all sectors for ones with same tag as activating line
for (i = -1; (i = P_FindSectorFromLineTag(line,i)) >= 0;)
{
sector_t *temp, *sector = sectors+i;
int j, bright = 0, min = sector->lightlevel;
for (j = 0; j < sector->linecount; j++)
if ((temp = getNextSector(sector->lines[j],sector)))
{
if (temp->lightlevel > bright)
bright = temp->lightlevel;
if (temp->lightlevel < min)
min = temp->lightlevel;
}
sector->lightlevel = // Set level in-between extremes
(level * bright + (FRACUNIT-level) * min) >> FRACBITS;
}
return 1;
}

2207
apps/plugins/doom/p_map.c Normal file

File diff suppressed because it is too large Load diff

90
apps/plugins/doom/p_map.h Normal file
View file

@ -0,0 +1,90 @@
/* Emacs style mode select -*- C++ -*-
*-----------------------------------------------------------------------------
*
*
* PrBoom a Doom port merged with LxDoom and LSDLDoom
* based on BOOM, a modified and improved DOOM engine
* Copyright (C) 1999 by
* id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
* Copyright (C) 1999-2000 by
* Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* DESCRIPTION:
* Map functions
*
*-----------------------------------------------------------------------------*/
#ifndef __P_MAP__
#define __P_MAP__
#include "r_defs.h"
#include "d_player.h"
#define USERANGE (64*FRACUNIT)
#define MELEERANGE (64*FRACUNIT)
#define MISSILERANGE (32*64*FRACUNIT)
// MAXRADIUS is for precalculated sector block boxes the spider demon
// is larger, but we do not have any moving sectors nearby
#define MAXRADIUS (32*FRACUNIT)
// killough 3/15/98: add fourth argument to P_TryMove
boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean dropoff);
// killough 8/9/98: extra argument for telefragging
boolean P_TeleportMove(mobj_t *thing, fixed_t x, fixed_t y,boolean boss);
void P_SlideMove(mobj_t *mo);
boolean P_CheckSight(mobj_t *t1, mobj_t *t2);
void P_UseLines(player_t *player);
// killough 8/2/98: add 'mask' argument to prevent friends autoaiming at others
fixed_t P_AimLineAttack(mobj_t *t1,angle_t angle,fixed_t distance, uint_64_t mask);
void P_LineAttack(mobj_t *t1, angle_t angle, fixed_t distance,
fixed_t slope, int damage );
void P_RadiusAttack(mobj_t *spot, mobj_t *source, int damage);
boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y);
//jff 3/19/98 P_CheckSector(): new routine to replace P_ChangeSector()
boolean P_ChangeSector(sector_t* sector,boolean crunch);
boolean P_CheckSector(sector_t *sector, boolean crunch);
void P_DelSeclist(msecnode_t*); // phares 3/16/98
void P_CreateSecNodeList(mobj_t*,fixed_t,fixed_t); // phares 3/14/98
boolean Check_Sides(mobj_t *, int, int); // phares
int P_GetMoveFactor(const mobj_t *mo, int *friction); // killough 8/28/98
int P_GetFriction(const mobj_t *mo, int *factor); // killough 8/28/98
void P_ApplyTorque(mobj_t *mo); // killough 9/12/98
/* cphipps 2004/08/30 */
void P_MapStart(void);
void P_MapEnd(void);
// If "floatok" true, move would be ok if within "tmfloorz - tmceilingz".
extern boolean floatok;
extern boolean felldown; // killough 11/98: indicates object pushed off ledge
extern fixed_t tmfloorz;
extern fixed_t tmceilingz;
extern line_t *ceilingline;
extern line_t *floorline; // killough 8/23/98
extern mobj_t *linetarget; // who got hit (or NULL)
extern msecnode_t *sector_list; // phares 3/16/98
extern fixed_t tmbbox[4]; // phares 3/20/98
extern line_t *blockline; // killough 8/11/98
#endif // __P_MAP__

View file

@ -0,0 +1,700 @@
/* Emacs style mode select -*- C++ -*-
*-----------------------------------------------------------------------------
*
*
* PrBoom a Doom port merged with LxDoom and LSDLDoom
* based on BOOM, a modified and improved DOOM engine
* Copyright (C) 1999 by
* id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
* Copyright (C) 1999-2000 by
* Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* DESCRIPTION:
* Movement/collision utility functions,
* as used by function in p_map.c.
* BLOCKMAP Iterator functions,
* and some PIT_* functions to use for iteration.
*
*-----------------------------------------------------------------------------*/
#include "doomstat.h"
#include "m_bbox.h"
#include "r_main.h"
#include "p_maputl.h"
#include "p_map.h"
#include "p_setup.h"
#include "rockmacros.h"
//
// P_AproxDistance
// Gives an estimation of distance (not exact)
//
fixed_t CONSTFUNC P_AproxDistance(fixed_t dx, fixed_t dy)
{
dx = D_abs(dx);
dy = D_abs(dy);
if (dx < dy)
return dx+dy-(dx>>1);
return dx+dy-(dy>>1);
}
//
// P_PointOnLineSide
// Returns 0 or 1
//
// killough 5/3/98: reformatted, cleaned up
int CONSTFUNC P_PointOnLineSide(fixed_t x, fixed_t y, const line_t *line)
{
return
!line->dx ? x <= line->v1->x ? line->dy > 0 : line->dy < 0 :
!line->dy ? y <= line->v1->y ? line->dx < 0 : line->dx > 0 :
FixedMul(y-line->v1->y, line->dx>>FRACBITS) >=
FixedMul(line->dy>>FRACBITS, x-line->v1->x);
}
//
// P_BoxOnLineSide
// Considers the line to be infinite
// Returns side 0 or 1, -1 if box crosses the line.
//
// killough 5/3/98: reformatted, cleaned up
int CONSTFUNC P_BoxOnLineSide(const fixed_t *tmbox, const line_t *ld)
{
switch (ld->slopetype)
{
int p;
default: // shut up compiler warnings -- killough
case ST_HORIZONTAL:
return
(tmbox[BOXBOTTOM] > ld->v1->y) == (p = tmbox[BOXTOP] > ld->v1->y) ?
p ^ (ld->dx < 0) : -1;
case ST_VERTICAL:
return
(tmbox[BOXLEFT] < ld->v1->x) == (p = tmbox[BOXRIGHT] < ld->v1->x) ?
p ^ (ld->dy < 0) : -1;
case ST_POSITIVE:
return
P_PointOnLineSide(tmbox[BOXRIGHT], tmbox[BOXBOTTOM], ld) ==
(p = P_PointOnLineSide(tmbox[BOXLEFT], tmbox[BOXTOP], ld)) ? p : -1;
case ST_NEGATIVE:
return
(P_PointOnLineSide(tmbox[BOXLEFT], tmbox[BOXBOTTOM], ld)) ==
(p = P_PointOnLineSide(tmbox[BOXRIGHT], tmbox[BOXTOP], ld)) ? p : -1;
}
}
//
// P_PointOnDivlineSide
// Returns 0 or 1.
//
// killough 5/3/98: reformatted, cleaned up
int CONSTFUNC P_PointOnDivlineSide(fixed_t x, fixed_t y, const divline_t *line)
{
return
!line->dx ? x <= line->x ? line->dy > 0 : line->dy < 0 :
!line->dy ? y <= line->y ? line->dx < 0 : line->dx > 0 :
(line->dy^line->dx^(x -= line->x)^(y -= line->y)) < 0 ? (line->dy^x) < 0 :
FixedMul(y>>8, line->dx>>8) >= FixedMul(line->dy>>8, x>>8);
}
//
// P_MakeDivline
//
void P_MakeDivline(const line_t *li, divline_t *dl)
{
dl->x = li->v1->x;
dl->y = li->v1->y;
dl->dx = li->dx;
dl->dy = li->dy;
}
//
// P_InterceptVector
// Returns the fractional intercept point
// along the first divline.
// This is only called by the addthings
// and addlines traversers.
//
// killough 5/3/98: reformatted, cleaned up
fixed_t CONSTFUNC P_InterceptVector(const divline_t *v2, const divline_t *v1)
{
fixed_t den = FixedMul(v1->dy>>8, v2->dx) - FixedMul(v1->dx>>8, v2->dy);
return den ? FixedDiv((FixedMul((v1->x-v2->x)>>8, v1->dy) +
FixedMul((v2->y-v1->y)>>8, v1->dx)), den) : 0;
}
//
// P_LineOpening
// Sets opentop and openbottom to the window
// through a two sided line.
// OPTIMIZE: keep this precalculated
//
fixed_t opentop;
fixed_t openbottom;
fixed_t openrange;
fixed_t lowfloor;
// moved front and back outside P-LineOpening and changed // phares 3/7/98
// them to these so we can pick up the new friction value
// in PIT_CheckLine()
sector_t *openfrontsector; // made global // phares
sector_t *openbacksector; // made global
void P_LineOpening(const line_t *linedef)
{
if (linedef->sidenum[1] == -1) // single sided line
{
openrange = 0;
return;
}
openfrontsector = linedef->frontsector;
openbacksector = linedef->backsector;
if (openfrontsector->ceilingheight < openbacksector->ceilingheight)
opentop = openfrontsector->ceilingheight;
else
opentop = openbacksector->ceilingheight;
if (openfrontsector->floorheight > openbacksector->floorheight)
{
openbottom = openfrontsector->floorheight;
lowfloor = openbacksector->floorheight;
}
else
{
openbottom = openbacksector->floorheight;
lowfloor = openfrontsector->floorheight;
}
openrange = opentop - openbottom;
}
//
// THING POSITION SETTING
//
//
// P_UnsetThingPosition
// Unlinks a thing from block map and sectors.
// On each position change, BLOCKMAP and other
// lookups maintaining lists ot things inside
// these structures need to be updated.
//
void P_UnsetThingPosition (mobj_t *thing)
{
if (!(thing->flags & MF_NOSECTOR))
{
/* invisible things don't need to be in sector list
* unlink from subsector
*
* killough 8/11/98: simpler scheme using pointers-to-pointers for prev
* pointers, allows head node pointers to be treated like everything else
*/
mobj_t **sprev = thing->sprev;
mobj_t *snext = thing->snext;
if ((*sprev = snext)) // unlink from sector list
snext->sprev = sprev;
// phares 3/14/98
//
// Save the sector list pointed to by touching_sectorlist.
// In P_SetThingPosition, we'll keep any nodes that represent
// sectors the Thing still touches. We'll add new ones then, and
// delete any nodes for sectors the Thing has vacated. Then we'll
// put it back into touching_sectorlist. It's done this way to
// avoid a lot of deleting/creating for nodes, when most of the
// time you just get back what you deleted anyway.
//
// If this Thing is being removed entirely, then the calling
// routine will clear out the nodes in sector_list.
sector_list = thing->touching_sectorlist;
thing->touching_sectorlist = NULL; //to be restored by P_SetThingPosition
}
if (!(thing->flags & MF_NOBLOCKMAP))
{
/* inert things don't need to be in blockmap
*
* killough 8/11/98: simpler scheme using pointers-to-pointers for prev
* pointers, allows head node pointers to be treated like everything else
*
* Also more robust, since it doesn't depend on current position for
* unlinking. Old method required computing head node based on position
* at time of unlinking, assuming it was the same position as during
* linking.
*/
mobj_t *bnext, **bprev = thing->bprev;
if (bprev && (*bprev = bnext = thing->bnext)) // unlink from block map
bnext->bprev = bprev;
}
}
//
// P_SetThingPosition
// Links a thing into both a block and a subsector
// based on it's x y.
// Sets thing->subsector properly
//
// killough 5/3/98: reformatted, cleaned up
void P_SetThingPosition(mobj_t *thing)
{ // link into subsector
subsector_t *ss = thing->subsector = R_PointInSubsector(thing->x, thing->y);
if (!(thing->flags & MF_NOSECTOR))
{
// invisible things don't go into the sector links
// killough 8/11/98: simpler scheme using pointer-to-pointer prev
// pointers, allows head nodes to be treated like everything else
mobj_t **link = &ss->sector->thinglist;
mobj_t *snext = *link;
if ((thing->snext = snext))
snext->sprev = &thing->snext;
thing->sprev = link;
*link = thing;
// phares 3/16/98
//
// If sector_list isn't NULL, it has a collection of sector
// nodes that were just removed from this Thing.
// Collect the sectors the object will live in by looking at
// the existing sector_list and adding new nodes and deleting
// obsolete ones.
// When a node is deleted, its sector links (the links starting
// at sector_t->touching_thinglist) are broken. When a node is
// added, new sector links are created.
P_CreateSecNodeList(thing,thing->x,thing->y);
thing->touching_sectorlist = sector_list; // Attach to Thing's mobj_t
sector_list = NULL; // clear for next time
}
// link into blockmap
if (!(thing->flags & MF_NOBLOCKMAP))
{
// inert things don't need to be in blockmap
int blockx = (thing->x - bmaporgx)>>MAPBLOCKSHIFT;
int blocky = (thing->y - bmaporgy)>>MAPBLOCKSHIFT;
if (blockx>=0 && blockx < bmapwidth && blocky>=0 && blocky < bmapheight)
{
// killough 8/11/98: simpler scheme using pointer-to-pointer prev
// pointers, allows head nodes to be treated like everything else
mobj_t **link = &blocklinks[blocky*bmapwidth+blockx];
mobj_t *bnext = *link;
if ((thing->bnext = bnext))
bnext->bprev = &thing->bnext;
thing->bprev = link;
*link = thing;
}
else // thing is off the map
thing->bnext = NULL, thing->bprev = NULL;
}
}
// killough 3/15/98:
//
// A fast function for testing intersections between things and linedefs.
boolean CONSTFUNC ThingIsOnLine(const mobj_t *t, const line_t *l)
{
int dx = l->dx >> FRACBITS; // Linedef vector
int dy = l->dy >> FRACBITS;
int a = (l->v1->x >> FRACBITS) - (t->x >> FRACBITS); // Thing-->v1 vector
int b = (l->v1->y >> FRACBITS) - (t->y >> FRACBITS);
int r = t->radius >> FRACBITS; // Thing radius
// First make sure bounding boxes of linedef and thing intersect.
// Leads to quick rejection using only shifts and adds/subs/compares.
if (D_abs(a*2+dx)-D_abs(dx) > r*2 || D_abs(b*2+dy)-D_abs(dy) > r*2)
return 0;
// Next, make sure that at least one thing crosshair intersects linedef's
// extension. Requires only 3-4 multiplications, the rest adds/subs/
// shifts/xors (writing the steps out this way leads to better codegen).
a *= dy;
b *= dx;
a -= b;
b = dx + dy;
b *= r;
if (((a-b)^(a+b)) < 0)
return 1;
dy -= dx;
dy *= r;
b = a+dy;
a -= dy;
return (a^b) < 0;
}
//
// BLOCK MAP ITERATORS
// For each line/thing in the given mapblock,
// call the passed PIT_* function.
// If the function returns false,
// exit with false without checking anything else.
//
//
// P_BlockLinesIterator
// The validcount flags are used to avoid checking lines
// that are marked in multiple mapblocks,
// so increment validcount before the first call
// to P_BlockLinesIterator, then make one or more calls
// to it.
//
// killough 5/3/98: reformatted, cleaned up
boolean P_BlockLinesIterator(int x, int y, boolean func(line_t*))
{
int offset;
const long *list; // killough 3/1/98: for removal of blockmap limit
if (x<0 || y<0 || x>=bmapwidth || y>=bmapheight)
return true;
offset = y*bmapwidth+x;
offset = *(blockmap+offset);
list = blockmaplump+offset; // original was reading // phares
// delmiting 0 as linedef 0 // phares
// killough 1/31/98: for compatibility we need to use the old method.
// Most demos go out of sync, and maybe other problems happen, if we
// don't consider linedef 0. For safety this should be qualified.
if (!demo_compatibility) // killough 2/22/98: demo_compatibility check
list++; // skip 0 starting delimiter // phares
for ( ; *list != -1 ; list++) // phares
{
line_t *ld = &lines[*list];
if (ld->validcount == validcount)
continue; // line has already been checked
ld->validcount = validcount;
if (!func(ld))
return false;
}
return true; // everything was checked
}
//
// P_BlockThingsIterator
//
// killough 5/3/98: reformatted, cleaned up
boolean P_BlockThingsIterator(int x, int y, boolean func(mobj_t*))
{
mobj_t *mobj;
if (!(x<0 || y<0 || x>=bmapwidth || y>=bmapheight))
for (mobj = blocklinks[y*bmapwidth+x]; mobj; mobj = mobj->bnext)
if (!func(mobj))
return false;
return true;
}
//
// INTERCEPT ROUTINES
//
// 1/11/98 killough: Intercept limit removed
static intercept_t *intercepts, *intercept_p;
// Check for limit and double size if necessary -- killough
static void check_intercept(void)
{
static size_t num_intercepts;
size_t offset = intercept_p - intercepts;
if (offset >= num_intercepts)
{
num_intercepts = num_intercepts ? num_intercepts*2 : 128;
intercepts = realloc(intercepts, sizeof(*intercepts)*num_intercepts);
intercept_p = intercepts + offset;
}
}
divline_t trace;
// PIT_AddLineIntercepts.
// Looks for lines in the given block
// that intercept the given trace
// to add to the intercepts list.
//
// A line is crossed if its endpoints
// are on opposite sides of the trace.
//
// killough 5/3/98: reformatted, cleaned up
boolean PIT_AddLineIntercepts(line_t *ld)
{
int s1;
int s2;
fixed_t frac;
divline_t dl;
// avoid precision problems with two routines
if (trace.dx > FRACUNIT*16 || trace.dy > FRACUNIT*16 ||
trace.dx < -FRACUNIT*16 || trace.dy < -FRACUNIT*16)
{
s1 = P_PointOnDivlineSide (ld->v1->x, ld->v1->y, &trace);
s2 = P_PointOnDivlineSide (ld->v2->x, ld->v2->y, &trace);
}
else
{
s1 = P_PointOnLineSide (trace.x, trace.y, ld);
s2 = P_PointOnLineSide (trace.x+trace.dx, trace.y+trace.dy, ld);
}
if (s1 == s2)
return true; // line isn't crossed
// hit the line
P_MakeDivline(ld, &dl);
frac = P_InterceptVector(&trace, &dl);
if (frac < 0)
return true; // behind source
check_intercept(); // killough
intercept_p->frac = frac;
intercept_p->isaline = true;
intercept_p->d.line = ld;
intercept_p++;
return true; // continue
}
//
// PIT_AddThingIntercepts
//
// killough 5/3/98: reformatted, cleaned up
boolean PIT_AddThingIntercepts(mobj_t *thing)
{
fixed_t x1, y1;
fixed_t x2, y2;
int s1, s2;
divline_t dl;
fixed_t frac;
// check a corner to corner crossection for hit
if ((trace.dx ^ trace.dy) > 0)
{
x1 = thing->x - thing->radius;
y1 = thing->y + thing->radius;
x2 = thing->x + thing->radius;
y2 = thing->y - thing->radius;
}
else
{
x1 = thing->x - thing->radius;
y1 = thing->y - thing->radius;
x2 = thing->x + thing->radius;
y2 = thing->y + thing->radius;
}
s1 = P_PointOnDivlineSide (x1, y1, &trace);
s2 = P_PointOnDivlineSide (x2, y2, &trace);
if (s1 == s2)
return true; // line isn't crossed
dl.x = x1;
dl.y = y1;
dl.dx = x2-x1;
dl.dy = y2-y1;
frac = P_InterceptVector (&trace, &dl);
if (frac < 0)
return true; // behind source
check_intercept(); // killough
intercept_p->frac = frac;
intercept_p->isaline = false;
intercept_p->d.thing = thing;
intercept_p++;
return true; // keep going
}
//
// P_TraverseIntercepts
// Returns true if the traverser function returns true
// for all lines.
//
// killough 5/3/98: reformatted, cleaned up
boolean P_TraverseIntercepts(traverser_t func, fixed_t maxfrac)
{
intercept_t *in = NULL;
int count = intercept_p - intercepts;
while (count--)
{
fixed_t dist = INT_MAX;
intercept_t *scan;
for (scan = intercepts; scan < intercept_p; scan++)
if (scan->frac < dist)
dist = (in=scan)->frac;
if (dist > maxfrac)
return true; // checked everything in range
if (!func(in))
return false; // don't bother going farther
in->frac = INT_MAX;
}
return true; // everything was traversed
}
//
// P_PathTraverse
// Traces a line from x1,y1 to x2,y2,
// calling the traverser function for each.
// Returns true if the traverser function returns true
// for all lines.
//
// killough 5/3/98: reformatted, cleaned up
boolean P_PathTraverse(fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2,
int flags, boolean trav(intercept_t *))
{
fixed_t xt1, yt1;
fixed_t xt2, yt2;
fixed_t xstep, ystep;
fixed_t partial;
fixed_t xintercept, yintercept;
int mapx, mapy;
int mapxstep, mapystep;
int count;
validcount++;
intercept_p = intercepts;
if (!((x1-bmaporgx)&(MAPBLOCKSIZE-1)))
x1 += FRACUNIT; // don't side exactly on a line
if (!((y1-bmaporgy)&(MAPBLOCKSIZE-1)))
y1 += FRACUNIT; // don't side exactly on a line
trace.x = x1;
trace.y = y1;
trace.dx = x2 - x1;
trace.dy = y2 - y1;
x1 -= bmaporgx;
y1 -= bmaporgy;
xt1 = x1>>MAPBLOCKSHIFT;
yt1 = y1>>MAPBLOCKSHIFT;
x2 -= bmaporgx;
y2 -= bmaporgy;
xt2 = x2>>MAPBLOCKSHIFT;
yt2 = y2>>MAPBLOCKSHIFT;
if (xt2 > xt1)
{
mapxstep = 1;
partial = FRACUNIT - ((x1>>MAPBTOFRAC)&(FRACUNIT-1));
ystep = FixedDiv (y2-y1,D_abs(x2-x1));
}
else
if (xt2 < xt1)
{
mapxstep = -1;
partial = (x1>>MAPBTOFRAC)&(FRACUNIT-1);
ystep = FixedDiv (y2-y1,D_abs(x2-x1));
}
else
{
mapxstep = 0;
partial = FRACUNIT;
ystep = 256*FRACUNIT;
}
yintercept = (y1>>MAPBTOFRAC) + FixedMul(partial, ystep);
if (yt2 > yt1)
{
mapystep = 1;
partial = FRACUNIT - ((y1>>MAPBTOFRAC)&(FRACUNIT-1));
xstep = FixedDiv (x2-x1,D_abs(y2-y1));
}
else
if (yt2 < yt1)
{
mapystep = -1;
partial = (y1>>MAPBTOFRAC)&(FRACUNIT-1);
xstep = FixedDiv (x2-x1,D_abs(y2-y1));
}
else
{
mapystep = 0;
partial = FRACUNIT;
xstep = 256*FRACUNIT;
}
xintercept = (x1>>MAPBTOFRAC) + FixedMul (partial, xstep);
// Step through map blocks.
// Count is present to prevent a round off error
// from skipping the break.
mapx = xt1;
mapy = yt1;
for (count = 0; count < 64; count++)
{
if (flags & PT_ADDLINES)
if (!P_BlockLinesIterator(mapx, mapy,PIT_AddLineIntercepts))
return false; // early out
if (flags & PT_ADDTHINGS)
if (!P_BlockThingsIterator(mapx, mapy,PIT_AddThingIntercepts))
return false; // early out
if (mapx == xt2 && mapy == yt2)
break;
if ((yintercept >> FRACBITS) == mapy)
{
yintercept += ystep;
mapx += mapxstep;
}
else
if ((xintercept >> FRACBITS) == mapx)
{
xintercept += xstep;
mapy += mapystep;
}
}
// go through the sorted list
return P_TraverseIntercepts(trav, FRACUNIT);
}

View file

@ -0,0 +1,91 @@
/* Emacs style mode select -*- C++ -*-
*-----------------------------------------------------------------------------
*
*
* PrBoom a Doom port merged with LxDoom and LSDLDoom
* based on BOOM, a modified and improved DOOM engine
* Copyright (C) 1999 by
* id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
* Copyright (C) 1999-2000 by
* Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* DESCRIPTION:
* Map utility functions
*
*-----------------------------------------------------------------------------*/
#ifndef __P_MAPUTL__
#define __P_MAPUTL__
#include "r_defs.h"
/* mapblocks are used to check movement against lines and things */
#define MAPBLOCKUNITS 128
#define MAPBLOCKSIZE (MAPBLOCKUNITS*FRACUNIT)
#define MAPBLOCKSHIFT (FRACBITS+7)
#define MAPBMASK (MAPBLOCKSIZE-1)
#define MAPBTOFRAC (MAPBLOCKSHIFT-FRACBITS)
#define PT_ADDLINES 1
#define PT_ADDTHINGS 2
#define PT_EARLYOUT 4
typedef struct {
fixed_t x;
fixed_t y;
fixed_t dx;
fixed_t dy;
} divline_t;
typedef struct {
fixed_t frac; /* along trace line */
boolean isaline;
union {
mobj_t* thing;
line_t* line;
} d;
} intercept_t;
typedef boolean (*traverser_t)(intercept_t *in);
#define CONSTFUNC
fixed_t CONSTFUNC P_AproxDistance (fixed_t dx, fixed_t dy);
int CONSTFUNC P_PointOnLineSide (fixed_t x, fixed_t y, const line_t *line);
int CONSTFUNC P_PointOnDivlineSide (fixed_t x, fixed_t y,
const divline_t *line);
int CONSTFUNC P_BoxOnLineSide (const fixed_t *tmbox, const line_t *ld);
fixed_t CONSTFUNC P_InterceptVector (const divline_t *v2, const divline_t *v1);
void P_MakeDivline (const line_t *li, divline_t *dl);
void P_LineOpening (const line_t *linedef);
void P_UnsetThingPosition(mobj_t *thing);
void P_SetThingPosition(mobj_t *thing);
boolean P_BlockLinesIterator (int x, int y, boolean func(line_t *));
boolean P_BlockThingsIterator(int x, int y, boolean func(mobj_t *));
boolean CONSTFUNC ThingIsOnLine(const mobj_t *t, const line_t *l); /* killough 3/15/98 */
boolean P_PathTraverse(fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2,
int flags, boolean trav(intercept_t *));
extern fixed_t opentop;
extern fixed_t openbottom;
extern fixed_t openrange;
extern fixed_t lowfloor;
extern divline_t trace;
#endif /* __P_MAPUTL__ */

1394
apps/plugins/doom/p_mobj.c Normal file

File diff suppressed because it is too large Load diff

409
apps/plugins/doom/p_mobj.h Normal file
View file

@ -0,0 +1,409 @@
/* Emacs style mode select -*- C++ -*-
*-----------------------------------------------------------------------------
*
*
* PrBoom a Doom port merged with LxDoom and LSDLDoom
* based on BOOM, a modified and improved DOOM engine
* Copyright (C) 1999 by
* id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
* Copyright (C) 1999-2000 by
* Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* DESCRIPTION:
* Map Objects, MObj, definition and handling.
*
*-----------------------------------------------------------------------------*/
#ifndef __P_MOBJ__
#define __P_MOBJ__
// Basics.
#include "tables.h"
#include "m_fixed.h"
// We need the thinker_t stuff.
#include "d_think.h"
// We need the WAD data structure for Map things,
// from the THINGS lump.
#include "doomdata.h"
// States are tied to finite states are
// tied to animation frames.
// Needs precompiled tables/data structures.
#include "info.h"
//
// NOTES: mobj_t
//
// mobj_ts are used to tell the refresh where to draw an image,
// tell the world simulation when objects are contacted,
// and tell the sound driver how to position a sound.
//
// The refresh uses the next and prev links to follow
// lists of things in sectors as they are being drawn.
// The sprite, frame, and angle elements determine which patch_t
// is used to draw the sprite if it is visible.
// The sprite and frame values are allmost allways set
// from state_t structures.
// The statescr.exe utility generates the states.h and states.c
// files that contain the sprite/frame numbers from the
// statescr.txt source file.
// The xyz origin point represents a point at the bottom middle
// of the sprite (between the feet of a biped).
// This is the default origin position for patch_ts grabbed
// with lumpy.exe.
// A walking creature will have its z equal to the floor
// it is standing on.
//
// The sound code uses the x,y, and subsector fields
// to do stereo positioning of any sound effited by the mobj_t.
//
// The play simulation uses the blocklinks, x,y,z, radius, height
// to determine when mobj_ts are touching each other,
// touching lines in the map, or hit by trace lines (gunshots,
// lines of sight, etc).
// The mobj_t->flags element has various bit flags
// used by the simulation.
//
// Every mobj_t is linked into a single sector
// based on its origin coordinates.
// The subsector_t is found with R_PointInSubsector(x,y),
// and the sector_t can be found with subsector->sector.
// The sector links are only used by the rendering code,
// the play simulation does not care about them at all.
//
// Any mobj_t that needs to be acted upon by something else
// in the play world (block movement, be shot, etc) will also
// need to be linked into the blockmap.
// If the thing has the MF_NOBLOCK flag set, it will not use
// the block links. It can still interact with other things,
// but only as the instigator (missiles will run into other
// things, but nothing can run into a missile).
// Each block in the grid is 128*128 units, and knows about
// every line_t that it contains a piece of, and every
// interactable mobj_t that has its origin contained.
//
// A valid mobj_t is a mobj_t that has the proper subsector_t
// filled in for its xy coordinates and is linked into the
// sector from which the subsector was made, or has the
// MF_NOSECTOR flag set (the subsector_t needs to be valid
// even if MF_NOSECTOR is set), and is linked into a blockmap
// block or has the MF_NOBLOCKMAP flag set.
// Links should only be modified by the P_[Un]SetThingPosition()
// functions.
// Do not change the MF_NO? flags while a thing is valid.
//
// Any questions?
//
//
// Misc. mobj flags
//
// Call P_SpecialThing when touched.
#define MF_SPECIAL (uint_64_t)(0x0000000000000001LL)
// Blocks.
#define MF_SOLID (uint_64_t)(0x0000000000000002LL)
// Can be hit.
#define MF_SHOOTABLE (uint_64_t)(0x0000000000000004LL)
// Don't use the sector links (invisible but touchable).
#define MF_NOSECTOR (uint_64_t)(0x0000000000000008LL)
// Don't use the blocklinks (inert but displayable)
#define MF_NOBLOCKMAP (uint_64_t)(0x0000000000000010LL)
// Not to be activated by sound, deaf monster.
#define MF_AMBUSH (uint_64_t)(0x0000000000000020LL)
// Will try to attack right back.
#define MF_JUSTHIT (uint_64_t)(0x0000000000000040LL)
// Will take at least one step before attacking.
#define MF_JUSTATTACKED (uint_64_t)(0x0000000000000080LL)
// On level spawning (initial position),
// hang from ceiling instead of stand on floor.
#define MF_SPAWNCEILING (uint_64_t)(0x0000000000000100LL)
// Don't apply gravity (every tic),
// that is, object will float, keeping current height
// or changing it actively.
#define MF_NOGRAVITY (uint_64_t)(0x0000000000000200LL)
// Movement flags.
// This allows jumps from high places.
#define MF_DROPOFF (uint_64_t)(0x0000000000000400LL)
// For players, will pick up items.
#define MF_PICKUP (uint_64_t)(0x0000000000000800LL)
// Player cheat. ???
#define MF_NOCLIP (uint_64_t)(0x0000000000001000LL)
// Player: keep info about sliding along walls.
#define MF_SLIDE (uint_64_t)(0x0000000000002000LL)
// Allow moves to any height, no gravity.
// For active floaters, e.g. cacodemons, pain elementals.
#define MF_FLOAT (uint_64_t)(0x0000000000004000LL)
// Don't cross lines
// ??? or look at heights on teleport.
#define MF_TELEPORT (uint_64_t)(0x0000000000008000LL)
// Don't hit same species, explode on block.
// Player missiles as well as fireballs of various kinds.
#define MF_MISSILE (uint_64_t)(0x0000000000010000LL)
// Dropped by a demon, not level spawned.
// E.g. ammo clips dropped by dying former humans.
#define MF_DROPPED (uint_64_t)(0x0000000000020000LL)
// Use fuzzy draw (shadow demons or spectres),
// temporary player invisibility powerup.
#define MF_SHADOW (uint_64_t)(0x0000000000040000LL)
// Flag: don't bleed when shot (use puff),
// barrels and shootable furniture shall not bleed.
#define MF_NOBLOOD (uint_64_t)(0x0000000000080000LL)
// Don't stop moving halfway off a step,
// that is, have dead bodies slide down all the way.
#define MF_CORPSE (uint_64_t)(0x0000000000100000LL)
// Floating to a height for a move, ???
// don't auto float to target's height.
#define MF_INFLOAT (uint_64_t)(0x0000000000200000LL)
// On kill, count this enemy object
// towards intermission kill total.
// Happy gathering.
#define MF_COUNTKILL (uint_64_t)(0x0000000000400000LL)
// On picking up, count this item object
// towards intermission item total.
#define MF_COUNTITEM (uint_64_t)(0x0000000000800000LL)
// Special handling: skull in flight.
// Neither a cacodemon nor a missile.
#define MF_SKULLFLY (uint_64_t)(0x0000000001000000LL)
// Don't spawn this object
// in death match mode (e.g. key cards).
#define MF_NOTDMATCH (uint_64_t)(0x0000000002000000LL)
// Player sprites in multiplayer modes are modified
// using an internal color lookup table for re-indexing.
// If 0x4 0x8 or 0xc,
// use a translation table for player colormaps
#define MF_TRANSLATION (uint_64_t)(0x000000000c000000LL)
#define MF_TRANSLATION1 (uint_64_t)(0x0000000004000000LL)
#define MF_TRANSLATION2 (uint_64_t)(0x0000000008000000LL)
// Hmm ???.
#define MF_TRANSSHIFT 26
// proff 11/19/98: Andy Baker's stealth monsters - unused yet
//Stealth Mode - Creatures that dissappear and reappear.
#define MF_STEALTH (uint_64_t)(0x0000000010000000LL)
// proff 11/19/98: 3 (4 counting opaque) levels of translucency
// not very good to set the next one in this enum, should be seperate
#define MF_TRANSLUCBITS (uint_64_t)(0x0000000060000000LL)
#define MF_TRANSLUC25 (uint_64_t)(0x0000000020000000LL)
#define MF_TRANSLUC50 (uint_64_t)(0x0000000040000000LL)
#define MF_TRANSLUC75 (uint_64_t)(0x0000000060000000LL)
// Translucent sprite? // phares
#define MF_TRANSLUCENT (uint_64_t)(0x0000000040000000LL)
// these are greater than an int. That's why the flags below are now uint_64_t
#define MF_TOUCHY (uint_64_t)(0x0000000100000000LL)
#define MF_BOUNCES (uint_64_t)(0x0000000200000000LL)
#define MF_FRIEND (uint_64_t)(0x0000000400000000LL)
// killough 9/15/98: Same, but internal flags, not intended for .deh
// (some degree of opaqueness is good, to avoid compatibility woes)
enum {
MIF_FALLING = 1, // Object is falling
MIF_ARMED = 2, // Object is armed (for MF_TOUCHY objects)
};
// Map Object definition.
//
// killough 2/20/98:
//
// WARNING: Special steps must be taken in p_saveg.c if C pointers are added to
// this mobj_s struct, or else savegames will crash when loaded. See p_saveg.c.
// Do not add "struct mobj_s *fooptr" without adding code to p_saveg.c to
// convert the pointers to ordinals and back for savegames. This was the whole
// reason behind monsters going to sleep when loading savegames (the "target"
// pointer was simply nullified after loading, to prevent Doom from crashing),
// and the whole reason behind loadgames crashing on savegames of AV attacks.
//
// killough 9/8/98: changed some fields to shorts,
// for better memory usage (if only for cache).
typedef struct mobj_s
{
// List: thinker links.
thinker_t thinker;
// Info for drawing: position.
fixed_t x;
fixed_t y;
fixed_t z;
// More list: links in sector (if needed)
struct mobj_s* snext;
struct mobj_s** sprev; // killough 8/10/98: change to ptr-to-ptr
//More drawing info: to determine current sprite.
angle_t angle; // orientation
spritenum_t sprite; // used to find patch_t and flip value
int frame; // might be ORed with FF_FULLBRIGHT
// Interaction info, by BLOCKMAP.
// Links in blocks (if needed).
struct mobj_s* bnext;
struct mobj_s** bprev; // killough 8/11/98: change to ptr-to-ptr
struct subsector_s* subsector;
// The closest interval over all contacted Sectors.
fixed_t floorz;
fixed_t ceilingz;
// killough 11/98: the lowest floor over all contacted Sectors.
fixed_t dropoffz;
// For movement checking.
fixed_t radius;
fixed_t height;
// Momentums, used to update position.
fixed_t momx;
fixed_t momy;
fixed_t momz;
// If == validcount, already checked.
int validcount;
mobjtype_t type;
mobjinfo_t* info; // &mobjinfo[mobj->type]
int tics; // state tic counter
state_t* state;
uint_64_t flags;
int intflags; // killough 9/15/98: internal flags
int health;
// Movement direction, movement generation (zig-zagging).
short movedir; // 0-7
short movecount; // when 0, select a new dir
short strafecount; // killough 9/8/98: monster strafing
// Thing being chased/attacked (or NULL),
// also the originator for missiles.
struct mobj_s* target;
// Reaction time: if non 0, don't attack yet.
// Used by player to freeze a bit after teleporting.
short reactiontime;
// If >0, the current target will be chased no
// matter what (even if shot by another object)
short threshold;
// killough 9/9/98: How long a monster pursues a target.
short pursuecount;
short gear; // killough 11/98: used in torque simulation
// Additional info record for player avatars only.
// Only valid if type == MT_PLAYER
struct player_s* player;
// Player number last looked for.
short lastlook;
// For nightmare respawn.
mapthing_t spawnpoint;
// Thing being chased/attacked for tracers.
struct mobj_s* tracer;
//proff 11/22/98: Andy Baker's stealth monsters
boolean invisible;
// new field: last known enemy -- killough 2/15/98
struct mobj_s* lastenemy;
// Are we above a Thing? above_thing points to the Thing // phares
// if so, otherwise it's zero. // |
// V
struct mobj_s* above_thing;
// Are we below a Thing? below_thing points to the Thing
// if so, otherwise it's zero.
// ^
struct mobj_s* below_thing; // |
// phares
// killough 8/2/98: friction properties part of sectors,
// not objects -- removed friction properties from here
// a linked list of sectors where this object appears
struct msecnode_s* touching_sectorlist; // phares 3/14/98
// SEE WARNING ABOVE ABOUT POINTER FIELDS!!!
} mobj_t;
// External declarations (fomerly in p_local.h) -- killough 5/2/98
#define VIEWHEIGHT (41*FRACUNIT)
#define PLAYERRADIUS (16*FRACUNIT)
#define GRAVITY FRACUNIT
#define MAXMOVE (30*FRACUNIT)
#define ONFLOORZ INT_MIN
#define ONCEILINGZ INT_MAX
// Time interval for item respawning.
#define ITEMQUESIZE 128
#define FLOATSPEED (FRACUNIT*4)
#define STOPSPEED (FRACUNIT/16)
// killough 11/98:
// For torque simulation:
#define OVERDRIVE 6
#define MAXGEAR (OVERDRIVE+16)
// killough 11/98:
// Whether an object is "sentient" or not. Used for environmental influences.
#define sentient(mobj) ((mobj)->health > 0 && (mobj)->info->seestate)
extern mapthing_t itemrespawnque[];
extern int itemrespawntime[];
extern int iquehead;
extern int iquetail;
void P_RespawnSpecials(void);
mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type);
void P_RemoveMobj(mobj_t *th);
boolean P_SetMobjState(mobj_t *mobj, statenum_t state);
void P_MobjThinker(mobj_t *mobj);
void P_SpawnPuff(fixed_t x, fixed_t y, fixed_t z);
void P_SpawnBlood(fixed_t x, fixed_t y, fixed_t z, int damage);
mobj_t *P_SpawnMissile(mobj_t *source, mobj_t *dest, mobjtype_t type);
void P_SpawnPlayerMissile(mobj_t *source, mobjtype_t type);
void P_SpawnMapThing (mapthing_t* mthing);
void P_CheckMissileSpawn(mobj_t*); // killough 8/2/98
void P_ExplodeMissile(mobj_t*); // killough
#endif

434
apps/plugins/doom/p_plats.c Normal file
View file

@ -0,0 +1,434 @@
/* Emacs style mode select -*- C++ -*-
*-----------------------------------------------------------------------------
*
*
* PrBoom a Doom port merged with LxDoom and LSDLDoom
* based on BOOM, a modified and improved DOOM engine
* Copyright (C) 1999 by
* id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
* Copyright (C) 1999-2000 by
* Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* DESCRIPTION:
* Plats (i.e. elevator platforms) code, raising/lowering.
*
*-----------------------------------------------------------------------------*/
#include "doomstat.h"
#include "m_random.h"
#include "r_main.h"
#include "p_spec.h"
#include "p_tick.h"
#include "s_sound.h"
#include "sounds.h"
#include "rockmacros.h"
platlist_t *activeplats; // killough 2/14/98: made global again
//
// T_PlatRaise()
//
// Action routine to move a plat up and down
//
// Passed a plat structure containing all pertinent information about the move
// No return
//
// jff 02/08/98 all cases with labels beginning with gen added to support
// generalized line type behaviors.
void T_PlatRaise(plat_t* plat)
{
result_e res;
// handle plat moving, up, down, waiting, or in stasis,
switch(plat->status)
{
case up: // plat moving up
res = T_MovePlane(plat->sector,plat->speed,plat->high,plat->crush,0,1);
// if a pure raise type, make the plat moving sound
if (plat->type == raiseAndChange
|| plat->type == raiseToNearestAndChange)
{
if (!(leveltime&7))
S_StartSound((mobj_t *)&plat->sector->soundorg, sfx_stnmov);
}
// if encountered an obstacle, and not a crush type, reverse direction
if (res == crushed && (!plat->crush))
{
plat->count = plat->wait;
plat->status = down;
S_StartSound((mobj_t *)&plat->sector->soundorg, sfx_pstart);
}
else // else handle reaching end of up stroke
{
if (res == pastdest) // end of stroke
{
// if not an instant toggle type, wait, make plat stop sound
if (plat->type!=toggleUpDn)
{
plat->count = plat->wait;
plat->status = waiting;
S_StartSound((mobj_t *)&plat->sector->soundorg, sfx_pstop);
}
else // else go into stasis awaiting next toggle activation
{
plat->oldstatus = plat->status;//jff 3/14/98 after action wait
plat->status = in_stasis; //for reactivation of toggle
}
// lift types and pure raise types are done at end of up stroke
// only the perpetual type waits then goes back up
switch(plat->type)
{
case blazeDWUS:
case downWaitUpStay:
case raiseAndChange:
case raiseToNearestAndChange:
case genLift:
P_RemoveActivePlat(plat); // killough
default:
break;
}
}
}
break;
case down: // plat moving down
res = T_MovePlane(plat->sector,plat->speed,plat->low,false,0,-1);
// handle reaching end of down stroke
if (res == pastdest)
{
// if not an instant toggle, start waiting, make plat stop sound
if (plat->type!=toggleUpDn) //jff 3/14/98 toggle up down
{ // is silent, instant, no waiting
plat->count = plat->wait;
plat->status = waiting;
S_StartSound((mobj_t *)&plat->sector->soundorg,sfx_pstop);
}
else // instant toggles go into stasis awaiting next activation
{
plat->oldstatus = plat->status;//jff 3/14/98 after action wait
plat->status = in_stasis; //for reactivation of toggle
}
//jff 1/26/98 remove the plat if it bounced so it can be tried again
//only affects plats that raise and bounce
//killough 1/31/98: relax compatibility to demo_compatibility
// remove the plat if its a pure raise type
if (!comp[comp_floors])
{
switch(plat->type)
{
case raiseAndChange:
case raiseToNearestAndChange:
P_RemoveActivePlat(plat);
default:
break;
}
}
}
break;
case waiting: // plat is waiting
if (!--plat->count) // downcount and check for delay elapsed
{
if (plat->sector->floorheight == plat->low)
plat->status = up; // if at bottom, start up
else
plat->status = down; // if at top, start down
// make plat start sound
S_StartSound((mobj_t *)&plat->sector->soundorg,sfx_pstart);
}
break; //jff 1/27/98 don't pickup code added later to in_stasis
case in_stasis: // do nothing if in stasis
break;
}
}
//
// EV_DoPlat
//
// Handle Plat linedef types
//
// Passed the linedef that activated the plat, the type of plat action,
// and for some plat types, an amount to raise
// Returns true if a thinker is started, or restarted from stasis
//
int EV_DoPlat
( line_t* line,
plattype_e type,
int amount )
{
plat_t* plat;
int secnum;
int rtn;
sector_t* sec;
secnum = -1;
rtn = 0;
// Activate all <type> plats that are in_stasis
switch(type)
{
case perpetualRaise:
P_ActivateInStasis(line->tag);
break;
case toggleUpDn:
P_ActivateInStasis(line->tag);
rtn=1;
break;
default:
break;
}
// act on all sectors tagged the same as the activating linedef
while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0)
{
sec = &sectors[secnum];
// don't start a second floor function if already moving
if (P_SectorActive(floor_special,sec)) //jff 2/23/98 multiple thinkers
continue;
// Create a thinker
rtn = 1;
plat = Z_Malloc( sizeof(*plat), PU_LEVSPEC, 0);
P_AddThinker(&plat->thinker);
plat->type = type;
plat->sector = sec;
plat->sector->floordata = plat; //jff 2/23/98 multiple thinkers
plat->thinker.function = T_PlatRaise;
plat->crush = false;
plat->tag = line->tag;
//jff 1/26/98 Avoid raise plat bouncing a head off a ceiling and then
//going down forever -- default low to plat height when triggered
plat->low = sec->floorheight;
// set up plat according to type
switch(type)
{
case raiseToNearestAndChange:
plat->speed = PLATSPEED/2;
sec->floorpic = sides[line->sidenum[0]].sector->floorpic;
plat->high = P_FindNextHighestFloor(sec,sec->floorheight);
plat->wait = 0;
plat->status = up;
sec->special = 0;
//jff 3/14/98 clear old field as well
sec->oldspecial = 0;
S_StartSound((mobj_t *)&sec->soundorg,sfx_stnmov);
break;
case raiseAndChange:
plat->speed = PLATSPEED/2;
sec->floorpic = sides[line->sidenum[0]].sector->floorpic;
plat->high = sec->floorheight + amount*FRACUNIT;
plat->wait = 0;
plat->status = up;
S_StartSound((mobj_t *)&sec->soundorg,sfx_stnmov);
break;
case downWaitUpStay:
plat->speed = PLATSPEED * 4;
plat->low = P_FindLowestFloorSurrounding(sec);
if (plat->low > sec->floorheight)
plat->low = sec->floorheight;
plat->high = sec->floorheight;
plat->wait = 35*PLATWAIT;
plat->status = down;
S_StartSound((mobj_t *)&sec->soundorg,sfx_pstart);
break;
case blazeDWUS:
plat->speed = PLATSPEED * 8;
plat->low = P_FindLowestFloorSurrounding(sec);
if (plat->low > sec->floorheight)
plat->low = sec->floorheight;
plat->high = sec->floorheight;
plat->wait = 35*PLATWAIT;
plat->status = down;
S_StartSound((mobj_t *)&sec->soundorg,sfx_pstart);
break;
case perpetualRaise:
plat->speed = PLATSPEED;
plat->low = P_FindLowestFloorSurrounding(sec);
if (plat->low > sec->floorheight)
plat->low = sec->floorheight;
plat->high = P_FindHighestFloorSurrounding(sec);
if (plat->high < sec->floorheight)
plat->high = sec->floorheight;
plat->wait = 35*PLATWAIT;
plat->status = P_Random(pr_plats)&1;
S_StartSound((mobj_t *)&sec->soundorg,sfx_pstart);
break;
case toggleUpDn: //jff 3/14/98 add new type to support instant toggle
plat->speed = PLATSPEED; //not used
plat->wait = 35*PLATWAIT; //not used
plat->crush = true; //jff 3/14/98 crush anything in the way
// set up toggling between ceiling, floor inclusive
plat->low = sec->ceilingheight;
plat->high = sec->floorheight;
plat->status = down;
break;
default:
break;
}
P_AddActivePlat(plat); // add plat to list of active plats
}
return rtn;
}
// The following were all rewritten by Lee Killough
// to use the new structure which places no limits
// on active plats. It also avoids spending as much
// time searching for active plats. Previously a
// fixed-size array was used, with NULL indicating
// empty entries, while now a doubly-linked list
// is used.
//
// P_ActivateInStasis()
//
// Activate a plat that has been put in stasis
// (stopped perpetual floor, instant floor/ceil toggle)
//
// Passed the tag of the plat that should be reactivated
// Returns nothing
//
void P_ActivateInStasis(int tag)
{
platlist_t *pl;
for (pl=activeplats; pl; pl=pl->next) // search the active plats
{
plat_t *plat = pl->plat; // for one in stasis with right tag
if (plat->tag == tag && plat->status == in_stasis)
{
if (plat->type==toggleUpDn) //jff 3/14/98 reactivate toggle type
plat->status = plat->oldstatus==up? down : up;
else
plat->status = plat->oldstatus;
plat->thinker.function = T_PlatRaise;
}
}
}
//
// EV_StopPlat()
//
// Handler for "stop perpetual floor" linedef type
//
// Passed the linedef that stopped the plat
// Returns true if a plat was put in stasis
//
// jff 2/12/98 added int return value, fixed return
//
int EV_StopPlat(line_t* line)
{
platlist_t *pl;
for (pl=activeplats; pl; pl=pl->next) // search the active plats
{
plat_t *plat = pl->plat; // for one with the tag not in stasis
if (plat->status != in_stasis && plat->tag == line->tag)
{
plat->oldstatus = plat->status; // put it in stasis
plat->status = in_stasis;
plat->thinker.function = NULL;
}
}
return 1;
}
//
// P_AddActivePlat()
//
// Add a plat to the head of the active plat list
//
// Passed a pointer to the plat to add
// Returns nothing
//
void P_AddActivePlat(plat_t* plat)
{
platlist_t *list = malloc(sizeof *list);
list->plat = plat;
plat->list = list;
if ((list->next = activeplats))
list->next->prev = &list->next;
list->prev = &activeplats;
activeplats = list;
}
//
// P_RemoveActivePlat()
//
// Remove a plat from the active plat list
//
// Passed a pointer to the plat to remove
// Returns nothing
//
void P_RemoveActivePlat(plat_t* plat)
{
platlist_t *list = plat->list;
plat->sector->floordata = NULL; //jff 2/23/98 multiple thinkers
P_RemoveThinker(&plat->thinker);
if ((*list->prev = list->next))
list->next->prev = list->prev;
free(list);
}
//
// P_RemoveAllActivePlats()
//
// Remove all plats from the active plat list
//
// Passed nothing, returns nothing
//
void P_RemoveAllActivePlats(void)
{
while (activeplats)
{
platlist_t *next = activeplats->next;
free(activeplats);
activeplats = next;
}
}

853
apps/plugins/doom/p_pspr.c Normal file
View file

@ -0,0 +1,853 @@
/* Emacs style mode select -*- C++ -*-
*-----------------------------------------------------------------------------
*
*
* PrBoom a Doom port merged with LxDoom and LSDLDoom
* based on BOOM, a modified and improved DOOM engine
* Copyright (C) 1999 by
* id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
* Copyright (C) 1999-2000 by
* Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* DESCRIPTION:
* Weapon sprite animation, weapon objects.
* Action functions for weapons.
*
*-----------------------------------------------------------------------------*/
#include "doomstat.h"
#include "r_main.h"
#include "p_map.h"
#include "p_inter.h"
#include "p_pspr.h"
#include "p_enemy.h"
#include "m_random.h"
#include "s_sound.h"
#include "sounds.h"
#include "d_event.h"
#include "rockmacros.h"
#define LOWERSPEED (FRACUNIT*6)
#define RAISESPEED (FRACUNIT*6)
#define WEAPONBOTTOM (FRACUNIT*128)
#define WEAPONTOP (FRACUNIT*32)
// plasma cells for a bfg attack
#define BFGCELLS 40
//#define BFGCELLS bfgcells /* Ty 03/09/98 externalized in p_inter.c */
extern void P_Thrust(player_t *, angle_t, fixed_t);
// The following array holds the recoil values // phares
static const int recoil_values[] = { // phares
10, // wp_fist
10, // wp_pistol
30, // wp_shotgun
10, // wp_chaingun
100,// wp_missile
20, // wp_plasma
100,// wp_bfg
0, // wp_chainsaw
80 // wp_supershotgun
};
//
// P_SetPsprite
//
static void P_SetPsprite(player_t *player, int position, statenum_t stnum)
{
pspdef_t *psp = &player->psprites[position];
do
{
state_t *state;
if (!stnum)
{
// object removed itself
psp->state = NULL;
break;
}
state = &states[stnum];
psp->state = state;
psp->tics = state->tics; // could be 0
if (state->misc1)
{
// coordinate set
psp->sx = state->misc1 << FRACBITS;
psp->sy = state->misc2 << FRACBITS;
}
// Call action routine.
// Modified handling.
if (state->action)
{
state->action(player, psp);
if (!psp->state)
break;
}
stnum = psp->state->nextstate;
}
while (!psp->tics); // an initial state of 0 could cycle through
}
//
// P_BringUpWeapon
// Starts bringing the pending weapon up
// from the bottom of the screen.
// Uses player
//
static void P_BringUpWeapon(player_t *player)
{
statenum_t newstate;
if (player->pendingweapon == wp_nochange)
player->pendingweapon = player->readyweapon;
if (player->pendingweapon == wp_chainsaw)
S_StartSound (player->mo, sfx_sawup);
newstate = weaponinfo[player->pendingweapon].upstate;
player->pendingweapon = wp_nochange;
// killough 12/98: prevent pistol from starting visibly at bottom of screen:
player->psprites[ps_weapon].sy =
mbf_features ? WEAPONBOTTOM+FRACUNIT*2 : WEAPONBOTTOM;
P_SetPsprite(player, ps_weapon, newstate);
}
// The first set is where the weapon preferences from // killough,
// default.cfg are stored. These values represent the keys used // phares
// in DOOM2 to bring up the weapon, i.e. 6 = plasma gun. These // |
// are NOT the wp_* constants. // V
int weapon_preferences[2][NUMWEAPONS+1] = {
{6, 9, 4, 3, 2, 8, 5, 7, 1, 0}, // !compatibility preferences
{6, 9, 4, 3, 2, 8, 5, 7, 1, 0}, // compatibility preferences
};
// P_SwitchWeapon checks current ammo levels and gives you the
// most preferred weapon with ammo. It will not pick the currently
// raised weapon. When called from P_CheckAmmo this won't matter,
// because the raised weapon has no ammo anyway. When called from
// G_BuildTiccmd you want to toggle to a different weapon regardless.
int P_SwitchWeapon(player_t *player)
{
int *prefer = weapon_preferences[demo_compatibility!=0]; // killough 3/22/98
int currentweapon = player->readyweapon;
int newweapon = currentweapon;
int i = NUMWEAPONS+1; // killough 5/2/98
// killough 2/8/98: follow preferences and fix BFG/SSG bugs
do
switch (*prefer++)
{
case 1:
if (!player->powers[pw_strength]) // allow chainsaw override
break;
case 0:
newweapon = wp_fist;
break;
case 2:
if (player->ammo[am_clip])
newweapon = wp_pistol;
break;
case 3:
if (player->weaponowned[wp_shotgun] && player->ammo[am_shell])
newweapon = wp_shotgun;
break;
case 4:
if (player->weaponowned[wp_chaingun] && player->ammo[am_clip])
newweapon = wp_chaingun;
break;
case 5:
if (player->weaponowned[wp_missile] && player->ammo[am_misl])
newweapon = wp_missile;
break;
case 6:
if (player->weaponowned[wp_plasma] && player->ammo[am_cell] &&
gamemode != shareware)
newweapon = wp_plasma;
break;
case 7:
if (player->weaponowned[wp_bfg] && gamemode != shareware &&
player->ammo[am_cell] >= (demo_compatibility ? 41 : 40))
newweapon = wp_bfg;
break;
case 8:
if (player->weaponowned[wp_chainsaw])
newweapon = wp_chainsaw;
break;
case 9:
if (player->weaponowned[wp_supershotgun] && gamemode == commercial &&
player->ammo[am_shell] >= (demo_compatibility ? 3 : 2))
newweapon = wp_supershotgun;
break;
}
while (newweapon==currentweapon && --i); // killough 5/2/98
return newweapon;
}
// killough 5/2/98: whether consoleplayer prefers weapon w1 over weapon w2.
int P_WeaponPreferred(int w1, int w2)
{
return
(weapon_preferences[0][0] != ++w2 && (weapon_preferences[0][0] == ++w1 ||
(weapon_preferences[0][1] != w2 && (weapon_preferences[0][1] == w1 ||
(weapon_preferences[0][2] != w2 && (weapon_preferences[0][2] == w1 ||
(weapon_preferences[0][3] != w2 && (weapon_preferences[0][3] == w1 ||
(weapon_preferences[0][4] != w2 && (weapon_preferences[0][4] == w1 ||
(weapon_preferences[0][5] != w2 && (weapon_preferences[0][5] == w1 ||
(weapon_preferences[0][6] != w2 && (weapon_preferences[0][6] == w1 ||
(weapon_preferences[0][7] != w2 && (weapon_preferences[0][7] == w1
))))))))))))))));
}
//
// P_CheckAmmo
// Returns true if there is enough ammo to shoot.
// If not, selects the next weapon to use.
// (only in demo_compatibility mode -- killough 3/22/98)
//
boolean P_CheckAmmo(player_t *player)
{
ammotype_t ammo = weaponinfo[player->readyweapon].ammo;
int count = 1; // Regular
if (player->readyweapon == wp_bfg) // Minimal amount for one shot varies.
count = BFGCELLS;
else
if (player->readyweapon == wp_supershotgun) // Double barrel.
count = 2;
// Some do not need ammunition anyway.
// Return if current ammunition sufficient.
if (ammo == am_noammo || player->ammo[ammo] >= count)
return true;
// Out of ammo, pick a weapon to change to.
//
// killough 3/22/98: for old demos we do the switch here and now;
// for Boom games we cannot do this, and have different player
// preferences across demos or networks, so we have to use the
// G_BuildTiccmd() interface instead of making the switch here.
if (demo_compatibility)
{
player->pendingweapon = P_SwitchWeapon(player); // phares
// Now set appropriate weapon overlay.
P_SetPsprite(player,ps_weapon,weaponinfo[player->readyweapon].downstate);
}
return false;
}
//
// P_FireWeapon.
//
int lastshottic; // killough 3/22/98
static void P_FireWeapon(player_t *player)
{
statenum_t newstate;
if (!P_CheckAmmo(player))
return;
P_SetMobjState(player->mo, S_PLAY_ATK1);
newstate = weaponinfo[player->readyweapon].atkstate;
P_SetPsprite(player, ps_weapon, newstate);
P_NoiseAlert(player->mo, player->mo);
lastshottic = gametic; // killough 3/22/98
}
//
// P_DropWeapon
// Player died, so put the weapon away.
//
void P_DropWeapon(player_t *player)
{
P_SetPsprite(player, ps_weapon, weaponinfo[player->readyweapon].downstate);
}
//
// A_WeaponReady
// The player can fire the weapon
// or change to another weapon at this time.
// Follows after getting weapon up,
// or after previous attack/fire sequence.
//
void A_WeaponReady(player_t *player, pspdef_t *psp)
{
// get out of attack state
if (player->mo->state == &states[S_PLAY_ATK1]
|| player->mo->state == &states[S_PLAY_ATK2] )
P_SetMobjState(player->mo, S_PLAY);
if (player->readyweapon == wp_chainsaw && psp->state == &states[S_SAW])
S_StartSound(player->mo, sfx_sawidl);
// check for change
// if player is dead, put the weapon away
if (player->pendingweapon != wp_nochange || !player->health)
{
// change weapon (pending weapon should already be validated)
statenum_t newstate = weaponinfo[player->readyweapon].downstate;
P_SetPsprite(player, ps_weapon, newstate);
return;
}
// check for fire
// the missile launcher and bfg do not auto fire
if (player->cmd.buttons & BT_ATTACK)
{
if (!player->attackdown || (player->readyweapon != wp_missile &&
player->readyweapon != wp_bfg))
{
player->attackdown = true;
P_FireWeapon(player);
return;
}
}
else
player->attackdown = false;
// bob the weapon based on movement speed
{
int angle = (128*leveltime) & FINEMASK;
psp->sx = FRACUNIT + FixedMul(player->bob, finecosine[angle]);
angle &= FINEANGLES/2-1;
psp->sy = WEAPONTOP + FixedMul(player->bob, finesine[angle]);
}
}
//
// A_ReFire
// The player can re-fire the weapon
// without lowering it entirely.
//
void A_ReFire(player_t *player, pspdef_t *psp)
{
(void)psp;
// check for fire
// (if a weaponchange is pending, let it go through instead)
if ( (player->cmd.buttons & BT_ATTACK)
&& player->pendingweapon == wp_nochange && player->health)
{
player->refire++;
P_FireWeapon(player);
}
else
{
player->refire = 0;
P_CheckAmmo(player);
}
}
void A_CheckReload(player_t *player, pspdef_t *psp)
{
(void)psp;
P_CheckAmmo(player);
}
//
// A_Lower
// Lowers current weapon,
// and changes weapon at bottom.
//
void A_Lower(player_t *player, pspdef_t *psp)
{
psp->sy += LOWERSPEED;
// Is already down.
if (psp->sy < WEAPONBOTTOM)
return;
// Player is dead.
if (player->playerstate == PST_DEAD)
{
psp->sy = WEAPONBOTTOM;
return; // don't bring weapon back up
}
// The old weapon has been lowered off the screen,
// so change the weapon and start raising it
if (!player->health)
{ // Player is dead, so keep the weapon off screen.
P_SetPsprite(player, ps_weapon, S_NULL);
return;
}
player->readyweapon = player->pendingweapon;
P_BringUpWeapon(player);
}
//
// A_Raise
//
void A_Raise(player_t *player, pspdef_t *psp)
{
statenum_t newstate;
psp->sy -= RAISESPEED;
if (psp->sy > WEAPONTOP)
return;
psp->sy = WEAPONTOP;
// The weapon has been raised all the way,
// so change to the ready state.
newstate = weaponinfo[player->readyweapon].readystate;
P_SetPsprite(player, ps_weapon, newstate);
}
// Weapons now recoil, amount depending on the weapon. // phares
// // |
// The P_SetPsprite call in each of the weapon firing routines // V
// was moved here so the recoil could be synched with the
// muzzle flash, rather than the pressing of the trigger.
// The BFG delay caused this to be necessary.
static void A_FireSomething(player_t* player,int adder)
{
P_SetPsprite(player, ps_flash,
weaponinfo[player->readyweapon].flashstate+adder);
// killough 3/27/98: prevent recoil in no-clipping mode
if (!(player->mo->flags & MF_NOCLIP))
if (!compatibility && weapon_recoil)
P_Thrust(player,
ANG180+player->mo->angle, // ^
2048*recoil_values[player->readyweapon]); // |
} // phares
//
// A_GunFlash
//
void A_GunFlash(player_t *player, pspdef_t *psp)
{
(void)psp;
P_SetMobjState(player->mo, S_PLAY_ATK2);
A_FireSomething(player,0); // phares
}
//
// WEAPON ATTACKS
//
//
// A_Punch
//
void A_Punch(player_t *player, pspdef_t *psp)
{
(void)psp;
angle_t angle;
int t, slope, damage = (P_Random(pr_punch)%10+1)<<1;
if (player->powers[pw_strength])
damage *= 10;
angle = player->mo->angle;
// killough 5/5/98: remove dependence on order of evaluation:
t = P_Random(pr_punchangle);
angle += (t - P_Random(pr_punchangle))<<18;
/* killough 8/2/98: make autoaiming prefer enemies */
if (!mbf_features ||
(slope = P_AimLineAttack(player->mo, angle, MELEERANGE, MF_FRIEND),
!linetarget))
slope = P_AimLineAttack(player->mo, angle, MELEERANGE, 0);
P_LineAttack(player->mo, angle, MELEERANGE, slope, damage);
if (!linetarget)
return;
S_StartSound(player->mo, sfx_punch);
// turn to face target
player->mo->angle = R_PointToAngle2(player->mo->x, player->mo->y,
linetarget->x, linetarget->y);
}
//
// A_Saw
//
void A_Saw(player_t *player, pspdef_t *psp)
{
(void)psp;
int slope, damage = 2*(P_Random(pr_saw)%10+1);
angle_t angle = player->mo->angle;
// killough 5/5/98: remove dependence on order of evaluation:
int t = P_Random(pr_saw);
angle += (t - P_Random(pr_saw))<<18;
/* Use meleerange + 1 so that the puff doesn't skip the flash
* killough 8/2/98: make autoaiming prefer enemies */
if (!mbf_features ||
(slope = P_AimLineAttack(player->mo, angle, MELEERANGE+1, MF_FRIEND),
!linetarget))
slope = P_AimLineAttack(player->mo, angle, MELEERANGE+1, 0);
P_LineAttack(player->mo, angle, MELEERANGE+1, slope, damage);
if (!linetarget)
{
S_StartSound(player->mo, sfx_sawful);
return;
}
S_StartSound(player->mo, sfx_sawhit);
// turn to face target
angle = R_PointToAngle2(player->mo->x, player->mo->y,
linetarget->x, linetarget->y);
if (angle - player->mo->angle > ANG180) {
if (angle - player->mo->angle < (unsigned)(-ANG90/20))
player->mo->angle = angle + ANG90/21;
else
player->mo->angle -= ANG90/20;
} else {
if (angle - player->mo->angle > ANG90/20)
player->mo->angle = angle - ANG90/21;
else
player->mo->angle += ANG90/20;
}
player->mo->flags |= MF_JUSTATTACKED;
}
//
// A_FireMissile
//
void A_FireMissile(player_t *player, pspdef_t *psp)
{
(void)psp;
player->ammo[weaponinfo[player->readyweapon].ammo]--;
P_SpawnPlayerMissile(player->mo, MT_ROCKET);
}
//
// A_FireBFG
//
void A_FireBFG(player_t *player, pspdef_t *psp)
{
(void)psp;
player->ammo[weaponinfo[player->readyweapon].ammo] -= BFGCELLS;
P_SpawnPlayerMissile(player->mo, MT_BFG);
}
/*
* A_FireOldBFG
*
* This function emulates Doom's Pre-Beta BFG
* By Lee Killough 6/6/98, 7/11/98, 7/19/98, 8/20/98
*
* This code may not be used in other mods without appropriate credit given.
* Code leeches will be telefragged.
*/
void A_FireOldBFG(player_t *player, pspdef_t *psp)
{
(void)psp;
(void)player;
}
//
// A_FirePlasma
//
void A_FirePlasma(player_t *player, pspdef_t *psp)
{
(void)psp;
player->ammo[weaponinfo[player->readyweapon].ammo]--;
A_FireSomething(player,P_Random(pr_plasma)&1); // phares
P_SpawnPlayerMissile(player->mo, MT_PLASMA);
}
//
// P_BulletSlope
// Sets a slope so a near miss is at aproximately
// the height of the intended target
//
static fixed_t bulletslope;
static void P_BulletSlope(mobj_t *mo)
{
angle_t an = mo->angle; // see which target is to be aimed at
/* killough 8/2/98: make autoaiming prefer enemies */
uint_64_t mask = mbf_features ? MF_FRIEND : 0;
do
{
bulletslope = P_AimLineAttack(mo, an, 16*64*FRACUNIT, mask);
if (!linetarget)
bulletslope = P_AimLineAttack(mo, an += 1<<26, 16*64*FRACUNIT, mask);
if (!linetarget)
bulletslope = P_AimLineAttack(mo, an -= 2<<26, 16*64*FRACUNIT, mask);
}
while (mask && (mask=0, !linetarget)); /* killough 8/2/98 */
}
//
// P_GunShot
//
void P_GunShot(mobj_t *mo, boolean accurate)
{
int damage = 5*(P_Random(pr_gunshot)%3+1);
angle_t angle = mo->angle;
if (!accurate)
{ // killough 5/5/98: remove dependence on order of evaluation:
int t = P_Random(pr_misfire);
angle += (t - P_Random(pr_misfire))<<18;
}
P_LineAttack(mo, angle, MISSILERANGE, bulletslope, damage);
}
//
// A_FirePistol
//
void A_FirePistol(player_t *player, pspdef_t *psp)
{
(void)psp;
S_StartSound(player->mo, sfx_pistol);
P_SetMobjState(player->mo, S_PLAY_ATK2);
player->ammo[weaponinfo[player->readyweapon].ammo]--;
A_FireSomething(player,0); // phares
P_BulletSlope(player->mo);
P_GunShot(player->mo, !player->refire);
}
//
// A_FireShotgun
//
void A_FireShotgun(player_t *player, pspdef_t *psp)
{
(void)psp;
int i;
S_StartSound(player->mo, sfx_shotgn);
P_SetMobjState(player->mo, S_PLAY_ATK2);
player->ammo[weaponinfo[player->readyweapon].ammo]--;
A_FireSomething(player,0); // phares
P_BulletSlope(player->mo);
for (i=0; i<7; i++)
P_GunShot(player->mo, false);
}
//
// A_FireShotgun2
//
void A_FireShotgun2(player_t *player, pspdef_t *psp)
{
(void)psp;
int i;
S_StartSound(player->mo, sfx_dshtgn);
P_SetMobjState(player->mo, S_PLAY_ATK2);
player->ammo[weaponinfo[player->readyweapon].ammo] -= 2;
A_FireSomething(player,0); // phares
P_BulletSlope(player->mo);
for (i=0; i<20; i++)
{
int damage = 5*(P_Random(pr_shotgun)%3+1);
angle_t angle = player->mo->angle;
// killough 5/5/98: remove dependence on order of evaluation:
int t = P_Random(pr_shotgun);
angle += (t - P_Random(pr_shotgun))<<19;
t = P_Random(pr_shotgun);
P_LineAttack(player->mo, angle, MISSILERANGE, bulletslope +
((t - P_Random(pr_shotgun))<<5), damage);
}
}
//
// A_FireCGun
//
void A_FireCGun(player_t *player, pspdef_t *psp)
{
if (player->ammo[weaponinfo[player->readyweapon].ammo] || comp[comp_sound])
S_StartSound(player->mo, sfx_pistol);
if (!player->ammo[weaponinfo[player->readyweapon].ammo])
return;
P_SetMobjState(player->mo, S_PLAY_ATK2);
player->ammo[weaponinfo[player->readyweapon].ammo]--;
A_FireSomething(player,psp->state - &states[S_CHAIN1]); // phares
P_BulletSlope(player->mo);
P_GunShot(player->mo, !player->refire);
}
void A_Light0(player_t *player, pspdef_t *psp)
{
(void)psp;
player->extralight = 0;
}
void A_Light1 (player_t *player, pspdef_t *psp)
{
(void)psp;
player->extralight = 1;
}
void A_Light2 (player_t *player, pspdef_t *psp)
{
(void)psp;
player->extralight = 2;
}
//
// A_BFGSpray
// Spawn a BFG explosion on every monster in view
//
void A_BFGSpray(mobj_t *mo)
{
int i;
for (i=0 ; i<40 ; i++) // offset angles from its attack angle
{
int j, damage;
angle_t an = mo->angle - ANG90/2 + ANG90/40*i;
// mo->target is the originator (player) of the missile
// killough 8/2/98: make autoaiming prefer enemies
if (!mbf_features ||
(P_AimLineAttack(mo->target, an, 16*64*FRACUNIT, MF_FRIEND),
!linetarget))
P_AimLineAttack(mo->target, an, 16*64*FRACUNIT, 0);
if (!linetarget)
continue;
P_SpawnMobj(linetarget->x, linetarget->y,
linetarget->z + (linetarget->height>>2), MT_EXTRABFG);
for (damage=j=0; j<15; j++)
damage += (P_Random(pr_bfg)&7) + 1;
P_DamageMobj(linetarget, mo->target, mo->target, damage);
}
}
//
// A_BFGsound
//
void A_BFGsound(player_t *player, pspdef_t *psp)
{
(void)psp;
S_StartSound(player->mo, sfx_bfg);
}
//
// P_SetupPsprites
// Called at start of level for each player.
//
void P_SetupPsprites(player_t *player)
{
int i;
// remove all psprites
for (i=0; i<NUMPSPRITES; i++)
player->psprites[i].state = NULL;
// spawn the gun
player->pendingweapon = player->readyweapon;
P_BringUpWeapon(player);
}
//
// P_MovePsprites
// Called every tic by player thinking routine.
//
void P_MovePsprites(player_t *player)
{
pspdef_t *psp = player->psprites;
int i;
// a null state means not active
// drop tic count and possibly change state
// a -1 tic count never changes
for (i=0; i<NUMPSPRITES; i++, psp++)
if (psp->state && psp->tics != -1 && !--psp->tics)
P_SetPsprite(player, i, psp->state->nextstate);
player->psprites[ps_flash].sx = player->psprites[ps_weapon].sx;
player->psprites[ps_flash].sy = player->psprites[ps_weapon].sy;
}

View file

@ -0,0 +1,93 @@
/* Emacs style mode select -*- C++ -*-
*-----------------------------------------------------------------------------
*
*
* PrBoom a Doom port merged with LxDoom and LSDLDoom
* based on BOOM, a modified and improved DOOM engine
* Copyright (C) 1999 by
* id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
* Copyright (C) 1999-2000 by
* Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* DESCRIPTION:
* Sprite animation.
*
*-----------------------------------------------------------------------------*/
#ifndef __P_PSPR__
#define __P_PSPR__
/* Basic data types.
* Needs fixed point, and BAM angles. */
#include "m_fixed.h"
#include "tables.h"
/* Needs to include the precompiled sprite animation tables.
*
* Header generated by multigen utility.
* This includes all the data for thing animation,
* i.e. the Thing Atrributes table and the Frame Sequence table.
*/
#include "info.h"
#ifdef __GNUG__
#pragma interface
#endif
/*
* Frame flags:
* handles maximum brightness (torches, muzzle flare, light sources)
*/
#define FF_FULLBRIGHT 0x8000 /* flag in thing->frame */
#define FF_FRAMEMASK 0x7fff
/*
* Overlay psprites are scaled shapes
* drawn directly on the view screen,
* coordinates are given for a 320*200 view screen.
*/
typedef enum
{
ps_weapon,
ps_flash,
NUMPSPRITES
} psprnum_t;
typedef struct
{
state_t *state; /* a NULL state means not active */
int tics;
fixed_t sx;
fixed_t sy;
} pspdef_t;
extern int weapon_preferences[2][NUMWEAPONS+1]; /* killough 5/2/98 */
int P_WeaponPreferred(int w1, int w2);
struct player_s;
int P_SwitchWeapon(struct player_s *player);
boolean P_CheckAmmo(struct player_s *player);
void P_SetupPsprites(struct player_s *curplayer);
void P_MovePsprites(struct player_s *curplayer);
void P_DropWeapon(struct player_s *player);
#endif

987
apps/plugins/doom/p_saveg.c Normal file
View file

@ -0,0 +1,987 @@
/* Emacs style mode select -*- C++ -*-
*-----------------------------------------------------------------------------
*
*
* PrBoom a Doom port merged with LxDoom and LSDLDoom
* based on BOOM, a modified and improved DOOM engine
* Copyright (C) 1999 by
* id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
* Copyright (C) 1999-2000 by
* Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* DESCRIPTION:
* Archiving: SaveGame I/O.
*
*-----------------------------------------------------------------------------*/
#include "doomstat.h"
#include "r_main.h"
#include "p_maputl.h"
#include "p_spec.h"
#include "p_tick.h"
#include "p_saveg.h"
#include "m_random.h"
#include "am_map.h"
#include "p_enemy.h"
#include "i_system.h"
#include "rockmacros.h"
byte *save_p;
// Pads save_p to a 4-byte boundary
// so that the load/save works on SGI&Gecko.
#define PADSAVEP() do { save_p += (4 - ((int) save_p & 3)) & 3; } while (0)
//
// P_ArchivePlayers
//
void P_ArchivePlayers (void)
{
int i;
CheckSaveGame(sizeof(player_t) * MAXPLAYERS); // killough
for (i=0 ; i<MAXPLAYERS ; i++)
if (playeringame[i])
{
int j;
player_t *dest;
PADSAVEP();
dest = (player_t *) save_p;
memcpy(dest, &players[i], sizeof(player_t));
save_p += sizeof(player_t);
for (j=0; j<NUMPSPRITES; j++)
if (dest->psprites[j].state)
dest->psprites[j].state =
(state_t *)(dest->psprites[j].state-states);
}
}
//
// P_UnArchivePlayers
//
void P_UnArchivePlayers (void)
{
int i;
for (i=0 ; i<MAXPLAYERS ; i++)
if (playeringame[i])
{
int j;
PADSAVEP();
memcpy(&players[i], save_p, sizeof(player_t));
save_p += sizeof(player_t);
// will be set when unarc thinker
players[i].mo = NULL;
players[i].message = NULL;
players[i].attacker = NULL;
for (j=0 ; j<NUMPSPRITES ; j++)
if (players[i]. psprites[j].state)
players[i]. psprites[j].state =
&states[ (int)players[i].psprites[j].state ];
}
}
//
// P_ArchiveWorld
//
void P_ArchiveWorld (void)
{
int i;
const sector_t *sec;
const line_t *li;
const side_t *si;
short *put;
// killough 3/22/98: fix bug caused by hoisting save_p too early
// killough 10/98: adjust size for changes below
size_t size =
(sizeof(short)*5 + sizeof sec->floorheight + sizeof sec->ceilingheight)
* numsectors + sizeof(short)*3*numlines + 4;
for (i=0; i<numlines; i++)
{
if (lines[i].sidenum[0] != -1)
size +=
sizeof(short)*3 + sizeof si->textureoffset + sizeof si->rowoffset;
if (lines[i].sidenum[1] != -1)
size +=
sizeof(short)*3 + sizeof si->textureoffset + sizeof si->rowoffset;
}
CheckSaveGame(size); // killough
PADSAVEP(); // killough 3/22/98
put = (short *)save_p;
// do sectors
for (i=0, sec = sectors ; i<numsectors ; i++,sec++)
{
// killough 10/98: save full floor & ceiling heights, including fraction
memcpy(put, &sec->floorheight, sizeof sec->floorheight);
put = (void *)((char *) put + sizeof sec->floorheight);
memcpy(put, &sec->ceilingheight, sizeof sec->ceilingheight);
put = (void *)((char *) put + sizeof sec->ceilingheight);
*put++ = sec->floorpic;
*put++ = sec->ceilingpic;
*put++ = sec->lightlevel;
*put++ = sec->special; // needed? yes -- transfer types
*put++ = sec->tag; // needed? need them -- killough
}
// do lines
for (i=0, li = lines ; i<numlines ; i++,li++)
{
int j;
*put++ = li->flags;
*put++ = li->special;
*put++ = li->tag;
for (j=0; j<2; j++)
if (li->sidenum[j] != -1)
{
si = &sides[li->sidenum[j]];
// killough 10/98: save full sidedef offsets,
// preserving fractional scroll offsets
memcpy(put, &si->textureoffset, sizeof si->textureoffset);
put = (void *)((char *) put + sizeof si->textureoffset);
memcpy(put, &si->rowoffset, sizeof si->rowoffset);
put = (void *)((char *) put + sizeof si->rowoffset);
*put++ = si->toptexture;
*put++ = si->bottomtexture;
*put++ = si->midtexture;
}
}
save_p = (byte *) put;
}
//
// P_UnArchiveWorld
//
void P_UnArchiveWorld (void)
{
int i;
sector_t *sec;
line_t *li;
const short *get;
PADSAVEP(); // killough 3/22/98
get = (short *) save_p;
// do sectors
for (i=0, sec = sectors ; i<numsectors ; i++,sec++)
{
// killough 10/98: load full floor & ceiling heights, including fractions
memcpy(&sec->floorheight, get, sizeof sec->floorheight);
get = (void *)((char *) get + sizeof sec->floorheight);
memcpy(&sec->ceilingheight, get, sizeof sec->ceilingheight);
get = (void *)((char *) get + sizeof sec->ceilingheight);
sec->floorpic = *get++;
sec->ceilingpic = *get++;
sec->lightlevel = *get++;
sec->special = *get++;
sec->tag = *get++;
sec->ceilingdata = 0; //jff 2/22/98 now three thinker fields, not two
sec->floordata = 0;
sec->lightingdata = 0;
sec->soundtarget = 0;
}
// do lines
for (i=0, li = lines ; i<numlines ; i++,li++)
{
int j;
li->flags = *get++;
li->special = *get++;
li->tag = *get++;
for (j=0 ; j<2 ; j++)
if (li->sidenum[j] != -1)
{
side_t *si = &sides[li->sidenum[j]];
// killough 10/98: load full sidedef offsets, including fractions
memcpy(&si->textureoffset, get, sizeof si->textureoffset);
get = (void *)((char *) get + sizeof si->textureoffset);
memcpy(&si->rowoffset, get, sizeof si->rowoffset);
get = (void *)((char *) get + sizeof si->rowoffset);
si->toptexture = *get++;
si->bottomtexture = *get++;
si->midtexture = *get++;
}
}
save_p = (byte *) get;
}
//
// Thinkers
//
typedef enum {
tc_end,
tc_mobj
} thinkerclass_t;
// phares 9/13/98: Moved this code outside of P_ArchiveThinkers so the
// thinker indices could be used by the code that saves sector info.
static int number_of_thinkers;
void P_ThinkerToIndex(void)
{
thinker_t *th;
// killough 2/14/98:
// count the number of thinkers, and mark each one with its index, using
// the prev field as a placeholder, since it can be restored later.
number_of_thinkers = 0;
for (th = thinkercap.next ; th != &thinkercap ; th=th->next)
if (th->function == P_MobjThinker)
th->prev = (thinker_t *) ++number_of_thinkers;
}
// phares 9/13/98: Moved this code outside of P_ArchiveThinkers so the
// thinker indices could be used by the code that saves sector info.
void P_IndexToThinker(void)
{
// killough 2/14/98: restore prev pointers
thinker_t *th;
thinker_t *prev = &thinkercap;
for (th = thinkercap.next ; th != &thinkercap ; prev=th, th=th->next)
th->prev = prev;
}
//
// P_ArchiveThinkers
//
// 2/14/98 killough: substantially modified to fix savegame bugs
void P_ArchiveThinkers (void)
{
thinker_t *th;
CheckSaveGame(sizeof brain); // killough 3/26/98: Save boss brain state
memcpy(save_p, &brain, sizeof brain);
save_p += sizeof brain;
/* check that enough room is available in savegame buffer
* - killough 2/14/98
* cph - use number_of_thinkers saved by P_ThinkerToIndex above
*/
CheckSaveGame(number_of_thinkers*(sizeof(mobj_t)+4));
// save off the current thinkers
for (th = thinkercap.next ; th != &thinkercap ; th=th->next)
if (th->function == P_MobjThinker)
{
mobj_t *mobj;
*save_p++ = tc_mobj;
PADSAVEP();
mobj = (mobj_t *)save_p;
memcpy (mobj, th, sizeof(*mobj));
save_p += sizeof(*mobj);
mobj->state = (state_t *)(mobj->state - states);
// killough 2/14/98: convert pointers into indices.
// Fixes many savegame problems, by properly saving
// target and tracer fields. Note: we store NULL if
// the thinker pointed to by these fields is not a
// mobj thinker.
if (mobj->target)
mobj->target = mobj->target->thinker.function ==
P_MobjThinker ?
(mobj_t *) mobj->target->thinker.prev : NULL;
if (mobj->tracer)
mobj->tracer = mobj->tracer->thinker.function ==
P_MobjThinker ?
(mobj_t *) mobj->tracer->thinker.prev : NULL;
// killough 2/14/98: new field: save last known enemy. Prevents
// monsters from going to sleep after killing monsters and not
// seeing player anymore.
if (mobj->lastenemy)
mobj->lastenemy = mobj->lastenemy->thinker.function ==
P_MobjThinker ?
(mobj_t *) mobj->lastenemy->thinker.prev : NULL;
// killough 2/14/98: end changes
if (mobj->above_thing) // phares
mobj->above_thing = mobj->above_thing->thinker.function ==
P_MobjThinker ?
(mobj_t *) mobj->above_thing->thinker.prev : NULL;
if (mobj->below_thing)
mobj->below_thing = mobj->below_thing->thinker.function ==
P_MobjThinker ?
(mobj_t *) mobj->below_thing->thinker.prev : NULL; // phares
if (mobj->player)
mobj->player = (player_t *)((mobj->player-players) + 1);
}
// add a terminating marker
*save_p++ = tc_end;
// killough 9/14/98: save soundtargets
{
int i;
CheckSaveGame(numsectors * sizeof(mobj_t *)); // killough 9/14/98
for (i = 0; i < numsectors; i++)
{
mobj_t *target = sectors[i].soundtarget;
if (target)
target = (mobj_t *) target->thinker.prev;
memcpy(save_p, &target, sizeof target);
save_p += sizeof target;
}
}
}
/*
* killough 11/98
*
* Same as P_SetTarget() in p_tick.c, except that the target is nullified
* first, so that no old target's reference count is decreased (when loading
* savegames, old targets are indices, not really pointers to targets).
*/
static void P_SetNewTarget(mobj_t **mop, mobj_t *targ)
{
*mop = NULL;
P_SetTarget(mop, targ);
}
//
// P_UnArchiveThinkers
//
// 2/14/98 killough: substantially modified to fix savegame bugs
//
void P_UnArchiveThinkers (void)
{
thinker_t *th;
mobj_t **mobj_p; // killough 2/14/98: Translation table
size_t size; // killough 2/14/98: size of or index into table
totallive = 0;
// killough 3/26/98: Load boss brain state
memcpy(&brain, save_p, sizeof brain);
save_p += sizeof brain;
// remove all the current thinkers
for (th = thinkercap.next; th != &thinkercap; )
{
thinker_t *next = th->next;
if (th->function == P_MobjThinker)
P_RemoveMobj ((mobj_t *) th);
else
Z_Free (th);
th = next;
}
P_InitThinkers ();
// killough 2/14/98: count number of thinkers by skipping through them
{
byte *sp = save_p; // save pointer and skip header
for (size = 1; *save_p++ == tc_mobj; size++) // killough 2/14/98
{ // skip all entries, adding up count
PADSAVEP();
save_p += sizeof(mobj_t);
}
if (*--save_p != tc_end)
I_Error ("P_UnArchiveThinkers: Unknown tclass %i in savegame", *save_p);
// first table entry special: 0 maps to NULL
*(mobj_p = malloc(size * sizeof *mobj_p)) = 0; // table of pointers
save_p = sp; // restore save pointer
}
// read in saved thinkers
for (size = 1; *save_p++ == tc_mobj; size++) // killough 2/14/98
{
mobj_t *mobj = Z_Malloc(sizeof(mobj_t), PU_LEVEL, NULL);
// killough 2/14/98 -- insert pointers to thinkers into table, in order:
mobj_p[size] = mobj;
PADSAVEP();
memcpy (mobj, save_p, sizeof(mobj_t));
save_p += sizeof(mobj_t);
mobj->state = states + (int) mobj->state;
if (mobj->player)
(mobj->player = &players[(int) mobj->player - 1]) -> mo = mobj;
P_SetThingPosition (mobj);
mobj->info = &mobjinfo[mobj->type];
// killough 2/28/98:
// Fix for falling down into a wall after savegame loaded:
// mobj->floorz = mobj->subsector->sector->floorheight;
// mobj->ceilingz = mobj->subsector->sector->ceilingheight;
mobj->thinker.function = P_MobjThinker;
P_AddThinker (&mobj->thinker);
if (!((mobj->flags ^ MF_COUNTKILL) & (MF_FRIEND | MF_COUNTKILL | MF_CORPSE)))
totallive++;
}
// killough 2/14/98: adjust target and tracer fields, plus
// lastenemy field, to correctly point to mobj thinkers.
// NULL entries automatically handled by first table entry.
//
// killough 11/98: use P_SetNewTarget() to set fields
for (th = thinkercap.next ; th != &thinkercap ; th=th->next)
{
P_SetNewTarget(&((mobj_t *) th)->target,
mobj_p[(size_t)((mobj_t *)th)->target]);
P_SetNewTarget(&((mobj_t *) th)->tracer,
mobj_p[(size_t)((mobj_t *)th)->tracer]);
P_SetNewTarget(&((mobj_t *) th)->lastenemy,
mobj_p[(size_t)((mobj_t *)th)->lastenemy]);
// phares: added two new fields for Sprite Height problem
P_SetNewTarget(&((mobj_t *) th)->above_thing,
mobj_p[(size_t)((mobj_t *)th)->above_thing]);
P_SetNewTarget(&((mobj_t *) th)->below_thing,
mobj_p[(size_t)((mobj_t *)th)->below_thing]);
}
{ // killough 9/14/98: restore soundtargets
int i;
for (i = 0; i < numsectors; i++)
{
mobj_t *target;
memcpy(&target, save_p, sizeof target);
save_p += sizeof target;
P_SetNewTarget(&sectors[i].soundtarget, mobj_p[(size_t) target]);
}
}
free(mobj_p); // free translation table
// killough 3/26/98: Spawn icon landings:
if (gamemode == commercial)
P_SpawnBrainTargets();
}
//
// P_ArchiveSpecials
//
enum {
tc_ceiling,
tc_door,
tc_floor,
tc_plat,
tc_flash,
tc_strobe,
tc_glow,
tc_elevator, //jff 2/22/98 new elevator type thinker
tc_scroll, // killough 3/7/98: new scroll effect thinker
tc_pusher, // phares 3/22/98: new push/pull effect thinker
tc_flicker, // killough 10/4/98
tc_endspecials
} specials_e;
//
// Things to handle:
//
// T_MoveCeiling, (ceiling_t: sector_t * swizzle), - active list
// T_VerticalDoor, (vldoor_t: sector_t * swizzle),
// T_MoveFloor, (floormove_t: sector_t * swizzle),
// T_LightFlash, (lightflash_t: sector_t * swizzle),
// T_StrobeFlash, (strobe_t: sector_t *),
// T_Glow, (glow_t: sector_t *),
// T_PlatRaise, (plat_t: sector_t *), - active list
// T_MoveElevator, (plat_t: sector_t *), - active list // jff 2/22/98
// T_Scroll // killough 3/7/98
// T_Pusher // phares 3/22/98
// T_FireFlicker // killough 10/4/98
//
void P_ArchiveSpecials (void)
{
thinker_t *th;
size_t size = 0; // killough
// save off the current thinkers (memory size calculation -- killough)
for (th = thinkercap.next ; th != &thinkercap ; th=th->next)
if (!th->function)
{
platlist_t *pl;
ceilinglist_t *cl; //jff 2/22/98 need this for ceilings too now
for (pl=activeplats; pl; pl=pl->next)
if (pl->plat == (plat_t *) th) // killough 2/14/98
{
size += 4+sizeof(plat_t);
goto end;
}
for (cl=activeceilings; cl; cl=cl->next) // search for activeceiling
if (cl->ceiling == (ceiling_t *) th) //jff 2/22/98
{
size += 4+sizeof(ceiling_t);
goto end;
}
end:;
}
else
size +=
th->function==T_MoveCeiling ? 4+sizeof(ceiling_t) :
th->function==T_VerticalDoor ? 4+sizeof(vldoor_t) :
th->function==T_MoveFloor ? 4+sizeof(floormove_t):
th->function==T_PlatRaise ? 4+sizeof(plat_t) :
th->function==T_LightFlash ? 4+sizeof(lightflash_t):
th->function==T_StrobeFlash ? 4+sizeof(strobe_t) :
th->function==T_Glow ? 4+sizeof(glow_t) :
th->function==T_MoveElevator ? 4+sizeof(elevator_t):
th->function==T_Scroll ? 4+sizeof(scroll_t) :
th->function==T_Pusher ? 4+sizeof(pusher_t) :
th->function==T_FireFlicker? 4+sizeof(fireflicker_t) :
0;
CheckSaveGame(size); // killough
// save off the current thinkers
for (th=thinkercap.next; th!=&thinkercap; th=th->next)
{
if (!th->function)
{
platlist_t *pl;
ceilinglist_t *cl; //jff 2/22/98 add iter variable for ceilings
// killough 2/8/98: fix plat original height bug.
// Since acv==NULL, this could be a plat in stasis.
// so check the active plats list, and save this
// plat (jff: or ceiling) even if it is in stasis.
for (pl=activeplats; pl; pl=pl->next)
if (pl->plat == (plat_t *) th) // killough 2/14/98
goto plat;
for (cl=activeceilings; cl; cl=cl->next)
if (cl->ceiling == (ceiling_t *) th) //jff 2/22/98
goto ceiling;
continue;
}
if (th->function == T_MoveCeiling)
{
ceiling_t *ceiling;
ceiling: // killough 2/14/98
*save_p++ = tc_ceiling;
PADSAVEP();
ceiling = (ceiling_t *)save_p;
memcpy (ceiling, th, sizeof(*ceiling));
save_p += sizeof(*ceiling);
ceiling->sector = (sector_t *)(ceiling->sector - sectors);
continue;
}
if (th->function == T_VerticalDoor)
{
vldoor_t *door;
*save_p++ = tc_door;
PADSAVEP();
door = (vldoor_t *) save_p;
memcpy (door, th, sizeof *door);
save_p += sizeof(*door);
door->sector = (sector_t *)(door->sector - sectors);
//jff 1/31/98 archive line remembered by door as well
door->line = (line_t *) (door->line ? door->line-lines : -1);
continue;
}
if (th->function == T_MoveFloor)
{
floormove_t *floor;
*save_p++ = tc_floor;
PADSAVEP();
floor = (floormove_t *)save_p;
memcpy (floor, th, sizeof(*floor));
save_p += sizeof(*floor);
floor->sector = (sector_t *)(floor->sector - sectors);
continue;
}
if (th->function == T_PlatRaise)
{
plat_t *plat;
plat: // killough 2/14/98: added fix for original plat height above
*save_p++ = tc_plat;
PADSAVEP();
plat = (plat_t *)save_p;
memcpy (plat, th, sizeof(*plat));
save_p += sizeof(*plat);
plat->sector = (sector_t *)(plat->sector - sectors);
continue;
}
if (th->function == T_LightFlash)
{
lightflash_t *flash;
*save_p++ = tc_flash;
PADSAVEP();
flash = (lightflash_t *)save_p;
memcpy (flash, th, sizeof(*flash));
save_p += sizeof(*flash);
flash->sector = (sector_t *)(flash->sector - sectors);
continue;
}
if (th->function == T_StrobeFlash)
{
strobe_t *strobe;
*save_p++ = tc_strobe;
PADSAVEP();
strobe = (strobe_t *)save_p;
memcpy (strobe, th, sizeof(*strobe));
save_p += sizeof(*strobe);
strobe->sector = (sector_t *)(strobe->sector - sectors);
continue;
}
if (th->function == T_Glow)
{
glow_t *glow;
*save_p++ = tc_glow;
PADSAVEP();
glow = (glow_t *)save_p;
memcpy (glow, th, sizeof(*glow));
save_p += sizeof(*glow);
glow->sector = (sector_t *)(glow->sector - sectors);
continue;
}
// killough 10/4/98: save flickers
if (th->function == T_FireFlicker)
{
fireflicker_t *flicker;
*save_p++ = tc_flicker;
PADSAVEP();
flicker = (fireflicker_t *)save_p;
memcpy (flicker, th, sizeof(*flicker));
save_p += sizeof(*flicker);
flicker->sector = (sector_t *)(flicker->sector - sectors);
continue;
}
//jff 2/22/98 new case for elevators
if (th->function == T_MoveElevator)
{
elevator_t *elevator; //jff 2/22/98
*save_p++ = tc_elevator;
PADSAVEP();
elevator = (elevator_t *)save_p;
memcpy (elevator, th, sizeof(*elevator));
save_p += sizeof(*elevator);
elevator->sector = (sector_t *)(elevator->sector - sectors);
continue;
}
// killough 3/7/98: Scroll effect thinkers
if (th->function == T_Scroll)
{
*save_p++ = tc_scroll;
memcpy (save_p, th, sizeof(scroll_t));
save_p += sizeof(scroll_t);
continue;
}
// phares 3/22/98: Push/Pull effect thinkers
if (th->function == T_Pusher)
{
*save_p++ = tc_pusher;
memcpy (save_p, th, sizeof(pusher_t));
save_p += sizeof(pusher_t);
continue;
}
}
// add a terminating marker
*save_p++ = tc_endspecials;
}
//
// P_UnArchiveSpecials
//
void P_UnArchiveSpecials (void)
{
byte tclass;
// read in saved thinkers
while ((tclass = *save_p++) != tc_endspecials) // killough 2/14/98
switch (tclass)
{
case tc_ceiling:
PADSAVEP();
{
ceiling_t *ceiling = Z_Malloc (sizeof(*ceiling), PU_LEVEL, NULL);
memcpy (ceiling, save_p, sizeof(*ceiling));
save_p += sizeof(*ceiling);
ceiling->sector = &sectors[(int)ceiling->sector];
ceiling->sector->ceilingdata = ceiling; //jff 2/22/98
if (ceiling->thinker.function)
ceiling->thinker.function = T_MoveCeiling;
P_AddThinker (&ceiling->thinker);
P_AddActiveCeiling(ceiling);
break;
}
case tc_door:
PADSAVEP();
{
vldoor_t *door = Z_Malloc (sizeof(*door), PU_LEVEL, NULL);
memcpy (door, save_p, sizeof(*door));
save_p += sizeof(*door);
door->sector = &sectors[(int)door->sector];
//jff 1/31/98 unarchive line remembered by door as well
door->line = (int)door->line!=-1? &lines[(int)door->line] : NULL;
door->sector->ceilingdata = door; //jff 2/22/98
door->thinker.function = T_VerticalDoor;
P_AddThinker (&door->thinker);
break;
}
case tc_floor:
PADSAVEP();
{
floormove_t *floor = Z_Malloc (sizeof(*floor), PU_LEVEL, NULL);
memcpy (floor, save_p, sizeof(*floor));
save_p += sizeof(*floor);
floor->sector = &sectors[(int)floor->sector];
floor->sector->floordata = floor; //jff 2/22/98
floor->thinker.function = T_MoveFloor;
P_AddThinker (&floor->thinker);
break;
}
case tc_plat:
PADSAVEP();
{
plat_t *plat = Z_Malloc (sizeof(*plat), PU_LEVEL, NULL);
memcpy (plat, save_p, sizeof(*plat));
save_p += sizeof(*plat);
plat->sector = &sectors[(int)plat->sector];
plat->sector->floordata = plat; //jff 2/22/98
if (plat->thinker.function)
plat->thinker.function = T_PlatRaise;
P_AddThinker (&plat->thinker);
P_AddActivePlat(plat);
break;
}
case tc_flash:
PADSAVEP();
{
lightflash_t *flash = Z_Malloc (sizeof(*flash), PU_LEVEL, NULL);
memcpy (flash, save_p, sizeof(*flash));
save_p += sizeof(*flash);
flash->sector = &sectors[(int)flash->sector];
flash->thinker.function = T_LightFlash;
P_AddThinker (&flash->thinker);
break;
}
case tc_strobe:
PADSAVEP();
{
strobe_t *strobe = Z_Malloc (sizeof(*strobe), PU_LEVEL, NULL);
memcpy (strobe, save_p, sizeof(*strobe));
save_p += sizeof(*strobe);
strobe->sector = &sectors[(int)strobe->sector];
strobe->thinker.function = T_StrobeFlash;
P_AddThinker (&strobe->thinker);
break;
}
case tc_glow:
PADSAVEP();
{
glow_t *glow = Z_Malloc (sizeof(*glow), PU_LEVEL, NULL);
memcpy (glow, save_p, sizeof(*glow));
save_p += sizeof(*glow);
glow->sector = &sectors[(int)glow->sector];
glow->thinker.function = T_Glow;
P_AddThinker (&glow->thinker);
break;
}
case tc_flicker: // killough 10/4/98
PADSAVEP();
{
fireflicker_t *flicker = Z_Malloc (sizeof(*flicker), PU_LEVEL, NULL);
memcpy (flicker, save_p, sizeof(*flicker));
save_p += sizeof(*flicker);
flicker->sector = &sectors[(int)flicker->sector];
flicker->thinker.function = T_FireFlicker;
P_AddThinker (&flicker->thinker);
break;
}
//jff 2/22/98 new case for elevators
case tc_elevator:
PADSAVEP();
{
elevator_t *elevator = Z_Malloc (sizeof(*elevator), PU_LEVEL, NULL);
memcpy (elevator, save_p, sizeof(*elevator));
save_p += sizeof(*elevator);
elevator->sector = &sectors[(int)elevator->sector];
elevator->sector->floordata = elevator; //jff 2/22/98
elevator->sector->ceilingdata = elevator; //jff 2/22/98
elevator->thinker.function = T_MoveElevator;
P_AddThinker (&elevator->thinker);
break;
}
case tc_scroll: // killough 3/7/98: scroll effect thinkers
{
scroll_t *scroll = Z_Malloc (sizeof(scroll_t), PU_LEVEL, NULL);
memcpy (scroll, save_p, sizeof(scroll_t));
save_p += sizeof(scroll_t);
scroll->thinker.function = T_Scroll;
P_AddThinker(&scroll->thinker);
break;
}
case tc_pusher: // phares 3/22/98: new Push/Pull effect thinkers
{
pusher_t *pusher = Z_Malloc (sizeof(pusher_t), PU_LEVEL, NULL);
memcpy (pusher, save_p, sizeof(pusher_t));
save_p += sizeof(pusher_t);
pusher->thinker.function = T_Pusher;
pusher->source = P_GetPushThing(pusher->affectee);
P_AddThinker(&pusher->thinker);
break;
}
default:
I_Error("P_UnarchiveSpecials: Unknown tclass %i in savegame", tclass);
}
}
// killough 2/16/98: save/restore random number generator state information
void P_ArchiveRNG(void)
{
CheckSaveGame(sizeof rng);
memcpy(save_p, &rng, sizeof rng);
save_p += sizeof rng;
}
void P_UnArchiveRNG(void)
{
memcpy(&rng, save_p, sizeof rng);
save_p += sizeof rng;
}
// killough 2/22/98: Save/restore automap state
// killough 2/22/98: Save/restore automap state
void P_ArchiveMap(void)
{
int zero = 0, one = 1;
CheckSaveGame(2 * sizeof zero + sizeof markpointnum +
markpointnum * sizeof *markpoints +
sizeof automapmode + sizeof one);
memcpy(save_p, &automapmode, sizeof automapmode);
save_p += sizeof automapmode;
memcpy(save_p, &one, sizeof one); // CPhipps - used to be viewactive, now
save_p += sizeof one; // that's worked out locally by D_Display
memcpy(save_p, &zero, sizeof zero); // CPhipps - used to be followplayer
save_p += sizeof zero; // that is now part of automapmode
memcpy(save_p, &zero, sizeof zero); // CPhipps - used to be automap_grid, ditto
save_p += sizeof zero;
memcpy(save_p, &markpointnum, sizeof markpointnum);
save_p += sizeof markpointnum;
if (markpointnum)
{
memcpy(save_p, markpoints, sizeof *markpoints * markpointnum);
save_p += markpointnum * sizeof *markpoints;
}
}
void P_UnArchiveMap(void)
{
int unused;
memcpy(&automapmode, save_p, sizeof automapmode);
save_p += sizeof automapmode;
memcpy(&unused, save_p, sizeof unused);
save_p += sizeof unused;
memcpy(&unused, save_p, sizeof unused);
save_p += sizeof unused;
memcpy(&unused, save_p, sizeof unused);
save_p += sizeof unused;
if (automapmode & am_active)
AM_Start();
memcpy(&markpointnum, save_p, sizeof markpointnum);
save_p += sizeof markpointnum;
if (markpointnum)
{
while (markpointnum >= markpointnum_max)
markpoints = realloc(markpoints, sizeof *markpoints *
(markpointnum_max = markpointnum_max ? markpointnum_max*2 : 16));
memcpy(markpoints, save_p, markpointnum * sizeof *markpoints);
save_p += markpointnum * sizeof *markpoints;
}
}

View file

@ -0,0 +1,63 @@
/* Emacs style mode select -*- C++ -*-
*-----------------------------------------------------------------------------
*
*
* PrBoom a Doom port merged with LxDoom and LSDLDoom
* based on BOOM, a modified and improved DOOM engine
* Copyright (C) 1999 by
* id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
* Copyright (C) 1999-2000 by
* Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* DESCRIPTION:
* Savegame I/O, archiving, persistence.
*
*-----------------------------------------------------------------------------*/
#ifndef __P_SAVEG__
#define __P_SAVEG__
#ifdef __GNUG__
#pragma interface
#endif
/* Persistent storage/archiving.
* These are the load / save game routines. */
void P_ArchivePlayers(void);
void P_UnArchivePlayers(void);
void P_ArchiveWorld(void);
void P_UnArchiveWorld(void);
void P_ArchiveThinkers(void);
void P_UnArchiveThinkers(void);
void P_ArchiveSpecials(void);
void P_UnArchiveSpecials(void);
void P_ThinkerToIndex(void); /* phares 9/13/98: save soundtarget in savegame */
void P_IndexToThinker(void); /* phares 9/13/98: save soundtarget in savegame */
/* 1/18/98 killough: add RNG info to savegame */
void P_ArchiveRNG(void);
void P_UnArchiveRNG(void);
/* 2/21/98 killough: add automap info to savegame */
void P_ArchiveMap(void);
void P_UnArchiveMap(void);
extern byte *save_p;
void CheckSaveGame(size_t); /* killough */
#endif

1255
apps/plugins/doom/p_setup.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,55 @@
/* Emacs style mode select -*- C++ -*-
*-----------------------------------------------------------------------------
*
*
* PrBoom a Doom port merged with LxDoom and LSDLDoom
* based on BOOM, a modified and improved DOOM engine
* Copyright (C) 1999 by
* id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
* Copyright (C) 1999-2000 by
* Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* DESCRIPTION:
* Setup a game, startup stuff.
*
*-----------------------------------------------------------------------------*/
#ifndef __P_SETUP__
#define __P_SETUP__
#include "p_mobj.h"
#ifdef __GNUG__
#pragma interface
#endif
void P_SetupLevel(int episode, int map, int playermask, skill_t skill);
void P_Init(void); /* Called by startup code. */
extern const byte *rejectmatrix; /* for fast sight rejection - cph - const* */
/* killough 3/1/98: change blockmap from "short" to "long" offsets: */
extern long *blockmaplump; /* offsets in blockmap are from here */
extern long *blockmap;
extern int bmapwidth;
extern int bmapheight; /* in mapblocks */
extern fixed_t bmaporgx;
extern fixed_t bmaporgy; /* origin of block map */
extern mobj_t **blocklinks; /* for thing chains */
#endif

346
apps/plugins/doom/p_sight.c Normal file
View file

@ -0,0 +1,346 @@
/* Emacs style mode select -*- C++ -*-
*-----------------------------------------------------------------------------
*
*
* PrBoom a Doom port merged with LxDoom and LSDLDoom
* based on BOOM, a modified and improved DOOM engine
* Copyright (C) 1999 by
* id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
* Copyright (C) 1999-2000 by
* Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* DESCRIPTION:
* LineOfSight/Visibility checks, uses REJECT Lookup Table.
*
*-----------------------------------------------------------------------------*/
#include "doomstat.h"
#include "r_main.h"
#include "p_maputl.h"
#include "p_setup.h"
#include "m_bbox.h"
#include "rockmacros.h"
//
// P_CheckSight
//
// killough 4/19/98:
// Convert LOS info to struct for reentrancy and efficiency of data locality
typedef struct {
fixed_t sightzstart, t2x, t2y; // eye z of looker
divline_t strace; // from t1 to t2
fixed_t topslope, bottomslope; // slopes to top and bottom of target
fixed_t bbox[4];
fixed_t maxz,minz; // cph - z optimisations for 2sided lines
} los_t;
static los_t los; // cph - made static
//
// P_DivlineSide
// Returns side 0 (front), 1 (back), or 2 (on).
//
// killough 4/19/98: made static, cleaned up
inline static int P_DivlineSide(fixed_t x, fixed_t y, const divline_t *node)
{
fixed_t left, right;
return
!node->dx ? x == node->x ? 2 : x <= node->x ? node->dy > 0 : node->dy < 0 :
!node->dy ? x == node->y ? 2 : y <= node->y ? node->dx < 0 : node->dx > 0 :
(right = ((y - node->y) >> FRACBITS) * (node->dx >> FRACBITS)) <
(left = ((x - node->x) >> FRACBITS) * (node->dy >> FRACBITS)) ? 0 :
right == left ? 2 : 1;
}
//
// P_InterceptVector2
// Returns the fractional intercept point
// along the first divline.
//
// killough 4/19/98: made static, cleaned up
static fixed_t P_InterceptVector2(const divline_t *v2, const divline_t *v1)
{
fixed_t den;
return (den = FixedMul(v1->dy>>8, v2->dx) - FixedMul(v1->dx>>8, v2->dy)) ?
FixedDiv(FixedMul((v1->x - v2->x)>>8, v1->dy) +
FixedMul((v2->y - v1->y)>>8, v1->dx), den) : 0;
}
//
// P_CrossSubsector
// Returns true
// if strace crosses the given subsector successfully.
//
// killough 4/19/98: made static and cleaned up
static boolean P_CrossSubsector(int num)
{
seg_t *seg = segs + subsectors[num].firstline;
int count;
fixed_t opentop = 0, openbottom = 0;
const sector_t *front = NULL, *back = NULL;
#ifdef RANGECHECK
if (num >= numsubsectors)
I_Error("P_CrossSubsector: ss %i with numss = %i", num, numsubsectors);
#endif
for (count = subsectors[num].numlines; --count >= 0; seg++) { // check lines
line_t *line = seg->linedef;
divline_t divl;
if(!line) // figgi -- skip minisegs
continue;
// allready checked other side?
if (line->validcount == validcount)
continue;
line->validcount = validcount;
/* OPTIMIZE: killough 4/20/98: Added quick bounding-box rejection test
* cph - this is causing demo desyncs on original Doom demos.
* Who knows why. Exclude test for those.
*/
if (!demo_compatibility)
if (line->bbox[BOXLEFT ] > los.bbox[BOXRIGHT ] ||
line->bbox[BOXRIGHT ] < los.bbox[BOXLEFT ] ||
line->bbox[BOXBOTTOM] > los.bbox[BOXTOP ] ||
line->bbox[BOXTOP] < los.bbox[BOXBOTTOM])
continue;
// cph - do what we can before forced to check intersection
if (line->flags & ML_TWOSIDED) {
// no wall to block sight with?
if ((front = seg->frontsector)->floorheight ==
(back = seg->backsector)->floorheight &&
front->ceilingheight == back->ceilingheight)
continue;
// possible occluder
// because of ceiling height differences
opentop = front->ceilingheight < back->ceilingheight ?
front->ceilingheight : back->ceilingheight ;
// because of floor height differences
openbottom = front->floorheight > back->floorheight ?
front->floorheight : back->floorheight ;
// cph - reject if does not intrude in the z-space of the possible LOS
if ((opentop >= los.maxz) && (openbottom <= los.minz))
continue;
}
{ // Forget this line if it doesn't cross the line of sight
const vertex_t *v1,*v2;
v1 = line->v1;
v2 = line->v2;
if (P_DivlineSide(v1->x, v1->y, &los.strace) ==
P_DivlineSide(v2->x, v2->y, &los.strace))
continue;
divl.dx = v2->x - (divl.x = v1->x);
divl.dy = v2->y - (divl.y = v1->y);
// line isn't crossed?
if (P_DivlineSide(los.strace.x, los.strace.y, &divl) ==
P_DivlineSide(los.t2x, los.t2y, &divl))
continue;
}
// cph - if bottom >= top or top < minz or bottom > maxz then it must be
// solid wrt this LOS
if (!(line->flags & ML_TWOSIDED) || (openbottom >= opentop) ||
(opentop < los.minz) || (openbottom > los.maxz))
return false;
{ // crosses a two sided line
fixed_t frac = P_InterceptVector2(&los.strace, &divl);
if (front->floorheight != back->floorheight)
{
fixed_t slope = FixedDiv(openbottom - los.sightzstart , frac);
if (slope > los.bottomslope)
los.bottomslope = slope;
}
if (front->ceilingheight != back->ceilingheight)
{
fixed_t slope = FixedDiv(opentop - los.sightzstart , frac);
if (slope < los.topslope)
los.topslope = slope;
}
if (los.topslope <= los.bottomslope)
return false; // stop
}
}
// passed the subsector ok
return true;
}
//
// P_CrossBSPNode
// Returns true
// if strace crosses the given node successfully.
//
// killough 4/20/98: rewritten to remove tail recursion, clean up, and optimize
// cph - Made to use R_PointOnSide instead of P_DivlineSide, since the latter
// could return 2 which was ambigous, and the former is
// better optimised; also removes two casts :-)
static boolean P_CrossBSPNode_LxDoom(int bspnum)
{
while (!(bspnum & NF_SUBSECTOR))
{
register const node_t *bsp = nodes + bspnum;
int side,side2;
side = R_PointOnSide(los.strace.x, los.strace.y, bsp);
side2 = R_PointOnSide(los.t2x, los.t2y, bsp);
if (side == side2)
bspnum = bsp->children[side]; // doesn't touch the other side
else // the partition plane is crossed here
if (!P_CrossBSPNode_LxDoom(bsp->children[side]))
return 0; // cross the starting side
else
bspnum = bsp->children[side^1]; // cross the ending side
}
return P_CrossSubsector(bspnum == -1 ? 0 : bspnum & ~NF_SUBSECTOR);
}
static boolean P_CrossBSPNode_PrBoom(int bspnum)
{
while (!(bspnum & NF_SUBSECTOR))
{
register const node_t *bsp = nodes + bspnum;
int side,side2;
side = P_DivlineSide(los.strace.x,los.strace.y,(divline_t *)bsp)&1;
side2= P_DivlineSide(los.t2x, los.t2y, (divline_t *) bsp);
if (side == side2)
bspnum = bsp->children[side]; // doesn't touch the other side
else // the partition plane is crossed here
if (!P_CrossBSPNode_PrBoom(bsp->children[side]))
return 0; // cross the starting side
else
bspnum = bsp->children[side^1]; // cross the ending side
}
return P_CrossSubsector(bspnum == -1 ? 0 : bspnum & ~NF_SUBSECTOR);
}
/* proff - Moved the compatibility check outside the functions
* this gives a slight speedup
*/
static boolean P_CrossBSPNode(int bspnum)
{
/* cph - LxDoom used some R_* funcs here */
if (compatibility_level == lxdoom_1_compatibility)
return P_CrossBSPNode_LxDoom(bspnum);
else
return P_CrossBSPNode_PrBoom(bspnum);
}
//
// P_CheckSight
// Returns true
// if a straight line between t1 and t2 is unobstructed.
// Uses REJECT.
//
// killough 4/20/98: cleaned up, made to use new LOS struct
boolean P_CheckSight(mobj_t *t1, mobj_t *t2)
{
const sector_t *s1 = t1->subsector->sector;
const sector_t *s2 = t2->subsector->sector;
int pnum = (s1-sectors)*numsectors + (s2-sectors);
// First check for trivial rejection.
// Determine subsector entries in REJECT table.
//
// Check in REJECT table.
if (rejectmatrix[pnum>>3] & (1 << (pnum&7))) // can't possibly be connected
return false;
// killough 4/19/98: make fake floors and ceilings block monster view
if ((s1->heightsec != -1 &&
((t1->z + t1->height <= sectors[s1->heightsec].floorheight &&
t2->z >= sectors[s1->heightsec].floorheight) ||
(t1->z >= sectors[s1->heightsec].ceilingheight &&
t2->z + t1->height <= sectors[s1->heightsec].ceilingheight)))
||
(s2->heightsec != -1 &&
((t2->z + t2->height <= sectors[s2->heightsec].floorheight &&
t1->z >= sectors[s2->heightsec].floorheight) ||
(t2->z >= sectors[s2->heightsec].ceilingheight &&
t1->z + t2->height <= sectors[s2->heightsec].ceilingheight))))
return false;
/* killough 11/98: shortcut for melee situations
* same subsector? obviously visible
* cph - compatibility optioned for demo sync, cf HR06-UV.LMP */
if ((t1->subsector == t2->subsector) &&
(compatibility_level >= mbf_compatibility))
return true;
// An unobstructed LOS is possible.
// Now look from eyes of t1 to any part of t2.
validcount++;
los.topslope = (los.bottomslope = t2->z - (los.sightzstart =
t1->z + t1->height -
(t1->height>>2))) + t2->height;
los.strace.dx = (los.t2x = t2->x) - (los.strace.x = t1->x);
los.strace.dy = (los.t2y = t2->y) - (los.strace.y = t1->y);
if (t1->x > t2->x)
los.bbox[BOXRIGHT] = t1->x, los.bbox[BOXLEFT] = t2->x;
else
los.bbox[BOXRIGHT] = t2->x, los.bbox[BOXLEFT] = t1->x;
if (t1->y > t2->y)
los.bbox[BOXTOP] = t1->y, los.bbox[BOXBOTTOM] = t2->y;
else
los.bbox[BOXTOP] = t2->y, los.bbox[BOXBOTTOM] = t1->y;
/* cph - calculate min and max z of the potential line of sight
* For old demos, we disable this optimisation by setting them to
* the extremes */
switch (compatibility_level) {
case lxdoom_1_compatibility:
if (los.sightzstart < t2->z) {
los.maxz = t2->z + t2->height; los.minz = los.sightzstart;
} else if (los.sightzstart > t2->z + t2->height) {
los.maxz = los.sightzstart; los.minz = t2->z;
} else {
los.maxz = t2->z + t2->height; los.minz = t2->z;
}
break;
default:
los.maxz = INT_MAX; los.minz = INT_MIN;
}
// the head node is the last node output
return P_CrossBSPNode(numnodes-1);
}

3255
apps/plugins/doom/p_spec.c Normal file

File diff suppressed because it is too large Load diff

1148
apps/plugins/doom/p_spec.h Normal file

File diff suppressed because it is too large Load diff

1138
apps/plugins/doom/p_switch.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,322 @@
/* Emacs style mode select -*- C++ -*-
*-----------------------------------------------------------------------------
*
*
* PrBoom a Doom port merged with LxDoom and LSDLDoom
* based on BOOM, a modified and improved DOOM engine
* Copyright (C) 1999 by
* id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
* Copyright (C) 1999-2000 by
* Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* DESCRIPTION:
* Teleportation.
*
*-----------------------------------------------------------------------------*/
#include "doomdef.h"
#include "doomstat.h"
#include "p_spec.h"
#include "p_maputl.h"
#include "p_map.h"
#include "r_main.h"
#include "p_tick.h"
#include "s_sound.h"
#include "sounds.h"
#include "p_user.h"
#include "rockmacros.h"
//
// TELEPORTATION
//
// killough 5/3/98: reformatted, cleaned up
int EV_Teleport(line_t *line, int side, mobj_t *thing)
{
thinker_t *thinker;
mobj_t *m;
int i;
// don't teleport missiles
// Don't teleport if hit back of line,
// so you can get out of teleporter.
if (side || thing->flags & MF_MISSILE)
return 0;
// killough 1/31/98: improve performance by using
// P_FindSectorFromLineTag instead of simple linear search.
for (i = -1; (i = P_FindSectorFromLineTag(line, i)) >= 0;)
for (thinker=thinkercap.next; thinker!=&thinkercap; thinker=thinker->next)
if (thinker->function == P_MobjThinker &&
(m = (mobj_t *) thinker)->type == MT_TELEPORTMAN &&
m->subsector->sector-sectors == i)
{
fixed_t oldx = thing->x, oldy = thing->y, oldz = thing->z;
player_t *player = thing->player;
// killough 5/12/98: exclude voodoo dolls:
if (player && player->mo != thing)
player = NULL;
if (!P_TeleportMove(thing, m->x, m->y, false)) /* killough 8/9/98 */
return 0;
if (!(demo_compatibility && gamemission >= pack_tnt))
thing->z = thing->floorz;
if (player)
player->viewz = thing->z + player->viewheight;
// spawn teleport fog and emit sound at source
S_StartSound(P_SpawnMobj(oldx, oldy, oldz, MT_TFOG), sfx_telept);
// spawn teleport fog and emit sound at destination
S_StartSound(P_SpawnMobj(m->x +
20*finecosine[m->angle>>ANGLETOFINESHIFT],
m->y +
20*finesine[m->angle>>ANGLETOFINESHIFT],
thing->z, MT_TFOG),
sfx_telept);
/* don't move for a bit
* cph - DEMOSYNC - BOOM had (player) here? */
if (thing->player)
thing->reactiontime = 18;
thing->angle = m->angle;
thing->momx = thing->momy = thing->momz = 0;
/* killough 10/98: kill all bobbing momentum too */
if (player)
player->momx = player->momy = 0;
return 1;
}
return 0;
}
//
// Silent TELEPORTATION, by Lee Killough
// Primarily for rooms-over-rooms etc.
//
int EV_SilentTeleport(line_t *line, int side, mobj_t *thing)
{
int i;
mobj_t *m;
thinker_t *th;
// don't teleport missiles
// Don't teleport if hit back of line,
// so you can get out of teleporter.
if (side || thing->flags & MF_MISSILE)
return 0;
for (i = -1; (i = P_FindSectorFromLineTag(line, i)) >= 0;)
for (th = thinkercap.next; th != &thinkercap; th = th->next)
if (th->function == P_MobjThinker &&
(m = (mobj_t *) th)->type == MT_TELEPORTMAN &&
m->subsector->sector-sectors == i)
{
// Height of thing above ground, in case of mid-air teleports:
fixed_t z = thing->z - thing->floorz;
// Get the angle between the exit thing and source linedef.
// Rotate 90 degrees, so that walking perpendicularly across
// teleporter linedef causes thing to exit in the direction
// indicated by the exit thing.
angle_t angle =
R_PointToAngle2(0, 0, line->dx, line->dy) - m->angle + ANG90;
// Sine, cosine of angle adjustment
fixed_t s = finesine[angle>>ANGLETOFINESHIFT];
fixed_t c = finecosine[angle>>ANGLETOFINESHIFT];
// Momentum of thing crossing teleporter linedef
fixed_t momx = thing->momx;
fixed_t momy = thing->momy;
// Whether this is a player, and if so, a pointer to its player_t
player_t *player = thing->player;
// Attempt to teleport, aborting if blocked
if (!P_TeleportMove(thing, m->x, m->y, false)) /* killough 8/9/98 */
return 0;
// Rotate thing according to difference in angles
thing->angle += angle;
// Adjust z position to be same height above ground as before
thing->z = z + thing->floorz;
// Rotate thing's momentum to come out of exit just like it entered
thing->momx = FixedMul(momx, c) - FixedMul(momy, s);
thing->momy = FixedMul(momy, c) + FixedMul(momx, s);
// Adjust player's view, in case there has been a height change
// Voodoo dolls are excluded by making sure player->mo == thing.
if (player && player->mo == thing)
{
// Save the current deltaviewheight, used in stepping
fixed_t deltaviewheight = player->deltaviewheight;
// Clear deltaviewheight, since we don't want any changes
player->deltaviewheight = 0;
// Set player's view according to the newly set parameters
P_CalcHeight(player);
// Reset the delta to have the same dynamics as before
player->deltaviewheight = deltaviewheight;
}
return 1;
}
return 0;
}
//
// Silent linedef-based TELEPORTATION, by Lee Killough
// Primarily for rooms-over-rooms etc.
// This is the complete player-preserving kind of teleporter.
// It has advantages over the teleporter with thing exits.
//
// maximum fixed_t units to move object to avoid hiccups
#define FUDGEFACTOR 10
int EV_SilentLineTeleport(line_t *line, int side, mobj_t *thing,
boolean reverse)
{
int i;
line_t *l;
if (side || thing->flags & MF_MISSILE)
return 0;
for (i = -1; (i = P_FindLineFromLineTag(line, i)) >= 0;)
if ((l=lines+i) != line && l->backsector)
{
// Get the thing's position along the source linedef
fixed_t pos = D_abs(line->dx) > D_abs(line->dy) ?
FixedDiv(thing->x - line->v1->x, line->dx) :
FixedDiv(thing->y - line->v1->y, line->dy) ;
// Get the angle between the two linedefs, for rotating
// orientation and momentum. Rotate 180 degrees, and flip
// the position across the exit linedef, if reversed.
angle_t angle = (reverse ? pos = FRACUNIT-pos, 0 : ANG180) +
R_PointToAngle2(0, 0, l->dx, l->dy) -
R_PointToAngle2(0, 0, line->dx, line->dy);
// Interpolate position across the exit linedef
fixed_t x = l->v2->x - FixedMul(pos, l->dx);
fixed_t y = l->v2->y - FixedMul(pos, l->dy);
// Sine, cosine of angle adjustment
fixed_t s = finesine[angle>>ANGLETOFINESHIFT];
fixed_t c = finecosine[angle>>ANGLETOFINESHIFT];
// Maximum distance thing can be moved away from interpolated
// exit, to ensure that it is on the correct side of exit linedef
int fudge = FUDGEFACTOR;
// Whether this is a player, and if so, a pointer to its player_t.
// Voodoo dolls are excluded by making sure thing->player->mo==thing.
player_t *player = thing->player && thing->player->mo == thing ?
thing->player : NULL;
// Whether walking towards first side of exit linedef steps down
int stepdown =
l->frontsector->floorheight < l->backsector->floorheight;
// Height of thing above ground
fixed_t z = thing->z - thing->floorz;
// Side to exit the linedef on positionally.
//
// Notes:
//
// This flag concerns exit position, not momentum. Due to
// roundoff error, the thing can land on either the left or
// the right side of the exit linedef, and steps must be
// taken to make sure it does not end up on the wrong side.
//
// Exit momentum is always towards side 1 in a reversed
// teleporter, and always towards side 0 otherwise.
//
// Exiting positionally on side 1 is always safe, as far
// as avoiding oscillations and stuck-in-wall problems,
// but may not be optimum for non-reversed teleporters.
//
// Exiting on side 0 can cause oscillations if momentum
// is towards side 1, as it is with reversed teleporters.
//
// Exiting on side 1 slightly improves player viewing
// when going down a step on a non-reversed teleporter.
int side = reverse || (player && stepdown);
// Make sure we are on correct side of exit linedef.
while (P_PointOnLineSide(x, y, l) != side && --fudge>=0)
if (D_abs(l->dx) > D_abs(l->dy))
y -= (l->dx < 0) != side ? -1 : 1;
else
x += (l->dy < 0) != side ? -1 : 1;
// Attempt to teleport, aborting if blocked
if (!P_TeleportMove(thing, x, y, false)) /* killough 8/9/98 */
return 0;
// Adjust z position to be same height above ground as before.
// Ground level at the exit is measured as the higher of the
// two floor heights at the exit linedef.
thing->z = z + sides[l->sidenum[stepdown]].sector->floorheight;
// Rotate thing's orientation according to difference in linedef angles
thing->angle += angle;
// Momentum of thing crossing teleporter linedef
x = thing->momx;
y = thing->momy;
// Rotate thing's momentum to come out of exit just like it entered
thing->momx = FixedMul(x, c) - FixedMul(y, s);
thing->momy = FixedMul(y, c) + FixedMul(x, s);
// Adjust a player's view, in case there has been a height change
if (player)
{
// Save the current deltaviewheight, used in stepping
fixed_t deltaviewheight = player->deltaviewheight;
// Clear deltaviewheight, since we don't want any changes now
player->deltaviewheight = 0;
// Set player's view according to the newly set parameters
P_CalcHeight(player);
// Reset the delta to have the same dynamics as before
player->deltaviewheight = deltaviewheight;
}
return 1;
}
return 0;
}

255
apps/plugins/doom/p_tick.c Normal file
View file

@ -0,0 +1,255 @@
/* Emacs style mode select -*- C++ -*-
*-----------------------------------------------------------------------------
*
*
* PrBoom a Doom port merged with LxDoom and LSDLDoom
* based on BOOM, a modified and improved DOOM engine
* Copyright (C) 1999 by
* id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
* Copyright (C) 1999-2000 by
* Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* DESCRIPTION:
* Thinker, Ticker.
*
*-----------------------------------------------------------------------------*/
#include "doomstat.h"
#include "p_user.h"
#include "p_spec.h"
#include "p_tick.h"
#include "p_map.h"
#include "rockmacros.h"
int leveltime;
//
// THINKERS
// All thinkers should be allocated by Z_Malloc
// so they can be operated on uniformly.
// The actual structures will vary in size,
// but the first element must be thinker_t.
//
// Both the head and tail of the thinker list.
thinker_t thinkercap;
// killough 8/29/98: we maintain several separate threads, each containing
// a special class of thinkers, to allow more efficient searches.
thinker_t thinkerclasscap[NUMTHCLASS];
//
// P_InitThinkers
//
void P_InitThinkers(void)
{
int i;
for (i=0; i<NUMTHCLASS; i++) // killough 8/29/98: initialize threaded lists
thinkerclasscap[i].cprev = thinkerclasscap[i].cnext = &thinkerclasscap[i];
thinkercap.prev = thinkercap.next = &thinkercap;
}
//
// killough 8/29/98:
//
// We maintain separate threads of friends and enemies, to permit more
// efficient searches.
//
void P_UpdateThinker(thinker_t *thinker)
{
// find the class the thinker belongs to
int class = thinker->function == P_MobjThinker &&
((mobj_t *) thinker)->health > 0 &&
(((mobj_t *) thinker)->flags & MF_COUNTKILL ||
((mobj_t *) thinker)->type == MT_SKULL) ?
((mobj_t *) thinker)->flags & MF_FRIEND ?
th_friends : th_enemies : th_misc;
// Remove from current thread
thinker_t *th = thinker->cnext;
(th->cprev = thinker->cprev)->cnext = th;
// Add to appropriate thread
th = &thinkerclasscap[class];
th->cprev->cnext = thinker;
thinker->cnext = th;
thinker->cprev = th->cprev;
th->cprev = thinker;
}
//
// P_AddThinker
// Adds a new thinker at the end of the list.
//
void P_AddThinker(thinker_t* thinker)
{
thinkercap.prev->next = thinker;
thinker->next = &thinkercap;
thinker->prev = thinkercap.prev;
thinkercap.prev = thinker;
thinker->references = 0; // killough 11/98: init reference counter to 0
// killough 8/29/98: set sentinel pointers, and then add to appropriate list
thinker->cnext = thinker->cprev = thinker;
P_UpdateThinker(thinker);
}
//
// killough 11/98:
//
// Make currentthinker external, so that P_RemoveThinkerDelayed
// can adjust currentthinker when thinkers self-remove.
static thinker_t *currentthinker;
//
// P_RemoveThinkerDelayed()
//
// Called automatically as part of the thinker loop in P_RunThinkers(),
// on nodes which are pending deletion.
//
// If this thinker has no more pointers referencing it indirectly,
// remove it, and set currentthinker to one node preceeding it, so
// that the next step in P_RunThinkers() will get its successor.
//
void P_RemoveThinkerDelayed(thinker_t *thinker)
{
if (!thinker->references)
{
thinker_t *next = thinker->next;
(next->prev = currentthinker = thinker->prev)->next = next;
Z_Free(thinker);
}
}
//
// P_RemoveThinker
//
// Deallocation is lazy -- it will not actually be freed
// until its thinking turn comes up.
//
// killough 4/25/98:
//
// Instead of marking the function with -1 value cast to a function pointer,
// set the function to P_RemoveThinkerDelayed(), so that later, it will be
// removed automatically as part of the thinker process.
//
void P_RemoveThinker(thinker_t *thinker)
{
thinker->function = P_RemoveThinkerDelayed;
// killough 8/29/98: remove immediately from threaded list
(thinker->cnext->cprev = thinker->cprev)->cnext = thinker->cnext;
}
/*
* P_SetTarget
*
* This function is used to keep track of pointer references to mobj thinkers.
* In Doom, objects such as lost souls could sometimes be removed despite
* their still being referenced. In Boom, 'target' mobj fields were tested
* during each gametic, and any objects pointed to by them would be prevented
* from being removed. But this was incomplete, and was slow (every mobj was
* checked during every gametic). Now, we keep a count of the number of
* references, and delay removal until the count is 0.
*/
void P_SetTarget(mobj_t **mop, mobj_t *targ)
{
if (*mop) // If there was a target already, decrease its refcount
(*mop)->thinker.references--;
if ((*mop = targ)) // Set new target and if non-NULL, increase its counter
targ->thinker.references++;
}
//
// P_RunThinkers
//
// killough 4/25/98:
//
// Fix deallocator to stop using "next" pointer after node has been freed
// (a Doom bug).
//
// Process each thinker. For thinkers which are marked deleted, we must
// load the "next" pointer prior to freeing the node. In Doom, the "next"
// pointer was loaded AFTER the thinker was freed, which could have caused
// crashes.
//
// But if we are not deleting the thinker, we should reload the "next"
// pointer after calling the function, in case additional thinkers are
// added at the end of the list.
//
// killough 11/98:
//
// Rewritten to delete nodes implicitly, by making currentthinker
// external and using P_RemoveThinkerDelayed() implicitly.
//
static void P_RunThinkers (void)
{
for (currentthinker = thinkercap.next;
currentthinker != &thinkercap;
currentthinker = currentthinker->next)
if (currentthinker->function)
currentthinker->function(currentthinker);
}
//
// P_Ticker
//
void P_Ticker (void)
{
int i;
/* pause if in menu and at least one tic has been run
*
* killough 9/29/98: note that this ties in with basetic,
* since G_Ticker does the pausing during recording or
* playback, and compenates by incrementing basetic.
*
* All of this complicated mess is used to preserve demo sync.
*/
if (paused || (menuactive && !demoplayback && !netgame &&
players[consoleplayer].viewz != 1))
return;
P_MapStart();
// not if this is an intermission screen
if(gamestate==GS_LEVEL)
for (i=0; i<MAXPLAYERS; i++)
if (playeringame[i])
P_PlayerThink(&players[i]);
P_RunThinkers();
P_UpdateSpecials();
P_RespawnSpecials();
P_MapEnd();
leveltime++; // for par times
}

View file

@ -0,0 +1,66 @@
/* Emacs style mode select -*- C++ -*-
*-----------------------------------------------------------------------------
*
*
* PrBoom a Doom port merged with LxDoom and LSDLDoom
* based on BOOM, a modified and improved DOOM engine
* Copyright (C) 1999 by
* id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
* Copyright (C) 1999-2000 by
* Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* DESCRIPTION:
* Core thinker processing prototypes.
*-----------------------------------------------------------------------------*/
#ifndef __P_TICK__
#define __P_TICK__
#include "d_think.h"
#ifdef __GNUG__
#pragma interface
#endif
/* Called by C_Ticker, can call G_PlayerExited.
* Carries out all thinking of monsters and players. */
void P_Ticker(void);
extern thinker_t thinkercap; // Both the head and tail of the thinker list
void P_InitThinkers(void);
void P_AddThinker(thinker_t *thinker);
void P_RemoveThinker(thinker_t *thinker);
void P_RemoveThinkerDelayed(thinker_t *thinker); // killough 4/25/98
void P_UpdateThinker(thinker_t *thinker); // killough 8/29/98
void P_SetTarget(mobj_t **mo, mobj_t *target); // killough 11/98
// killough 8/29/98: threads of thinkers, for more efficient searches
typedef enum {
th_misc,
th_friends,
th_enemies,
NUMTHCLASS
} th_class;
extern thinker_t thinkerclasscap[];
#endif

420
apps/plugins/doom/p_user.c Normal file
View file

@ -0,0 +1,420 @@
/* Emacs style mode select -*- C++ -*-
*-----------------------------------------------------------------------------
*
*
* PrBoom a Doom port merged with LxDoom and LSDLDoom
* based on BOOM, a modified and improved DOOM engine
* Copyright (C) 1999 by
* id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
* Copyright (C) 1999-2000 by
* Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* DESCRIPTION:
* Player related stuff.
* Bobbing POV/weapon, movement.
* Pending weapon.
*
*-----------------------------------------------------------------------------*/
#include "doomstat.h"
#include "d_event.h"
#include "r_main.h"
#include "p_map.h"
#include "p_spec.h"
#include "p_user.h"
#include "rockmacros.h"
// Index of the special effects (INVUL inverse) map.
#define INVERSECOLORMAP 32
//
// Movement.
//
// 16 pixels of bob
#define MAXBOB 0x100000
boolean onground; // whether player is on ground or in air
//
// P_Thrust
// Moves the given origin along a given angle.
//
void P_Thrust(player_t* player,angle_t angle,fixed_t move)
{
angle >>= ANGLETOFINESHIFT;
player->mo->momx += FixedMul(move,finecosine[angle]);
player->mo->momy += FixedMul(move,finesine[angle]);
}
/*
* P_Bob
* Same as P_Thrust, but only affects bobbing.
*
* killough 10/98: We apply thrust separately between the real physical player
* and the part which affects bobbing. This way, bobbing only comes from player
* motion, nothing external, avoiding many problems, e.g. bobbing should not
* occur on conveyors, unless the player walks on one, and bobbing should be
* reduced at a regular rate, even on ice (where the player coasts).
*/
void P_Bob(player_t *player, angle_t angle, fixed_t move)
{
player->momx += FixedMul(move,finecosine[angle >>= ANGLETOFINESHIFT]);
player->momy += FixedMul(move,finesine[angle]);
}
//
// P_CalcHeight
// Calculate the walking / running height adjustment
//
void P_CalcHeight (player_t* player)
{
int angle;
fixed_t bob;
// Regular movement bobbing
// (needs to be calculated for gun swing
// even if not on ground)
// OPTIMIZE: tablify angle
// Note: a LUT allows for effects
// like a ramp with low health.
/* killough 10/98: Make bobbing depend only on player-applied motion.
*
* Note: don't reduce bobbing here if on ice: if you reduce bobbing here,
* it causes bobbing jerkiness when the player moves from ice to non-ice,
* and vice-versa.
*/
player->bob = !mbf_features ?
(FixedMul (player->mo->momx, player->mo->momx)
+ FixedMul (player->mo->momy,player->mo->momy))>>2 :
player_bobbing ? (FixedMul(player->momx,player->momx) +
FixedMul(player->momy,player->momy))>>2 : 0;
if (player->bob > MAXBOB)
player->bob = MAXBOB;
if (!onground || player->cheats & CF_NOMOMENTUM)
{
player->viewz = player->mo->z + VIEWHEIGHT;
if (player->viewz > player->mo->ceilingz-4*FRACUNIT)
player->viewz = player->mo->ceilingz-4*FRACUNIT;
// The following line was in the Id source and appears // phares 2/25/98
// to be a bug. player->viewz is checked in a similar
// manner at a different exit below.
// player->viewz = player->mo->z + player->viewheight;
return;
}
angle = (FINEANGLES/20*leveltime)&FINEMASK;
bob = FixedMul(player->bob/2,finesine[angle]);
// move viewheight
if (player->playerstate == PST_LIVE)
{
player->viewheight += player->deltaviewheight;
if (player->viewheight > VIEWHEIGHT)
{
player->viewheight = VIEWHEIGHT;
player->deltaviewheight = 0;
}
if (player->viewheight < VIEWHEIGHT/2)
{
player->viewheight = VIEWHEIGHT/2;
if (player->deltaviewheight <= 0)
player->deltaviewheight = 1;
}
if (player->deltaviewheight)
{
player->deltaviewheight += FRACUNIT/4;
if (!player->deltaviewheight)
player->deltaviewheight = 1;
}
}
player->viewz = player->mo->z + player->viewheight + bob;
if (player->viewz > player->mo->ceilingz-4*FRACUNIT)
player->viewz = player->mo->ceilingz-4*FRACUNIT;
}
//
// P_MovePlayer
//
// Adds momentum if the player is not in the air
//
// killough 10/98: simplified
void P_MovePlayer (player_t* player)
{
ticcmd_t *cmd = &player->cmd;
mobj_t *mo = player->mo;
mo->angle += cmd->angleturn << 16;
onground = mo->z <= mo->floorz;
// killough 10/98:
//
// We must apply thrust to the player and bobbing separately, to avoid
// anomalies. The thrust applied to bobbing is always the same strength on
// ice, because the player still "works just as hard" to move, while the
// thrust applied to the movement varies with 'movefactor'.
if (cmd->forwardmove | cmd->sidemove) // killough 10/98
{
if (onground || mo->flags & MF_BOUNCES) // killough 8/9/98
{
int friction, movefactor = P_GetMoveFactor(mo, &friction);
// killough 11/98:
// On sludge, make bobbing depend on efficiency.
// On ice, make it depend on effort.
int bobfactor =
friction < ORIG_FRICTION ? movefactor : ORIG_FRICTION_FACTOR;
if (cmd->forwardmove)
{
P_Bob(player,mo->angle,cmd->forwardmove*bobfactor);
P_Thrust(player,mo->angle,cmd->forwardmove*movefactor);
}
if (cmd->sidemove)
{
P_Bob(player,mo->angle-ANG90,cmd->sidemove*bobfactor);
P_Thrust(player,mo->angle-ANG90,cmd->sidemove*movefactor);
}
}
if (mo->state == states+S_PLAY)
P_SetMobjState(mo,S_PLAY_RUN1);
}
}
#define ANG5 (ANG90/18)
//
// P_DeathThink
// Fall on your face when dying.
// Decrease POV height to floor height.
//
void P_DeathThink (player_t* player)
{
angle_t angle;
angle_t delta;
P_MovePsprites (player);
// fall to the ground
if (player->viewheight > 6*FRACUNIT)
player->viewheight -= FRACUNIT;
if (player->viewheight < 6*FRACUNIT)
player->viewheight = 6*FRACUNIT;
player->deltaviewheight = 0;
onground = (player->mo->z <= player->mo->floorz);
P_CalcHeight (player);
if (player->attacker && player->attacker != player->mo)
{
angle = R_PointToAngle2 (player->mo->x,
player->mo->y,
player->attacker->x,
player->attacker->y);
delta = angle - player->mo->angle;
if (delta < ANG5 || delta > (unsigned)-ANG5)
{
// Looking at killer,
// so fade damage flash down.
player->mo->angle = angle;
if (player->damagecount)
player->damagecount--;
}
else if (delta < ANG180)
player->mo->angle += ANG5;
else
player->mo->angle -= ANG5;
}
else if (player->damagecount)
player->damagecount--;
if (player->cmd.buttons & BT_USE)
player->playerstate = PST_REBORN;
}
//
// P_PlayerThink
//
void P_PlayerThink (player_t* player)
{
ticcmd_t* cmd;
weapontype_t newweapon;
// killough 2/8/98, 3/21/98:
if (player->cheats & CF_NOCLIP)
player->mo->flags |= MF_NOCLIP;
else
player->mo->flags &= ~MF_NOCLIP;
// chain saw run forward
cmd = &player->cmd;
if (player->mo->flags & MF_JUSTATTACKED)
{
cmd->angleturn = 0;
cmd->forwardmove = 0xc800/512;
cmd->sidemove = 0;
player->mo->flags &= ~MF_JUSTATTACKED;
}
if (player->playerstate == PST_DEAD)
{
P_DeathThink (player);
return;
}
// Move around.
// Reactiontime is used to prevent movement
// for a bit after a teleport.
if (player->mo->reactiontime)
player->mo->reactiontime--;
else
P_MovePlayer (player);
P_CalcHeight (player); // Determines view height and bobbing
// Determine if there's anything about the sector you're in that's
// going to affect you, like painful floors.
if (player->mo->subsector->sector->special)
P_PlayerInSpecialSector (player);
// Check for weapon change.
if (cmd->buttons & BT_CHANGE)
{
// The actual changing of the weapon is done
// when the weapon psprite can do it
// (read: not in the middle of an attack).
newweapon = (cmd->buttons & BT_WEAPONMASK)>>BT_WEAPONSHIFT;
// killough 3/22/98: For demo compatibility we must perform the fist
// and SSG weapons switches here, rather than in G_BuildTiccmd(). For
// other games which rely on user preferences, we must use the latter.
if (demo_compatibility)
{ // compatibility mode -- required for old demos -- killough
if (newweapon == wp_fist && player->weaponowned[wp_chainsaw] &&
(player->readyweapon != wp_chainsaw ||
!player->powers[pw_strength]))
newweapon = wp_chainsaw;
if (gamemode == commercial &&
newweapon == wp_shotgun &&
player->weaponowned[wp_supershotgun] &&
player->readyweapon != wp_supershotgun)
newweapon = wp_supershotgun;
}
// killough 2/8/98, 3/22/98 -- end of weapon selection changes
if (player->weaponowned[newweapon] && newweapon != player->readyweapon)
// Do not go to plasma or BFG in shareware,
// even if cheated.
if ((newweapon != wp_plasma && newweapon != wp_bfg)
|| (gamemode != shareware) )
player->pendingweapon = newweapon;
}
// check for use
if (cmd->buttons & BT_USE)
{
if (!player->usedown)
{
P_UseLines (player);
player->usedown = true;
}
}
else
player->usedown = false;
// cycle psprites
P_MovePsprites (player);
// Counters, time dependent power ups.
// Strength counts up to diminish fade.
if (player->powers[pw_strength])
player->powers[pw_strength]++;
// killough 1/98: Make idbeholdx toggle:
if (player->powers[pw_invulnerability] > 0) // killough
player->powers[pw_invulnerability]--;
if (player->powers[pw_invisibility] > 0) // killough
if (! --player->powers[pw_invisibility] )
player->mo->flags &= ~MF_SHADOW;
if (player->powers[pw_infrared] > 0) // killough
player->powers[pw_infrared]--;
if (player->powers[pw_ironfeet] > 0) // killough
player->powers[pw_ironfeet]--;
if (player->damagecount)
player->damagecount--;
if (player->bonuscount)
player->bonuscount--;
// Handling colormaps.
// killough 3/20/98: reformat to terse C syntax
player->fixedcolormap = player->powers[pw_invulnerability] > 4*32 ||
player->powers[pw_invulnerability] & 8 ? INVERSECOLORMAP :
player->powers[pw_infrared] > 4*32 || player->powers[pw_infrared] & 8;
}

View file

@ -0,0 +1,45 @@
/* Emacs style mode select -*- C++ -*-
*-----------------------------------------------------------------------------
*
*
* PrBoom a Doom port merged with LxDoom and LSDLDoom
* based on BOOM, a modified and improved DOOM engine
* Copyright (C) 1999 by
* id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
* Copyright (C) 1999-2000 by
* Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* DESCRIPTION:
* Player related stuff.
* Bobbing POV/weapon, movement.
* Pending weapon.
*
*-----------------------------------------------------------------------------*/
#ifndef __P_USER__
#define __P_USER__
#include "d_player.h"
void P_PlayerThink(player_t *player);
void P_CalcHeight(player_t *player);
void P_DeathThink(player_t *player);
void P_MovePlayer(player_t *player);
void P_Thrust(player_t *player, angle_t angle, fixed_t move);
#endif /* __P_USER__ */

576
apps/plugins/doom/r_bsp.c Normal file
View file

@ -0,0 +1,576 @@
/* Emacs style mode select -*- C++ -*-
*-----------------------------------------------------------------------------
*
*
* PrBoom a Doom port merged with LxDoom and LSDLDoom
* based on BOOM, a modified and improved DOOM engine
* Copyright (C) 1999 by
* id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
* Copyright (C) 1999-2000 by
* Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* DESCRIPTION:
* BSP traversal, handling of LineSegs for rendering.
*
*-----------------------------------------------------------------------------*/
#include "doomdef.h"
#include "m_bbox.h"
#include "i_system.h"
#include "r_main.h"
#include "r_plane.h"
#include "r_things.h"
// State.
#include "doomstat.h"
#include "r_state.h"
#include "r_segs.h"
#include "rockmacros.h"
seg_t *curline;
side_t *sidedef;
line_t *linedef;
sector_t *frontsector;
sector_t *backsector;
drawseg_t *ds_p;
drawseg_t *drawsegs;
unsigned maxdrawsegs;
//
// R_ClearDrawSegs
//
void R_ClearDrawSegs (void)
{
ds_p = drawsegs;
}
// CPhipps -
// Instead of clipsegs, let's try using an array with one entry for each column,
// indicating whether it's blocked by a solid wall yet or not.
byte solidcol[SCREENWIDTH] IBSS_ATTR;
// CPhipps -
// R_ClipWallSegment
//
// Replaces the old R_Clip*WallSegment functions. It draws bits of walls in those
// columns which aren't solid, and updates the solidcol[] array appropriately
void R_ClipWallSegment(int first, int last, boolean solid)
{
byte *p;
while (first < last) {
if (solidcol[first]) {
if (!(p = memchr(solidcol+first, 0, last-first))) return; // All solid
first = p - solidcol;
} else {
int to;
if (!(p = memchr(solidcol+first, 1, last-first))) to = last;
else to = p - solidcol;
R_StoreWallRange(first, to-1);
if (solid) {
memset(solidcol+first,1,to-first);
}
first = to;
}
}
}
//
// R_ClearClipSegs
//
void R_ClearClipSegs (void)
{
memset(solidcol, 0, SCREENWIDTH);
}
// killough 1/18/98 -- This function is used to fix the automap bug which
// showed lines behind closed doors simply because the door had a dropoff.
//
// cph - converted to R_RecalcLineFlags. This recalculates all the flags for
// a line, including closure and texture tiling.
static void R_RecalcLineFlags(void)
{
linedef->r_validcount = gametic;
/* First decide if the line is closed, normal, or invisible */
if (!(linedef->flags & ML_TWOSIDED)
|| backsector->ceilingheight <= frontsector->floorheight
|| backsector->floorheight >= frontsector->ceilingheight
|| (
// if door is closed because back is shut:
backsector->ceilingheight <= backsector->floorheight
// preserve a kind of transparent door/lift special effect:
&& (backsector->ceilingheight >= frontsector->ceilingheight ||
curline->sidedef->toptexture)
&& (backsector->floorheight <= frontsector->floorheight ||
curline->sidedef->bottomtexture)
// properly render skies (consider door "open" if both ceilings are sky):
&& (backsector->ceilingpic !=skyflatnum ||
frontsector->ceilingpic!=skyflatnum)
)
)
linedef->r_flags = RF_CLOSED;
else {
// Reject empty lines used for triggers
// and special events.
// Identical floor and ceiling on both sides,
// identical light levels on both sides,
// and no middle texture.
// CPhipps - recode for speed, not certain if this is portable though
if (backsector->ceilingheight != frontsector->ceilingheight
|| backsector->floorheight != frontsector->floorheight
|| curline->sidedef->midtexture
|| memcmp(&backsector->floor_xoffs, &frontsector->floor_xoffs,
sizeof(frontsector->floor_xoffs) + sizeof(frontsector->floor_yoffs) +
sizeof(frontsector->ceiling_xoffs) + sizeof(frontsector->ceiling_yoffs) +
sizeof(frontsector->ceilingpic) + sizeof(frontsector->floorpic) +
sizeof(frontsector->lightlevel) + sizeof(frontsector->floorlightsec) +
sizeof(frontsector->ceilinglightsec))) {
linedef->r_flags = 0; return;
} else
linedef->r_flags = RF_IGNORE;
}
/* cph - I'm too lazy to try and work with offsets in this */
if (curline->sidedef->rowoffset) return;
/* Now decide on texture tiling */
if (linedef->flags & ML_TWOSIDED) {
int c;
/* Does top texture need tiling */
if ((c = frontsector->ceilingheight - backsector->ceilingheight) > 0 &&
(textureheight[texturetranslation[curline->sidedef->toptexture]] > c))
linedef->r_flags |= RF_TOP_TILE;
/* Does bottom texture need tiling */
if ((c = frontsector->floorheight - backsector->floorheight) > 0 &&
(textureheight[texturetranslation[curline->sidedef->bottomtexture]] > c))
linedef->r_flags |= RF_BOT_TILE;
} else {
int c;
/* Does middle texture need tiling */
if ((c = frontsector->ceilingheight - frontsector->floorheight) > 0 &&
(textureheight[texturetranslation[curline->sidedef->midtexture]] > c))
linedef->r_flags |= RF_MID_TILE;
}
}
//
// killough 3/7/98: Hack floor/ceiling heights for deep water etc.
//
// If player's view height is underneath fake floor, lower the
// drawn ceiling to be just under the floor height, and replace
// the drawn floor and ceiling textures, and light level, with
// the control sector's.
//
// Similar for ceiling, only reflected.
//
// killough 4/11/98, 4/13/98: fix bugs, add 'back' parameter
//
sector_t *R_FakeFlat(sector_t *sec, sector_t *tempsec,
int *floorlightlevel, int *ceilinglightlevel,
boolean back)
{
if (floorlightlevel)
*floorlightlevel = sec->floorlightsec == -1 ?
sec->lightlevel : sectors[sec->floorlightsec].lightlevel;
if (ceilinglightlevel)
*ceilinglightlevel = sec->ceilinglightsec == -1 ? // killough 4/11/98
sec->lightlevel : sectors[sec->ceilinglightsec].lightlevel;
if (sec->heightsec != -1)
{
const sector_t *s = &sectors[sec->heightsec];
int heightsec = viewplayer->mo->subsector->sector->heightsec;
int underwater = heightsec!=-1 && viewz<=sectors[heightsec].floorheight;
// Replace sector being drawn, with a copy to be hacked
*tempsec = *sec;
// Replace floor and ceiling height with other sector's heights.
tempsec->floorheight = s->floorheight;
tempsec->ceilingheight = s->ceilingheight;
// killough 11/98: prevent sudden light changes from non-water sectors:
if (underwater && (tempsec-> floorheight = sec->floorheight,
tempsec->ceilingheight = s->floorheight-1, !back))
{ // head-below-floor hack
tempsec->floorpic = s->floorpic;
tempsec->floor_xoffs = s->floor_xoffs;
tempsec->floor_yoffs = s->floor_yoffs;
if (underwater) {
if (s->ceilingpic == skyflatnum) {
tempsec->floorheight = tempsec->ceilingheight+1;
tempsec->ceilingpic = tempsec->floorpic;
tempsec->ceiling_xoffs = tempsec->floor_xoffs;
tempsec->ceiling_yoffs = tempsec->floor_yoffs;
} else {
tempsec->ceilingpic = s->ceilingpic;
tempsec->ceiling_xoffs = s->ceiling_xoffs;
tempsec->ceiling_yoffs = s->ceiling_yoffs;
}
}
tempsec->lightlevel = s->lightlevel;
if (floorlightlevel)
*floorlightlevel = s->floorlightsec == -1 ? s->lightlevel :
sectors[s->floorlightsec].lightlevel; // killough 3/16/98
if (ceilinglightlevel)
*ceilinglightlevel = s->ceilinglightsec == -1 ? s->lightlevel :
sectors[s->ceilinglightsec].lightlevel; // killough 4/11/98
}
else
if (heightsec != -1 && viewz >= sectors[heightsec].ceilingheight &&
sec->ceilingheight > s->ceilingheight)
{ // Above-ceiling hack
tempsec->ceilingheight = s->ceilingheight;
tempsec->floorheight = s->ceilingheight + 1;
tempsec->floorpic = tempsec->ceilingpic = s->ceilingpic;
tempsec->floor_xoffs = tempsec->ceiling_xoffs = s->ceiling_xoffs;
tempsec->floor_yoffs = tempsec->ceiling_yoffs = s->ceiling_yoffs;
if (s->floorpic != skyflatnum)
{
tempsec->ceilingheight = sec->ceilingheight;
tempsec->floorpic = s->floorpic;
tempsec->floor_xoffs = s->floor_xoffs;
tempsec->floor_yoffs = s->floor_yoffs;
}
tempsec->lightlevel = s->lightlevel;
if (floorlightlevel)
*floorlightlevel = s->floorlightsec == -1 ? s->lightlevel :
sectors[s->floorlightsec].lightlevel; // killough 3/16/98
if (ceilinglightlevel)
*ceilinglightlevel = s->ceilinglightsec == -1 ? s->lightlevel :
sectors[s->ceilinglightsec].lightlevel; // killough 4/11/98
}
sec = tempsec; // Use other sector
}
return sec;
}
//
// R_AddLine
// Clips the given segment
// and adds any visible pieces to the line list.
//
static void R_AddLine (seg_t *line)
{
int x1;
int x2;
angle_t angle1;
angle_t angle2;
angle_t span;
angle_t tspan;
static sector_t tempsec; // killough 3/8/98: ceiling/water hack
// boolean solid = true;
curline = line;
angle1 = R_PointToAngle (line->v1->x, line->v1->y);
angle2 = R_PointToAngle (line->v2->x, line->v2->y);
// Clip to view edges.
span = angle1 - angle2;
// Back side, i.e. backface culling
if (span >= ANG180)
return;
// Global angle needed by segcalc.
rw_angle1 = angle1;
angle1 -= viewangle;
angle2 -= viewangle;
tspan = angle1 + clipangle;
if (tspan > 2*clipangle)
{
tspan -= 2*clipangle;
// Totally off the left edge?
if (tspan >= span)
return;
angle1 = clipangle;
}
tspan = clipangle - angle2;
if (tspan > 2*clipangle)
{
tspan -= 2*clipangle;
// Totally off the left edge?
if (tspan >= span)
return;
angle2 = 0-clipangle;
}
// The seg is in the view range,
// but not necessarily visible.
angle1 = (angle1+ANG90)>>ANGLETOFINESHIFT;
angle2 = (angle2+ANG90)>>ANGLETOFINESHIFT;
// killough 1/31/98: Here is where "slime trails" can SOMETIMES occur:
x1 = viewangletox[angle1];
x2 = viewangletox[angle2];
// Does not cross a pixel?
if (x1 >= x2) // killough 1/31/98 -- change == to >= for robustness
return;
backsector = line->backsector;
// Single sided line?
if (backsector)
// killough 3/8/98, 4/4/98: hack for invisible ceilings / deep water
backsector = R_FakeFlat(backsector, &tempsec, NULL, NULL, true);
/* cph - roll up linedef properties in flags */
if ((linedef = curline->linedef)->r_validcount != gametic)
R_RecalcLineFlags();
if (linedef->r_flags & RF_IGNORE)
{
return;
}
else
R_ClipWallSegment (x1, x2, linedef->r_flags & RF_CLOSED);
}
//
// R_CheckBBox
// Checks BSP node/subtree bounding box.
// Returns true
// if some part of the bbox might be visible.
//
static const int checkcoord[12][4] = // killough -- static const
{
{3,0,2,1},
{3,0,2,0},
{3,1,2,0},
{0},
{2,0,2,1},
{0,0,0,0},
{3,1,3,0},
{0},
{2,0,3,1},
{2,1,3,1},
{2,1,3,0}
};
// killough 1/28/98: static // CPhipps - const parameter, reformatted
static boolean R_CheckBBox(const fixed_t *bspcoord)
{
angle_t angle1, angle2;
{
int boxpos;
const int* check;
// Find the corners of the box
// that define the edges from current viewpoint.
boxpos = (viewx <= bspcoord[BOXLEFT] ? 0 : viewx < bspcoord[BOXRIGHT ] ? 1 : 2) +
(viewy >= bspcoord[BOXTOP ] ? 0 : viewy > bspcoord[BOXBOTTOM] ? 4 : 8);
if (boxpos == 5)
return true;
check = checkcoord[boxpos];
angle1 = R_PointToAngle (bspcoord[check[0]], bspcoord[check[1]]) - viewangle;
angle2 = R_PointToAngle (bspcoord[check[2]], bspcoord[check[3]]) - viewangle;
}
// cph - replaced old code, which was unclear and badly commented
// Much more efficient code now
if ((signed)angle1 < (signed)angle2) { /* it's "behind" us */
/* Either angle1 or angle2 is behind us, so it doesn't matter if we
* change it to the corect sign
*/
if ((angle1 >= ANG180) && (angle1 < ANG270))
angle1 = INT_MAX; /* which is ANG180-1 */
else
angle2 = INT_MIN;
}
if ((signed)angle2 >= (signed)clipangle) return false; // Both off left edge
if ((signed)angle1 <= -(signed)clipangle) return false; // Both off right edge
if ((signed)angle1 >= (signed)clipangle) angle1 = clipangle; // Clip at left edge
if ((signed)angle2 <= -(signed)clipangle) angle2 = 0-clipangle; // Clip at right edge
// Find the first clippost
// that touches the source post
// (adjacent pixels are touching).
angle1 = (angle1+ANG90)>>ANGLETOFINESHIFT;
angle2 = (angle2+ANG90)>>ANGLETOFINESHIFT;
{
int sx1 = viewangletox[angle1];
int sx2 = viewangletox[angle2];
// const cliprange_t *start;
// Does not cross a pixel.
if (sx1 == sx2)
return false;
if (!memchr(solidcol+sx1, 0, sx2-sx1)) return false;
// All columns it covers are already solidly covered
}
return true;
}
//
// R_Subsector
// Determine floor/ceiling planes.
// Add sprites of things in sector.
// Draw one or more line segments.
//
// killough 1/31/98 -- made static, polished
// Had to move this out of the function - causes stack overflows in RockBox
sector_t tempsec IBSS_ATTR; // killough 3/7/98: deep water hack
static void R_Subsector(int num)
{
int count;
seg_t *line;
subsector_t *sub;
int floorlightlevel; // killough 3/16/98: set floor lightlevel
int ceilinglightlevel; // killough 4/11/98
#ifdef RANGECHECK
if (num>=numsubsectors)
I_Error ("R_Subsector: ss %i with numss = %i", num, numsubsectors);
#endif
sub = &subsectors[num];
frontsector = sub->sector;
count = sub->numlines;
line = &segs[sub->firstline];
// sscount++;
// killough 3/8/98, 4/4/98: Deep water / fake ceiling effect
frontsector = R_FakeFlat(frontsector, &tempsec, &floorlightlevel,
&ceilinglightlevel, false); // killough 4/11/98
// killough 3/7/98: Add (x,y) offsets to flats, add deep water check
// killough 3/16/98: add floorlightlevel
// killough 10/98: add support for skies transferred from sidedefs
floorplane = frontsector->floorheight < viewz || // killough 3/7/98
(frontsector->heightsec != -1 &&
sectors[frontsector->heightsec].ceilingpic == skyflatnum)
?
R_FindPlane(frontsector->floorheight,
frontsector->floorpic == skyflatnum && // kilough 10/98
frontsector->sky & PL_SKYFLAT ? frontsector->sky :
frontsector->floorpic,
floorlightlevel, // killough 3/16/98
frontsector->floor_xoffs, // killough 3/7/98
frontsector->floor_yoffs
) : NULL;
ceilingplane = frontsector->ceilingheight > viewz ||
frontsector->ceilingpic == skyflatnum ||
(frontsector->heightsec != -1 &&
sectors[frontsector->heightsec].floorpic == skyflatnum)
?
R_FindPlane(frontsector->ceilingheight, // killough 3/8/98
frontsector->ceilingpic == skyflatnum && // kilough 10/98
frontsector->sky & PL_SKYFLAT ? frontsector->sky :
frontsector->ceilingpic,
ceilinglightlevel, // killough 4/11/98
frontsector->ceiling_xoffs, // killough 3/7/98
frontsector->ceiling_yoffs
) : NULL;
// killough 9/18/98: Fix underwater slowdown, by passing real sector
// instead of fake one. Improve sprite lighting by basing sprite
// lightlevels on floor & ceiling lightlevels in the surrounding area.
//
// 10/98 killough:
//
// NOTE: TeamTNT fixed this bug incorrectly, messing up sprite lighting!!!
// That is part of the 242 effect!!! If you simply pass sub->sector to
// the old code you will not get correct lighting for underwater sprites!!!
// Either you must pass the fake sector and handle validcount here, on the
// real sector, or you must account for the lighting in some other way,
// like passing it as an argument.
R_AddSprites(sub, (floorlightlevel+ceilinglightlevel)/2);
while (count--)
{
if (line->miniseg == false)
R_AddLine (line);
line++;
}
}
//
// RenderBSPNode
// Renders all subsectors below a given node,
// traversing subtree recursively.
// Just call with BSP root.
//
// killough 5/2/98: reformatted, removed tail recursion
void R_RenderBSPNode(int bspnum)
{
while (!(bspnum & NF_SUBSECTOR)) // Found a subsector?
{
const node_t *bsp = &nodes[bspnum];
// Decide which side the view point is on.
int side = R_PointOnSide(viewx, viewy, bsp);
// Recursively divide front space.
R_RenderBSPNode(bsp->children[side]);
// Possibly divide back space.
if (!R_CheckBBox(bsp->bbox[side^1]))
return;
bspnum = bsp->children[side^1];
}
R_Subsector(bspnum == -1 ? 0 : bspnum & ~NF_SUBSECTOR);
}

78
apps/plugins/doom/r_bsp.h Normal file
View file

@ -0,0 +1,78 @@
/* Emacs style mode select -*- C++ -*-
*-----------------------------------------------------------------------------
*
*
* PrBoom a Doom port merged with LxDoom and LSDLDoom
* based on BOOM, a modified and improved DOOM engine
* Copyright (C) 1999 by
* id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
* Copyright (C) 1999-2000 by
* Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* DESCRIPTION:
* Refresh module, BSP traversal and handling.
*
*-----------------------------------------------------------------------------*/
#ifndef __R_BSP__
#define __R_BSP__
#ifdef __GNUG__
#pragma interface
#endif
extern seg_t *curline;
extern side_t *sidedef;
extern line_t *linedef;
extern sector_t *frontsector;
extern sector_t *backsector;
extern int rw_x;
extern int rw_stopx;
extern boolean segtextured;
extern boolean markfloor; /* false if the back side is the same plane */
extern boolean markceiling;
//extern boolean skymap;
/* old code -- killough:
* extern drawseg_t drawsegs[MAXDRAWSEGS];
* new code -- killough: */
extern drawseg_t *drawsegs;
extern unsigned maxdrawsegs;
extern drawseg_t* ds_p;
/*extern lighttable_t** hscalelight;
extern lighttable_t** vscalelight;
extern lighttable_t** dscalelight;
*/
//typedef void (*drawfunc_t) (int start, int stop);
// BSP?
void R_ClearClipSegs (void);
void R_ClearDrawSegs (void);
void R_RenderBSPNode (int bspnum);
int R_DoorClosed(void); /* killough 1/17/98 */
/* killough 4/13/98: fake floors/ceilings for deep water / fake ceilings: */
sector_t *R_FakeFlat(sector_t *, sector_t *, int *, int *, boolean);
#endif

975
apps/plugins/doom/r_data.c Normal file
View file

@ -0,0 +1,975 @@
/* Emacs style mode select -*- C++ -*-
*-----------------------------------------------------------------------------
*
*
* PrBoom a Doom port merged with LxDoom and LSDLDoom
* based on BOOM, a modified and improved DOOM engine
* Copyright (C) 1999 by
* id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
* Copyright (C) 1999-2000 by
* Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* DESCRIPTION:
* Preparation of data for rendering,
* generation of lookups, caching, retrieval by name.
*
*-----------------------------------------------------------------------------*/
#include "doomstat.h"
#include "w_wad.h"
#include "r_main.h"
#include "r_sky.h"
#include "i_system.h"
#include "m_swap.h"
#include "p_tick.h"
//#include "lprintf.h" // jff 08/03/98 - declaration of lprintf
#include "rockmacros.h"
//
// Graphics.
// DOOM graphics for walls and sprites
// is stored in vertical runs of opaque pixels (posts).
// A column is composed of zero or more posts,
// a patch or sprite is composed of zero or more columns.
//
//
// Texture definition.
// Each texture is composed of one or more patches,
// with patches being lumps stored in the WAD.
// The lumps are referenced by number, and patched
// into the rectangular texture space using origin
// and possibly other attributes.
//
typedef struct
{
short originx;
short originy;
short patch;
short stepdir; // unused in Doom but might be used in Phase 2 Boom
short colormap; // unused in Doom but might be used in Phase 2 Boom
} PACKEDATTR mappatch_t;
typedef struct
{
char name[8];
boolean masked;
short width;
short height;
char pad[4]; // unused in Doom but might be used in Boom Phase 2
short patchcount;
mappatch_t patches[1];
} PACKEDATTR maptexture_t;
// A maptexturedef_t describes a rectangular texture, which is composed
// of one or more mappatch_t structures that arrange graphic patches.
// killough 4/17/98: make firstcolormaplump,lastcolormaplump external
int firstcolormaplump, lastcolormaplump; // killough 4/17/98
int firstflat, lastflat, numflats;
int firstspritelump, lastspritelump, numspritelumps;
int numtextures;
static texture_t **textures;
fixed_t *textureheight; //needed for texture pegging (and TFE fix - killough)
int *flattranslation; // for global animation
int *texturetranslation;
// needed for pre-rendering
fixed_t *spritewidth, *spriteoffset, *spritetopoffset;
//
// MAPTEXTURE_T CACHING
// When a texture is first needed,
// it counts the number of composite columns
// required in the texture and allocates space
// for a column directory and any new columns.
// The directory will simply point inside other patches
// if there is only one patch in a given column,
// but any columns with multiple patches
// will have new column_ts generated.
//
//
// R_DrawColumnInCache
// Clip and draw a column
// from a patch into a cached post.
//
// Rewritten by Lee Killough for performance and to fix Medusa bug
//
void R_DrawColumnInCache(const column_t *patch, byte *cache,
int originy, int cacheheight, byte *marks)
{
while (patch->topdelta != 0xff)
{
int count = patch->length;
int position = originy + patch->topdelta;
if (position < 0)
{
count += position;
position = 0;
}
if (position + count > cacheheight)
count = cacheheight - position;
if (count > 0)
{
memcpy (cache + position, (byte *)patch + 3, count);
// killough 4/9/98: remember which cells in column have been drawn,
// so that column can later be converted into a series of posts, to
// fix the Medusa bug.
memset (marks + position, 0xff, count);
}
patch = (column_t *)((byte *) patch + patch->length + 4);
}
}
//
// R_GenerateComposite
// Using the texture definition,
// the composite texture is created from the patches,
// and each column is cached.
//
// Rewritten by Lee Killough for performance and to fix Medusa bug
void R_GenerateComposite(int texnum)
{
texture_t *texture = textures[texnum];
byte *block = Z_Malloc(texture->compositesize, PU_STATIC,
(void **)&texture->composite);
// Composite the columns together.
texpatch_t *patch = texture->patches;
short *collump = texture->columnlump;
unsigned *colofs = texture->columnofs; // killough 4/9/98: make 32-bit
int i = texture->patchcount;
// killough 4/9/98: marks to identify transparent regions in merged textures
byte *marks = calloc(texture->width, texture->height), *source;
for (; --i >=0; patch++)
{
const patch_t *realpatch = W_CacheLumpNum(patch->patch); // cph
int x1 = patch->originx, x2 = x1 + SHORT(realpatch->width);
const int *cofs = realpatch->columnofs-x1;
if (x1<0)
x1 = 0;
if (x2 > texture->width)
x2 = texture->width;
for (; x1<x2 ; x1++)
if (collump[x1] == -1) // Column has multiple patches?
// killough 1/25/98, 4/9/98: Fix medusa bug.
R_DrawColumnInCache((column_t*)((byte*)realpatch+LONG(cofs[x1])),
block+colofs[x1],patch->originy,texture->height,
marks + x1 * texture->height);
W_UnlockLumpNum(patch->patch); // cph - unlock the patch lump
}
// killough 4/9/98: Next, convert multipatched columns into true columns,
// to fix Medusa bug while still allowing for transparent regions.
source = malloc(texture->height); // temporary column
for (i=0; i < texture->width; i++)
if (collump[i] == -1) // process only multipatched columns
{
column_t *col = (column_t *)(block + colofs[i] - 3); // cached column
const byte *mark = marks + i * texture->height;
int j = 0;
// save column in temporary so we can shuffle it around
memcpy(source, (byte *) col + 3, texture->height);
for (;;) // reconstruct the column by scanning transparency marks
{
while (j < texture->height && !mark[j]) // skip transparent cells
j++;
if (j >= texture->height) // if at end of column
{
col->topdelta = -1; // end-of-column marker
break;
}
col->topdelta = j; // starting offset of post
for (col->length=0; j < texture->height && mark[j]; j++)
col->length++; // count opaque cells
// copy opaque cells from the temporary back into the column
memcpy((byte *) col + 3, source + col->topdelta, col->length);
col = (column_t *)((byte *) col + col->length + 4); // next post
}
}
free(source); // free temporary column
free(marks); // free transparency marks
// Now that the texture has been built in column cache,
// it is purgable from zone memory.
Z_ChangeTag(block, PU_CACHE);
}
//
// R_GenerateLookup
//
// Rewritten by Lee Killough for performance and to fix Medusa bug
//
static void R_GenerateLookup(int texnum, int *const errors)
{
texture_t *texture = textures[texnum];
// killough 4/9/98: make column offsets 32-bit;
// clean up malloc-ing to use sizeof
// CPhipps - moved allocing here
short *collump = texture->columnlump =
Z_Malloc(texture->width*sizeof(*texture->columnlump), PU_STATIC,0);
unsigned *colofs = texture->columnofs =
Z_Malloc(texture->width*sizeof(*texture->columnofs), PU_STATIC,0);
// killough 4/9/98: keep count of posts in addition to patches.
// Part of fix for medusa bug for multipatched 2s normals.
struct {
unsigned short patches, posts;
} *count = calloc(sizeof *count, texture->width);
{
int i = texture->patchcount;
const texpatch_t *patch = texture->patches;
while (--i >= 0)
{
int pat = patch->patch;
const patch_t *realpatch = W_CacheLumpNum(pat);
int x1 = patch++->originx, x2 = x1 + SHORT(realpatch->width), x = x1;
const int *cofs = realpatch->columnofs-x1;
if (x2 > texture->width)
x2 = texture->width;
if (x1 < 0)
x = 0;
for ( ; x<x2 ; x++)
{
// killough 4/9/98: keep a count of the number of posts in column,
// to fix Medusa bug while allowing for transparent multipatches.
const column_t *col = (column_t*)((byte*)realpatch+LONG(cofs[x]));
for (;col->topdelta != 0xff; count[x].posts++)
col = (column_t *)((byte *) col + col->length + 4);
count[x].patches++;
collump[x] = pat;
colofs[x] = LONG(cofs[x])+3;
}
W_UnlockLumpNum(pat);
}
}
// Composited texture not created yet.
texture->composite = NULL;
// Now count the number of columns
// that are covered by more than one patch.
// Fill in the lump / offset, so columns
// with only a single patch are all done.
{
int x = texture->width;
int height = texture->height;
int csize = 0;
while (--x >= 0)
{
if (!count[x].patches) // killough 4/9/98
{
//jff 8/3/98 use logical output routine
printf("\nR_GenerateLookup: Column %d is without a patch in texture %s",
x, texture->name);
if (errors) ++*errors;
else I_Error("R_GenerateLookup: Failed");
}
if (count[x].patches > 1) // killough 4/9/98
{
// killough 1/25/98, 4/9/98:
//
// Fix Medusa bug, by adding room for column header
// and trailer bytes for each post in merged column.
// For now, just allocate conservatively 4 bytes
// per post per patch per column, since we don't
// yet know how many posts the merged column will
// require, and it's bounded above by this limit.
collump[x] = -1; // mark lump as multipatched
colofs[x] = csize + 3; // three header bytes in a column
csize += 4*count[x].posts+1; // 1 stop byte plus 4 bytes per post
}
csize += height; // height bytes of texture data
}
texture->compositesize = csize;
}
free(count); // killough 4/9/98
}
//
// R_GetColumn
//
const byte *R_GetColumn(int tex, int col)
{
const texture_t *texture = textures[tex];
if (!texture->columnlump) R_GenerateLookup(tex, NULL);
{
int lump = texture->columnlump[col &= texture->widthmask];
int ofs = texture->columnofs[col]; // cph - WARNING: must be after the above line
// cph - remember the last lump, so we can unlock it if no longer needed,
// or reuse it if possible to reduce lump locking/unlocking
static int lastlump = -1;
static const byte* lastlumpdata;
if ((lump<=0) && (lastlump<=0))
lump = lastlump; // cph - force equal
if (lump != lastlump) {
// cph - must change the cached lump
if (lastlump>0)
W_UnlockLumpNum(lastlump);
if ((lastlump = lump) > 0)
lastlumpdata = W_CacheLumpNum(lump);
#ifdef RANGECHECK
else
lastlumpdata = NULL;
#endif
}
if (lump > 0)
return lastlumpdata + ofs;
if (!texture->composite)
R_GenerateComposite(tex);
return texture->composite + ofs;
}
}
//
// R_InitTextures
// Initializes the texture list
// with the textures from the world map.
//
void R_InitTextures (void)
{
maptexture_t *mtexture;
texture_t *texture;
mappatch_t *mpatch;
texpatch_t *patch;
int i, j;
int maptex_lump[2] = {-1, -1};
const int *maptex;
const int *maptex1, *maptex2;
char name[9];
int names_lump; // cph - new wad lump handling
const char *names; // cph -
const char *name_p;// const*'s
int *patchlookup;
int totalwidth;
int nummappatches;
int offset;
int maxoff, maxoff2;
int numtextures1, numtextures2;
const int *directory;
int errors = 0;
// Load the patch names from pnames.lmp.
name[8] = 0;
names = W_CacheLumpNum(names_lump = W_GetNumForName("PNAMES"));
nummappatches = LONG(*((const int *)names));
name_p = names+4;
patchlookup = malloc(nummappatches*sizeof(*patchlookup)); // killough
for (i=0 ; i<nummappatches ; i++)
{
strncpy (name,name_p+i*8, 8);
patchlookup[i] = W_CheckNumForName(name);
if (patchlookup[i] == -1)
{
// killough 4/17/98:
// Some wads use sprites as wall patches, so repeat check and
// look for sprites this time, but only if there were no wall
// patches found. This is the same as allowing for both, except
// that wall patches always win over sprites, even when they
// appear first in a wad. This is a kludgy solution to the wad
// lump namespace problem.
patchlookup[i] = (W_CheckNumForName)(name, ns_sprites);
if (patchlookup[i] == -1 && devparm)
//jff 8/3/98 use logical output routine
printf("\nWarning: patch %.8s, index %d does not exist",name,i);
}
}
W_UnlockLumpNum(names_lump); // cph - release the lump
// Load the map texture definitions from textures.lmp.
// The data is contained in one or two lumps,
// TEXTURE1 for shareware, plus TEXTURE2 for commercial.
maptex = maptex1 = W_CacheLumpNum(maptex_lump[0] = W_GetNumForName("TEXTURE1"));
numtextures1 = LONG(*maptex);
maxoff = W_LumpLength(maptex_lump[0]);
directory = maptex+1;
if (W_CheckNumForName("TEXTURE2") != -1)
{
maptex2 = W_CacheLumpNum(maptex_lump[1] = W_GetNumForName("TEXTURE2"));
numtextures2 = LONG(*maptex2);
maxoff2 = W_LumpLength(maptex_lump[1]);
}
else
{
maptex2 = NULL;
numtextures2 = 0;
maxoff2 = 0;
}
numtextures = numtextures1 + numtextures2;
// killough 4/9/98: make column offsets 32-bit;
// clean up malloc-ing to use sizeof
textures = Z_Malloc(numtextures*sizeof*textures, PU_STATIC, 0);
textureheight = Z_Malloc(numtextures*sizeof*textureheight, PU_STATIC, 0);
totalwidth = 0;
for (i=0 ; i<numtextures ; i++, directory++)
{
if (i == numtextures1)
{
// Start looking in second texture file.
maptex = maptex2;
maxoff = maxoff2;
directory = maptex+1;
}
offset = LONG(*directory);
if (offset > maxoff)
I_Error("R_InitTextures: Bad texture directory");
mtexture = (maptexture_t *) ( (byte *)maptex + offset);
texture = textures[i] =
Z_Malloc(sizeof(texture_t) +
sizeof(texpatch_t)*(SHORT(mtexture->patchcount)-1),
PU_STATIC, 0);
texture->width = SHORT(mtexture->width);
texture->height = SHORT(mtexture->height);
texture->patchcount = SHORT(mtexture->patchcount);
/* Mattias Engdegård emailed me of the following explenation of
* why memcpy doesnt work on some systems:
* "I suppose it is the mad unaligned allocation
* going on (and which gcc in some way manages to cope with
* through the __attribute__ ((packed))), and which it forgets
* when optimizing memcpy (to a single word move) since it appears
* to be aligned. Technically a gcc bug, but I can't blame it when
* it's stressed with that amount of
* non-standard nonsense."
* So in short the unaligned struct confuses gcc's optimizer so
* i took the memcpy out alltogether to avoid future problems-Jess
*/
/* The above was #ifndef SPARC, but i got a mail from
* Putera Joseph F NPRI <PuteraJF@Npt.NUWC.Navy.Mil> containing:
* I had to use the memcpy function on a sparc machine. The
* other one would give me a core dump.
* cph - I find it hard to believe that sparc memcpy is broken,
* but I don't believe the pointers to memcpy have to be aligned
* either. Use fast memcpy on other machines anyway.
*/
/*
proff - I took this out, because Oli Kraus (olikraus@yahoo.com) told
me the memcpy produced a buserror. Since this function isn't time-
critical I'm using the for loop now.
*/
/*
#ifndef GCC
memcpy(texture->name, mtexture->name, sizeof(texture->name));
#else
*/
{
unsigned int j;
for(j=0;j<sizeof(texture->name);j++)
texture->name[j]=mtexture->name[j];
}
/* #endif */
mpatch = mtexture->patches;
patch = texture->patches;
for (j=0 ; j<texture->patchcount ; j++, mpatch++, patch++)
{
patch->originx = SHORT(mpatch->originx);
patch->originy = SHORT(mpatch->originy);
patch->patch = patchlookup[SHORT(mpatch->patch)];
if (patch->patch == -1)
{
//jff 8/3/98 use logical output routine
printf("\nR_InitTextures: Missing patch %d in texture %s",
SHORT(mpatch->patch), texture->name); // killough 4/17/98
++errors;
}
}
texture->columnofs = NULL; texture->columnlump = NULL;
for (j=1; j*2 <= texture->width; j<<=1)
;
texture->widthmask = j-1;
textureheight[i] = texture->height<<FRACBITS;
totalwidth += texture->width;
}
free(patchlookup); // killough
for (i=0; i<2; i++) // cph - release the TEXTUREx lumps
if (maptex_lump[i] != -1)
W_UnlockLumpNum(maptex_lump[i]);
if (errors)
I_Error("R_InitTextures: %d errors", errors);
// Precalculate whatever possible.
if (devparm) // cph - If in development mode, generate now so all errors are found at once
for (i=0 ; i<numtextures ; i++)
R_GenerateLookup(i, &errors);
if (errors)
I_Error("R_InitTextures: %d errors", errors);
// Create translation table for global animation.
// killough 4/9/98: make column offsets 32-bit;
// clean up malloc-ing to use sizeof
texturetranslation =
Z_Malloc((numtextures+1)*sizeof*texturetranslation, PU_STATIC, 0);
for (i=0 ; i<numtextures ; i++)
texturetranslation[i] = i;
// killough 1/31/98: Initialize texture hash table
for (i = 0; i<numtextures; i++)
textures[i]->index = -1;
while (--i >= 0)
{
int j = W_LumpNameHash(textures[i]->name) % (unsigned) numtextures;
textures[i]->next = textures[j]->index; // Prepend to chain
textures[j]->index = i;
}
}
//
// R_InitFlats
//
void R_InitFlats(void)
{
int i;
firstflat = W_GetNumForName("F_START") + 1;
lastflat = W_GetNumForName("F_END") - 1;
numflats = lastflat - firstflat + 1;
// Create translation table for global animation.
// killough 4/9/98: make column offsets 32-bit;
// clean up malloc-ing to use sizeof
flattranslation =
Z_Malloc((numflats+1)*sizeof(*flattranslation), PU_STATIC, 0);
for (i=0 ; i<numflats ; i++)
flattranslation[i] = i;
}
//
// R_InitSpriteLumps
// Finds the width and hoffset of all sprites in the wad,
// so the sprite does not need to be cached completely
// just for having the header info ready during rendering.
//
void R_InitSpriteLumps(void)
{
int i;
const patch_t *patch;
firstspritelump = W_GetNumForName("S_START") + 1;
lastspritelump = W_GetNumForName("S_END") - 1;
numspritelumps = lastspritelump - firstspritelump + 1;
// killough 4/9/98: make columnd offsets 32-bit;
// clean up malloc-ing to use sizeof
spritewidth = Z_Malloc(numspritelumps*sizeof*spritewidth, PU_STATIC, 0);
spriteoffset = Z_Malloc(numspritelumps*sizeof*spriteoffset, PU_STATIC, 0);
spritetopoffset =
Z_Malloc(numspritelumps*sizeof*spritetopoffset, PU_STATIC, 0);
for (i=0 ; i< numspritelumps ; i++)
{
patch = W_CacheLumpNum(firstspritelump+i);
spritewidth[i] = SHORT(patch->width)<<FRACBITS;
spriteoffset[i] = SHORT(patch->leftoffset)<<FRACBITS;
spritetopoffset[i] = SHORT(patch->topoffset)<<FRACBITS;
W_UnlockLumpNum(firstspritelump+i);
}
}
//
// R_InitColormaps
//
// killough 3/20/98: rewritten to allow dynamic colormaps
// and to remove unnecessary 256-byte alignment
//
// killough 4/4/98: Add support for C_START/C_END markers
//
void R_InitColormaps(void)
{
int i;
firstcolormaplump = W_GetNumForName("C_START");
lastcolormaplump = W_GetNumForName("C_END");
numcolormaps = lastcolormaplump - firstcolormaplump;
colormaps = Z_Malloc(sizeof(*colormaps) * numcolormaps, PU_STATIC, 0);
colormaps[0] = (lighttable_t *)W_CacheLumpName("COLORMAP");
for (i=1; i<numcolormaps; i++)
colormaps[i] = (lighttable_t *)W_CacheLumpNum(i+firstcolormaplump);
// cph - always lock
}
// killough 4/4/98: get colormap number from name
// killough 4/11/98: changed to return -1 for illegal names
// killough 4/17/98: changed to use ns_colormaps tag
int R_ColormapNumForName(const char *name)
{
register int i = 0;
if (strncasecmp(name,"COLORMAP",8)) // COLORMAP predefined to return 0
if ((i = (W_CheckNumForName)(name, ns_colormaps)) != -1)
i -= firstcolormaplump;
return i;
}
//
// R_InitTranMap
//
// Initialize translucency filter map
//
// By Lee Killough 2/21/98
//
struct _cache {
unsigned char pct;
unsigned char playpal[256];
} cache;
int tran_filter_pct = 66; // filter percent
#define TSC 12 /* number of fixed point digits in filter percent */
void R_InitTranMap(int progress)
{
int lump = W_CheckNumForName("TRANMAP");
// If a tranlucency filter map lump is present, use it
if (lump != -1) // Set a pointer to the translucency filter maps.
main_tranmap = W_CacheLumpNum(lump); // killough 4/11/98
else
{ // Compose a default transparent filter map based on PLAYPAL.
const byte *playpal = W_CacheLumpName("PLAYPAL");
byte *my_tranmap;
int cachefd = open(GAMEBASE"tranmap.dat",O_RDONLY);
main_tranmap = my_tranmap = Z_Malloc(256*256, PU_STATIC, 0); // killough 4/11/98
// Use cached translucency filter if it's available
if ((cachefd<0) ? cachefd = open(GAMEBASE"tranmap.dat",O_WRONLY | O_CREAT) , 1 :
read(cachefd, &cache, sizeof(cache)) != sizeof(cache) ||
cache.pct != tran_filter_pct ||
memcmp(cache.playpal, playpal, sizeof cache.playpal) ||
read(cachefd, my_tranmap, 256*256) != 256*256 ) // killough 4/11/98
{
long *stackdeath=malloc(256*7*sizeof(long)); // This was a bunch of static varibles, way too big for rockbox
long *pal[3], *tot, *pal_w1[3];
pal[0]=&stackdeath[0];
pal[1]=&stackdeath[256];
pal[2]=&stackdeath[256*2];
tot=&stackdeath[256*3];
pal_w1[0]=&stackdeath[256*4];
pal_w1[1]=&stackdeath[256*5];
pal_w1[2]=&stackdeath[256*6];
long w1 = ((unsigned long) tran_filter_pct<<TSC)/100;
long w2 = (1l<<TSC)-w1;
if (progress)
printf("Please wait: Tranmap build");
// First, convert playpal into long int type, and transpose array,
// for fast inner-loop calculations. Precompute tot array.
{
register int i = 255;
register const unsigned char *p = playpal+255*3;
do
{
register long t,d;
pal_w1[0][i] = (pal[0][i] = t = p[0]) * w1;
d = t*t;
pal_w1[1][i] = (pal[1][i] = t = p[1]) * w1;
d += t*t;
pal_w1[2][i] = (pal[2][i] = t = p[2]) * w1;
d += t*t;
p -= 3;
tot[i] = d << (TSC-1);
} while (--i>=0);
}
// Next, compute all entries using minimum arithmetic.
{
int i,j;
byte *tp = my_tranmap;
for (i=0;i<256;i++)
{
long r1 = pal[0][i] * w2;
long g1 = pal[1][i] * w2;
long b1 = pal[2][i] * w2;
if (!(i & 31) && progress)
//jff 8/3/98 use logical output routine
printf(" Computing: %d", 256/32-i/32);
for (j=0;j<256;j++,tp++)
{
register int color = 255;
register long err;
long r = pal_w1[0][j] + r1;
long g = pal_w1[1][j] + g1;
long b = pal_w1[2][j] + b1;
long best = LONG_MAX;
do
if ((err = tot[color] - pal[0][color]*r
- pal[1][color]*g - pal[2][color]*b) < best)
best = err, *tp = color;
while (--color >= 0);
}
}
}
free(stackdeath); // Free this beast
if (cachefd) // write out the cached translucency map
{
cache.pct = tran_filter_pct;
memcpy(cache.playpal, playpal, 256);
lseek(cachefd, 0, SEEK_SET);
write(cachefd, &cache, sizeof cache);
write(cachefd,main_tranmap, 256*256);
// CPhipps - leave close for a few lines...
}
}
if (cachefd) // killough 11/98: fix filehandle leak
close(cachefd);
W_UnlockLumpName("PLAYPAL");
}
}
//
// R_InitData
// Locates all the lumps
// that will be used by all views
// Must be called after W_Init.
//
void R_InitData (void)
{
R_InitTextures ();
printf ("\nInitTextures");
R_InitFlats ();
printf ("\nInitFlats");
R_InitSpriteLumps ();
printf ("\nInitSprites");
if (general_translucency) // killough 3/1/98
R_InitTranMap(1);
R_InitColormaps ();
printf ("\nInitColormaps");
}
//
// R_FlatNumForName
// Retrieval, get a flat number for a flat name.
//
// killough 4/17/98: changed to use ns_flats namespace
//
int R_FlatNumForName(const char *name) // killough -- const added
{
int i = (W_CheckNumForName)(name, ns_flats);
if (i == -1)
I_Error("R_FlatNumForName: %s not found", name);
return i - firstflat;
}
//
// R_CheckTextureNumForName
// Check whether texture is available.
// Filter out NoTexture indicator.
//
// Rewritten by Lee Killough to use hash table for fast lookup. Considerably
// reduces the time needed to start new levels. See w_wad.c for comments on
// the hashing algorithm, which is also used for lump searches.
//
// killough 1/21/98, 1/31/98
//
int R_CheckTextureNumForName(const char *name)
{
int i = 0;
if (*name != '-') // "NoTexture" marker.
{
i = textures[W_LumpNameHash(name) % (unsigned) numtextures]->index;
while (i >= 0 && strncasecmp(textures[i]->name,name,8))
i = textures[i]->next;
}
return i;
}
//
// R_TextureNumForName
// Calls R_CheckTextureNumForName,
// aborts with error message.
//
int R_TextureNumForName(const char *name) // const added -- killough
{
int i = R_CheckTextureNumForName(name);
if (i == -1)
I_Error("R_TextureNumForName: %s not found", name);
return i;
}
//
// R_PrecacheLevel
// Preloads all relevant graphics for the level.
//
// Totally rewritten by Lee Killough to use less memory,
// to avoid using alloca(), and to improve performance.
// cph - new wad lump handling, calls cache functions but acquires no locks
void R_PrecacheLevel(void)
{
register int i;
register byte *hitlist;
if (demoplayback)
return;
{
size_t size = numflats > numsprites ? numflats : numsprites;
hitlist = malloc((size_t)numtextures > size ? (unsigned)numtextures : size);
}
// Precache flats.
memset(hitlist, 0, numflats);
for (i = numsectors; --i >= 0; )
hitlist[sectors[i].floorpic] = hitlist[sectors[i].ceilingpic] = 1;
for (i = numflats; --i >= 0; )
if (hitlist[i])
(W_CacheLumpNum)(firstflat + i, 0);
// Precache textures.
memset(hitlist, 0, numtextures);
for (i = numsides; --i >= 0;)
hitlist[sides[i].bottomtexture] =
hitlist[sides[i].toptexture] =
hitlist[sides[i].midtexture] = 1;
// Sky texture is always present.
// Note that F_SKY1 is the name used to
// indicate a sky floor/ceiling as a flat,
// while the sky texture is stored like
// a wall texture, with an episode dependend
// name.
hitlist[skytexture] = 1;
for (i = numtextures; --i >= 0; )
if (hitlist[i])
{
texture_t *texture = textures[i];
int j = texture->patchcount;
while (--j >= 0)
(W_CacheLumpNum)(texture->patches[j].patch, 0);
}
// Precache sprites.
memset(hitlist, 0, numsprites);
{
thinker_t *th;
for (th = thinkercap.next ; th != &thinkercap ; th=th->next)
if (th->function == P_MobjThinker)
hitlist[((mobj_t *)th)->sprite] = 1;
}
for (i=numsprites; --i >= 0;)
if (hitlist[i])
{
int j = sprites[i].numframes;
while (--j >= 0)
{
short *sflump = sprites[i].spriteframes[j].lump;
int k = 7;
do
(W_CacheLumpNum)(firstspritelump + sflump[k], 0);
while (--k >= 0);
}
}
free(hitlist);
}
// Proff - Added for OpenGL
void R_SetPatchNum(patchnum_t *patchnum, const char *name)
{
patch_t *patch;
patch = (patch_t *) W_CacheLumpName(name);
patchnum->width = patch->width;
patchnum->height = patch->height;
patchnum->leftoffset = patch->leftoffset;
patchnum->topoffset = patch->topoffset;
patchnum->lumpnum = W_GetNumForName(name);
W_UnlockLumpName(name);
}

105
apps/plugins/doom/r_data.h Normal file
View file

@ -0,0 +1,105 @@
/* Emacs style mode select -*- C++ -*-
*-----------------------------------------------------------------------------
*
*
* PrBoom a Doom port merged with LxDoom and LSDLDoom
* based on BOOM, a modified and improved DOOM engine
* Copyright (C) 1999 by
* id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
* Copyright (C) 1999-2000 by
* Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* DESCRIPTION:
* Refresh module, data I/O, caching, retrieval of graphics
* by name.
*
*-----------------------------------------------------------------------------*/
#ifndef __R_DATA__
#define __R_DATA__
#include "r_defs.h"
#include "r_state.h"
#ifdef __GNUG__
#pragma interface
#endif
// A single patch from a texture definition, basically
// a rectangular area within the texture rectangle.
typedef struct
{
int originx, originy; // Block origin, which has already accounted
int patch; // for the internal origin of the patch.
} texpatch_t;
//
// Texture definition.
// A DOOM wall texture is a list of patches
// which are to be combined in a predefined order.
//
typedef struct
{
char name[8]; // Keep name for switch changing, etc.
int next, index; // killough 1/31/98: used in hashing algorithm
// CPhipps - moved arrays with per-texture entries to elements here
unsigned widthmask;
size_t compositesize;
byte *composite;
short *columnlump;
unsigned *columnofs;
// CPhipps - end of additions
short width, height;
short patchcount; // All the patches[patchcount] are drawn
texpatch_t patches[1]; // back-to-front into the cached texture.
} texture_t;
// Retrieve column data for span blitting.
const byte*
R_GetColumn
( int tex,
int col );
// I/O, setting up the stuff.
void R_InitData (void);
void R_PrecacheLevel (void);
// Retrieval.
// Floor/ceiling opaque texture tiles,
// lookup by name. For animation?
int R_FlatNumForName (const char* name); // killough -- const added
// Called by P_Ticker for switches and animations,
// returns the texture number for the texture name.
int R_TextureNumForName (const char *name); // killough -- const added
int R_CheckTextureNumForName (const char *name);
void R_InitTranMap(int); // killough 3/6/98: translucency initialization
int R_ColormapNumForName(const char *name); // killough 4/4/98
extern const byte *main_tranmap, *tranmap;
/* Proff - Added for OpenGL - cph - const char* param */
void R_SetPatchNum(patchnum_t *patchnum, const char *name);
#endif

422
apps/plugins/doom/r_defs.h Normal file
View file

@ -0,0 +1,422 @@
// Emacs style mode select -*- C++ -*-
//-----------------------------------------------------------------------------
//
// $Id$
//
// Copyright (C) 1993-1996 by id Software, Inc.
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// DESCRIPTION:
// Refresh/rendering module, shared data struct definitions.
//
//-----------------------------------------------------------------------------
#ifndef __R_DEFS__
#define __R_DEFS__
// Screenwidth.
#include "doomdef.h"
// Some more or less basic data types
// we depend on.
#include "m_fixed.h"
// We rely on the thinker data struct
// to handle sound origins in sectors.
#include "d_think.h"
// SECTORS do store MObjs anyway.
#include "p_mobj.h"
#ifdef __GNUG__
#pragma interface
#endif
// Silhouette, needed for clipping Segs (mainly)
// and sprites representing things.
#define SIL_NONE 0
#define SIL_BOTTOM 1
#define SIL_TOP 2
#define SIL_BOTH 3
#define MAXDRAWSEGS 256
//
// INTERNAL MAP TYPES
// used by play and refresh
//
//
// Your plain vanilla vertex.
// Note: transformed values not buffered locally,
// like some DOOM-alikes ("wt", "WebView") do.
//
typedef struct
{
fixed_t x, y;
} vertex_t;
// Forward of LineDefs, for Sectors.
struct line_s;
// Each sector has a degenmobj_t in its center for sound origin purposes.
typedef struct
{
thinker_t thinker; // not used for anything
fixed_t x, y, z;
} degenmobj_t;
//
// The SECTORS record, at runtime.
// Stores things/mobjs.
//
typedef struct
{
fixed_t floorheight;
fixed_t ceilingheight;
int nexttag,firsttag; // killough 1/30/98: improves searches for tags.
int soundtraversed; // 0 = untraversed, 1,2 = sndlines-1
mobj_t *soundtarget; // thing that made a sound (or null)
int blockbox[4]; // mapblock bounding box for height changes
degenmobj_t soundorg; // origin for any sounds played by the sector
int validcount; // if == validcount, already checked
mobj_t *thinglist; // list of mobjs in sector
/* killough 8/28/98: friction is a sector property, not an mobj property.
* these fields used to be in mobj_t, but presented performance problems
* when processed as mobj properties. Fix is to make them sector properties.
*/
int friction,movefactor;
// thinker_t for reversable actions
void *floordata; // jff 2/22/98 make thinkers on
void *ceilingdata; // floors, ceilings, lighting,
void *lightingdata; // independent of one another
// jff 2/26/98 lockout machinery for stairbuilding
int stairlock; // -2 on first locked -1 after thinker done 0 normally
int prevsec; // -1 or number of sector for previous step
int nextsec; // -1 or number of next step sector
// killough 3/7/98: support flat heights drawn at another sector's heights
int heightsec; // other sector, or -1 if no other sector
int bottommap, midmap, topmap; // killough 4/4/98: dynamic colormaps
// list of mobjs that are at least partially in the sector
// thinglist is a subset of touching_thinglist
struct msecnode_s *touching_thinglist; // phares 3/14/98
int linecount;
struct line_s **lines;
// killough 10/98: support skies coming from sidedefs. Allows scrolling
// skies and other effects. No "level info" kind of lump is needed,
// because you can use an arbitrary number of skies per level with this
// method. This field only applies when skyflatnum is used for floorpic
// or ceilingpic, because the rest of Doom needs to know which is sky
// and which isn't, etc.
int sky;
// killough 3/7/98: floor and ceiling texture offsets
fixed_t floor_xoffs, floor_yoffs;
fixed_t ceiling_xoffs, ceiling_yoffs;
// killough 4/11/98: support for lightlevels coming from another sector
int floorlightsec, ceilinglightsec;
short floorpic;
short ceilingpic;
short lightlevel;
short special;
short oldspecial; //jff 2/16/98 remembers if sector WAS secret (automap)
short tag;
void* specialdata; // ROCKDOOM obsolete
} sector_t;
//
// The SideDef.
//
typedef struct
{
fixed_t textureoffset; // add this to the calculated texture column
fixed_t rowoffset; // add this to the calculated texture top
short toptexture; // Texture indices. We do not maintain names here.
short bottomtexture;
short midtexture;
sector_t* sector; // Sector the SideDef is facing.
// killough 4/4/98, 4/11/98: highest referencing special linedef's type,
// or lump number of special effect. Allows texture names to be overloaded
// for other functions.
int special;
} side_t;
//
// Move clipping aid for LineDefs.
//
typedef enum
{
ST_HORIZONTAL,
ST_VERTICAL,
ST_POSITIVE,
ST_NEGATIVE
} slopetype_t;
typedef struct line_s
{
vertex_t *v1, *v2; // Vertices, from v1 to v2.
fixed_t dx, dy; // Precalculated v2 - v1 for side checking.
short flags; // Animation related.
short special;
short tag;
short sidenum[2]; // Visual appearance: SideDefs.
fixed_t bbox[4]; // A bounding box, for the linedef's extent
slopetype_t slopetype; // To aid move clipping.
sector_t *frontsector; // Front and back sector.
sector_t *backsector;
int validcount; // if == validcount, already checked
void *specialdata; // thinker_t for reversable actions
int tranlump; // killough 4/11/98: translucency filter, -1 == none
int firsttag,nexttag; // killough 4/17/98: improves searches for tags.
int r_validcount; // cph: if == gametic, r_flags already done
enum { // cph:
RF_TOP_TILE = 1, // Upper texture needs tiling
RF_MID_TILE = 2, // Mid texture needs tiling
RF_BOT_TILE = 4, // Lower texture needs tiling
RF_IGNORE = 8, // Renderer can skip this line
RF_CLOSED =16, // Line blocks view
} r_flags;
} line_t;
// phares 3/14/98
//
// Sector list node showing all sectors an object appears in.
//
// There are two threads that flow through these nodes. The first thread
// starts at touching_thinglist in a sector_t and flows through the m_snext
// links to find all mobjs that are entirely or partially in the sector.
// The second thread starts at touching_sectorlist in an mobj_t and flows
// through the m_tnext links to find all sectors a thing touches. This is
// useful when applying friction or push effects to sectors. These effects
// can be done as thinkers that act upon all objects touching their sectors.
// As an mobj moves through the world, these nodes are created and
// destroyed, with the links changed appropriately.
//
// For the links, NULL means top or end of list.
typedef struct msecnode_s
{
sector_t *m_sector; // a sector containing this object
struct mobj_s *m_thing; // this object
struct msecnode_s *m_tprev; // prev msecnode_t for this thing
struct msecnode_s *m_tnext; // next msecnode_t for this thing
struct msecnode_s *m_sprev; // prev msecnode_t for this sector
struct msecnode_s *m_snext; // next msecnode_t for this sector
boolean visited; // killough 4/4/98, 4/7/98: used in search algorithms
} msecnode_t;
//
// The LineSeg.
//
typedef struct
{
vertex_t *v1, *v2;
fixed_t offset;
angle_t angle;
side_t* sidedef;
line_t* linedef;
boolean miniseg;
// Sector references.
// Could be retrieved from linedef, too
// (but that would be slower -- killough)
// backsector is NULL for one sided lines
sector_t *frontsector, *backsector;
} seg_t;
//
// A SubSector.
// References a Sector.
// Basically, this is a list of LineSegs,
// indicating the visible walls that define
// (all or some) sides of a convex BSP leaf.
//
typedef struct subsector_s
{
sector_t *sector;
unsigned short numlines, firstline;
} subsector_t;
//
// BSP node.
//
typedef struct
{
fixed_t x, y, dx, dy; // Partition line.
fixed_t bbox[2][4]; // Bounding box for each child.
unsigned short children[2]; // If NF_SUBSECTOR its a subsector.
} node_t;
// posts are runs of non masked source pixels
typedef struct
{
byte topdelta; // -1 is the last post in a column
byte length; // length data bytes follows
} post_t;
// column_t is a list of 0 or more post_t, (byte)-1 terminated
typedef post_t column_t;
//
// OTHER TYPES
//
// This could be wider for >8 bit display.
// Indeed, true color support is posibble
// precalculating 24bpp lightmap/colormap LUT.
// from darkening PLAYPAL to all black.
// Could even us emore than 32 levels.
typedef byte lighttable_t;
//
// Masked 2s linedefs
//
typedef struct drawseg_s
{
seg_t* curline;
int x1, x2;
fixed_t scale1, scale2, scalestep;
int silhouette; // 0=none, 1=bottom, 2=top, 3=both
fixed_t bsilheight; // do not clip sprites above this
fixed_t tsilheight; // do not clip sprites below this
// Pointers to lists for sprite clipping,
// all three adjusted so [x1] is first value.
short *sprtopclip, *sprbottomclip, *maskedtexturecol;
} drawseg_t;
//
// Patches.
// A patch holds one or more columns.
// Patches are used for sprites and all masked pictures,
// and we compose textures from the TEXTURE1/2 lists
// of patches.
//
typedef struct
{
short width, height; // bounding box size
short leftoffset; // pixels to the left of origin
short topoffset; // pixels below the origin
int columnofs[8]; // only [width] used
} patch_t;
// proff: Added for OpenGL
typedef struct
{
int width,height;
int leftoffset,topoffset;
int lumpnum;
} patchnum_t;
//
// A vissprite_t is a thing that will be drawn during a refresh.
// i.e. a sprite object that is partly visible.
//
typedef struct vissprite_s
{
int x1, x2;
fixed_t gx, gy; // for line side calculation
fixed_t gz, gzt; // global bottom / top for silhouette clipping
fixed_t startfrac; // horizontal position of x1
fixed_t scale;
fixed_t xiscale; // negative if flipped
fixed_t texturemid;
int patch;
uint_64_t mobjflags;
// for color translation and shadow draw, maxbright frames as well
lighttable_t *colormap;
// killough 3/27/98: height sector for underwater/fake ceiling support
int heightsec;
} vissprite_t;
//
// Sprites are patches with a special naming convention
// so they can be recognized by R_InitSprites.
// The base name is NNNNFx or NNNNFxFx, with
// x indicating the rotation, x = 0, 1-7.
// The sprite and frame specified by a thing_t
// is range checked at run time.
// A sprite is a patch_t that is assumed to represent
// a three dimensional object and may have multiple
// rotations pre drawn.
// Horizontal flipping is used to save space,
// thus NNNNF2F5 defines a mirrored patch.
// Some sprites will only have one picture used
// for all views: NNNNF0
//
typedef struct
{
// If false use 0 for any position.
// Note: as eight entries are available,
// we might as well insert the same name eight times.
boolean rotate;
// Lump to use for view angles 0-7.
short lump[8];
// Flip bit (1 = flip) to use for view angles 0-7.
byte flip[8];
} spriteframe_t;
//
// A sprite definition:
// a number of animation frames.
//
typedef struct
{
int numframes;
spriteframe_t *spriteframes;
} spritedef_t;
//
// Now what is a visplane, anyway?
//
typedef struct visplane
{
struct visplane *next; // Next visplane in hash chain -- killough
int picnum, lightlevel, minx, maxx;
fixed_t height;
fixed_t xoffs, yoffs; // killough 2/28/98: Support scrolling flats
unsigned short pad1; // leave pads for [minx-1]/[maxx+1]
unsigned short top[SCREENWIDTH];
unsigned short pad2, pad3; // killough 2/8/98, 4/25/98
unsigned short bottom[SCREENWIDTH];
unsigned short pad4;
} visplane_t;
#endif

677
apps/plugins/doom/r_draw.c Normal file
View file

@ -0,0 +1,677 @@
/* Emacs style mode select -*- C++ -*-
*-----------------------------------------------------------------------------
*
*
* PrBoom a Doom port merged with LxDoom and LSDLDoom
* based on BOOM, a modified and improved DOOM engine
* Copyright (C) 1999 by
* id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
* Copyright (C) 1999-2000 by
* Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* DESCRIPTION:
* The actual span/column drawing functions.
* Here find the main potential for optimization,
* e.g. inline assembly, different algorithms.
*
*-----------------------------------------------------------------------------*/
#include "doomstat.h"
#include "w_wad.h"
#include "r_main.h"
#include "v_video.h"
#include "st_stuff.h"
#include "g_game.h"
#include "am_map.h"
//#include "lprintf.h"
#include "rockmacros.h"
#define MAXWIDTH 1120
#define MAXHEIGHT 832
// status bar height at bottom of screen
#define SBARHEIGHT 32
//
// All drawing to the view buffer is accomplished in this file.
// The other refresh files only know about ccordinates,
// not the architecture of the frame buffer.
// Conveniently, the frame buffer is a linear one,
// and we need only the base address,
// and the total size == width*height*depth/8.,
//
//byte* viewimage;
int viewwidth;
int scaledviewwidth;
int viewheight;
int viewwindowx;
int viewwindowy;
byte *topleft IBSS_ATTR;
// Color tables for different players,
// translate a limited part to another
// (color ramps used for suit colors).
//
// CPhipps - made const*'s
const byte *tranmap IBSS_ATTR; // translucency filter maps 256x256 // phares
const byte *main_tranmap IBSS_ATTR; // killough 4/11/98
//
// R_DrawColumn
// Source is the top of the column to scale.
//
lighttable_t *dc_colormap IBSS_ATTR;
int dc_x IBSS_ATTR;
int dc_yl IBSS_ATTR;
int dc_yh IBSS_ATTR;
fixed_t dc_iscale IBSS_ATTR;
fixed_t dc_texturemid IBSS_ATTR;
int dc_texheight IBSS_ATTR; // killough
const byte *dc_source IBSS_ATTR; // first pixel in a column (possibly virtual)
//
// A column is a vertical slice/span from a wall texture that,
// given the DOOM style restrictions on the view orientation,
// will always have constant z depth.
// Thus a special case loop for very fast rendering can
// be used. It has also been used with Wolfenstein 3D.
//
void R_DrawColumn (void)
{
int count;
register byte *dest; // killough
register fixed_t frac; // killough
// leban 1/17/99:
// removed the + 1 here, adjusted the if test, and added an increment
// later. this helps a compiler pipeline a bit better. the x86
// assembler also does this.
count = dc_yh - dc_yl;
// Zero length, column does not exceed a pixel.
if (count < 0)
return;
#ifdef RANGECHECK
if ((unsigned)dc_x >= SCREENWIDTH
|| dc_yl < 0
|| dc_yh >= SCREENHEIGHT)
I_Error ("R_DrawColumn: %d to %d at %d", dc_yl, dc_yh, dc_x);
#endif
count++;
// Framebuffer destination address.
dest = topleft + dc_yl*SCREENWIDTH + dc_x;
// Determine scaling,
// which is the only mapping to be done.
#define fracstep dc_iscale
frac = dc_texturemid + (dc_yl-centery)*fracstep;
// Inner loop that does the actual texture mapping,
// e.g. a DDA-lile scaling.
// This is as fast as it gets. (Yeah, right!!! -- killough)
//
// killough 2/1/98: more performance tuning
if (dc_texheight == 128) {
while(count--)
{
*dest = dc_colormap[dc_source[(frac>>FRACBITS)&127]];
frac += fracstep;
dest += SCREENWIDTH;
}
} else if (dc_texheight == 0) {
/* cph - another special case */
while (count--) {
*dest = dc_colormap[dc_source[frac>>FRACBITS]];
frac += fracstep;
dest += SCREENWIDTH;
}
} else {
register unsigned heightmask = dc_texheight-1; // CPhipps - specify type
if (! (dc_texheight & heightmask) ) // power of 2 -- killough
{
while (count>0) // texture height is a power of 2 -- killough
{
*dest = dc_colormap[dc_source[(frac>>FRACBITS) & heightmask]];
dest += SCREENWIDTH;
frac += fracstep;
count--;
}
}
else
{
heightmask++;
heightmask <<= FRACBITS;
if (frac < 0)
while ((frac += heightmask) < 0);
else
while (frac >= (int)heightmask)
frac -= heightmask;
while(count>0)
{
// Re-map color indices from wall texture column
// using a lighting/special effects LUT.
// heightmask is the Tutti-Frutti fix -- killough
*dest = dc_colormap[dc_source[frac>>FRACBITS]];
dest += SCREENWIDTH;
if ((frac += fracstep) >= (int)heightmask)
frac -= heightmask;
count--;
}
}
}
}
#undef fracstep
// Here is the version of R_DrawColumn that deals with translucent // phares
// textures and sprites. It's identical to R_DrawColumn except // |
// for the spot where the color index is stuffed into *dest. At // V
// that point, the existing color index and the new color index
// are mapped through the TRANMAP lump filters to get a new color
// index whose RGB values are the average of the existing and new
// colors.
//
// Since we're concerned about performance, the 'translucent or
// opaque' decision is made outside this routine, not down where the
// actual code differences are.
void R_DrawTLColumn (void)
{
int count;
register byte *dest; // killough
register fixed_t frac; // killough
count = dc_yh - dc_yl + 1;
// Zero length, column does not exceed a pixel.
if (count <= 0)
return;
#ifdef RANGECHECK
if ((unsigned)dc_x >= (unsigned)SCREENWIDTH
|| dc_yl < 0
|| dc_yh >= SCREENHEIGHT)
I_Error("R_DrawTLColumn: %i to %i at %i", dc_yl, dc_yh, dc_x);
#endif
// Framebuffer destination address.
dest = topleft + dc_yl*SCREENWIDTH + dc_x;
// Determine scaling,
// which is the only mapping to be done.
#define fracstep dc_iscale
frac = dc_texturemid + (dc_yl-centery)*fracstep;
// Inner loop that does the actual texture mapping,
// e.g. a DDA-lile scaling.
// This is as fast as it gets. (Yeah, right!!! -- killough)
//
// killough 2/1/98, 2/21/98: more performance tuning
{
register const byte *source = dc_source;
register const lighttable_t *colormap = dc_colormap;
register unsigned heightmask = dc_texheight-1; // CPhipps - specify type
if (dc_texheight & heightmask) // not a power of 2 -- killough
{
heightmask++;
heightmask <<= FRACBITS;
if (frac < 0)
while ((frac += heightmask) < 0);
else
while (frac >= (int)heightmask)
frac -= heightmask;
do
{
// Re-map color indices from wall texture column
// using a lighting/special effects LUT.
// heightmask is the Tutti-Frutti fix -- killough
*dest = tranmap[(*dest<<8)+colormap[source[frac>>FRACBITS]]]; // phares
dest += SCREENWIDTH;
if ((frac += fracstep) >= (int)heightmask)
frac -= heightmask;
}
while (--count);
}
else
{
while ((count-=2)>=0) // texture height is a power of 2 -- killough
{
*dest = tranmap[(*dest<<8)+colormap[source[(frac>>FRACBITS) & heightmask]]]; // phares
dest += SCREENWIDTH;
frac += fracstep;
*dest = tranmap[(*dest<<8)+colormap[source[(frac>>FRACBITS) & heightmask]]]; // phares
dest += SCREENWIDTH;
frac += fracstep;
}
if (count & 1)
*dest = tranmap[(*dest<<8)+colormap[source[(frac>>FRACBITS) & heightmask]]]; // phares
}
}
}
#undef fracstep
//
// Spectre/Invisibility.
//
#define FUZZTABLE 50
// proff 08/17/98: Changed for high-res
//#define FUZZOFF (SCREENWIDTH)
#define FUZZOFF 1
static const int fuzzoffset_org[FUZZTABLE] ICONST_ATTR = {
FUZZOFF,-FUZZOFF,FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,
FUZZOFF,FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,
FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,-FUZZOFF,-FUZZOFF,-FUZZOFF,
FUZZOFF,-FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,
FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,-FUZZOFF,FUZZOFF,
FUZZOFF,-FUZZOFF,-FUZZOFF,-FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,
FUZZOFF,FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,FUZZOFF
} ;
static int fuzzoffset[FUZZTABLE] IBSS_ATTR;
static int fuzzpos IBSS_ATTR = 0;
//
// Framebuffer postprocessing.
// Creates a fuzzy image by copying pixels
// from adjacent ones to left and right.
// Used with an all black colormap, this
// could create the SHADOW effect,
// i.e. spectres and invisible players.
//
void R_DrawFuzzColumn(void)
{
int count;
byte *dest;
fixed_t frac;
fixed_t fracstep;
// Adjust borders. Low...
if (!dc_yl)
dc_yl = 1;
// .. and high.
if (dc_yh == viewheight-1)
dc_yh = viewheight - 2;
count = dc_yh - dc_yl;
// Zero length.
if (count < 0)
return;
#ifdef RANGECHECK
if ((unsigned) dc_x >= (unsigned)SCREENWIDTH
|| dc_yl < 0
|| (unsigned)dc_yh >= (unsigned)SCREENHEIGHT)
I_Error("R_DrawFuzzColumn: %i to %i at %i", dc_yl, dc_yh, dc_x);
#endif
// Keep till detailshift bug in blocky mode fixed,
// or blocky mode removed.
// Does not work with blocky mode.
dest = topleft + dc_yl*SCREENWIDTH + dc_x;
// Looks familiar.
fracstep = dc_iscale;
frac = dc_texturemid + (dc_yl-centery)*fracstep;
// Looks like an attempt at dithering,
// using the colormap #6 (of 0-31, a bit brighter than average).
do
{
// Lookup framebuffer, and retrieve
// a pixel that is either one column
// left or right of the current one.
// Add index from colormap to index.
// killough 3/20/98: use fullcolormap instead of colormaps
*dest = fullcolormap[6*256+dest[fuzzoffset[fuzzpos]]];
// Some varying invisibility effects can be gotten by playing // phares
// with this logic. For example, try // phares
// // phares
// *dest = fullcolormap[0*256+dest[FUZZOFF]]; // phares
// Clamp table lookup index.
if (++fuzzpos == FUZZTABLE)
fuzzpos = 0;
dest += SCREENWIDTH;
frac += fracstep;
} while (count--);
}
//
// R_DrawTranslatedColumn
// Used to draw player sprites
// with the green colorramp mapped to others.
// Could be used with different translation
// tables, e.g. the lighter colored version
// of the BaronOfHell, the HellKnight, uses
// identical sprites, kinda brightened up.
//
byte *dc_translation, *translationtables;
void R_DrawTranslatedColumn (void)
{
int count;
byte *dest;
fixed_t frac;
fixed_t fracstep;
count = dc_yh - dc_yl;
if (count < 0)
return;
#ifdef RANGECHECK
if ((unsigned)dc_x >= (unsigned)SCREENWIDTH
|| dc_yl < 0
|| (unsigned)dc_yh >= (unsigned)SCREENHEIGHT)
I_Error("R_DrawColumn: %i to %i at %i", dc_yl, dc_yh, dc_x);
#endif
// FIXME. As above.
dest = topleft + dc_yl*SCREENWIDTH + dc_x;
// Looks familiar.
fracstep = dc_iscale;
frac = dc_texturemid + (dc_yl-centery)*fracstep;
// Here we do an additional index re-mapping.
do
{
// Translation tables are used
// to map certain colorramps to other ones,
// used with PLAY sprites.
// Thus the "green" ramp of the player 0 sprite
// is mapped to gray, red, black/indigo.
*dest = dc_colormap[dc_translation[dc_source[frac>>FRACBITS]]];
dest += SCREENWIDTH;
frac += fracstep;
}
while (count--);
}
//
// R_InitTranslationTables
// Creates the translation tables to map
// the green color ramp to gray, brown, red.
// Assumes a given structure of the PLAYPAL.
// Could be read from a lump instead.
//
byte playernumtotrans[MAXPLAYERS];
extern lighttable_t *(*c_zlight)[LIGHTLEVELS][MAXLIGHTZ];
void R_InitTranslationTables (void)
{
int i, j;
#define MAXTRANS 3
byte transtocolour[MAXTRANS];
// killough 5/2/98:
// Remove dependency of colormaps aligned on 256-byte boundary
if (translationtables == NULL) // CPhipps - allow multiple calls
translationtables = Z_Malloc(256*MAXTRANS, PU_STATIC, 0);
for (i=0; i<MAXTRANS; i++) transtocolour[i] = 255;
for (i=0; i<MAXPLAYERS; i++) {
byte wantcolour = mapcolor_plyr[i];
playernumtotrans[i] = 0;
if (wantcolour != 0x70) // Not green, would like translation
for (j=0; j<MAXTRANS; j++)
if (transtocolour[j] == 255) {
transtocolour[j] = wantcolour; playernumtotrans[i] = j+1; break;
}
}
// translate just the 16 green colors
for (i=0; i<256; i++)
if (i >= 0x70 && i<= 0x7f)
{
// CPhipps - configurable player colours
translationtables[i] = colormaps[0][((i&0xf)<<9) + transtocolour[0]];
translationtables[i+256] = colormaps[0][((i&0xf)<<9) + transtocolour[1]];
translationtables[i+512] = colormaps[0][((i&0xf)<<9) + transtocolour[2]];
}
else // Keep all other colors as is.
translationtables[i]=translationtables[i+256]=translationtables[i+512]=i;
}
//
// R_DrawSpan
// With DOOM style restrictions on view orientation,
// the floors and ceilings consist of horizontal slices
// or spans with constant z depth.
// However, rotation around the world z axis is possible,
// thus this mapping, while simpler and faster than
// perspective correct texture mapping, has to traverse
// the texture at an angle in all but a few cases.
// In consequence, flats are not stored by column (like walls),
// and the inner loop has to step in texture space u and v.
//
int ds_y IBSS_ATTR;
int ds_x1 IBSS_ATTR;
int ds_x2 IBSS_ATTR;
lighttable_t *ds_colormap IBSS_ATTR;
fixed_t ds_xfrac IBSS_ATTR;
fixed_t ds_yfrac IBSS_ATTR;
fixed_t ds_xstep IBSS_ATTR;
fixed_t ds_ystep IBSS_ATTR;
// start of a 64*64 tile image
byte *ds_source IBSS_ATTR;
void R_DrawSpan (void)
{
register unsigned count,xfrac = ds_xfrac,yfrac = ds_yfrac;
byte *source;
byte *colormap;
byte *dest;
source = ds_source;
colormap = ds_colormap;
dest = topleft + ds_y*SCREENWIDTH + ds_x1;
count = ds_x2 - ds_x1 + 1;
while (count)
{
register unsigned xtemp = xfrac >> 16;
register unsigned ytemp = yfrac >> 10;
register unsigned spot;
ytemp &= 4032;
xtemp &= 63;
spot = xtemp | ytemp;
xfrac += ds_xstep;
yfrac += ds_ystep;
*dest++ = colormap[source[spot]];
count--;
}
}
//
// R_InitBuffer
// Creats lookup tables that avoid
// multiplies and other hazzles
// for getting the framebuffer address
// of a pixel to draw.
//
void R_InitBuffer(int width, int height)
{
int i=0;
// Handle resize,
// e.g. smaller view windows
// with border and/or status bar.
viewwindowx = (SCREENWIDTH-width) >> 1;
// Same with base row offset.
viewwindowy = width==SCREENWIDTH ? 0 : (SCREENHEIGHT-(ST_SCALED_HEIGHT-1)-height)>>1;
topleft = screens[0] + viewwindowy*SCREENWIDTH + viewwindowx;
// Preclaculate all row offsets.
// CPhipps - merge viewwindowx into here
for (i=0; i<FUZZTABLE; i++)
fuzzoffset[i] = fuzzoffset_org[i]*SCREENWIDTH;
}
//
// R_FillBackScreen
// Fills the back screen with a pattern
// for variable screen sizes
// Also draws a beveled edge.
//
// CPhipps - patch drawing updated
void R_FillBackScreen (void)
{
int x,y;
if (scaledviewwidth == SCREENWIDTH)
return;
V_DrawBackground(gamemode == commercial ? "GRNROCK" : "FLOOR7_2", 1);
for (x=0 ; x<scaledviewwidth ; x+=8)
V_DrawNamePatch(viewwindowx+x,viewwindowy-8,1,"brdr_t", CR_DEFAULT, VPT_NONE);
for (x=0 ; x<scaledviewwidth ; x+=8)
V_DrawNamePatch(viewwindowx+x,viewwindowy+viewheight,1,"brdr_b", CR_DEFAULT, VPT_NONE);
for (y=0 ; y<viewheight ; y+=8)
V_DrawNamePatch(viewwindowx-8,viewwindowy+y,1,"brdr_l", CR_DEFAULT, VPT_NONE);
for (y=0 ; y<viewheight ; y+=8)
V_DrawNamePatch(viewwindowx+scaledviewwidth,viewwindowy+y,1,"brdr_r", CR_DEFAULT, VPT_NONE);
// Draw beveled edge.
V_DrawNamePatch(viewwindowx-8,viewwindowy-8,1,"brdr_tl", CR_DEFAULT, VPT_NONE);
V_DrawNamePatch(viewwindowx+scaledviewwidth,viewwindowy-8,1,"brdr_tr", CR_DEFAULT, VPT_NONE);
V_DrawNamePatch(viewwindowx-8,viewwindowy+viewheight,1,"brdr_bl", CR_DEFAULT, VPT_NONE);
V_DrawNamePatch(viewwindowx+scaledviewwidth,viewwindowy+viewheight,1,"brdr_br", CR_DEFAULT, VPT_NONE);
}
//
// Copy a screen buffer.
//
void R_VideoErase(unsigned ofs, int count)
{
memcpy(screens[0]+ofs, screens[1]+ofs, count); // LFB copy.
}
//
// R_DrawViewBorder
// Draws the border around the view
// for different size windows?
//
void R_DrawViewBorder(void)
{
int top, side, ofs, i;
// proff/nicolas 09/20/98: Added for high-res (inspired by DosDOOM)
int side2;
// proff/nicolas 09/20/98: Removed for high-res
// if (scaledviewwidth == SCREENWIDTH)
// return;
// proff/nicolas 09/20/98: Added for high-res (inspired by DosDOOM)
if ((SCREENHEIGHT != viewheight) ||
((automapmode & am_active) && ! (automapmode & am_overlay)))
{
ofs = ( SCREENHEIGHT - ST_SCALED_HEIGHT ) * SCREENWIDTH;
side= ( SCREENWIDTH - ST_SCALED_WIDTH ) / 2;
side2 = side * 2;
R_VideoErase ( ofs, side );
ofs += ( SCREENWIDTH - side );
for ( i = 1; i < ST_SCALED_HEIGHT; i++ )
{
R_VideoErase ( ofs, side2 );
ofs += SCREENWIDTH;
}
R_VideoErase ( ofs, side );
}
if ( viewheight >= ( SCREENHEIGHT - ST_SCALED_HEIGHT ))
return; // if high-res, donŽt go any further!
top = ((SCREENHEIGHT-ST_SCALED_HEIGHT)-viewheight)/2;
side = (SCREENWIDTH-scaledviewwidth)/2;
// copy top and one line of left side
R_VideoErase (0, top*SCREENWIDTH+side);
// copy one line of right side and bottom
ofs = (viewheight+top)*SCREENWIDTH-side;
R_VideoErase (ofs, top*SCREENWIDTH+side);
// copy sides using wraparound
ofs = top*SCREENWIDTH + SCREENWIDTH-side;
side <<= 1;
for (i=1 ; i<viewheight ; i++)
{
R_VideoErase (ofs, side);
ofs += SCREENWIDTH;
}
}

View file

@ -0,0 +1,99 @@
/* Emacs style mode select -*- C++ -*-
*-----------------------------------------------------------------------------
*
*
* PrBoom a Doom port merged with LxDoom and LSDLDoom
* based on BOOM, a modified and improved DOOM engine
* Copyright (C) 1999 by
* id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
* Copyright (C) 1999-2000 by
* Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* DESCRIPTION:
* System specific interface stuff.
*
*-----------------------------------------------------------------------------*/
#ifndef __R_DRAW__
#define __R_DRAW__
#include "r_defs.h"
#ifdef __GNUG__
#pragma interface
#endif
extern lighttable_t *dc_colormap;
extern int dc_x;
extern int dc_yl;
extern int dc_yh;
extern fixed_t dc_iscale;
extern fixed_t dc_texturemid;
extern int dc_texheight; // killough
// first pixel in a column
extern const byte *dc_source;
// The span blitting interface.
// Hook in assembler or system specific BLT here.
void R_DrawColumn(void) ICODE_ATTR;
void R_DrawTLColumn(void) ICODE_ATTR; // drawing translucent textures // phares
void R_DrawFuzzColumn(void) ICODE_ATTR; // The Spectre/Invisibility effect.
// Draw with color translation tables, for player sprite rendering,
// Green/Red/Blue/Indigo shirts.
void R_DrawTranslatedColumn(void);
void R_VideoErase(unsigned ofs, int count);
extern lighttable_t *ds_colormap;
extern int ds_y;
extern int ds_x1;
extern int ds_x2;
extern fixed_t ds_xfrac;
extern fixed_t ds_yfrac;
extern fixed_t ds_xstep;
extern fixed_t ds_ystep;
// start of a 64*64 tile image
extern byte *ds_source;
extern byte playernumtotrans[MAXPLAYERS]; // CPhipps - what translation table for what player
extern byte *translationtables;
extern byte *dc_translation;
// Span blitting for rows, floor/ceiling. No Spectre effect needed.
void R_DrawSpan(void) ICODE_ATTR;
void R_InitBuffer(int width, int height);
// Initialize color translation tables, for player rendering etc.
void R_InitTranslationTables(void);
// Rendering function.
void R_FillBackScreen(void);
// If the view size is not full screen, draws a border around it.
void R_DrawViewBorder(void);
extern const byte *tranmap; // translucency filter maps 256x256 // phares
extern const byte *main_tranmap; // killough 4/11/98
#endif

531
apps/plugins/doom/r_main.c Normal file
View file

@ -0,0 +1,531 @@
/* Emacs style mode select -*- C++ -*-
*-----------------------------------------------------------------------------
*
*
* PrBoom a Doom port merged with LxDoom and LSDLDoom
* based on BOOM, a modified and improved DOOM engine
* Copyright (C) 1999 by
* id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
* Copyright (C) 1999-2000 by
* Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* DESCRIPTION:
* Rendering main loop and setup functions,
* utility functions (BSP, geometry, trigonometry).
* See tables.c, too.
*
*-----------------------------------------------------------------------------*/
#include "doomstat.h"
#include "w_wad.h"
#include "r_main.h"
#include "r_things.h"
#include "r_plane.h"
#include "r_bsp.h"
#include "r_draw.h"
#include "m_bbox.h"
#include "r_sky.h"
#include "v_video.h"
#include "i_system.h"
//#include "lprintf.h"
#include "st_stuff.h"
#include "rockmacros.h"
// Fineangles in the SCREENWIDTH wide window.
#define FIELDOFVIEW 2048
// killough: viewangleoffset is a legacy from the pre-v1.2 days, when Doom
// had Left/Mid/Right viewing. +/-ANG90 offsets were placed here on each
// node, by d_net.c, to set up a L/M/R session.
int viewangleoffset;
int validcount = 1; // increment every time a check is made
lighttable_t *fixedcolormap;
int centerx IBSS_ATTR;
int centery IBSS_ATTR;
fixed_t centerxfrac, centeryfrac;
fixed_t projection;
fixed_t viewx, viewy, viewz;
angle_t viewangle;
fixed_t viewcos, viewsin;
player_t *viewplayer;
extern lighttable_t **walllights;
//
// precalculated math tables
//
angle_t clipangle;
// The viewangletox[viewangle + FINEANGLES/4] lookup
// maps the visible view angles to screen X coordinates,
// flattening the arc to a flat projection plane.
// There will be many angles mapped to the same X.
int viewangletox[FINEANGLES/2];
// The xtoviewangleangle[] table maps a screen pixel
// to the lowest viewangle that maps back to x ranges
// from clipangle to -clipangle.
angle_t xtoviewangle[SCREENWIDTH+1]; // killough 2/8/98
// killough 3/20/98: Support dynamic colormaps, e.g. deep water
// killough 4/4/98: support dynamic number of them as well
int numcolormaps;
lighttable_t *(*c_scalelight)[LIGHTLEVELS][MAXLIGHTSCALE];
lighttable_t *(*c_zlight)[LIGHTLEVELS][MAXLIGHTZ];
lighttable_t *(*scalelight)[MAXLIGHTSCALE];
lighttable_t *(*zlight)[MAXLIGHTZ];
lighttable_t *fullcolormap;
lighttable_t **colormaps;
// killough 3/20/98, 4/4/98: end dynamic colormaps
int extralight; // bumped light from gun blasts
void (*colfunc)(void);
//
// R_PointOnSide
// Traverse BSP (sub) tree,
// check point against partition plane.
// Returns side 0 (front) or 1 (back).
//
// killough 5/2/98: reformatted
//
int R_PointOnSide(fixed_t x, fixed_t y, const node_t *node)
{
if (!node->dx)
return x <= node->x ? node->dy > 0 : node->dy < 0;
if (!node->dy)
return y <= node->y ? node->dx < 0 : node->dx > 0;
x -= node->x;
y -= node->y;
// Try to quickly decide by looking at sign bits.
if ((node->dy ^ node->dx ^ x ^ y) < 0)
return (node->dy ^ x) < 0; // (left is negative)
return FixedMul(y, node->dx>>FRACBITS) >= FixedMul(node->dy>>FRACBITS, x);
}
// killough 5/2/98: reformatted
int R_PointOnSegSide(fixed_t x, fixed_t y, const seg_t *line)
{
fixed_t lx = line->v1->x;
fixed_t ly = line->v1->y;
fixed_t ldx = line->v2->x - lx;
fixed_t ldy = line->v2->y - ly;
if (!ldx)
return x <= lx ? ldy > 0 : ldy < 0;
if (!ldy)
return y <= ly ? ldx < 0 : ldx > 0;
x -= lx;
y -= ly;
// Try to quickly decide by looking at sign bits.
if ((ldy ^ ldx ^ x ^ y) < 0)
return (ldy ^ x) < 0; // (left is negative)
return FixedMul(y, ldx>>FRACBITS) >= FixedMul(ldy>>FRACBITS, x);
}
//
// R_PointToAngle
// To get a global angle from cartesian coordinates,
// the coordinates are flipped until they are in
// the first octant of the coordinate system, then
// the y (<=x) is scaled and divided by x to get a
// tangent (slope) value which is looked up in the
// tantoangle[] table. The +1 size of tantoangle[]
// is to handle the case when x==y without additional
// checking.
//
// killough 5/2/98: reformatted, cleaned up
angle_t R_PointToAngle(fixed_t x, fixed_t y)
{
return (y -= viewy, (x -= viewx) || y) ?
x >= 0 ?
y >= 0 ?
(x > y) ? tantoangle[SlopeDiv(y,x)] : // octant 0
ANG90-1-tantoangle[SlopeDiv(x,y)] : // octant 1
x > (y = -y) ? 0-tantoangle[SlopeDiv(y,x)] : // octant 8
ANG270+tantoangle[SlopeDiv(x,y)] : // octant 7
y >= 0 ? (x = -x) > y ? ANG180-1-tantoangle[SlopeDiv(y,x)] : // octant 3
ANG90 + tantoangle[SlopeDiv(x,y)] : // octant 2
(x = -x) > (y = -y) ? ANG180+tantoangle[ SlopeDiv(y,x)] : // octant 4
ANG270-1-tantoangle[SlopeDiv(x,y)] : // octant 5
0;
}
angle_t R_PointToAngle2(fixed_t viewx, fixed_t viewy, fixed_t x, fixed_t y)
{
return (y -= viewy, (x -= viewx) || y) ?
x >= 0 ?
y >= 0 ?
(x > y) ? tantoangle[SlopeDiv(y,x)] : // octant 0
ANG90-1-tantoangle[SlopeDiv(x,y)] : // octant 1
x > (y = -y) ? 0-tantoangle[SlopeDiv(y,x)] : // octant 8
ANG270+tantoangle[SlopeDiv(x,y)] : // octant 7
y >= 0 ? (x = -x) > y ? ANG180-1-tantoangle[SlopeDiv(y,x)] : // octant 3
ANG90 + tantoangle[SlopeDiv(x,y)] : // octant 2
(x = -x) > (y = -y) ? ANG180+tantoangle[ SlopeDiv(y,x)] : // octant 4
ANG270-1-tantoangle[SlopeDiv(x,y)] : // octant 5
0;
}
//
// R_InitTextureMapping
//
// killough 5/2/98: reformatted
static void R_InitTextureMapping (void)
{
register int i,x;
fixed_t focallength;
// Use tangent table to generate viewangletox:
// viewangletox will give the next greatest x
// after the view angle.
//
// Calc focallength
// so FIELDOFVIEW angles covers SCREENWIDTH.
focallength = FixedDiv(centerxfrac, finetangent[FINEANGLES/4+FIELDOFVIEW/2]);
for (i=0 ; i<FINEANGLES/2 ; i++)
{
int t;
if (finetangent[i] > FRACUNIT*2)
t = -1;
else
if (finetangent[i] < -FRACUNIT*2)
t = viewwidth+1;
else
{
t = FixedMul(finetangent[i], focallength);
t = (centerxfrac - t + FRACUNIT-1) >> FRACBITS;
if (t < -1)
t = -1;
else
if (t > viewwidth+1)
t = viewwidth+1;
}
viewangletox[i] = t;
}
// Scan viewangletox[] to generate xtoviewangle[]:
// xtoviewangle will give the smallest view angle
// that maps to x.
for (x=0; x<=viewwidth; x++)
{
for (i=0; viewangletox[i] > x; i++)
;
xtoviewangle[x] = (i<<ANGLETOFINESHIFT)-ANG90;
}
// Take out the fencepost cases from viewangletox.
for (i=0; i<FINEANGLES/2; i++)
if (viewangletox[i] == -1)
viewangletox[i] = 0;
else
if (viewangletox[i] == viewwidth+1)
viewangletox[i] = viewwidth;
clipangle = xtoviewangle[0];
}
//
// R_InitLightTables
// Only inits the zlight table,
// because the scalelight table changes with view size.
//
#define DISTMAP 2
void R_InitLightTables (void)
{
int i;
// killough 4/4/98: dynamic colormaps
c_zlight = malloc(sizeof(*c_zlight) * numcolormaps);
c_scalelight = malloc(sizeof(*c_scalelight) * numcolormaps);
// Calculate the light levels to use
// for each level / distance combination.
for (i=0; i< LIGHTLEVELS; i++)
{
int j, startmap = ((LIGHTLEVELS-1-i)*2)*NUMCOLORMAPS/LIGHTLEVELS;
for (j=0; j<MAXLIGHTZ; j++)
{
// CPhipps - use 320 here instead of SCREENWIDTH, otherwise hires is
// brighter than normal res
int scale = FixedDiv ((320/2*FRACUNIT), (j+1)<<LIGHTZSHIFT);
int t, level = startmap - (scale >>= LIGHTSCALESHIFT)/DISTMAP;
if (level < 0)
level = 0;
else
if (level >= NUMCOLORMAPS)
level = NUMCOLORMAPS-1;
// killough 3/20/98: Initialize multiple colormaps
level *= 256;
for (t=0; t<numcolormaps; t++) // killough 4/4/98
c_zlight[t][i][j] = colormaps[t] + level;
}
}
}
//
// R_SetViewSize
// Do not really change anything here,
// because it might be in the middle of a refresh.
// The change will take effect next refresh.
//
boolean setsizeneeded;
int setblocks;
void R_SetViewSize(int blocks)
{
setsizeneeded = true;
setblocks = blocks;
}
//
// R_ExecuteSetViewSize
//
void R_ExecuteSetViewSize (void)
{
int i;
setsizeneeded = false;
if (setblocks == 11)
{
scaledviewwidth = SCREENWIDTH;
viewheight = SCREENHEIGHT;
}
else
{
scaledviewwidth = setblocks*32;
viewheight = (setblocks*168/10)&~7;
}
viewwidth = scaledviewwidth;
centery = viewheight/2;
centerx = viewwidth/2;
centerxfrac = centerx<<FRACBITS;
centeryfrac = centery<<FRACBITS;
projection = centerxfrac;
R_InitBuffer (scaledviewwidth, viewheight);
R_InitTextureMapping();
// psprite scales
pspritescale = FRACUNIT*viewwidth/SCREENWIDTH;
pspriteiscale = FRACUNIT*SCREENWIDTH/viewwidth;
// thing clipping
for (i=0 ; i<viewwidth ; i++)
screenheightarray[i] = viewheight;
// planes
for (i=0 ; i<viewheight ; i++)
{ // killough 5/2/98: reformatted
fixed_t dy = D_abs(((i-viewheight/2)<<FRACBITS)+FRACUNIT/2);
yslope[i] = FixedDiv ( (viewwidth)/2*FRACUNIT, dy);
}
for (i=0 ; i<viewwidth ; i++)
{
fixed_t cosadj = D_abs(finecosine[xtoviewangle[i]>>ANGLETOFINESHIFT]);
distscale[i] = FixedDiv(FRACUNIT,cosadj);
}
// Calculate the light levels to use
// for each level / scale combination.
for (i=0; i<LIGHTLEVELS; i++)
{
int j, startmap = ((LIGHTLEVELS-1-i)*2)*NUMCOLORMAPS/LIGHTLEVELS;
for (j=0 ; j<MAXLIGHTSCALE ; j++)
{
// CPhipps - use 320 here instead of SCREENWIDTH, otherwise hires is
// brighter than normal res
int scale = FixedDiv ((320/2*FRACUNIT), (j+1)<<LIGHTZSHIFT);
int t, level = startmap - (scale >>= LIGHTSCALESHIFT)/DISTMAP;
if (level < 0)
level = 0;
if (level >= NUMCOLORMAPS)
level = NUMCOLORMAPS-1;
// killough 3/20/98: initialize multiple colormaps
level *= 256;
for (t=0; t<numcolormaps; t++) // killough 4/4/98
c_scalelight[t][i][j] = colormaps[t] + level;
}
}
}
//
// R_Init
//
extern int screenblocks;
void R_Init (void)
{
// CPhipps - R_DrawColumn isn't constant anymore, so must
// initialise in code
colfunc = R_DrawColumn; // current column draw function
if (SCREENWIDTH<320)
I_Error("R_Init: Screenwidth(%d) < 320",SCREENWIDTH);
#if 1
printf("\nR_LoadTrigTables: ");
R_LoadTrigTables();
#endif
printf("\nR_InitData: ");
R_InitData();
R_SetViewSize(screenblocks);
printf("\nR_Init: R_InitPlanes ");
R_InitPlanes();
printf("R_InitLightTables ");
R_InitLightTables();
printf("R_InitSkyMap ");
R_InitSkyMap();
printf("R_InitTranslationsTables ");
R_InitTranslationTables();
}
//
// R_PointInSubsector
//
// killough 5/2/98: reformatted, cleaned up
subsector_t *R_PointInSubsector(fixed_t x, fixed_t y)
{
int nodenum = numnodes-1;
while (!(nodenum & NF_SUBSECTOR))
nodenum = nodes[nodenum].children[R_PointOnSide(x, y, nodes+nodenum)];
return &subsectors[nodenum & ~NF_SUBSECTOR];
}
//
// R_SetupFrame
//
void R_SetupFrame (player_t *player)
{
int i, cm;
viewplayer = player;
viewx = player->mo->x;
viewy = player->mo->y;
viewangle = player->mo->angle + viewangleoffset;
extralight = player->extralight;
viewz = player->viewz;
viewsin = finesine[viewangle>>ANGLETOFINESHIFT];
viewcos = finecosine[viewangle>>ANGLETOFINESHIFT];
// killough 3/20/98, 4/4/98: select colormap based on player status
if (player->mo->subsector->sector->heightsec != -1)
{
const sector_t *s = player->mo->subsector->sector->heightsec + sectors;
cm = viewz < s->floorheight ? s->bottommap : viewz > s->ceilingheight ?
s->topmap : s->midmap;
if (cm < 0 || cm > numcolormaps)
cm = 0;
}
else
cm = 0;
fullcolormap = colormaps[cm];
zlight = c_zlight[cm];
scalelight = c_scalelight[cm];
if (player->fixedcolormap)
{
// killough 3/20/98: localize scalelightfixed (readability/optimization)
static lighttable_t *scalelightfixed[MAXLIGHTSCALE];
fixedcolormap = fullcolormap // killough 3/20/98: use fullcolormap
+ player->fixedcolormap*256*sizeof(lighttable_t);
walllights = scalelightfixed;
for (i=0 ; i<MAXLIGHTSCALE ; i++)
scalelightfixed[i] = fixedcolormap;
}
else
fixedcolormap = 0;
validcount++;
}
//
// R_RenderView
//
void R_RenderPlayerView (player_t* player)
{
R_SetupFrame (player);
// Clear buffers.
R_ClearClipSegs ();
R_ClearDrawSegs ();
R_ClearPlanes ();
R_ClearSprites ();
// check for new console commands.
// NetUpdate ();
// The head node is the last node output.
R_RenderBSPNode (numnodes-1);
// Check for new console commands.
// NetUpdate ();
R_DrawPlanes ();
// Check for new console commands.
// NetUpdate ();
R_DrawMasked ();
// Check for new console commands.
// NetUpdate ();
}

125
apps/plugins/doom/r_main.h Normal file
View file

@ -0,0 +1,125 @@
/* Emacs style mode select -*- C++ -*-
*-----------------------------------------------------------------------------
*
*
* PrBoom a Doom port merged with LxDoom and LSDLDoom
* based on BOOM, a modified and improved DOOM engine
* Copyright (C) 1999 by
* id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
* Copyright (C) 1999-2000 by
* Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* DESCRIPTION:
* Renderer main interface.
*
*-----------------------------------------------------------------------------*/
#ifndef __R_MAIN__
#define __R_MAIN__
#include "d_player.h"
#include "r_data.h"
#ifdef __GNUG__
#pragma interface
#endif
//
// POV related.
//
extern fixed_t viewcos;
extern fixed_t viewsin;
extern int viewwidth;
extern int viewheight;
extern int viewwindowx;
extern int viewwindowy;
extern int centerx;
extern int centery;
extern fixed_t centerxfrac;
extern fixed_t centeryfrac;
extern fixed_t projection;
extern int validcount;
extern int linecount;
extern int loopcount;
//
// Rendering stats
//
extern int rendered_visplanes, rendered_segs, rendered_vissprites;
extern boolean rendering_stats;
//
// Lighting LUT.
// Used for z-depth cuing per column/row,
// and other lighting effects (sector ambient, flash).
//
// Lighting constants.
#define LIGHTLEVELS 16
#define LIGHTSEGSHIFT 4
#define MAXLIGHTSCALE 48
#define LIGHTSCALESHIFT 12
#define MAXLIGHTZ 128
#define LIGHTZSHIFT 20
// killough 3/20/98: Allow colormaps to be dynamic (e.g. underwater)
extern lighttable_t *(*scalelight)[MAXLIGHTSCALE];
extern lighttable_t *(*zlight)[MAXLIGHTZ];
extern lighttable_t *fullcolormap;
extern int numcolormaps; // killough 4/4/98: dynamic number of maps
extern lighttable_t **colormaps;
// killough 3/20/98, 4/4/98: end dynamic colormaps
extern int extralight;
extern lighttable_t *fixedcolormap;
// Number of diminishing brightness levels.
// There a 0-31, i.e. 32 LUT in the COLORMAP lump.
#define NUMCOLORMAPS 32
//
// Function pointers to switch refresh/drawing functions.
// Used to select shadow mode etc.
//
extern void (*colfunc)(void);
//
// Utility functions.
//
int R_PointOnSide(fixed_t x, fixed_t y, const node_t *node);
int R_PointOnSegSide(fixed_t x, fixed_t y, const seg_t *line);
angle_t R_PointToAngle(fixed_t x, fixed_t y);
angle_t R_PointToAngle2(fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2);
subsector_t *R_PointInSubsector(fixed_t x, fixed_t y);
//
// REFRESH - the actual rendering functions.
//
void R_RenderPlayerView(player_t *player); // Called by G_Drawer.
void R_Init(void); // Called by startup code.
void R_SetViewSize(int blocks); // Called by M_Responder.
void R_ExecuteSetViewSize(void); // cph - called by D_Display to complete a view resize
#endif

434
apps/plugins/doom/r_plane.c Normal file
View file

@ -0,0 +1,434 @@
/* Emacs style mode select -*- C++ -*-
*-----------------------------------------------------------------------------
*
*
* PrBoom a Doom port merged with LxDoom and LSDLDoom
* based on BOOM, a modified and improved DOOM engine
* Copyright (C) 1999 by
* id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
* Copyright (C) 1999-2000 by
* Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* DESCRIPTION:
* Here is a core component: drawing the floors and ceilings,
* while maintaining a per column clipping list only.
* Moreover, the sky areas have to be determined.
*
* MAXVISPLANES is no longer a limit on the number of visplanes,
* but a limit on the number of hash slots; larger numbers mean
* better performance usually but after a point they are wasted,
* and memory and time overheads creep in.
*
* For more information on visplanes, see:
*
* http://classicgaming.com/doom/editing/
*
* Lee Killough
*
*-----------------------------------------------------------------------------*/
#include "z_zone.h" /* memory allocation wrappers -- killough */
#include "doomstat.h"
#include "w_wad.h"
#include "r_main.h"
#include "r_draw.h"
#include "r_things.h"
#include "r_sky.h"
#include "r_plane.h"
#include "rockmacros.h"
#define MAXVISPLANES 128 /* must be a power of 2 */
static visplane_t *visplanes[MAXVISPLANES] IBSS_ATTR; // killough
static visplane_t *freetail; // killough
static visplane_t **freehead = &freetail; // killough
visplane_t *floorplane, *ceilingplane;
// killough -- hash function for visplanes
// Empirically verified to be fairly uniform:
#define visplane_hash(picnum,lightlevel,height) \
((unsigned)((picnum)*3+(lightlevel)+(height)*7) & (MAXVISPLANES-1))
size_t maxopenings;
short *openings,*lastopening;
// Clip values are the solid pixel bounding the range.
// floorclip starts out SCREENHEIGHT
// ceilingclip starts out -1
short floorclip[SCREENWIDTH], ceilingclip[SCREENWIDTH];
// spanstart holds the start of a plane span; initialized to 0 at start
static int spanstart[SCREENHEIGHT]; // killough 2/8/98
//
// texture mapping
//
static lighttable_t **planezlight;
static fixed_t planeheight;
// killough 2/8/98: make variables static
static fixed_t basexscale, baseyscale;
static fixed_t cachedheight[SCREENHEIGHT];
static fixed_t cacheddistance[SCREENHEIGHT];
static fixed_t cachedxstep[SCREENHEIGHT];
static fixed_t cachedystep[SCREENHEIGHT];
static fixed_t xoffs, yoffs; // killough 2/28/98: flat offsets
fixed_t yslope[SCREENHEIGHT], distscale[SCREENWIDTH];
//
// R_InitPlanes
// Only at game startup.
//
void R_InitPlanes (void)
{
}
//
// R_MapPlane
//
// Uses global vars:
// planeheight
// ds_source
// basexscale
// baseyscale
// viewx
// viewy
// xoffs
// yoffs
//
// BASIC PRIMITIVE
//
static void R_MapPlane(int y, int x1, int x2)
{
angle_t angle;
fixed_t distance, length;
unsigned index;
#ifdef RANGECHECK
if (x2 < x1 || x1<0 || x2>=viewwidth || (unsigned)y>(unsigned)viewheight)
I_Error ("R_MapPlane: %i, %i at %i",x1,x2,y);
#endif
if (planeheight != cachedheight[y])
{
cachedheight[y] = planeheight;
distance = cacheddistance[y] = FixedMul (planeheight, yslope[y]);
ds_xstep = cachedxstep[y] = FixedMul (distance,basexscale);
ds_ystep = cachedystep[y] = FixedMul (distance,baseyscale);
}
else
{
distance = cacheddistance[y];
ds_xstep = cachedxstep[y];
ds_ystep = cachedystep[y];
}
length = FixedMul (distance,distscale[x1]);
angle = (viewangle + xtoviewangle[x1])>>ANGLETOFINESHIFT;
// killough 2/28/98: Add offsets
ds_xfrac = viewx + FixedMul(finecosine[angle], length) + xoffs;
ds_yfrac = -viewy - FixedMul(finesine[angle], length) + yoffs;
if (!(ds_colormap = fixedcolormap))
{
index = distance >> LIGHTZSHIFT;
if (index >= MAXLIGHTZ )
index = MAXLIGHTZ-1;
ds_colormap = planezlight[index];
}
ds_y = y;
ds_x1 = x1;
ds_x2 = x2;
R_DrawSpan();
}
//
// R_ClearPlanes
// At begining of frame.
//
void R_ClearPlanes(void)
{
int i;
angle_t angle;
// opening / clipping determination
for (i=0 ; i<viewwidth ; i++)
floorclip[i] = viewheight, ceilingclip[i] = -1;
for (i=0;i<MAXVISPLANES;i++) // new code -- killough
for (*freehead = visplanes[i], visplanes[i] = NULL; *freehead; )
freehead = &(*freehead)->next;
lastopening = openings;
// texture calculation
memset (cachedheight, 0, sizeof(cachedheight));
// left to right mapping
angle = (viewangle-ANG90)>>ANGLETOFINESHIFT;
// scale will be unit scale at SCREENWIDTH/2 distance
basexscale = FixedDiv (finecosine[angle],centerxfrac);
baseyscale = -FixedDiv (finesine[angle],centerxfrac);
}
// New function, by Lee Killough
static visplane_t *new_visplane(unsigned hash)
{
visplane_t *check = freetail;
if (!check)
check = calloc(1, sizeof *check);
else
if (!(freetail = freetail->next))
freehead = &freetail;
check->next = visplanes[hash];
visplanes[hash] = check;
return check;
}
/*
* R_DupPlane
*
* cph 2003/04/18 - create duplicate of existing visplane and set initial range
*/
visplane_t *R_DupPlane(const visplane_t *pl, int start, int stop)
{
unsigned hash = visplane_hash(pl->picnum, pl->lightlevel, pl->height);
visplane_t *new_pl = new_visplane(hash);
new_pl->height = pl->height;
new_pl->picnum = pl->picnum;
new_pl->lightlevel = pl->lightlevel;
new_pl->xoffs = pl->xoffs; // killough 2/28/98
new_pl->yoffs = pl->yoffs;
new_pl->minx = start;
new_pl->maxx = stop;
memset(new_pl->top, 0xff, sizeof new_pl->top);
return new_pl;
}
//
// R_FindPlane
//
// killough 2/28/98: Add offsets
visplane_t *R_FindPlane(fixed_t height, int picnum, int lightlevel,
fixed_t xoffs, fixed_t yoffs)
{
visplane_t *check;
unsigned hash; // killough
if (picnum == skyflatnum || picnum & PL_SKYFLAT)
height = lightlevel = 0; // killough 7/19/98: most skies map together
// New visplane algorithm uses hash table -- killough
hash = visplane_hash(picnum,lightlevel,height);
for (check=visplanes[hash]; check; check=check->next) // killough
if (height == check->height &&
picnum == check->picnum &&
lightlevel == check->lightlevel &&
xoffs == check->xoffs && // killough 2/28/98: Add offset checks
yoffs == check->yoffs)
return check;
check = new_visplane(hash); // killough
check->height = height;
check->picnum = picnum;
check->lightlevel = lightlevel;
check->minx = viewwidth; // Was SCREENWIDTH -- killough 11/98
check->maxx = -1;
check->xoffs = xoffs; // killough 2/28/98: Save offsets
check->yoffs = yoffs;
memset (check->top, 0xff, sizeof check->top);
return check;
}
//
// R_CheckPlane
//
visplane_t *R_CheckPlane(visplane_t *pl, int start, int stop)
{
int intrl, intrh, unionl, unionh, x;
if (start < pl->minx)
intrl = pl->minx, unionl = start;
else
unionl = pl->minx, intrl = start;
if (stop > pl->maxx)
intrh = pl->maxx, unionh = stop;
else
unionh = pl->maxx, intrh = stop;
for (x=intrl ; x <= intrh && pl->top[x] == 0xffff; x++)
;
if (x > intrh) { /* Can use existing plane; extend range */
pl->minx = unionl; pl->maxx = unionh;
return pl;
} else /* Cannot use existing plane; create a new one */
return R_DupPlane(pl,start,stop);
}
//
// R_MakeSpans
//
static void R_MakeSpans(int x, int t1, int b1, int t2, int b2)
{
for (; t1 < t2 && t1 <= b1; t1++)
R_MapPlane(t1, spanstart[t1], x-1);
for (; b1 > b2 && b1 >= t1; b1--)
R_MapPlane(b1, spanstart[b1] ,x-1);
while (t2 < t1 && t2 <= b2)
spanstart[t2++] = x;
while (b2 > b1 && b2 >= t2)
spanstart[b2--] = x;
}
// New function, by Lee Killough
static void R_DoDrawPlane(visplane_t *pl)
{
register int x;
if (pl->minx <= pl->maxx) {
if (pl->picnum == skyflatnum || pl->picnum & PL_SKYFLAT) { // sky flat
int texture;
angle_t an, flip;
// killough 10/98: allow skies to come from sidedefs.
// Allows scrolling and/or animated skies, as well as
// arbitrary multiple skies per level without having
// to use info lumps.
an = viewangle;
if (pl->picnum & PL_SKYFLAT)
{
// Sky Linedef
const line_t *l = &lines[pl->picnum & ~PL_SKYFLAT];
// Sky transferred from first sidedef
const side_t *s = *l->sidenum + sides;
// Texture comes from upper texture of reference sidedef
texture = texturetranslation[s->toptexture];
// Horizontal offset is turned into an angle offset,
// to allow sky rotation as well as careful positioning.
// However, the offset is scaled very small, so that it
// allows a long-period of sky rotation.
an += s->textureoffset;
// Vertical offset allows careful sky positioning.
dc_texturemid = s->rowoffset - 28*FRACUNIT;
// We sometimes flip the picture horizontally.
//
// Doom always flipped the picture, so we make it optional,
// to make it easier to use the new feature, while to still
// allow old sky textures to be used.
flip = l->special==272 ? 0u : ~0u;
}
else
{ // Normal Doom sky, only one allowed per level
dc_texturemid = skytexturemid; // Default y-offset
texture = skytexture; // Default texture
flip = 0; // Doom flips it
}
/* Sky is always drawn full bright, i.e. colormaps[0] is used.
* Because of this hack, sky is not affected by INVUL inverse mapping.
* Until Boom fixed this. Compat option added in MBF. */
if (comp[comp_skymap] || !(dc_colormap = fixedcolormap))
dc_colormap = fullcolormap; // killough 3/20/98
dc_texheight = textureheight[skytexture]>>FRACBITS; // killough
// proff 09/21/98: Changed for high-res
dc_iscale = FRACUNIT*200/viewheight;
// killough 10/98: Use sky scrolling offset, and possibly flip picture
for (x = pl->minx; (dc_x = x) <= pl->maxx; x++)
if ((dc_yl = pl->top[x]) <= (dc_yh = pl->bottom[x]))
{
dc_source = R_GetColumn(texture, ((an + xtoviewangle[x])^flip) >>
ANGLETOSKYSHIFT);
colfunc();
}
} else { // regular flat
int stop, light;
ds_source = W_CacheLumpNum(firstflat + flattranslation[pl->picnum]);
xoffs = pl->xoffs; // killough 2/28/98: Add offsets
yoffs = pl->yoffs;
planeheight = D_abs(pl->height-viewz);
light = (pl->lightlevel >> LIGHTSEGSHIFT) + extralight;
if (light >= LIGHTLEVELS)
light = LIGHTLEVELS-1;
if (light < 0)
light = 0;
stop = pl->maxx + 1;
planezlight = zlight[light];
pl->top[pl->minx-1] = pl->top[stop] = 0xffff;
for (x = pl->minx ; x <= stop ; x++)
R_MakeSpans(x,pl->top[x-1],pl->bottom[x-1],pl->top[x],pl->bottom[x]);
W_UnlockLumpNum(firstflat + flattranslation[pl->picnum]);
}
}
}
//
// RDrawPlanes
// At the end of each frame.
//
void R_DrawPlanes (void)
{
visplane_t *pl;
int i;
for (i=0;i<MAXVISPLANES;i++)
for (pl=visplanes[i]; pl; pl=pl->next)
R_DoDrawPlane(pl);
}

Some files were not shown because too many files have changed in this diff Show more