ZDoom 1.23b25.

This commit is contained in:
Randy Heit 2001-08-15 00:00:00 +00:00
parent 320d485ed0
commit 58398fe06f
418 changed files with 21199 additions and 4683 deletions

172
Makefile Normal file
View file

@ -0,0 +1,172 @@
####################################################################
#
# Makefile for ZDoom. This probably requires GNU Make.
#
####################################################################
CC = gcc -V3.0
CXX = g++ -V3.0
AS = nasm
RM = rm -f
RMTREE = rm -R
RMDIR = rmdir
CP = cp
LD = ld
INSTALL = install
ECHO = echo
TAR = tar
GZIP = gzip
basename = zdoom-1.23
# the OS type we are building for; should match a directory in src_dir
SYSTEM = linux
# distribution names
BINTAR = $(basename)-i586.tar.gz
SRCTAR = $(basename).tar.gz
# options common to all builds
prefix = /usr/local
lib_dir = $(prefix)/lib
bin_dir = $(prefix)/bin
doc_dir = $(prefix)/doc/zdoom
share_dir = $(prefix)/share
zdoomshare_dir = $(share_dir)/zdoom
X_libs = /usr/X11R6/lib
src_dir = src
IMPDIR = $(src_dir)/$(SYSTEM)
mode = release
# directory to hold all intermediate files
INTDIR = $(IMPDIR)/$(mode)
SRCDOC = INSTALL README
CPPFLAGS_common = -Wall -Winline -I$(src_dir) -I$(src_dir)/fmodsound -I$(IMPDIR) \
-I$(src_dir)/g_shared -I$(src_dir)/g_doom -I$(src_dir)/g_raven \
-I$(src_dir)/g_heretic -I$(src_dir)/g_hexen -Ifmod/api/inc
OUTFILE = zdoom
zdoom doom release all: $(INTDIR)/$(OUTFILE)
include $(IMPDIR)/files.mak
# options specific to the debug build
CPPFLAGS_debug = -g -Wp,-DRANGECHECK
LDFLAGS_debug =
ASFLAGS_debug = -g
DEFS_debug = -Wp,-DDEBUG,-DUSEASM # -DNOASM
# options specific to the release build
CPPFLAGS_release = -O2 -march=pentium -fomit-frame-pointer
LDFLAGS_release = -s
ASFLAGS_release =
DEFS_release = -Wp,-DNDEBUG,-DUSEASM
# select flags for this build
CPPFLAGS = $(CPPFLAGS_common) $(CPPFLAGS_$(mode)) \
$(DEFS_common) $(DEFS_$(mode))
LDFLAGS = $(LDFLAGS_common) $(LDFLAGS_$(mode))
ASFLAGS = $(ASFLAGS_common) $(ASFLAGS_$(mode))
# directory to get dependency files
DEPSDIR = deps
# pull in common object and source files extracted from zdoom.dsp
include dspfiles
# object files
OBJS = $(DSPOBJS) $(SYSOBJS)
# all dependency directories
DEPSDIRS = $(DSPDEPSDIRS) $(DEPSDIR)/$(SYSTEM)
ALLSOURCES = $(DSPSOURCES) $(SOURCES) $(HWSOURCES)
DSPDEPS = $(patsubst $(src_dir)/%.cpp,$(DEPSDIR)/%.d, \
$(filter %.cpp %.c,$(DSPSOURCES)))
SYSDEPS = $(patsubst $(src_dir)/%.cpp,$(DEPSDIR)/%.d, \
$(filter %.cpp %.c,$(SYSSOURCES)))
# If the VC++ project file changes, remake our list of source files
dspfiles: $(src_dir)/zdoom.dsp util/cvdsp
util/cvdsp $(src_dir)/zdoom.dsp > dspfiles
util/cvdsp: util/cvdsp.c
$(CC) util/cvdsp.c -o util/cvdsp -s -O
debug:
$(MAKE) mode=debug
clean:
$(RMTREE) $(IMPDIR)/release
$(RMTREE) $(IMPDIR)/debug
$(RMTREE) $(DEPSDIR)
$(INTDIR)/$(OUTFILE): common sysspecific
$(CXX) $(LDFLAGS) $(OBJS) -o $@ $(LIBS)
common: $(DSPINTDIRS) $(DSPDEPS) $(DSPOBJS)
sysspecific: $(INTDIR)/$(SYSTEM) $(SYSDEPS) $(SYSOBJS)
# Compile .cpp files
$(INTDIR)/%.o: $(src_dir)/%.cpp
$(CXX) $(CPPFLAGS) -c $< -o $@
# Assemble .nas files
$(INTDIR)/%.o: $(src_dir)/%.nas
$(AS) $(ASFLAGS) -o $@ $<
# Make intermediate directories
$(INTDIR):
mkdir -p $@
$(INTDIR)/%:
mkdir -p $@
#$(INTDIR)/%.o: $(IMPDIR)/%.nas
# $(AS) $(ASFLAGS) -o $@ $<
#$(INTDIR)/%.o: $(IMPDIR)/%.cpp
# $(CXX) $(CPPFLAGS) -c $< -o $@
# Create dependency files
$(DEPSDIR)/%.d: $(src_dir)/%.cpp
mkdir -p $(DEPSDIRS)
$(SHELL) -ec '$(CXX) -MM $(CPPFLAGS_common) $(DEFS_common) $< \
| sed '\''s/\($(*F)\)\.o[ :]*/$$\(INTDIR\)\/\1.o $(subst /,\/,$(@D))\/$(@F) : /g'\'' > $@; \
[ -s $@ ] || rm -f $@'
include $(DSPDEPS)
include $(SYSDEPS)
# Create a binary tarball
bintar: install
$(TAR) -cv \
$(bin_dir)/$(OUTFILE) \
$(lib_dir)/libzdoom-x.so \
$(lib_dir)/libzdoom-svgalib.so \
$(zdoomshare_dir)/zdoom.wad \
$(zdoomshare_dir)/xkeys \
$(zdoomshare_dir)/bots.cfg \
$(zdoomshare_dir)/railgun.bex \
$(doc_dir)/* \
| $(GZIP) -9c > $(BINTAR)
# Create a source tarball
srctar: $(ALLSOURCES) Makefile $(SRCDOC) docs/* other/*
$(SHELL) -ec 'cd ..; \
$(TAR) -cv --no-recursion --exclude=*.d --exclude=*~\
$(basename)/Makefile \
$(basename)/docs/* \
$(basename)/other/* \
$(basename)/$(src_dir)/* \
$(basename)/$(src_dir)/linux/* \
$(basename)/$(src_dir)/win32/* \
$(SRCDOC:%=$(basename)/%) \
| $(GZIP) -9c > $(basename)/$(SRCTAR)'
srcbz2: srctar
$(GZIP) -cd $(SRCTAR) | bzip2 -9c > $(basename).tar.bz2

View file

@ -1,98 +0,0 @@
#ifndef __C_DISPATCH_H__
#define __C_DISPATCH_H__
#include "dobject.h"
class FConfigFile;
#define HASH_SIZE 251 // I think this is prime
void C_ExecCmdLineParams ();
// add commands to the console as if they were typed in
// for map changing, etc
void AddCommandString (char *text);
// Write out alias commands to a file for all current aliases.
void C_ArchiveAliases (FConfigFile *f);
void C_SetAlias (const char *name, const char *cmd);
// build a single string out of multiple strings
char *BuildString (int argc, char **argv);
typedef void (*CCmdRun) (int argc, char **argv, const char *args, AActor *instigator);
class FConsoleCommand
{
public:
FConsoleCommand (const char *name, CCmdRun RunFunc);
virtual ~FConsoleCommand ();
virtual bool IsAlias ();
void PrintCommand () { Printf ("%s\n", m_Name); }
virtual void Run (int argc, char **argv, const char *args, AActor *instigator);
FConsoleCommand *m_Next, **m_Prev;
char *m_Name;
protected:
FConsoleCommand ();
bool AddToHash (FConsoleCommand **table);
CCmdRun m_RunFunc;
friend void C_DoCommand (char *cmd);
};
#define CCMD(n) \
void Cmd_##n (int, char **, const char *, AActor *); \
FConsoleCommand Cmd_##n##_ (#n, Cmd_##n); \
void Cmd_##n (int argc, char **argv, const char *args, AActor *m_Instigator)
class FConsoleAlias : public FConsoleCommand
{
public:
FConsoleAlias (const char *name, const char *command);
~FConsoleAlias ();
void Run (int argc, char **argv, const char *args, AActor *m_Instigator);
bool IsAlias ();
void PrintAlias () { Printf ("%s : %s\n", m_Name, m_Command); }
void Archive (FConfigFile *f);
protected:
char *m_Command;
};
// Actions
#define ACTION_MLOOK 0
#define ACTION_KLOOK 1
#define ACTION_USE 2
#define ACTION_ATTACK 3
#define ACTION_SPEED 4
#define ACTION_MOVERIGHT 5
#define ACTION_MOVELEFT 6
#define ACTION_STRAFE 7
#define ACTION_LOOKDOWN 8
#define ACTION_LOOKUP 9
#define ACTION_BACK 10
#define ACTION_FORWARD 11
#define ACTION_RIGHT 12
#define ACTION_LEFT 13
#define ACTION_MOVEDOWN 14
#define ACTION_MOVEUP 15
#define ACTION_JUMP 16
#define ACTION_SHOWSCORES 17
#define NUM_ACTIONS 18
extern byte Actions[NUM_ACTIONS];
struct ActionBits
{
unsigned int key;
int index;
char name[12];
};
extern unsigned int MakeKey (const char *s);
#endif //__C_DISPATCH_H__

View file

@ -1,403 +0,0 @@
#include "decallib.h"
#include "sc_man.h"
#include "w_wad.h"
#include "v_video.h"
#include "v_palette.h"
#include "cmdlib.h"
FDecalLib DecalLibrary;
struct FDecalLib::FTranslation
{
FTranslation (DWORD start, DWORD end);
FTranslation *LocateTranslation (DWORD start, DWORD end);
DWORD StartColor, EndColor;
FTranslation *Next;
BYTE PalRemap[256];
};
static const char *DecalKeywords[] =
{
"x-scale",
"y-scale",
"pic",
"translucency",
"flipx",
"flipy",
"fullbright",
"fuzzy",
"shade",
"colors",
NULL
};
enum
{
DECAL_XSCALE,
DECAL_YSCALE,
DECAL_PIC,
DECAL_TRANSLUCENCY,
DECAL_FLIPX,
DECAL_FLIPY,
DECAL_FULLBRIGHT,
DECAL_FUZZY,
DECAL_SHADE,
DECAL_COLORS
};
FDecalLib::FDecalLib ()
{
Root = NULL;
Translations = NULL;
}
FDecalLib::~FDecalLib ()
{
Clear ();
}
void FDecalLib::Clear ()
{
FTranslation *trans;
DelTree (Root);
Root = NULL;
trans = Translations;
while (trans != NULL)
{
FTranslation *next = trans->Next;
delete trans;
trans = next;
}
}
void FDecalLib::DelTree (FDecal *root)
{
if (root != NULL)
{
DelTree (root->Left);
DelTree (root->Right);
delete root;
}
}
void FDecalLib::ReadAllDecals ()
{
int lump, lastlump = 0;
while ((lump = W_FindLump ("DECALDEF", &lastlump)) != -1)
{
SC_OpenLumpNum (lump, "DECALDEF");
ReadDecals ();
SC_Close ();
}
}
void FDecalLib::ReadDecals ()
{
char decalName[64];
byte decalNum;
FDecal newdecal;
int code;
while (SC_GetString ())
{
if (!SC_Compare ("decal"))
{
SC_ScriptError (NULL);
}
SC_MustGetString ();
strcpy (decalName, sc_String);
SC_MustGetString ();
if (!IsNum (sc_String))
{
SC_UnGet ();
decalNum = 0;
}
else
{
unsigned long num = strtoul (sc_String, NULL, 10);
if (num < 1 || num > 255)
{
SC_ScriptError ("Decal ID must be between 1 and 255");
}
decalNum = (byte)num;
}
SC_MustGetStringName ("{");
memset (&newdecal, 0, sizeof(newdecal));
newdecal.PicNum = 0xffff;
newdecal.ScaleX = newdecal.ScaleY = 63;
newdecal.RenderFlags = RF_WALLSPRITE;
newdecal.RenderStyle = STYLE_Translucent;
newdecal.Alpha = 0x8000;
for (;;)
{
SC_GetString ();
if (SC_Compare ("}"))
{
AddDecal (decalName, decalNum, newdecal);
break;
}
switch ((code = SC_MustMatchString (DecalKeywords)))
{
case DECAL_XSCALE:
case DECAL_YSCALE:
SC_MustGetNumber ();
if (--sc_Number < 0)
sc_Number = 0;
if (sc_Number > 255)
sc_Number = 255;
if (code == DECAL_XSCALE)
newdecal.ScaleX = sc_Number;
else
newdecal.ScaleY = sc_Number;
break;
case DECAL_PIC:
SC_MustGetString ();
newdecal.PicNum = R_CheckTileNumForName (sc_String, TILE_Patch);
break;
case DECAL_TRANSLUCENCY:
SC_MustGetFloat ();
newdecal.Alpha = (WORD)(32768.f * sc_Float);
break;
case DECAL_FLIPX:
newdecal.RenderFlags |= RF_XFLIP;
break;
case DECAL_FLIPY:
newdecal.RenderFlags |= RF_YFLIP;
break;
case DECAL_FULLBRIGHT:
newdecal.RenderFlags |= RF_FULLBRIGHT;
break;
case DECAL_FUZZY:
newdecal.RenderStyle = STYLE_Fuzzy;
break;
case DECAL_SHADE:
SC_MustGetString ();
newdecal.RenderStyle = STYLE_Shaded;
newdecal.ShadeColor = V_GetColor (NULL, sc_String);
newdecal.ShadeColor |=
ColorMatcher.Pick (RPART(newdecal.ShadeColor),
GPART(newdecal.ShadeColor), BPART(newdecal.ShadeColor)) << 24;
break;
case DECAL_COLORS:
DWORD startcolor, endcolor;
SC_MustGetString (); startcolor = V_GetColor (NULL, sc_String);
SC_MustGetString (); endcolor = V_GetColor (NULL, sc_String);
newdecal.Translation = GenerateTranslation (startcolor, endcolor)->PalRemap;
break;
}
}
}
}
void FDecalLib::AddDecal (const char *name, byte num, const FDecal &decal)
{
FDecal *node = Root, **prev = &Root;
while (node != NULL)
{
int lexx = stricmp (name, node->Name);
if (lexx == 0)
{
break;
}
else if (lexx < 0)
{
prev = &node->Left;
node = node->Left;
}
else
{
prev = &node->Right;
node = node->Right;
}
}
if (node == NULL)
{
node = new FDecal;
*node = decal;
node->Name = copystring (name);
node->SpawnID = num;
node->Left = node->Right = NULL;
*prev = node;
}
else
{
char *savename = node->Name;
*node = decal;
node->Name = savename;
node->SpawnID = num;
}
if (num != 0)
{
FDecal *spawner = ScanTreeForNum (num, Root);
if (spawner != node)
{
spawner->SpawnID = 0;
}
}
}
const FDecal *FDecalLib::GetDecalByNum (byte num) const
{
if (num == 0)
{
return NULL;
}
FDecal *node = ScanTreeForNum (num, Root);
return node;
}
const FDecal *FDecalLib::GetDecalByName (const char *name) const
{
if (name == NULL)
{
return NULL;
}
FDecal *node = ScanTreeForName (name, Root);
return node;
}
FDecal *FDecalLib::ScanTreeForNum (const BYTE num, FDecal *root)
{
while (root != NULL)
{
if (root->SpawnID == num)
{
break;
}
ScanTreeForNum (num, root->Left);
root = root->Right; // Avoid tail-recursion
}
return root;
}
FDecal *FDecalLib::ScanTreeForName (const char *name, FDecal *root)
{
while (root != NULL)
{
int lexx = stricmp (name, root->Name);
if (lexx == 0)
{
break;
}
else if (lexx < 0)
{
root = root->Left;
}
else
{
root = root->Right;
}
}
return root;
}
FDecalLib::FTranslation *FDecalLib::GenerateTranslation (DWORD start, DWORD end)
{
FTranslation *trans;
if (Translations != NULL)
{
trans = Translations->LocateTranslation (start, end);
}
else
{
trans = NULL;
}
if (trans == NULL)
{
trans = new FTranslation (start, end);
trans->Next = Translations;
Translations = trans;
}
return trans;
}
FDecal::FDecal ()
{
Name = NULL;
Translation = NULL;
}
FDecal::~FDecal ()
{
if (Name != NULL)
delete[] Name;
}
void FDecal::ApplyToActor (AActor *actor) const
{
if (RenderStyle == STYLE_Shaded)
{
actor->SetShade (ShadeColor);
}
actor->translation = Translation;
actor->xscale = ScaleX;
actor->yscale = ScaleY;
actor->picnum = PicNum;
actor->renderflags = RenderFlags |
(actor->renderflags & (RF_RELMASK|RF_CLIPMASK|RF_INVISIBLE|RF_ONESIDED));
actor->alpha = Alpha << 1;
actor->RenderStyle = RenderStyle;
}
FDecalLib::FTranslation::FTranslation (DWORD start, DWORD end)
{
DWORD ri, gi, bi, rs, gs, bs;
PalEntry *first, *last;
int i;
StartColor = start;
EndColor = end;
Next = NULL;
first = (PalEntry *)&StartColor;
last = (PalEntry *)&EndColor;
ri = first->r << 24;
gi = first->g << 24;
bi = first->b << 24;
rs = last->r << 24;
gs = last->g << 24;
bs = last->b << 24;
rs = (rs - ri) / 255;
gs = (gs - ri) / 255;
bs = (bs - bi) / 255;
for (i = 1; i < 256; i++, ri += rs, gi += gs, bi += bs)
{
PalRemap[i] = ColorMatcher.Pick (ri >> 24, gi >> 24, bi >> 24);
}
PalRemap[0] = PalRemap[1];
}
FDecalLib::FTranslation *FDecalLib::FTranslation::LocateTranslation (DWORD start, DWORD end)
{
FTranslation *trans = this;
do
{
if (start == trans->StartColor && end == trans->EndColor)
{
return trans;
}
trans = trans->Next;
} while (trans != NULL);
return trans;
}

View file

@ -1,38 +0,0 @@
#ifndef __V_TEXT_H__
#define __V_TEXT_H__
#include "doomtype.h"
#include "v_font.h"
struct brokenlines_s {
short width;
byte nlterminated;
byte pad;
char *string;
};
typedef struct brokenlines_s brokenlines_t;
#define TEXTCOLOR_ESCAPE '\x81'
#define TEXTCOLOR_BRICK "\x81""A"
#define TEXTCOLOR_TAN "\x81""B"
#define TEXTCOLOR_GRAY "\x81""C"
#define TEXTCOLOR_GREY "\x81""C"
#define TEXTCOLOR_GREEN "\x81""D"
#define TEXTCOLOR_BROWN "\x81""E"
#define TEXTCOLOR_GOLD "\x81""F"
#define TEXTCOLOR_RED "\x81""G"
#define TEXTCOLOR_BLUE "\x81""H"
#define TEXTCOLOR_ORANGE "\x81""I"
#define TEXTCOLOR_WHITE "\x81""J"
#define TEXTCOLOR_YELLOW "\x81""k"
#define TEXTCOLOR_NORMAL "\x81-"
#define TEXTCOLOR_BOLD "\x81+"
brokenlines_t *V_BreakLines (int maxwidth, const byte *str, bool keepspace=false);
void V_FreeBrokenLines (brokenlines_t *lines);
inline brokenlines_t *V_BreakLines (int maxwidth, const char *str, bool keepspace=false)
{ return V_BreakLines (maxwidth, (const byte *)str, keepspace); }
#endif //__V_TEXT_H__

File diff suppressed because it is too large Load diff

View file

@ -1,45 +0,0 @@
#ifndef __MUS2STRM_H__
#define __MUS2STRM_H__
#include "mid2strm.h"
#define MUS_RELEASE 0
#define MUS_PLAY 1
#define MUS_PITCHBEND 2
#define MUS_SYSEVENT 3
#define MUS_CTRLCHANGE 4
#define MUS_UNKNOWN1 5
#define MUS_END 6
#define MUS_UNKNOWN2 7
#define MUSMAGIC "MUS\032"
typedef unsigned short int2;
typedef struct
{
char ID[4]; /* identifier "MUS" 0x1A */
int2 ScoreLength;
int2 ScoreStart;
int2 channels; /* count of primary channels */
int2 SecChannels; /* count of secondary channels (?) */
int2 InstrCnt;
} MUSheader;
struct Track
{
unsigned long current;
char vel;
long DeltaTime;
unsigned char LastEvent;
char *data; /* Primary data */
};
extern OUTSTREAMSTATE ots;
PSTREAMBUF mus2strmConvert (BYTE *inFile, DWORD inSize);
void mus2strmCleanup (void);
#endif //__MUS2STRM_H__

View file

@ -1,8 +1,3 @@
This file is sorely outdated in regards to DObject usage. You can still use
it as a baseline, but see the source for actual implementation details, since
many of them have changed.
ZDoom 1.19 offers a partial conversion of the Doom code to C++. As such, some
functions and classes have been encapsulated in classes. This document tries
to give an overview of those classes and how to use them.

756
docs/colors.txt Normal file
View file

@ -0,0 +1,756 @@
! $XConsortium: rgb.txt,v 10.41 94/02/20 18:39:36 rws Exp $
255 250 250 snow
248 248 255 ghost white
248 248 255 GhostWhite
245 245 245 white smoke
245 245 245 WhiteSmoke
220 220 220 gainsboro
255 250 240 floral white
255 250 240 FloralWhite
253 245 230 old lace
253 245 230 OldLace
250 240 230 linen
250 235 215 antique white
250 235 215 AntiqueWhite
255 239 213 papaya whip
255 239 213 PapayaWhip
255 235 205 blanched almond
255 235 205 BlanchedAlmond
255 228 196 bisque
255 218 185 peach puff
255 218 185 PeachPuff
255 222 173 navajo white
255 222 173 NavajoWhite
255 228 181 moccasin
255 248 220 cornsilk
255 255 240 ivory
255 250 205 lemon chiffon
255 250 205 LemonChiffon
255 245 238 seashell
240 255 240 honeydew
245 255 250 mint cream
245 255 250 MintCream
240 255 255 azure
240 248 255 alice blue
240 248 255 AliceBlue
230 230 250 lavender
255 240 245 lavender blush
255 240 245 LavenderBlush
255 228 225 misty rose
255 228 225 MistyRose
255 255 255 white
0 0 0 black
47 79 79 dark slate gray
47 79 79 DarkSlateGray
47 79 79 dark slate grey
47 79 79 DarkSlateGrey
105 105 105 dim gray
105 105 105 DimGray
105 105 105 dim grey
105 105 105 DimGrey
112 128 144 slate gray
112 128 144 SlateGray
112 128 144 slate grey
112 128 144 SlateGrey
119 136 153 light slate gray
119 136 153 LightSlateGray
119 136 153 light slate grey
119 136 153 LightSlateGrey
190 190 190 gray
190 190 190 grey
211 211 211 light grey
211 211 211 LightGrey
211 211 211 light gray
211 211 211 LightGray
25 25 112 midnight blue
25 25 112 MidnightBlue
0 0 128 navy
0 0 128 navy blue
0 0 128 NavyBlue
100 149 237 cornflower blue
100 149 237 CornflowerBlue
72 61 139 dark slate blue
72 61 139 DarkSlateBlue
106 90 205 slate blue
106 90 205 SlateBlue
123 104 238 medium slate blue
123 104 238 MediumSlateBlue
132 112 255 light slate blue
132 112 255 LightSlateBlue
0 0 205 medium blue
0 0 205 MediumBlue
65 105 225 royal blue
65 105 225 RoyalBlue
0 0 255 blue
30 144 255 dodger blue
30 144 255 DodgerBlue
0 191 255 deep sky blue
0 191 255 DeepSkyBlue
135 206 235 sky blue
135 206 235 SkyBlue
135 206 250 light sky blue
135 206 250 LightSkyBlue
70 130 180 steel blue
70 130 180 SteelBlue
176 196 222 light steel blue
176 196 222 LightSteelBlue
173 216 230 light blue
173 216 230 LightBlue
176 224 230 powder blue
176 224 230 PowderBlue
175 238 238 pale turquoise
175 238 238 PaleTurquoise
0 206 209 dark turquoise
0 206 209 DarkTurquoise
72 209 204 medium turquoise
72 209 204 MediumTurquoise
64 224 208 turquoise
0 255 255 cyan
224 255 255 light cyan
224 255 255 LightCyan
95 158 160 cadet blue
95 158 160 CadetBlue
102 205 170 medium aquamarine
102 205 170 MediumAquamarine
127 255 212 aquamarine
0 100 0 dark green
0 100 0 DarkGreen
85 107 47 dark olive green
85 107 47 DarkOliveGreen
143 188 143 dark sea green
143 188 143 DarkSeaGreen
46 139 87 sea green
46 139 87 SeaGreen
60 179 113 medium sea green
60 179 113 MediumSeaGreen
32 178 170 light sea green
32 178 170 LightSeaGreen
152 251 152 pale green
152 251 152 PaleGreen
0 255 127 spring green
0 255 127 SpringGreen
124 252 0 lawn green
124 252 0 LawnGreen
0 255 0 green
127 255 0 chartreuse
0 250 154 medium spring green
0 250 154 MediumSpringGreen
173 255 47 green yellow
173 255 47 GreenYellow
50 205 50 lime green
50 205 50 LimeGreen
154 205 50 yellow green
154 205 50 YellowGreen
34 139 34 forest green
34 139 34 ForestGreen
107 142 35 olive drab
107 142 35 OliveDrab
189 183 107 dark khaki
189 183 107 DarkKhaki
240 230 140 khaki
238 232 170 pale goldenrod
238 232 170 PaleGoldenrod
250 250 210 light goldenrod yellow
250 250 210 LightGoldenrodYellow
255 255 224 light yellow
255 255 224 LightYellow
255 255 0 yellow
255 215 0 gold
238 221 130 light goldenrod
238 221 130 LightGoldenrod
218 165 32 goldenrod
184 134 11 dark goldenrod
184 134 11 DarkGoldenrod
188 143 143 rosy brown
188 143 143 RosyBrown
205 92 92 indian red
205 92 92 IndianRed
139 69 19 saddle brown
139 69 19 SaddleBrown
160 82 45 sienna
205 133 63 peru
222 184 135 burlywood
245 245 220 beige
245 222 179 wheat
244 164 96 sandy brown
244 164 96 SandyBrown
210 180 140 tan
210 105 30 chocolate
178 34 34 firebrick
165 42 42 brown
233 150 122 dark salmon
233 150 122 DarkSalmon
250 128 114 salmon
255 160 122 light salmon
255 160 122 LightSalmon
255 165 0 orange
255 140 0 dark orange
255 140 0 DarkOrange
255 127 80 coral
240 128 128 light coral
240 128 128 LightCoral
255 99 71 tomato
255 69 0 orange red
255 69 0 OrangeRed
255 0 0 red
255 105 180 hot pink
255 105 180 HotPink
255 20 147 deep pink
255 20 147 DeepPink
255 192 203 pink
255 182 193 light pink
255 182 193 LightPink
219 112 147 pale violet red
219 112 147 PaleVioletRed
176 48 96 maroon
199 21 133 medium violet red
199 21 133 MediumVioletRed
208 32 144 violet red
208 32 144 VioletRed
255 0 255 magenta
238 130 238 violet
221 160 221 plum
218 112 214 orchid
186 85 211 medium orchid
186 85 211 MediumOrchid
153 50 204 dark orchid
153 50 204 DarkOrchid
148 0 211 dark violet
148 0 211 DarkViolet
138 43 226 blue violet
138 43 226 BlueViolet
160 32 240 purple
147 112 219 medium purple
147 112 219 MediumPurple
216 191 216 thistle
255 250 250 snow1
238 233 233 snow2
205 201 201 snow3
139 137 137 snow4
255 245 238 seashell1
238 229 222 seashell2
205 197 191 seashell3
139 134 130 seashell4
255 239 219 AntiqueWhite1
238 223 204 AntiqueWhite2
205 192 176 AntiqueWhite3
139 131 120 AntiqueWhite4
255 228 196 bisque1
238 213 183 bisque2
205 183 158 bisque3
139 125 107 bisque4
255 218 185 PeachPuff1
238 203 173 PeachPuff2
205 175 149 PeachPuff3
139 119 101 PeachPuff4
255 222 173 NavajoWhite1
238 207 161 NavajoWhite2
205 179 139 NavajoWhite3
139 121 94 NavajoWhite4
255 250 205 LemonChiffon1
238 233 191 LemonChiffon2
205 201 165 LemonChiffon3
139 137 112 LemonChiffon4
255 248 220 cornsilk1
238 232 205 cornsilk2
205 200 177 cornsilk3
139 136 120 cornsilk4
255 255 240 ivory1
238 238 224 ivory2
205 205 193 ivory3
139 139 131 ivory4
240 255 240 honeydew1
224 238 224 honeydew2
193 205 193 honeydew3
131 139 131 honeydew4
255 240 245 LavenderBlush1
238 224 229 LavenderBlush2
205 193 197 LavenderBlush3
139 131 134 LavenderBlush4
255 228 225 MistyRose1
238 213 210 MistyRose2
205 183 181 MistyRose3
139 125 123 MistyRose4
240 255 255 azure1
224 238 238 azure2
193 205 205 azure3
131 139 139 azure4
131 111 255 SlateBlue1
122 103 238 SlateBlue2
105 89 205 SlateBlue3
71 60 139 SlateBlue4
72 118 255 RoyalBlue1
67 110 238 RoyalBlue2
58 95 205 RoyalBlue3
39 64 139 RoyalBlue4
0 0 255 blue1
0 0 238 blue2
0 0 205 blue3
0 0 139 blue4
30 144 255 DodgerBlue1
28 134 238 DodgerBlue2
24 116 205 DodgerBlue3
16 78 139 DodgerBlue4
99 184 255 SteelBlue1
92 172 238 SteelBlue2
79 148 205 SteelBlue3
54 100 139 SteelBlue4
0 191 255 DeepSkyBlue1
0 178 238 DeepSkyBlue2
0 154 205 DeepSkyBlue3
0 104 139 DeepSkyBlue4
135 206 255 SkyBlue1
126 192 238 SkyBlue2
108 166 205 SkyBlue3
74 112 139 SkyBlue4
176 226 255 LightSkyBlue1
164 211 238 LightSkyBlue2
141 182 205 LightSkyBlue3
96 123 139 LightSkyBlue4
198 226 255 SlateGray1
185 211 238 SlateGray2
159 182 205 SlateGray3
108 123 139 SlateGray4
202 225 255 LightSteelBlue1
188 210 238 LightSteelBlue2
162 181 205 LightSteelBlue3
110 123 139 LightSteelBlue4
191 239 255 LightBlue1
178 223 238 LightBlue2
154 192 205 LightBlue3
104 131 139 LightBlue4
224 255 255 LightCyan1
209 238 238 LightCyan2
180 205 205 LightCyan3
122 139 139 LightCyan4
187 255 255 PaleTurquoise1
174 238 238 PaleTurquoise2
150 205 205 PaleTurquoise3
102 139 139 PaleTurquoise4
152 245 255 CadetBlue1
142 229 238 CadetBlue2
122 197 205 CadetBlue3
83 134 139 CadetBlue4
0 245 255 turquoise1
0 229 238 turquoise2
0 197 205 turquoise3
0 134 139 turquoise4
0 255 255 cyan1
0 238 238 cyan2
0 205 205 cyan3
0 139 139 cyan4
151 255 255 DarkSlateGray1
141 238 238 DarkSlateGray2
121 205 205 DarkSlateGray3
82 139 139 DarkSlateGray4
127 255 212 aquamarine1
118 238 198 aquamarine2
102 205 170 aquamarine3
69 139 116 aquamarine4
193 255 193 DarkSeaGreen1
180 238 180 DarkSeaGreen2
155 205 155 DarkSeaGreen3
105 139 105 DarkSeaGreen4
84 255 159 SeaGreen1
78 238 148 SeaGreen2
67 205 128 SeaGreen3
46 139 87 SeaGreen4
154 255 154 PaleGreen1
144 238 144 PaleGreen2
124 205 124 PaleGreen3
84 139 84 PaleGreen4
0 255 127 SpringGreen1
0 238 118 SpringGreen2
0 205 102 SpringGreen3
0 139 69 SpringGreen4
0 255 0 green1
0 238 0 green2
0 205 0 green3
0 139 0 green4
127 255 0 chartreuse1
118 238 0 chartreuse2
102 205 0 chartreuse3
69 139 0 chartreuse4
192 255 62 OliveDrab1
179 238 58 OliveDrab2
154 205 50 OliveDrab3
105 139 34 OliveDrab4
202 255 112 DarkOliveGreen1
188 238 104 DarkOliveGreen2
162 205 90 DarkOliveGreen3
110 139 61 DarkOliveGreen4
255 246 143 khaki1
238 230 133 khaki2
205 198 115 khaki3
139 134 78 khaki4
255 236 139 LightGoldenrod1
238 220 130 LightGoldenrod2
205 190 112 LightGoldenrod3
139 129 76 LightGoldenrod4
255 255 224 LightYellow1
238 238 209 LightYellow2
205 205 180 LightYellow3
139 139 122 LightYellow4
255 255 0 yellow1
238 238 0 yellow2
205 205 0 yellow3
139 139 0 yellow4
255 215 0 gold1
238 201 0 gold2
205 173 0 gold3
139 117 0 gold4
255 193 37 goldenrod1
238 180 34 goldenrod2
205 155 29 goldenrod3
139 105 20 goldenrod4
255 185 15 DarkGoldenrod1
238 173 14 DarkGoldenrod2
205 149 12 DarkGoldenrod3
139 101 8 DarkGoldenrod4
255 193 193 RosyBrown1
238 180 180 RosyBrown2
205 155 155 RosyBrown3
139 105 105 RosyBrown4
255 106 106 IndianRed1
238 99 99 IndianRed2
205 85 85 IndianRed3
139 58 58 IndianRed4
255 130 71 sienna1
238 121 66 sienna2
205 104 57 sienna3
139 71 38 sienna4
255 211 155 burlywood1
238 197 145 burlywood2
205 170 125 burlywood3
139 115 85 burlywood4
255 231 186 wheat1
238 216 174 wheat2
205 186 150 wheat3
139 126 102 wheat4
255 165 79 tan1
238 154 73 tan2
205 133 63 tan3
139 90 43 tan4
255 127 36 chocolate1
238 118 33 chocolate2
205 102 29 chocolate3
139 69 19 chocolate4
255 48 48 firebrick1
238 44 44 firebrick2
205 38 38 firebrick3
139 26 26 firebrick4
255 64 64 brown1
238 59 59 brown2
205 51 51 brown3
139 35 35 brown4
255 140 105 salmon1
238 130 98 salmon2
205 112 84 salmon3
139 76 57 salmon4
255 160 122 LightSalmon1
238 149 114 LightSalmon2
205 129 98 LightSalmon3
139 87 66 LightSalmon4
255 165 0 orange1
238 154 0 orange2
205 133 0 orange3
139 90 0 orange4
255 127 0 DarkOrange1
238 118 0 DarkOrange2
205 102 0 DarkOrange3
139 69 0 DarkOrange4
255 114 86 coral1
238 106 80 coral2
205 91 69 coral3
139 62 47 coral4
255 99 71 tomato1
238 92 66 tomato2
205 79 57 tomato3
139 54 38 tomato4
255 69 0 OrangeRed1
238 64 0 OrangeRed2
205 55 0 OrangeRed3
139 37 0 OrangeRed4
255 0 0 red1
238 0 0 red2
205 0 0 red3
139 0 0 red4
255 20 147 DeepPink1
238 18 137 DeepPink2
205 16 118 DeepPink3
139 10 80 DeepPink4
255 110 180 HotPink1
238 106 167 HotPink2
205 96 144 HotPink3
139 58 98 HotPink4
255 181 197 pink1
238 169 184 pink2
205 145 158 pink3
139 99 108 pink4
255 174 185 LightPink1
238 162 173 LightPink2
205 140 149 LightPink3
139 95 101 LightPink4
255 130 171 PaleVioletRed1
238 121 159 PaleVioletRed2
205 104 137 PaleVioletRed3
139 71 93 PaleVioletRed4
255 52 179 maroon1
238 48 167 maroon2
205 41 144 maroon3
139 28 98 maroon4
255 62 150 VioletRed1
238 58 140 VioletRed2
205 50 120 VioletRed3
139 34 82 VioletRed4
255 0 255 magenta1
238 0 238 magenta2
205 0 205 magenta3
139 0 139 magenta4
255 131 250 orchid1
238 122 233 orchid2
205 105 201 orchid3
139 71 137 orchid4
255 187 255 plum1
238 174 238 plum2
205 150 205 plum3
139 102 139 plum4
224 102 255 MediumOrchid1
209 95 238 MediumOrchid2
180 82 205 MediumOrchid3
122 55 139 MediumOrchid4
191 62 255 DarkOrchid1
178 58 238 DarkOrchid2
154 50 205 DarkOrchid3
104 34 139 DarkOrchid4
155 48 255 purple1
145 44 238 purple2
125 38 205 purple3
85 26 139 purple4
171 130 255 MediumPurple1
159 121 238 MediumPurple2
137 104 205 MediumPurple3
93 71 139 MediumPurple4
255 225 255 thistle1
238 210 238 thistle2
205 181 205 thistle3
139 123 139 thistle4
0 0 0 gray0
0 0 0 grey0
3 3 3 gray1
3 3 3 grey1
5 5 5 gray2
5 5 5 grey2
8 8 8 gray3
8 8 8 grey3
10 10 10 gray4
10 10 10 grey4
13 13 13 gray5
13 13 13 grey5
15 15 15 gray6
15 15 15 grey6
18 18 18 gray7
18 18 18 grey7
20 20 20 gray8
20 20 20 grey8
23 23 23 gray9
23 23 23 grey9
26 26 26 gray10
26 26 26 grey10
28 28 28 gray11
28 28 28 grey11
31 31 31 gray12
31 31 31 grey12
33 33 33 gray13
33 33 33 grey13
36 36 36 gray14
36 36 36 grey14
38 38 38 gray15
38 38 38 grey15
41 41 41 gray16
41 41 41 grey16
43 43 43 gray17
43 43 43 grey17
46 46 46 gray18
46 46 46 grey18
48 48 48 gray19
48 48 48 grey19
51 51 51 gray20
51 51 51 grey20
54 54 54 gray21
54 54 54 grey21
56 56 56 gray22
56 56 56 grey22
59 59 59 gray23
59 59 59 grey23
61 61 61 gray24
61 61 61 grey24
64 64 64 gray25
64 64 64 grey25
66 66 66 gray26
66 66 66 grey26
69 69 69 gray27
69 69 69 grey27
71 71 71 gray28
71 71 71 grey28
74 74 74 gray29
74 74 74 grey29
77 77 77 gray30
77 77 77 grey30
79 79 79 gray31
79 79 79 grey31
82 82 82 gray32
82 82 82 grey32
84 84 84 gray33
84 84 84 grey33
87 87 87 gray34
87 87 87 grey34
89 89 89 gray35
89 89 89 grey35
92 92 92 gray36
92 92 92 grey36
94 94 94 gray37
94 94 94 grey37
97 97 97 gray38
97 97 97 grey38
99 99 99 gray39
99 99 99 grey39
102 102 102 gray40
102 102 102 grey40
105 105 105 gray41
105 105 105 grey41
107 107 107 gray42
107 107 107 grey42
110 110 110 gray43
110 110 110 grey43
112 112 112 gray44
112 112 112 grey44
115 115 115 gray45
115 115 115 grey45
117 117 117 gray46
117 117 117 grey46
120 120 120 gray47
120 120 120 grey47
122 122 122 gray48
122 122 122 grey48
125 125 125 gray49
125 125 125 grey49
127 127 127 gray50
127 127 127 grey50
130 130 130 gray51
130 130 130 grey51
133 133 133 gray52
133 133 133 grey52
135 135 135 gray53
135 135 135 grey53
138 138 138 gray54
138 138 138 grey54
140 140 140 gray55
140 140 140 grey55
143 143 143 gray56
143 143 143 grey56
145 145 145 gray57
145 145 145 grey57
148 148 148 gray58
148 148 148 grey58
150 150 150 gray59
150 150 150 grey59
153 153 153 gray60
153 153 153 grey60
156 156 156 gray61
156 156 156 grey61
158 158 158 gray62
158 158 158 grey62
161 161 161 gray63
161 161 161 grey63
163 163 163 gray64
163 163 163 grey64
166 166 166 gray65
166 166 166 grey65
168 168 168 gray66
168 168 168 grey66
171 171 171 gray67
171 171 171 grey67
173 173 173 gray68
173 173 173 grey68
176 176 176 gray69
176 176 176 grey69
179 179 179 gray70
179 179 179 grey70
181 181 181 gray71
181 181 181 grey71
184 184 184 gray72
184 184 184 grey72
186 186 186 gray73
186 186 186 grey73
189 189 189 gray74
189 189 189 grey74
191 191 191 gray75
191 191 191 grey75
194 194 194 gray76
194 194 194 grey76
196 196 196 gray77
196 196 196 grey77
199 199 199 gray78
199 199 199 grey78
201 201 201 gray79
201 201 201 grey79
204 204 204 gray80
204 204 204 grey80
207 207 207 gray81
207 207 207 grey81
209 209 209 gray82
209 209 209 grey82
212 212 212 gray83
212 212 212 grey83
214 214 214 gray84
214 214 214 grey84
217 217 217 gray85
217 217 217 grey85
219 219 219 gray86
219 219 219 grey86
222 222 222 gray87
222 222 222 grey87
224 224 224 gray88
224 224 224 grey88
227 227 227 gray89
227 227 227 grey89
229 229 229 gray90
229 229 229 grey90
232 232 232 gray91
232 232 232 grey91
235 235 235 gray92
235 235 235 grey92
237 237 237 gray93
237 237 237 grey93
240 240 240 gray94
240 240 240 grey94
242 242 242 gray95
242 242 242 grey95
245 245 245 gray96
245 245 245 grey96
247 247 247 gray97
247 247 247 grey97
250 250 250 gray98
250 250 250 grey98
252 252 252 gray99
252 252 252 grey99
255 255 255 gray100
255 255 255 grey100
169 169 169 dark grey
169 169 169 DarkGrey
169 169 169 dark gray
169 169 169 DarkGray
0 0 139 dark blue
0 0 139 DarkBlue
0 139 139 dark cyan
0 139 139 DarkCyan
139 0 139 dark magenta
139 0 139 DarkMagenta
139 0 0 dark red
139 0 0 DarkRed
144 238 144 light green
144 238 144 LightGreen

1742
docs/commands.txt Normal file

File diff suppressed because it is too large Load diff

534
docs/history.txt Normal file
View file

@ -0,0 +1,534 @@
ZDoom Release History
More detailed info can be found in the file docs/rh-log.txt included with
the source code.
1.22 (12 December 1999)
=======================
* Scroll_Texture_Both and TranslucentLine specials can now be used from ACS.
* Fixed compiler-dependent cvar ordering during netgame arbitration.
* Fixed certain polyobject movement combinations that would not stop even
though they were supposed to.
* Did some cleanup for Alpha processors.
1.21 (26 November 1999)
=======================
* Fixed problems with thinkers removing themselves and causing other thinkers
to not get a chance to think.
* Added hud_scale cvar.
1.20 (25 November 1999)
=======================
* Fixed saving, reloading, and then resaving games when travelling between
levels in a hub.
* Fixed saving of ACS scripts scheduled to occur on a future level.
1.19 (24 November 1999)
=======================
* DeHackEd patches that set an actor's death sound to 0 without removing
the A_Scream call no longer crash.
* Fixed sync problems when playing with bullet puffs as particles vs as
sprites.
* Fixed friction when walking on the bottom of swimmable water.
* Added Jeffrey Cuenco's fixes to get -host and -join to work properly.
* Fixed BOOM generalized locked doors so that the open/close type will
actually close.
* Added pointer tracking and cleanup. This should fix the occasional
crashes when saving games and various other anomalies.
1.18b (15 September 1999)
=========================
* Fixed crash when saving games with more than 1024 objects.
* Fixed crash when loading a game without starting a new one first.
* Reduced the size and frequency of pregame network packets, under the
assumption that problems people were having using 1.18 on the Internet
are a result of limited modem bandwidth.
1.18a (12 September 1999)
=========================
* Fixed liquid warping temporarily stopping when changing levels.
* +/-mlook commands do not generate unknown command messages.
* Fixed support for maps with >10 deathmatch starts. Thanks to Roman
Hatsiev.
* Fixed support for the special "maps" EndGame? in MAPINFO lumps.
* Teleport destination (no gravity) now works as intended.
* Hopefully fixed savegame problems.
* Bots are restored from savegames.
* Fixed keyboard turning speed when -dup is used.
* Network commands get executed only once when -dup is used.
* In sectors with damaging floors and swimmable deep water, the damage
will also be applied while the player is swimming and not just when
the player is on the ground.
1.18 (5 September 1999)
=======================
* Replaced the older Cajun 0.71 with Cajun 0.97.
* Fixed handling of status bar faces with skins that provide them.
* Added swimmable water.
* Messages printed to the middle of the screen also print to the console.
* Skill and other server cvars get saved in savegames again.
* Added liquid texture warping.
* Bad MAPINFO lumps generate error messages instead of hanging.
* Realized that it's impossible to guarantee that all object pointers will
be valid without some effort, so FArchive saves DObject objects as NULL
objects now instead of aborting with an error.
* Added the ACS built-in functions localambientsound, activatorsound, and
setlinemonsterblocking.
* Added a thing that does nothing but count toward the number of secrets.
* Added a fly mode.
* Finally implemented the +moveup and +movedown commands.
118test10-source only (14 August 1999)
======================================
* Reimplemented hub travel.
* Optimized R_MapPlane slightly.
* Added fov command.
* Added vertical sub-pixel accuracy to the renderer.
* Added searches for an IWAD in the current directory, $DOOMWADDIR, and
$HOME.
118test9 (9 August 1999)
========================
* Fixed the "wild" bot spinning problem.
* Commands like changemap that could make network games go out of sync
should work properly now. The reason they would do that is closely related
to the reason that the bots would start spinning.
* Finished the serializer. Now savegames work. Hubs don't, because I haven't
written the player travelling code yet.
* Various other code cleanup.
118test8 (20 July 1999)
=======================
* Fixed a crash problem with the "burn" screen wipe.
* Fixed a crash problem with playing non-assigned sound sequences.
* Fixed a crash problem related to trying to shutdown the music subsystem
twice.
* If you try to add more coop bots than there are coop starts, the extra
bot leaves quietly instead of ending the game.
* Weapondrop is now a "server" cvar, which it should have been in the
first place.
* Changed the nodetable file format to be more compact.
* Bots can now be recorded in demos.
* Bots work in multiplayer games. Still buggy. Spawning bots can cause
consistancy failures, and they can start spinning wildly.
118test7 (12 July 1999)
=======================
* Fixed handling of maps with scrolling walls.
* Single player works again. In test6, all games were considered either coop
or deathmatch.
* Disabled the bot thinking code in single player games, so you don't suffer
a performance hitwhen not using bots.
* Added some performance counters accessible through the stat command.
118test6 (10 July 1999)
=======================
* Rewrote the wu line drawer to look better (especially in overlay mode).
* Stretched skies now get stretched horizontally as well as vertically.
* Did an initial integration of the Cajun Bot 0.71 code.
118test5 (6 July 1999)
======================
* Fixed a potential infinite loop that was introduced in 118test1.
* Delayed the initial execution of cvar callbacks.
* Added Heretic's anti-aliased Wu line drawer to the automap.
118test4 (3 July 1999)
======================
* Fixed the "Bad DCanvas::CopyRect" problem introduced in test3.
* Fixed sound sequences that should not be cut off when stopped (such as
the standard doors).
118test3 (2 July 1999)
======================
* Removed unnecessary display mode switches.
* Created a DCanvas class to encapsulate most 2D rendering.
118test2 (1 July 1999)
======================
* Fixed vertical aim clipping (BFG works again).
* Fixed monster wandering.
* Maps with mapthings of type 0 no longer generate warning messages.
* Crushers that do no damage no longer act as if they inflict pain to
actors.
* The alias command lists aliases again.
* Aliases are saved to the config file again.
118test1 (30 June 1999)
=======================
* Tweaked the optimized renderer for fifth-generation processors.
* Added the following specials:
- Line_AlignFloor
- Line_AlignCeiling
- Sector_SetRotation
- Sector_SetCeilingPanning
- Sector_SetFloorPanning
- Secter_SetCeilingScale
- Sector_SetFloorScale
* Added an additional parameter to the Transfer_Heights special.
* Switched to the OpenPTC library for display.
* Converted lots of code to an object-oriented C++ architecture.
1.17c (5 May 1999)
==================
* Fixed game saving crashes on maps with wind/current effects.
* In deep water sectors, the underwater light and fog colors can now be
set independently of the area above water.
* Added nojump, allowjump, nofreelook, and allowfreelook keywords for
use in MAPINFO lumps.
* The random number seed now changes each time you run the program.
1.17b (15 March 1999)
=====================
1.17b contains some minor bug fixes over 1.17 and 1.17a. It also loads
faster because the sprite dimensions are not cached until they are
actually needed. There are also some other internal changes in
preparation for supporting Heretic and Hexen, but those don't affect
the user yet.
1.17a (21 February 1999)
========================
1.17a is mostly minor bug fixes and was released because Herian 2 needed
some of those fixes. There are a few new features, however:
* If you have a skins directory in the same directory as zdoom.exe,
every wad file in it will be automatically loaded when the game starts.
This way, you don't have to load your skins by hand to use them.
* New formatting options for text printed using ACS.
* A code pointer to make monsters fire a railgun.
1.17 (17 February 1999)
=======================
* I'm releasing both DOS and Win32 versions simultaneously. (The DOS version
does not support MIDI/MUS music or a joystick.)
Bug fixes:
* Multiplayer games with monsters do not crash.
* Player corpses do not levitate and then fall down when a player respawns
in multiplayer games.
* Using togglemap outside of a game will not crash.
* Monsters stop attacking their target once it's dead.
* EV_StopPlat() does not get stuck in an infinite loop if there are moving
platforms.
* Partially invisible players are drawn the proper colors (instead of
green) if r_drawfuzz is 0.
* If you are invisible, so are your muzzle flashes.
* Trying to execute a non-existant script will not crash.
* Using a ChangeCamera special from an open script will not crash.
* The FloorAndCeiling_RaiseByValue and FloorAndCeiling_LowerByValues now
behave like Hexen's.
* Using -loadgame from the command line works.
* Fixed a memory leak during generation of the translucency tables.
* In high resolutions, weapon sprites meet the bottom of the screen.
* Sounds will not cut out mysteriously when there is no reason for them to
do so.
* Sounds will also not be stopped immediately when a thing is removed, so
explosion sounds will play to their full length.
* Things can make more than one sound at once.
* The deathmatch scoreboard is aligned properly at high resolutions.
* Spynext and spyprev work properly instead of leaving the status bar
"lagging behind" the player being viewed.
* The light-amp does not disable colored lighting.
* The sky gets inverted when using the invulnerability powerup.
* Implemented better z-checking code (from Heretic/Hexen).
* Pain elementals will spawn one lost soul at a time instead of two inside
of each other.
* Bex patches that use thing mnemonics really do work now, and unknown bit
messages aren't generated for regular DeHackEd patches.
* Linedef type 134 for regular DOOM/BOOM maps requires a red key for
activation (it was being improperly translated to require a blue one).
* Monsters can activate secret lines when they cross them. (See DOOM2/MAP08).
* The player extreme death sound is used.
* When a player leaves a network game, their body is removed instead of
being left empty.
* 0-length sounds are treated as empty sounds instead of sounds 4 gigs long.
* Skins that replaced player sounds with sounds in the IWAD work.
* Muzzle flashes do not light up foggy areas, and fullbright sprites stay
shrouded in fog.
* Alphanumeric keys no longer automatically repeat on the console.
* Wads such as gothicdm2 that used new flats in addition to the ones in the
IWAD with the regular doom.exe work.
New features:
* Significant speed improvements on modern processors.
* Armor and keys are shown on the fullscreen HUD.
* Colored text.
* A playdemo console command.
* A chasecam.
* A particle sytsem.
* An optional railgun to show off the particle system. (Start the game with
-deh railgun.bex if you want to use it.)
New features interesting for wad authors:
* Polyobjects.
* Sound sequences.
* WAVE files can be used as sound lumps without converting them to DMX's
format first.
* A sky can be specified to not be stretched even if it is shorter than 200
pixels.
* Sparks.
* Particle fountains.
* Parallax skies.
* Some new DeHackEd thing flags from Hexen (bobbing, reflective, etc.).
1.16 (22 December 1998)
=======================
Bug fixes:
* No more limit on size of savegames or demos.
* Screen resolutions above 320x200 are now the proper brightness (they were
too bright before.)
* Improved the brightness of the console font.
* Bullet puffs can show up on the floor and ceiling and not just walls.
* Missile weapons can trigger gun activation lines.
* Barrels now bounce around as much as they did in original DOOM. (They were
too "inert" in 1.14.)
* If a demo is being recorded, quitting the game normally will save the demo
to disk. (Previously, you had to use the stop command to do this.)
New features for players:
* Proper support for BOOM maps.
* Mouse wheel support and weapnext/weapprev commands.
* Doublebindings.
* Better analog joystick support.
* 180 degree turn command for keyboarders.
* Damage done by a rocket to its shooter is configurable and defaults to the
original Doom behavior.
* User-configurable gender. (Even though I don't have any new player sounds,
at least the obituaries are gender-aware. :-)
* Teamplay mode.
* New cvar to disable manual aiming of the BFG to prevent someone from
shooting it at the floor and quickly triggering tracer damage before.
* Maps no longer need to have as many deathmatch starts as there are players
in a deathmatch game.
* Support for Doom Legacy skins.
* Rewrote the MIDI/MUS code so that it has a working volume control.
* Many more console commands and cvars.
New features for editors:
* Proper support for BOOM maps.
* Obituaries are configurable with a .bex patch.
* Moster paths
* Colored lighting
* Fog can be applied to only part of a level instead of all of it.
* Per-sector gravity settings.
* Support for up to 256 ambient sounds (as opposed to the limit of 64 in
earlier versions).
* Sector damage adjustable from between 0-255 points of damage.
* Changable camera views.
* The following editing features that were introduced in Hexen are also
available in ZDoom:
- Most line specials take arguments that modify their behavior.
- ACS scripting.
- Hubs.
- Earthquakes.
- Dormant monsters.
- Trigger events to happen on monster deaths.
- "Waggling" floors.
- Pillar builders.
- Push activation lines (walking into a wall can trigger an event).
- Thing spawning (e.g. for traps/gifts).
1.14a (27 July 1998)
====================
Bugs fixed are:
* No more crashing about freeing a pointer without ZONEID when changing
levels.
* Skies wider than 256 pixels are drawn correctly.
* Monsters' heights are once again the same as they were in id's original
DOOM, so certain areas work properly again.
* Monsters shouldn't teleport into each other anymore.
* Improved support for international keyboards.
* The skill level chosen for a new game is no longer ignored if the new
game is started while a demo is playing.
Cosmetic changes:
* No more "sv_gravity changed to...", "skill changed to...", etc. messages
in single player games.
* Activating the player setup menu automatically stops any playing demos,
since it doesn't work properly while they play.
* Barrels don't go flying away when exploding anymore.
* Added def_patch cvar to automatically load a DeHackEd patch each time the
game is started.
* ZDoom save games now use the name zdoomsv?.dsg instead of doomsav?.dsg.
This version also includes some preliminary BOOM support as I started
integrating some of the BOOM source code with ZDoom:
* Medusa fix.
* Openings limit removed.
* Removed limit on switches and animations.
* Added support for BOOM-like ANIMATED and SWITCHES lumps in PWADs.
* Added support for BOOM-style scrollers (including conveyors).
* Added partial deep-water support.
1.14 (14 July 1998)
===================
Bugs fixed:
* The bunny scroller at the end of E3M8 no longer crashes the game.
* The IDKFA cheat gives the proper amount of armor again.
* Demo recording works again.
* Telefragging works again.
* Picking up the invulnerability sphere displays the correct colors now.
* DeHackEd patches containing text replacements no longer crash the game.
* Printing a string containing "%s" to the console and then changing the
video mode will no longer crash the game.
* Chat mode finally works again.
* If MIDAS can't initialize, you can still play the game but without sound.
* Pistol and chaingun sounds no longer cut out when there are lots of
zombie men shooting their pistols at you.
* Mouse input should no longer be so jerky under Windows NT.
* The crosshair is finally accurate for aiming.
* Autoaim is properly remembered each time you start ZDoom.
* Switches in the Ultimate Doom that aren't also in the shareware Doom
properly change their appearance when switched.
New features:
* Players can choose their own colors and names.
(Player setup menu is included).
* 8-player support (untested but should work).
* Miscellaneous internal code changes have been borrowed from the BOOM
source. (This does *not* mean that ZDoom supports BOOM levels yet.)
* Cheats, chat messages, and gamestate changes are now recorded in demos.
* Single-player demos recorded with ZDoom are generally smaller than
before.
* Quake 2-style deathmatch flags.
* Cheats (optionally) work in multiplayer games.
* Mode X is now supported under Win95, so all the machines that couldn't
run ZDoom in 320x200 before should be able to now.
* Fewer conditions result in error messages that quit the game. (If you
have Heretic, try this: Start ZDoom with -file heretic and go to the
console and type "MAP E1M1".)
* Keys can repeat in the console.
* The console and chat mode now use the localized keymap set with the
Keyboard control panel.
* Messages at the top of the screen now break along between words instead
of in the middle of them.
* Added -config command line parameter.
* Added -fastdemo command line parameter.
* Added new screen shot command. (bound to "Print Screen" key by default)
* Added Quake-like +showscores command. (bound to "\" key by default)
* Aliases are now saved in the config file.
* Added support for multiple pitched sounds like in very old version of
Doom. (Use the snd_pitched cvar to turn it on and off.)
1.13 (26 May 1998)
==================
* Fixed some major bugs (that crashed the game) and other lesser bugs that were
just annoying.
* 3-D collisions for walking under and standing on other things.
* The status bar can be scaled to the full width of the screen.
* The screen mode can be selected from a menu inside the game.
* ZDoom can run in a window on the desktop.
* Better DeHackEd support. Only a few text replacements are not supported.
Everything else works (including monster infighting which I haven't seen
in any other port).
* New features for level designers (see editing.txt for details):
Specification of next and secret maps on a per-map basis.
Specify sky texture on a per-map basis.
Use any lump in a wad as music for a map.
Give maps a custom name without using a DeHackEd patch.
Maps can be named anything (not just E?M? or MAP??).
Place any messages of any length between any two maps.
Hexen-style fog (of any color).
Ambient sounds--either point like Quake or global like Heretic and Hexen.
Automatic use of DeHackEd patches in PWADs.
No more tutti-frutti for short textures of certain heights.
zdoom.wcf file for use with WadAuthor.
* Rocket jumping. (One very important note about this: You need to be *in the
air* when your rocket explodes for rocket jumping to work. This is different
from Quake, and I will probably rewrite it for the next release.)
* Dynamic palette flashes.
* Supports stretching skies for freelook.
* Larger freelook range.
* Added tab-completion to the console.
* zdoom.cfg is now the name of the default configuration file since Doom
Legacy decided to start using config.cfg.
* French language support. (Set language cvar to "french".)
* Player obituaries.
* Unlimited ammo cheat (use g_unlimitedammo cvar).
1.12 (7 April 1998)
===================
* Some visual enhancements were made such as centering the menus and
drawing borders around the status bar in higher resolutions.
* Console commands can now be specified on the command line.
* Removed some of DOOM's limits such as VisPlanes, VisSprites, and 2S
HOM.
* Rewrote some of the inner loops in assembly. (There was some assembly
in 1.11, but it never got used.)
* New cvars relating to mouse movement. (invertmouse, m_pitch, m_yaw,
etc.)
* Mouse movement doesn't get sluggish in high resolutions.
* Automap colors are customizable.
* Automap overlay and rotation are available.
* Eight crosshairs.
* Shoot up/down.
* Alt-Tab and Pause work properly on all machines now.
* The +jump command now works.
* 25% and 75% translucency levels in addition to 50%. The translucency
tables now get saved to disk, too, so they only need to be calculated
once instead of every time the game is run.
* The console font is now editable.
* Near complete support for DeHackEd patches. (Only monster infighting
and changing a few minor text strings are not supported.)
* Sky height and position is now fixed for high resolutions. (It still
wraps if you look up, but at least now if you look straight ahead, it
never will.)
* Weapon sprite is always drawn at the correct location. (It was being
drawn too low in some resolutions like 400x300.)
* New options menu, which includes a key configuration screen.
* "Stealth" monsters.
* New full-screen HUD.
* And a few other things not worth mentioning separately.
1.11 (6 March 1998) Initial Release
===================================
* Works under both Windows 95 and NT 4.0, although it works best under
Win95.
* Limited support for the Pause key. It works with some keyboards on
some machines.
* Supports any resolution compatible with your DirectDraw drivers.
* Look up/down ala Heretic.
* Translucency for selected objects.
* Has a console with most of the functionality of Quake's. The only
significant missing feature is Tab-completion.
* Notarget cheat.
* Command to kill all monsters in a level or yourself.
* Can play MUS, MIDI, and MOD music.
* Selected sounds are played in surround sound.
* Doors that need keys to open are highlighted on the automap.
* Automap now shows various statistics in addition to the level name.
* True keybindings. Bind any key to any command or sequence of
commands.
* Intermission screen can now display your stats using absolute values
rather than percentages.
* A new more general demo format.

View file

@ -1,3 +1,313 @@
August 15, 2001
- Fixed: Wind in Hexen played wrong because it used S_GetSoundPlayingInfo(),
which has no way of following sound links. And now that I have random
sounds, I can't think of an easy way to make it work with those. Fixed it
by adding S_IsActorPlayingSomething() and using that instead. Changed a
few other places that called S_GetSoundPlayingInfo() to match.
- Fixed: Animating flats with an ANIMDEFS lump was broken.
- Fixed: The values returned by MakeKey() changed with each rebuild because
I was using the address of get_crc_table() as the CRC table instead of
actually calling the function to get the CRC table's location.
- Changed falling damage so that it can't kill you if you have god mode on.
- Added the filterstarts mapinfo flag to enable filtering out player starts
based on skill/gametype.
- Fixed: Redefining sounds with a random list (whether it had one before or
not) would cause problems because I was still sorting the S_rnd array--a
remnant from the time when random lists were found by using binary search
on S_rnd instead of by following the sound's link field.
- Added the sv_ihatesounds cvar for people who think they should be able
to shut up the BFG by landing on the ground. It forces all sounds to
use channel 1 instead of their preferred channel.
- Changed crushing ceilings to not restart their sound sequences each time
they reach the top or bottom of their path.
- Added a tag argument to S_StopSoundID() so that it only stops sounds in
a certain group. For my purposes, a group is currently defined as "any
sectors with the same tag." Actors do not utilise sound groups.
- Removed S_CheckSound().
- Added entries to DOOMX and HERETICX to make mirrors and slopes possible
without using the Hexen map format. Also added some of EDGE's default
linetypes for scrolling, translucency, and 2-unit floor raising.
August 12, 2001
- Changed the algorithm in W_LumpNameHash() and MakeKey() to a CRC32
algorithm because it hashes better. The only problem was that using a CRC,
klook and mlook both have the same CRC value, so I had to twiddle MakeKey
a little to give them unique keys.
August 11, 2001
- Added support for sprite frames with 16 rotations ala EDGE. The assignment
of rotations is the same as for EDGE: 1,9,2,A,3,B,4,C,5,D,6,E,7,F,8,G.
- Changed the music streamers to use FSOUND_Stream_Play3DAttrib because of a
report that they were actually being positioned with snd_3d true. I can't
use snd_3d under NT, where I do most of my development, so I don't know if
it made a difference or not.
- Fixed music recognition so that wave files can be played as music.
- Fudged about with slope handling in AActor::RunThink and P_CheckSlopeWalk
in an effort to let the player walk on some steep slopes that are not very
far off the surrounding ground. It is a big hack. I do not like it.
August 10, 2001
- Fixed drawing of rotated, scaled, and sloped flats.
- Fixed: PCD_PRINTNUMBER did not update the stack pointer.
August 8, 2001
- Fixed drawing of scaled and sloped flats.
- Restored the default radius and height for AInvisibleBridge, since it can no
longer inherit them from ABridge (which sets them at game start time).
August 4, 2001
- The alwaysfake modification for R_FakeFlat() did not work as intended, so I
removed it. The changes Lee Killough made for MBF seem to be good enough.
- Added new Thing_Destroy semantics: a tid of 0 will kill all monsters in the
level, just like the massacre cheat.
- Changed the friendly fire check in P_DamageMobj from (target != source) to
(target->player != source->player). This is just so that voodoo doll damage
cannot be reduced by turning on teamplay and changing teamdamage.
August 2, 2001
- Fixed: Items were respawning at the location where they were picked up when
they should have respawned where the level author placed them on the map.
- Changed the criteria for executing thing death specials from MF_COUNTKILL to
!MF_SPECIAL. Now you can give a barrel a special, and it will be executed when
the barrel is destroyed.
- Added the print command to print a string from the string table.
- Added the contributed Italian translation.
- Fixed: OB_UNDEAD said "revevant" instead of "revenant".
- Added names for all the new keys I found when looking at the dinput.h from
the DX8 SDK.
- Fixed: Bindings for kp= would not save in the ini file properly.
- Added rebind command to change the binding of the key that activated it.
This is intended to allow the creation of generic sequential aliases. (That
is, a series of aliases that do something, then bind a key to the next alias
in the sequence.) Like this:
alias dumb1 "echo one; rebind dumb2"
alias dumb2 "echo two; rebind dumb1"
July 26, 2001
- Fixed the TMulScale<x> definitions for GCC.
July 25, 2001
- In I_InitSound(), A3D is no longer the default if snd_3d is true.
- Moved s_sfxvolume, s_midivolume, and s_musicvolume into their appropriate
i_* files and integrated them with the functions they called. Also made
their ranges uniform at [0.0,1.0].
July 23, 2001
- Added some more checks to p_setup.cpp to catch bad maps. In this
case, the checks were added for ma_sincity.wad, which has two one-
sided linedefs that have -1 as their front sector and will crash if
you look at them.
June 8, 2001
- Fixed: Single files added with -file were recorded with their lump
names instead of the file names so if they got closed, they could
not be reopened.
June 3, 2001
- Finished TiMidity++ support for the Win32 version. It has two modes
of operations: 1) Just play as normal. This only works if the sound
card can play multiple wave streams at a time. 2) The default, have
TiMidity output wave data through a pipe and use that to fill an
FMOD stream. This will work with all sound cards and offers a little
more control over the output. The only problem I could not figure out
how to solve was how to make TiMidity quit (safely) when ZDoom wants
it to without modifying TiMidity. The solution I ended up using was to
have TiMidity start a thread that waits on a special named event and
calls exit when the event becomes signalled.
Ironically, the whole purpose of being able to use TiMidity for music
was that it could provide better music support under Linux, yet the
Linux side of things has not even been done yet. When I do write it, it
should work fine with an unmodified TiMidity.
June 1, 2001
- Put back the "<type> operator *()" members of the different cvar
classes because VC++ always uses a bitwise copy when passing a class
to a varargs function EVEN IF THE COPY CONSTRUCTOR IS DEFINED. This
means that something like printf ("%d", dmflags); will actually copy
dmflags to the stack instead of just dmflag's value. To make it work
as expected, you need to use printf ("%d", (int)dmflags);. Since
printf ("%d", *dmflags); is more compact, I decided operator * is
useful after all.
I just hope the timidity cvars are the only ones I used with printf
style functions. I did not see any others when I scanned the source,
but that doesn't mean I didn't miss any. :-(
- Changed the name of the variable passed to cvar callbacks from "var"
to "self" to make its use more obvious.
- Changed the "<type> operator *()" of the different cvar types to
"operator <type> ()" so that fetching a cvar's value looks just like
fetching any other variable's value.
May 30, 2001
- Added snd_midiprecache cvar so that people without GUSes can turn off
the precaching.
- Fixed: snd_surround was ignored.
- Fixed: snd_reset turned off MIDI.
- Added assembly routines for the different r_detail settings.
May 28, 2001
- Fixed: LEVEL_SPECOPENDOOR opened the door at a speed of 8*TICRATE instead
of 8*FRACUNIT, about 1872 times slower than it should have been.
May 26, 2001
- Fixed the positioning of y-doubled view windows and changed the x-doubling
so that it works with the optimized column drawer and does not need the
columnofs table.
- Fixed: M_FindResponseFile had a poor parser that considered lots of things
to be white space that weren't and did not treat quotes specially. Now it
uses essentially the same parser as the console.
- Fixed Heretic/Hexen wind specials so that they can apply even when an
actor's current velocity is 0.
- Added MF3_NOBLOCKMONST flag to indicate which things can cross
ML_BLOCKMONSTERS lines (because this is a better way than writing a
special case for Heretic's APod).
- Removed MaxSpecialCross, since it isn't needed anymore.
May 25, 2001
- Fixed: ATreeDestructible's default list was missing the mass property.
- Added Hexen's falling damage code and made the two types of falling damage
(ZDoom or Hexen) selectable from the level and dmflags. The dmflags falling
damage selector can now be used to enable falling damage but not to disable
it to avoid cheating in levels meant to be played with falling damage.
- Added a new dmflag (sv_nopassover) to make thing z-checking work as it
did in Doom (that is, not at all, except for missiles).
- Fixed: Chat macros did not work because Windows sends WM_SYSCHAR instead of
WM_CHAR when ALT is held down.
May 14, 2001
- Added decal groups and generators to DECALDEF.
- Fixed potential crash when defining decals with SpawnIDs.
May 3, 2001
- Added lightning scripts, which get executed whenever lightning strikes in
a level.
- Added the OutdoorLightning sector special (197) so that skyboxes can
flash outdoor (as opposed to indoor) lightning without fancy scripts.
May 2, 2001
- Fixed: When teleporting in a non-hub environment, the level's snapshot
would stay around if the player had saved while in it. This was especially
obvious if the player was moving to the same map he just left.
- Enabled key repeating in the menus.
- Added Hexen's lightning and fixed a bug in Hexen's code: It is not safe
to assume that the number of sectors that lightning can apply to will
remain constant through the level (thanks to ACS).
May 1, 20001
- Fixed: The SkyBox member of sector_t was not serialized.
April 26, 2001
- Fixed: When loading savegames, bobbing actors would have semi-random
heights because they get loaded in a different memory address than they
were saved at. The actor's address is used to determine its phase shift
compared to other bobbing actors, so when the actor was restored there
was no way to restore the original cycle. The solution is to take out the
bob offset before saving and add it back in when restoring.
- Added some DrawChar functions to DCanvas.
- Fixed DCanvas::StringWidth() for high ASCII characters.
- Changed the arrangement of codes in ESpecialGUIKeys to document the
standard ASCII codes in the range [1,31].
- Changed text color escape character from 0x81 to 0x1c, because 0x81 is a
printable character (though most Windows fonts seem to leave it undefined).
- Added support for WM_CHAR messages (they get fired off as EV_GUI_Char), so
now you can do all the standard Windows text manipulation stuff when typing
text at the console or elsewhere.
- Fixed: Decals were being saved to savegames but were not restored properly.
I think this was also causing crash problems after loading savegames.
- Changed mouse pointer hiding to change the cursor to an invisible cursor
instead of changing its visibility. This is to ensure that it works
correctly all the time instead of just most of the time.
- Removed testing for WM_ACTIVATE in the window procedure. Looking for
input focus is what we really want to do where the window's active status
was being checked.
- Got rid of I_Pause/ResumeMouse() and let the code in i_input.cpp decide
whether or not the pointer should be visible.
April 25, 2001
- Changed action command handling so that multiple keys bound to the same
action can coexist peacefully. That is, if you are pressing two keys bound
to the same action and release one of them, the action will still persist
until the second key is also released. This is like Quake.
- Added a check for key bindings to check if a binding contains the substring
"bind". Only if it does is the binding copied before being executed.
Previously, the command was always copied, even if it was unneccessary.
- Changed C_DoCommand()'s argument to a const char *.
April 24, 2001
- Changed command line handling for console commands so that argv and argc
are not calculated until the first time they are needed.
April 23, 2001
- Added shuffle parameter to playlist command.
April 22, 2001
- Added playlistprev and playlistnext commands.
- Pressing F1 at the save/load menu replaces the comment with the actual
file name of the savegame.
- Added GK_ entries for the function keys.
- Fixed: Quicksaving without saving/loading first crashed.
- Added reverse tab-completion to the console, when pressing Shift-Tab.
April 21, 2001
- Fixed: P_GiveAmmo() did not check userinfo.neverswitch before setting the
pendingweapon.
- Got rid of P_GiveWeapon() and moved its functionality into AWeapon::
TryPickup() and added some more AWeapon member functions just so that
picking up a weapon with sv_weaponstay true will produce all the standard
pickup feedback. This breaks the "give weapons" cheat, but you can still
summon them, so how bad is that really?
- Changed P_GroupLines() to warn about lines that lack frontsectors instead of
crashing.
April 20, 2001
- Fixed: In Heretic and Hexen, things are supposed to gib at negative half
their original health.
April 17, 2001
- Fixed: It was possible to stand at the very edge of a steep slope and not
fall off of it. It is still possible to "balance" by running away from the
edge, but I think that will take more time to fix than it's work (especially
if I really do go ahead and rewrite the level geometry collision detection.)
- Added in-air friction that depends on aircontrol: The greater aircontrol is,
the more friction affects things. Only affects players.
- Made level gravity and aircontrol accessible through MAPINFO as well as ACS.
- Disabled migration of zdoom.cfg. Perhaps it is better to make a clean break
from the old format than to try and import it if zdoom.ini is not found.
- Fixed: When the status bar face graphic changed and the status bar was
scaled, only the area enclosing the new graphic was updated to the screen.
It should update the entire face box.
- Fixed: When a dehacked/bex patch changed a level's name, the change was not
reflected in the level infos, so it did not actually become visible.
April 14, 2001
- Modified S_LookupPlayerSound() to detect player sounds which were defined
but did not have any valid lumps and automatically try again using male.
- Added storesavepic cvar.
- Added sorting to the savegame menus.
- Finally tested the savegame menus to make sure that they work with more
save games than are visible and discovered that they didn't, so I fixed
them so they do work.
- DCanvas::StringWidth() now knows about '\n' characters and returns the
length of the longest line.
- Changed the savegame menus to display games saved with an incompatible
ZDoom version so that the user has a more convenient means of deleting them
than by opening the savegames in a hex editor to find out which version each
one was saved with.
- Added "name" support to archives. Basically, names are just managed strings
that allow duplicates to be stored by index instead of duplicating the
string.
April 13, 2001
- Fixed: Particles were rendered as if they were being drawn to the main
frame buffer, even when they weren't.
- Fixed: After deleting the last save game, the menu would think you still
had a game selected and crashed if you tried to delete again.
- Discovered the problem with some of Tei Tenga's cameras: They have invalid
heights that put them above/below the sector. Copied the viewz clamping
from P_CalcHeight() into R_SetupFrame() to compensate. I don't know why
they worked in earlier versions.
- Moved zvox.wad loading to happen after loading the IWAD. There are certain
places where the IWAD is assumed to be the second wad loaded.
April 12, 2001
- Added a new game menu for Hexen that explains you cannot start Hexen from
a menu yet.

1134
docs/zdoom.txt Normal file

File diff suppressed because it is too large Load diff

35
install Normal file
View file

@ -0,0 +1,35 @@
This applies to the Linux version. Ignore it if you aren't using Linux.
INSTALLING ZDOOM
----------------
You need SDL installed. Go get it from http://www.libsdl.org/ if you don't
have it already.
You also need FMOD. Get it from http://www.fmod.org/
INSTALLING FROM SOURCE
----------------------
Get and install nasm from http://www.web-sites.co.uk/nasm/
Edit the makefile as needed. Then run make. Make install probably
doesn't work right now, so you can find the executable in
src/linux/release.
INSTALLING PRECOMPILED BINARIES
-------------------------------
I don't have any yet.
INSTALLING IWADS
----------------
Copy your DOOM IWAD files to /usr/share/zdoom. Alternatively, you can
keep the IWADs somewhere else and create symbolic links to them in
/usr/local/share/zdoom.
ZDoom will also look for IWADs in the current directory, ~/.zdoom, and
$DOOMWADDIR.
COMPILING UNDER OSF/1
---------------------
OSF/1 is no longer supported. (Not that it ever really was, but now I
have no access to OSF/1 machines, so I can't even test a minimal build.)

View file

@ -223,6 +223,7 @@ enum
MF3_CANBLAST = 0x00020000, // Actor is not a monster but can be blasted
MF3_NOTARGET = 0x00040000, // This actor not targetted when it hurts something else
MF3_DONTGIB = 0x00080000, // Don't gib this corpse
MF3_NOBLOCKMONST = 0x00100000, // Can cross ML_BLOCKMONSTERS lines
// --- mobj.renderflags ---
@ -285,6 +286,7 @@ enum ERenderStyle
#define HX_ALTSHADOW (0x6800)
class FPlayerSkin;
class FDecalBase;
inline AActor *GetDefaultByName (const char *name)
{
@ -437,7 +439,8 @@ public:
// no matter what (even if shot)
player_s *player; // only valid if type of APlayerPawn
int lastlook; // player number last looked for
mapthing2_t spawnpoint; // For nightmare respawn
WORD SpawnPoint[3]; // For nightmare respawn
WORD SpawnAngle;
AActor *tracer; // Thing being chased/attacked for tracers
fixed_t floorclip; // value to use for floor clipping
WORD tid; // thing identifier
@ -448,6 +451,7 @@ public:
AActor *goal; // Monster's goal if not chasing anything
FPlayerSkin *skin; // Sprite override
byte waterlevel; // 0=none, 1=feet, 2=waist, 3=eyes
BYTE SpawnFlags;
SWORD gear; // killough 11/98: used in torque simulation
// a linked list of sectors where this object appears
@ -480,6 +484,9 @@ public:
FState *IDeathState;
FState *RaiseState;
// [RH] Decal(s) this weapon/projectile generates on impact.
FDecalBase *DecalGenerator;
// Public functions
bool IsTeammate (AActor *other);

View file

@ -529,7 +529,7 @@ static void AM_initColors (BOOL overlayed)
NotSeenColor = TSWallColor = am_ovunseencolor.GetIndex ();
IntraTeleportColor = InterTeleportColor = am_ovtelecolor.GetIndex ();
}
else if (*am_usecustomcolors)
else if (am_usecustomcolors)
{
/* Use the custom colors in the am_* cvars */
Background = am_backcolor.GetIndex ();
@ -546,7 +546,7 @@ static void AM_initColors (BOOL overlayed)
InterTeleportColor = am_interlevelcolor.GetIndex ();
IntraTeleportColor = am_intralevelcolor.GetIndex ();
DWORD ba = *am_backcolor;
DWORD ba = am_backcolor;
int r = RPART(ba) - 16;
int g = GPART(ba) - 16;
@ -733,11 +733,11 @@ CCMD (togglemap)
if (!automapactive)
{
AM_Start ();
viewactive = (*am_overlay != 0.f);
viewactive = (am_overlay != 0.f);
}
else
{
if (*am_overlay && viewactive)
if (am_overlay && viewactive)
{
viewactive = false;
SB_state = screen->GetPageCount ();
@ -1561,7 +1561,7 @@ void AM_drawGrid (int color)
{
ml.a.x = x;
ml.b.x = x;
if (*am_rotate)
if (am_rotate)
{
AM_rotatePoint (&ml.a.x, &ml.a.y);
AM_rotatePoint (&ml.b.x, &ml.b.y);
@ -1583,7 +1583,7 @@ void AM_drawGrid (int color)
{
ml.a.y = y;
ml.b.y = y;
if (*am_rotate)
if (am_rotate)
{
AM_rotatePoint (&ml.a.x, &ml.a.y);
AM_rotatePoint (&ml.b.x, &ml.b.y);
@ -1608,7 +1608,7 @@ void AM_drawWalls ()
l.b.x = lines[i].v2->x;
l.b.y = lines[i].v2->y;
if (*am_rotate)
if (am_rotate)
{
AM_rotatePoint (&l.a.x, &l.a.y);
AM_rotatePoint (&l.b.x, &l.b.y);
@ -1756,7 +1756,7 @@ void AM_drawPlayers ()
if (!multiplayer)
{
if (*am_rotate)
if (am_rotate)
angle = ANG90;
else
angle = players[consoleplayer].camera->angle;
@ -1779,7 +1779,7 @@ void AM_drawPlayers ()
mpoint_t pt;
if (!playeringame[i] ||
(*deathmatch && !demoplayback) && p != players[consoleplayer].camera->player)
(deathmatch && !demoplayback) && p != players[consoleplayer].camera->player)
{
continue;
}
@ -1794,7 +1794,7 @@ void AM_drawPlayers ()
pt.y = p->mo->y;
angle = p->mo->angle;
if (*am_rotate)
if (am_rotate)
{
AM_rotatePoint (&pt.x, &pt.y);
angle -= players[consoleplayer].camera->angle - ANG90;
@ -1822,7 +1822,7 @@ void AM_drawThings (int color)
p.y = t->y;
angle = t->angle;
if (*am_rotate)
if (am_rotate)
{
AM_rotatePoint (&p.x, &p.y);
angle += ANG90 - players[consoleplayer].camera->angle;
@ -1853,7 +1853,7 @@ void AM_drawMarks ()
pt.x = markpoints[i].x;
pt.y = markpoints[i].y;
if (*am_rotate)
if (am_rotate)
AM_rotatePoint (&pt.x, &pt.y);
fx = CXMTOF(pt.x);
@ -1897,7 +1897,7 @@ void AM_Drawer ()
f_w = realviewwidth;
f_h = realviewheight;
f_p = screen->GetPitch ();
WeightingScale = (int)(*am_ovtrans * 256.f);
WeightingScale = (int)(am_ovtrans * 256.f);
if (WeightingScale < 0 || WeightingScale >= 256)
{
WeightingScale = 0;

View file

@ -31,7 +31,7 @@ CCMD (addbot)
return;
}
if (argc > 2)
if (argv.argc() > 2)
{
Printf ("addbot [botname] : add a bot to the game\n");
return;
@ -44,7 +44,7 @@ CCMD (addbot)
if (color>10) color=10;
}
*/
if (argc > 1)
if (argv.argc() > 1)
bglobal.SpawnBot (argv[1]);
else
bglobal.SpawnBot (NULL);

View file

@ -311,7 +311,7 @@ AActor *DCajunMaster::Choose_Mate (AActor *bot)
target = NULL;
closest_dist = FIXED_MAX;
if (*bot_observer)
if (bot_observer)
observer = players[consoleplayer].mo;
else
observer = NULL;
@ -324,10 +324,10 @@ AActor *DCajunMaster::Choose_Mate (AActor *bot)
if (playeringame[count]
&& client->mo
&& bot != client->mo
&& (bot->IsTeammate (client->mo) || !*deathmatch)
&& (bot->IsTeammate (client->mo) || !deathmatch)
&& client->mo->health > 0
&& client->mo != observer
&& ((bot->health/2) <= client->mo->health || !*deathmatch)
&& ((bot->health/2) <= client->mo->health || !deathmatch)
&& !p_leader[count]) //taken?
{
@ -374,7 +374,7 @@ AActor *DCajunMaster::Find_enemy (AActor *bot)
AActor *observer;
//Allow monster killing. keep monster enemy.
if (!*deathmatch)
if (!deathmatch)
return NULL;
//Note: It's hard to ambush a bot who is not alone
@ -386,7 +386,7 @@ AActor *DCajunMaster::Find_enemy (AActor *bot)
target = NULL;
closest_dist = FIXED_MAX;
if (*bot_observer)
if (bot_observer)
observer = players[consoleplayer].mo;
else
observer = NULL;

View file

@ -129,7 +129,7 @@ void DCajunMaster::Main (int buf)
}
//Check if player should go observer. Or un observe
if (*bot_observer && !observer)
if (bot_observer && !observer)
{
Printf ("%s is now observer\n", players[consoleplayer].userinfo.netname);
observer = true;
@ -138,7 +138,7 @@ void DCajunMaster::Main (int buf)
players[consoleplayer].mo->flags2 |= MF2_FLY;
players[consoleplayer].mo->LinkToWorld ();
}
else if (!*bot_observer && observer) //Go back
else if (!bot_observer && observer) //Go back
{
Printf ("%s returned to the fray\n", players[consoleplayer].userinfo.netname);
observer = false;
@ -182,13 +182,13 @@ void DCajunMaster::Init ()
}
}
if (ctf && *teamplay == false)
if (ctf && teamplay == false)
teamplay = true; //Need teamplay for ctf. (which is not done yet)
t_join = (wanted_botnum + 1) * SPAWN_DELAY; //The + is to let player get away before the bots come in.
//Determine Combat distance for each weapon.
if (*deathmatch)
if (deathmatch)
{
combatdst[wp_fist] = 1 ;
combatdst[wp_pistol] = 25000000;
@ -253,8 +253,10 @@ void DCajunMaster::End ()
bool DCajunMaster::SpawnBot (const char *name, int color)
{
#if 0
int num=0;
static bool red; //ctf, spawning helper, spawn first blue then a red ...
#endif
int i;
//COLORS
@ -334,11 +336,11 @@ bool DCajunMaster::SpawnBot (const char *name, int color)
Net_WriteByte (playernumber);
{
//Set color.
if (color == NOCOLOR && *bot_next_color < NOCOLOR && *bot_next_color >= 0)
if (color == NOCOLOR && bot_next_color < NOCOLOR && bot_next_color >= 0)
{
char concat[256];
strcpy (concat, thebot->info);
strcat (concat, colors[*bot_next_color]);
strcat (concat, colors[bot_next_color]);
Net_WriteString (concat);
}
else
@ -378,7 +380,7 @@ bool DCajunMaster::SpawnBot (const char *name, int color)
void DCajunMaster::DoAddBot (int bnum, char *info)
{
D_ReadUserInfoStrings (bnum, (byte **)&info, false);
if (!*deathmatch && playerstarts[bnum].type == 0)
if (!deathmatch && playerstarts[bnum].type == 0)
{
Printf ("%s tried to join, but there was no player %d start\n",
players[bnum].userinfo.netname, bnum+1);
@ -507,7 +509,7 @@ void DCajunMaster::ForgetBots ()
bool DCajunMaster::LoadBots ()
{
bglobal.ForgetBots ();
#ifndef UNIX
#ifndef unix
if (!FileExists ("zcajun/" BOTFILENAME))
{
DPrintf ("No " BOTFILENAME ", so no bots\n");

View file

@ -29,7 +29,7 @@ void DCajunMaster::Think (AActor *actor, ticcmd_t *cmd)
if (actor->health > 0) //Still alive
{
if (*teamplay || !*deathmatch)
if (teamplay || !deathmatch)
actor->player->mate = Choose_Mate (actor);
angle_t oldyaw = actor->angle;
@ -285,13 +285,13 @@ void DCajunMaster::WhatToGet (AActor *actor, AActor *item)
return;
else if ((typeis (AMegasphere) || typeis (ASoulsphere) || typeis (AHealthBonus)) && actor->health >= deh.MaxSoulsphere)
return;
else if (((typeis (ASuperShotgun) || typeis (AShotgun) || typeis (AShell) || typeis (AShellBox)) && b->ammo[am_shell] == b->maxammo[am_shell]) || (*deathmatch != 2 && ((typeis (AShotgun) && b->weaponowned[wp_shotgun]) || (typeis (ASuperShotgun) && b->weaponowned[wp_supershotgun]))))
else if (((typeis (ASuperShotgun) || typeis (AShotgun) || typeis (AShell) || typeis (AShellBox)) && b->ammo[am_shell] == b->maxammo[am_shell]) || (deathmatch != 2 && ((typeis (AShotgun) && b->weaponowned[wp_shotgun]) || (typeis (ASuperShotgun) && b->weaponowned[wp_supershotgun]))))
return;
else if (((typeis (AChaingun) || typeis (AClip) || typeis (AClipBox)) && b->ammo[am_clip] == b->maxammo[am_clip]) || (*deathmatch != 2 && (typeis (AChaingun) && b->weaponowned[wp_chaingun])))
else if (((typeis (AChaingun) || typeis (AClip) || typeis (AClipBox)) && b->ammo[am_clip] == b->maxammo[am_clip]) || (deathmatch != 2 && (typeis (AChaingun) && b->weaponowned[wp_chaingun])))
return;
else if (((typeis (APlasmaRifle) || typeis (ABigFreakingGun) || typeis (ACell) || typeis (ACellPack)) && b->ammo[am_cell] == b->maxammo[am_cell]) || (*deathmatch != 2 && ((typeis (ABigFreakingGun) && b->weaponowned[wp_bfg]) || (typeis (APlasmaRifle) && b->weaponowned[wp_plasma]))))
else if (((typeis (APlasmaRifle) || typeis (ABigFreakingGun) || typeis (ACell) || typeis (ACellPack)) && b->ammo[am_cell] == b->maxammo[am_cell]) || (deathmatch != 2 && ((typeis (ABigFreakingGun) && b->weaponowned[wp_bfg]) || (typeis (APlasmaRifle) && b->weaponowned[wp_plasma]))))
return;
else if (((typeis (ARocketLauncher) || typeis (ARocketAmmo) || typeis (ARocketBox)) && b->ammo[am_misl] == b->maxammo[am_misl]) || (*deathmatch != 2 && (typeis (ARocketLauncher) && b->weaponowned[wp_missile])))
else if (((typeis (ARocketLauncher) || typeis (ARocketAmmo) || typeis (ARocketBox)) && b->ammo[am_misl] == b->maxammo[am_misl]) || (deathmatch != 2 && (typeis (ARocketLauncher) && b->weaponowned[wp_missile])))
return;
else if (typeis (AChainsaw) && b->weaponowned[wp_chainsaw])
return;

View file

@ -75,7 +75,7 @@ static const FBinding DefBindings[] =
{ "f12", "spynext" },
{ "mwheeldown", "weapnext" },
{ "mwheelup", "weapprev" },
NULL
{ NULL }
};
static const FBinding DefRavenBindings[] =
@ -86,7 +86,7 @@ static const FBinding DefRavenBindings[] =
{ "pgdn", "+lookup" },
{ "del", "+lookdown" },
{ "end", "centerview" },
NULL
{ NULL }
};
static const FBinding DefHexenBindings[] =
@ -100,52 +100,53 @@ static const FBinding DefHexenBindings[] =
// 7 arti_teleportother
// 6 arti_egg
// 5 arti_invulnerability
NULL
{ NULL }
};
const char *KeyNames[NUM_KEYS] = {
const char *KeyNames[NUM_KEYS] =
{
// This array is dependant on the particular keyboard input
// codes generated in i_input.c. If they change there, they
// also need to change here. In this case, we use the
// DirectInput codes and assume a qwerty keyboard layout.
// See <dinput.h> for the DIK_* codes
NULL, "escape","1", "2", "3", "4", "5", "6", //00
"7", "8", "9", "0", "-", "=", "backspace","tab", //08
"q", "w", "e", "r", "t", "y", "u", "i", //10
"o", "p", "[", "]", "enter","ctrl", "a", "s", //18
"d", "f", "g", "h", "j", "k", "l", ";", //20
"'", "`", "shift","\\", "z", "x", "c", "v", //28
"b", "n", "m", ",", ".", "/", NULL, "kp*", //30
"alt", "space","capslock","f1","f2", "f3", "f4", "f5", //38
"f6", "f7", "f8", "f9", "f10", "numlock","scroll", "kp7", //40
"kp8", "kp9", "kp-", "kp4", "kp5", "kp6", "kp+", "kp1", //48
"kp2", "kp3", "kp0", "kp.", NULL, NULL, NULL, "f11", //50
"f12", NULL, NULL, NULL, NULL, NULL, NULL, NULL, //58
NULL, NULL, NULL, NULL, "f13", "f14", "f15", NULL, //60
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, //68
"kana", NULL, NULL, NULL, NULL, NULL, NULL, NULL, //70
NULL, "convert",NULL, "noconvert",NULL,"yen", NULL, NULL, //78
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, //80
NULL, NULL, NULL, NULL, NULL, "kp=", NULL, NULL, //88
"circumflex","@",":", "_", "kanji","stop", "ax", "unlabeled",//90
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, //98
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, //A0
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, //A8
NULL, NULL, NULL, "kp,", NULL, "kp/", NULL, "sysrq", //B0
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, //B8
NULL, NULL, NULL, NULL, NULL, NULL, NULL, "home", //C0
"uparrow","pgup",NULL, "leftarrow",NULL,"rightarrow",NULL, "end", //C8
"downarrow","pgdn","ins","del", NULL, NULL, NULL, NULL, //D0
NULL, NULL, NULL, "lwin", "rwin", "apps", NULL, NULL, //D8
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, //E0
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, //E8
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, //F0
NULL, NULL, NULL, NULL, NULL, NULL, NULL, "pause", //F8
NULL, "escape", "1", "2", "3", "4", "5", "6", //00
"7", "8", "9", "0", "-", "=", "backspace","tab", //08
"q", "w", "e", "r", "t", "y", "u", "i", //10
"o", "p", "[", "]", "enter", "ctrl", "a", "s", //18
"d", "f", "g", "h", "j", "k", "l", ";", //20
"'", "`", "shift", "\\", "z", "x", "c", "v", //28
"b", "n", "m", ",", ".", "/", NULL, "kp*", //30
"alt", "space", "capslock", "f1", "f2", "f3", "f4", "f5", //38
"f6", "f7", "f8", "f9", "f10", "numlock", "scroll", "kp7", //40
"kp8", "kp9", "kp-", "kp4", "kp5", "kp6", "kp+", "kp1", //48
"kp2", "kp3", "kp0", "kp.", NULL, NULL, "oem102", "f11", //50
"f12", NULL, NULL, NULL, NULL, NULL, NULL, NULL, //58
NULL, NULL, NULL, NULL, "f13", "f14", "f15", NULL, //60
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, //68
"kana", NULL, NULL, "abnt_c1", NULL, NULL, NULL, NULL, //70
NULL, "convert", NULL, "noconvert",NULL, "yen", "abnt_c2", NULL, //78
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, //80
NULL, NULL, NULL, NULL, NULL, "kp=", NULL, NULL, //88
"circumflex","@", ":", "_", "kanji", "stop", "ax", "unlabeled",//90
NULL, "prevtrack",NULL, NULL, NULL, NULL, NULL, NULL, //98
"mute", "calculator","play", NULL, "stop", NULL, NULL, NULL, //A0
NULL, NULL, NULL, NULL, NULL, NULL, "voldown", NULL, //A8
"volup", NULL, "webhome", "kp,", NULL, "kp/", NULL, "sysrq", //B0
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, //B8
NULL, NULL, NULL, NULL, NULL, "pause", NULL, "home", //C0
"uparrow", "pgup", NULL, "leftarrow",NULL, "rightarrow",NULL, "end", //C8
"downarrow","pgdn", "ins", "del", NULL, NULL, NULL, NULL, //D0
NULL, NULL, NULL, "lwin", "rwin", "apps", "power", "sleep", //D8
NULL, NULL, NULL, "wake", NULL, "search", "favorites","refresh", //E0
"webstop", "webforward","webback", "mycomputer","mail", "mediaselect",NULL, NULL, //E8
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, //F0
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, //F8
// non-keyboard buttons that can be bound
"mouse1", "mouse2", "mouse3", "mouse4", // 4 mouse buttons
"mwheelup", "mwheeldown",NULL, NULL, // the wheel and some extra space
"mouse1", "mouse2", "mouse3", "mouse4", // 6 mouse buttons
"mouse5", "mouse6", "mwheelup", "mwheeldown", // and the wheel
"joy1", "joy2", "joy3", "joy4", // 32 joystick buttons
"joy5", "joy6", "joy7", "joy8",
"joy9", "joy10", "joy11", "joy12",
@ -157,6 +158,7 @@ const char *KeyNames[NUM_KEYS] = {
};
static char *Bindings[NUM_KEYS];
static char *DoubleBindings[NUM_KEYS];
static int DClickTime[NUM_KEYS];
static byte DClicked[(NUM_KEYS+7)/8];
@ -166,12 +168,14 @@ static int GetKeyFromName (const char *name)
int i;
// Names of the form #xxx are translated to key xxx automatically
if (name[0] == '#' && name[1] != 0) {
if (name[0] == '#' && name[1] != 0)
{
return atoi (name + 1);
}
// Otherwise, we scan the KeyNames[] array for a matching name
for (i = 0; i < NUM_KEYS; i++) {
for (i = 0; i < NUM_KEYS; i++)
{
if (KeyNames[i] && !stricmp (KeyNames[i], name))
return i;
}
@ -189,30 +193,33 @@ static const char *KeyName (int key)
return name;
}
CCMD (unbindall)
void C_UnbindAll ()
{
int i;
for (i = 0; i < NUM_KEYS; i++)
for (int i = 0; i < NUM_KEYS; ++i)
{
if (Bindings[i])
{
free (Bindings[i]);
Bindings[i] = NULL;
}
for (i = 0; i < NUM_KEYS; i++)
if (DoubleBindings[i])
{
free (DoubleBindings[i]);
DoubleBindings[i] = NULL;
}
}
}
CCMD (unbindall)
{
C_UnbindAll ();
}
CCMD (unbind)
{
int i;
if (argc > 1)
if (argv.argc() > 1)
{
if ( (i = GetKeyFromName (argv[1])) )
{
@ -235,21 +242,29 @@ CCMD (bind)
{
int i;
if (argc > 1) {
if (argv.argc() > 1)
{
i = GetKeyFromName (argv[1]);
if (!i) {
if (!i)
{
Printf ("Unknown key \"%s\"\n", argv[1]);
return;
}
if (argc == 2) {
if (argv.argc() == 2)
{
Printf ("\"%s\" = \"%s\"\n", argv[1], (Bindings[i] ? Bindings[i] : ""));
} else {
ReplaceString (&Bindings[i], argv[2]);
}
} else {
else
{
ReplaceString (&Bindings[i], argv.AllButFirstArg (2));
}
}
else
{
Printf ("Current key bindings:\n");
for (i = 0; i < NUM_KEYS; i++) {
for (i = 0; i < NUM_KEYS; i++)
{
if (Bindings[i])
Printf ("%s \"%s\"\n", KeyName (i), Bindings[i]);
}
@ -260,7 +275,7 @@ CCMD (undoublebind)
{
int i;
if (argc > 1)
if (argv.argc() > 1)
{
if ( (i = GetKeyFromName (argv[1])) )
{
@ -283,7 +298,7 @@ CCMD (doublebind)
{
int i;
if (argc > 1)
if (argv.argc() > 1)
{
i = GetKeyFromName (argv[1]);
if (!i)
@ -291,13 +306,13 @@ CCMD (doublebind)
Printf ("Unknown key \"%s\"\n", argv[1]);
return;
}
if (argc == 2)
if (argv.argc() == 2)
{
Printf ("\"%s\" = \"%s\"\n", argv[1], (DoubleBindings[i] ? DoubleBindings[i] : ""));
}
else
{
ReplaceString (&DoubleBindings[i], argv[2]);
ReplaceString (&DoubleBindings[i], argv.AllButFirstArg (2));
}
}
else
@ -312,6 +327,32 @@ CCMD (doublebind)
}
}
CCMD (rebind)
{
char **bindings;
if (key == 0)
{
Printf ("Rebind cannot be used from the console\n");
return;
}
if (key & KEY_DBLCLICKED)
{
bindings = DoubleBindings;
key &= KEY_DBLCLICKED-1;
}
else
{
bindings = Bindings;
}
if (argv.argc() > 1)
{
ReplaceString (&bindings[key], argv.AllButFirstArg (1));
}
}
static void SetBinds (const FBinding *array)
{
while (array->Key)
@ -321,7 +362,7 @@ static void SetBinds (const FBinding *array)
}
}
CCMD(binddefaults)
void C_BindDefaults ()
{
SetBinds (DefBindings);
@ -336,9 +377,21 @@ CCMD(binddefaults)
}
}
CCMD(binddefaults)
{
C_BindDefaults ();
}
void C_SetDefaultBindings ()
{
C_UnbindAll ();
C_BindDefaults ();
}
BOOL C_DoKey (event_t *ev)
{
char *binding = NULL;
bool dclick;
int dclickspot;
byte dclickmask;
@ -347,61 +400,61 @@ BOOL C_DoKey (event_t *ev)
dclickspot = ev->data1 >> 3;
dclickmask = 1 << (ev->data1 & 7);
dclick = false;
if (DClickTime[ev->data1] > level.time && ev->type == EV_KeyDown)
{
// Key pressed for a double click
binding = DoubleBindings[ev->data1];
DClicked[dclickspot] |= dclickmask;
dclick = true;
}
else
{
if (ev->type == EV_KeyDown)
{
// Key pressed for a normal press
{ // Key pressed for a normal press
binding = Bindings[ev->data1];
DClickTime[ev->data1] = level.time + 20;
}
else if (DClicked[dclickspot] & dclickmask)
{
// Key released from a double click
{ // Key released from a double click
binding = DoubleBindings[ev->data1];
DClicked[dclickspot] &= ~dclickmask;
DClickTime[ev->data1] = 0;
dclick = true;
}
else
{
// Key released from a normal press
{ // Key released from a normal press
binding = Bindings[ev->data1];
}
}
if (!binding)
binding = Bindings[ev->data1];
if (binding && (chatmodeon == 0 || ev->data1 < 256))
if (binding == NULL)
{
if (ev->type == EV_KeyDown)
{
char copy[1024];
// Copy the command in case the binding rebinds the key
strcpy (copy, binding);
AddCommandString (copy);
}
else
{
char *achar;
achar = strchr (binding, '+');
if (!achar)
return false;
binding = Bindings[ev->data1];
dclick = false;
}
if ((achar == binding) || (*(achar - 1) <= ' '))
if (binding != NULL && (chatmodeon == 0 || ev->data1 < 256))
{
if (ev->type == EV_KeyUp)
{
if (binding[0] != '+')
{
*achar = '-';
AddCommandString (binding);
*achar = '+';
return false;
}
binding[0] = '-';
}
// Copy the command in case it rebinds the key
char copy[1024];
strncpy (copy, binding, 1023);
copy[1023] = 0;
AddCommandString (copy, dclick ? ev->data1 | KEY_DBLCLICKED : ev->data1);
if (ev->type == EV_KeyUp)
{
binding[0] = '+';
}
return true;
}
@ -429,6 +482,8 @@ void C_ArchiveBindings (FConfigFile *f, bool dodouble)
name = "RightBracket";
else if (name[0] == '=')
name = "Equals";
else if (strcmp (name, "kp=") == 0)
name = "KP-Equals";
}
f->SetValueForKey (name, bindings[i]);
}
@ -452,6 +507,10 @@ void C_DoBind (const char *key, const char *bind, bool dodouble)
{
keynum = GetKeyFromName ("=");
}
else if (stricmp (key, "KP-Equals") == 0)
{
keynum = GetKeyFromName ("kp=");
}
}
if (keynum != 0)
{
@ -465,8 +524,10 @@ int C_GetKeysForCommand (char *cmd, int *first, int *second)
*first = *second = c = i = 0;
while (i < NUM_KEYS && c < 2) {
if (Bindings[i] && !stricmp (cmd, Bindings[i])) {
while (i < NUM_KEYS && c < 2)
{
if (Bindings[i] && stricmp (cmd, Bindings[i]) == 0)
{
if (c++ == 0)
*first = i;
else
@ -482,14 +543,16 @@ void C_NameKeys (char *str, int first, int second)
int c = 0;
*str = 0;
if (first) {
if (first)
{
c++;
strcpy (str, KeyName (first));
if (second)
strcat (str, " or ");
}
if (second) {
if (second)
{
c++;
strcat (str, KeyName (second));
}
@ -502,8 +565,10 @@ void C_UnbindACommand (char *str)
{
int i;
for (i = 0; i < NUM_KEYS; i++) {
if (Bindings[i] && !stricmp (str, Bindings[i])) {
for (i = 0; i < NUM_KEYS; i++)
{
if (Bindings[i] && !stricmp (str, Bindings[i]))
{
delete[] Bindings[i];
Bindings[i] = NULL;
}

View file

@ -16,8 +16,10 @@ void C_NameKeys (char *str, int first, int second);
void C_UnbindACommand (char *str);
void C_ChangeBinding (const char *str, int newone);
void C_DoBind (const char *key, const char *bind, bool doublebind);
void C_SetDefaultBindings ();
void C_UnbindAll ();
// Returns string bound to given key (NULL if none)
char *C_GetBinding (int key);
#endif //__C_BINDINGS_H__
#endif //__C_BINDINGS_H__

View file

@ -40,7 +40,7 @@ CCMD (toggleconsole)
BOOL CheckCheatmode ()
{
if (((*gameskill == sk_nightmare) || netgame || *deathmatch) && (*sv_cheats == 0.0))
if (((gameskill == sk_nightmare) || netgame || deathmatch) && (sv_cheats == 0.0))
{
Printf ("You must run the server with '+set sv_cheats 1' to enable this command.\n");
return true;
@ -152,7 +152,7 @@ CCMD (chase)
{
int i;
if (*chasedemo)
if (chasedemo)
{
chasedemo = false;
for (i = 0; i < MAXPLAYERS; i++)
@ -167,7 +167,7 @@ CCMD (chase)
}
else
{
if (*deathmatch && CheckCheatmode ())
if (deathmatch && CheckCheatmode ())
return;
Net_WriteByte (DEM_GENERICCHEAT);
@ -180,7 +180,7 @@ CCMD (idclev)
if (CheckCheatmode ())
return;
if ((argc > 1) && (*(argv[1] + 2) == 0) && *(argv[1] + 1) && *argv[1])
if ((argv.argc() > 1) && (*(argv[1] + 2) == 0) && *(argv[1] + 1) && *argv[1])
{
int epsd, map;
char buf[2];
@ -225,7 +225,7 @@ CCMD (changemap)
return;
}
if (argc > 1)
if (argv.argc() > 1)
{
if (W_CheckNumForName (argv[1]) == -1)
{
@ -241,20 +241,11 @@ CCMD (changemap)
CCMD (give)
{
char *name;
if (CheckCheatmode ())
if (CheckCheatmode () || argv.argc() < 2)
return;
if (argc < 2)
return;
if ( (name = BuildString (argc - 1, argv + 1)) )
{
Net_WriteByte (DEM_GIVECHEAT);
Net_WriteString (name);
delete[] name;
}
Net_WriteByte (DEM_GIVECHEAT);
Net_WriteString (argv.AllButFirstArg ());
}
CCMD (gameversion)
@ -262,12 +253,32 @@ CCMD (gameversion)
Printf ("%d.%d : " __DATE__ "\n", VERSION / 100, VERSION % 100);
}
CCMD (print)
{
if (argv.argc() != 2)
{
Printf ("print <name>: Print a string from the string table\n");
return;
}
GStrings.LoadNames ();
int strnum = GStrings.FindString (argv[1]);
if (strnum < 0)
{
Printf ("%s unknown\n", argv[1]);
}
else
{
Printf ("%s\n", GStrings(strnum));
}
GStrings.FlushNames ();
}
CCMD (exec)
{
FILE *f;
char cmd[4096];
if (argc < 2)
if (argv.argc() < 2)
return;
if ( (f = fopen (argv[1], "r")) )
@ -300,9 +311,11 @@ CCMD (dumpheap)
{
int lo = PU_STATIC, hi = PU_CACHE;
if (argc >= 2) {
if (argv.argc() >= 2)
{
lo = atoi (argv[1]);
if (argc >= 3) {
if (argv.argc() >= 3)
{
hi = atoi (argv[2]);
}
}
@ -325,7 +338,7 @@ CCMD (logfile)
Logfile = NULL;
}
if (argc >= 2)
if (argv.argc() >= 2)
{
if ( (Logfile = fopen (argv[1], "w")) )
{
@ -343,17 +356,25 @@ bool P_StartScript (AActor *who, line_t *where, int script, char *map, int lineS
CCMD (puke)
{
if (argc < 2 || argc > 5) {
int argc = argv.argc();
if (argc < 2 || argc > 5)
{
Printf (" puke <script> [arg1] [arg2] [arg3]\n");
} else {
}
else
{
int script = atoi (argv[1]);
int arg0=0, arg1=0, arg2=0;
if (argc > 2) {
if (argc > 2)
{
arg0 = atoi (argv[2]);
if (argc > 3) {
if (argc > 3)
{
arg1 = atoi (argv[3]);
if (argc > 4) {
if (argc > 4)
{
arg2 = atoi (argv[4]);
}
}
@ -364,9 +385,7 @@ CCMD (puke)
CCMD (error)
{
char *text = BuildString (argc - 1, argv + 1);
char *textcopy = copystring (text);
delete[] text;
char *textcopy = copystring (argv.AllButFirstArg ());
I_Error (textcopy);
}
@ -383,9 +402,9 @@ CCMD (dir)
return;
}
if (argc == 1 || chdir (argv[1]))
if (argv.argc() == 1 || chdir (argv[1]))
{
match = argc == 1 ? (char *)"./*" : argv[1];
match = argv.argc() == 1 ? (char *)"./*" : argv[1];
ExtractFilePath (match, dir);
if (dir[0])
@ -438,7 +457,7 @@ CCMD (fov)
player_t *player = m_Instigator ? m_Instigator->player
: &players[consoleplayer];
if (argc != 2)
if (argv.argc() != 2)
Printf ("fov is %g\n", player->DesiredFOV);
else
player->DesiredFOV = atof (argv[1]);

View file

@ -38,7 +38,7 @@
#define RIGHTMARGIN 8
#define BOTTOMARGIN 12
static void C_TabComplete ();
static void C_TabComplete (bool goForward);
static BOOL TabbedLast; // Last key pressed was tab
@ -118,32 +118,32 @@ FIntCVar msglevel ("msg", 0, CVAR_ARCHIVE);
CUSTOM_CVAR (Int, msg0color, 6, CVAR_ARCHIVE)
{
setmsgcolor (0, *var);
setmsgcolor (0, self);
}
CUSTOM_CVAR (Int, msg1color, 5, CVAR_ARCHIVE)
{
setmsgcolor (1, *var);
setmsgcolor (1, self);
}
CUSTOM_CVAR (Int, msg2color, 2, CVAR_ARCHIVE)
{
setmsgcolor (2, *var);
setmsgcolor (2, self);
}
CUSTOM_CVAR (Int, msg3color, 3, CVAR_ARCHIVE)
{
setmsgcolor (3, *var);
setmsgcolor (3, self);
}
CUSTOM_CVAR (Int, msg4color, 3, CVAR_ARCHIVE)
{
setmsgcolor (4, *var);
setmsgcolor (4, self);
}
CUSTOM_CVAR (Int, msgmidcolor, 5, CVAR_ARCHIVE)
{
setmsgcolor (PRINTLEVELS, *var);
setmsgcolor (PRINTLEVELS, self);
}
static void maybedrawnow ()
@ -200,7 +200,7 @@ void C_InitConsole (int width, int height, BOOL ingame)
if (stylize)
{
byte *fadetable = (byte *)W_CacheLumpName ("COLORMAP", PU_CACHE), f, *v, *i;
byte *fadetable = (byte *)W_CacheLumpName ("COLORMAP", PU_CACHE), f, *i;
int x, y;
for (y = 0; y < conback->GetHeight(); y++)
@ -212,7 +212,7 @@ void C_InitConsole (int width, int height, BOOL ingame)
f = y;
else
f = 199 - y;
v = fadetable + (30 - f) * 256;
byte *v = fadetable + (30 - f) * 256;
for (x = 0; x < conback->GetWidth(); x++)
{
*i = v[*i];
@ -224,11 +224,12 @@ void C_InitConsole (int width, int height, BOOL ingame)
for (x = 0; x < conback->GetWidth(); x++)
{
if (x <= 8)
v = fadetable + (30 - x) * 256;
*i = *(fadetable + (30 - x) * 256 + *i);
else if (x > 312)
v = fadetable + (x - 289) * 256;
*i = v[*i];
i++;
*i = *(fadetable + (x - 289) * 256 + *i);
else
*i = *(fadetable + 22*256 + *i);
++i;
}
}
}
@ -253,7 +254,7 @@ void C_InitConsole (int width, int height, BOOL ingame)
char *fmtBuff = (char *)malloc (CONSOLESIZE);
char **fmtLines = (char **)malloc (CONSOLELINES*sizeof(char*)*4);
int out;
int out = 0;
if (fmtBuff && fmtLines)
{
@ -264,7 +265,7 @@ void C_InitConsole (int width, int height, BOOL ingame)
fmtpos = fmtBuff;
memset (fmtBuff, 0, CONSOLESIZE);
for (in = TopLine, out = 0; in != InsertLine; in = (in + 1) & LINEMASK)
for (in = TopLine; in != InsertLine; in = (in + 1) & LINEMASK)
{
int len = strlen (Lines[in]);
@ -348,12 +349,12 @@ void C_AddNotifyString (int printlevel, const char *source)
brokenlines_t *lines;
int i, len, width;
if ((printlevel != 128 && !*show_messages) ||
if ((printlevel != 128 && !show_messages) ||
!(len = strlen (source)) ||
gamestate != GS_LEVEL)
return;
width = *con_scaletext ? DisplayWidth / CleanXfac : DisplayWidth;
width = con_scaletext ? DisplayWidth / CleanXfac : DisplayWidth;
if (addtype == APPENDLINE && NotifyStrings[NUMNOTIFIES-1].printlevel == printlevel
&& (work = (char *)malloc (strlen ((char *)NotifyStrings[NUMNOTIFIES-1].text)
@ -377,7 +378,7 @@ void C_AddNotifyString (int printlevel, const char *source)
if (addtype == NEWLINE)
memmove (&NotifyStrings[0], &NotifyStrings[1], sizeof(struct NotifyText) * (NUMNOTIFIES-1));
strcpy ((char *)NotifyStrings[NUMNOTIFIES-1].text, lines[i].string);
NotifyStrings[NUMNOTIFIES-1].timeout = gametic + (int)(*con_notifytime * TICRATE);
NotifyStrings[NUMNOTIFIES-1].timeout = gametic + (int)(con_notifytime * TICRATE);
NotifyStrings[NUMNOTIFIES-1].printlevel = printlevel;
addtype = NEWLINE;
}
@ -486,6 +487,7 @@ static void AddToConsole (int printlevel, const char *text)
{
strcpy (work, Lines[InsertLine]);
strcat (work, text);
cc = CR_TAN;
}
else if (printlevel >= 0)
{
@ -583,7 +585,7 @@ static void AddToConsole (int printlevel, const char *text)
/* Adds a string to the console and also to the notify buffer */
int PrintString (int printlevel, const char *outline)
{
if (printlevel < *msglevel || *outline == '\0')
if (printlevel < msglevel || *outline == '\0')
{
return 0;
}
@ -659,7 +661,7 @@ int STACK_ARGS DPrintf (const char *format, ...)
va_list argptr;
int count;
if (*developer)
if (developer)
{
va_start (argptr, format);
count = VPrintf (PRINT_HIGH, format, argptr);
@ -735,7 +737,7 @@ void C_Ticker ()
static void C_DrawNotifyText ()
{
bool center = (*con_centernotify != 0.f);
bool center = (con_centernotify != 0.f);
int i, line, color;
if (gamestate != GS_LEVEL || menuactive)
@ -749,7 +751,7 @@ static void C_DrawNotifyText ()
{
if (NotifyStrings[i].timeout > gametic)
{
if (!*show_messages && NotifyStrings[i].printlevel != 128)
if (!show_messages && NotifyStrings[i].printlevel != 128)
continue;
if (NotifyStrings[i].printlevel >= PRINTLEVELS)
@ -757,7 +759,7 @@ static void C_DrawNotifyText ()
else
color = PrintColors[NotifyStrings[i].printlevel];
if (*con_scaletext)
if (con_scaletext)
{
if (!center)
screen->DrawTextClean (color, 0, line, NotifyStrings[i].text);
@ -917,14 +919,14 @@ void C_DrawConsole ()
else
{
CmdLine[2+CmdLine[0]] = 0;
screen->DrawText (CR_ORANGE, left, bottomline, "\x1c");
screen->DrawChar (CR_ORANGE, left, bottomline, '\x1c');
screen->DrawText (CR_ORANGE, left + 8, bottomline,
(char *)&CmdLine[2+CmdLine[259]]);
}
if (cursoron)
{
screen->DrawText (CR_YELLOW, left + 8 + (CmdLine[1] - CmdLine[259])* 8,
bottomline, "\xb");
screen->DrawChar (CR_YELLOW, left + 8 + (CmdLine[1] - CmdLine[259])* 8,
bottomline, '\xb');
}
if (RowAdjust && ConBottom >= 28)
{
@ -957,7 +959,6 @@ void C_FullConsole ()
S_Start ();
SN_StopAllSequences ();
V_SetBlend (0,0,0,0);
I_PauseMouse ();
}
else
{
@ -976,13 +977,11 @@ void C_ToggleConsole ()
ConsoleState = c_falling;
HistPos = NULL;
TabbedLast = false;
I_PauseMouse ();
}
else if (gamestate != GS_FULLCONSOLE && gamestate != GS_STARTUP)
{
ConsoleState = c_rising;
C_FlushDisplay ();
I_ResumeMouse ();
}
}
@ -995,10 +994,6 @@ void C_HideConsole ()
ConsoleState = c_up;
ConBottom = 0;
HistPos = NULL;
if (!menuactive)
{
I_ResumeMouse ();
}
}
}
@ -1030,316 +1025,314 @@ static void makestartposgood ()
static BOOL C_HandleKey (event_t *ev, byte *buffer, int len)
{
switch (ev->data1)
{
case '\t':
// Try to do tab-completion
C_TabComplete ();
break;
case GK_PGUP:
if (ev->data3 & (GKM_SHIFT|GKM_CTRL))
{ // Scroll console buffer up one page
RowAdjust += (SCREENHEIGHT-4) /
((gamestate == GS_FULLCONSOLE || gamestate == GS_STARTUP) ? 8 : 16) - 3;
}
else if (RowAdjust < CONSOLELINES)
{ // Scroll console buffer up
RowAdjust++;
}
break;
case GK_PGDN:
if (ev->data3 & (GKM_SHIFT|GKM_CTRL))
{ // Scroll console buffer down one page
const int scrollamt = (SCREENHEIGHT-4) /
((gamestate == GS_FULLCONSOLE || gamestate == GS_STARTUP) ? 8 : 16) - 3;
if (RowAdjust < scrollamt)
if (ev->subtype == EV_GUI_Char)
{ // Add keypress to command line
if (buffer[0] < len)
{
if (buffer[1] == buffer[0])
{
RowAdjust = 0;
buffer[buffer[0] + 2] = ev->data1;
}
else
{
RowAdjust -= scrollamt;
char *c, *e;
e = (char *)&buffer[buffer[0] + 1];
c = (char *)&buffer[buffer[1] + 2];
for (; e >= c; e--)
*(e + 1) = *e;
*c = ev->data1;
}
}
else if (RowAdjust > 0)
{ // Scroll console buffer down
RowAdjust--;
}
break;
case GK_HOME:
if (ev->data3 & GKM_CTRL)
{ // Move to top of console buffer
RowAdjust = CONSOLELINES;
}
else
{ // Move cursor to start of line
buffer[1] = buffer[len+4] = 0;
}
break;
case GK_END:
if (ev->data3 & GKM_CTRL)
{ // Move to bottom of console buffer
RowAdjust = 0;
}
else
{ // Move cursor to end of line
buffer[1] = buffer[0];
makestartposgood ();
}
break;
case GK_LEFT:
// Move cursor left one character
if (buffer[1])
{
buffer[1]--;
makestartposgood ();
}
break;
case GK_RIGHT:
// Move cursor right one character
if (buffer[1] < buffer[0])
{
buffer[0]++;
buffer[1]++;
makestartposgood ();
}
break;
case '\b':
// Erase character to left of cursor
if (buffer[0] && buffer[1])
{
char *c, *e;
e = (char *)&buffer[buffer[0] + 2];
c = (char *)&buffer[buffer[1] + 2];
for (; c < e; c++)
*(c - 1) = *c;
buffer[0]--;
buffer[1]--;
if (buffer[len+4])
buffer[len+4]--;
makestartposgood ();
}
TabbedLast = false;
break;
case GK_DEL:
// Erase charater under cursor
if (buffer[1] < buffer[0])
{
char *c, *e;
e = (char *)&buffer[buffer[0] + 2];
c = (char *)&buffer[buffer[1] + 3];
for (; c < e; c++)
*(c - 1) = *c;
buffer[0]--;
makestartposgood ();
}
TabbedLast = false;
break;
case GK_UP:
// Move to previous entry in the command history
if (HistPos == NULL)
{
HistPos = HistHead;
}
else if (HistPos->Older)
{
HistPos = HistPos->Older;
}
if (HistPos)
{
strcpy ((char *)&buffer[2], HistPos->String);
buffer[0] = buffer[1] = strlen ((char *)&buffer[2]);
buffer[len+4] = 0;
makestartposgood();
}
TabbedLast = false;
break;
case GK_DOWN:
// Move to next entry in the command history
if (HistPos && HistPos->Newer)
{
HistPos = HistPos->Newer;
strcpy ((char *)&buffer[2], HistPos->String);
buffer[0] = buffer[1] = strlen ((char *)&buffer[2]);
}
else
{
HistPos = NULL;
buffer[0] = buffer[1] = 0;
}
buffer[len+4] = 0;
makestartposgood();
TabbedLast = false;
break;
case '\r':
// Execute command line (ENTER)
buffer[2 + buffer[0]] = 0;
if (HistHead && stricmp (HistHead->String, (char *)&buffer[2]) == 0)
}
else
{
switch (ev->data1)
{
// Command line was the same as the previous one,
// so leave the history list alone
}
else
{
// Command line is different from last command line,
// or there is nothing in the history list,
// so add it to the history list.
case '\t':
// Try to do tab-completion
C_TabComplete ((ev->data3 & GKM_SHIFT) ? false : true);
break;
History *temp = (History *)Malloc (sizeof(struct History) + buffer[0]);
strcpy (temp->String, (char *)&buffer[2]);
temp->Older = HistHead;
if (HistHead)
{
HistHead->Newer = temp;
case GK_PGUP:
if (ev->data3 & (GKM_SHIFT|GKM_CTRL))
{ // Scroll console buffer up one page
RowAdjust += (SCREENHEIGHT-4) /
((gamestate == GS_FULLCONSOLE || gamestate == GS_STARTUP) ? 8 : 16) - 3;
}
temp->Newer = NULL;
HistHead = temp;
if (!HistTail)
{
HistTail = temp;
else if (RowAdjust < CONSOLELINES)
{ // Scroll console buffer up
RowAdjust++;
}
break;
if (HistSize == MAXHISTSIZE)
{
HistTail = HistTail->Newer;
free (HistTail->Older);
HistTail->Older = NULL;
}
else
{
HistSize++;
}
}
HistPos = NULL;
Printf (127, "]%s\n", &buffer[2]);
buffer[0] = buffer[1] = buffer[len+4] = 0;
AddCommandString ((char *)&buffer[2]);
TabbedLast = false;
break;
case '`':
case GK_ESCAPE:
// Close console and clear command line. But if we're in the
// fullscreen console mode, there's nothing to fall back on
// if it's closed, so open the main menu instead.
if (gamestate == GS_STARTUP)
{
return false;
}
else if (gamestate == GS_FULLCONSOLE)
{
AddCommandString ("menu_main");
}
else
{
buffer[0] = buffer[1] = buffer[len+4] = 0;
HistPos = NULL;
C_ToggleConsole ();
}
break;
case 'C':
case 'V':
TabbedLast = false;
if (ev->data3 & GKM_CTRL)
{
if (ev->data1 == 'C')
{ // copy to clipboard
if (buffer[0] > 0)
case GK_PGDN:
if (ev->data3 & (GKM_SHIFT|GKM_CTRL))
{ // Scroll console buffer down one page
const int scrollamt = (SCREENHEIGHT-4) /
((gamestate == GS_FULLCONSOLE || gamestate == GS_STARTUP) ? 8 : 16) - 3;
if (RowAdjust < scrollamt)
{
buffer[2 + buffer[0]] = 0;
I_PutInClipboard ((char *)&buffer[2]);
}
break;
}
else
{ // paste from clipboard
char *clip = I_GetFromClipboard ();
if (clip != NULL)
{
strtok (clip, "\r\n\b");
int cliplen = strlen (clip);
cliplen = MIN(len, cliplen);
if (buffer[0] + cliplen > len)
{
cliplen = len - buffer[0];
}
if (cliplen > 0)
{
if (buffer[1] < buffer[0])
{
memmove (&buffer[2 + buffer[1] + cliplen],
&buffer[2 + buffer[1]], buffer[0] - buffer[1]);
}
memcpy (&buffer[2 + buffer[1]], clip, cliplen);
buffer[0] += cliplen;
buffer[1] += cliplen;
makestartposgood ();
HistPos = NULL;
}
delete[] clip;
}
break;
}
}
// intentional fall-through
default:
if (ev->data2 >= ' ')
{ // Add keypress to command line
if (buffer[0] < len)
{
char data = ev->data2;
if (buffer[1] == buffer[0])
{
buffer[buffer[0] + 2] = data;
RowAdjust = 0;
}
else
{
char *c, *e;
e = (char *)&buffer[buffer[0] + 1];
c = (char *)&buffer[buffer[1] + 2];
for (; e >= c; e--)
*(e + 1) = *e;
*c = data;
RowAdjust -= scrollamt;
}
buffer[0]++;
}
else if (RowAdjust > 0)
{ // Scroll console buffer down
RowAdjust--;
}
break;
case GK_HOME:
if (ev->data3 & GKM_CTRL)
{ // Move to top of console buffer
RowAdjust = CONSOLELINES;
}
else
{ // Move cursor to start of line
buffer[1] = buffer[len+4] = 0;
}
break;
case GK_END:
if (ev->data3 & GKM_CTRL)
{ // Move to bottom of console buffer
RowAdjust = 0;
}
else
{ // Move cursor to end of line
buffer[1] = buffer[0];
makestartposgood ();
}
break;
case GK_LEFT:
// Move cursor left one character
if (buffer[1])
{
buffer[1]--;
makestartposgood ();
}
break;
case GK_RIGHT:
// Move cursor right one character
if (buffer[1] < buffer[0])
{
buffer[1]++;
makestartposgood ();
HistPos = NULL;
}
break;
case '\b':
// Erase character to left of cursor
if (buffer[0] && buffer[1])
{
char *c, *e;
e = (char *)&buffer[buffer[0] + 2];
c = (char *)&buffer[buffer[1] + 2];
for (; c < e; c++)
*(c - 1) = *c;
buffer[0]--;
buffer[1]--;
if (buffer[len+4])
buffer[len+4]--;
makestartposgood ();
}
TabbedLast = false;
break;
case GK_DEL:
// Erase charater under cursor
if (buffer[1] < buffer[0])
{
char *c, *e;
e = (char *)&buffer[buffer[0] + 2];
c = (char *)&buffer[buffer[1] + 3];
for (; c < e; c++)
*(c - 1) = *c;
buffer[0]--;
makestartposgood ();
}
TabbedLast = false;
break;
case GK_UP:
// Move to previous entry in the command history
if (HistPos == NULL)
{
HistPos = HistHead;
}
else if (HistPos->Older)
{
HistPos = HistPos->Older;
}
if (HistPos)
{
strcpy ((char *)&buffer[2], HistPos->String);
buffer[0] = buffer[1] = strlen ((char *)&buffer[2]);
buffer[len+4] = 0;
makestartposgood();
}
TabbedLast = false;
break;
case GK_DOWN:
// Move to next entry in the command history
if (HistPos && HistPos->Newer)
{
HistPos = HistPos->Newer;
strcpy ((char *)&buffer[2], HistPos->String);
buffer[0] = buffer[1] = strlen ((char *)&buffer[2]);
}
else
{
HistPos = NULL;
buffer[0] = buffer[1] = 0;
}
buffer[len+4] = 0;
makestartposgood();
TabbedLast = false;
break;
case '\r':
// Execute command line (ENTER)
buffer[2 + buffer[0]] = 0;
if (HistHead && stricmp (HistHead->String, (char *)&buffer[2]) == 0)
{
// Command line was the same as the previous one,
// so leave the history list alone
}
else
{
// Command line is different from last command line,
// or there is nothing in the history list,
// so add it to the history list.
History *temp = (History *)Malloc (sizeof(struct History) + buffer[0]);
strcpy (temp->String, (char *)&buffer[2]);
temp->Older = HistHead;
if (HistHead)
{
HistHead->Newer = temp;
}
temp->Newer = NULL;
HistHead = temp;
if (!HistTail)
{
HistTail = temp;
}
if (HistSize == MAXHISTSIZE)
{
HistTail = HistTail->Newer;
free (HistTail->Older);
HistTail->Older = NULL;
}
else
{
HistSize++;
}
}
HistPos = NULL;
Printf (127, "]%s\n", &buffer[2]);
buffer[0] = buffer[1] = buffer[len+4] = 0;
AddCommandString ((char *)&buffer[2]);
TabbedLast = false;
break;
case '`':
case GK_ESCAPE:
// Close console and clear command line. But if we're in the
// fullscreen console mode, there's nothing to fall back on
// if it's closed, so open the main menu instead.
if (gamestate == GS_STARTUP)
{
return false;
}
else if (gamestate == GS_FULLCONSOLE)
{
C_DoCommand ("menu_main");
}
else
{
buffer[0] = buffer[1] = buffer[len+4] = 0;
HistPos = NULL;
C_ToggleConsole ();
}
break;
case 'C':
case 'V':
TabbedLast = false;
if (ev->data3 & GKM_CTRL)
{
if (ev->data1 == 'C')
{ // copy to clipboard
if (buffer[0] > 0)
{
buffer[2 + buffer[0]] = 0;
I_PutInClipboard ((char *)&buffer[2]);
}
break;
}
else
{ // paste from clipboard
char *clip = I_GetFromClipboard ();
if (clip != NULL)
{
strtok (clip, "\r\n\b");
int cliplen = strlen (clip);
cliplen = MIN(len, cliplen);
if (buffer[0] + cliplen > len)
{
cliplen = len - buffer[0];
}
if (cliplen > 0)
{
if (buffer[1] < buffer[0])
{
memmove (&buffer[2 + buffer[1] + cliplen],
&buffer[2 + buffer[1]], buffer[0] - buffer[1]);
}
memcpy (&buffer[2 + buffer[1]], clip, cliplen);
buffer[0] += cliplen;
buffer[1] += cliplen;
makestartposgood ();
HistPos = NULL;
}
delete[] clip;
}
break;
}
}
break;
}
break;
}
CursorTicker = C_BLINKRATE;
cursoron = 1;
@ -1356,7 +1349,9 @@ BOOL C_Responder (event_t *ev)
return false;
}
if (ev->subtype == EV_GUI_KeyDown || ev->subtype == EV_GUI_KeyRepeat)
if (ev->subtype == EV_GUI_KeyDown ||
ev->subtype == EV_GUI_KeyRepeat ||
ev->subtype == EV_GUI_Char)
{
return C_HandleKey (ev, CmdLine, 255);
}
@ -1383,12 +1378,7 @@ CCMD (clear)
CCMD (echo)
{
if (argc > 1)
{
char *str = BuildString (argc - 1, argv + 1);
Printf ("%s\n", str);
delete[] str;
}
Printf ("%s\n", argv.AllButFirstArg());
}
/* Printing in the middle of the screen */
@ -1411,7 +1401,7 @@ void C_MidPrint (const char *msg)
AddToConsole (-1, buff);
StatusBar->AttachMessage (new FHUDMessage (msg, 1.5f, 0.375f,
(EColorRange)PrintColors[PRINTLEVELS], *con_midtime), 'CNTR');
(EColorRange)PrintColors[PRINTLEVELS], con_midtime), 'CNTR');
}
else
{
@ -1495,7 +1485,7 @@ static int FindDiffPoint (const char *str1, const char *str2)
return i;
}
static void C_TabComplete ()
static void C_TabComplete (bool goForward)
{
int i;
int diffpoint;
@ -1524,11 +1514,26 @@ static void C_TabComplete ()
if (!FindTabCommand ((char *)(CmdLine + TabStart), &TabPos, TabSize))
return; // No initial matches
TabPos--;
if (goForward)
{ // Position just before the list of completions so that when TabPos
// gets advanced below, it will be at the first one.
--TabPos;
}
else
{ // Find the last matching tab, then go one past it.
while (++TabPos < NumTabCommands)
{
if (FindDiffPoint (TabCommands[TabPos].Name, (char *)(CmdLine + TabStart)) < TabSize)
{
break;
}
}
}
TabbedLast = true;
}
if (++TabPos == NumTabCommands)
if ((goForward && ++TabPos == NumTabCommands) ||
(!goForward && --TabPos < 0))
{
TabbedLast = false;
CmdLine[0] = CmdLine[1] = TabSize;

View file

@ -24,8 +24,8 @@ void C_NewModeAdjust (void);
void C_Ticker (void);
int PrintString (int printlevel, const char *string);
int VPrintf (int printlevel, const char *format, va_list parms);
int STACK_ARGS Printf_Bold (const char *format, ...);
int VPrintf (int printlevel, const char *format, va_list parms) GCCFORMAT(2);
int STACK_ARGS Printf_Bold (const char *format, ...) GCCPRINTF(1,2);
void C_DrawConsole (void);
void C_ToggleConsole (void);

View file

@ -401,7 +401,9 @@ void FBaseCVar::EnableCallbacks ()
while (cvar)
{
if (!(cvar->Flags & CVAR_NOINITCALL))
{
cvar->Callback ();
}
cvar = cvar->m_Next;
}
}
@ -676,8 +678,6 @@ void FColorCVar::SetGenericRepDefault (UCVarValue value, ECVarType type)
void FColorCVar::DoSet (UCVarValue value, ECVarType type)
{
if (strcmp (Name, "dimcolor") == 0)
value = value;
Value = ToInt2 (value, type);
if (screen)
Index = ColorMatcher.Pick (RPART(Value), GPART(Value), BPART(Value));
@ -777,14 +777,14 @@ ECVarType FFlagCVar::GetRealType () const
UCVarValue FFlagCVar::GetGenericRep (ECVarType type) const
{
return FromBool ((*ValueVar & BitVal) != 0, type);
return FromBool ((ValueVar & BitVal) != 0, type);
}
UCVarValue FFlagCVar::GetFavoriteRep (ECVarType *type) const
{
UCVarValue ret;
*type = CVAR_Bool;
ret.Bool = (*ValueVar & BitVal) != 0;
ret.Bool = (ValueVar & BitVal) != 0;
return ret;
}
@ -1022,6 +1022,28 @@ FBaseCVar *FindCVar (const char *var_name, FBaseCVar **prev)
return var;
}
FBaseCVar *FindCVarSub (const char *var_name, int namelen)
{
FBaseCVar *var;
if (var_name == NULL)
return NULL;
var = CVars;
while (var)
{
const char *probename = var->GetName ();
if (strnicmp (probename, var_name, namelen) == 0 &&
probename[namelen] == 0)
{
break;
}
var = var->m_Next;
}
return var;
}
void UnlatchCVars (void)
{
FLatchedValue var;
@ -1088,34 +1110,41 @@ void C_ArchiveCVars (FConfigFile *f, int type)
}
}
void FBaseCVar::CmdSet (const char *newval)
{
UCVarValue val;
// Casting away the const is safe in this case.
val.String = const_cast<char *>(newval);
SetGenericRep (val, CVAR_String);
if (GetFlags() & CVAR_NOSET)
Printf ("%s is write protected.\n", GetName());
else if (GetFlags() & CVAR_LATCH)
Printf ("%s will be changed for next game.\n", GetName());
}
CCMD (set)
{
if (argc != 3)
if (argv.argc() != 3)
{
Printf ("usage: set <variable> <value>\n");
}
else
{
FBaseCVar *var, *prev;
UCVarValue val;
FBaseCVar *var;
var = FindCVar (argv[1], &prev);
if (!var)
var = FindCVar (argv[1], NULL);
if (var == NULL)
var = new FStringCVar (argv[1], NULL, CVAR_AUTO | CVAR_UNSETTABLE | cvar_defflags);
val.String = argv[2];
var->SetGenericRep (val, CVAR_String);
if (var->GetFlags() & CVAR_NOSET)
Printf ("%s is write protected.\n", argv[1]);
else if (var->GetFlags() & CVAR_LATCH)
Printf ("%s will be changed for next game.\n", argv[1]);
var->CmdSet (argv[2]);
}
}
CCMD (unset)
{
if (argc != 2)
if (argv.argc() != 2)
{
Printf ("usage: unset <variable>\n");
}
@ -1140,7 +1169,7 @@ CCMD (get)
{
FBaseCVar *var, *prev;
if (argc >= 2)
if (argv.argc() >= 2)
{
if ( (var = FindCVar (argv[1], &prev)) )
{
@ -1164,7 +1193,7 @@ CCMD (toggle)
FBaseCVar *var, *prev;
UCVarValue val;
if (argc > 1)
if (argv.argc() > 1)
{
if ( (var = FindCVar (argv[1], &prev)) )
{
@ -1177,7 +1206,7 @@ CCMD (toggle)
}
}
CCMD (cvarlist)
void FBaseCVar::ListVars (const char *filter)
{
FBaseCVar *var = CVars;
int count = 0;
@ -1197,8 +1226,20 @@ CCMD (cvarlist)
flags & CVAR_LATCH ? 'L' :
flags & CVAR_UNSETTABLE ? '*' : ' ',
var->GetName(),
val.String);
var->GetGenericRep (CVAR_String).String);
var = var->m_Next;
}
Printf ("%d cvars\n", count);
}
CCMD (cvarlist)
{
if (argv.argc() == 1)
{
FBaseCVar::ListVars (NULL);
}
else
{
FBaseCVar::ListVars (argv[1]);
}
}

View file

@ -21,11 +21,12 @@ enum
// but can be set from the command line
CVAR_LATCH = 16, // save changes until server restart
CVAR_UNSETTABLE = 32, // can unset this var from console
CVAR_DEMOSAVE = 64, // save the value of this FBaseCVar in a demo
CVAR_DEMOSAVE = 64, // save the value of this cvar in a demo
CVAR_ISDEFAULT = 128, // is cvar unchanged since creation?
CVAR_AUTO = 256, // allocated; needs to be freed when destroyed
CVAR_NOINITCALL = 512, // don't call callback at game start
CVAR_GLOBALCONFIG = 1024, // cvar is saved to global config section
CVAR_VIDEOCONFIG = 2048, // cvar is saved to video config section
};
union UCVarValue
@ -60,6 +61,7 @@ public:
inline const char *GetName () const { return Name; }
inline DWORD GetFlags () const { return Flags; }
void CmdSet (const char *newval);
void ForceSet (UCVarValue value, ECVarType type);
void SetGenericRep (UCVarValue value, ECVarType type);
void ResetToDefault ();
@ -80,7 +82,10 @@ public:
static void EnableCallbacks ();
static void ResetColors (); // recalc color cvars' indices after screen change
static void ListVars (const char *filter);
protected:
FBaseCVar () {}
virtual void DoSet (UCVarValue value, ECVarType type) = 0;
static bool ToBool (UCVarValue value, ECVarType type);
@ -96,8 +101,8 @@ protected:
DWORD Flags;
private:
FBaseCVar (const char *name, DWORD flags);
FBaseCVar (const FBaseCVar &var);
FBaseCVar (const char *name, DWORD flags);
void (*m_Callback)(FBaseCVar &);
FBaseCVar *m_Next;
@ -105,8 +110,6 @@ private:
static bool m_UseCallback;
static bool m_DoNoSet;
friend void Cmd_cvarlist (int, char **, const char *, AActor *);
// Writes all cvars that could effect demo sync to *demo_p. These are
// cvars that have either CVAR_SERVERINFO or CVAR_DEMOSAVE set.
friend void C_WriteCVars (byte **demo_p, DWORD filter, bool compact=false);
@ -120,6 +123,7 @@ private:
// Finds a named cvar
friend FBaseCVar *FindCVar (const char *var_name, FBaseCVar **prev);
friend FBaseCVar *FindCVarSub (const char *var_name, int namelen);
// Called from G_InitNew()
friend void UnlatchCVars (void);
@ -148,7 +152,8 @@ public:
inline bool operator= (bool boolval)
{ UCVarValue val; val.Bool = boolval; SetGenericRep (val, CVAR_Bool); return boolval; }
inline bool operator* () { return Value; }
inline operator bool () const { return Value; }
inline bool operator *() const { return Value; }
protected:
virtual void DoSet (UCVarValue value, ECVarType type);
@ -172,7 +177,8 @@ public:
int operator= (int intval)
{ UCVarValue val; val.Int = intval; SetGenericRep (val, CVAR_Int); return intval; }
inline int operator* () { return Value; }
inline operator int () const { return Value; }
inline int operator *() const { return Value; }
protected:
virtual void DoSet (UCVarValue value, ECVarType type);
@ -198,7 +204,8 @@ public:
float operator= (float floatval)
{ UCVarValue val; val.Float = floatval; SetGenericRep (val, CVAR_Float); return floatval; }
inline float operator* () { return Value; }
inline operator float () const { return Value; }
inline float operator *() const { return Value; }
protected:
virtual void DoSet (UCVarValue value, ECVarType type);
@ -222,7 +229,8 @@ public:
char *operator= (char *stringrep)
{ UCVarValue val; val.String = stringrep; SetGenericRep (val, CVAR_String); return stringrep; }
inline const char *operator* () { return Value; }
inline operator const char * () const { return Value; }
inline const char *operator *() const { return Value; }
protected:
virtual void DoSet (UCVarValue value, ECVarType type);
@ -242,8 +250,9 @@ public:
virtual UCVarValue GetGenericRepDefault (ECVarType type) const;
virtual void SetGenericRepDefault (UCVarValue value, ECVarType type);
inline int operator* () { return Value; }
inline int GetIndex () { return Index; }
inline operator DWORD () const { return Value; }
inline DWORD operator *() const { return Value; }
inline int GetIndex () const { return Index; }
protected:
virtual void DoSet (UCVarValue value, ECVarType type);
@ -269,7 +278,8 @@ public:
bool operator= (bool boolval)
{ UCVarValue val; val.Bool = boolval; SetGenericRep (val, CVAR_Bool); return boolval; }
inline int operator* () { return (*ValueVar & BitVal); }
inline operator int () const { return (ValueVar & BitVal); }
inline int operator *() const { return (ValueVar & BitVal); }
protected:
virtual void DoSet (UCVarValue value, ECVarType type);
@ -300,7 +310,7 @@ void C_RestoreCVars (void);
#define CUSTOM_CVAR(type,name,def,flags) \
static void cvarfunc_##name(F##type##CVar &); \
F##type##CVar name (#name, def, flags, cvarfunc_##name); \
static void cvarfunc_##name(F##type##CVar &var)
static void cvarfunc_##name(F##type##CVar &self)
#define CVAR(type,name,def,flags) \
F##type##CVar name (#name, def, flags);

View file

@ -13,6 +13,9 @@
#include "m_alloc.h"
#include "d_player.h"
#include "configfile.h"
#include "z_zone.h"
#include "m_crc32.h"
static long ParseCommandLine (const char *args, int *argc, char **argv);
@ -38,45 +41,65 @@ class DStoredCommand : public DThinker
{
DECLARE_CLASS (DStoredCommand, DThinker)
public:
DStoredCommand (int argc, char **argv, const char *args);
DStoredCommand (FConsoleCommand *com, const char *cmd);
~DStoredCommand ();
void RunThink ();
private:
DStoredCommand ();
int ArgC;
char **ArgV;
char *ArgS;
FConsoleCommand *Command;
char *Text;
};
static FConsoleCommand *FindNameInHashTable (FConsoleCommand **table, const char *name);
static FConsoleCommand *ScanChainForName (FConsoleCommand *start, const char *name, FConsoleCommand **prev);
struct FActionMap
{
unsigned int Key; // value from passing Name to MakeKey()
FButtonStatus *Button;
char Name[12];
};
static FConsoleCommand *FindNameInHashTable (FConsoleCommand **table, const char *name, int namelen);
static FConsoleCommand *ScanChainForName (FConsoleCommand *start, const char *name, int namelen, FConsoleCommand **prev);
FConsoleCommand *Commands[HASH_SIZE];
struct ActionBits actionbits[NUM_ACTIONS] =
FButtonStatus Button_Mlook, Button_Klook, Button_Use,
Button_Attack, Button_Speed, Button_MoveRight, Button_MoveLeft,
Button_Strafe, Button_LookDown, Button_LookUp, Button_Back,
Button_Forward, Button_Right, Button_Left, Button_MoveDown,
Button_MoveUp, Button_Jump, Button_ShowScores;
// To add new actions, go to the console and type "key <action name>".
// This will give you the key value to use in the first column. Then
// insert your new action into this list so that the keys remain sorted
// in ascending order. No two keys can be identical. If yours matches
// an existing key, either modify MakeKey(), or (preferably) change the
// name of your action.
FActionMap ActionMaps[] =
{
{ 0x00409, ACTION_USE, "use" },
{ 0x0074d, ACTION_BACK, "back" },
{ 0x007e4, ACTION_LEFT, "left" },
{ 0x00816, ACTION_JUMP, "jump" },
{ 0x0106d, ACTION_KLOOK, "klook" },
{ 0x0109d, ACTION_MLOOK, "mlook" },
{ 0x010d8, ACTION_RIGHT, "right" },
{ 0x0110a, ACTION_SPEED, "speed" },
{ 0x01fc5, ACTION_ATTACK, "attack" },
{ 0x021ae, ACTION_LOOKUP, "lookup" },
{ 0x021fe, ACTION_MOVEUP, "moveup" },
{ 0x02315, ACTION_STRAFE, "strafe" },
{ 0x041c4, ACTION_FORWARD, "forward" },
{ 0x08788, ACTION_LOOKDOWN, "lookdown" },
{ 0x088c4, ACTION_MOVELEFT, "moveleft" },
{ 0x088c8, ACTION_MOVEDOWN, "movedown" },
{ 0x11268, ACTION_MOVERIGHT, "moveright" },
{ 0x2314d, ACTION_SHOWSCORES, "showscores" }
{ 0x0f26fef6, &Button_Speed, "speed" },
{ 0x1ccf57bf, &Button_MoveUp, "moveup" },
{ 0x22beba5f, &Button_Klook, "klook" },
{ 0x47c02d3b, &Button_Attack, "attack" },
{ 0x6dcec137, &Button_Back, "back" },
{ 0x7a67e768, &Button_Left, "left" },
{ 0x84b8789a, &Button_MoveLeft, "moveleft" },
{ 0x8fd9bf1e, &Button_ShowScores, "showscores" },
{ 0x94b1cc4b, &Button_Use, "use" },
{ 0xa7b30616, &Button_Jump, "jump" },
{ 0xadfe4fff, &Button_Mlook, "mlook" },
{ 0xb4ca7514, &Button_Right, "right" },
{ 0xb563e265, &Button_LookDown, "lookdown" },
{ 0xb67a0835, &Button_Strafe, "strafe" },
{ 0xe2200fc9, &Button_MoveDown, "movedown" },
{ 0xe78739bb, &Button_MoveRight, "moveright" },
{ 0xe7912f86, &Button_Forward, "forward" },
{ 0xf01cb105, &Button_LookUp, "lookup" },
};
byte Actions[NUM_ACTIONS];
#define NUM_ACTIONS (sizeof(ActionMaps)/sizeof(FActionMap))
IMPLEMENT_CLASS (DWaitingCommand)
@ -119,195 +142,294 @@ IMPLEMENT_CLASS (DStoredCommand)
DStoredCommand::DStoredCommand ()
{
Text = NULL;
Destroy ();
}
DStoredCommand::DStoredCommand (int argc, char **argv, const char *args)
DStoredCommand::DStoredCommand (FConsoleCommand *command, const char *args)
{
ArgC = argc;
if (argc != 0)
{
int len;
int i;
for (i = len = 0; i < argc; i++)
{
len += strlen (argv[i]) + 1;
}
ArgV = new char *[argc];
ArgV[0] = new char[len];
ArgV[0][0] = 0;
for (i = len = 0; i < argc; i++)
{
ArgV[i] = ArgV[0] + len;
strcpy (ArgV[0] + len, argv[i]);
len += strlen (argv[i]) + 1;
}
ArgS = new char[strlen (args) + 1];
strcpy (ArgS, args);
}
Command = command;
Text = copystring (args);
}
DStoredCommand::~DStoredCommand ()
{
if (ArgC != 0)
if (Text != NULL)
{
delete[] ArgV[0];
delete[] ArgV;
delete[] ArgS;
delete[] Text;
}
}
void DStoredCommand::RunThink ()
{
if (ArgC != 0)
if (Text != NULL && Command != NULL)
{
FConsoleCommand *com = FindNameInHashTable (Commands, ArgV[0]);
if (com != NULL)
{
com->Run (ArgC, ArgV, ArgS, players[consoleplayer].mo);
}
FCommandLine args (Text);
Command->Run (args, players[consoleplayer].mo, 0);
}
Destroy ();
}
static int ListActionCommands (void)
{
int i;
unsigned int i;
for (i = 0; i < NUM_ACTIONS; i++)
for (i = 0; i < NUM_ACTIONS; ++i)
{
Printf ("+%s\n", actionbits[i].name);
Printf ("-%s\n", actionbits[i].name);
Printf ("+%s\n", ActionMaps[i].Name);
Printf ("-%s\n", ActionMaps[i].Name);
}
return NUM_ACTIONS * 2;
}
unsigned int MakeKey (const char *s)
{
register unsigned int v = 0;
DWORD key = 0xffffffff;
const DWORD *table = GetCRCTable ();
if (*s)
v = tolower(*s++);
if (*s)
v = (v*3) + tolower(*s++);
while (*s)
v = (v << 1) + tolower(*s++);
return v;
{
key = CRC1 (key, tolower (*s++), table);
}
return key ^ 0xffffffff;
}
// GetActionBit scans through the actionbits[] array
unsigned int MakeKey (const char *s, int len)
{
if (len == 0)
{
return 0xffffffff;
}
DWORD key = 0xffffffff;
const DWORD *table = GetCRCTable ();
while (len > 0)
{
key = CRC1 (key, tolower(*s++), table);
--len;
}
return key ^ 0xffffffff;
}
// FindButton scans through the actionbits[] array
// for a matching key and returns an index or -1 if
// the key could not be found. This uses binary search,
// so actionbits[] must be sorted in ascending order.
int GetActionBit (unsigned int key)
FButtonStatus *FindButton (unsigned int key)
{
const ActionBits *bit;
const FActionMap *bit;
bit = BinarySearch (actionbits, NUM_ACTIONS, &ActionBits::key, key);
return bit ? bit->index : -1;
bit = BinarySearch<FActionMap, unsigned int>
(ActionMaps, NUM_ACTIONS, &FActionMap::Key, key);
return bit ? bit->Button : NULL;
}
void C_DoCommand (char *cmd)
void FButtonStatus::PressKey (int keynum)
{
int argc;
long argsize;
char **argv;
FConsoleCommand *com;
int i, open;
keynum &= KEY_DBLCLICKED-1;
if (keynum == 0)
{ // Issued from console instead of a key, so force on
Keys[0] = 0xffff;
for (i = MAX_KEYS-1; i > 0; --i)
{
Keys[i] = 0;
}
}
else
{
for (i = MAX_KEYS-1, open = -1; i >= 0; --i)
{
if (Keys[i] == 0)
{
open = i;
}
else if (Keys[i] == keynum)
{ // Key is already down; do nothing
return;
}
}
if (open < 0)
{ // No free key slots, so do nothing
Printf ("More than %u keys pressed for a single action!\n", MAX_KEYS);
return;
}
Keys[open] = keynum;
}
bDown = bWentDown = true;
}
void FButtonStatus::ReleaseKey (int keynum)
{
int i, numdown, match;
keynum &= KEY_DBLCLICKED-1;
if (keynum == 0)
{ // Issued from console instead of a key, so force off
for (i = MAX_KEYS-1; i >= 0; --i)
{
Keys[i] = 0;
}
bWentUp = true;
bDown = false;
}
else
{
for (i = MAX_KEYS-1, numdown = 0, match = -1; i >= 0; --i)
{
if (Keys[i] != 0)
{
++numdown;
if (Keys[i] == keynum)
{
match = i;
}
}
}
if (match < 0)
{ // Key was not down; do nothing
return;
}
Keys[match] = 0;
bWentUp = true;
if (--numdown == 0)
{
bDown = false;
}
}
}
void ResetButtonTriggers ()
{
for (int i = NUM_ACTIONS-1; i >= 0; --i)
{
ActionMaps[i].Button->ResetTriggers ();
}
}
void ResetButtonStates ()
{
for (int i = NUM_ACTIONS-1; i >= 0; --i)
{
FButtonStatus *button = ActionMaps[i].Button;
if (button != &Button_Mlook && button != &Button_Klook)
{
button->ReleaseKey (0);
}
button->ResetTriggers ();
}
}
void C_DoCommand (const char *cmd, int keynum)
{
FConsoleCommand *com;
const char *end;
const char *beg;
// Skip any beginning whitespace
while (*cmd && *cmd <= ' ')
cmd++;
// Check if this is an action
if (*cmd == '+' || *cmd == '-')
// Find end of the command name
if (*cmd == '\"')
{
int action;
char *end = cmd+1;
char brk;
for (end = beg = cmd+1; *end && *end != '\"'; ++end)
;
}
else
{
beg = cmd;
for (end = cmd+1; *end > ' '; ++end)
;
}
while (*end && *end > ' ')
end++;
brk = *end;
*end = 0;
action = GetActionBit (MakeKey (cmd + 1));
*end = brk;
if (action >= 0)
// Check if this is an action
if (*beg == '+' || *beg == '-')
{
FButtonStatus *button;
button = FindButton (MakeKey (beg + 1, end - beg - 1));
if (button != NULL)
{
if (*cmd == '+')
if (*beg == '+')
{
//if (Actions[check] < 255)
// Actions[check]++;
Actions[action] = 1;
button->PressKey (keynum);
}
else
{
//if (Actions[check])
// Actions[check]--;
Actions[action] = 0;
if (action == ACTION_MLOOK && *lookspring)
button->ReleaseKey (keynum);
if (button == &Button_Mlook && lookspring)
{
AddCommandString ("centerview");
C_DoCommand ("centerview");
}
}
return;
}
}
// Parse it as a normal command
argsize = ParseCommandLine (cmd, &argc, NULL);
argv = (char **)Malloc (argc*sizeof(char *) + argsize);
argv[0] = (char *)argv + argc*sizeof(char *);
ParseCommandLine (cmd, NULL, argv);
const int len = end - beg;
// Parse it as a normal command
// Checking for matching commands follows this search order:
// 1. Check the Commands[] hash table
// 2. Check the CVars list
if ( (com = FindNameInHashTable (Commands, argv[0])) )
if ( (com = FindNameInHashTable (Commands, beg, len)) )
{
if (gamestate != GS_STARTUP ||
stricmp (argv[0], "set") == 0 ||
stricmp (argv[0], "logfile") == 0 ||
stricmp (argv[0], "unbindall") == 0 ||
stricmp (argv[0], "exec") == 0)
(len == 3 && strnicmp (beg, "set", 3) == 0) ||
(len == 7 && strnicmp (beg, "logfile", 7) == 0) ||
(len == 9 && strnicmp (beg, "unbindall", 9) == 0) ||
(len == 4 && strnicmp (beg, "bind", 4) == 0) ||
(len == 4 && strnicmp (beg, "exec", 4) == 0) ||
(len ==10 && strnicmp (beg, "doublebind", 10) == 0)
)
{
com->Run (argc, argv, cmd, players[consoleplayer].mo);
FCommandLine args (beg);
com->Run (args, players[consoleplayer].mo, keynum);
}
else
{
new DStoredCommand (argc, argv, cmd);
new DStoredCommand (com, beg);
}
}
else
{
// Check for any console vars that match the command
FBaseCVar *var;
{ // Check for any console vars that match the command
FBaseCVar *var = FindCVarSub (beg, len);
if ( (var = FindCVar (argv[0], NULL)) )
if (var != NULL)
{
if (argc >= 2)
{ // Hack
com = FindNameInHashTable (Commands, "set");
com->Run (argc + 1, argv - 1, cmd, players[consoleplayer].mo);
FCommandLine args (beg);
if (args.argc() >= 2)
{ // Set the variable
var->CmdSet (args.AllButFirstArg (1));
}
else
{
{ // Get the variable's value
UCVarValue val = var->GetGenericRep (CVAR_String);
Printf ("\"%s\" is \"%s\"\n", var->GetName(), val.String);
}
}
else
{
// We don't know how to handle this command
Printf ("Unknown command \"%s\"\n", argv[0]);
{ // We don't know how to handle this command
char cmdname[64];
int minlen = MIN (len, 63);
memcpy (cmdname, beg, minlen);
cmdname[len] = 0;
Printf ("Unknown command \"%s\"\n", cmdname);
}
}
free (argv);
}
void AddCommandString (char *cmd)
void AddCommandString (char *cmd, int keynum)
{
char *brkpt;
int more;
@ -336,12 +458,13 @@ void AddCommandString (char *cmd)
{
more = 0;
}
// Intercept wait commands here
// Intercept wait commands here. Note: wait must be lowercase
while (*cmd && *cmd <= ' ')
cmd++;
if (*cmd)
{
if (strnicmp (cmd, "wait", 4) == 0 && (cmd[4] == 0 || cmd[4] == ' '))
if (cmd[0] == 'w' && cmd[1] == 'a' && cmd[2] == 'i' && cmd[3] == 't' &&
(cmd[4] == 0 || cmd[4] == ' '))
{
int tics;
@ -357,6 +480,8 @@ void AddCommandString (char *cmd)
{
if (more)
{ // The remainder of the command will be executed later
// Note that deferred commands lose track of which key
// (if any) they were pressed from.
*brkpt = ';';
new DWaitingCommand (brkpt + 1, tics);
}
@ -365,7 +490,7 @@ void AddCommandString (char *cmd)
}
else
{
C_DoCommand (cmd);
C_DoCommand (cmd, keynum);
}
}
if (more)
@ -476,17 +601,86 @@ static long ParseCommandLine (const char *args, int *argc, char **argv)
return (long)buffplace;
}
static FConsoleCommand *ScanChainForName (FConsoleCommand *start, const char *name, FConsoleCommand **prev)
FCommandLine::FCommandLine (const char *commandline)
{
cmd = commandline;
_argc = -1;
_argv = NULL;
}
FCommandLine::~FCommandLine ()
{
if (_argv != NULL)
{
Z_Free (_argv);
}
}
int FCommandLine::argc ()
{
if (_argc == -1)
{
argsize = ParseCommandLine (cmd, &_argc, NULL);
}
return _argc;
}
char *FCommandLine::operator[] (int i)
{
if (_argv == NULL)
{
int count = argc();
_argv = (char **)Z_Malloc (count*sizeof(char *) + argsize, PU_STATIC, 0);
_argv[0] = (char *)_argv + count*sizeof(char *);
ParseCommandLine (cmd, NULL, _argv);
}
return _argv[i];
}
const char *FCommandLine::AllButFirstArg (int numToSkip)
{
const char *start = cmd;
if (argc() != numToSkip + 1)
{
while (--numToSkip >= 0 && *start)
{
// Skip non-white space (the arg itself)
while (*start > ' ')
{
if (*start == '\"')
{ // skip to end of quoted string
while (*start && *start != '\"')
++start;
if (*start == 0)
return start;
}
++start;
}
// Skip white space after arg
while (*start && *start <= ' ')
++start;
}
return start;
}
else
{
return operator[] (numToSkip);
}
}
static FConsoleCommand *ScanChainForName (FConsoleCommand *start, const char *name, int namelen, FConsoleCommand **prev)
{
int comp;
*prev = NULL;
while (start)
{
comp = stricmp (start->m_Name, name);
comp = strnicmp (start->m_Name, name, namelen);
if (comp > 0)
return NULL;
else if (comp == 0)
else if (comp == 0 && start->m_Name[namelen] == 0)
return start;
*prev = start;
@ -495,11 +689,11 @@ static FConsoleCommand *ScanChainForName (FConsoleCommand *start, const char *na
return NULL;
}
static FConsoleCommand *FindNameInHashTable (FConsoleCommand **table, const char *name)
static FConsoleCommand *FindNameInHashTable (FConsoleCommand **table, const char *name, int namelen)
{
FConsoleCommand *dummy;
return ScanChainForName (table[MakeKey (name) % HASH_SIZE], name, &dummy);
return ScanChainForName (table[MakeKey (name, namelen) % HASH_SIZE], name, namelen, &dummy);
}
bool FConsoleCommand::AddToHash (FConsoleCommand **table)
@ -513,7 +707,7 @@ bool FConsoleCommand::AddToHash (FConsoleCommand **table)
key = MakeKey (m_Name);
bucket = &table[key % HASH_SIZE];
if (ScanChainForName (*bucket, m_Name, &insert))
if (ScanChainForName (*bucket, m_Name, strlen (m_Name), &insert))
{
return false;
}
@ -547,14 +741,14 @@ FConsoleCommand::FConsoleCommand (const char *name, CCmdRun runFunc)
if (firstTime)
{
char tname[16];
int i;
unsigned int i;
firstTime = false;
// Add all the action commands for tab completion
for (i = 0; i < NUM_ACTIONS; i++)
{
strcpy (&tname[1], actionbits[i].name);
strcpy (&tname[1], ActionMaps[i].Name);
tname[0] = '+';
C_AddTabCommand (tname);
tname[0] = '-';
@ -582,9 +776,9 @@ FConsoleCommand::~FConsoleCommand ()
delete[] m_Name;
}
void FConsoleCommand::Run (int argc, char **argv, const char *args, AActor *instigator)
void FConsoleCommand::Run (FCommandLine &argv, AActor *instigator, int key)
{
m_RunFunc (argc, argv, args, instigator);
m_RunFunc (argv, instigator, key);
}
FConsoleAlias::FConsoleAlias (const char *name, const char *command)
@ -682,7 +876,7 @@ void C_SetAlias (const char *name, const char *cmd)
FConsoleCommand *prev, *alias, **chain;
chain = &Commands[MakeKey (name) % HASH_SIZE];
alias = ScanChainForName (*chain, name, &prev);
alias = ScanChainForName (*chain, name, strlen (name), &prev);
if (alias != NULL)
{
delete alias;
@ -694,7 +888,7 @@ CCMD (alias)
{
FConsoleCommand *prev, *alias, **chain;
if (argc == 1)
if (argv.argc() == 1)
{
Printf ("Current alias commands:\n");
DumpHash (Commands, true);
@ -703,25 +897,23 @@ CCMD (alias)
{
chain = &Commands[MakeKey (argv[1]) % HASH_SIZE];
if (argc == 2)
{
// Remove the alias
if (argv.argc() == 2)
{ // Remove the alias
if ( (alias = ScanChainForName (*chain, argv[1], &prev)) )
if ( (alias = ScanChainForName (*chain, argv[1], strlen (argv[1]), &prev)) )
{
delete alias;
}
}
else
{
// Add/Change the alias
{ // Add/change the alias
alias = ScanChainForName (*chain, argv[1], &prev);
alias = ScanChainForName (*chain, argv[1], strlen (argv[1]), &prev);
if (alias)
delete alias;
if (argc > 3)
new FConsoleAlias (argv[1], BuildString (argc - 2, &argv[2]));
if (argv.argc() > 3)
new FConsoleAlias (argv[1], copystring (argv.AllButFirstArg(2)));
else
new FConsoleAlias (argv[1], copystring (argv[2]));
}
@ -739,15 +931,15 @@ CCMD (cmdlist)
CCMD (key)
{
if (argc > 1)
if (argv.argc() > 1)
{
while (argc > 1)
int i;
for (i = 1; i < argv.argc(); ++i)
{
Printf (" %08x", MakeKey (argv[1]));
argc--;
argv++;
unsigned int key = MakeKey (argv[i]);
Printf (" 0x%08x\n", key, key);
}
Printf ("\n");
}
}
@ -792,7 +984,7 @@ bool FConsoleAlias::IsAlias ()
return true;
}
void FConsoleAlias::Run (int argc, char **argv, const char *args, AActor *m_Instigator)
void FConsoleAlias::Run (FCommandLine &args, AActor *m_Instigator, int key)
{
AddCommandString (m_Command);
AddCommandString (m_Command, key);
}

117
src/c_dispatch.h Normal file
View file

@ -0,0 +1,117 @@
#ifndef __C_DISPATCH_H__
#define __C_DISPATCH_H__
#include "dobject.h"
class FConfigFile;
#define HASH_SIZE 251 // I think this is prime
void C_ExecCmdLineParams ();
// Add commands to the console as if they were typed in. Can handle wait
// and semicolon-separated commands. This function may modify the source
// string, but the string will be restored to its original state before
// returning. Therefore, commands passed must not be in read-only memory.
void AddCommandString (char *text, int keynum=0);
// Process a single console command. Does not handle wait.
void C_DoCommand (const char *cmd, int keynum=0);
// Write out alias commands to a file for all current aliases.
void C_ArchiveAliases (FConfigFile *f);
void C_SetAlias (const char *name, const char *cmd);
// build a single string out of multiple strings
char *BuildString (int argc, char **argv);
// Class that can parse command lines
class FCommandLine
{
public:
FCommandLine (const char *commandline);
~FCommandLine ();
int argc ();
char *operator[] (int i);
const char *args () { return cmd; }
const char *AllButFirstArg (int numToSkip=1); // like args(), but can skip first n args
private:
const char *cmd;
int _argc;
char **_argv;
long argsize;
};
typedef void (*CCmdRun) (FCommandLine &argv, AActor *instigator, int key);
class FConsoleCommand
{
public:
FConsoleCommand (const char *name, CCmdRun RunFunc);
virtual ~FConsoleCommand ();
virtual bool IsAlias ();
void PrintCommand () { Printf ("%s\n", m_Name); }
virtual void Run (FCommandLine &args, AActor *instigator, int key);
FConsoleCommand *m_Next, **m_Prev;
char *m_Name;
protected:
FConsoleCommand ();
bool AddToHash (FConsoleCommand **table);
CCmdRun m_RunFunc;
};
#define CCMD(n) \
void Cmd_##n (FCommandLine &, AActor *, int key); \
FConsoleCommand Cmd_##n##_ (#n, Cmd_##n); \
void Cmd_##n (FCommandLine &argv, AActor *m_Instigator, int key)
const int KEY_DBLCLICKED = 0x8000;
class FConsoleAlias : public FConsoleCommand
{
public:
FConsoleAlias (const char *name, const char *command);
~FConsoleAlias ();
void Run (FCommandLine &args, AActor *Instigator, int key);
bool IsAlias ();
void PrintAlias () { Printf ("%s : %s\n", m_Name, m_Command); }
void Archive (FConfigFile *f);
protected:
char *m_Command;
};
// Actions
struct FButtonStatus
{
enum { MAX_KEYS = 6 }; // Maximum number of keys that can press this button
WORD Keys[MAX_KEYS];
BYTE bDown; // Button is down right now
BYTE bWentDown; // Button went down this tic
BYTE bWentUp; // Button went up this tic
BYTE padTo16Bytes;
void PressKey (int keynum);
void ReleaseKey (int keynum);
void ResetTriggers () { bWentDown = bWentUp = false; }
};
extern FButtonStatus Button_Mlook, Button_Klook, Button_Use,
Button_Attack, Button_Speed, Button_MoveRight, Button_MoveLeft,
Button_Strafe, Button_LookDown, Button_LookUp, Button_Back,
Button_Forward, Button_Right, Button_Left, Button_MoveDown,
Button_MoveUp, Button_Jump, Button_ShowScores;
void ResetButtonTriggers (); // Call ResetTriggers for all buttons
void ResetButtonStates (); // Same as above, but also clear bDown
extern unsigned int MakeKey (const char *s);
#endif //__C_DISPATCH_H__

View file

@ -60,7 +60,7 @@ void FColorMatcher::SetPalette (const DWORD *palette)
#ifdef BEFAST
Seed seeds[255];
byte seedspread[HISIZE+1][HISIZE+1][HISIZE+1];
byte seedspread[CHISIZE+1][CHISIZE+1][CHISIZE+1];
int numseeds;
int i, radius;
@ -70,9 +70,9 @@ void FColorMatcher::SetPalette (const DWORD *palette)
// Plant each color from the palette as seeds in the color cube
for (i = 1; i < 256; i++)
{
int r = (Pal[i].r + LOSIZE/2) >> LOBITS;
int g = (Pal[i].g + LOSIZE/2) >> LOBITS;
int b = (Pal[i].b + LOSIZE/2) >> LOBITS;
int r = (Pal[i].r + CLOSIZE/2) >> CLOBITS;
int g = (Pal[i].g + CLOSIZE/2) >> CLOBITS;
int b = (Pal[i].b + CLOSIZE/2) >> CLOBITS;
if (FirstColor[r][g][b] == 0)
{
@ -96,7 +96,7 @@ void FColorMatcher::SetPalette (const DWORD *palette)
// Grow each seed outward as a cube until no seed can
// grow any further.
for (radius = 1; radius < HISIZE; radius++)
for (radius = 1; radius < CHISIZE; radius++)
{
int seedsused = 0;
for (i = numseeds - 1; i >= 0; i--)
@ -120,11 +120,11 @@ void FColorMatcher::SetPalette (const DWORD *palette)
// Check to see which planes are acceptable
byte bad = 0;
if (r1 < 0) bad |= 1, r1 = 0;
if (r2 > HISIZE) bad |= 2, r2 = HISIZE;
if (r2 > CHISIZE) bad |= 2, r2 = CHISIZE;
if (g1 < 0) bad |= 4, g1 = 0;
if (g2 > HISIZE) bad |= 8, g2 = HISIZE;
if (g2 > CHISIZE) bad |= 8, g2 = CHISIZE;
if (b1 < 0) bad |= 16, b1 = 0;
if (b2 > HISIZE) bad |= 32, b2 = HISIZE;
if (b2 > CHISIZE) bad |= 32, b2 = CHISIZE;
bad |= seeds[i].bad;
@ -187,7 +187,7 @@ void FColorMatcher::SetPalette (const DWORD *palette)
}
int FColorMatcher::FillPlane (int r1, int r2, int g1, int g2, int b1, int b2,
byte seedspread[HISIZE+1][HISIZE+1][HISIZE+1],
byte seedspread[CHISIZE+1][CHISIZE+1][CHISIZE+1],
Seed *seeds, int thisseed)
{
const Seed *secnd = seeds + thisseed;
@ -239,7 +239,7 @@ byte FColorMatcher::Pick (int r, int g, int b)
byte bestcolor;
int bestdist;
byte color = FirstColor[(r+LOSIZE/2)>>LOBITS][(g+LOSIZE/2)>>LOBITS][(b+LOSIZE/2)>>LOBITS];
byte color = FirstColor[(r+CLOSIZE/2)>>CLOBITS][(g+CLOSIZE/2)>>CLOBITS][(b+CLOSIZE/2)>>CLOBITS];
if (NextColor[color] == 0)
return color;

View file

@ -31,17 +31,17 @@ public:
FColorMatcher &operator= (const FColorMatcher &other);
private:
enum { HIBITS=4, LOBITS=8-HIBITS, HISIZE=1<<HIBITS, LOSIZE=1<<LOBITS};
enum { CHIBITS=4, CLOBITS=8-CHIBITS, CHISIZE=1<<CHIBITS, CLOSIZE=1<<CLOBITS};
struct Seed;
struct PalEntry;
const PalEntry *Pal;
byte FirstColor[HISIZE+1][HISIZE+1][HISIZE+1];
byte FirstColor[CHISIZE+1][CHISIZE+1][CHISIZE+1];
byte NextColor[256];
int FillPlane (int r1, int r2, int g1, int g2, int b1, int b2,
byte seedspread[HISIZE+1][HISIZE+1][HISIZE+1],
byte seedspread[CHISIZE+1][CHISIZE+1][CHISIZE+1],
Seed *seeds, int thisseed);
};
#endif //__COLORMATCHER_H__
#endif //__COLORMATCHER_H__

View file

@ -65,4 +65,4 @@ private:
FConfigEntry *NewConfigEntry (FConfigSection *section, const char *key, const char *value);
};
#endif //__CONFIGFILE_H__
#endif //__CONFIGFILE_H__

View file

@ -114,53 +114,58 @@ void CT_Stop ()
BOOL CT_Responder (event_t *ev)
{
if (chatmodeon && ev->type == EV_GUI_Event &&
(ev->subtype == EV_GUI_KeyDown || ev->subtype == EV_GUI_KeyRepeat))
if (chatmodeon && ev->type == EV_GUI_Event)
{
// send a macro
if ((ev->data3 & GKM_ALT) && (ev->data1 >= '0' && ev->data1 <= '9'))
if (ev->subtype == EV_GUI_KeyDown || ev->subtype == EV_GUI_KeyRepeat)
{
ShoveChatStr (**chat_macros[ev->data1 - '0'], chatmodeon - 1);
CT_Stop ();
return true;
}
if (ev->data1 == '\r')
{
ShoveChatStr ((char *)ChatQueue, chatmodeon - 1);
CT_Stop ();
return true;
}
else if (ev->data1 == GK_ESCAPE)
{
CT_Stop ();
return true;
}
else if (ev->data1 == '\b')
{
CT_BackSpace ();
return true;
}
else if (ev->data1 == 'C' && (ev->data3 & GKM_CTRL))
{
I_PutInClipboard ((char *)ChatQueue);
}
else if (ev->data1 == 'V' && (ev->data3 & GKM_CTRL))
{
char *clip = I_GetFromClipboard ();
if (clip != NULL)
if (ev->data1 == '\r')
{
char *clip_p = clip;
strtok (clip, "\n\r\b");
while (*clip_p)
ShoveChatStr ((char *)ChatQueue, chatmodeon - 1);
CT_Stop ();
return true;
}
else if (ev->data1 == GK_ESCAPE)
{
CT_Stop ();
return true;
}
else if (ev->data1 == '\b')
{
CT_BackSpace ();
return true;
}
else if (ev->data1 == 'C' && (ev->data3 & GKM_CTRL))
{
I_PutInClipboard ((char *)ChatQueue);
return true;
}
else if (ev->data1 == 'V' && (ev->data3 & GKM_CTRL))
{
char *clip = I_GetFromClipboard ();
if (clip != NULL)
{
CT_AddChar (*clip_p++);
char *clip_p = clip;
strtok (clip, "\n\r\b");
while (*clip_p)
{
CT_AddChar (*clip_p++);
}
delete[] clip;
}
delete[] clip;
}
}
else
else if (ev->subtype == EV_GUI_Char)
{
CT_AddChar (ev->data2);
// send a macro
if (ev->data2 && (ev->data1 >= '0' && ev->data1 <= '9'))
{
ShoveChatStr (*chat_macros[ev->data1 - '0'], chatmodeon - 1);
CT_Stop ();
}
else
{
CT_AddChar (ev->data1);
}
return true;
}
}
@ -181,7 +186,7 @@ void CT_Drawer (void)
static const char *prompt = "Say: ";
int i, x, scalex, y, promptwidth;
if (*con_scaletext)
if (con_scaletext)
{
scalex = CleanXfac;
y = (!viewactive ? -30 : -10) * CleanYfac;
@ -216,7 +221,7 @@ void CT_Drawer (void)
// draw the prompt, text, and cursor
ChatQueue[len] = gameinfo.gametype == GAME_Doom ? '_' : '[';
ChatQueue[len+1] = '\0';
if (*con_scaletext)
if (con_scaletext)
{
screen->DrawTextClean (CR_GREEN, 0, y, prompt);
screen->DrawTextClean (CR_GREY, promptwidth, y, ChatQueue + i);
@ -231,8 +236,8 @@ void CT_Drawer (void)
BorderTopRefresh = screen->GetPageCount ();
}
if (*deathmatch &&
((Actions[ACTION_SHOWSCORES]) ||
if (deathmatch &&
(Button_ShowScores.bDown ||
players[consoleplayer].camera->health <= 0))
{
HU_DrawScores (&players[consoleplayer]);
@ -301,12 +306,7 @@ CCMD (messagemode)
CCMD (say)
{
if (argc > 1)
{
char *chat = BuildString (argc - 1, argv + 1);
ShoveChatStr (chat, 0);
delete[] chat;
}
ShoveChatStr (argv.AllButFirstArg(), 0);
}
CCMD (messagemode2)
@ -321,12 +321,7 @@ CCMD (messagemode2)
CCMD (say_team)
{
if (argc > 1)
{
char *chat = BuildString (argc - 1, argv + 1);
ShoveChatStr (chat, 1);
delete[] chat;
}
ShoveChatStr (argv.AllButFirstArg(), 1);
}
static int STACK_ARGS compare (const void *arg1, const void *arg2)
@ -361,7 +356,7 @@ void HU_DrawScores (player_t *player)
if (playeringame[i])
{
int width = screen->StringWidth (players[i].userinfo.netname);
if (*teamplay)
if (teamplay)
width += screen->StringWidth (
players[i].userinfo.team == TEAM_None ? "None"
: TeamNames[players[i].userinfo.team]) + 24;
@ -376,9 +371,9 @@ void HU_DrawScores (player_t *player)
y = (ST_Y >> 1) - (MAXPLAYERS * 6);
if (y < 48) y = 48;
if (*deathmatch && *timelimit && gamestate == GS_LEVEL)
if (deathmatch && timelimit && gamestate == GS_LEVEL)
{
int timeleft = (int)(*timelimit * TICRATE * 60) - level.time;
int timeleft = (int)(timelimit * TICRATE * 60) - level.time;
int hours, minutes, seconds;
if (timeleft < 0)
@ -414,7 +409,7 @@ void HU_DrawScores (player_t *player)
screen->DrawTextClean (sortedplayers[i] == player ? CR_GREEN : CR_BRICK,
margin, y, str);
if (*teamplay && sortedplayers[i]->userinfo.team != TEAM_None)
if (teamplay && sortedplayers[i]->userinfo.team != TEAM_None)
sprintf (str, "%s (%s)", sortedplayers[i]->userinfo.netname,
TeamNames[sortedplayers[i]->userinfo.team]);
else

View file

@ -123,89 +123,89 @@ static CodePtrMap *CodePtrNames;
static int NumCodePtrs;
static const actionf_t CodePtrs[] =
{
{(actionf_p1)NULL},
{(actionf_p1)A_MonsterRail},
{(actionf_p1)A_FireRailgun},
{(actionf_p1)A_FireRailgunLeft},
{(actionf_p1)A_FireRailgunRight},
{(actionf_p1)A_RailWait},
{(actionf_p1)A_Light0},
{(actionf_p1)A_WeaponReady},
{(actionf_p1)A_Lower},
{(actionf_p1)A_Raise},
{(actionf_p1)A_Punch},
{(actionf_p1)A_ReFire},
{(actionf_p1)A_FirePistol},
{(actionf_p1)A_Light1},
{(actionf_p1)A_FireShotgun},
{(actionf_p1)A_Light2},
{(actionf_p1)A_FireShotgun2},
{(actionf_p1)A_CheckReload},
{(actionf_p1)A_OpenShotgun2},
{(actionf_p1)A_LoadShotgun2},
{(actionf_p1)A_CloseShotgun2},
{(actionf_p1)A_FireCGun},
{(actionf_p1)A_GunFlash},
{(actionf_p1)A_FireMissile},
{(actionf_p1)A_Saw},
{(actionf_p1)A_FirePlasma},
{(actionf_p1)A_BFGsound},
{(actionf_p1)A_FireBFG},
{(actionf_p1)A_BFGSpray},
{(actionf_p1)A_Explode},
{(actionf_p1)A_Pain},
{(actionf_p1)A_PlayerScream},
{(actionf_p1)A_NoBlocking},
{(actionf_p1)A_XScream},
{(actionf_p1)A_Look},
{(actionf_p1)A_Chase},
{(actionf_p1)A_FaceTarget},
{(actionf_p1)A_PosAttack},
{(actionf_p1)A_Scream},
{(actionf_p1)A_SPosAttack},
{(actionf_p1)A_VileChase},
{(actionf_p1)A_VileStart},
{(actionf_p1)A_VileTarget},
{(actionf_p1)A_VileAttack},
{(actionf_p1)A_StartFire},
{(actionf_p1)A_Fire},
{(actionf_p1)A_FireCrackle},
{(actionf_p1)A_Tracer},
{(actionf_p1)A_SkelWhoosh},
{(actionf_p1)A_SkelFist},
{(actionf_p1)A_SkelMissile},
{(actionf_p1)A_FatRaise},
{(actionf_p1)A_FatAttack1},
{(actionf_p1)A_FatAttack2},
{(actionf_p1)A_FatAttack3},
{(actionf_p1)A_BossDeath},
{(actionf_p1)A_CPosAttack},
{(actionf_p1)A_CPosRefire},
{(actionf_p1)A_TroopAttack},
{(actionf_p1)A_SargAttack},
{(actionf_p1)A_HeadAttack},
{(actionf_p1)A_BruisAttack},
{(actionf_p1)A_SkullAttack},
{(actionf_p1)A_Metal},
{(actionf_p1)A_SpidRefire},
{(actionf_p1)A_BabyMetal},
{(actionf_p1)A_BspiAttack},
{(actionf_p1)A_Hoof},
{(actionf_p1)A_CyberAttack},
{(actionf_p1)A_PainAttack},
{(actionf_p1)A_PainDie},
{(actionf_p1)A_KeenDie},
{(actionf_p1)A_BrainPain},
{(actionf_p1)A_BrainScream},
{(actionf_p1)A_BrainDie},
{(actionf_p1)A_BrainAwake},
{(actionf_p1)A_BrainSpit},
{(actionf_p1)A_SpawnSound},
{(actionf_p1)A_SpawnFly},
{(actionf_p1)A_BrainExplode},
{(actionf_p1)A_Die},
{(actionf_p1)A_Detonate},
{(actionf_p1)A_Mushroom},
{(void *)NULL},
{(void *)A_MonsterRail},
{(void *)A_FireRailgun},
{(void *)A_FireRailgunLeft},
{(void *)A_FireRailgunRight},
{(void *)A_RailWait},
{(void *)A_Light0},
{(void *)A_WeaponReady},
{(void *)A_Lower},
{(void *)A_Raise},
{(void *)A_Punch},
{(void *)A_ReFire},
{(void *)A_FirePistol},
{(void *)A_Light1},
{(void *)A_FireShotgun},
{(void *)A_Light2},
{(void *)A_FireShotgun2},
{(void *)A_CheckReload},
{(void *)A_OpenShotgun2},
{(void *)A_LoadShotgun2},
{(void *)A_CloseShotgun2},
{(void *)A_FireCGun},
{(void *)A_GunFlash},
{(void *)A_FireMissile},
{(void *)A_Saw},
{(void *)A_FirePlasma},
{(void *)A_BFGsound},
{(void *)A_FireBFG},
{(void *)A_BFGSpray},
{(void *)A_Explode},
{(void *)A_Pain},
{(void *)A_PlayerScream},
{(void *)A_NoBlocking},
{(void *)A_XScream},
{(void *)A_Look},
{(void *)A_Chase},
{(void *)A_FaceTarget},
{(void *)A_PosAttack},
{(void *)A_Scream},
{(void *)A_SPosAttack},
{(void *)A_VileChase},
{(void *)A_VileStart},
{(void *)A_VileTarget},
{(void *)A_VileAttack},
{(void *)A_StartFire},
{(void *)A_Fire},
{(void *)A_FireCrackle},
{(void *)A_Tracer},
{(void *)A_SkelWhoosh},
{(void *)A_SkelFist},
{(void *)A_SkelMissile},
{(void *)A_FatRaise},
{(void *)A_FatAttack1},
{(void *)A_FatAttack2},
{(void *)A_FatAttack3},
{(void *)A_BossDeath},
{(void *)A_CPosAttack},
{(void *)A_CPosRefire},
{(void *)A_TroopAttack},
{(void *)A_SargAttack},
{(void *)A_HeadAttack},
{(void *)A_BruisAttack},
{(void *)A_SkullAttack},
{(void *)A_Metal},
{(void *)A_SpidRefire},
{(void *)A_BabyMetal},
{(void *)A_BspiAttack},
{(void *)A_Hoof},
{(void *)A_CyberAttack},
{(void *)A_PainAttack},
{(void *)A_PainDie},
{(void *)A_KeenDie},
{(void *)A_BrainPain},
{(void *)A_BrainScream},
{(void *)A_BrainDie},
{(void *)A_BrainAwake},
{(void *)A_BrainSpit},
{(void *)A_SpawnSound},
{(void *)A_SpawnFly},
{(void *)A_BrainExplode},
{(void *)A_Die},
{(void *)A_Detonate},
{(void *)A_Mushroom},
};
// Miscellaneous info that used to be constant
@ -679,6 +679,7 @@ static int PatchThing (int thingy)
if (thingy > NumInfos || thingy <= 0)
{
info = &dummy;
ednum = &dummyed;
Printf ("Thing %d out of range.\n", thingy);
}
else
@ -1015,6 +1016,7 @@ static int PatchFrame (int frameNum)
else
{
info = &dummy;
tics = misc1 = frame = 0;
Printf ("Frame %d out of range\n", frameNum);
}
@ -1937,6 +1939,7 @@ static void UnloadDehSupp ()
Z_FreeTags (PU_DEHACKED, PU_DEHACKED);
GStrings.FlushNames ();
GStrings.Compact ();
G_SetLevelStrings ();
}
}

View file

@ -3,4 +3,4 @@
void DoDehPatch (const char *patchfile, BOOL autoloading);
#endif //__D_DEHACK_H__
#endif //__D_DEHACK_H__

View file

@ -8,6 +8,7 @@ enum EGUIEvent
EV_GUI_KeyDown, // data1: unshifted ASCII, data2: shifted ASCII, data3: modifiers
EV_GUI_KeyRepeat, // same
EV_GUI_KeyUp, // same
EV_GUI_Char, // data1: translated character (for user text input), data2: alt down?
EV_GUI_MouseMove,
EV_GUI_LButtonDown,
EV_GUI_LButtonUp,
@ -29,7 +30,7 @@ enum GUIKeyModifiers
GKM_ALT = 4
};
// Special "ASCII" codes for some GUI keys
// Special codes for some GUI keys, including a few real ASCII codes.
enum ESpecialGUIKeys
{
GK_PGUP = 1,
@ -38,10 +39,33 @@ enum ESpecialGUIKeys
GK_END = 4,
GK_LEFT = 5,
GK_RIGHT = 6,
GK_UP = 11,
GK_ALERT = 7, // ASCII bell
GK_BACKSPACE= 8, // ASCII
GK_TAB = 9, // ASCII
GK_LINEFEED = 10, // ASCII
GK_DOWN = 10,
GK_DEL = 14,
GK_ESCAPE = 27
GK_VTAB = 11, // ASCII
GK_UP = 11,
GK_FORMFEED = 12, // ASCII
GK_RETURN = 13, // ASCII
GK_F1 = 14,
GK_F2 = 15,
GK_F3 = 16,
GK_F4 = 17,
GK_F5 = 18,
GK_F6 = 19,
GK_F7 = 20,
GK_F8 = 21,
GK_F9 = 22,
GK_F10 = 23,
GK_F11 = 24,
GK_F12 = 25,
GK_DEL = 26,
GK_ESCAPE = 27, // ASCII
GK_FREE1 = 28,
GK_FREE2 = 29,
GK_FREE3 = 30,
GK_CESCAPE = 31 // color escape
};
#endif //__D_GUI_H__
#endif //__D_GUI_H__

View file

@ -389,4 +389,4 @@ gitem_t itemlist[] = {
void InitItems (void)
{
num_items = sizeof(itemlist)/sizeof(itemlist[0]) - 1;
}
}

View file

@ -68,4 +68,4 @@ gitem_t *FindItem (const char *pickup_name);
#define ITEM_INDEX(i) ((i)-itemlist)
#endif //__D_ITEMS_H__
#endif //__D_ITEMS_H__

View file

@ -33,7 +33,7 @@
#include <sys/stat.h>
#endif
#ifdef UNIX
#ifdef unix
#include <unistd.h>
#endif
@ -254,14 +254,17 @@ CUSTOM_CVAR (Int, dmflags, 0, CVAR_SERVERINFO)
if (textureheight)
R_InitSkyMap ();
if (*var & DF_NO_FREELOOK)
AddCommandString ("centerview");
if (self & DF_NO_FREELOOK)
{
C_DoCommand ("centerview");
}
}
CVAR (Flag, sv_nohealth, dmflags, DF_NO_HEALTH);
CVAR (Flag, sv_noitems, dmflags, DF_NO_ITEMS);
CVAR (Flag, sv_weaponstay, dmflags, DF_WEAPONS_STAY);
CVAR (Flag, sv_falldamage, dmflags, DF_YES_FALLING);
CVAR (Flag, sv_falldamage, dmflags, DF_FORCE_FALLINGHX);
CVAR (Flag, sv_oldfalldamage, dmflags, DF_FORCE_FALLINGZD);
CVAR (Flag, sv_samelevel, dmflags, DF_SAME_LEVEL);
CVAR (Flag, sv_spawnfarthest, dmflags, DF_SPAWN_FARTHEST);
CVAR (Flag, sv_forcerespawn, dmflags, DF_FORCE_RESPAWN);
@ -275,13 +278,14 @@ CVAR (Flag, sv_fastmonsters, dmflags, DF_FAST_MONSTERS);
CVAR (Flag, sv_nojump, dmflags, DF_NO_JUMP);
CVAR (Flag, sv_nofreelook, dmflags, DF_NO_FREELOOK);
CVAR (Flag, sv_respawnsuper, dmflags, DF_RESPAWN_SUPER);
CVAR (Flag, sv_nopassover, dmflags, DF_NO_PASSMOBJ);
//==========================================================================
//
// CVAR dmflags2
//
// [RH] From Skull Tag. Some of these were already done as separate cvars
// (such as bfgaiming), but I collected them here like Skull Tag did.
// (such as bfgaiming), but I collected them here like Skull Tag does.
//
//==========================================================================
@ -349,7 +353,7 @@ void D_Display (bool screenshot)
// Refresh the console.
C_NewModeAdjust ();
// Reload crosshair if transitioned to a different size
crosshair = *crosshair;
crosshair.Callback ();
}
}
@ -362,7 +366,7 @@ void D_Display (bool screenshot)
setmodeneeded = false;
}
if (screen->Lock (TransArea >= *vid_bufferarea || screenshot))
if (screen->Lock (TransArea >= vid_bufferarea || screenshot))
{
SB_state = screen->GetPageCount ();
BorderNeedRefresh = screen->GetPageCount ();
@ -595,10 +599,8 @@ void D_DoomLoop ()
{
TryRunTics (); // will run at least one tic
}
// [RH] Use the consoleplayer's camera to update sounds
S_UpdateSounds (players[consoleplayer].camera); // move positional sounds
// Update display, next frame, with current state.
D_Display (false);
}
@ -1183,12 +1185,13 @@ static EIWADType IdentifyVersion (void)
CheckIWADinEnvDir (value + 1, wads);
}
}
#ifdef UNIX
#ifdef unix
else if (*value == '~' && (*(value + 1) == 0 || *(value + 1) == '/'))
{
homepath = GetUserFile (*(value + 1) ? value + 2 : value + 1);
CheckIWAD (homepath, wads);
delete[] homepath;
homepath = NULL;
}
#endif
else
@ -1223,7 +1226,7 @@ static EIWADType IdentifyVersion (void)
pickwad = 0;
if (!iwadparmfound && numwads > 1 && *queryiwad)
if (!iwadparmfound && numwads > 1 && queryiwad)
{
pickwad = I_PickIWad (wads, numwads);
}
@ -1256,7 +1259,7 @@ static const char *BaseFileSearch (const char *file, const char *ext)
if (!FileExists (file))
{
#ifndef UNIX
#ifndef unix
sprintf (wad, "%s%s", progdir, file);
if (!FileExists (wad))
{
@ -1386,6 +1389,11 @@ void D_DoomMain (void)
else
I_FatalError ("Cannot find zdoom.wad");
M_LoadDefaults (); // load before initing other systems
I_SetTitleString (IWADTypeNames[IdentifyVersion ()]);
GameConfig->DoGameSetup (GameNames[gameinfo.gametype]);
C_ExecCmdLineParams (); // [RH] do all +set commands on the command line
// [RH] zvox.wad - A wad I had intended to be automatically generate
// from Q2's pak0.pak so the female and cyborg player could have
// voices. I never got around to writing the utility to do it, though.
@ -1393,13 +1401,8 @@ void D_DoomMain (void)
if (wad)
D_AddFile (wad);
M_LoadDefaults (); // load before initing other systems
I_SetTitleString (IWADTypeNames[IdentifyVersion ()]);
GameConfig->DoGameSetup (GameNames[gameinfo.gametype]);
C_ExecCmdLineParams (); // [RH] do all +set commands on the command line
// [RH] Add any .wad files in the skins directory
#ifdef UNIX
#ifdef unix
sprintf (file, "%sskins", SHARE_DIR);
#else
sprintf (file, "%sskins", progdir);
@ -1436,7 +1439,7 @@ void D_DoomMain (void)
}
}
delete files;
W_InitMultipleFiles (&wadfiles);
// [RH] Initialize localizable strings.
@ -1513,7 +1516,7 @@ void D_DoomMain (void)
bglobal.wanted_botnum = bglobal.getspawned->NumArgs();
}
flags = *dmflags;
flags = dmflags;
if (Args.CheckParm ("-nomonsters")) flags |= DF_NO_MONSTERS;
if (Args.CheckParm ("-respawn")) flags |= DF_MONSTERS_RESPAWN;
@ -1581,7 +1584,7 @@ void D_DoomMain (void)
if (devparm)
Printf (GStrings(D_DEVSTR));
#ifndef UNIX
#ifndef unix
if (Args.CheckParm("-cdrom"))
{
Printf (GStrings(D_CDROM));
@ -1620,7 +1623,7 @@ void D_DoomMain (void)
// Check for -file in shareware
if (modifiedgame && (gameinfo.flags & GI_SHAREWARE))
I_FatalError ("You cannot -file with the shareware version. Register!");
Printf ("Init miscellaneous info.\n");
M_Init ();
@ -1631,7 +1634,7 @@ void D_DoomMain (void)
P_Init ();
Printf ("Setting up sound.\n");
S_Init ((int)*snd_sfxvolume /* *8 */, (int)*snd_musicvolume /* *8*/ );
S_Init ();
I_FinishClockCalibration ();

View file

@ -295,11 +295,7 @@ unsigned NetbufferChecksum (int len)
c = 0x1234567;
// FIXME -endianess?
//#ifdef NORMALUNIX
// return 0; // byte order problems
//#endif
// FIXME -endianess? [RH] Is endian-ness still a problem?
l = (len - myoffsetof(doomdata_t, retransmitfrom))/4;
for (i=0 ; i<l ; i++)
c += ((unsigned *)&netbuffer->retransmitfrom)[i] * (i+1);
@ -481,7 +477,7 @@ void GetPackets (void)
nodeingame[netnode] = false;
playeringame[netconsole] = false;
if (*deathmatch)
if (deathmatch)
{
Printf ("%s left the game with %d frags\n",
players[netconsole].userinfo.netname,
@ -1331,7 +1327,7 @@ void Net_DoCommand (int type, byte **stream, int player)
{
byte which = ReadByte (stream);
FWeaponInfo **infos = (players[player].powers[pw_weaponlevel2]
&& *deathmatch) ? wpnlev2info : wpnlev1info;
&& deathmatch) ? wpnlev2info : wpnlev1info;
if (which < NUMWEAPONS
&& which != players[player].readyweapon
@ -1400,13 +1396,11 @@ void Net_DoCommand (int type, byte **stream, int player)
{
paused = 0;
S_ResumeSound ();
I_ResumeMouse ();
}
else
{
paused = player + 1;
S_PauseSound ();
I_PauseMouse ();
}
BorderNeedRefresh = screen->GetPageCount ();
break;

View file

@ -51,4 +51,4 @@ void D_DoServerInfoChange (byte **stream);
void D_WriteUserInfoStrings (int player, byte **stream, bool compact=false);
void D_ReadUserInfoStrings (int player, byte **stream, bool update);
#endif //__D_CLIENTINFO_H__
#endif //__D_CLIENTINFO_H__

View file

@ -75,17 +75,17 @@ void D_SetupUserInfo (void)
for (i = 0; i < MAXPLAYERS; i++)
memset (&players[i].userinfo, 0, sizeof(userinfo_t));
strncpy (coninfo->netname, *name, MAXPLAYERNAME);
coninfo->team = *team;
coninfo->aimdist = abs ((int)(*autoaim * (float)ANGLE_1));
strncpy (coninfo->netname, name, MAXPLAYERNAME);
coninfo->team = team;
coninfo->aimdist = abs ((int)(autoaim * (float)ANGLE_1));
if (coninfo->aimdist > ANGLE_1*32)
{
coninfo->aimdist = ANGLE_1*32;
}
coninfo->color = *color;
coninfo->skin = R_FindSkin (*skin);
coninfo->gender = D_GenderToInt (*gender);
coninfo->neverswitch = *neverswitchonpickup;
coninfo->color = color;
coninfo->skin = R_FindSkin (skin);
coninfo->gender = D_GenderToInt (gender);
coninfo->neverswitch = neverswitchonpickup;
R_BuildPlayerTranslation (consoleplayer, coninfo->color);
}
@ -96,12 +96,12 @@ void D_UserInfoChanged (FBaseCVar *cvar)
if (cvar == &autoaim)
{
if (*autoaim < 0.0f)
if (autoaim < 0.0f)
{
autoaim = 0.0f;
return;
}
else if (*autoaim > 5000.0f)
else if (autoaim > 5000.0f)
{
autoaim = 5000.f;
return;
@ -403,7 +403,7 @@ FArchive &operator<< (FArchive &arc, userinfo_t &info)
CCMD (playerinfo)
{
if (argc < 2)
if (argv.argc() < 2)
{
int i;

View file

@ -185,7 +185,6 @@ public:
int jumpTics; // delay the next jump for a moment
int respawn_time; // [RH] delay respawning until this tic
fixed_t oldvelocity[3]; // [RH] Used for falling damage
AActor *camera; // [RH] Whose eyes this player sees through
int air_finished; // [RH] Time when you start drowning

View file

@ -322,4 +322,4 @@ void SkipChunk (byte **stream)
len = ReadLong (stream);
stream += len + (len & 1);
}
}

View file

@ -145,4 +145,4 @@ void WriteLong (int val, byte **stream);
void WriteFloat (float val, byte **stream);
void WriteString (const char *string, byte **stream);
#endif //__D_PROTOCOL_H__
#endif //__D_PROTOCOL_H__

587
src/decallib.cpp Normal file
View file

@ -0,0 +1,587 @@
#include "decallib.h"
#include "sc_man.h"
#include "w_wad.h"
#include "v_video.h"
#include "v_palette.h"
#include "cmdlib.h"
#include "m_random.h"
#include "weightedlist.h"
FDecalLib DecalLibrary;
// A decal group holds multiple decals and returns one randomly
// when GetDecal() is called.
class FDecalGroup : public FDecalBase
{
friend class FDecalLib;
public:
FDecalGroup () : Choices (pr_decalchoice) {}
FDecal *GetDecal ();
void AddDecal (FDecalBase *decal, WORD weight)
{
Choices.AddEntry (decal, weight);
}
private:
TWeightedList<FDecalBase *> Choices;
};
struct FDecalLib::FTranslation
{
FTranslation (DWORD start, DWORD end);
FTranslation *LocateTranslation (DWORD start, DWORD end);
DWORD StartColor, EndColor;
FTranslation *Next;
BYTE PalRemap[256];
};
static const char *DecalKeywords[] =
{
"x-scale",
"y-scale",
"pic",
"solid",
"add",
"translucent",
"flipx",
"flipy",
"randomflipx",
"randomflipy",
"fullbright",
"fuzzy",
"shade",
"colors",
NULL
};
enum
{
DECAL_XSCALE,
DECAL_YSCALE,
DECAL_PIC,
DECAL_SOLID,
DECAL_ADD,
DECAL_TRANSLUCENT,
DECAL_FLIPX,
DECAL_FLIPY,
DECAL_RANDOMFLIPX,
DECAL_RANDOMFLIPY,
DECAL_FULLBRIGHT,
DECAL_FUZZY,
DECAL_SHADE,
DECAL_COLORS
};
FDecal *FDecalBase::GetDecal ()
{
return NULL;
}
FDecalLib::FDecalLib ()
{
Root = NULL;
Translations = NULL;
}
FDecalLib::~FDecalLib ()
{
Clear ();
}
void FDecalLib::Clear ()
{
FTranslation *trans;
DelTree (Root);
Root = NULL;
trans = Translations;
while (trans != NULL)
{
FTranslation *next = trans->Next;
delete trans;
trans = next;
}
}
void FDecalLib::DelTree (FDecalBase *root)
{
if (root != NULL)
{
DelTree (root->Left);
DelTree (root->Right);
delete root;
}
}
void FDecalLib::ReadAllDecals ()
{
int lump, lastlump = 0;
while ((lump = W_FindLump ("DECALDEF", &lastlump)) != -1)
{
SC_OpenLumpNum (lump, "DECALDEF");
ReadDecals ();
SC_Close ();
}
}
void FDecalLib::ReadDecals ()
{
while (SC_GetString ())
{
if (SC_Compare ("decal"))
{
ParseDecal ();
}
else if (SC_Compare ("decalgroup"))
{
ParseDecalGroup ();
}
else if (SC_Compare ("generator"))
{
ParseGenerator ();
}
else
{
SC_ScriptError (NULL);
}
}
}
BYTE FDecalLib::GetDecalID ()
{
SC_MustGetString ();
if (!IsNum (sc_String))
{
SC_UnGet ();
return 0;
}
else
{
unsigned long num = strtoul (sc_String, NULL, 10);
if (num < 1 || num > 255)
{
SC_ScriptError ("Decal ID must be between 1 and 255");
}
return (BYTE)num;
}
}
void FDecalLib::ParseDecal ()
{
char decalName[64];
byte decalNum;
FDecal newdecal;
int code;
SC_MustGetString ();
strcpy (decalName, sc_String);
decalNum = GetDecalID ();
SC_MustGetStringName ("{");
memset (&newdecal, 0, sizeof(newdecal));
newdecal.PicNum = 0xffff;
newdecal.ScaleX = newdecal.ScaleY = 63;
newdecal.RenderFlags = RF_WALLSPRITE;
newdecal.RenderStyle = STYLE_Normal;
newdecal.Alpha = 0x8000;
for (;;)
{
SC_GetString ();
if (SC_Compare ("}"))
{
AddDecal (decalName, decalNum, newdecal);
break;
}
switch ((code = SC_MustMatchString (DecalKeywords)))
{
case DECAL_XSCALE:
case DECAL_YSCALE:
SC_MustGetNumber ();
if (--sc_Number < 0)
sc_Number = 0;
if (sc_Number > 255)
sc_Number = 255;
if (code == DECAL_XSCALE)
newdecal.ScaleX = sc_Number;
else
newdecal.ScaleY = sc_Number;
break;
case DECAL_PIC:
SC_MustGetString ();
newdecal.PicNum = R_CheckTileNumForName (sc_String, TILE_Patch);
break;
case DECAL_SOLID:
newdecal.RenderStyle = STYLE_Normal;
break;
case DECAL_ADD:
SC_MustGetFloat ();
newdecal.Alpha = (WORD)(32768.f * sc_Float);
newdecal.RenderStyle = STYLE_Add;
break;
case DECAL_TRANSLUCENT:
SC_MustGetFloat ();
newdecal.Alpha = (WORD)(32768.f * sc_Float);
newdecal.RenderStyle = STYLE_Translucent;
break;
case DECAL_FLIPX:
newdecal.RenderFlags |= RF_XFLIP;
break;
case DECAL_FLIPY:
newdecal.RenderFlags |= RF_YFLIP;
break;
case DECAL_RANDOMFLIPX:
newdecal.RenderFlags |= FDecal::DECAL_RandomFlipX;
break;
case DECAL_RANDOMFLIPY:
newdecal.RenderFlags |= FDecal::DECAL_RandomFlipY;
break;
case DECAL_FULLBRIGHT:
newdecal.RenderFlags |= RF_FULLBRIGHT;
break;
case DECAL_FUZZY:
newdecal.RenderStyle = STYLE_Fuzzy;
break;
case DECAL_SHADE:
SC_MustGetString ();
newdecal.RenderStyle = STYLE_Shaded;
newdecal.ShadeColor = V_GetColor (NULL, sc_String);
newdecal.ShadeColor |=
ColorMatcher.Pick (RPART(newdecal.ShadeColor),
GPART(newdecal.ShadeColor), BPART(newdecal.ShadeColor)) << 24;
break;
case DECAL_COLORS:
DWORD startcolor, endcolor;
SC_MustGetString (); startcolor = V_GetColor (NULL, sc_String);
SC_MustGetString (); endcolor = V_GetColor (NULL, sc_String);
newdecal.Translation = GenerateTranslation (startcolor, endcolor)->PalRemap;
break;
}
}
}
void FDecalLib::ParseDecalGroup ()
{
char groupName[64];
BYTE decalNum;
FDecalBase *targetDecal;
FDecalGroup *group;
SC_MustGetString ();
strcpy (groupName, sc_String);
decalNum = GetDecalID ();
SC_MustGetStringName ("{");
group = new FDecalGroup;
for (;;)
{
SC_GetString ();
if (SC_Compare ("}"))
{
group->Name = copystring (groupName);
AddDecal (group);
break;
}
targetDecal = ScanTreeForName (sc_String, Root);
if (targetDecal == NULL)
{
const char *arg = sc_String;
SC_ScriptError ("%s has not been defined", &arg);
}
SC_MustGetNumber ();
group->AddDecal (targetDecal, sc_Number);
}
}
void FDecalLib::ParseGenerator ()
{
const TypeInfo *type;
FDecalBase *decal;
AActor *actor;
// Get name of generator (actor)
SC_MustGetString ();
type = TypeInfo::FindType (sc_String);
if (type == NULL || type->ActorInfo == NULL)
{
const char *eekMsg = "%s is not an actor.";
const char *args[2];
args[0] = sc_String;
if (type == NULL)
{
type = TypeInfo::IFindType (sc_String);
if (type != NULL)
{
args[1] = type->Name + 1;
eekMsg = "%s is not an actor.\nDid you mean %s?";
}
}
SC_ScriptError (eekMsg, args);
}
actor = (AActor *)type->ActorInfo->Defaults;
// Get name of generated decal
SC_MustGetString ();
decal = ScanTreeForName (sc_String, Root);
if (decal == NULL)
{
const char *arg = sc_String;
SC_ScriptError ("%s has not been defined.", &arg);
}
actor->DecalGenerator = decal;
}
void FDecalLib::AddDecal (const char *name, byte num, const FDecal &decal)
{
FDecal *newDecal = new FDecal;
*newDecal = decal;
newDecal->Name = copystring (name);
newDecal->SpawnID = num;
AddDecal (newDecal);
}
void FDecalLib::AddDecal (FDecalBase *decal)
{
FDecalBase *node = Root, **prev = &Root;
int num = decal->SpawnID;
decal->SpawnID = 0;
while (node != NULL)
{
int lexx = stricmp (decal->Name, node->Name);
if (lexx == 0)
{
break;
}
else if (lexx < 0)
{
prev = &node->Left;
node = node->Left;
}
else
{
prev = &node->Right;
node = node->Right;
}
}
if (node == NULL)
{
decal->SpawnID = 0;
*prev = decal;
decal->Left = NULL;
decal->Right = NULL;
}
else
{
decal->Left = node->Left;
decal->Right = node->Right;
*prev = decal;
delete node;
}
if (num != 0)
{
FDecalBase *spawner = ScanTreeForNum (num, Root);
if (spawner != NULL)
{
spawner->SpawnID = 0;
}
decal->SpawnID = num;
}
}
const FDecal *FDecalLib::GetDecalByNum (byte num) const
{
if (num == 0)
{
return NULL;
}
return ScanTreeForNum (num, Root)->GetDecal ();
}
const FDecal *FDecalLib::GetDecalByName (const char *name) const
{
if (name == NULL)
{
return NULL;
}
return ScanTreeForName (name, Root)->GetDecal ();
}
FDecalBase *FDecalLib::ScanTreeForNum (const BYTE num, FDecalBase *root)
{
while (root != NULL)
{
if (root->SpawnID == num)
{
break;
}
ScanTreeForNum (num, root->Left);
root = root->Right; // Avoid tail-recursion
}
return root;
}
FDecalBase *FDecalLib::ScanTreeForName (const char *name, FDecalBase *root)
{
while (root != NULL)
{
int lexx = stricmp (name, root->Name);
if (lexx == 0)
{
break;
}
else if (lexx < 0)
{
root = root->Left;
}
else
{
root = root->Right;
}
}
return root;
}
FDecalLib::FTranslation *FDecalLib::GenerateTranslation (DWORD start, DWORD end)
{
FTranslation *trans;
if (Translations != NULL)
{
trans = Translations->LocateTranslation (start, end);
}
else
{
trans = NULL;
}
if (trans == NULL)
{
trans = new FTranslation (start, end);
trans->Next = Translations;
Translations = trans;
}
return trans;
}
FDecalBase::FDecalBase ()
{
Name = NULL;
}
FDecalBase::~FDecalBase ()
{
if (Name != NULL)
delete[] Name;
}
void FDecal::ApplyToActor (AActor *actor) const
{
if (RenderStyle == STYLE_Shaded)
{
actor->SetShade (ShadeColor);
}
actor->translation = Translation;
actor->xscale = ScaleX;
actor->yscale = ScaleY;
actor->picnum = PicNum;
actor->alpha = Alpha << 1;
actor->RenderStyle = RenderStyle;
actor->renderflags = (RenderFlags & ~(DECAL_RandomFlipX|DECAL_RandomFlipY)) |
(actor->renderflags & (RF_RELMASK|RF_CLIPMASK|RF_INVISIBLE|RF_ONESIDED));
if (RenderFlags & (DECAL_RandomFlipX|DECAL_RandomFlipY))
{
actor->renderflags ^= P_Random (pr_decal) &
((RenderFlags & (DECAL_RandomFlipX|DECAL_RandomFlipY)) >> 8);
}
}
FDecal *FDecal::GetDecal ()
{
return this;
}
FDecalLib::FTranslation::FTranslation (DWORD start, DWORD end)
{
DWORD ri, gi, bi, rs, gs, bs;
PalEntry *first, *last;
int i;
StartColor = start;
EndColor = end;
Next = NULL;
first = (PalEntry *)&StartColor;
last = (PalEntry *)&EndColor;
ri = first->r << 24;
gi = first->g << 24;
bi = first->b << 24;
rs = last->r << 24;
gs = last->g << 24;
bs = last->b << 24;
rs = (rs - ri) / 255;
gs = (gs - ri) / 255;
bs = (bs - bi) / 255;
for (i = 1; i < 256; i++, ri += rs, gi += gs, bi += bs)
{
PalRemap[i] = ColorMatcher.Pick (ri >> 24, gi >> 24, bi >> 24);
}
PalRemap[0] = PalRemap[1];
}
FDecalLib::FTranslation *FDecalLib::FTranslation::LocateTranslation (DWORD start, DWORD end)
{
FTranslation *trans = this;
do
{
if (start == trans->StartColor && end == trans->EndColor)
{
return trans;
}
trans = trans->Next;
} while (trans != NULL);
return trans;
}
FDecal *FDecalGroup::GetDecal ()
{
FDecalBase *decal = Choices.PickEntry ();
FDecalBase *remember;
// Repeatedly GetDecal() until the result is the same, since
// the choice might be another FDecalGroup.
do
{
remember = decal;
decal = decal->GetDecal ();
} while (decal != remember);
return static_cast<FDecal *>(decal);
}

View file

@ -6,28 +6,41 @@
#include "doomtype.h"
class AActor;
class FDecal;
class FDecal
class FDecalBase
{
friend class FDecalLib;
private:
FDecal ();
~FDecal ();
FDecal *Left, *Right;
public:
virtual FDecal *GetDecal ();
protected:
FDecalBase ();
virtual ~FDecalBase ();
FDecalBase *Left, *Right;
char *Name;
BYTE SpawnID;
};
class FDecal : public FDecalBase
{
friend class FDecalLib;
public:
FDecal () : Translation (NULL) {}
void ApplyToActor (AActor *actor) const;
FDecal *GetDecal ();
DWORD ShadeColor;
BYTE *Translation;
char *Name;
BYTE ScaleX, ScaleY;
BYTE SpawnID, RenderStyle;
BYTE RenderStyle;
WORD PicNum;
WORD RenderFlags;
WORD Alpha; // same as (actor->alpha >> 1)
enum { DECAL_RandomFlipX = 0x100, DECAL_RandomFlipY = 0x200 };
};
class FDecalLib
@ -42,20 +55,26 @@ public:
const FDecal *GetDecalByNum (byte num) const;
const FDecal *GetDecalByName (const char *name) const;
void AddDecal (const char *name, byte num, const FDecal &decal);
private:
struct FTranslation;
static void DelTree (FDecal *root);
static FDecal *ScanTreeForNum (const BYTE num, FDecal *root);
static FDecal *ScanTreeForName (const char *name, FDecal *root);
static void DelTree (FDecalBase *root);
static FDecalBase *ScanTreeForNum (const BYTE num, FDecalBase *root);
static FDecalBase *ScanTreeForName (const char *name, FDecalBase *root);
FTranslation *GenerateTranslation (DWORD start, DWORD end);
void AddDecal (const char *name, byte num, const FDecal &decal);
void AddDecal (FDecalBase *decal);
FDecal *Root;
BYTE GetDecalID ();
void ParseDecal ();
void ParseDecalGroup ();
void ParseGenerator ();
FDecalBase *Root;
FTranslation *Translations;
};
extern FDecalLib DecalLibrary;
#endif //__DECALLIB_H__
#endif //__DECALLIB_H__

View file

@ -121,7 +121,7 @@ CCMD (dumpclasses)
int shown, omitted;
bool showall = true;
if (argc > 1)
if (argv.argc() > 1)
{
root = TypeInfo::IFindType (argv[1]);
if (root == NULL)
@ -131,7 +131,7 @@ CCMD (dumpclasses)
}
if (stricmp (argv[1], "Actor") == 0)
{
if (argc < 3 || stricmp (argv[2], "all") != 0)
if (argv.argc() < 3 || stricmp (argv[2], "all") != 0)
{
showall = false;
}

View file

@ -116,9 +116,8 @@ enum ESkillLevels
#define TELEFOGHEIGHT (gameinfo.telefogheight)
//
// DOOM keyboard definition.
// This is the stuff configured by Setup.Exe.
// Most key data are simple ascii (uppercased).
// DOOM keyboard definition. Everything below 0x100 matches
// a DirectInput key code.
//
#define KEY_RIGHTARROW 0xcd // DIK_RIGHT
#define KEY_LEFTARROW 0xcb // DIK_LEFT
@ -142,7 +141,7 @@ enum ESkillLevels
#define KEY_F12 0x58 // DIK_F12
#define KEY_BACKSPACE 0x0e // DIK_BACK
#define KEY_PAUSE 0xff
#define KEY_PAUSE 0xc5 // DIK_PAUSE
#define KEY_EQUALS 0x0d // DIK_EQUALS
#define KEY_MINUS 0x0c // DIK_MINUS
@ -166,8 +165,10 @@ enum ESkillLevels
#define KEY_MOUSE2 0x101
#define KEY_MOUSE3 0x102
#define KEY_MOUSE4 0x103
#define KEY_MWHEELUP 0x104
#define KEY_MWHEELDOWN 0x105
#define KEY_MOUSE5 0x104
#define KEY_MOUSE6 0x105
#define KEY_MWHEELUP 0x106
#define KEY_MWHEELDOWN 0x107
#define KEY_JOY1 0x108
#define KEY_JOY2 0x109
@ -208,7 +209,8 @@ enum ESkillLevels
#define DF_NO_HEALTH 1 // Do not spawn health items (DM)
#define DF_NO_ITEMS 2 // Do not spawn powerups (DM)
#define DF_WEAPONS_STAY 4 // Leave weapons around after pickup (DM)
#define DF_YES_FALLING 8 // Falling too far hurts
#define DF_FORCE_FALLINGZD 8 // Falling too far hurts (old ZDoom style)
#define DF_FORCE_FALLINGHX 16 // Falling too far hurts (Hexen style)
//#define DF_INVENTORY_ITEMS 32 // Wait for player to use powerups when picked up
#define DF_SAME_LEVEL 64 // Stay on the same map when someone exits (DM)
#define DF_SPAWN_FARTHEST 128 // Spawn players as far as possible from other players (DM)
@ -223,6 +225,7 @@ enum ESkillLevels
#define DF_NO_JUMP 65536 // Don't allow jumping
#define DF_NO_FREELOOK 131072 // Don't allow freelook
#define DF_RESPAWN_SUPER 262144 // Respawn invulnerability and invisibility
#define DF_NO_PASSMOBJ 524288 // Pretend every actor is infinitely tall
// [BC] More dmflags. w00p!
//#define DF2_YES_IMPALING 1 // Player gets implaed on MF2_IMPALE items

View file

@ -65,4 +65,4 @@ CUSTOM_CVAR (String, language, "auto", CVAR_ARCHIVE)
}
// [RH] Network arbitrator
int Net_Arbitrator = 0;
int Net_Arbitrator = 0;

View file

@ -98,17 +98,9 @@ EXTERN_CVAR (Float, teamdamage)
// -------------------------
// 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_CVAR (Int, snd_sfxvolume) // maximum volume for sound
EXTERN_CVAR (Int, snd_musicvolume) // maximum volume for music
EXTERN_CVAR (Float, snd_sfxvolume) // maximum volume for sound
EXTERN_CVAR (Float, snd_musicvolume) // maximum volume for music
// -------------------------

View file

@ -26,6 +26,14 @@
#include <limits.h>
#ifdef _WIN32
// VC++ does not define PATH_MAX, but the Windows headers do define MAX_PATH.
// However, we want to avoid including the Windows headers in most of the
// source files, so we can't use it. So define PATH_MAX to be what MAX_PATH
// currently is:
#define PATH_MAX 260
#endif
#ifndef __BYTEBOOL__
#define __BYTEBOOL__
// [RH] Some windows includes already define this
@ -35,13 +43,6 @@ typedef int BOOL;
typedef unsigned char byte;
#endif
#ifdef __GNUC__
#define GCCPRINTF(stri,firstargi) __attribute__((format(printf,stri,firstargi)))
#else
#define GCCPRINTF(a,b)
#endif
#if defined(_MSC_VER) || defined(__WATCOMC__)
#define STACK_ARGS __cdecl
#else
@ -90,8 +91,8 @@ typedef DWORD BITFIELD;
typedef SDWORD fixed_t;
typedef DWORD dsfixed_t; // fixedpt used by span drawer
#define FIXED_MAX 0x7fffffff
#define FIXED_MIN 0x80000000
#define FIXED_MAX (signed)(0x7fffffff)
#define FIXED_MIN (signed)(0x80000000)
#ifndef NOASM
#ifndef USEASM
@ -103,6 +104,18 @@ typedef DWORD dsfixed_t; // fixedpt used by span drawer
#endif
#endif
#ifdef __GNUC__
#define GCCPRINTF(stri,firstargi) __attribute__((format(printf,stri,firstargi)))
#define GCCFORMAT(stri) __attribute__((format(printf,stri,0)))
#define GCCNOWARN __attribute__((unused))
#else
#define GCCPRINTF(a,b)
#define GCCFORMAT(a)
#define GCCNOWARN
#endif
// [RH] This gets used all over; define it here:
int STACK_ARGS Printf (int printlevel, const char *, ...) GCCPRINTF(2,3);
int STACK_ARGS Printf (const char *, ...) GCCPRINTF(1,2);

View file

@ -65,4 +65,4 @@ protected:
DMovingCeiling ();
};
#endif //__DSECTOREFFECT_H__
#endif //__DSECTOREFFECT_H__

View file

@ -130,7 +130,7 @@ void DThinker::ChangeStatNum (int statnum)
statnum = MAX_STATNUM;
}
Remove ();
if (ObjectFlags & OF_JustSpawned)
if ((ObjectFlags & OF_JustSpawned) && statnum >= STAT_FIRST_THINKING)
{
FreshThinkers[statnum].AddTail (this);
}
@ -334,4 +334,4 @@ DThinker *it;
void mine ()
{
it = new DThinker;
}
}

View file

@ -112,4 +112,4 @@ public:
}
};
#endif //__DTHINKER_H__
#endif //__DTHINKER_H__

View file

@ -43,4 +43,4 @@ public:
CFatalError(const char *message) : CDoomError(message) {}
};
#endif //__ERRORS_H__
#endif //__ERRORS_H__

View file

@ -601,7 +601,7 @@ void F_CastDrawer (void)
sprdef = &sprites[castsprite];
sprframe = &sprdef->spriteframes[caststate->GetFrame()];
lump = sprframe->lump[0];
flip = (BOOL)sprframe->flip[0];
flip = (BOOL)sprframe->flip & 1;
patch = (patch_t *)W_CacheLumpNum (lump, PU_CACHE);
if (flip)

View file

@ -376,7 +376,7 @@ int wipe_exitFade (int ticks)
int wipe_StartScreen (void)
{
CurrentWipeType = *wipetype;
CurrentWipeType = wipetype;
if (CurrentWipeType < 0)
CurrentWipeType = 0;
else if (CurrentWipeType >= wipe_NUMWIPES)

View file

@ -9,9 +9,20 @@
#include "cmdlib.h"
#include "i_system.h"
#include "c_cvars.h"
#include "c_dispatch.h"
#include "d_player.h"
#include "dobject.h"
#define NEW_OBJ ((BYTE)1)
#define NEW_CLS_OBJ ((BYTE)2)
#define OLD_OBJ ((BYTE)3)
#define NULL_OBJ ((BYTE)4)
#define NEW_PLYR_OBJ ((BYTE)5)
#define NEW_PLYR_CLS_OBJ ((BYTE)6)
#define NEW_NAME ((BYTE)27)
#define OLD_NAME ((BYTE)28)
#define NIL_NAME ((BYTE)33)
#ifdef __BIG_ENDIAN__
#define SWAP_WORD(x)
#define SWAP_DWORD(x)
@ -231,7 +242,7 @@ void FCompressedFile::Implode ()
byte *oldbuf = m_Buffer;
int r;
if (!*nofilecompression && !m_NoCompress)
if (!nofilecompression && !m_NoCompress)
{
outlen = OUT_LEN(len);
do
@ -248,12 +259,12 @@ void FCompressedFile::Implode ()
// If the data could not be compressed, store it as-is.
if (r != Z_OK || outlen >= len)
{
DPrintf ("cfile could not be deflated\n");
DPrintf ("cfile could not be compress\n");
outlen = 0;
}
else
{
DPrintf ("cfile shrank from %u to %u bytes\n", len, outlen);
DPrintf ("cfile shrank from %lu to %lu bytes\n", len, outlen);
}
}
else
@ -407,7 +418,7 @@ void FCompressedMemFile::Serialize (FArchive &arc)
{
if (m_ImplodedBuffer == NULL)
{
I_Error ("FCompressedMemFile must be deflated before storing");
I_Error ("FCompressedMemFile must be compressed before storing");
}
arc.Write (ZSig, 4);
@ -485,7 +496,10 @@ FArchive::FArchive (FFile &file)
}
m_ClassCount = 0;
for (i = 0; i < EObjectHashSize; i++)
{
m_ObjectHash[i] = ~0;
m_NameHash[i] = NameMap::NO_INDEX;
}
}
FArchive::~FArchive ()
@ -513,7 +527,7 @@ void FArchive::Close ()
{
m_File->Close ();
m_File = NULL;
DPrintf ("Processed %d objects\n", m_ObjectCount);
DPrintf ("Processed %ld objects\n", m_ObjectCount);
}
}
@ -548,6 +562,72 @@ DWORD FArchive::ReadCount ()
return count;
}
void FArchive::WriteName (const char *name)
{
BYTE id;
if (name == NULL)
{
id = NIL_NAME;
Write (&id, 1);
}
else
{
DWORD index = FindName (name);
if (index != NameMap::NO_INDEX)
{
id = OLD_NAME;
Write (&id, 1);
WriteCount (index);
}
else
{
AddName (name);
id = NEW_NAME;
Write (&id, 1);
WriteString (name);
}
}
}
const char *FArchive::ReadName ()
{
BYTE id;
operator<< (id);
if (id == NIL_NAME)
{
return NULL;
}
else if (id == OLD_NAME)
{
DWORD index = ReadCount ();
if (index >= m_Names.Size())
{
I_Error ("Name %lu has not been read yet\n", index);
}
return &m_NameStorage[m_Names[index].StringStart];
}
else if (id == NEW_NAME)
{
DWORD index;
DWORD size = ReadCount ();
char *str;
index = m_NameStorage.Reserve (size);
str = &m_NameStorage[index];
Read (str, size-1);
str[size-1] = 0;
AddName (index);
return str;
}
else
{
I_Error ("Expected a name but got something else\n");
return NULL;
}
}
void FArchive::WriteString (const char *str)
{
if (str == NULL)
@ -717,13 +797,6 @@ FArchive &FArchive::SerializeObject (DObject *&object, TypeInfo *type)
return ReadObject (object, type);
}
#define NEW_OBJ ((BYTE)1)
#define NEW_CLS_OBJ ((BYTE)2)
#define OLD_OBJ ((BYTE)3)
#define NULL_OBJ ((BYTE)4)
#define NEW_PLYR_OBJ ((BYTE)5)
#define NEW_PLYR_CLS_OBJ ((BYTE)6)
FArchive &FArchive::WriteObject (DObject *obj)
{
player_t *player;
@ -828,7 +901,7 @@ FArchive &FArchive::ReadObject (DObject* &obj, TypeInfo *wanttype)
index = ReadCount ();
if (index >= m_ObjectCount)
{
I_Error ("Object reference too high (%u; max is %u)\n", index, m_ObjectCount);
I_Error ("Object reference too high (%lu; max is %lu)\n", index, m_ObjectCount);
}
obj = (DObject *)m_ObjectMap[index].object;
break;
@ -888,6 +961,52 @@ FArchive &FArchive::ReadObject (DObject* &obj, TypeInfo *wanttype)
return *this;
}
DWORD FArchive::AddName (const char *name)
{
DWORD index;
size_t hash = MakeKey (name) % EObjectHashSize;
index = FindName (name, hash);
if (index == NameMap::NO_INDEX)
{
size_t namelen = strlen (name) + 1;
size_t strpos = m_NameStorage.Reserve (namelen);
NameMap mapper = { strpos, m_NameHash[hash] };
memcpy (&m_NameStorage[strpos], name, namelen);
m_NameHash[hash] = index = m_Names.Push (mapper);
}
return index;
}
DWORD FArchive::AddName (size_t start)
{
size_t hash = MakeKey (&m_NameStorage[start]) % EObjectHashSize;
NameMap mapper = { start, m_NameHash[hash] };
return (m_NameHash[hash] = m_Names.Push (mapper));
}
DWORD FArchive::FindName (const char *name) const
{
return FindName (name, MakeKey (name) % EObjectHashSize);
}
DWORD FArchive::FindName (const char *name, size_t bucket) const
{
size_t map = m_NameHash[bucket];
while (map != NameMap::NO_INDEX)
{
const NameMap *mapping = &m_Names[map];
if (strcmp (name, &m_NameStorage[mapping->StringStart]) == 0)
{
return map;
}
map = mapping->HashNext;
}
return map;
}
DWORD FArchive::WriteClass (const TypeInfo *info)
{
if (m_ClassCount >= TypeInfo::m_NumTypes)
@ -930,7 +1049,7 @@ const TypeInfo *FArchive::ReadClass ()
return TypeInfo::m_Types[i];
}
}
I_Error ("Unknown class '%s'\n", typeName);
I_Error ("Unknown class '%s'\n", typeName.val);
return NULL;
}
@ -951,7 +1070,7 @@ const TypeInfo *FArchive::ReadStoredClass (const TypeInfo *wanttype)
DWORD index = ReadCount ();
if (index >= m_ClassCount)
{
I_Error ("Class reference too high (%u; max is %u)\n", index, m_ClassCount);
I_Error ("Class reference too high (%lu; max is %lu)\n", index, m_ClassCount);
}
const TypeInfo *type = m_TypeMap[index].toCurrent;
if (!type->IsDescendantOf (wanttype))
@ -990,7 +1109,7 @@ DWORD FArchive::MapObject (const DObject *obj)
DWORD FArchive::HashObject (const DObject *obj) const
{
return (DWORD)((ptrdiff_t)obj % EObjectHashSize);
return (DWORD)((size_t)obj % EObjectHashSize);
}
DWORD FArchive::FindObjectIndex (const DObject *obj) const
@ -1046,4 +1165,4 @@ void FArchive::UserReadClass (const TypeInfo *&type)
type = NULL;
break;
}
}
}

View file

@ -4,6 +4,7 @@
#include <stdio.h>
#include "doomtype.h"
#include "dobject.h"
#include "tarray.h"
class DObject;
@ -137,6 +138,9 @@ virtual void Read (void *mem, unsigned int len);
FArchive& WriteObject (DObject *obj);
FArchive& ReadObject (DObject *&obj, TypeInfo *wanttype);
void WriteName (const char *name);
const char *ReadName (); // The returned name disappears with the archive, unlike strings
inline FArchive& operator<< (char &c) { return operator<< ((BYTE &)c); }
inline FArchive& operator<< (SBYTE &c) { return operator<< ((BYTE &)c); }
inline FArchive& operator<< (SWORD &s) { return operator<< ((WORD &)s); }
@ -159,6 +163,10 @@ protected:
const TypeInfo *ReadClass (const TypeInfo *wanttype);
const TypeInfo *ReadStoredClass (const TypeInfo *wanttype);
DWORD HashObject (const DObject *obj) const;
DWORD AddName (const char *name);
DWORD AddName (size_t start); // Name has already been added to storage
DWORD FindName (const char *name) const;
DWORD FindName (const char *name, size_t bucket) const;
bool m_Persistent; // meant for persistent storage (disk)?
bool m_Loading; // extracting objects?
@ -168,13 +176,15 @@ protected:
DWORD m_ObjectCount; // # of objects currently serialized
DWORD m_MaxObjectCount;
DWORD m_ClassCount; // # of unique classes currently serialized
struct TypeMap
{
const TypeInfo *toCurrent; // maps archive type index to execution type index
DWORD toArchive; // maps execution type index to archive type index
enum { NO_INDEX = 0xffffffff};
enum { NO_INDEX = 0xffffffff };
} *m_TypeMap;
struct ObjectMap
{
const DObject *object;
@ -182,6 +192,16 @@ protected:
} *m_ObjectMap;
size_t m_ObjectHash[EObjectHashSize];
struct NameMap
{
DWORD StringStart; // index into m_NameStorage
DWORD HashNext; // next in hash bucket
enum { NO_INDEX = 0xffffffff };
};
TArray<NameMap> m_Names;
TArray<char> m_NameStorage;
size_t m_NameHash[EObjectHashSize];
private:
FArchive (const FArchive &src) {}
void operator= (const FArchive &src) {}

1912
src/fmodsound/i_music.cpp Normal file

File diff suppressed because it is too large Load diff

View file

@ -40,4 +40,4 @@ bool I_SetSongPosition (long handle, int order);
// Is the song still playing?
bool I_QrySongPlaying (long handle);
#endif //__I_MUSIC_H__
#endif //__I_MUSIC_H__

View file

@ -1,12 +1,17 @@
/* i_sound.cpp: System interface for sound, uses fmod.dll
*/
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <mmsystem.h>
#include "resource.h"
extern HWND Window;
extern HINSTANCE hInstance;
#else
#define FALSE 0
#define TRUE 1
#endif
#include <stdio.h>
#include <stdlib.h>
@ -46,7 +51,10 @@ static const char *OutputNames[] =
"No sound",
"Windows Multimedia",
"DirectSound",
"A3D"
"A3D",
"OSS (Open Sound System)",
"ESD (Enlightenment Sound Daemon)",
"ALSA (Advanced Linux Sound Architecture)"
};
static const char *MixerNames[] =
{
@ -60,7 +68,7 @@ static const char *MixerNames[] =
"Quality PPro MMX"
};
EXTERN_CVAR (Int, snd_sfxvolume)
EXTERN_CVAR (Float, snd_sfxvolume)
CVAR (Int, snd_samplerate, 44100, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
CVAR (Int, snd_buffersize, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
CVAR (Int, snd_driver, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
@ -69,7 +77,7 @@ CVAR (Bool, snd_3d, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
// killough 2/21/98: optionally use varying pitched sounds
CVAR (Bool, snd_pitched, false, CVAR_ARCHIVE)
#define PITCH(f,x) (*snd_pitched ? ((f)*(x))/128 : (f))
#define PITCH(f,x) (snd_pitched ? ((f)*(x))/128 : (f))
// Maps sfx channels onto FMOD channels
static struct ChanMap
@ -484,26 +492,32 @@ void UncheckSound (sfxinfo_t *sfx, BOOL looped)
//
// SFX API
//
void I_SetSfxVolume (int volume)
//==========================================================================
//
// CVAR snd_sfxvolume
//
// Maximum volume of a sound effect.
//==========================================================================
CUSTOM_CVAR (Float, snd_sfxvolume, 0.5f, CVAR_ARCHIVE|CVAR_GLOBALCONFIG|CVAR_NOINITCALL)
{
// volume range is 0-15, but FMOD wants 0-255
FSOUND_SetSFXMasterVolume ((volume << 4) | volume);
// FMOD apparently resets absolute volume channels when setting master vol
snd_musicvolume.Callback ();
if (self < 0.f)
self = 0.f;
else if (self > 1.f)
self = 1.f;
else
{
FSOUND_SetSFXMasterVolume ((int)(self * 255.f));
// FMOD apparently resets absolute volume channels when setting master vol
snd_musicvolume.Callback ();
}
}
//
// 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.
//
// vol range is 0-255
// sep range is 0-255, -1 for surround, -2 for full vol middle
//
long I_StartSound (sfxinfo_t *sfx, int vol, int sep, int pitch, int channel, BOOL looping)
{
if (_nosound)
@ -739,6 +753,7 @@ void I_LoadSound (sfxinfo_t *sfx)
}
}
#ifdef _WIN32
// [RH] Dialog procedure for the error dialog that appears if FMOD
// could not be initialized for some reason.
BOOL CALLBACK InitBoxCallback (HWND hwndDlg, UINT message, WPARAM wParam, LPARAM lParam)
@ -757,6 +772,7 @@ BOOL CALLBACK InitBoxCallback (HWND hwndDlg, UINT message, WPARAM wParam, LPARAM
}
return FALSE;
}
#endif
static char FModLog (char success)
{
@ -773,8 +789,16 @@ static char FModLog (char success)
void I_InitSound ()
{
#ifdef _WIN32
static const FSOUND_OUTPUTTYPES outtypes[2] =
{ FSOUND_OUTPUT_DSOUND, FSOUND_OUTPUT_WINMM };
const int maxtrynum = 2;
#else
static const FSOUND_OUTPUTTYPES outtypes[3] =
{ FSOUND_OUTPUT_DSOUND, FSOUND_OUTPUT_WINMM, FSOUND_OUTPUT_DSOUND };
{ FSOUND_OUTPUT_ALSA, FSOUND_OUTPUT_OSS, FSOUND_OUTPUT_ESD };
const int maxtrynum = 3;
#endif
bool trya3d = false;
/* Get command line options: */
_nosound = !!Args.CheckParm ("-nosfx") || !!Args.CheckParm ("-nosound");
@ -786,35 +810,52 @@ void I_InitSound ()
int outindex;
int trynum;
bool trya3d = false;
if (stricmp (*snd_output, "dsound") == 0)
#ifdef _WIN32
if (stricmp (snd_output, "dsound") == 0)
{
outindex = 0;
}
else if (stricmp (*snd_output, "winmm") == 0)
else if (stricmp (snd_output, "winmm") == 0)
{
outindex = 1;
}
else
{
outindex = (OSPlatform == os_WinNT) ? 1 : 0;
if (*snd_3d || stricmp (*snd_output, "a3d") == 0)
if (stricmp (snd_output, "a3d") == 0)
{
trya3d = true;
}
}
#else
if (stricmp (snd_output, "oss") == 0)
{
outindex = 2;
}
else if (stricmp (snd_output, "esd") == 0 ||
stricmp (snd_output, "esound") == 0)
{
outindex = 1;
}
else
{
outindex = 0;
}
#endif
Printf ("I_InitSound: Initializing FMOD\n");
#ifdef _WIN32
FSOUND_SetHWND (Window);
#endif
while (!_nosound)
{
trynum = 0;
while (trynum < 2)
while (trynum < maxtrynum)
{
long outtype = trya3d ? FSOUND_OUTPUT_A3D
: outtypes[outindex+trynum];
: outtypes[(outindex+trynum) % maxtrynum];
Printf (" Setting %s output", OutputNames[outtype]);
FModLog (FSOUND_SetOutput (outtype));
@ -828,12 +869,12 @@ void I_InitSound ()
}
else
{
trynum++;
++trynum;
}
continue;
}
Printf (" Setting driver %d", *snd_driver);
FModLog (FSOUND_SetDriver (*snd_driver));
FModLog (FSOUND_SetDriver (snd_driver));
if (FSOUND_GetOutput() != outtype)
{
Printf (" Output changed to %s\n Trying driver 0",
@ -842,14 +883,15 @@ void I_InitSound ()
FModLog (FSOUND_SetDriver (0));
}
// FSOUND_GetDriverCaps (FSOUND_GetDriver(), &DriverCaps);
if (*snd_buffersize)
if (snd_buffersize)
{
Printf (" Setting buffer size %d", *snd_buffersize);
FModLog (FSOUND_SetBufferSize (*snd_buffersize));
FModLog (FSOUND_SetBufferSize (snd_buffersize));
}
//FSOUND_SetMinHardwareChannels (32);
Printf (" Initialization");
if (!FModLog (FSOUND_Init (*snd_samplerate, 64, 0)))
if (!FModLog (FSOUND_Init (snd_samplerate, 64,
FSOUND_INIT_USEDEFAULTMIDISYNTH)))
{
if (trya3d)
{
@ -869,6 +911,7 @@ void I_InitSound ()
{ // Initialized successfully
break;
}
#ifdef _WIN32
// If sound cannot be initialized, give the user some options.
switch (DialogBox (hInstance,
MAKEINTRESOURCE(IDD_FMODINITFAILED),
@ -883,13 +926,17 @@ void I_InitSound ()
exit (0);
break;
}
#else
Printf ("Sound init failed. Using nosound.\n");
_nosound = true;
#endif
}
if (!_nosound)
{
Enable_FSOUND_IO_Loader ();
OutputType = FSOUND_GetOutput ();
if (*snd_3d)
if (snd_3d)
{
Sound3D = true;
//FSOUND_Reverb_SetEnvironment (FSOUND_PRESET_GENERIC);
@ -904,6 +951,7 @@ void I_InitSound ()
{
Sound3D = false;
}
snd_sfxvolume.Callback ();
static bool didthis = false;
if (!didthis)

View file

@ -23,7 +23,11 @@
#ifndef __I_SOUND__
#define __I_SOUND__
#ifdef _WIN32
#include <io.h>
#else
#include <unistd.h>
#endif
#include "doomdef.h"

View file

@ -239,7 +239,7 @@ void A_BrainExplode (AActor *self)
void A_BrainDie (AActor *self)
{
// [RH] If noexit, then don't end the level.
if ((*deathmatch || *alwaysapplydmflags) && (*dmflags & DF_NO_EXIT))
if ((deathmatch || alwaysapplydmflags) && (dmflags & DF_NO_EXIT))
return;
G_ExitLevel (0);
@ -337,7 +337,7 @@ ABossTarget *DBrainState::GetTarget ()
{
Easy = !Easy;
if (*gameskill <= sk_easy && !Easy)
if (gameskill <= sk_easy && !Easy)
return NULL;
ABossTarget *target;

View file

@ -49,7 +49,7 @@ const char *AInvulnerabilitySphere::PickupMessage ()
bool AInvulnerabilitySphere::ShouldRespawn ()
{
return Super::ShouldRespawn () && (*dmflags & DF_RESPAWN_SUPER);
return Super::ShouldRespawn () && (dmflags & DF_RESPAWN_SUPER);
}
// Soulsphere --------------------------------------------------------------
@ -172,7 +172,7 @@ public:
}
virtual bool ShouldRespawn ()
{
return Super::ShouldRespawn () && (*dmflags & DF_RESPAWN_SUPER);
return Super::ShouldRespawn () && (dmflags & DF_RESPAWN_SUPER);
}
protected:
virtual bool TryPickup (AActor *toucher)

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