ZDoom 1.16.

This commit is contained in:
Randy Heit 1998-12-22 00:00:00 +00:00
parent 25f75d4f53
commit 8dc4dd899f
165 changed files with 28224 additions and 21846 deletions

View file

@ -29,6 +29,7 @@
#include "doomdef.h" #include "doomdef.h"
#include "st_stuff.h" #include "st_stuff.h"
#include "p_local.h" #include "p_local.h"
#include "p_lnspec.h"
#include "w_wad.h" #include "w_wad.h"
#include "m_cheat.h" #include "m_cheat.h"
@ -55,7 +56,8 @@ static int Background, YourColor, WallColor, TSWallColor,
FDWallColor, CDWallColor, ThingColor, FDWallColor, CDWallColor, ThingColor,
SecretWallColor, GridColor, XHairColor, SecretWallColor, GridColor, XHairColor,
NotSeenColor, NotSeenColor,
Key1Color, Key2Color, Key3Color; LockedColor,
AlmostBackground;
cvar_t *am_backcolor, cvar_t *am_backcolor,
*am_yourcolor, *am_yourcolor,
@ -67,12 +69,7 @@ cvar_t *am_backcolor,
*am_gridcolor, *am_gridcolor,
*am_xhaircolor, *am_xhaircolor,
*am_notseencolor, *am_notseencolor,
*am_key1color, *am_lockedcolor,
*am_key2color,
*am_key3color,
*am_key4color,
*am_key5color,
*am_key6color,
*am_usecustomcolors, *am_usecustomcolors,
*am_ovyourcolor, *am_ovyourcolor,
*am_ovwallcolor, *am_ovwallcolor,
@ -499,9 +496,7 @@ void AM_initColors (BOOL overlayed)
ThingColor = V_GetColorFromString (palette, am_ovthingcolor->string); ThingColor = V_GetColorFromString (palette, am_ovthingcolor->string);
FDWallColor = FDWallColor =
CDWallColor = CDWallColor =
Key1Color = LockedColor = V_GetColorFromString (palette, am_ovotherwallscolor->string);
Key2Color =
Key3Color = V_GetColorFromString (palette, am_ovotherwallscolor->string);
NotSeenColor = NotSeenColor =
TSWallColor = V_GetColorFromString (palette, am_ovunseencolor->string); TSWallColor = V_GetColorFromString (palette, am_ovunseencolor->string);
} else if (am_usecustomcolors->value) { } else if (am_usecustomcolors->value) {
@ -517,24 +512,39 @@ void AM_initColors (BOOL overlayed)
GridColor = V_GetColorFromString (palette, am_gridcolor->string); GridColor = V_GetColorFromString (palette, am_gridcolor->string);
XHairColor = V_GetColorFromString (palette, am_xhaircolor->string); XHairColor = V_GetColorFromString (palette, am_xhaircolor->string);
NotSeenColor = V_GetColorFromString (palette, am_notseencolor->string); NotSeenColor = V_GetColorFromString (palette, am_notseencolor->string);
Key1Color = V_GetColorFromString (palette, am_key1color->string); LockedColor = V_GetColorFromString (palette, am_lockedcolor->string);
Key2Color = V_GetColorFromString (palette, am_key2color->string); {
Key3Color = V_GetColorFromString (palette, am_key3color->string); unsigned int ba = V_GetColorFromString (NULL, am_backcolor->string);
int r = RPART(ba) - 16;
int g = GPART(ba) - 16;
int b = BPART(ba) - 16;
if (r < 0)
r += 32;
if (g < 0)
g += 32;
if (b < 0)
b += 32;
if (screens[0].is8bit)
AlmostBackground = BestColor (DefaultPalette->basecolors, r, g , b, DefaultPalette->numcolors);
else
AlmostBackground = MAKERGB(r,g,b);
}
} else { } else {
/* Use colors corresponding to the original Doom's */ /* Use colors corresponding to the original Doom's */
Background = V_GetColorFromString (palette, "0000 0000 0000"); Background = V_GetColorFromString (palette, "00 00 00");
AlmostBackground = V_GetColorFromString (palette, "10 10 10");
SecretWallColor = SecretWallColor =
WallColor = V_GetColorFromString (palette, "fcfc 0000 0000"); WallColor = V_GetColorFromString (palette, "fc 00 00");
TSWallColor = V_GetColorFromString (palette, "8080 8080 8080"); TSWallColor = V_GetColorFromString (palette, "80 80 80");
FDWallColor = V_GetColorFromString (palette, "bcbc 7878 4848"); FDWallColor = V_GetColorFromString (palette, "bc 78 48");
Key1Color = LockedColor =
Key2Color = CDWallColor = V_GetColorFromString (palette, "fc fc 00");
Key3Color = ThingColor = V_GetColorFromString (palette, "74 fc 6c");
CDWallColor = V_GetColorFromString (palette, "fcfc fcfc 0000"); GridColor = V_GetColorFromString (palette, "4c 4c 4c");
ThingColor = V_GetColorFromString (palette, "7474 fcfc 6c6c"); XHairColor = V_GetColorFromString (palette, "80 80 80");
GridColor = V_GetColorFromString (palette, "4c4c 4c4c 4c4c"); NotSeenColor = V_GetColorFromString (palette, "6c 6c 6c");
XHairColor = V_GetColorFromString (palette, "8080 8080 8080");
NotSeenColor = V_GetColorFromString (palette, "6c6c 6c6c 6c6c");
} }
} }
@ -546,9 +556,9 @@ void AM_loadPics(void)
int i; int i;
char namebuf[9]; char namebuf[9];
for (i=0;i<10;i++) { for (i = 0; i < 10; i++) {
sprintf(namebuf, "AMMNUM%d", i); sprintf(namebuf, "AMMNUM%d", i);
marknums[i] = W_CacheLumpName(namebuf, PU_STATIC); marknums[i] = W_CacheLumpName (namebuf, PU_STATIC);
} }
} }
@ -556,8 +566,8 @@ void AM_unloadPics(void)
{ {
int i; int i;
for (i=0;i<10;i++) for (i = 0; i < 10; i++)
Z_ChangeTag(marknums[i], PU_CACHE); Z_ChangeTag (marknums[i], PU_CACHE);
} }
void AM_clearMarks(void) void AM_clearMarks(void)
@ -596,7 +606,7 @@ void AM_Stop (void)
{ {
static event_t st_notify = { 0, ev_keyup, AM_MSGEXITED }; static event_t st_notify = { 0, ev_keyup, AM_MSGEXITED };
AM_unloadPics(); AM_unloadPics ();
automapactive = false; automapactive = false;
ST_Responder(&st_notify); ST_Responder(&st_notify);
stopped = true; stopped = true;
@ -663,7 +673,7 @@ void Cmd_Togglemap (void *plyr, int argc, char **argv)
// //
// Handle events (user inputs) in automap mode // Handle events (user inputs) in automap mode
// //
BOOL AM_Responder( event_t* ev ) BOOL AM_Responder (event_t *ev)
{ {
int rc; int rc;
static int cheatstate=0; static int cheatstate=0;
@ -736,7 +746,7 @@ BOOL AM_Responder( event_t* ev )
} }
} }
if (!deathmatch->value && cht_CheckCheat(&cheat_amap, (char)ev->data2)) { if (!deathmatch->value && cht_CheckCheat(&cheat_amap, (char)ev->data2)) {
rc = false; rc = true; // [RH] Eat last keypress of cheat sequence
cheating = (cheating+1) % 3; cheating = (cheating+1) % 3;
} }
} }
@ -773,7 +783,7 @@ BOOL AM_Responder( event_t* ev )
// //
// Zooming // Zooming
// //
void AM_changeWindowScale(void) void AM_changeWindowScale (void)
{ {
// Change the scaling multipliers // Change the scaling multipliers
scale_mtof = FixedMul(scale_mtof, mtof_zoommul); scale_mtof = FixedMul(scale_mtof, mtof_zoommul);
@ -999,7 +1009,7 @@ AM_drawFline
static fuck = 0; static fuck = 0;
// For debugging only // For debugging only
if ( fl->a.x < 0 || fl->a.x >= f_w if ( fl->a.x < 0 || fl->a.x >= f_w
|| fl->a.y < 0 || fl->a.y >= f_h || fl->a.y < 0 || fl->a.y >= f_h
|| fl->b.x < 0 || fl->b.x >= f_w || fl->b.x < 0 || fl->b.x >= f_w
|| fl->b.y < 0 || fl->b.y >= f_h) || fl->b.y < 0 || fl->b.y >= f_h)
@ -1087,17 +1097,14 @@ AM_drawFline
// //
// Clip lines, draw visible part sof lines. // Clip lines, draw visible parts of lines.
// //
void void AM_drawMline (mline_t *ml, int color)
AM_drawMline
( mline_t* ml,
int color )
{ {
static fline_t fl; static fline_t fl;
if (AM_clipMline(ml, &fl)) if (AM_clipMline (ml, &fl))
AM_drawFline(&fl, color); // draws it on frame buffer using fb coords AM_drawFline (&fl, color); // draws it on frame buffer using fb coords
} }
@ -1185,21 +1192,9 @@ void AM_drawWalls(void)
AM_drawMline(&l, SecretWallColor); AM_drawMline(&l, SecretWallColor);
else else
AM_drawMline(&l, WallColor); AM_drawMline(&l, WallColor);
} else if (lines[i].special == 26 || } else if (lines[i].special == Door_LockedRaise ||
lines[i].special == 32 || lines[i].special == ACS_LockedExecute) {
lines[i].special == 133 || AM_drawMline (&l, LockedColor); // [RH] locked special
lines[i].special == 99) {
AM_drawMline (&l, Key1Color); // blue key doors
} else if (lines[i].special == 28 ||
lines[i].special == 33 ||
lines[i].special == 135 ||
lines[i].special == 13) {
AM_drawMline (&l, Key2Color); // red key doors
} else if (lines[i].special == 27 ||
lines[i].special == 34 ||
lines[i].special == 137 ||
lines[i].special == 136) {
AM_drawMline (&l, Key3Color); // yellow key doors
} else if (lines[i].backsector->floorheight } else if (lines[i].backsector->floorheight
!= lines[i].frontsector->floorheight) { != lines[i].frontsector->floorheight) {
AM_drawMline(&l, FDWallColor); // floor level change AM_drawMline(&l, FDWallColor); // floor level change
@ -1329,15 +1324,15 @@ void AM_drawPlayers(void)
continue; continue;
if (p->powers[pw_invisibility]) if (p->powers[pw_invisibility])
color = 246; // *close* to black color = AlmostBackground;
else if (screens[0].is8bit) else if (screens[0].is8bit)
color = BestColor (DefaultPalette->basecolors, color = BestColor (DefaultPalette->basecolors,
RPART(p->userinfo->color), RPART(p->userinfo.color),
GPART(p->userinfo->color), GPART(p->userinfo.color),
BPART(p->userinfo->color), BPART(p->userinfo.color),
DefaultPalette->numcolors); DefaultPalette->numcolors);
else else
color = p->userinfo->color; color = p->userinfo.color;
pt.x = p->mo->x; pt.x = p->mo->x;
pt.y = p->mo->y; pt.y = p->mo->y;

View file

@ -22,6 +22,8 @@
#ifndef __AMMAP_H__ #ifndef __AMMAP_H__
#define __AMMAP_H__ #define __AMMAP_H__
#include "d_event.h"
// Used by ST StatusBar stuff. // Used by ST StatusBar stuff.
#define AM_MSGHEADER (('a'<<24)+('m'<<16)) #define AM_MSGHEADER (('a'<<24)+('m'<<16))
#define AM_MSGENTERED (AM_MSGHEADER | ('e'<<8)) #define AM_MSGENTERED (AM_MSGHEADER | ('e'<<8))

View file

@ -3,6 +3,7 @@
#include <stdio.h> #include <stdio.h>
#include <time.h> #include <time.h>
#include "version.h"
#include "c_consol.h" #include "c_consol.h"
#include "c_cmds.h" #include "c_cmds.h"
#include "c_dispch.h" #include "c_dispch.h"
@ -11,23 +12,32 @@
#include "doomstat.h" #include "doomstat.h"
#include "d_englsh.h" #include "d_englsh.h"
#include "sounds.h"
#include "s_sound.h" #include "s_sound.h"
#include "g_game.h" #include "g_game.h"
#include "d_items.h" #include "d_items.h"
#include "p_inter.h" #include "p_inter.h"
#include "z_zone.h" #include "z_zone.h"
#include "w_wad.h" #include "w_wad.h"
#include "g_level.h"
extern FILE *Logfile; extern FILE *Logfile;
cvar_t *sv_cheats; cvar_t *sv_cheats;
struct CmdDispatcher CmdList[] = { struct CmdDispatcher CmdList[] = {
{ "error", Cmd_Error },
{ "endgame", Cmd_Endgame },
{ "mem", Cmd_Mem },
{ "pings", Cmd_Pings },
{ "skins", Cmd_Skins },
{ "turn180", Cmd_Turn180 },
{ "puke", Cmd_Puke },
{ "spynext", Cmd_SpyNext }, { "spynext", Cmd_SpyNext },
{ "spyprev", Cmd_SpyPrev }, { "spyprev", Cmd_SpyPrev },
{ "messagemode", Cmd_MessageMode }, { "messagemode", Cmd_MessageMode },
{ "say", Cmd_Say }, { "say", Cmd_Say },
{ "messagemode2", Cmd_MessageMode2 },
{ "say_team", Cmd_Say_Team },
{ "limits", Cmd_Limits }, { "limits", Cmd_Limits },
{ "screenshot", Cmd_Screenshot }, { "screenshot", Cmd_Screenshot },
{ "vid_setmode", Cmd_Vid_SetMode }, { "vid_setmode", Cmd_Vid_SetMode },
@ -42,10 +52,14 @@ struct CmdDispatcher CmdList[] = {
{ "sizedown", Cmd_Sizedown }, { "sizedown", Cmd_Sizedown },
{ "sizeup", Cmd_Sizeup }, { "sizeup", Cmd_Sizeup },
{ "impulse", Cmd_Impulse }, { "impulse", Cmd_Impulse },
{ "weapnext", Cmd_WeapNext },
{ "weapprev", Cmd_WeapPrev },
{ "alias", Cmd_Alias }, { "alias", Cmd_Alias },
{ "cmdlist", Cmd_Cmdlist }, { "cmdlist", Cmd_Cmdlist },
{ "unbind", Cmd_Unbind }, { "unbind", Cmd_Unbind },
{ "unbindall", Cmd_Unbindall }, { "unbindall", Cmd_Unbindall },
{ "undoublebind", Cmd_UnDoubleBind },
{ "doublebind", Cmd_DoubleBind },
{ "bind", Cmd_Bind }, { "bind", Cmd_Bind },
{ "binddefaults", Cmd_BindDefaults }, { "binddefaults", Cmd_BindDefaults },
{ "dumpheap", Cmd_DumpHeap }, { "dumpheap", Cmd_DumpHeap },
@ -69,7 +83,7 @@ struct CmdDispatcher CmdList[] = {
{ "logfile", Cmd_Logfile }, { "logfile", Cmd_Logfile },
{ "noclip", Cmd_Noclip }, { "noclip", Cmd_Noclip },
{ "notarget", Cmd_Notarget }, { "notarget", Cmd_Notarget },
{ "quit", I_Quit }, { "quit", Cmd_Quit },
{ "set", Cmd_Set }, { "set", Cmd_Set },
{ "menu_main", Cmd_Menu_Main }, { "menu_main", Cmd_Menu_Main },
{ "menu_load", Cmd_Menu_Load }, { "menu_load", Cmd_Menu_Load },
@ -89,6 +103,8 @@ struct CmdDispatcher CmdList[] = {
{ "bumpgamma", Cmd_Bumpgamma }, { "bumpgamma", Cmd_Bumpgamma },
{ "togglemessages", Cmd_ToggleMessages }, { "togglemessages", Cmd_ToggleMessages },
{ "stop", Cmd_Stop }, { "stop", Cmd_Stop },
{ "soundlist", Cmd_Soundlist },
{ "soundlinks", Cmd_Soundlinks },
{ NULL } { NULL }
}; };
@ -107,6 +123,11 @@ BOOL CheckCheatmode (void)
} }
} }
void Cmd_Quit (player_t *plyr, int argc, char **argv)
{
exit (0);
}
void Cmd_ChangeMus (player_t *plyr, int argc, char **argv) void Cmd_ChangeMus (player_t *plyr, int argc, char **argv)
{ {
if (argc > 1) { if (argc > 1) {
@ -341,23 +362,50 @@ void Cmd_Logfile (player_t *plyr, int argc, char **argv)
void Cmd_Limits (player_t *plyr, int argc, char **argv) void Cmd_Limits (player_t *plyr, int argc, char **argv)
{ {
extern int MaxDeathmatchStarts; extern int MaxDeathmatchStarts;
extern int MaxPlats;
extern int MaxCeilings;
extern int MaxSpecialCross; extern int MaxSpecialCross;
extern int MaxDrawSegs; extern int MaxDrawSegs;
extern int MaxSegs; extern int MaxSegs;
extern int MaxVisPlanes;
extern int MaxVisSprites; extern int MaxVisSprites;
extern int maxopenings; extern int maxopenings;
Printf_Bold ("Note that the following values are\n" Printf_Bold ("Note that the following values are\n"
"dynamic and will increase as needed.\n\n"); "dynamic and will increase as needed.\n\n");
Printf ("MaxCeilings: %u\n", MaxCeilings);
Printf ("MaxDeathmatchStarts: %u\n", MaxDeathmatchStarts); Printf ("MaxDeathmatchStarts: %u\n", MaxDeathmatchStarts);
Printf ("MaxDrawSegs: %u\n", MaxDrawSegs); Printf ("MaxDrawSegs: %u\n", MaxDrawSegs);
Printf ("MaxPlats: %u\n", MaxPlats);
Printf ("MaxSegs: %u\n", MaxSegs); Printf ("MaxSegs: %u\n", MaxSegs);
Printf ("MaxSpecialCross: %u\n", MaxSpecialCross); Printf ("MaxSpecialCross: %u\n", MaxSpecialCross);
Printf ("MaxVisPlanes: %u\n", MaxVisPlanes);
Printf ("MaxVisSprites: %u\n", MaxVisSprites); Printf ("MaxVisSprites: %u\n", MaxVisSprites);
} Printf ("MaxOpeninings: %u\n", maxopenings);
}
BOOL P_StartScript (void *who, void *where, int script, char *map, int lineSide,
int arg0, int arg1, int arg2, int always);
void Cmd_Puke (player_t *plyr, int argc, char **argv)
{
if (argc < 2 || argc > 5) {
Printf (" puke <script> [arg1] [arg2] [arg3]\n");
} else {
int script = atoi (argv[1]);
int arg0=0, arg1=0, arg2=0;
if (argc > 2) {
arg0 = atoi (argv[2]);
if (argc > 3) {
arg1 = atoi (argv[3]);
if (argc > 4) {
arg2 = atoi (argv[4]);
}
}
}
P_StartScript (plyr->mo, NULL, script, level.mapname, 0, arg0, arg1, arg2, false);
}
}
void Cmd_Error (player_t *plyr, int argc, char **argv)
{
char *text = BuildString (argc - 1, argv + 1);
char *textcopy = Z_Malloc (strlen (text) + 1, PU_LEVEL, 0);
strcpy (textcopy, text);
free (text);
I_Error (textcopy);
}

View file

@ -55,12 +55,10 @@ void UnlatchCVars (void)
void SetCVar (cvar_t *var, char *value) void SetCVar (cvar_t *var, char *value)
{ {
// TODO: Find a better way to not send serverinfo updates if (var->flags & CVAR_LATCH && gamestate != GS_FULLCONSOLE && gamestate != GS_STARTUP) {
// when not inside a game.
if (var->flags & CVAR_LATCH) {
var->modified = true; var->modified = true;
var->u.latched_string = copystring (value); var->u.latched_string = copystring (value);
} else if (var->flags & CVAR_SERVERINFO && gamestate > -1) { } else if (var->flags & CVAR_SERVERINFO && gamestate != GS_STARTUP) {
if (netgame && consoleplayer != 0) { if (netgame && consoleplayer != 0) {
Printf ("Only player 1 can change %s\n", var->name); Printf ("Only player 1 can change %s\n", var->name);
return; return;
@ -85,6 +83,8 @@ void SetCVarFloat (cvar_t *var, float value)
SetCVar (var, string); SetCVar (var, string);
} }
int cvar_defflags;
cvar_t *cvar (char *var_name, char *value, int flags) cvar_t *cvar (char *var_name, char *value, int flags)
{ {
cvar_t *var, *dummy; cvar_t *var, *dummy;
@ -104,7 +104,7 @@ cvar_t *cvar (char *var_name, char *value, int flags)
CVars = var; CVars = var;
C_AddTabCommand (var_name); C_AddTabCommand (var_name);
} }
var->flags = flags; var->flags = flags | cvar_defflags;;
return var; return var;
} }

View file

@ -29,18 +29,7 @@ gamedir will hold progdir + the game directory (id1, id2, etc)
*/ */
char progdir[1024]; char progdir[1024];
void SetProgDir (void)
{
#ifdef _WIN32
GetModuleFileName (NULL, progdir, 1024);
*(strrchr (progdir, '\\') + 1) = 0;
FixPathSeperator (progdir);
#else
Printf ("SetProgDir: Rewrite this\n");
#endif
}
void FixPathSeperator (char *path) void FixPathSeperator (char *path)
{ {
@ -215,9 +204,27 @@ void DefaultExtension (char *path, char *extension)
Extract file parts Extract file parts
==================== ====================
*/ */
// FIXME: should include the slash, otherwise
// backing to an empty path will be wrong when appending a slash
void ExtractFilePath (char *path, char *dest)
{
char *src;
src = path + strlen(path) - 1;
//
// back up until a \ or the start
//
while (src != path && *(src-1) != '\\' && *(src-1) != '/')
src--;
memcpy (dest, path, src-path);
dest[src-path] = 0;
}
void ExtractFileBase (char *path, char *dest) void ExtractFileBase (char *path, char *dest)
{ {
char *src; char *src;
src = path + strlen(path) - 1; src = path + strlen(path) - 1;
@ -242,8 +249,8 @@ ParseNum / ParseHex
*/ */
int ParseHex (char *hex) int ParseHex (char *hex)
{ {
char *str; char *str;
int num; int num;
num = 0; num = 0;
str = hex; str = hex;
@ -285,7 +292,7 @@ BOOL IsNum (char *str)
BOOL result = true; BOOL result = true;
while (*str) { while (*str) {
if ((*str < '0') || (*str > '9')) { if (((*str < '0') || (*str > '9')) && (*str != '-')) {
result = false; result = false;
break; break;
} }

View file

@ -31,10 +31,10 @@ BOOL FileExists (char *filename);
extern char progdir[1024]; extern char progdir[1024];
void FixPathSeperator (char *path); void FixPathSeperator (char *path);
void SetProgDir (void);
void DefaultExtension (char *path, char *extension); void DefaultExtension (char *path, char *extension);
void ExtractFilePath (char *path, char *dest);
void ExtractFileBase (char *path, char *dest); void ExtractFileBase (char *path, char *dest);
int ParseHex (char *str); int ParseHex (char *str);

File diff suppressed because it is too large Load diff

View file

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

View file

@ -52,7 +52,7 @@ extern weaponinfo_t weaponinfo[NUMWEAPONS];
#define IT_ARMOR 4 #define IT_ARMOR 4
#define IT_KEY 8 #define IT_KEY 8
#define IT_ARTIFACT 16 // Don't auto-activate item (unused) #define IT_ARTIFACT 16 // Don't auto-activate item (unused)
#define IT_POWER 32 // Auto-activate item #define IT_POWERUP 32 // Auto-activate item
struct gitem_s struct gitem_s
{ {
@ -67,16 +67,18 @@ struct gitem_s
}; };
typedef struct gitem_s gitem_t; typedef struct gitem_s gitem_t;
extern gitem_t ItemList[]; extern int num_items;
extern gitem_t itemlist[];
void InitItems (void); void InitItems (void);
// FindItem // FindItem
gitem_t *GetItemByIndex (int index); gitem_t *GetItemByIndex (int index);
gitem_t *FindItemByClassname (char *classname); gitem_t *FindItemByClassname (const char *classname);
gitem_t *FindItem (char *pickup_name); gitem_t *FindItem (const char *pickup_name);
#define ITEM_INDEX(i) ((i)-ItemList) #define ITEM_INDEX(i) ((i)-itemlist)
#endif #endif

File diff suppressed because it is too large Load diff

View file

@ -22,7 +22,7 @@
// //
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#include "version.h"
#include "m_alloc.h" #include "m_alloc.h"
#include "m_menu.h" #include "m_menu.h"
#include "i_system.h" #include "i_system.h"
@ -34,7 +34,6 @@
#include "c_consol.h" #include "c_consol.h"
#include "d_netinf.h" #include "d_netinf.h"
#include "cmdlib.h" #include "cmdlib.h"
#include "sounds.h"
#include "s_sound.h" #include "s_sound.h"
#include "m_cheat.h" #include "m_cheat.h"
@ -71,6 +70,9 @@ BOOL remoteresend[MAXNETNODES]; // set when local needs tics
int resendto[MAXNETNODES]; // set when remote needs tics int resendto[MAXNETNODES]; // set when remote needs tics
int resendcount[MAXNETNODES]; int resendcount[MAXNETNODES];
unsigned int lastrecvtime[MAXPLAYERS]; // [RH] Used for pings
unsigned int currrecvtime[MAXPLAYERS];
int nodeforplayer[MAXPLAYERS]; int nodeforplayer[MAXPLAYERS];
int maketic; int maketic;
@ -288,6 +290,10 @@ void GetPackets (void)
netconsole = netbuffer->player & ~PL_DRONE; netconsole = netbuffer->player & ~PL_DRONE;
netnode = doomcom->remotenode; netnode = doomcom->remotenode;
// [RH] Get "ping" times
lastrecvtime[netconsole] = currrecvtime[netconsole];
currrecvtime[netconsole] = I_MSTime ();
// to save bytes, only the low byte of tic numbers are sent // to save bytes, only the low byte of tic numbers are sent
// Figure out what the rest of the bytes are // Figure out what the rest of the bytes are
@ -305,10 +311,10 @@ void GetPackets (void)
if (deathmatch->value) { if (deathmatch->value) {
Printf ("%s left the game with %d frags\n", Printf ("%s left the game with %d frags\n",
players[netconsole].userinfo->netname, players[netconsole].userinfo.netname,
players[netconsole].fragcount); players[netconsole].fragcount);
} else { } else {
Printf ("%s left the game\n", players[netconsole].userinfo->netname); Printf ("%s left the game\n", players[netconsole].userinfo.netname);
} }
if (demorecording) { if (demorecording) {
@ -492,11 +498,12 @@ void CheckAbort (void)
{ {
event_t *ev; event_t *ev;
int stoptic; int stoptic;
Printf (""); // [RH] Give the console a chance to redraw itself
stoptic = I_GetTime () + 2; stoptic = I_GetTime () + 2;
while (I_GetTime() < stoptic) while (I_GetTime() < stoptic)
I_StartTic (); I_StartTic ();
I_StartTic (); I_StartTic ();
for ( ; eventtail != eventhead for ( ; eventtail != eventhead
; eventtail = (++eventtail)&(MAXEVENTS-1) ) ; eventtail = (++eventtail)&(MAXEVENTS-1) )
@ -531,7 +538,7 @@ void D_ArbitrateNetStart (void)
nodesdetected[0] = 1; // Detect ourselves nodesdetected[0] = 1; // Detect ourselves
// [RH] Rewrote this loop based on Doom Legacy 1.11's code. // [RH] Rewrote this loop based on Doom Legacy 1.11's code.
Printf ("Waiting for %d more players...\n", doomcom->numnodes - 1); Printf ("Waiting for %d more player%s...\n", doomcom->numnodes - 1, (doomcom->numnodes == 2) ? "" : "s");
do { do {
CheckAbort (); CheckAbort ();
@ -569,7 +576,7 @@ void D_ArbitrateNetStart (void)
D_ReadUserInfoStrings (netbuffer->player, &stream, false); D_ReadUserInfoStrings (netbuffer->player, &stream, false);
Printf ("%s joined the game (node %d, player %d)\n", Printf ("%s joined the game (node %d, player %d)\n",
players[netbuffer->player].userinfo->netname, players[netbuffer->player].userinfo.netname,
doomcom->remotenode, doomcom->remotenode,
netbuffer->player); netbuffer->player);
} }
@ -644,7 +651,7 @@ void D_CheckNetGame (void)
// I_InitNetwork sets doomcom and netgame // I_InitNetwork sets doomcom and netgame
I_InitNetwork (); I_InitNetwork ();
if (doomcom->id != DOOMCOM_ID) if (doomcom->id != DOOMCOM_ID)
I_Error ("Doomcom buffer invalid!"); I_FatalError ("Doomcom buffer invalid!");
netbuffer = &doomcom->data; netbuffer = &doomcom->data;
consoleplayer = displayplayer = doomcom->consoleplayer; consoleplayer = displayplayer = doomcom->consoleplayer;
@ -652,36 +659,22 @@ void D_CheckNetGame (void)
// [RH] Setup user info // [RH] Setup user info
D_SetupUserInfo (); D_SetupUserInfo ();
UnlatchCVars ();
if (netgame) if (netgame)
D_ArbitrateNetStart (); D_ArbitrateNetStart ();
UnlatchCVars ();
{
char map[9];
strncpy (map, startmap, 8);
map[8] = 0;
Printf ("skill: %g deathmatch: %g map: %s dmflags: %i\n",
gameskill->value, deathmatch->value, map, dmflags);
}
// read values out of doomcom // read values out of doomcom
ticdup = doomcom->ticdup; ticdup = doomcom->ticdup;
maxsend = BACKUPTICS/(2*ticdup)-1; maxsend = BACKUPTICS/(2*ticdup)-1;
if (maxsend<1) if (maxsend<1)
maxsend = 1; maxsend = 1;
for (i=0 ; i<doomcom->numplayers ; i++) for (i = 0; i < doomcom->numplayers; i++)
playeringame[i] = true; playeringame[i] = true;
for (i=0 ; i<doomcom->numnodes ; i++) for (i = 0; i < doomcom->numnodes; i++)
nodeingame[i] = true; nodeingame[i] = true;
Printf ("player %i of %i (%i nodes)\n", Printf ("player %i of %i (%i nodes)\n",
consoleplayer+1, doomcom->numplayers, doomcom->numnodes); consoleplayer+1, doomcom->numplayers, doomcom->numnodes);
} }
@ -692,7 +685,7 @@ void D_CheckNetGame (void)
// //
void D_QuitNetGame (void) void D_QuitNetGame (void)
{ {
int i, j; int i, j;
if (debugfile) if (debugfile)
fclose (debugfile); fclose (debugfile);
@ -703,9 +696,9 @@ void D_QuitNetGame (void)
// send a bunch of packets for security // send a bunch of packets for security
netbuffer->player = consoleplayer; netbuffer->player = consoleplayer;
netbuffer->numtics = 0; netbuffer->numtics = 0;
for (i=0 ; i<4 ; i++) for (i = 0; i < 4; i++)
{ {
for (j=1 ; j<doomcom->numnodes ; j++) for (j = 1; j < doomcom->numnodes; j++)
if (nodeingame[j]) if (nodeingame[j])
HSendPacket (j, NCMD_EXIT, myoffsetof(doomdata_t,cmds)); HSendPacket (j, NCMD_EXIT, myoffsetof(doomdata_t,cmds));
I_WaitVBL (1); I_WaitVBL (1);
@ -938,16 +931,28 @@ void Net_DoCommand (int type, byte **stream, int player)
switch (type) { switch (type) {
case DEM_SAY: case DEM_SAY:
{ {
int who = ReadByte (stream); byte who = ReadByte (stream);
s = ReadString (stream); s = ReadString (stream);
if (!who || (who - 1) == consoleplayer) { if ((who == 0) || players[player].userinfo.team[0] == 0) {
Printf_Bold ("%s: %s\n", players[player].userinfo->netname, s); // Said to everyone
Printf_Bold ("%s: %s\n", players[player].userinfo.netname, s);
if (gamemode == commercial) if (gamemode == commercial) {
S_StartSound(ORIGIN_AMBIENT3, sfx_radio); S_StartSound (ORIGIN_AMBIENT3, "misc/chat", 60);
else } else {
S_StartSound(ORIGIN_AMBIENT3, sfx_tink); S_StartSound (ORIGIN_AMBIENT3, "misc/chat2", 60);
}
} else if (!stricmp (players[player].userinfo.team,
players[consoleplayer].userinfo.team)) {
// Said only to members of the player's team
Printf_Bold ("(%s): %s\n", players[player].userinfo.netname, s);
if (gamemode == commercial) {
S_StartSound (ORIGIN_AMBIENT3, "misc/chat", 60);
} else {
S_StartSound (ORIGIN_AMBIENT3, "misc/chat2", 60);
}
} }
} }
break; break;
@ -989,7 +994,7 @@ void Net_DoCommand (int type, byte **stream, int player)
strncpy (level.nextmap, s, 8); strncpy (level.nextmap, s, 8);
// Using LEVEL_NOINTERMISSION tends to throw the game out of sync. // Using LEVEL_NOINTERMISSION tends to throw the game out of sync.
level.flags |= LEVEL_CHANGEMAPCHEAT; level.flags |= LEVEL_CHANGEMAPCHEAT;
G_ExitLevel (); G_ExitLevel (0);
break; break;
case DEM_SUICIDE: case DEM_SUICIDE:
@ -1003,4 +1008,15 @@ void Net_DoCommand (int type, byte **stream, int player)
if (s) if (s)
free (s); free (s);
} }
// [RH] List ping times
void Cmd_Pings (void *plyr, int argc, char **argv)
{
int i;
for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i])
Printf ("% 4u %s\n", currrecvtime[i] - lastrecvtime[i],
players[i].userinfo.netname);
}

View file

@ -157,19 +157,23 @@ typedef struct player_s
// can be set to REDCOLORMAP for pain, etc. // can be set to REDCOLORMAP for pain, etc.
int fixedcolormap; int fixedcolormap;
// Player skin colorshift, // [RH] Amount to shift view horizontally (for earthquakes)
// 0-3 for which color to draw player. int xviewshift;
int colormap;
// Overlay view sprites (gun, etc). // Overlay view sprites (gun, etc).
pspdef_t psprites[NUMPSPRITES]; pspdef_t psprites[NUMPSPRITES];
// [RH] Pointer to a userinfo struct // [RH] A userinfo struct
userinfo_t *userinfo; userinfo_t userinfo;
// [RH] Tic when respawning is allowed // [RH] Tic when respawning is allowed
int respawn_time; int respawn_time;
// [RH] Used for calculating falling damage
fixed_t oldvelocity[3];
// [RH] Camera to use to draw view from. Normally same as mo
mobj_t *camera;
} player_t; } player_t;

View file

@ -280,7 +280,7 @@ void ReadTicCmd (ticcmd_t *tcmd, byte **stream, int player)
} }
static byte *lenspot; byte *lenspot;
// Write the header of an IFF chunk and leave space // Write the header of an IFF chunk and leave space
// for the length field. // for the length field.

View file

@ -30,11 +30,6 @@
// //
// Global parameters/defines. // Global parameters/defines.
// //
// DOOM version
enum { VERSION = 114 };
#define VERSIONSTR "114"
#define GAMEVER (0x010e)
// Game mode handling - identify IWAD version // Game mode handling - identify IWAD version
// to handle IWAD dependend animations etc. // to handle IWAD dependend animations etc.
@ -45,7 +40,7 @@ typedef enum
commercial, // DOOM 2 retail, E1 M34 commercial, // DOOM 2 retail, E1 M34
// DOOM 2 german edition not handled // DOOM 2 german edition not handled
retail, // DOOM 1 retail, E4, M36 retail, // DOOM 1 retail, E4, M36
indetermined // Well, no IWAD found. undetermined // Well, no IWAD found.
} GameMode_t; } GameMode_t;
@ -69,7 +64,6 @@ typedef enum
french, french,
german, german,
unknown unknown
} Language_t; } Language_t;
@ -77,36 +71,6 @@ typedef enum
// most parameter validation debugging code will not be compiled // most parameter validation debugging code will not be compiled
#define RANGECHECK #define RANGECHECK
// Do or do not use external soundserver.
// The sndserver binary to be run separately
// has been introduced by Dave Taylor.
// The integrated sound support is experimental,
// and unfinished. Default is synchronous.
// Experimental asynchronous timer based is
// handled by SNDINTR.
#define SNDSERV 1
//#define SNDINTR 1
// This one switches between MIT SHM (no proper mouse)
// and XFree86 DGA (mickey sampling). The original
// linuxdoom used SHM, which is default.
//#define X11_DGA 1
//
// For resize of screen, at start of game.
// It will not work dynamically, see visplanes.
//
#define BASE_WIDTH 320
// It is educational but futile to change this
// scaling e.g. to 2. Drawing of status bar,
// menues etc. is tied to the scale implied
// by the graphics.
#define SCREEN_MUL 1
#define INV_ASPECT_RATIO 0.625 // 0.75, ideally
// The maximum number of players, multiplayer/networking. // The maximum number of players, multiplayer/networking.
#define MAXPLAYERS 8 #define MAXPLAYERS 8
@ -121,7 +85,10 @@ typedef enum
GS_LEVEL, GS_LEVEL,
GS_INTERMISSION, GS_INTERMISSION,
GS_FINALE, GS_FINALE,
GS_DEMOSCREEN GS_DEMOSCREEN,
GS_FULLCONSOLE, // [RH] Fullscreen console
GS_HIDECONSOLE, // [RH] The menu just did something that should hide fs console
GS_STARTUP // [RH] Console is fullscreen, and game is just starting
} gamestate_t; } gamestate_t;
// //
@ -138,11 +105,11 @@ typedef enum
typedef float skill_t; typedef float skill_t;
#define sk_baby 0.0 #define sk_baby 0.0f
#define sk_easy 1.0 #define sk_easy 1.0f
#define sk_medium 2.0 #define sk_medium 2.0f
#define sk_hard 3.0 #define sk_hard 3.0f
#define sk_nightmare 4.0 #define sk_nightmare 4.0f
@ -288,6 +255,8 @@ typedef enum
#define KEY_MOUSE2 0x101 #define KEY_MOUSE2 0x101
#define KEY_MOUSE3 0x102 #define KEY_MOUSE3 0x102
#define KEY_MOUSE4 0x103 #define KEY_MOUSE4 0x103
#define KEY_MWHEELUP 0x104
#define KEY_MWHEELDOWN 0x105
#define KEY_JOY1 0x108 #define KEY_JOY1 0x108
#define KEY_JOY2 0x109 #define KEY_JOY2 0x109
@ -322,13 +291,14 @@ typedef enum
#define KEY_JOY31 0x126 #define KEY_JOY31 0x126
#define KEY_JOY32 0x127 #define KEY_JOY32 0x127
#define NUM_KEYS 0x128
// [RH] dmflags->value flags (based on Q2's) // [RH] dmflags->value flags (based on Q2's)
#define DF_NO_HEALTH 1 // Do not spawn health items (DM) #define DF_NO_HEALTH 1 // Do not spawn health items (DM)
#define DF_NO_ITEMS 2 // Do not spawn powerups (DM) #define DF_NO_ITEMS 2 // Do not spawn powerups (DM)
#define DF_WEAPONS_STAY 4 // Leave weapons around after pickup (DM) #define DF_WEAPONS_STAY 4 // Leave weapons around after pickup (DM)
#define DF_YES_FALLING 8 // Falling too far hurts #define DF_YES_FALLING 8 // Falling too far hurts
#define DF_YES_FALLING_LOTS 16 // Falling too far hurts a lot #define DF_NO_FRIENDLY_FIRE 16 // Can't hurt teammates
//#define DF_INVENTORY_ITEMS 32 // Wait for player to use powerups when picked up //#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_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) #define DF_SPAWN_FARTHEST 128 // Spawn players as far as possible from other players (DM)
@ -343,4 +313,14 @@ typedef enum
#define DF_NO_JUMP 65536 // Don't allow jumping #define DF_NO_JUMP 65536 // Don't allow jumping
#define DF_NO_FREELOOK 131072 // Don't allow freelook #define DF_NO_FREELOOK 131072 // Don't allow freelook
// phares 3/20/98:
//
// Player friction is variable, based on controlling
// linedefs. More friction can create mud, sludge,
// magnetized floors, etc. Less friction can create ice.
#define MORE_FRICTION_MOMENTUM 15000 // mud factor based on momentum
#define ORIG_FRICTION 0xE800 // original value
#define ORIG_FRICTION_FACTOR 2048 // original value
#endif // __DOOMDEF__ #endif // __DOOMDEF__

View file

@ -28,7 +28,7 @@
// Game Mode - identify IWAD as shareware, retail etc. // Game Mode - identify IWAD as shareware, retail etc.
GameMode_t gamemode = indetermined; GameMode_t gamemode = undetermined;
GameMission_t gamemission = doom; GameMission_t gamemission = doom;
// Language. // Language.
@ -43,6 +43,9 @@ cvar_t *developer;
// True if an old demo is being played back. // True if an old demo is being played back.
BOOL olddemo; BOOL olddemo;
// [RH] Feature control cvars
cvar_t *boom_friction, *boom_pushers;
// [RH] Deathmatch flags // [RH] Deathmatch flags
cvar_t *dmflagsvar; cvar_t *dmflagsvar;
int dmflags; // Copy of dmflagsvar->value, but as an integer. int dmflags; // Copy of dmflagsvar->value, but as an integer.

View file

@ -83,7 +83,10 @@ extern BOOL respawnmonsters;
extern BOOL netgame; extern BOOL netgame;
// Flag: true only if started as net deathmatch. // Flag: true only if started as net deathmatch.
extern cvar_t *deathmatch; extern cvar_t *deathmatch;
// [RH] Teamplay mode
extern cvar_t *teamplay;
// ------------------------- // -------------------------
// Internal parameters for sound rendering. // Internal parameters for sound rendering.
@ -278,26 +281,30 @@ void EndMMX (void);
#endif #endif
extern cvar_t *boom_friction;
extern cvar_t *boom_pushers;
// [RH] Miscellaneous info for DeHackEd support // [RH] Miscellaneous info for DeHackEd support
struct DehInfo {
extern int deh_StartHealth; int StartHealth;
extern int deh_StartBullets; int StartBullets;
extern int deh_MaxHealth; int MaxHealth;
extern int deh_MaxArmor; int MaxArmor;
extern int deh_GreenAC; int GreenAC;
extern int deh_BlueAC; int BlueAC;
extern int deh_MaxSoulsphere; int MaxSoulsphere;
extern int deh_SoulsphereHealth; int SoulsphereHealth;
extern int deh_MegasphereHealth; int MegasphereHealth;
extern int deh_GodHealth; int GodHealth;
extern int deh_FAArmor; int FAArmor;
extern int deh_FAAC; int FAAC;
extern int deh_KFAArmor; int KFAArmor;
extern int deh_KFAAC; int KFAAC;
extern int deh_BFGCells; int BFGCells;
extern int deh_Infight; int Infight;
};
extern struct DehInfo deh;
// [RH] Deathmatch flags // [RH] Deathmatch flags

View file

@ -48,6 +48,7 @@ typedef unsigned char byte;
// Predefined with some OS. // Predefined with some OS.
#ifdef __GNUC__ #ifdef __GNUC__
#include <values.h> #include <values.h>
typedef long long __int64;
#else #else
/* [Petteri] Don't redefine if we already have these */ /* [Petteri] Don't redefine if we already have these */
#ifndef MAXCHAR #ifndef MAXCHAR
@ -68,8 +69,10 @@ typedef unsigned char byte;
#ifndef NOASM #ifndef NOASM
#ifndef USEASM
#define USEASM #define USEASM
#endif #endif
#endif

View file

@ -34,8 +34,6 @@
#include "cmdlib.h" #include "cmdlib.h"
#include "g_level.h" #include "g_level.h"
cvar_t *var_language;
char* endmsg[NUM_QUITMESSAGES+1]= char* endmsg[NUM_QUITMESSAGES+1]=
{ {
// DOOM1 // DOOM1
@ -60,228 +58,228 @@ char* endmsg[NUM_QUITMESSAGES+1]=
gamestring_t Strings[NUMSTRINGS] = { gamestring_t Strings[NUMSTRINGS] = {
{ 0, "Development mode ON.\n", NULL }, { 0, "D_DEVSTR", "Useless mode ON.\n", NULL },
{ 0, "CD-ROM Version: default.cfg from c:\\doomdata\n", NULL }, { 0, "D_CDROM", "CD-ROM Version: zdoom.cfg from c:\\zdoomdat\n", NULL },
{ 0, "press a key.", NULL }, { 0, "PRESSKEY", "press a key.", NULL },
{ 0, "press y or n.", NULL }, { 0, "PRESSYN", "press y or n.", NULL },
{ 0, "are you sure you want to\nquit this great game?", NULL }, { 0, "QUITMSG", "are you sure you want to\nquit this great game?", NULL },
{ 0, "you can't do load while in a net game!\n\npress a key.", NULL }, { 0, "LOADNET", "you can't do load while in a net game!\n\npress a key.", NULL },
{ 0, "you can't quickload during a netgame!\n\npress a key.", NULL }, { 0, "QLOADNET", "you can't quickload during a netgame!\n\npress a key.", NULL },
{ 0, "you haven't picked a quicksave slot yet!\n\npress a key.", NULL }, { 0, "QSAVESPOT", "you haven't picked a quicksave slot yet!\n\npress a key.", NULL },
{ 0, "you can't save if you aren't playing!\n\npress a key.", NULL }, { 0, "SAVEDEAD", "you can't save if you aren't playing!\n\npress a key.", NULL },
{ 0, "quicksave over your game named\n\n'%s'?\n\npress y or n.", NULL }, { 0, "QSPROMPT", "quicksave over your game named\n\n'%s'?\n\npress y or n.", NULL },
{ 0, "do you want to quickload the game named\n\n'%s'?\n\npress y or n.", NULL }, { 0, "QLPROMPT", "do you want to quickload the game named\n\n'%s'?\n\npress y or n.", NULL },
{ 0, "you can't start a new game\nwhile in a network game.\n\npress a key.", NULL }, { 0, "NEWGAME", "you can't start a new game\nwhile in a network game.\n\npress a key.", NULL },
{ 0, "are you sure? this skill level\nisn't even remotely fair.\n\npress y or n.", NULL }, { 0, "NIGHTMARE", "are you sure? this skill level\nisn't even remotely fair.\n\npress y or n.", NULL },
{ 0, "this is the shareware version of doom.\n\nyou need to order the entire trilogy.\n\npress a key.", NULL }, { 0, "SWSTRING", "this is the shareware version of doom.\n\nyou need to order the entire trilogy.\n\npress a key.", NULL },
{ 0, "Messages OFF", NULL }, { 0, "MSGOFF", "Messages OFF", NULL },
{ 0, "Messages ON", NULL }, { 0, "MSGON", "Messages ON", NULL },
{ 0, "you can't end a netgame!\n\npress a key.", NULL }, { 0, "NETEND", "you can't end a netgame!\n\npress a key.", NULL },
{ 0, "are you sure you want to end the game?\n\npress y or n.", NULL }, { 0, "ENDGAME", "are you sure you want to end the game?\n\npress y or n.", NULL },
{ 0, "(press y to quit)", NULL }, { 0, "DOSY", "(press y to quit)", NULL },
{ 0, "empty slot", NULL }, { 0, "EMPTYSTRING", "empty slot", NULL },
{ 0, "Picked up the armor.", NULL }, { 0, "GOTARMOR", "Picked up the armor.", NULL },
{ 0, "Picked up the MegaArmor!", NULL }, { 0, "GOTMEGA", "Picked up the MegaArmor!", NULL },
{ 0, "Picked up a health bonus.", NULL }, { 0, "GOTHTHBONUS", "Picked up a health bonus.", NULL },
{ 0, "Picked up an armor bonus.", NULL }, { 0, "GOTARMBONUS", "Picked up an armor bonus.", NULL },
{ 0, "Picked up a stimpack.", NULL }, { 0, "GOTSTIM", "Picked up a stimpack.", NULL },
{ 0, "Picked up a medikit that you REALLY need!", NULL }, { 0, "GOTMEDINEED", "Picked up a medikit that you REALLY need!", NULL },
{ 0, "Picked up a medikit.", NULL }, { 0, "GOTMEDIKIT", "Picked up a medikit.", NULL },
{ 0, "Supercharge!", NULL }, { 0, "GOTSUPER", "Supercharge!", NULL },
{ 0, "Picked up a blue keycard.", NULL }, { 0, "GOTBLUECARD", "Picked up a blue keycard.", NULL },
{ 0, "Picked up a yellow keycard.", NULL }, { 0, "GOTYELWCARD", "Picked up a yellow keycard.", NULL },
{ 0, "Picked up a red keycard.", NULL }, { 0, "GOTREDCARD", "Picked up a red keycard.", NULL },
{ 0, "Picked up a blue skull key.", NULL }, { 0, "GOTBLUESKUL", "Picked up a blue skull key.", NULL },
{ 0, "Picked up a yellow skull key.", NULL }, { 0, "GOTYELWSKUL", "Picked up a yellow skull key.", NULL },
{ 0, "Picked up a red skull key.", NULL }, { 0, "GOTREDSKUL", "Picked up a red skull key.", NULL },
{ 0, "Invulnerability!", NULL }, { 0, "GOTINVUL", "Invulnerability!", NULL },
{ 0, "Berserk!", NULL }, { 0, "GOTBERSERK", "Berserk!", NULL },
{ 0, "Partial Invisibility", NULL }, { 0, "GOTINVIS", "Partial Invisibility", NULL },
{ 0, "Radiation Shielding Suit", NULL }, { 0, "GOTSUIT", "Radiation Shielding Suit", NULL },
{ 0, "Computer Area Map", NULL }, { 0, "GOTMAP", "Computer Area Map", NULL },
{ 0, "Light Amplification Visor", NULL }, { 0, "GOTVISOR", "Light Amplification Visor", NULL },
{ 0, "MegaSphere!", NULL }, { 0, "GOTMSPHERE", "MegaSphere!", NULL },
{ 0, "Picked up a clip.", NULL }, { 0, "GOTCLIP", "Picked up a clip.", NULL },
{ 0, "Picked up a box of bullets.", NULL }, { 0, "GOTCLIPBOX", "Picked up a box of bullets.", NULL },
{ 0, "Picked up a rocket.", NULL }, { 0, "GOTROCKET", "Picked up a rocket.", NULL },
{ 0, "Picked up a box of rockets.", NULL }, { 0, "GOTROCKBOX", "Picked up a box of rockets.", NULL },
{ 0, "Picked up an energy cell.", NULL }, { 0, "GOTCELL", "Picked up an energy cell.", NULL },
{ 0, "Picked up an energy cell pack.", NULL }, { 0, "GOTCELLBOX", "Picked up an energy cell pack.", NULL },
{ 0, "Picked up 4 shotgun shells.", NULL }, { 0, "GOTSHELLS", "Picked up 4 shotgun shells.", NULL },
{ 0, "Picked up a box of shotgun shells.", NULL }, { 0, "GOTSHELLBOX", "Picked up a box of shotgun shells.", NULL },
{ 0, "Picked up a backpack full of ammo!", NULL }, { 0, "GOTBACKPACK", "Picked up a backpack full of ammo!", NULL },
{ 0, "You got the BFG9000! Oh, yes.", NULL }, { 0, "GOTBFG9000", "You got the BFG9000! Oh, yes.", NULL },
{ 0, "You got the chaingun!", NULL }, { 0, "GOTCHAINGUN", "You got the chaingun!", NULL },
{ 0, "A chainsaw! Find some meat!", NULL }, { 0, "GOTCHAINSAW", "A chainsaw! Find some meat!", NULL },
{ 0, "You got the rocket launcher!", NULL }, { 0, "GOTLAUNCHER", "You got the rocket launcher!", NULL },
{ 0, "You got the plasma gun!", NULL }, { 0, "GOTPLASMA", "You got the plasma gun!", NULL },
{ 0, "You got the shotgun!", NULL }, { 0, "GOTSHOTGUN", "You got the shotgun!", NULL },
{ 0, "You got the super shotgun!", NULL }, { 0, "GOTSHOTGUN2", "You got the super shotgun!", NULL },
{ 0, "You need a blue key to activate this object", NULL }, { 0, "PD_BLUEO", "You need a blue key to activate this object", NULL },
{ 0, "You need a red key to activate this object", NULL }, { 0, "PD_REDO", "You need a red key to activate this object", NULL },
{ 0, "You need a yellow key to activate this object", NULL }, { 0, "PD_YELLOWO", "You need a yellow key to activate this object", NULL },
{ 0, "You need a blue key to open this door", NULL }, { 0, "PD_BLUEK", "You need a blue key to open this door", NULL },
{ 0, "You need a red key to open this door", NULL }, { 0, "PD_REDK", "You need a red key to open this door", NULL },
{ 0, "You need a yellow key to open this door", NULL }, { 0, "PD_YELLOWK", "You need a yellow key to open this door", NULL },
{ 0, "game saved.", NULL }, { 0, "GGSAVED", "game saved.", NULL },
{ 0, "[Message unsent]", NULL }, { 0, "HUSTR_MSGU", "[Message unsent]", NULL },
{ 0, "E1M1: Hangar", NULL }, { 0, "HUSTR_E1M1", "E1M1: Hangar", NULL },
{ 0, "E1M2: Nuclear Plant", NULL }, { 0, "HUSTR_E1M2", "E1M2: Nuclear Plant", NULL },
{ 0, "E1M3: Toxin Refinery", NULL }, { 0, "HUSTR_E1M3", "E1M3: Toxin Refinery", NULL },
{ 0, "E1M4: Command Control", NULL }, { 0, "HUSTR_E1M4", "E1M4: Command Control", NULL },
{ 0, "E1M5: Phobos Lab", NULL }, { 0, "HUSTR_E1M5", "E1M5: Phobos Lab", NULL },
{ 0, "E1M6: Central Processing", NULL }, { 0, "HUSTR_E1M6", "E1M6: Central Processing", NULL },
{ 0, "E1M7: Computer Station", NULL }, { 0, "HUSTR_E1M7", "E1M7: Computer Station", NULL },
{ 0, "E1M8: Phobos Anomaly", NULL }, { 0, "HUSTR_E1M8", "E1M8: Phobos Anomaly", NULL },
{ 0, "E1M9: Military Base", NULL }, { 0, "HUSTR_E1M9", "E1M9: Military Base", NULL },
{ 0, "E2M1: Deimos Anomaly", NULL }, { 0, "HUSTR_E2M1", "E2M1: Deimos Anomaly", NULL },
{ 0, "E2M2: Containment Area", NULL }, { 0, "HUSTR_E2M2", "E2M2: Containment Area", NULL },
{ 0, "E2M3: Refinery", NULL }, { 0, "HUSTR_E2M3", "E2M3: Refinery", NULL },
{ 0, "E2M4: Deimos Lab", NULL }, { 0, "HUSTR_E2M4", "E2M4: Deimos Lab", NULL },
{ 0, "E2M5: Command Center", NULL }, { 0, "HUSTR_E2M5", "E2M5: Command Center", NULL },
{ 0, "E2M6: Halls of the Damned", NULL }, { 0, "HUSTR_E2M6", "E2M6: Halls of the Damned", NULL },
{ 0, "E2M7: Spawning Vats", NULL }, { 0, "HUSTR_E2M7", "E2M7: Spawning Vats", NULL },
{ 0, "E2M8: Tower of Babel", NULL }, { 0, "HUSTR_E2M8", "E2M8: Tower of Babel", NULL },
{ 0, "E2M9: Fortress of Mystery", NULL }, { 0, "HUSTR_E2M9", "E2M9: Fortress of Mystery", NULL },
{ 0, "E3M1: Hell Keep", NULL }, { 0, "HUSTR_E3M1", "E3M1: Hell Keep", NULL },
{ 0, "E3M2: Slough of Despair", NULL }, { 0, "HUSTR_E3M2", "E3M2: Slough of Despair", NULL },
{ 0, "E3M3: Pandemonium", NULL }, { 0, "HUSTR_E3M3", "E3M3: Pandemonium", NULL },
{ 0, "E3M4: House of Pain", NULL }, { 0, "HUSTR_E3M4", "E3M4: House of Pain", NULL },
{ 0, "E3M5: Unholy Cathedral", NULL }, { 0, "HUSTR_E3M5", "E3M5: Unholy Cathedral", NULL },
{ 0, "E3M6: Mt. Erebus", NULL }, { 0, "HUSTR_E3M6", "E3M6: Mt. Erebus", NULL },
{ 0, "E3M7: Limbo", NULL }, { 0, "HUSTR_E3M7", "E3M7: Limbo", NULL },
{ 0, "E3M8: Dis", NULL }, { 0, "HUSTR_E3M8", "E3M8: Dis", NULL },
{ 0, "E3M9: Warrens", NULL }, { 0, "HUSTR_E3M9", "E3M9: Warrens", NULL },
{ 0, "E4M1: Hell Beneath", NULL }, { 0, "HUSTR_E4M1", "E4M1: Hell Beneath", NULL },
{ 0, "E4M2: Perfect Hatred", NULL }, { 0, "HUSTR_E4M2", "E4M2: Perfect Hatred", NULL },
{ 0, "E4M3: Sever The Wicked", NULL }, { 0, "HUSTR_E4M3", "E4M3: Sever The Wicked", NULL },
{ 0, "E4M4: Unruly Evil", NULL }, { 0, "HUSTR_E4M4", "E4M4: Unruly Evil", NULL },
{ 0, "E4M5: They Will Repent", NULL }, { 0, "HUSTR_E4M5", "E4M5: They Will Repent", NULL },
{ 0, "E4M6: Against Thee Wickedly", NULL }, { 0, "HUSTR_E4M6", "E4M6: Against Thee Wickedly", NULL },
{ 0, "E4M7: And Hell Followed", NULL }, { 0, "HUSTR_E4M7", "E4M7: And Hell Followed", NULL },
{ 0, "E4M8: Unto The Cruel", NULL }, { 0, "HUSTR_E4M8", "E4M8: Unto The Cruel", NULL },
{ 0, "E4M9: Fear", NULL }, { 0, "HUSTR_E4M9", "E4M9: Fear", NULL },
{ 0, "level 1: entryway", NULL }, { 0, "HUSTR_1", "level 1: entryway", NULL },
{ 0, "level 2: underhalls", NULL }, { 0, "HUSTR_2", "level 2: underhalls", NULL },
{ 0, "level 3: the gantlet", NULL }, { 0, "HUSTR_3", "level 3: the gantlet", NULL },
{ 0, "level 4: the focus", NULL }, { 0, "HUSTR_4", "level 4: the focus", NULL },
{ 0, "level 5: the waste tunnels", NULL }, { 0, "HUSTR_5", "level 5: the waste tunnels", NULL },
{ 0, "level 6: the crusher", NULL }, { 0, "HUSTR_6", "level 6: the crusher", NULL },
{ 0, "level 7: dead simple", NULL }, { 0, "HUSTR_7", "level 7: dead simple", NULL },
{ 0, "level 8: tricks and traps", NULL }, { 0, "HUSTR_8", "level 8: tricks and traps", NULL },
{ 0, "level 9: the pit", NULL }, { 0, "HUSTR_9", "level 9: the pit", NULL },
{ 0, "level 10: refueling base", NULL }, { 0, "HUSTR_10", "level 10: refueling base", NULL },
{ 0, "level 11: 'o' of destruction!", NULL }, { 0, "HUSTR_11", "level 11: 'o' of destruction!", NULL },
{ 0, "level 12: the factory", NULL }, { 0, "HUSTR_12", "level 12: the factory", NULL },
{ 0, "level 13: downtown", NULL }, { 0, "HUSTR_13", "level 13: downtown", NULL },
{ 0, "level 14: the inmost dens", NULL }, { 0, "HUSTR_14", "level 14: the inmost dens", NULL },
{ 0, "level 15: industrial zone", NULL }, { 0, "HUSTR_15", "level 15: industrial zone", NULL },
{ 0, "level 16: suburbs", NULL }, { 0, "HUSTR_16", "level 16: suburbs", NULL },
{ 0, "level 17: tenements", NULL }, { 0, "HUSTR_17", "level 17: tenements", NULL },
{ 0, "level 18: the courtyard", NULL }, { 0, "HUSTR_18", "level 18: the courtyard", NULL },
{ 0, "level 19: the citadel", NULL }, { 0, "HUSTR_19", "level 19: the citadel", NULL },
{ 0, "level 20: gotcha!", NULL }, { 0, "HUSTR_20", "level 20: gotcha!", NULL },
{ 0, "level 21: nirvana", NULL }, { 0, "HUSTR_21", "level 21: nirvana", NULL },
{ 0, "level 22: the catacombs", NULL }, { 0, "HUSTR_22", "level 22: the catacombs", NULL },
{ 0, "level 23: barrels o' fun", NULL }, { 0, "HUSTR_23", "level 23: barrels o' fun", NULL },
{ 0, "level 24: the chasm", NULL }, { 0, "HUSTR_24", "level 24: the chasm", NULL },
{ 0, "level 25: bloodfalls", NULL }, { 0, "HUSTR_25", "level 25: bloodfalls", NULL },
{ 0, "level 26: the abandoned mines", NULL }, { 0, "HUSTR_26", "level 26: the abandoned mines", NULL },
{ 0, "level 27: monster condo", NULL }, { 0, "HUSTR_27", "level 27: monster condo", NULL },
{ 0, "level 28: the spirit world", NULL }, { 0, "HUSTR_28", "level 28: the spirit world", NULL },
{ 0, "level 29: the living end", NULL }, { 0, "HUSTR_29", "level 29: the living end", NULL },
{ 0, "level 30: icon of sin", NULL }, { 0, "HUSTR_30", "level 30: icon of sin", NULL },
{ 0, "level 31: wolfenstein", NULL }, { 0, "HUSTR_31", "level 31: wolfenstein", NULL },
{ 0, "level 32: grosse", NULL }, { 0, "HUSTR_32", "level 32: grosse", NULL },
{ 0, "level 1: congo", NULL }, { 0, "PHUSTR_1", "level 1: congo", NULL },
{ 0, "level 2: well of souls", NULL }, { 0, "PHUSTR_2", "level 2: well of souls", NULL },
{ 0, "level 3: aztec", NULL }, { 0, "PHUSTR_3", "level 3: aztec", NULL },
{ 0, "level 4: caged", NULL }, { 0, "PHUSTR_4", "level 4: caged", NULL },
{ 0, "level 5: ghost town", NULL }, { 0, "PHUSTR_5", "level 5: ghost town", NULL },
{ 0, "level 6: baron's lair", NULL }, { 0, "PHUSTR_6", "level 6: baron's lair", NULL },
{ 0, "level 7: caughtyard", NULL }, { 0, "PHUSTR_7", "level 7: caughtyard", NULL },
{ 0, "level 8: realm", NULL }, { 0, "PHUSTR_8", "level 8: realm", NULL },
{ 0, "level 9: abattoire", NULL }, { 0, "PHUSTR_9", "level 9: abattoire", NULL },
{ 0, "level 10: onslaught", NULL }, { 0, "PHUSTR_10", "level 10: onslaught", NULL },
{ 0, "level 11: hunted", NULL }, { 0, "PHUSTR_11", "level 11: hunted", NULL },
{ 0, "level 12: speed", NULL }, { 0, "PHUSTR_12", "level 12: speed", NULL },
{ 0, "level 13: the crypt", NULL }, { 0, "PHUSTR_13", "level 13: the crypt", NULL },
{ 0, "level 14: genesis", NULL }, { 0, "PHUSTR_14", "level 14: genesis", NULL },
{ 0, "level 15: the twilight", NULL }, { 0, "PHUSTR_15", "level 15: the twilight", NULL },
{ 0, "level 16: the omen", NULL }, { 0, "PHUSTR_16", "level 16: the omen", NULL },
{ 0, "level 17: compound", NULL }, { 0, "PHUSTR_17", "level 17: compound", NULL },
{ 0, "level 18: neurosphere", NULL }, { 0, "PHUSTR_18", "level 18: neurosphere", NULL },
{ 0, "level 19: nme", NULL }, { 0, "PHUSTR_19", "level 19: nme", NULL },
{ 0, "level 20: the death domain", NULL }, { 0, "PHUSTR_20", "level 20: the death domain", NULL },
{ 0, "level 21: slayer", NULL }, { 0, "PHUSTR_21", "level 21: slayer", NULL },
{ 0, "level 22: impossible mission", NULL }, { 0, "PHUSTR_22", "level 22: impossible mission", NULL },
{ 0, "level 23: tombstone", NULL }, { 0, "PHUSTR_23", "level 23: tombstone", NULL },
{ 0, "level 24: the final frontier", NULL }, { 0, "PHUSTR_24", "level 24: the final frontier", NULL },
{ 0, "level 25: the temple of darkness", NULL }, { 0, "PHUSTR_25", "level 25: the temple of darkness", NULL },
{ 0, "level 26: bunker", NULL }, { 0, "PHUSTR_26", "level 26: bunker", NULL },
{ 0, "level 27: anti-christ", NULL }, { 0, "PHUSTR_27", "level 27: anti-christ", NULL },
{ 0, "level 28: the sewers", NULL }, { 0, "PHUSTR_28", "level 28: the sewers", NULL },
{ 0, "level 29: odyssey of noises", NULL }, { 0, "PHUSTR_29", "level 29: odyssey of noises", NULL },
{ 0, "level 30: the gateway of hell", NULL }, { 0, "PHUSTR_30", "level 30: the gateway of hell", NULL },
{ 0, "level 31: cyberden", NULL }, { 0, "PHUSTR_31", "level 31: cyberden", NULL },
{ 0, "level 32: go 2 it", NULL }, { 0, "PHUSTR_32", "level 32: go 2 it", NULL },
{ 0, "level 1: system control", NULL }, { 0, "THUSTR_1", "level 1: system control", NULL },
{ 0, "level 2: human bbq", NULL }, { 0, "THUSTR_2", "level 2: human bbq", NULL },
{ 0, "level 3: power control", NULL }, { 0, "THUSTR_3", "level 3: power control", NULL },
{ 0, "level 4: wormhole", NULL }, { 0, "THUSTR_4", "level 4: wormhole", NULL },
{ 0, "level 5: hanger", NULL }, { 0, "THUSTR_5", "level 5: hanger", NULL },
{ 0, "level 6: open season", NULL }, { 0, "THUSTR_6", "level 6: open season", NULL },
{ 0, "level 7: prison", NULL }, { 0, "THUSTR_7", "level 7: prison", NULL },
{ 0, "level 8: metal", NULL }, { 0, "THUSTR_8", "level 8: metal", NULL },
{ 0, "level 9: stronghold", NULL }, { 0, "THUSTR_9", "level 9: stronghold", NULL },
{ 0, "level 10: redemption", NULL }, { 0, "THUSTR_10", "level 10: redemption", NULL },
{ 0, "level 11: storage facility", NULL }, { 0, "THUSTR_11", "level 11: storage facility", NULL },
{ 0, "level 12: crater", NULL }, { 0, "THUSTR_12", "level 12: crater", NULL },
{ 0, "level 13: nukage processing", NULL }, { 0, "THUSTR_13", "level 13: nukage processing", NULL },
{ 0, "level 14: steel works", NULL }, { 0, "THUSTR_14", "level 14: steel works", NULL },
{ 0, "level 15: dead zone", NULL }, { 0, "THUSTR_15", "level 15: dead zone", NULL },
{ 0, "level 16: deepest reaches", NULL }, { 0, "THUSTR_16", "level 16: deepest reaches", NULL },
{ 0, "level 17: processing area", NULL }, { 0, "THUSTR_17", "level 17: processing area", NULL },
{ 0, "level 18: mill", NULL }, { 0, "THUSTR_18", "level 18: mill", NULL },
{ 0, "level 19: shipping/respawning", NULL }, { 0, "THUSTR_19", "level 19: shipping/respawning", NULL },
{ 0, "level 20: central processing", NULL }, { 0, "THUSTR_20", "level 20: central processing", NULL },
{ 0, "level 21: administration center", NULL }, { 0, "THUSTR_21", "level 21: administration center", NULL },
{ 0, "level 22: habitat", NULL }, { 0, "THUSTR_22", "level 22: habitat", NULL },
{ 0, "level 23: lunar mining project", NULL }, { 0, "THUSTR_23", "level 23: lunar mining project", NULL },
{ 0, "level 24: quarry", NULL }, { 0, "THUSTR_24", "level 24: quarry", NULL },
{ 0, "level 25: baron's den", NULL }, { 0, "THUSTR_25", "level 25: baron's den", NULL },
{ 0, "level 26: ballistyx", NULL }, { 0, "THUSTR_26", "level 26: ballistyx", NULL },
{ 0, "level 27: mount pain", NULL }, { 0, "THUSTR_27", "level 27: mount pain", NULL },
{ 0, "level 28: heck", NULL }, { 0, "THUSTR_28", "level 28: heck", NULL },
{ 0, "level 29: river styx", NULL }, { 0, "THUSTR_29", "level 29: river styx", NULL },
{ 0, "level 30: last call", NULL }, { 0, "THUSTR_30", "level 30: last call", NULL },
{ 0, "level 31: pharaoh", NULL }, { 0, "THUSTR_31", "level 31: pharaoh", NULL },
{ 0, "level 32: caribbean", NULL }, { 0, "THUSTR_32", "level 32: caribbean", NULL },
{ 0, "You mumble to yourself", NULL }, { 0, "HUSTR_TALKTOSELF1", "You mumble to yourself", NULL },
{ 0, "Who's there?", NULL }, { 0, "HUSTR_TALKTOSELF2", "Who's there?", NULL },
{ 0, "You scare yourself", NULL }, { 0, "HUSTR_TALKTOSELF3", "You scare yourself", NULL },
{ 0, "You start to rave", NULL }, { 0, "HUSTR_TALKTOSELF4", "You start to rave", NULL },
{ 0, "You've lost it...", NULL }, { 0, "HUSTR_TALKTOSELF5", "You've lost it...", NULL },
{ 0, "[Message Sent]", NULL }, { 0, "HUSTR_MESSAGESENT", "[Message Sent]", NULL },
{ 0, "Follow Mode ON", NULL }, { 0, "AMSTR_FOLLOWON", "Follow Mode ON", NULL },
{ 0, "Follow Mode OFF", NULL }, { 0, "AMSTR_FOLLOWOFF", "Follow Mode OFF", NULL },
{ 0, "Grid ON", NULL }, { 0, "AMSTR_GRIDON", "Grid ON", NULL },
{ 0, "Grid OFF", NULL }, { 0, "AMSTR_GRIDOFF", "Grid OFF", NULL },
{ 0, "Marked Spot", NULL }, { 0, "AMSTR_MARKEDSPOT", "Marked Spot", NULL },
{ 0, "All Marks Cleared", NULL }, { 0, "AMSTR_MARKSCLEARED", "All Marks Cleared", NULL },
{ 0, "Music Change", NULL }, { 0, "STSTR_MUS", "Music Change", NULL },
{ 0, "IMPOSSIBLE SELECTION", NULL }, { 0, "STSTR_NOMUS", "IMPOSSIBLE SELECTION", NULL },
{ 0, "Degreelessness Mode ON", NULL }, { 0, "STSTR_DQDON", "Degreelessness Mode ON", NULL },
{ 0, "Degreelessness Mode OFF", NULL }, { 0, "STSTR_DQDOFF", "Degreelessness Mode OFF", NULL },
{ 0, "Very Happy Ammo Added", NULL }, { 0, "STSTR_KFAADDED", "Very Happy Ammo Added", NULL },
{ 0, "Ammo (no keys) Added", NULL }, { 0, "STSTR_FAADDED", "Ammo (no keys) Added", NULL },
{ 0, "No Clipping Mode ON", NULL }, { 0, "STSTR_NCON", "No Clipping Mode ON", NULL },
{ 0, "No Clipping Mode OFF", NULL }, { 0, "STSTR_NCOFF", "No Clipping Mode OFF", NULL },
{ 0, "inVuln, Str, Inviso, Rad, Allmap, or Lite-amp", NULL }, { 0, "STSTR_BEHOLD", "inVuln, Str, Inviso, Rad, Allmap, or Lite-amp", NULL },
{ 0, "Power-up Toggled", NULL }, { 0, "STSTR_BEHOLDX", "Power-up Toggled", NULL },
{ 0, "... doesn't suck - GM", NULL }, { 0, "STSTR_CHOPPERS", "... doesn't suck - GM", NULL },
{ 0, "Changing Level...\n", NULL }, { 0, "STSTR_CLEV", "Changing Level...\n", NULL },
{ 0, "Once you beat the big badasses and\n"\ { 0, "E1TEXT", "Once you beat the big badasses and\n"\
"clean out the moon base you're supposed\n"\ "clean out the moon base you're supposed\n"\
"to win, aren't you? Aren't you? Where's\n"\ "to win, aren't you? Aren't you? Where's\n"\
"your fat reward and ticket home? What\n"\ "your fat reward and ticket home? What\n"\
@ -297,7 +295,7 @@ gamestring_t Strings[NUMSTRINGS] = {
"The Shores of Hell and its amazing\n"\ "The Shores of Hell and its amazing\n"\
"sequel, Inferno!\n" "sequel, Inferno!\n"
, NULL }, , NULL },
{ 0, "You've done it! The hideous cyber-\n"\ { 0, "E2TEXT", "You've done it! The hideous cyber-\n"\
"demon lord that ruled the lost Deimos\n"\ "demon lord that ruled the lost Deimos\n"\
"moon base has been slain and you\n"\ "moon base has been slain and you\n"\
"are triumphant! But ... where are\n"\ "are triumphant! But ... where are\n"\
@ -315,7 +313,7 @@ gamestring_t Strings[NUMSTRINGS] = {
"Now, it's on to the final chapter of\n"\ "Now, it's on to the final chapter of\n"\
"DOOM! -- Inferno." "DOOM! -- Inferno."
, NULL }, , NULL },
{ 0, "The loathsome spiderdemon that\n"\ { 0, "E3TEXT", "The loathsome spiderdemon that\n"\
"masterminded the invasion of the moon\n"\ "masterminded the invasion of the moon\n"\
"bases and caused so much death has had\n"\ "bases and caused so much death has had\n"\
"its ass kicked for all time.\n"\ "its ass kicked for all time.\n"\
@ -333,7 +331,7 @@ gamestring_t Strings[NUMSTRINGS] = {
"spawn could have come through that\n"\ "spawn could have come through that\n"\
"door with you ..." "door with you ..."
, NULL }, , NULL },
{ 0, "the spider mastermind must have sent forth\n"\ { 0, "E4TEXT", "the spider mastermind must have sent forth\n"\
"its legions of hellspawn before your\n"\ "its legions of hellspawn before your\n"\
"final confrontation with that terrible\n"\ "final confrontation with that terrible\n"\
"beast from hell. but you stepped forward\n"\ "beast from hell. but you stepped forward\n"\
@ -350,7 +348,7 @@ gamestring_t Strings[NUMSTRINGS] = {
"\n"\ "\n"\
"next stop, hell on earth!" "next stop, hell on earth!"
, NULL }, , NULL },
{ 0, "YOU HAVE ENTERED DEEPLY INTO THE INFESTED\n" \ { 0, "C1TEXT", "YOU HAVE ENTERED DEEPLY INTO THE INFESTED\n" \
"STARPORT. BUT SOMETHING IS WRONG. THE\n" \ "STARPORT. BUT SOMETHING IS WRONG. THE\n" \
"MONSTERS HAVE BROUGHT THEIR OWN REALITY\n" \ "MONSTERS HAVE BROUGHT THEIR OWN REALITY\n" \
"WITH THEM, AND THE STARPORT'S TECHNOLOGY\n" \ "WITH THEM, AND THE STARPORT'S TECHNOLOGY\n" \
@ -363,7 +361,7 @@ gamestring_t Strings[NUMSTRINGS] = {
"SWITCH WHICH HOLDS EARTH'S POPULATION\n" \ "SWITCH WHICH HOLDS EARTH'S POPULATION\n" \
"HOSTAGE." "HOSTAGE."
, NULL }, , NULL },
{ 0, "YOU HAVE WON! YOUR VICTORY HAS ENABLED\n" \ { 0, "C2TEXT", "YOU HAVE WON! YOUR VICTORY HAS ENABLED\n" \
"HUMANKIND TO EVACUATE EARTH AND ESCAPE\n"\ "HUMANKIND TO EVACUATE EARTH AND ESCAPE\n"\
"THE NIGHTMARE. NOW YOU ARE THE ONLY\n"\ "THE NIGHTMARE. NOW YOU ARE THE ONLY\n"\
"HUMAN LEFT ON THE FACE OF THE PLANET.\n"\ "HUMAN LEFT ON THE FACE OF THE PLANET.\n"\
@ -381,7 +379,7 @@ gamestring_t Strings[NUMSTRINGS] = {
"STARPORT.\" SLOWLY AND PAINFULLY YOU GET\n"\ "STARPORT.\" SLOWLY AND PAINFULLY YOU GET\n"\
"UP AND RETURN TO THE FRAY." "UP AND RETURN TO THE FRAY."
, NULL }, , NULL },
{ 0, "YOU ARE AT THE CORRUPT HEART OF THE CITY,\n"\ { 0, "C3TEXT", "YOU ARE AT THE CORRUPT HEART OF THE CITY,\n"\
"SURROUNDED BY THE CORPSES OF YOUR ENEMIES.\n"\ "SURROUNDED BY THE CORPSES OF YOUR ENEMIES.\n"\
"YOU SEE NO WAY TO DESTROY THE CREATURES'\n"\ "YOU SEE NO WAY TO DESTROY THE CREATURES'\n"\
"ENTRYWAY ON THIS SIDE, SO YOU CLENCH YOUR\n"\ "ENTRYWAY ON THIS SIDE, SO YOU CLENCH YOUR\n"\
@ -391,7 +389,7 @@ gamestring_t Strings[NUMSTRINGS] = {
"OTHER SIDE. WHAT DO YOU CARE IF YOU'VE\n"\ "OTHER SIDE. WHAT DO YOU CARE IF YOU'VE\n"\
"GOT TO GO THROUGH HELL TO GET TO IT?" "GOT TO GO THROUGH HELL TO GET TO IT?"
, NULL }, , NULL },
{ 0, "THE HORRENDOUS VISAGE OF THE BIGGEST\n"\ { 0, "C4TEXT", "THE HORRENDOUS VISAGE OF THE BIGGEST\n"\
"DEMON YOU'VE EVER SEEN CRUMBLES BEFORE\n"\ "DEMON YOU'VE EVER SEEN CRUMBLES BEFORE\n"\
"YOU, AFTER YOU PUMP YOUR ROCKETS INTO\n"\ "YOU, AFTER YOU PUMP YOUR ROCKETS INTO\n"\
"HIS EXPOSED BRAIN. THE MONSTER SHRIVELS\n"\ "HIS EXPOSED BRAIN. THE MONSTER SHRIVELS\n"\
@ -407,17 +405,17 @@ gamestring_t Strings[NUMSTRINGS] = {
"HOME. REBUILDING EARTH OUGHT TO BE A\n"\ "HOME. REBUILDING EARTH OUGHT TO BE A\n"\
"LOT MORE FUN THAN RUINING IT WAS.\n" "LOT MORE FUN THAN RUINING IT WAS.\n"
, NULL }, , NULL },
{ 0, "CONGRATULATIONS, YOU'VE FOUND THE SECRET\n"\ { 0, "C5TEXT", "CONGRATULATIONS, YOU'VE FOUND THE SECRET\n"\
"LEVEL! LOOKS LIKE IT'S BEEN BUILT BY\n"\ "LEVEL! LOOKS LIKE IT'S BEEN BUILT BY\n"\
"HUMANS, RATHER THAN DEMONS. YOU WONDER\n"\ "HUMANS, RATHER THAN DEMONS. YOU WONDER\n"\
"WHO THE INMATES OF THIS CORNER OF HELL\n"\ "WHO THE INMATES OF THIS CORNER OF HELL\n"\
"WILL BE." "WILL BE."
, NULL }, , NULL },
{ 0, "CONGRATULATIONS, YOU'VE FOUND THE\n"\ { 0, "C6TEXT", "CONGRATULATIONS, YOU'VE FOUND THE\n"\
"SUPER SECRET LEVEL! YOU'D BETTER\n"\ "SUPER SECRET LEVEL! YOU'D BETTER\n"\
"BLAZE THROUGH THIS ONE!\n" "BLAZE THROUGH THIS ONE!\n"
, NULL }, , NULL },
{ 0, "You gloat over the steaming carcass of the\n"\ { 0, "P1TEXT", "You gloat over the steaming carcass of the\n"\
"Guardian. With its death, you've wrested\n"\ "Guardian. With its death, you've wrested\n"\
"the Accelerator from the stinking claws\n"\ "the Accelerator from the stinking claws\n"\
"of Hell. You relax and glance around the\n"\ "of Hell. You relax and glance around the\n"\
@ -430,14 +428,14 @@ gamestring_t Strings[NUMSTRINGS] = {
"moving, keep fighting, keep killing.\n"\ "moving, keep fighting, keep killing.\n"\
"Oh yes, keep living, too." "Oh yes, keep living, too."
, NULL }, , NULL },
{ 0, "Even the deadly Arch-Vile labyrinth could\n"\ { 0, "P2TEXT", "Even the deadly Arch-Vile labyrinth could\n"\
"not stop you, and you've gotten to the\n"\ "not stop you, and you've gotten to the\n"\
"prototype Accelerator which is soon\n"\ "prototype Accelerator which is soon\n"\
"efficiently and permanently deactivated.\n"\ "efficiently and permanently deactivated.\n"\
"\n"\ "\n"\
"You're good at that kind of thing." "You're good at that kind of thing."
, NULL }, , NULL },
{ 0, "You've bashed and battered your way into\n"\ { 0, "P3TEXT", "You've bashed and battered your way into\n"\
"the heart of the devil-hive. Time for a\n"\ "the heart of the devil-hive. Time for a\n"\
"Search-and-Destroy mission, aimed at the\n"\ "Search-and-Destroy mission, aimed at the\n"\
"Gatekeeper, whose foul offspring is\n"\ "Gatekeeper, whose foul offspring is\n"\
@ -448,7 +446,7 @@ gamestring_t Strings[NUMSTRINGS] = {
"get ready to give the bastard a little Hell\n"\ "get ready to give the bastard a little Hell\n"\
"of your own making!" "of your own making!"
, NULL }, , NULL },
{ 0, "The Gatekeeper's evil face is splattered\n"\ { 0, "P4TEXT", "The Gatekeeper's evil face is splattered\n"\
"all over the place. As its tattered corpse\n"\ "all over the place. As its tattered corpse\n"\
"collapses, an inverted Gate forms and\n"\ "collapses, an inverted Gate forms and\n"\
"sucks down the shards of the last\n"\ "sucks down the shards of the last\n"\
@ -461,16 +459,16 @@ gamestring_t Strings[NUMSTRINGS] = {
"when you die, you'll need it for some\n"\ "when you die, you'll need it for some\n"\
"final cleaning-up ..." "final cleaning-up ..."
, NULL }, , NULL },
{ 0, "You've found the second-hardest level we\n"\ { 0, "P5TEXT", "You've found the second-hardest level we\n"\
"got. Hope you have a saved game a level or\n"\ "got. Hope you have a saved game a level or\n"\
"two previous. If not, be prepared to die\n"\ "two previous. If not, be prepared to die\n"\
"aplenty. For master marines only." "aplenty. For master marines only."
, NULL }, , NULL },
{ 0, "Betcha wondered just what WAS the hardest\n"\ { 0, "P6TEXT", "Betcha wondered just what WAS the hardest\n"\
"level we had ready for ya? Now you know.\n"\ "level we had ready for ya? Now you know.\n"\
"No one gets out alive." "No one gets out alive."
, NULL }, , NULL },
{ 0, "You've fought your way out of the infested\n"\ { 0, "T1TEXT", "You've fought your way out of the infested\n"\
"experimental labs. It seems that UAC has\n"\ "experimental labs. It seems that UAC has\n"\
"once again gulped it down. With their\n"\ "once again gulped it down. With their\n"\
"high turnover, it must be hard for poor\n"\ "high turnover, it must be hard for poor\n"\
@ -483,7 +481,7 @@ gamestring_t Strings[NUMSTRINGS] = {
"complex still has some warlike ordnance\n"\ "complex still has some warlike ordnance\n"\
"laying around." "laying around."
, NULL }, , NULL },
{ 0, "You hear the grinding of heavy machinery\n"\ { 0, "T2TEXT", "You hear the grinding of heavy machinery\n"\
"ahead. You sure hope they're not stamping\n"\ "ahead. You sure hope they're not stamping\n"\
"out new hellspawn, but you're ready to\n"\ "out new hellspawn, but you're ready to\n"\
"ream out a whole herd if you have to.\n"\ "ream out a whole herd if you have to.\n"\
@ -493,7 +491,7 @@ gamestring_t Strings[NUMSTRINGS] = {
"\n"\ "\n"\
"You don't plan to go down easy." "You don't plan to go down easy."
, NULL }, , NULL },
{ 0, "The vista opening ahead looks real damn\n"\ { 0, "T3TEXT", "The vista opening ahead looks real damn\n"\
"familiar. Smells familiar, too -- like\n"\ "familiar. Smells familiar, too -- like\n"\
"fried excrement. You didn't like this\n"\ "fried excrement. You didn't like this\n"\
"place before, and you sure as hell ain't\n"\ "place before, and you sure as hell ain't\n"\
@ -502,7 +500,7 @@ gamestring_t Strings[NUMSTRINGS] = {
"Hefting your gun, an evil grin trickles\n"\ "Hefting your gun, an evil grin trickles\n"\
"onto your face. Time to take some names." "onto your face. Time to take some names."
, NULL }, , NULL },
{ 0, "Suddenly, all is silent, from one horizon\n"\ { 0, "T4TEXT", "Suddenly, all is silent, from one horizon\n"\
"to the other. The agonizing echo of Hell\n"\ "to the other. The agonizing echo of Hell\n"\
"fades away, the nightmare sky turns to\n"\ "fades away, the nightmare sky turns to\n"\
"blue, the heaps of monster corpses start \n"\ "blue, the heaps of monster corpses start \n"\
@ -514,13 +512,13 @@ gamestring_t Strings[NUMSTRINGS] = {
"A blue light begins to glow inside the\n"\ "A blue light begins to glow inside the\n"\
"ruined skull of the demon-spitter." "ruined skull of the demon-spitter."
, NULL }, , NULL },
{ 0, "What now? Looks totally different. Kind\n"\ { 0, "T5TEXT", "What now? Looks totally different. Kind\n"\
"of like King Tut's condo. Well,\n"\ "of like King Tut's condo. Well,\n"\
"whatever's here can't be any worse\n"\ "whatever's here can't be any worse\n"\
"than usual. Can it? Or maybe it's best\n"\ "than usual. Can it? Or maybe it's best\n"\
"to let sleeping gods lie.." "to let sleeping gods lie.."
, NULL }, , NULL },
{ 0, "Time for a vacation. You've burst the\n"\ { 0, "T6TEXT", "Time for a vacation. You've burst the\n"\
"bowels of hell and by golly you're ready\n"\ "bowels of hell and by golly you're ready\n"\
"for a break. You mutter to yourself,\n"\ "for a break. You mutter to yourself,\n"\
"Maybe someone else can kick Hell's ass\n"\ "Maybe someone else can kick Hell's ass\n"\
@ -531,93 +529,114 @@ gamestring_t Strings[NUMSTRINGS] = {
"As you step off the transport, you hear\n"\ "As you step off the transport, you hear\n"\
"the stomp of a cyberdemon's iron shoe." "the stomp of a cyberdemon's iron shoe."
, NULL }, , NULL },
{ 0, "ZOMBIEMAN", NULL }, { 0, "CC_ZOMBIE", "ZOMBIEMAN", NULL },
{ 0, "SHOTGUN GUY", NULL }, { 0, "CC_SHOTGUN", "SHOTGUN GUY", NULL },
{ 0, "HEAVY WEAPON DUDE", NULL }, { 0, "CC_HEAVY", "HEAVY WEAPON DUDE", NULL },
{ 0, "IMP", NULL }, { 0, "CC_IMP", "IMP", NULL },
{ 0, "DEMON", NULL }, { 0, "CC_DEMON", "DEMON", NULL },
{ 0, "LOST SOUL", NULL }, { 0, "CC_LOST", "LOST SOUL", NULL },
{ 0, "CACODEMON", NULL }, { 0, "CC_CACO", "CACODEMON", NULL },
{ 0, "HELL KNIGHT", NULL }, { 0, "CC_HELL", "HELL KNIGHT", NULL },
{ 0, "BARON OF HELL", NULL }, { 0, "CC_BARON", "BARON OF HELL", NULL },
{ 0, "ARACHNOTRON", NULL }, { 0, "CC_ARACH", "ARACHNOTRON", NULL },
{ 0, "PAIN ELEMENTAL", NULL }, { 0, "CC_PAIN", "PAIN ELEMENTAL", NULL },
{ 0, "REVENANT", NULL }, { 0, "CC_REVEN", "REVENANT", NULL },
{ 0, "MANCUBUS", NULL }, { 0, "CC_MANCU", "MANCUBUS", NULL },
{ 0, "ARCH-VILE", NULL }, { 0, "CC_ARCH", "ARCH-VILE", NULL },
{ 0, "THE SPIDER MASTERMIND", NULL }, { 0, "CC_SPIDER", "THE SPIDER MASTERMIND", NULL },
{ 0, "THE CYBERDEMON", NULL }, { 0, "CC_CYBER", "THE CYBERDEMON", NULL },
{ 0, "OUR HERO", NULL } { 0, "CC_HERO", "OUR HERO", NULL },
};
void newlanguage (cvar_t *var) // [RH] New strings from BOOM
{ { 0, "PD_BLUEC", "You need a blue card to open this door", NULL },
D_InitStrings (); { 0, "PD_REDC", "You need a red card to open this door", NULL },
G_SetLevelStrings (); { 0, "PD_YELLOWC", "You need a yellow card to open this door", NULL },
} { 0, "PD_BLUES", "You need a blue skull to open this door", NULL },
{ 0, "PD_REDS", "You need a red skull to open this door", NULL },
{ 0, "PD_YELLOWS", "You need a yellow skull to open this door", NULL },
{ 0, "PD_ANY", "Any key will open this door", NULL },
{ 0, "PD_ALL3", "You need all three keys to open this door", NULL },
{ 0, "PD_ALL6", "You need all six keys to open this door", NULL },
// [RH] Obituary strings
{ 0, "OB_SUICIDE", "suicides", NULL },
{ 0, "OB_FALLING", "fell too far", NULL },
{ 0, "OB_CRUSH", "was squished", NULL },
{ 0, "OB_EXIT", "tried to leave", NULL },
{ 0, "OB_WATER", "can't swim", NULL },
{ 0, "OB_SLIME", "mutated", NULL },
{ 0, "OB_LAVA", "melted", NULL },
{ 0, "OB_BARREL", "went boom", NULL },
{ 0, "OB_SPLASH", "stood in the wrong spot", NULL },
{ 0, "OB_R_SPLASH", "should have stood back", NULL },
{ 0, "OB_ROCKET", "should have stood back", NULL },
{ 0, "OB_KILLEDSELF", "killed %hself", NULL },
{ 0, "OB_STEALTHBABY", "thought %g saw an arachnotron", NULL },
{ 0, "OB_STEALTHVILE", "thought %g saw an archvile", NULL },
{ 0, "OB_STEALTHBARON", "thought %g saw a Baron of Hell", NULL },
{ 0, "OB_STEALTHCACO", "thought %g saw a cacodemon", NULL },
{ 0, "OB_STEALTHCHAINGUY", "thought %g saw a chaingunner", NULL },
{ 0, "OB_STEALTHDEMON", "thought %g saw a demon", NULL },
{ 0, "OB_STEALTHKNIGHT", "thought %g saw a Hell Knight", NULL },
{ 0, "OB_STEALTHIMP", "thought %g saw an imp", NULL },
{ 0, "OB_STEALTHFATSO", "thought %g saw a mancubus", NULL },
{ 0, "OB_STEALTHUNDEAD", "thought %g saw a revenant", NULL },
{ 0, "OB_STEALTHSHOTGUY", "thought %g saw a sargeant", NULL },
{ 0, "OB_STEALTHZOMBIE", "thought %g saw a zombieman", NULL },
{ 0, "OB_UNDEADHIT", "was punched by a revenant", NULL },
{ 0, "OB_IMPHIT", "was slashed by an imp", NULL },
{ 0, "OB_CACOHIT", "got too close to a cacodemon", NULL },
{ 0, "OB_DEMONHIT", "was bit by a demon", NULL },
{ 0, "OB_SPECTREHIT", "was eaten by a spectre", NULL },
{ 0, "OB_BARONHIT", "was ripped open by a Baron of Hell", NULL },
{ 0, "OB_KNIGHTHIT", "was gutted by a Hell Knight", NULL },
{ 0, "OB_ZOMBIE", "was killed by a zombieman", NULL },
{ 0, "OB_SHOTGUY", "was shot by a sargeant", NULL },
{ 0, "OB_VILE", "was incinerated by an archvile", NULL },
{ 0, "OB_UNDEAD", "couldn't evade a revevant's fireball", NULL },
{ 0, "OB_FATSO", "was squashed by a mancubus", NULL },
{ 0, "OB_CHAINGUY", "was perforated by a chaingunner", NULL },
{ 0, "OB_SKULL", "was spooked by a lost soul", NULL },
{ 0, "OB_IMP", "was burned by an imp", NULL },
{ 0, "OB_CACO", "was smitten by a cacodemon", NULL },
{ 0, "OB_BARON", "was bruised by a Baron of Hell", NULL },
{ 0, "OB_KNIGHT", "was splayed by a Hell Knight", NULL },
{ 0, "OB_SPIDER", "stood in awe of the spider demon", NULL },
{ 0, "OB_BABY", "let an arachnotron get %h", NULL },
{ 0, "OB_CYBORG", "was splattered by a cyberdemon", NULL },
{ 0, "OB_WOLFSS", "was no match for the past", NULL },
{ 0, "OB_MPFIST", "chewed on %s's fist", NULL },
{ 0, "OB_MPCHAINSAW", "was mowed over by %s's chainsaw", NULL },
{ 0, "OB_MPPISTOL", "was tickled by %s", NULL },
{ 0, "OB_MPSHOTGUN", "chewed on %s's boomstick", NULL },
{ 0, "OB_MPSSHOTGUN", "was splattered by %s's super shotgun", NULL },
{ 0, "OB_MPCHAINGUN", "was mowed down by %s", NULL },
{ 0, "OB_MPROCKET", "rode %s's rocket", NULL },
{ 0, "OB_MPR_SPLASH", "almost dodged %s's rocket", NULL },
{ 0, "OB_MPPLASMARIFLE", "was melted by %s", NULL },
{ 0, "OB_MPBFG_BOOM", "was splintered by %s's BFG", NULL },
{ 0, "OB_MPBFG_SPLASH", "couldn't hide from %s's BFG", NULL },
{ 0, "OB_MPTELEFRAG", "was telefragged by %s", NULL },
{ 0, "OB_DEFAULT", "died", NULL },
{ 0, "OB_FRIENDLY1", "mows down a teammate", NULL },
{ 0, "OB_FRIENDLY2", "checks %p glasses", NULL },
{ 0, "OB_FRIENDLY3", "gets a frag for the other team", NULL },
{ 0, "OB_FRIENDLY4", "loses another friend", NULL },
{ 0, "SAVEGAMENAME", "zdoomsv", NULL },
{ 0, "STARTUP1", "", NULL },
{ 0, "STARTUP2", "", NULL },
{ 0, "STARTUP3", "", NULL },
{ 0, "STARTUP4", "", NULL },
{ 0, "STARTUP5", "", NULL },
};
void D_InitStrings (void) void D_InitStrings (void)
{ {
byte *strings;
char *str;
char *languagename;
int i; int i;
int chunksize;
var_language->u.callback = newlanguage; for (i = 0; i < NUMSTRINGS; i++) {
languagename = var_language->string; if (Strings[i].type == str_notchanged)
ReplaceString (&Strings[i].string, Strings[i].builtin);
if (languagename) {
i = W_CheckNumForName ("LANGDATA");
str = "";
if (i != -1) {
strings = W_CacheLumpNum (i, PU_CACHE);
while (1) {
str = ReadString (&strings);
if (*str == 0)
break; // No more languages
chunksize = ReadLong (&strings);
if (!stricmp (str, languagename))
break;
strings += chunksize;
}
if (*str) {
language = english + 1;
for (i = 0; i < NUMSTRINGS; i++) {
str = ReadString (&strings);
chunksize -= strlen (str) + 1;
if (chunksize < 0) {
Printf ("Language \"%s\" is missing %d strings\n", languagename, NUMSTRINGS - i);
languagename = NULL;
break;
}
if (Strings[i].type == str_notchanged || Strings[i].type == str_foreign) {
ReplaceString (&Strings[i].string, str);
Strings[i].type = str_foreign;
}
}
}
}
if (languagename && !stricmp (languagename, "English")) {
languagename = NULL;
} else if (*str == 0) {
Printf ("Unknown language \"%s\"\n", languagename);
languagename = NULL;
}
}
if (!languagename) {
for (i = 0; i < NUMSTRINGS; i++) {
if (Strings[i].type == str_notchanged || Strings[i].type == str_foreign) {
ReplaceString (&Strings[i].string, Strings[i].builtin);
Strings[i].type = str_notchanged;
}
}
} }
endmsg[0] = QUITMSG; endmsg[0] = QUITMSG;

View file

@ -31,9 +31,6 @@ void D_InitStrings (void);
void ReplaceString (char **ptr, char *str); void ReplaceString (char **ptr, char *str);
// Misc. other strings.
#define SAVEGAMENAME "zdoomsv"
// QuitDOOM messages // QuitDOOM messages
#define NUM_QUITMESSAGES 14 #define NUM_QUITMESSAGES 14
@ -42,13 +39,13 @@ extern char* endmsg[];
// [RH] String handling has changed significantly and is no longer static per build. // [RH] String handling has changed significantly and is no longer static per build.
typedef enum { typedef enum {
str_notchanged, str_notchanged,
str_foreign,
str_patched, str_patched,
str_custom str_custom
} strtype_t; } strtype_t;
typedef struct gamestring_s { typedef struct gamestring_s {
strtype_t type; strtype_t type;
char *name;
char *builtin; char *builtin;
char *string; char *string;
} gamestring_t; } gamestring_t;
@ -370,7 +367,89 @@ typedef struct gamestring_s {
#define CC_CYBER (Strings[258].string) #define CC_CYBER (Strings[258].string)
#define CC_HERO (Strings[259].string) #define CC_HERO (Strings[259].string)
#define NUMSTRINGS 260 #define PD_BLUEC (Strings[260].string)
#define PD_REDC (Strings[261].string)
#define PD_YELLOWC (Strings[262].string)
#define PD_BLUES (Strings[263].string)
#define PD_REDS (Strings[264].string)
#define PD_YELLOWS (Strings[265].string)
#define PD_ANY (Strings[266].string)
#define PD_ALL3 (Strings[267].string)
#define PD_ALL6 (Strings[268].string)
#define OB_SUICIDE (Strings[269].string)
#define OB_FALLING (Strings[270].string)
#define OB_CRUSH (Strings[271].string)
#define OB_EXIT (Strings[272].string)
#define OB_WATER (Strings[273].string)
#define OB_SLIME (Strings[274].string)
#define OB_LAVA (Strings[275].string)
#define OB_BARREL (Strings[276].string)
#define OB_SPLASH (Strings[277].string)
#define OB_R_SPLASH (Strings[278].string)
#define OB_ROCKET (Strings[279].string)
#define OB_KILLEDSELF (Strings[280].string)
#define OB_STEALTHBABY (Strings[281].string)
#define OB_STEALTHVILE (Strings[282].string)
#define OB_STEALTHBARON (Strings[283].string)
#define OB_STEALTHCACO (Strings[284].string)
#define OB_STEALTHCHAINGUY (Strings[285].string)
#define OB_STEALTHDEMON (Strings[286].string)
#define OB_STEALTHKNIGHT (Strings[287].string)
#define OB_STEALTHIMP (Strings[288].string)
#define OB_STEALTHFATSO (Strings[289].string)
#define OB_STEALTHUNDEAD (Strings[290].string)
#define OB_STEALTHSHOTGUY (Strings[291].string)
#define OB_STEALTHZOMBIE (Strings[292].string)
#define OB_UNDEADHIT (Strings[293].string)
#define OB_IMPHIT (Strings[294].string)
#define OB_CACOHIT (Strings[295].string)
#define OB_DEMONHIT (Strings[296].string)
#define OB_SPECTREHIT (Strings[297].string)
#define OB_BARONHIT (Strings[298].string)
#define OB_KNIGHTHIT (Strings[299].string)
#define OB_ZOMBIE (Strings[300].string)
#define OB_SHOTGUY (Strings[301].string)
#define OB_VILE (Strings[302].string)
#define OB_UNDEAD (Strings[303].string)
#define OB_FATSO (Strings[304].string)
#define OB_CHAINGUY (Strings[305].string)
#define OB_SKULL (Strings[306].string)
#define OB_IMP (Strings[307].string)
#define OB_CACO (Strings[308].string)
#define OB_BARON (Strings[309].string)
#define OB_KNIGHT (Strings[310].string)
#define OB_SPIDER (Strings[311].string)
#define OB_BABY (Strings[312].string)
#define OB_CYBORG (Strings[313].string)
#define OB_WOLFSS (Strings[314].string)
#define OB_MPFIST (Strings[315].string)
#define OB_MPCHAINSAW (Strings[316].string)
#define OB_MPPISTOL (Strings[317].string)
#define OB_MPSHOTGUN (Strings[318].string)
#define OB_MPSSHOTGUN (Strings[319].string)
#define OB_MPCHAINGUN (Strings[320].string)
#define OB_MPROCKET (Strings[321].string)
#define OB_MPR_SPLASH (Strings[322].string)
#define OB_MPPLASMARIFLE (Strings[323].string)
#define OB_MPBFG_BOOM (Strings[324].string)
#define OB_MPBFG_SPLASH (Strings[325].string)
#define OB_MPTELEFRAG (Strings[326].string)
#define OB_DEFAULT (Strings[327].string)
#define OB_FRIENDLY1 (Strings[328].string)
#define OB_FRIENDLY2 (Strings[329].string)
#define OB_FRIENDLY3 (Strings[330].string)
#define OB_FRIENDLY4 (Strings[331].string)
#define SAVEGAMENAME (Strings[332].string)
#define STARTUP1 (Strings[333].string)
#define STARTUP2 (Strings[334].string)
#define STARTUP3 (Strings[335].string)
#define STARTUP4 (Strings[336].string)
#define STARTUP5 (Strings[337].string)
#define NUMSTRINGS 338
extern gamestring_t Strings[]; extern gamestring_t Strings[];

View file

@ -31,16 +31,18 @@
#include "m_swap.h" #include "m_swap.h"
#include "z_zone.h" #include "z_zone.h"
#include "v_video.h" #include "v_video.h"
#include "v_text.h"
#include "w_wad.h" #include "w_wad.h"
#include "s_sound.h" #include "s_sound.h"
// Data. // Data.
#include "dstrings.h" #include "dstrings.h"
#include "sounds.h"
#include "doomstat.h" #include "doomstat.h"
#include "r_state.h" #include "r_state.h"
#include "hu_stuff.h"
// ? // ?
//#include "doomstat.h" //#include "doomstat.h"
//#include "r_local.h" //#include "r_local.h"
@ -129,7 +131,7 @@ BOOL F_Responder (event_t *event)
// //
void F_Ticker (void) void F_Ticker (void)
{ {
int i; int i;
// check for skipping // check for skipping
// [RH] Non-commercial can be skipped now, too // [RH] Non-commercial can be skipped now, too
@ -176,9 +178,7 @@ void F_Ticker (void)
// //
// F_TextWrite // F_TextWrite
// //
extern patch_t *hu_font[HU_FONTSIZE];
#include "hu_stuff.h"
extern patch_t *hu_font[HU_FONTSIZE];
void F_TextWrite (void) void F_TextWrite (void)
@ -270,6 +270,7 @@ castinfo_t castorder[] = {
int castnum; int castnum;
int casttics; int casttics;
int castsprite; // [RH] For overriding the player sprite with a skin
state_t* caststate; state_t* caststate;
BOOL castdeath; BOOL castdeath;
int castframes; int castframes;
@ -307,6 +308,10 @@ void F_StartCast (void)
wipegamestate = -1; // force a screen wipe wipegamestate = -1; // force a screen wipe
castnum = 0; castnum = 0;
caststate = &states[mobjinfo[castorder[castnum].type].seestate]; caststate = &states[mobjinfo[castorder[castnum].type].seestate];
if (castorder[castnum].type == MT_PLAYER)
castsprite = skins[players[consoleplayer].userinfo.skin].sprite;
else
castsprite = caststate->sprite;
casttics = caststate->tics; casttics = caststate->tics;
castdeath = false; castdeath = false;
finalestage = 2; finalestage = 2;
@ -322,9 +327,8 @@ void F_StartCast (void)
// //
void F_CastTicker (void) void F_CastTicker (void)
{ {
int st; int st;
int sfx; void *origin;
void *origin;
if (--casttics > 0) if (--casttics > 0)
return; // not time to change state yet return; // not time to change state yet
@ -346,13 +350,19 @@ void F_CastTicker (void)
origin = ORIGIN_AMBIENT; origin = ORIGIN_AMBIENT;
break; break;
} }
S_StartSound (origin, mobjinfo[castorder[castnum].type].seesound); S_StartSound (origin, mobjinfo[castorder[castnum].type].seesound, 90);
} }
caststate = &states[mobjinfo[castorder[castnum].type].seestate]; caststate = &states[mobjinfo[castorder[castnum].type].seestate];
if (castorder[castnum].type == MT_PLAYER)
castsprite = skins[players[consoleplayer].userinfo.skin].sprite;
else
castsprite = caststate->sprite;
castframes = 0; castframes = 0;
} }
else else
{ {
char *sfx;
// just advance to next state in animation // just advance to next state in animation
if (caststate == &states[S_PLAY_ATK1]) if (caststate == &states[S_PLAY_ATK1])
goto stopattack; // Oh, gross hack! goto stopattack; // Oh, gross hack!
@ -363,37 +373,37 @@ void F_CastTicker (void)
// sound hacks.... // sound hacks....
switch (st) switch (st)
{ {
case S_PLAY_ATK1: sfx = sfx_dshtgn; break; case S_PLAY_ATK1: sfx = "weapons/sshotf"; break;
case S_POSS_ATK2: sfx = sfx_pistol; break; case S_POSS_ATK2: sfx = "grunt/attack"; break;
case S_SPOS_ATK2: sfx = sfx_shotgn; break; case S_SPOS_ATK2: sfx = "shotguy/attack"; break;
case S_VILE_ATK2: sfx = sfx_vilatk; break; case S_VILE_ATK2: sfx = "vile/start"; break;
case S_SKEL_FIST2: sfx = sfx_skeswg; break; case S_SKEL_FIST2: sfx = "skeleton/swing"; break;
case S_SKEL_FIST4: sfx = sfx_skepch; break; case S_SKEL_FIST4: sfx = "skeleton/melee"; break;
case S_SKEL_MISS2: sfx = sfx_skeatk; break; case S_SKEL_MISS2: sfx = "skeleton/attack"; break;
case S_FATT_ATK8: case S_FATT_ATK8:
case S_FATT_ATK5: case S_FATT_ATK5:
case S_FATT_ATK2: sfx = sfx_firsht; break; case S_FATT_ATK2: sfx = "fatso/attack"; break;
case S_CPOS_ATK2: case S_CPOS_ATK2:
case S_CPOS_ATK3: case S_CPOS_ATK3:
case S_CPOS_ATK4: sfx = sfx_shotgn; break; case S_CPOS_ATK4: sfx = "chainguy/attack"; break;
case S_TROO_ATK3: sfx = sfx_claw; break; case S_TROO_ATK3: sfx = "imp/attack"; break;
case S_SARG_ATK2: sfx = sfx_sgtatk; break; case S_SARG_ATK2: sfx = "demon/melee"; break;
case S_BOSS_ATK2: case S_BOSS_ATK2:
case S_BOS2_ATK2: case S_BOS2_ATK2:
case S_HEAD_ATK2: sfx = sfx_firsht; break; case S_HEAD_ATK2: sfx = "caco/attack"; break;
case S_SKULL_ATK2: sfx = sfx_sklatk; break; case S_SKULL_ATK2: sfx = "skull/melee"; break;
case S_SPID_ATK2: case S_SPID_ATK2:
case S_SPID_ATK3: sfx = sfx_shotgn; break; case S_SPID_ATK3: sfx = "spider/attack"; break;
case S_BSPI_ATK2: sfx = sfx_plasma; break; case S_BSPI_ATK2: sfx = "baby/attack"; break;
case S_CYBER_ATK2: case S_CYBER_ATK2:
case S_CYBER_ATK4: case S_CYBER_ATK4:
case S_CYBER_ATK6: sfx = sfx_rlaunc; break; case S_CYBER_ATK6: sfx = "weapons/rocklf"; break;
case S_PAIN_ATK3: sfx = sfx_sklatk; break; case S_PAIN_ATK3: sfx = "skull/melee"; break;
default: sfx = 0; break; default: sfx = 0; break;
} }
if (sfx) if (sfx)
S_StartSound (ORIGIN_AMBIENT, sfx); S_StartSound (ORIGIN_AMBIENT, sfx, 90);
} }
if (castframes == 12) if (castframes == 12)
@ -464,61 +474,38 @@ BOOL F_CastResponder (event_t* ev)
origin = ORIGIN_AMBIENT; origin = ORIGIN_AMBIENT;
break; break;
} }
S_StartSound (origin, mobjinfo[castorder[castnum].type].deathsound); if (castorder[castnum].type == MT_PLAYER) {
static const char sndtemplate[] = "player/%s/death1";
static const char *genders[] = { "male", "female", "neuter" };
char nametest[128];
int sndnum;
sprintf (nametest, sndtemplate, skins[players[consoleplayer].userinfo.skin].name);
sndnum = S_FindSound (nametest);
if (sndnum == -1) {
sprintf (nametest, sndtemplate, genders);
sndnum = S_FindSound (nametest);
if (sndnum == -1)
sndnum = S_FindSound ("player/male/death1");
}
S_StartSfx (origin, sndnum, 90);
} else
S_StartSound (origin, mobjinfo[castorder[castnum].type].deathsound, 90);
} }
return true; return true;
} }
void F_CastPrint (char* text) void F_CastPrint (char *text)
{ {
char* ch; char text2[80], *t2 = text2;
int c;
int cx; while (*text)
int w; *t2++ = *text++ ^ 0x80;
int width; *t2 = 0;
V_DrawTextClean ((screens[0].width - V_StringWidth (text2) * CleanXfac) >> 1,
// find width (screens[0].height * 180) / 200, text2);
ch = text;
width = 0;
while (ch)
{
c = *ch++;
if (!c)
break;
c = toupper(c) - HU_FONTSTART;
if (c < 0 || c> HU_FONTSIZE)
{
width += 4;
continue;
}
w = SHORT (hu_font[c]->width);
width += w;
}
// draw it
cx = (CleanWidth-width)/2;
ch = text;
while (ch)
{
c = *ch++;
if (!c)
break;
c = toupper(c) - HU_FONTSTART;
if (c < 0 || c> HU_FONTSIZE)
{
cx += 4;
continue;
}
w = SHORT (hu_font[c]->width);
V_DrawPatchCleanNoMove (cx, (screens[0].height * 180) / 200, &screens[0], hu_font[c]);
cx+=w;
}
} }
int V_DrawPatchFlipped (int, int, screen_t *, patch_t *); int V_DrawPatchFlipped (int, int, screen_t *, patch_t *);
@ -539,12 +526,12 @@ void F_CastDrawer (void)
F_CastPrint (castorder[castnum].name); F_CastPrint (castorder[castnum].name);
// draw the current frame in the middle of the screen // draw the current frame in the middle of the screen
sprdef = &sprites[caststate->sprite]; sprdef = &sprites[castsprite];
sprframe = &sprdef->spriteframes[ caststate->frame & FF_FRAMEMASK]; sprframe = &sprdef->spriteframes[ caststate->frame & FF_FRAMEMASK];
lump = sprframe->lump[0]; lump = sprframe->lump[0];
flip = (BOOL)sprframe->flip[0]; flip = (BOOL)sprframe->flip[0];
patch = W_CacheLumpNum (lump+firstspritelump, PU_CACHE); patch = W_CacheLumpNum (lump, PU_CACHE);
if (flip) if (flip)
V_DrawPatchFlipped (160,170,&screens[0],patch); V_DrawPatchFlipped (160,170,&screens[0],patch);
else else
@ -703,7 +690,7 @@ void F_BunnyScroll (void)
stage = 6; stage = 6;
if (stage > laststage) if (stage > laststage)
{ {
S_StartSound (ORIGIN_AMBIENT, sfx_pistol); S_StartSound (ORIGIN_AMBIENT, "weapons/pistol", 64);
laststage = stage; laststage = stage;
} }

View file

@ -24,13 +24,16 @@
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h>
#include <stddef.h>
#include "version.h"
#include "minilzo.h"
#include "m_alloc.h"
#include "doomdef.h" #include "doomdef.h"
#include "doomstat.h" #include "doomstat.h"
#include "d_proto.h" #include "d_proto.h"
#include "d_netinf.h" #include "d_netinf.h"
#include "z_zone.h" #include "z_zone.h"
#include "f_finale.h" #include "f_finale.h"
#include "m_argv.h" #include "m_argv.h"
@ -38,42 +41,26 @@
#include "m_menu.h" #include "m_menu.h"
#include "m_random.h" #include "m_random.h"
#include "i_system.h" #include "i_system.h"
#include "p_setup.h" #include "p_setup.h"
#include "p_saveg.h" #include "p_saveg.h"
#include "p_tick.h" #include "p_tick.h"
#include "d_main.h" #include "d_main.h"
#include "wi_stuff.h" #include "wi_stuff.h"
#include "hu_stuff.h" #include "hu_stuff.h"
#include "st_stuff.h" #include "st_stuff.h"
#include "am_map.h" #include "am_map.h"
#include "c_consol.h" #include "c_consol.h"
#include "c_cvars.h" #include "c_cvars.h"
#include "c_bind.h" #include "c_bind.h"
#include "c_dispch.h" #include "c_dispch.h"
// Needs access to LFB.
#include "v_video.h" #include "v_video.h"
#include "w_wad.h" #include "w_wad.h"
#include "p_local.h" #include "p_local.h"
#include "s_sound.h" #include "s_sound.h"
// Data.
#include "dstrings.h" #include "dstrings.h"
#include "sounds.h"
// SKY handling - still the wrong place.
#include "r_data.h" #include "r_data.h"
#include "r_sky.h" #include "r_sky.h"
#include "r_draw.h" #include "r_draw.h"
#include "g_game.h" #include "g_game.h"
#include "g_level.h" #include "g_level.h"
@ -81,6 +68,9 @@
#define SAVEGAMESIZE 0x2c000 #define SAVEGAMESIZE 0x2c000
#define SAVESTRINGSIZE 24 #define SAVESTRINGSIZE 24
#define TURN180_TICKS 9 // [RH] # of ticks to complete a turn180
size_t savegamesize = SAVEGAMESIZE; // killough // [RH] made global
BOOL G_CheckDemoStatus (void); BOOL G_CheckDemoStatus (void);
void G_ReadDemoTiccmd (ticcmd_t* cmd, int player); void G_ReadDemoTiccmd (ticcmd_t* cmd, int player);
@ -89,7 +79,6 @@ void G_PlayerReborn (int player);
void G_DoReborn (int playernum); void G_DoReborn (int playernum);
void G_DoLoadLevel (void);
void G_DoNewGame (void); void G_DoNewGame (void);
void G_DoLoadGame (void); void G_DoLoadGame (void);
void G_DoPlayDemo (void); void G_DoPlayDemo (void);
@ -116,7 +105,8 @@ BOOL noblit; // for comparative timing purposes
BOOL viewactive; BOOL viewactive;
cvar_t *deathmatch; // only if started as net death cvar_t *deathmatch; // deathmatch?
cvar_t *teamplay; // [RH] teamplay flag
BOOL netgame; // only true if packets are broadcast BOOL netgame; // only true if packets are broadcast
BOOL playeringame[MAXPLAYERS]; BOOL playeringame[MAXPLAYERS];
player_t players[MAXPLAYERS]; player_t players[MAXPLAYERS];
@ -131,7 +121,7 @@ BOOL demoplayback;
BOOL netdemo; BOOL netdemo;
byte* demobuffer; byte* demobuffer;
byte* demo_p; byte* demo_p;
byte* demoend; size_t maxdemosize;
byte* zdemformend; // end of FORM ZDEM chunk byte* zdemformend; // end of FORM ZDEM chunk
byte* zdembodyend; // end of ZDEM BODY chunk byte* zdembodyend; // end of ZDEM BODY chunk
BOOL singledemo; // quit after playing a demo from cmdline BOOL singledemo; // quit after playing a demo from cmdline
@ -171,7 +161,10 @@ int turnheld; // for accelerative turning
int mousex; int mousex;
int mousey; int mousey;
// joystick values are repeated // joystick values are repeated
// [RH] now, if the joystick is enabled, it will generate an event every tick
// so the values here are reset to zero after each tic build (in case
// use_joystick gets set to 0 when the joystick is off center)
int joyxmove; int joyxmove;
int joyymove; int joyymove;
@ -181,8 +174,6 @@ char savedescription[32];
// [RH] Name of screenshot file to generate (usually NULL) // [RH] Name of screenshot file to generate (usually NULL)
char *shotfile; char *shotfile;
#define BODYQUESIZE 32
mobj_t* bodyque[BODYQUESIZE]; mobj_t* bodyque[BODYQUESIZE];
int bodyqueslot; int bodyqueslot;
@ -227,14 +218,86 @@ void Cmd_Pause (player_t *plyr, int argc, char **argv)
sendpause = true; sendpause = true;
} }
static int turntick;
void Cmd_Turn180 (player_t *plyr, int argc, char **argv)
{
turntick = TURN180_TICKS;
}
//
// [RH] WeapNext and WeapPrev commands
//
static const char *weaponnames[] = {
"Fist",
"Pistol",
"Shotgun",
"Chaingun",
"Rocket Launcher",
"Plasma Gun",
"BFG9000",
"Chainsaw",
"Super Shotgun",
"Chainsaw"
};
void Cmd_WeapNext (player_t *plyr, int argc, char **argv)
{
gitem_t *item = FindItem (weaponnames[plyr->readyweapon]);
int selected_weapon;
int i, index;
if (!item)
return;
selected_weapon = ITEM_INDEX(item);
for (i = 1; i <= num_items; i++) {
index = (selected_weapon + i) % num_items;
if (!(itemlist[index].flags & IT_WEAPON))
continue;
if (!plyr->weaponowned[itemlist[index].offset])
continue;
if (!plyr->ammo[weaponinfo[itemlist[index].offset].ammo])
continue;
Impulse = itemlist[index].offset + 50;
return;
}
}
void Cmd_WeapPrev (player_t *plyr, int argc, char **argv)
{
gitem_t *item = FindItem (weaponnames[plyr->readyweapon]);
int selected_weapon;
int i, index;
if (!item)
return;
selected_weapon = ITEM_INDEX(item);
for (i = 1; i <= num_items; i++) {
index = (selected_weapon + num_items - i) % num_items;
if (!(itemlist[index].flags & IT_WEAPON))
continue;
if (!plyr->weaponowned[itemlist[index].offset])
continue;
if (!plyr->ammo[weaponinfo[itemlist[index].offset].ammo])
continue;
Impulse = itemlist[index].offset + 50;
return;
}
}
// //
// G_BuildTiccmd // G_BuildTiccmd
// Builds a ticcmd from all of the available inputs // Builds a ticcmd from all of the available inputs
// or reads it from the demo buffer. // or reads it from the demo buffer.
// If recording a demo, write it out // If recording a demo, write it out
// //
void G_BuildTiccmd (ticcmd_t* cmd) void G_BuildTiccmd (ticcmd_t *cmd)
{ {
BOOL strafe; BOOL strafe;
int speed; int speed;
int tspeed; int tspeed;
@ -242,66 +305,53 @@ void G_BuildTiccmd (ticcmd_t* cmd)
int side; int side;
int look; int look;
int fly; int fly;
ticcmd_t* base; ticcmd_t* base;
base = I_BaseTiccmd (); // empty, or external driver base = I_BaseTiccmd (); // empty, or external driver
memcpy (cmd,base,sizeof(*cmd)); memcpy (cmd,base,sizeof(*cmd));
cmd->consistancy = cmd->consistancy = consistancy[consoleplayer][maketic%BACKUPTICS];
consistancy[consoleplayer][maketic%BACKUPTICS];
strafe = Actions & ACTION_STRAFE; strafe = Actions & ACTION_STRAFE;
speed = ((Actions & ACTION_SPEED) || (cl_run->value)) ? 1 : 0; speed = ((Actions & ACTION_SPEED) || (cl_run->value)) ? 1 : 0;
forward = side = look = fly = 0;
// use two stage accelerative turning
// on the keyboard and joystick
if (joyxmove < 0
|| joyxmove > 0
|| (Actions & ACTION_LEFT)
|| (Actions & ACTION_RIGHT))
turnheld += ticdup;
else
turnheld = 0;
if (turnheld < SLOWTURNTICS) forward = side = look = fly = 0;
tspeed = 2; // slow turn
else // [RH] only use two stage accelerative turning on the keyboard
// and not the joystick, since we treat the joystick as
// the analog device it is.
if ((Actions & ACTION_LEFT) || (Actions & ACTION_RIGHT))
turnheld += ticdup;
else
turnheld = 0;
if (turnheld < SLOWTURNTICS)
tspeed = 2; // slow turn
else
tspeed = speed; tspeed = speed;
// let movement keys cancel each other out // let movement keys cancel each other out
if (strafe) if (strafe)
{ {
if (Actions & ACTION_RIGHT) if (Actions & ACTION_RIGHT)
{ {
// fprintf(stderr, "strafe right\n"); // fprintf(stderr, "strafe right\n");
side += sidemove[speed]; side += sidemove[speed];
} }
if (Actions & ACTION_LEFT) if (Actions & ACTION_LEFT)
{ {
// fprintf(stderr, "strafe left\n"); // fprintf(stderr, "strafe left\n");
side -= sidemove[speed]; side -= sidemove[speed];
} }
if (joyxmove > 0) }
side += sidemove[speed]; else
if (joyxmove < 0) {
side -= sidemove[speed]; if (Actions & ACTION_RIGHT)
cmd->ucmd.yaw -= angleturn[tspeed];
} if (Actions & ACTION_LEFT)
else cmd->ucmd.yaw += angleturn[tspeed];
{ }
if (Actions & ACTION_RIGHT)
cmd->ucmd.yaw -= angleturn[tspeed];
if (Actions & ACTION_LEFT)
cmd->ucmd.yaw += angleturn[tspeed];
if (joyxmove > 0)
cmd->ucmd.yaw -= angleturn[tspeed];
if (joyxmove < 0)
cmd->ucmd.yaw += angleturn[tspeed];
}
if (Actions & ACTION_LOOKUP) if (Actions & ACTION_LOOKUP)
look += lookspeed[speed]; look += lookspeed[speed];
@ -325,30 +375,45 @@ void G_BuildTiccmd (ticcmd_t* cmd)
forward -= forwardmove[speed]; forward -= forwardmove[speed];
} }
if (joyymove < 0) if (Actions & ACTION_MOVERIGHT)
forward += forwardmove[speed]; side += sidemove[speed];
if (joyymove > 0) if (Actions & ACTION_MOVELEFT)
forward -= forwardmove[speed];
if (Actions & ACTION_MOVERIGHT)
side += sidemove[speed];
if (Actions & ACTION_MOVELEFT)
side -= sidemove[speed]; side -= sidemove[speed];
// buttons // buttons
if (Actions & ACTION_ATTACK) if (Actions & ACTION_ATTACK)
cmd->ucmd.buttons |= BT_ATTACK; cmd->ucmd.buttons |= BT_ATTACK;
if (Actions & ACTION_USE) if (Actions & ACTION_USE)
cmd->ucmd.buttons |= BT_USE; cmd->ucmd.buttons |= BT_USE;
if (Actions & ACTION_JUMP) if (Actions & ACTION_JUMP)
cmd->ucmd.buttons |= BT_JUMP; cmd->ucmd.buttons |= BT_JUMP;
// chainsaw overrides // [RH] Handle impulses. If they are between 1 and 7,
if (Impulse >= 1 && Impulse <= NUMWEAPONS-1) { // they get sent as weapon change events.
if (Impulse >= 1 && Impulse <= 7) {
cmd->ucmd.buttons |= BT_CHANGE; cmd->ucmd.buttons |= BT_CHANGE;
cmd->ucmd.buttons |= (Impulse - 1) << BT_WEAPONSHIFT; cmd->ucmd.buttons |= (Impulse - 1) << BT_WEAPONSHIFT;
Impulse = 0; } else {
cmd->ucmd.impulse = Impulse;
}
Impulse = 0;
// [RH] Scale joystick moves to full range of allowed speeds
if (strafe || lookstrafe->value)
side += (MAXPLMOVE * joyxmove) / 256;
else
cmd->ucmd.yaw -= (angleturn[1] * joyxmove) / 256;
// [RH] Scale joystick moves over full range
if (Actions & ACTION_MLOOK) {
if (invertmouse->value)
look -= (joyymove * 32767) / 256;
else
look += (joyymove * 32767) / 256;
} else {
forward += (MAXPLMOVE * joyymove) / 256;
} }
if ((Actions & ACTION_MLOOK) || freelook->value) { if ((Actions & ACTION_MLOOK) || freelook->value) {
@ -359,10 +424,6 @@ void G_BuildTiccmd (ticcmd_t* cmd)
look -= val; look -= val;
else else
look += val; look += val;
if (look > 32767)
look = 32767;
else if (look < -32767)
look = -32767;
} else { } else {
forward += (int)((float)mousey * m_forward->value); forward += (int)((float)mousey * m_forward->value);
} }
@ -370,6 +431,11 @@ void G_BuildTiccmd (ticcmd_t* cmd)
if (sendcenterview) { if (sendcenterview) {
sendcenterview = false; sendcenterview = false;
look = -32768; look = -32768;
} else {
if (look > 32767)
look = 32767;
else if (look < -32767)
look = -32767;
} }
if (strafe || lookstrafe->value) if (strafe || lookstrafe->value)
@ -378,7 +444,7 @@ void G_BuildTiccmd (ticcmd_t* cmd)
cmd->ucmd.yaw -= (int)((float)(mousex*0x8) * m_yaw->value); cmd->ucmd.yaw -= (int)((float)(mousex*0x8) * m_yaw->value);
mousex = mousey = 0; mousex = mousey = 0;
if (forward > MAXPLMOVE) if (forward > MAXPLMOVE)
forward = MAXPLMOVE; forward = MAXPLMOVE;
else if (forward < -MAXPLMOVE) else if (forward < -MAXPLMOVE)
@ -408,6 +474,15 @@ void G_BuildTiccmd (ticcmd_t* cmd)
cmd->ucmd.forwardmove <<= 8; cmd->ucmd.forwardmove <<= 8;
cmd->ucmd.sidemove <<= 8; cmd->ucmd.sidemove <<= 8;
// [RH] 180-degree turn overrides all other yaws
if (turntick) {
turntick--;
cmd->ucmd.yaw = (ANG180 / TURN180_TICKS) >> 16;
}
joyxmove = 0;
joyymove = 0;
} }
@ -418,7 +493,8 @@ static void ChangeSpy (void)
// [RH] Use some BOOM code here: // [RH] Use some BOOM code here:
ST_Start(); // killough 3/7/98: switch status bar views too ST_Start(); // killough 3/7/98: switch status bar views too
HU_Start(); HU_Start();
S_UpdateSounds(players[displayplayer].mo); players[consoleplayer].camera = players[displayplayer].mo;
S_UpdateSounds(players[consoleplayer].camera);
} }
void Cmd_SpyNext (player_t *plyr, int argc, char **argv) void Cmd_SpyNext (player_t *plyr, int argc, char **argv)
@ -461,8 +537,7 @@ BOOL G_Responder (event_t* ev)
// any other key pops up menu if in demos // any other key pops up menu if in demos
// [RH] But only if the key isn't bound to a "special" command // [RH] But only if the key isn't bound to a "special" command
if (gameaction == ga_nothing && !singledemo && if (gameaction == ga_nothing && !singledemo &&
(demoplayback || gamestate == GS_DEMOSCREEN) (demoplayback || gamestate == GS_DEMOSCREEN))
)
{ {
char *cmd = C_GetBinding (ev->data1); char *cmd = C_GetBinding (ev->data1);
@ -483,11 +558,11 @@ BOOL G_Responder (event_t* ev)
M_StartControlPanel (); M_StartControlPanel ();
return true; return true;
} else { } else {
return C_DoKey (ev->data1, false); return C_DoKey (ev);
} }
} }
if (cmd && cmd[0] == '+') if (cmd && cmd[0] == '+')
return C_DoKey (ev->data1, true); return C_DoKey (ev);
return false; return false;
} }
@ -520,12 +595,12 @@ BOOL G_Responder (event_t* ev)
switch (ev->type) switch (ev->type)
{ {
case ev_keydown: case ev_keydown:
if (C_DoKey (ev->data1, false)) if (C_DoKey (ev))
return true; return true;
break; break;
case ev_keyup: case ev_keyup:
C_DoKey (ev->data1, true); C_DoKey (ev);
break; break;
// [RH] mouse buttons are now sent with key up/down events // [RH] mouse buttons are now sent with key up/down events
@ -578,7 +653,7 @@ void G_Ticker (void)
switch (gameaction) switch (gameaction)
{ {
case ga_loadlevel: case ga_loadlevel:
G_DoLoadLevel (); G_DoLoadLevel (-1);
break; break;
case ga_newgame: case ga_newgame:
G_DoNewGame (); G_DoNewGame ();
@ -610,9 +685,14 @@ void G_Ticker (void)
} }
gameaction = ga_nothing; gameaction = ga_nothing;
break; break;
case ga_fullconsole:
C_FullConsole ();
gameaction = ga_nothing;
break;
case ga_nothing: case ga_nothing:
break; break;
} }
C_AdjustBottom ();
} }
// get commands, check consistancy, // get commands, check consistancy,
@ -636,7 +716,7 @@ void G_Ticker (void)
if (cmd->ucmd.forwardmove > TURBOTHRESHOLD if (cmd->ucmd.forwardmove > TURBOTHRESHOLD
&& !(gametic&31) && ((gametic>>5)&3) == i ) && !(gametic&31) && ((gametic>>5)&3) == i )
{ {
Printf ("%s is turbo!\n",players[i].userinfo->netname); Printf ("%s is turbo!\n", players[i].userinfo.netname);
} }
if (netgame && !netdemo && !(gametic%ticdup) ) if (netgame && !netdemo && !(gametic%ticdup) )
@ -764,7 +844,7 @@ void G_PlayerReborn (int player)
int killcount; int killcount;
int itemcount; int itemcount;
int secretcount; int secretcount;
userinfo_t *userinfo; // [RH] Save userinfo userinfo_t userinfo; // [RH] Save userinfo
p = &players[player]; p = &players[player];
@ -773,7 +853,7 @@ void G_PlayerReborn (int player)
killcount = p->killcount; killcount = p->killcount;
itemcount = p->itemcount; itemcount = p->itemcount;
secretcount = p->secretcount; secretcount = p->secretcount;
userinfo = p->userinfo; memcpy (&userinfo, &p->userinfo, sizeof(userinfo));
memset (p, 0, sizeof(*p)); memset (p, 0, sizeof(*p));
@ -782,17 +862,17 @@ void G_PlayerReborn (int player)
p->killcount = killcount; p->killcount = killcount;
p->itemcount = itemcount; p->itemcount = itemcount;
p->secretcount = secretcount; p->secretcount = secretcount;
p->userinfo = userinfo; memcpy (&p->userinfo, &userinfo, sizeof(userinfo));
p->usedown = p->attackdown = p->jumpdown = true; // don't do anything immediately p->usedown = p->attackdown = p->jumpdown = true; // don't do anything immediately
p->playerstate = PST_LIVE; p->playerstate = PST_LIVE;
p->health = deh_StartHealth; // [RH] Used to be MAXHEALTH p->health = deh.StartHealth; // [RH] Used to be MAXHEALTH
p->readyweapon = p->pendingweapon = wp_pistol; p->readyweapon = p->pendingweapon = wp_pistol;
p->weaponowned[wp_fist] = true; p->weaponowned[wp_fist] = true;
p->weaponowned[wp_pistol] = true; p->weaponowned[wp_pistol] = true;
p->ammo[am_clip] = deh_StartBullets; // [RH] Used to be 50 p->ammo[am_clip] = deh.StartBullets; // [RH] Used to be 50
for (i=0 ; i<NUMAMMO ; i++) for (i = 0; i < NUMAMMO; i++)
p->maxammo[i] = maxammo[i]; p->maxammo[i] = maxammo[i];
} }
@ -824,15 +904,25 @@ BOOL G_CheckSpot (int playernum, mapthing2_t *mthing)
if (!players[playernum].mo) if (!players[playernum].mo)
{ {
// first spawn of level, before corpses // first spawn of level, before corpses
for (i=0 ; i<playernum ; i++) for (i = 0; i < playernum; i++)
if (players[i].mo->x == x if (players[i].mo->x == x && players[i].mo->y == y)
&& players[i].mo->y == y)
return false; return false;
return true; return true;
} }
players[playernum].mo->z = z; // [RH] Checks are now full 3-D players[playernum].mo->z = z; // [RH] Checks are now full 3-D
if (!P_CheckPosition (players[playernum].mo, x, y))
// killough 4/2/98: fix bug where P_CheckPosition() uses a non-solid
// corpse to detect collisions with other players in DM starts
//
// Old code:
// if (!P_CheckPosition (players[playernum].mo, x, y))
// return false;
players[playernum].mo->flags |= MF_SOLID;
i = P_CheckPosition(players[playernum].mo, x, y);
players[playernum].mo->flags &= ~MF_SOLID;
if (!i)
return false; return false;
// flush an old corpse if needed // flush an old corpse if needed
@ -848,9 +938,8 @@ BOOL G_CheckSpot (int playernum, mapthing2_t *mthing)
, z , z
, MT_TFOG, 0); , MT_TFOG, 0);
// [RH] consoleplayer changed to displayplayer if (level.time)
if (players[displayplayer].viewz != 1) S_StartSound (mo, "misc/teleport", 32); // don't start sound on first frame
S_StartSound (mo, sfx_telept); // don't start sound on first frame
return true; return true;
} }
@ -912,12 +1001,12 @@ static mapthing2_t *SelectRandomDeathmatchSpot (int playernum, int selections)
i = P_Random (pr_dmspawn) % selections; i = P_Random (pr_dmspawn) % selections;
if (G_CheckSpot (playernum, &deathmatchstarts[i]) ) if (G_CheckSpot (playernum, &deathmatchstarts[i]) )
{ {
return &deathmatchstarts[i]; return &deathmatchstarts[i];
} }
} }
return NULL; // [RH] return a spot anyway, since we allow telefragging when a player spawns
return olddemo ? NULL : &deathmatchstarts[i];
} }
void G_DeathMatchSpawnPlayer (int playernum) void G_DeathMatchSpawnPlayer (int playernum)
@ -926,10 +1015,9 @@ void G_DeathMatchSpawnPlayer (int playernum)
mapthing2_t *spot; mapthing2_t *spot;
selections = deathmatch_p - deathmatchstarts; selections = deathmatch_p - deathmatchstarts;
// [RH] 4 changed to doomcom->numplayers // [RH] We can get by with just 1 deathmatch start
if (selections < doomcom->numplayers) if (selections < 1)
I_Error ("Only %i deathmatch spots, %d required", I_Error ("No deathmatch starts");
selections, doomcom->numplayers);
// At level start, none of the players have mobjs attached to them, // At level start, none of the players have mobjs attached to them,
// so we always use the random deathmatch spawn. During the game, // so we always use the random deathmatch spawn. During the game,
@ -969,7 +1057,8 @@ void G_DoReborn (int playernum)
// respawn at the start // respawn at the start
// first dissasociate the corpse // first dissasociate the corpse
players[playernum].mo->player = NULL; if (players[playernum].mo)
players[playernum].mo->player = NULL;
// spawn at random spot if in death match // spawn at random spot if in death match
if (deathmatch->value) if (deathmatch->value)
@ -990,10 +1079,9 @@ void G_DoReborn (int playernum)
if (G_CheckSpot (playernum, &playerstarts[i]) ) if (G_CheckSpot (playernum, &playerstarts[i]) )
{ {
int oldtype = playerstarts[i].type; int oldtype = playerstarts[i].type;
if (playernum < 4)
playerstarts[i].type = playernum+1; // fake as other player // fake as other player
else playerstarts[i].type = (playernum < 4) ? playernum + 1 : playernum + 4001 - 4;
playerstarts[i].type = playernum+4001-4; // [RH] fake as high player
P_SpawnPlayer (&playerstarts[i]); P_SpawnPlayer (&playerstarts[i]);
playerstarts[i].type = oldtype; // restore playerstarts[i].type = oldtype; // restore
return; return;
@ -1022,7 +1110,7 @@ void G_ScreenShot (char *filename)
extern BOOL setsizeneeded; extern BOOL setsizeneeded;
void R_ExecuteSetViewSize (void); void R_ExecuteSetViewSize (void);
char savename[256]; char savename[256];
void G_LoadGame (char* name) void G_LoadGame (char* name)
{ {
@ -1030,52 +1118,59 @@ void G_LoadGame (char* name)
gameaction = ga_loadgame; gameaction = ga_loadgame;
} }
#define VERSIONSIZE 16
void G_DoLoadGame (void) void G_DoLoadGame (void)
{ {
int length; int length;
int i; int i;
char vcheck[VERSIONSIZE];
char mapname[9]; char mapname[9];
gameaction = ga_nothing; gameaction = ga_nothing;
length = M_ReadFile (savename, &savebuffer); length = M_ReadFile (savename, &savebuffer);
save_p = savebuffer + SAVESTRINGSIZE; save_p = savebuffer + SAVESTRINGSIZE; // skip the description field
// skip the description field if (strncmp (save_p, SAVESIG, 16)) // Bad version
memset (vcheck,0,sizeof(vcheck)); I_Error ("Savegame is from a different version\n");
sprintf (vcheck,"version %ia",VERSION);
if (strcmp (save_p, vcheck)) save_p += 16;
return; // bad version
save_p += VERSIONSIZE;
memcpy (mapname, save_p, 8); memcpy (mapname, save_p, 8);
mapname[8] = 0; mapname[8] = 0;
save_p += 8; save_p += 8;
for (i=0 ; i<MAXPLAYERS ; i++) for (i=0 ; i<MAXPLAYERS ; i++)
playeringame[i] = *save_p++; playeringame[i] = *save_p++;
C_ReadCVars (&save_p); // [RH] Read server info cvars C_ReadCVars (&save_p); // [RH] read server info cvars
// load a base level
G_InitNew (mapname);
// dearchive all the modifications // dearchive all the modifications
P_UnArchiveLevelLocals (); // [RH] dearchive level locals G_UnArchiveSnapshots (); // [RH] restore all level snapshots
P_UnArchivePlayers (); P_UnArchivePlayers ();
P_UnArchiveWorld ();
P_UnArchiveThinkers ();
P_UnArchiveSpecials ();
P_UnArchiveRNGState (); // [RH] retrieve the state of the RNG P_UnArchiveRNGState (); // [RH] retrieve the state of the RNG
P_UnArchiveACSDefereds (); // [RH] restore script info on other maps
// load a base level
{
// [RH] G_InitNew zaps these
byte *saved = save_p, *savedbuffer = savebuffer;
savegamerestore = true; // [RH] Use the player mobjs in the savegame
G_InitNew (mapname);
savegamerestore = false;
save_p = saved;
savebuffer = savedbuffer;
}
level.time = ReadLong (&save_p);
memcpy (WorldVars, save_p, sizeof(WorldVars)); // [RH] restore world vars
save_p += sizeof(WorldVars);
if (*save_p != 0x1d) if (*save_p != 0x1d)
I_Error ("Bad savegame"); I_Error ("Bad savegame");
// done // done
Z_Free (savebuffer); Z_Free (savebuffer);
save_p = savebuffer = NULL;
if (setsizeneeded) if (setsizeneeded)
R_ExecuteSetViewSize (); R_ExecuteSetViewSize ();
@ -1097,56 +1192,85 @@ void G_SaveGame (int slot, char *description)
sendsave = true; sendsave = true;
} }
void G_BuildSaveName (char *name, int slot)
{
if (M_CheckParm ("-cdrom"))
sprintf(name, "c:\\zdoomdat\\%s%d.zds", SAVEGAMENAME, slot);
else
sprintf (name, "%s%d.zds", SAVEGAMENAME, slot);
}
// Check for overrun and realloc if necessary -- Lee Killough 1/22/98
void CheckSaveGame (size_t size)
{
size_t pos = save_p - savebuffer;
size += 1024; // breathing room
if (pos+size > savegamesize)
save_p = (savebuffer = Realloc (savebuffer,
savegamesize += (size+1023) & ~1023)) + pos;
}
void G_DoSaveGame (void) void G_DoSaveGame (void)
{ {
char name[100]; char name[100];
char name2[VERSIONSIZE];
char* description; char* description;
int length;
int i; int i;
if (M_CheckParm("-cdrom")) G_SnapshotLevel ();
sprintf(name,"c:\\doomdata\\"SAVEGAMENAME"%d.dsg",savegameslot);
else G_BuildSaveName (name, savegameslot);
sprintf (name,SAVEGAMENAME"%d.dsg",savegameslot);
description = savedescription; description = savedescription;
save_p = savebuffer = Z_Malloc (SAVEGAMESIZE + 0x4000, PU_STATIC, 0); save_p = savebuffer = Malloc (savegamesize);
CheckSaveGame (SAVESTRINGSIZE+16+sizeof(unsigned long));
memcpy (save_p, description, SAVESTRINGSIZE); memcpy (save_p, description, SAVESTRINGSIZE);
save_p += SAVESTRINGSIZE; save_p += SAVESTRINGSIZE;
memset (name2,0,sizeof(name2));
sprintf (name2,"version %ia",VERSION); strncpy (save_p, SAVESIG, 16);
memcpy (save_p, name2, VERSIONSIZE); save_p += 16;
save_p += VERSIONSIZE;
memcpy (save_p, level.mapname, 8); memcpy (save_p, level.mapname, 8);
save_p += 8; save_p += 8;
for (i=0 ; i<MAXPLAYERS ; i++) for (i=0 ; i<MAXPLAYERS ; i++)
*save_p++ = playeringame[i]; *save_p++ = playeringame[i];
C_WriteCVars (&save_p, CVAR_SERVERINFO); // [RH] Save serverinfo cvars C_WriteCVars (&save_p, CVAR_SERVERINFO); // [RH] Save serverinfo cvars
P_ArchiveLevelLocals (); // [RH] Archive level locals // killough 3/22/98: add Z_CheckHeap after each call to ensure consistency
Z_CheckHeap ();
G_ArchiveSnapshots (); // [RH] save level snapshots
Z_CheckHeap ();
P_ArchivePlayers (); P_ArchivePlayers ();
P_ArchiveWorld (); Z_CheckHeap ();
P_ArchiveThinkers ();
P_ArchiveSpecials ();
P_ArchiveRNGState (); // [RH] save the state of the RNG P_ArchiveRNGState (); // [RH] save the state of the RNG
Z_CheckHeap ();
P_ArchiveACSDefereds (); // [RH] archive script info on other maps
Z_CheckHeap ();
WriteLong (level.time, &save_p);
memcpy (save_p, WorldVars, sizeof(WorldVars)); // [RH] Save world vars
save_p += sizeof(WorldVars);
*save_p++ = 0x1d; // consistancy marker *save_p++ = 0x1d; // consistancy marker
length = save_p - savebuffer; {
if (length > SAVEGAMESIZE) FILE *file = fopen (name, "wb");
I_Error ("Savegame buffer overrun");
M_WriteFile (name, savebuffer, length); if (file) {
Z_Free (savebuffer); fwrite (savebuffer, 1, save_p - savebuffer, file);
fclose (file);
} else {
Printf ("Could not create savegame\n");
}
}
free (savebuffer);
savebuffer = save_p = NULL;
gameaction = ga_nothing; gameaction = ga_nothing;
savedescription[0] = 0; savedescription[0] = 0;
players[consoleplayer].message = GGSAVED; players[consoleplayer].message = GGSAVED;
// draw the pattern into the back screen
R_FillBackScreen ();
} }
@ -1228,6 +1352,7 @@ void Cmd_Stop (player_t *plyr, int argc, char **argv)
{ {
stoprecording = true; stoprecording = true;
} }
extern byte *lenspot;
void G_WriteDemoTiccmd (ticcmd_t *cmd, int player) void G_WriteDemoTiccmd (ticcmd_t *cmd, int player)
{ {
@ -1263,10 +1388,15 @@ void G_WriteDemoTiccmd (ticcmd_t *cmd, int player)
memcpy (&LastUserCmd, &cmd->ucmd, sizeof(usercmd_t)); memcpy (&LastUserCmd, &cmd->ucmd, sizeof(usercmd_t));
} }
if (demo_p > demoend - 16) { // [RH] Bigger safety margin
// no more space if (demo_p > demobuffer + maxdemosize - 64) {
G_CheckDemoStatus (); ptrdiff_t pos = demo_p - demobuffer;
return; ptrdiff_t spot = lenspot - demobuffer;
// [RH] Allocate more space for the demo
maxdemosize += 0x20000;
demobuffer = Realloc (demobuffer, maxdemosize);
demo_p = demobuffer + pos;
lenspot = demobuffer + spot;
} }
// if (!clonecount) // if (!clonecount)
@ -1281,21 +1411,17 @@ void G_WriteDemoTiccmd (ticcmd_t *cmd, int player)
void G_RecordDemo (char* name) void G_RecordDemo (char* name)
{ {
int i; int i;
int maxsize;
usergame = false; usergame = false;
strcpy (demoname, name); strcpy (demoname, name);
FixPathSeperator (demoname); FixPathSeperator (demoname);
DefaultExtension (demoname, ".lmp"); DefaultExtension (demoname, ".lmp");
maxsize = 0x20000;
i = M_CheckParm ("-maxdemo"); i = M_CheckParm ("-maxdemo");
if (i && i<myargc-1) { if (i && i<myargc-1)
maxsize = atoi(myargv[i+1])*1024; maxdemosize = atoi(myargv[i+1])*1024;
if (maxsize < 0x20000) if (maxdemosize < 0x20000)
maxsize = 0x20000; maxdemosize = 0x20000;
} demobuffer = Malloc (maxdemosize);
demobuffer = Z_Malloc (maxsize,PU_STATIC,NULL);
demoend = demobuffer + maxsize;
demorecording = true; demorecording = true;
} }
@ -1521,25 +1647,23 @@ void G_DoPlayDemo (void)
SetCVarFloat (gameskill, skill); SetCVarFloat (gameskill, skill);
AddCommandString ("set fraglimit 0; set timelimit 0; set cheats 0, sv_gravity 800"); AddCommandString ("set fraglimit 0; set timelimit 0; set cheats 0; sv_gravity 800");
{ {
// Setup compatible userinfo // Setup compatible userinfo
static char greenPlayer[] = "\\name\\Green\\autoaim\\50000\\color\\74 fc 6c"; static char *playerStreams[4] = {
static char indigoPlayer[] = "\\name\\Indigo\\autoaim\\50000\\color\\80 80 80"; "\\name\\Green\\autoaim\\5000\\color\\74 fc 6c\\skin\\base\\gender\\male",
static char brownPlayer[] = "\\name\\Brown\\autoaim\\50000\\color\\bc 78 48"; "\\name\\Indigo\\autoaim\\5000\\color\\80 80 80\\skin\\base\\gender\\male",
static char redPlayer[] = "\\name\\Red\\autoaim\\50000\\color\\fc 00 00"; "\\name\\Brown\\autoaim\\5000\\color\\bc 78 48\\skin\\base\\gender\\male",
"\\name\\Red\\autoaim\\5000\\color\\fc 00 00\\skin\\base\\gender\\male"
};
byte *stream; byte *stream;
int jookie;
stream = greenPlayer; for (jookie = 0; jookie < 4; jookie++) {
D_ReadUserInfoStrings (0, &stream, false); stream = playerStreams[jookie];
stream = indigoPlayer; D_ReadUserInfoStrings (jookie, &stream, false);
D_ReadUserInfoStrings (1, &stream, false); }
stream = brownPlayer;
D_ReadUserInfoStrings (2, &stream, false);
stream = redPlayer;
D_ReadUserInfoStrings (3, &stream, false);
R_BuildCompatiblePlayerTranslations (); R_BuildCompatiblePlayerTranslations ();
} }
} else { } else {
@ -1589,10 +1713,12 @@ extern cvar_t *color;
BOOL G_CheckDemoStatus (void) BOOL G_CheckDemoStatus (void)
{ {
if (!demorecording) {
// [RH] Restore the player's userinfo settings. // [RH] Restore the player's userinfo settings.
D_UserInfoChanged (name); D_UserInfoChanged (name);
D_UserInfoChanged (autoaim); D_UserInfoChanged (autoaim);
D_UserInfoChanged (color); D_UserInfoChanged (color);
}
if (timingdemo) if (timingdemo)
{ {
@ -1602,8 +1728,8 @@ BOOL G_CheckDemoStatus (void)
endtime = I_GetTimeReally () - starttime; endtime = I_GetTimeReally () - starttime;
C_RestoreCVars (); // [RH] Restore cvars demo might have changed C_RestoreCVars (); // [RH] Restore cvars demo might have changed
I_Error ("timed %i gametics in %i realtics (%.1f fps)",gametic I_Error ("timed %i gametics in %i realtics (%.1f fps)", gametic,
, endtime, (float)gametic/(float)endtime*(float)TICRATE); endtime, (float)gametic/(float)endtime*(float)TICRATE);
} }
if (demoplayback) if (demoplayback)
@ -1611,7 +1737,7 @@ BOOL G_CheckDemoStatus (void)
C_RestoreCVars (); // [RH] Restore cvars demo might have changed C_RestoreCVars (); // [RH] Restore cvars demo might have changed
if (singledemo) if (singledemo)
I_Quit (); exit (0);
Z_ChangeTag (demobuffer, PU_CACHE); Z_ChangeTag (demobuffer, PU_CACHE);
olddemo = false; olddemo = false;
@ -1644,10 +1770,10 @@ BOOL G_CheckDemoStatus (void)
WriteLong (demo_p - demobuffer - 8, &formlen); WriteLong (demo_p - demobuffer - 8, &formlen);
M_WriteFile (demoname, demobuffer, demo_p - demobuffer); M_WriteFile (demoname, demobuffer, demo_p - demobuffer);
Z_Free (demobuffer); free (demobuffer);
demorecording = false; demorecording = false;
stoprecording = false; stoprecording = false;
I_Error ("Demo %s recorded",demoname); Printf ("Demo %s recorded\n", demoname);
} }
return false; return false;

View file

@ -42,6 +42,7 @@ void G_LoadGame (char* name);
void G_DoLoadGame (void); void G_DoLoadGame (void);
// Called by M_Responder. // Called by M_Responder.
void G_BuildSaveName (char *name, int slot);
void G_SaveGame (int slot, char* description); void G_SaveGame (int slot, char* description);
// Only called by startup code. // Only called by startup code.
@ -62,10 +63,10 @@ void G_ScreenShot (char *filename);
void G_PlayerFinishLevel (int player); void G_PlayerFinishLevel (int player);
#define BODYQUESIZE 32
struct mobj_s;
extern struct mobj_s *bodyque[BODYQUESIZE];
extern int bodyqueslot;
#endif #endif
//-----------------------------------------------------------------------------
//
// $Log:$
//
//-----------------------------------------------------------------------------

View file

@ -22,6 +22,16 @@
#include "v_video.h" #include "v_video.h"
#include "st_stuff.h" #include "st_stuff.h"
#include "hu_stuff.h" #include "hu_stuff.h"
#include "p_saveg.h"
#include "p_acs.h"
#include "d_proto.h"
#include "minilzo.h"
// [RH] Output buffer size for LZO compression.
// Extra space in case uncompressable.
#define OUT_LEN(a) ((a) + (a) / 64 + 16 + 3)
static level_info_t *FindDefLevelInfo (char *mapname); static level_info_t *FindDefLevelInfo (char *mapname);
static cluster_info_t *FindDefClusterInfo (int cluster); static cluster_info_t *FindDefClusterInfo (int cluster);
@ -32,7 +42,12 @@ extern int timingdemo;
int starttime; int starttime;
// ACS variables with world scope
int WorldVars[NUM_WORLDVARS];
extern BOOL netdemo; extern BOOL netdemo;
BOOL savegamerestore;
extern int mousex, mousey, joyxmove, joyymove, Impulse; extern int mousex, mousey, joyxmove, joyymove, Impulse;
extern BOOL sendpause, sendsave, sendcenterview; extern BOOL sendpause, sendsave, sendcenterview;
@ -46,6 +61,9 @@ static cluster_info_t *wadclusterinfos;
static int numwadlevelinfos = 0; static int numwadlevelinfos = 0;
static int numwadclusterinfos = 0; static int numwadclusterinfos = 0;
BOOL HexenHack;
static int FindWadLevelInfo (char *name) static int FindWadLevelInfo (char *name)
{ {
int i; int i;
@ -110,6 +128,9 @@ void G_ParseMapInfo (void)
int map = atoi (com_token); int map = atoi (com_token);
sprintf (com_token, "MAP%02u", map); sprintf (com_token, "MAP%02u", map);
SKYFLATNAME[5] = 0; SKYFLATNAME[5] = 0;
// Hexen levels are automatically nointermission
levelflags = LEVEL_NOINTERMISSION;
HexenHack = true;
} }
if ((levelindex = FindWadLevelInfo (com_token)) == -1) if ((levelindex = FindWadLevelInfo (com_token)) == -1)
{ {
@ -118,14 +139,27 @@ void G_ParseMapInfo (void)
memset (wadlevelinfos + levelindex, 0, sizeof(level_pwad_info_t)); memset (wadlevelinfos + levelindex, 0, sizeof(level_pwad_info_t));
} }
levelinfo = wadlevelinfos + levelindex; levelinfo = wadlevelinfos + levelindex;
levelinfo->snapshot = NULL;
levelinfo->outsidefog = 0xff000000;
strncpy (levelinfo->mapname, com_token, 8); strncpy (levelinfo->mapname, com_token, 8);
strncpy (levelinfo->fadetable, "COLORMAP", 8);
data = COM_Parse (data); data = COM_Parse (data);
ReplaceString (&levelinfo->level_name, com_token); ReplaceString (&levelinfo->level_name, com_token);
mapinfo = data; mapinfo = data;
// Set up levelnum now so that the Teleport_NewMap specials
// in hexen.wad work without modification.
if (!strnicmp (levelinfo->mapname, "MAP", 3) && levelinfo->mapname[5] == 0) {
int mapnum = atoi (levelinfo->mapname + 3);
if (mapnum >= 1 && mapnum <= 99)
levelinfo->levelnum = mapnum;
}
} else if (levelindex > -1) { } else if (levelindex > -1) {
if (!stricmp (com_token, "levelnum") || if (!stricmp (com_token, "levelnum")) {
!stricmp (com_token, "warptrans")) {
// levelnum <levelnum> // levelnum <levelnum>
mapinfo = COM_Parse (data); mapinfo = COM_Parse (data);
levelinfo->levelnum = atoi (com_token); levelinfo->levelnum = atoi (com_token);
@ -149,6 +183,11 @@ void G_ParseMapInfo (void)
// cluster <clusternum> // cluster <clusternum>
mapinfo = COM_Parse (data); mapinfo = COM_Parse (data);
levelinfo->cluster = atoi (com_token); levelinfo->cluster = atoi (com_token);
if (HexenHack) {
cluster_info_t *cluster = FindClusterInfo (levelinfo->cluster);
if (cluster)
cluster->flags |= CLUSTER_HUB;
}
} else if (!stricmp (com_token, "sky1")) { } else if (!stricmp (com_token, "sky1")) {
// sky1 <sky1texture> <sky1scrollspeed> // sky1 <sky1texture> <sky1scrollspeed>
@ -176,6 +215,18 @@ void G_ParseMapInfo (void)
levelinfo->fadeto = V_GetColorFromString (NULL, com_token); levelinfo->fadeto = V_GetColorFromString (NULL, com_token);
} }
} else if (!stricmp (com_token, "outsidefog")) {
// outsidefog <colorname> OR fade <colordescriptor>
char *colorstring;
mapinfo = COM_Parse (data);
if ( (colorstring = V_GetColorStringByName (com_token)) ) {
levelinfo->outsidefog = V_GetColorFromString (NULL, colorstring);
free (colorstring);
} else {
levelinfo->outsidefog = V_GetColorFromString (NULL, com_token);
}
} else if (!stricmp (com_token, "titlepatch")) { } else if (!stricmp (com_token, "titlepatch")) {
// titlepatch <patchname> // titlepatch <patchname>
mapinfo = COM_Parse (data); mapinfo = COM_Parse (data);
@ -250,14 +301,19 @@ void G_ParseMapInfo (void)
// lightning // lightning
mapinfo = data; mapinfo = data;
} else if (!stricmp (com_token, "fadetable")) {
// fadetable
mapinfo = COM_Parse (data);
uppercopy (levelinfo->fadetable, com_token);
} else if (!stricmp (com_token, "cdtrack") || } else if (!stricmp (com_token, "cdtrack") ||
!stricmp (com_token, "fadetable") ||
!stricmp (com_token, "cd_start_track") || !stricmp (com_token, "cd_start_track") ||
!stricmp (com_token, "cd_end1_track") || !stricmp (com_token, "cd_end1_track") ||
!stricmp (com_token, "cd_end2_track") || !stricmp (com_token, "cd_end2_track") ||
!stricmp (com_token, "cd_end3_track") || !stricmp (com_token, "cd_end3_track") ||
!stricmp (com_token, "cd_intermission_track") || !stricmp (com_token, "cd_intermission_track") ||
!stricmp (com_token, "cd_title_track")) { !stricmp (com_token, "cd_title_track") ||
!stricmp (com_token, "warptrans")) {
mapinfo = COM_Parse (data); mapinfo = COM_Parse (data);
} }
@ -301,6 +357,11 @@ void G_ParseMapInfo (void)
mapinfo = COM_Parse (data); mapinfo = COM_Parse (data);
strncpy (clusterinfo->finaleflat, com_token, 8); strncpy (clusterinfo->finaleflat, com_token, 8);
} else if (!stricmp (com_token, "hub")) {
// hub
mapinfo = data;
clusterinfo->flags |= CLUSTER_HUB;
} }
} }
} }
@ -312,12 +373,38 @@ void G_ParseMapInfo (void)
} }
} }
static void zapDefereds (acsdefered_t *def)
{
while (def) {
acsdefered_t *next = def->next;
Z_Free (def);
def = next;
}
}
void P_RemoveDefereds (void)
{
int i;
// Remove any existing defereds
for (i = 0; i < numwadlevelinfos; i++)
if (wadlevelinfos[i].defered) {
zapDefereds (wadlevelinfos[i].defered);
wadlevelinfos[i].defered = NULL;
}
for (i = 0; LevelInfos[i].level_name; i++)
if (LevelInfos[i].defered) {
zapDefereds (LevelInfos[i].defered);
LevelInfos[i].defered = NULL;
}
}
// //
// G_InitNew // G_InitNew
// Can be called by the startup code or the menu task, // Can be called by the startup code or the menu task,
// consoleplayer, displayplayer, playeringame[] should be set. // consoleplayer, displayplayer, playeringame[] should be set.
// //
static char d_mapname[9]; static char d_mapname[9];
void G_DeferedInitNew (char *mapname) void G_DeferedInitNew (char *mapname)
{ {
@ -367,12 +454,17 @@ void G_InitNew (char *mapname)
{ {
int i; int i;
// [RH] Mark all levels as not visited if (!savegamerestore)
for (i = 0; i < numwadlevelinfos; i++) G_ClearSnapshots ();
wadlevelinfos[i].flags &= ~LEVEL_VISITED;
for (i = 0; LevelInfos[i].mapname[0]; i++) // [RH] Mark all levels as not visited
LevelInfos[i].flags &= ~LEVEL_VISITED; if (!savegamerestore) {
for (i = 0; i < numwadlevelinfos; i++)
wadlevelinfos[i].flags &= ~LEVEL_VISITED;
for (i = 0; LevelInfos[i].mapname[0]; i++)
LevelInfos[i].flags &= ~LEVEL_VISITED;
}
UnlatchCVars (); UnlatchCVars ();
@ -391,7 +483,7 @@ void G_InitNew (char *mapname)
// [RH] If this map doesn't exist, bomb out // [RH] If this map doesn't exist, bomb out
if (W_CheckNumForName (mapname) == -1) { if (W_CheckNumForName (mapname) == -1) {
I_Error ("Could not start map %s\n", mapname); I_Error ("Could not find map %s\n", mapname);
} }
if ((gameskill->value == sk_nightmare) || (dmflags & DF_MONSTERS_RESPAWN) ) if ((gameskill->value == sk_nightmare) || (dmflags & DF_MONSTERS_RESPAWN) )
@ -418,44 +510,70 @@ void G_InitNew (char *mapname)
mobjinfo[MT_TROOPSHOT].speed = 10*FRACUNIT; mobjinfo[MT_TROOPSHOT].speed = 10*FRACUNIT;
} }
M_ClearRandom (); if (!savegamerestore)
M_ClearRandom ();
// [RH] Clear ACS world variables and time
// (Savegame restores them after calling G_InitNew)
memset (WorldVars, 0, sizeof(WorldVars));
level.time = 0;
// force players to be initialized upon first level load // force players to be initialized upon first level load
for (i=0 ; i<MAXPLAYERS ; i++) if (!savegamerestore)
players[i].playerstate = PST_REBORN; for (i=0 ; i<MAXPLAYERS ; i++)
players[i].playerstate = PST_REBORN;
usergame = true; // will be set false if a demo usergame = true; // will be set false if a demo
paused = false; paused = false;
demoplayback = false; demoplayback = false;
automapactive = false; automapactive = false;
viewactive = true; viewactive = true;
viewactive = true;
strncpy (level.mapname, mapname, 8); strncpy (level.mapname, mapname, 8);
G_DoLoadLevel (); G_DoLoadLevel (0);
} }
// //
// G_DoCompleted // G_DoCompleted
// //
BOOL secretexit; BOOL secretexit;
static int startpos; // [RH] Support for multiple starts per level
extern char* pagename; extern char* pagename;
extern BOOL NoWipe; // [RH] Don't wipe when travelling in hubs
void G_ExitLevel (void)
// [RH] The position parameter to these next two functions should
// match the first parameter of the single player start spots
// that should appear in the next map.
static void goOn (int position)
{
cluster_info_t *thiscluster = FindClusterInfo (level.cluster);
cluster_info_t *nextcluster = FindClusterInfo (FindLevelInfo (level.nextmap)->cluster);
startpos = position;
gameaction = ga_completed;
if (thiscluster && (thiscluster->flags & CLUSTER_HUB)) {
if ((level.flags & LEVEL_NOINTERMISSION) || (nextcluster == thiscluster))
NoWipe = 4;
D_DrawIcon = "TELEICON";
}
}
void G_ExitLevel (int position)
{ {
secretexit = false; secretexit = false;
gameaction = ga_completed; goOn (position);
} }
// Here's for the german edition. // Here's for the german edition.
void G_SecretExitLevel (void) void G_SecretExitLevel (int position)
{ {
// [RH] Check for secret levels is done in // [RH] Check for secret levels is done in
// G_DoCompleted() // G_DoCompleted()
secretexit = true; secretexit = true;
gameaction = ga_completed; goOn (position);
} }
void G_DoCompleted (void) void G_DoCompleted (void)
@ -468,18 +586,9 @@ void G_DoCompleted (void)
if (!(level.flags & LEVEL_CHANGEMAPCHEAT)) if (!(level.flags & LEVEL_CHANGEMAPCHEAT))
FindLevelInfo (level.mapname)->flags |= LEVEL_VISITED; FindLevelInfo (level.mapname)->flags |= LEVEL_VISITED;
for (i=0 ; i<MAXPLAYERS ; i++)
if (playeringame[i])
G_PlayerFinishLevel (i); // take away cards and stuff
if (automapactive) if (automapactive)
AM_Stop (); AM_Stop ();
if (level.flags & LEVEL_NOINTERMISSION) {
G_WorldDone ();
return;
}
wminfo.epsd = level.cluster - 1; // Only used for DOOM I. wminfo.epsd = level.cluster - 1; // Only used for DOOM I.
strncpy (wminfo.lname0, level.info->pname, 8); strncpy (wminfo.lname0, level.info->pname, 8);
strncpy (wminfo.current, level.mapname, 8); strncpy (wminfo.current, level.mapname, 8);
@ -524,11 +633,46 @@ void G_DoCompleted (void)
wminfo.plyr[i].fragcount = players[i].fragcount; wminfo.plyr[i].fragcount = players[i].fragcount;
} }
// [RH] If we're in a hub and staying within that hub, take a snapshot
// of the level. If we're traveling to a new hub, take stuff from
// the player and clear the world vars. If this is just an
// ordinary cluster (not a hub), take stuff from the player, but
// leave the world vars alone.
{
cluster_info_t *thiscluster = FindClusterInfo (level.cluster);
cluster_info_t *nextcluster = FindClusterInfo (FindLevelInfo (level.nextmap)->cluster);
if (thiscluster != nextcluster ||
deathmatch->value ||
!(thiscluster->flags & CLUSTER_HUB)) {
for (i=0 ; i<MAXPLAYERS ; i++)
if (playeringame[i])
G_PlayerFinishLevel (i); // take away cards and stuff
if (nextcluster->flags & CLUSTER_HUB) {
memset (WorldVars, 0, sizeof(WorldVars));
P_RemoveDefereds ();
G_ClearSnapshots ();
}
} else {
G_SnapshotLevel ();
}
if (!(nextcluster->flags & CLUSTER_HUB) || !(thiscluster->flags & CLUSTER_HUB))
level.time = 0; // Reset time to zero if not entering/staying in a hub
if (!deathmatch->value &&
(level.flags & LEVEL_NOINTERMISSION) ||
((nextcluster == thiscluster) && (thiscluster->flags & CLUSTER_HUB))) {
G_WorldDone ();
return;
}
}
gamestate = GS_INTERMISSION; gamestate = GS_INTERMISSION;
viewactive = false; viewactive = false;
automapactive = false; automapactive = false;
// [RH] If you ever get a statistics driver operational, uncomment this. // [RH] If you ever get a statistics driver operational, adapt this.
// if (statcopy) // if (statcopy)
// memcpy (statcopy, &wminfo, sizeof(wminfo)); // memcpy (statcopy, &wminfo, sizeof(wminfo));
@ -538,19 +682,33 @@ void G_DoCompleted (void)
// //
// G_DoLoadLevel // G_DoLoadLevel
// //
extern gamestate_t wipegamestate; extern gamestate_t wipegamestate;
extern float BaseBlendA;
void G_DoLoadLevel (void) void G_DoLoadLevel (int position)
{ {
int i; static int lastposition = 0;
gamestate_t oldgs = gamestate;
int i;
if (position == -1)
position = lastposition;
else
lastposition = position;
G_InitLevelLocals (); G_InitLevelLocals ();
Printf ("\n\35\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36" Printf ("\n\35\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36"
"\36\36\36\36\36\36\36\36\36\36\36\36\37\n%s\n\n", "\36\36\36\36\36\36\36\36\36\36\36\36\37\n%s\n\n",
level.level_name); level.level_name);
if (wipegamestate == GS_LEVEL)
wipegamestate = -1; // force a wipe
gamestate = GS_LEVEL;
C_HideConsole (); if (demoplayback || oldgs == GS_STARTUP)
C_HideConsole ();
C_FlushDisplay (); C_FlushDisplay ();
// Set the sky map. // Set the sky map.
@ -569,11 +727,6 @@ void G_DoLoadLevel (void)
// [RH] Set up details about sky rendering // [RH] Set up details about sky rendering
R_InitSkyMap (r_stretchsky); R_InitSkyMap (r_stretchsky);
if (wipegamestate == GS_LEVEL)
wipegamestate = -1; // force a wipe
gamestate = GS_LEVEL;
for (i=0 ; i<MAXPLAYERS ; i++) for (i=0 ; i<MAXPLAYERS ; i++)
{ {
if (playeringame[i] && players[i].playerstate == PST_DEAD) if (playeringame[i] && players[i].playerstate == PST_DEAD)
@ -592,9 +745,7 @@ void G_DoLoadLevel (void)
headsecnode = NULL; headsecnode = NULL;
} }
P_SetupLevel (level.mapname, position);
S_ClearAmbients (); // [RH] Clear all ambient sounds
P_SetupLevel (level.mapname);
displayplayer = consoleplayer; // view the guy you are playing displayplayer = consoleplayer; // view the guy you are playing
ST_Start(); // [RH] Make sure status bar knows who we are ST_Start(); // [RH] Make sure status bar knows who we are
HU_Start(); HU_Start();
@ -610,6 +761,10 @@ void G_DoLoadLevel (void)
level.starttime = I_GetTime (); level.starttime = I_GetTime ();
G_UnSnapshotLevel (!savegamerestore); // [RH] Restore the state of the level.
P_DoDeferedScripts (); // [RH] Do script actions that were triggerd on another map.
if (timingdemo) { if (timingdemo) {
static BOOL firstTime = true; static BOOL firstTime = true;
@ -643,8 +798,9 @@ void G_WorldDone (void)
else else
nextcluster = FindClusterInfo (FindLevelInfo (level.secretmap)->cluster); nextcluster = FindClusterInfo (FindLevelInfo (level.secretmap)->cluster);
if (nextcluster->cluster != level.cluster) { if (nextcluster->cluster != level.cluster && !deathmatch->value) {
// Only start the finale if the next level's cluster is different than the current one. // Only start the finale if the next level's cluster is different
// than the current one and we're not in deathmatch.
if (nextcluster->entertext) { if (nextcluster->entertext) {
F_StartFinale (nextcluster->messagemusic, nextcluster->finaleflat, nextcluster->entertext); F_StartFinale (nextcluster->messagemusic, nextcluster->finaleflat, nextcluster->entertext);
} else if (thiscluster->exittext) { } else if (thiscluster->exittext) {
@ -664,12 +820,14 @@ void G_DoWorldDone (void)
} else { } else {
strncpy (level.mapname, wminfo.next, 8); strncpy (level.mapname, wminfo.next, 8);
} }
G_DoLoadLevel (); G_DoLoadLevel (startpos);
startpos = 0;
gameaction = ga_nothing; gameaction = ga_nothing;
viewactive = true; viewactive = true;
} }
extern dyncolormap_t NormalLight;
void G_InitLevelLocals () void G_InitLevelLocals ()
{ {
@ -677,21 +835,32 @@ void G_InitLevelLocals ()
level_info_t *info; level_info_t *info;
int i; int i;
BaseBlendA = 0.0f; // Remove underwater blend effect, if any
NormalLight.maps = realcolormaps;
if ((i = FindWadLevelInfo (level.mapname)) > -1) { if ((i = FindWadLevelInfo (level.mapname)) > -1) {
level_pwad_info_t *pinfo = wadlevelinfos + i; level_pwad_info_t *pinfo = wadlevelinfos + i;
level.info = (level_info_t *)pinfo; level.info = (level_info_t *)pinfo;
level.skyspeed1 = pinfo->skyspeed1; level.skyspeed1 = pinfo->skyspeed1;
level.skyspeed2 = pinfo->skyspeed2; level.skyspeed2 = pinfo->skyspeed2;
level.fadeto = pinfo->fadeto;
info = (level_info_t *)pinfo; info = (level_info_t *)pinfo;
strncpy (level.skypic2, pinfo->skypic2, 8); strncpy (level.skypic2, pinfo->skypic2, 8);
level.fadeto = pinfo->fadeto;
if (level.fadeto) {
NormalLight.maps = DefaultPalette->maps.colormaps;
} else {
R_SetDefaultColormap (pinfo->fadetable);
}
level.outsidefog = pinfo->outsidefog;
} else { } else {
info = FindDefLevelInfo (level.mapname); info = FindDefLevelInfo (level.mapname);
level.info = info; level.info = info;
level.skyspeed1 = level.skyspeed2 = 0; level.skyspeed1 = level.skyspeed2 = 0;
level.fadeto = 0; level.fadeto = 0;
level.outsidefog = 0xff000000; // 0xff000000 signals not to handle it special
level.skypic2[0] = 0; level.skypic2[0] = 0;
R_SetDefaultColormap ("COLORMAP");
} }
if (info->level_name) { if (info->level_name) {
@ -719,6 +888,8 @@ void G_InitLevelLocals ()
level.levelnum = 1; level.levelnum = 1;
} }
memset (level.vars, 0, sizeof(level.vars));
if (oldfade != level.fadeto) if (oldfade != level.fadeto)
RefreshPalettes (); RefreshPalettes ();
} }
@ -867,6 +1038,255 @@ void G_SetLevelStrings (void)
strncpy (level.level_name, level.info->level_name, 63); strncpy (level.level_name, level.info->level_name, 63);
} }
// Archives the current level
void G_SnapshotLevel (void)
{
save_p = savebuffer = Malloc (savegamesize);
if (level.info->snapshot)
Z_Free (level.info->snapshot);
WriteLong (level.flags, &save_p);
WriteLong (level.fadeto, &save_p);
WriteLong (level.found_secrets, &save_p);
WriteLong (level.found_items, &save_p);
WriteLong (level.killed_monsters, &save_p);
memcpy (save_p, level.vars, sizeof(level.vars));
save_p += sizeof(level.vars);
P_ArchiveWorld ();
Z_CheckHeap ();
P_ArchiveThinkers ();
Z_CheckHeap ();
P_ArchiveSpecials ();
Z_CheckHeap ();
P_ArchiveScripts ();
Z_CheckHeap ();
// Now compress it. This seems to shrink the data down to
// about 20% of its original size fairly consistantly.
{
int outlen;
int len = save_p - savebuffer;
lzo_byte *compressed;
lzo_byte *wrkmem;
int r;
compressed = Z_Malloc (OUT_LEN(len), PU_STATIC, 0);
wrkmem = Z_Malloc (LZO1X_1_MEM_COMPRESS, PU_STATIC, 0);
r = lzo1x_1_compress (savebuffer, len, compressed, &outlen, wrkmem);
Z_Free (wrkmem);
// If the data could not be compressed, store it as-is.
if (r != LZO_E_OK || outlen > len) {
DPrintf ("Snapshot uncompressable\n");
outlen = 0;
} else {
DPrintf ("Snapshot: %d .. %d bytes\n", len, outlen);
}
level.info->snapshot = Z_Malloc (((outlen == 0) ? len : outlen) + sizeof(int)*2, PU_STATIC, 0);
((int *)(level.info->snapshot))[0] = outlen;
((int *)(level.info->snapshot))[1] = len;
if (outlen == 0)
memcpy (level.info->snapshot + sizeof(int)*2, savebuffer, len);
else
memcpy (level.info->snapshot + sizeof(int)*2, compressed, outlen);
Z_Free (compressed);
}
free (savebuffer);
savebuffer = save_p = NULL;
}
// Unarchives the current level based on its snapshot
// The level should have already been loaded and setup.
void G_UnSnapshotLevel (BOOL keepPlayers)
{
int expandsize, cprlen;
byte *expand;
if (!level.info->snapshot)
return;
cprlen = ((int *)(level.info->snapshot))[0];
expandsize = ((int *)(level.info->snapshot))[1];
if (cprlen) {
int r, newlen;
expand = Z_Malloc (expandsize, PU_STATIC, 0);
r = lzo1x_decompress (level.info->snapshot + sizeof(int)*2, cprlen, expand, &newlen, NULL);
if (r != LZO_E_OK || newlen != expandsize) {
Printf ("Could not decompress snapshot");
Z_Free (expand);
return;
}
save_p = expand;
} else {
save_p = level.info->snapshot + sizeof(int)*2;
expand = NULL;
}
level.flags = ReadLong (&save_p);
level.fadeto = ReadLong (&save_p);
level.found_secrets = ReadLong (&save_p);
level.found_items = ReadLong (&save_p);
level.killed_monsters = ReadLong (&save_p);
memcpy (level.vars, save_p, sizeof(level.vars));
save_p += sizeof(level.vars);
P_UnArchiveWorld ();
P_UnArchiveThinkers (keepPlayers);
P_UnArchiveSpecials ();
P_UnArchiveScripts ();
if (expand)
Z_Free (expand);
// No reason to keep the snapshot around once the level's been entered.
Z_Free (level.info->snapshot);
level.info->snapshot = NULL;
save_p = NULL;
}
void G_ClearSnapshots (void)
{
int i;
for (i = 0; i < numwadlevelinfos; i++)
if (wadlevelinfos[i].snapshot) {
Z_Free (wadlevelinfos[i].snapshot);
wadlevelinfos[i].snapshot = NULL;
}
for (i = 0; LevelInfos[i].level_name; i++)
if (LevelInfos[i].snapshot) {
Z_Free (LevelInfos[i].snapshot);
LevelInfos[i].snapshot = NULL;
}
}
static void writeSnapShot (level_info_t *i)
{
int len;
len = ((int *)(i->snapshot))[0];
if (len == 0)
len = ((int *)(i->snapshot))[1];
CheckSaveGame (len + 8 + sizeof(int)*2 + 4);
memcpy (save_p, i->mapname, 8);
save_p += 8;
PADSAVEP();
memcpy (save_p, i->snapshot, len + sizeof(int)*2);
save_p += len + sizeof(int)*2;
}
void G_ArchiveSnapshots (void)
{
int i;
for (i = 0; i < numwadlevelinfos; i++)
if (wadlevelinfos[i].snapshot)
writeSnapShot ((level_info_t *)&wadlevelinfos[i]);
for (i = 0; LevelInfos[i].level_name; i++)
if (LevelInfos[i].snapshot)
writeSnapShot (&LevelInfos[i]);
// Signal end of snapshots
CheckSaveGame (1);
*save_p++ = 0;
}
void G_UnArchiveSnapshots (void)
{
level_info_t *i;
int shortsize, fullsize, savesize;
G_ClearSnapshots ();
while (*save_p) {
i = FindLevelInfo (save_p);
save_p += 8;
PADSAVEP();
shortsize = ((int *)save_p)[0];
fullsize = ((int *)save_p)[1];
savesize = (shortsize ? shortsize : fullsize) + sizeof(int)*2;
if (i) {
i->snapshot = Z_Malloc (savesize, PU_STATIC, 0);
memcpy (i->snapshot, save_p, savesize);
}
save_p += savesize;
}
save_p++;
}
static void writeDefereds (level_info_t *i)
{
acsdefered_t *def = i->defered;
memcpy (save_p, i->mapname, 8);
save_p += 8;
while (def) {
CheckSaveGame (sizeof (*def));
memcpy (save_p, def, sizeof(*def));
save_p += sizeof(*def);
def = def->next;
}
}
void P_ArchiveACSDefereds (void)
{
int i;
for (i = 0; i < numwadlevelinfos; i++)
if (wadlevelinfos[i].defered)
writeDefereds ((level_info_t *)&wadlevelinfos[i]);
for (i = 0; LevelInfos[i].level_name; i++)
if (LevelInfos[i].defered)
writeDefereds (&LevelInfos[i]);
// Signal end of defereds
CheckSaveGame (1);
*save_p++ = 0;
}
void P_UnArchiveACSDefereds (void)
{
level_info_t *i;
acsdefered_t *def, **prev;
P_RemoveDefereds ();
while (*save_p) {
i = FindLevelInfo (save_p);
if (!i) {
char name[9];
strncpy (name, save_p, 8);
name[8] = 0;
I_Error ("Unknown map %s in savegame", name);
}
save_p += 8;
prev = &i->defered;
do {
def = Z_Malloc (sizeof(*def), PU_STATIC, 0);
memcpy (def, save_p, sizeof(*def));
save_p += sizeof(*def);
*prev = def;
prev = &def->next;
} while (*prev);
}
save_p++;
}
// Static level info from original game // Static level info from original game
// The level names and cluster messages now get filled in // The level names and cluster messages now get filled in
// by G_SetLevelStrings(). // by G_SetLevelStrings().

View file

@ -5,6 +5,9 @@
#include "doomdef.h" #include "doomdef.h"
#include "m_fixed.h" #include "m_fixed.h"
#define NUM_MAPVARS 32
#define NUM_WORLDVARS 64
#define LEVEL_NOINTERMISSION 0x00000001 #define LEVEL_NOINTERMISSION 0x00000001
#define LEVEL_DOUBLESKY 0x00000004 #define LEVEL_DOUBLESKY 0x00000004
#define LEVEL_NOSOUNDCLIPPING 0x00000008 #define LEVEL_NOSOUNDCLIPPING 0x00000008
@ -23,6 +26,7 @@
#define LEVEL_CHANGEMAPCHEAT 0x40000000 // Don't display cluster messages #define LEVEL_CHANGEMAPCHEAT 0x40000000 // Don't display cluster messages
#define LEVEL_VISITED 0x80000000 // Used for intermission map #define LEVEL_VISITED 0x80000000 // Used for intermission map
struct acsdefered_s;
struct level_info_s { struct level_info_s {
char mapname[8]; char mapname[8];
@ -36,6 +40,8 @@ struct level_info_s {
char music[8]; char music[8];
unsigned flags; unsigned flags;
int cluster; int cluster;
byte *snapshot;
struct acsdefered_s *defered;
}; };
typedef struct level_info_s level_info_t; typedef struct level_info_s level_info_t;
@ -51,11 +57,15 @@ struct level_pwad_info_s {
char music[8]; char music[8];
unsigned flags; unsigned flags;
int cluster; int cluster;
byte *snapshot;
struct acsdefered_s *defered;
char skypic2[8]; char skypic2[8];
fixed_t skyspeed1; fixed_t skyspeed1;
fixed_t skyspeed2; fixed_t skyspeed2;
unsigned fadeto; unsigned fadeto;
char fadetable[8];
unsigned outsidefog;
}; };
typedef struct level_pwad_info_s level_pwad_info_t; typedef struct level_pwad_info_s level_pwad_info_t;
@ -76,6 +86,7 @@ struct level_locals_s {
unsigned flags; unsigned flags;
unsigned fadeto; // The color the palette fades to (usually black) unsigned fadeto; // The color the palette fades to (usually black)
unsigned outsidefog; // The fog for sectors with sky ceilings
char music[8]; char music[8];
char skypic1[8]; char skypic1[8];
@ -92,6 +103,12 @@ struct level_locals_s {
int total_monsters; int total_monsters;
int killed_monsters; int killed_monsters;
// The following are all used for ACS scripting
byte *behavior;
int *scripts;
int *strings;
int vars[NUM_MAPVARS];
}; };
typedef struct level_locals_s level_locals_t; typedef struct level_locals_s level_locals_t;
@ -101,13 +118,21 @@ struct cluster_info_s {
char finaleflat[8]; char finaleflat[8];
char *exittext; char *exittext;
char *entertext; char *entertext;
int flags;
}; };
typedef struct cluster_info_s cluster_info_t; typedef struct cluster_info_s cluster_info_t;
// Only one cluster flag right now
#define CLUSTER_HUB 0x00000001
extern level_locals_t level; extern level_locals_t level;
extern level_info_t LevelInfos[]; extern level_info_t LevelInfos[];
extern cluster_info_t ClusterInfos[]; extern cluster_info_t ClusterInfos[];
extern int WorldVars[NUM_WORLDVARS];
extern BOOL savegamerestore;
void G_InitNew (char *mapname); void G_InitNew (char *mapname);
// Can be called by the startup code or M_Responder. // Can be called by the startup code or M_Responder.
@ -115,10 +140,10 @@ void G_InitNew (char *mapname);
// but a warp test can start elsewhere // but a warp test can start elsewhere
void G_DeferedInitNew (char *mapname); void G_DeferedInitNew (char *mapname);
void G_ExitLevel (void); void G_ExitLevel (int position);
void G_SecretExitLevel (void); void G_SecretExitLevel (int position);
void G_DoLoadLevel (void); void G_DoLoadLevel (int position);
void G_InitLevelLocals (void); void G_InitLevelLocals (void);
@ -132,4 +157,10 @@ char *CalcMapName (int episode, int level);
void G_ParseMapInfo (void); void G_ParseMapInfo (void);
void G_ClearSnapshots (void);
void G_SnapshotLevel (void);
void G_UnSnapshotLevel (BOOL keepPlayers);
void G_ArchiveSnapshots (void);
void G_UnArchiveSnapshots (void);
#endif //__G_LEVEL_H__ #endif //__G_LEVEL_H__

View file

@ -40,7 +40,6 @@
// Data. // Data.
#include "dstrings.h" #include "dstrings.h"
#include "sounds.h"
#include "c_consol.h" #include "c_consol.h"
#include "c_dispch.h" #include "c_dispch.h"
@ -71,7 +70,7 @@ cvar_t *chat_macros[10];
static player_t* plr; static player_t* plr;
patch_t* hu_font[HU_FONTSIZE]; patch_t* hu_font[HU_FONTSIZE];
BOOL chat_on; int chat_on;
static hu_itext_t w_chat; static hu_itext_t w_chat;
static BOOL message_on; static BOOL message_on;
@ -120,11 +119,15 @@ void HU_Start(void)
if (headsupactive) if (headsupactive)
HU_Stop(); HU_Stop();
plr = &players[displayplayer]; // [RH] Not consoleplayer // [RH] Give status bar preference to the camera
if (players[consoleplayer].camera && players[consoleplayer].camera->player)
plr = players[consoleplayer].camera->player;
else
plr = &players[consoleplayer];
message_on = false; message_on = false;
message_dontfuckwithme = false; message_dontfuckwithme = false;
message_nottobefuckedwith = false; message_nottobefuckedwith = false;
chat_on = false; chat_on = 0;
// create the chat widget // create the chat widget
HUlib_initIText(&w_chat, HUlib_initIText(&w_chat,
@ -139,8 +142,8 @@ void HU_Drawer(void)
{ {
HUlib_drawIText(&w_chat); HUlib_drawIText(&w_chat);
if (deathmatch->value && ((Actions & ACTION_SHOWSCORES) || players[displayplayer].health <= 0)) if (deathmatch->value && ((Actions & ACTION_SHOWSCORES) || plr->health <= 0))
HU_DrawScores (displayplayer); HU_DrawScores (plr - players);
} }
void HU_Erase(void) void HU_Erase(void)
@ -170,7 +173,9 @@ void HU_DrawScores (int player)
maxwidth = 0; maxwidth = 0;
for (i = 0; i < MAXPLAYERS; i++) { for (i = 0; i < MAXPLAYERS; i++) {
if (playeringame[i]) { if (playeringame[i]) {
int width = V_StringWidth (players[i].userinfo->netname); int width = V_StringWidth (players[i].userinfo.netname);
if (teamplay->value)
width += V_StringWidth (players[i].userinfo.team) + 24;
if (width > maxwidth) if (width > maxwidth)
maxwidth = width; maxwidth = width;
} }
@ -183,7 +188,7 @@ void HU_DrawScores (int player)
if (y < 48) y = 48; if (y < 48) y = 48;
for (i = 0; i < MAXPLAYERS && y < ST_Y - 12 * CleanYfac; i++) { for (i = 0; i < MAXPLAYERS && y < ST_Y - 12 * CleanYfac; i++) {
int color = players[sortedplayers[i]].userinfo->color; int color = players[sortedplayers[i]].userinfo.color;
char str[24]; char str[24];
if (playeringame[sortedplayers[i]]) { if (playeringame[sortedplayers[i]]) {
@ -197,7 +202,11 @@ void HU_DrawScores (int player)
sprintf (str, "%d", players[sortedplayers[i]].fragcount); sprintf (str, "%d", players[sortedplayers[i]].fragcount);
V_DrawTextClean (margin, y, str); V_DrawTextClean (margin, y, str);
strcpy (str, players[sortedplayers[i]].userinfo->netname); if (teamplay->value)
sprintf (str, "%s (%s)", players[sortedplayers[i]].userinfo.netname,
players[sortedplayers[i]].userinfo.team);
else
strcpy (str, players[sortedplayers[i]].userinfo.netname);
if (sortedplayers[i] != player) if (sortedplayers[i] != player)
for (j = 0; j < 23 && str[j]; j++) for (j = 0; j < 23 && str[j]; j++)
@ -258,6 +267,12 @@ BOOL HU_Responder (event_t *ev)
if (chat_on) if (chat_on)
{ {
// [RH] You can actually cancel out of messagemode now
if (ev->data1 == KEY_ESCAPE) {
chat_on = 0;
return true;
}
c = ev->data3; // [RH] Use localized keymap c = ev->data3; // [RH] Use localized keymap
// send a macro // send a macro
@ -268,10 +283,10 @@ BOOL HU_Responder (event_t *ev)
if (c > 9) if (c > 9)
return false; return false;
ShoveChatStr (chat_macros[c]->string, 0); ShoveChatStr (chat_macros[c]->string, chat_on - 1);
// leave chat mode // leave chat mode
chat_on = false; chat_on = 0;
eatkey = true; eatkey = true;
} }
else else
@ -281,10 +296,10 @@ BOOL HU_Responder (event_t *ev)
eatkey = HUlib_keyInIText(&w_chat, c); eatkey = HUlib_keyInIText(&w_chat, c);
if (ev->data1 == KEY_ENTER) { if (ev->data1 == KEY_ENTER) {
chat_on = false; ShoveChatStr (w_chat.l.l, chat_on - 1);
ShoveChatStr (w_chat.l.l, 0); chat_on = 0;
} else if (ev->data1 == KEY_ESCAPE) } else if (ev->data1 == KEY_ESCAPE)
chat_on = false; chat_on = 0;
} }
} }
@ -293,11 +308,9 @@ BOOL HU_Responder (event_t *ev)
void Cmd_MessageMode (player_t *plyr, int argc, char **argv) void Cmd_MessageMode (player_t *plyr, int argc, char **argv)
{ {
if (netgame) { chat_on = 1;
chat_on = true; C_HideConsole ();
C_HideConsole (); HUlib_resetIText (&w_chat);
HUlib_resetIText (&w_chat);
}
} }
void Cmd_Say (player_t *plyr, int argc, char **argv) void Cmd_Say (player_t *plyr, int argc, char **argv)
@ -305,4 +318,18 @@ void Cmd_Say (player_t *plyr, int argc, char **argv)
if (argc > 1) { if (argc > 1) {
ShoveChatStr (BuildString (argc - 1, argv + 1), 0); ShoveChatStr (BuildString (argc - 1, argv + 1), 0);
} }
} }
void Cmd_MessageMode2 (player_t *plyr, int argc, char **argv)
{
chat_on = 2;
C_HideConsole ();
HUlib_resetIText (&w_chat);
}
void Cmd_Say_Team (player_t *plyr, int argc, char **argv)
{
if (argc > 1) {
ShoveChatStr (BuildString (argc - 1, argv + 1), 1);
}
}

View file

@ -1,354 +0,0 @@
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <mmsystem.h>
#include "m_argv.h"
#include "i_music.h"
#include "w_wad.h"
#include "c_consol.h"
#include "../midas/include/midasdll.h"
#define TYPE_MIDI 0
#define TYPE_MOD 1
#define TYPE_CD 2
#define STATE_STOPPED 0
#define STATE_PLAYING 1
#define STATE_PAUSED 2
struct MusInfo {
int type;
int status;
union {
MIDASmodule module;
MCIDEVICEID mciDevice;
};
union {
DWORD unpausePosition;
int cdTrack;
MIDASmodulePlayHandle handle;
};
char *filename;
BOOL looping;
};
typedef struct MusInfo info_t;
static info_t *currSong;
extern HWND Window;
/* Music using Windows MIDI device - yuck */
static int nomusic = 0;
static char musName[512];
static char midName[512];
static int musicdies=-1;
static int musicvolume;
void I_SetMusicVolume (int volume)
{
if (volume != 127) {
// Internal state variable.
musicvolume = volume;
// Now set volume on output device.
if (currSong && currSong->type == TYPE_MOD)
MIDASsetMusicVolume (currSong->handle, musicvolume);
}
}
void I_InitMusic (void)
{
char *temp;
Printf ("I_InitMusic\n");
nomusic = !!M_CheckParm("-nomusic") || !!M_CheckParm("-nosound");
/* Create temporary file names: */
temp = getenv("TEMP");
if ( temp == NULL )
temp = ".";
strcpy(musName, temp);
while ( musName[strlen(musName)-1] == '\\' )
musName[strlen(musName)-1] = 0;
strcat(musName, "\\");
strcpy(midName, musName);
strcat(musName, "doomtemp.mus");
strcat(midName, "doomtemp.mid");
}
void I_ShutdownMusic(void)
{
if (currSong) {
I_UnRegisterSong ((int)currSong);
currSong = NULL;
}
remove (midName);
remove (musName);
}
int SendMCI(MCIDEVICEID device, UINT msg, DWORD command, DWORD param)
{
int res;
res = mciSendCommand(device, msg, command, param);
if (res) {
char errorStr[256];
mciGetErrorString(res, errorStr, 255);
Printf_Bold ("MCI error:\n");
Printf ("%s\n", errorStr);
}
return res;
}
void I_PlaySong (int handle, int _looping)
{
info_t *info = (info_t *)handle;
if (!info || nomusic)
return;
info->status = STATE_STOPPED;
info->looping = _looping;
switch (info->type) {
case TYPE_MIDI: {
MCI_OPEN_PARMS openParms;
MCI_PLAY_PARMS playParms;
openParms.lpstrDeviceType = "sequencer";
openParms.lpstrElementName = info->filename;
if (SendMCI (0, MCI_OPEN, MCI_OPEN_TYPE | MCI_OPEN_ELEMENT, (DWORD)&openParms))
return;
playParms.dwCallback = (DWORD)Window;
if(SendMCI (openParms.wDeviceID, MCI_PLAY, MCI_NOTIFY, (DWORD)&playParms)) {
SendMCI (openParms.wDeviceID, MCI_CLOSE, 0, (DWORD)NULL);
return;
}
info->mciDevice = openParms.wDeviceID;
info->status = STATE_PLAYING;
break;
}
case TYPE_MOD:
if (info->handle = MIDASplayModule (info->module, _looping)) {
MIDASsetMusicVolume (info->handle, musicvolume);
info->status = STATE_PLAYING;
}
break;
}
currSong = info;
}
void I_RestartSong (void)
{
MCI_PLAY_PARMS playParms;
if (!currSong ||
currSong->type != TYPE_MIDI ||
currSong->status != STATE_PLAYING)
return;
if (!currSong->looping) {
I_StopSong ((int)currSong);
return;
}
playParms.dwFrom = 0;
playParms.dwCallback = (DWORD)Window;
if (SendMCI (currSong->mciDevice, MCI_PLAY, MCI_NOTIFY | MCI_FROM, (DWORD)(LPVOID)&playParms)) {
SendMCI (currSong->mciDevice, MCI_CLOSE, 0, (DWORD)NULL);
currSong->mciDevice = 0;
currSong = NULL;
}
}
void I_PauseSong (int handle)
{
info_t *info = (info_t *)handle;
if (!info || info->status != STATE_PLAYING)
return;
switch (info->type) {
case TYPE_MIDI: {
MCI_SET_PARMS setParms;
MCI_STATUS_PARMS statusParms;
setParms.dwTimeFormat = MCI_FORMAT_MILLISECONDS;
if (SendMCI (info->mciDevice, MCI_SET, MCI_SET_TIME_FORMAT, (DWORD)&setParms))
return;
statusParms.dwCallback = (DWORD)Window;
statusParms.dwItem = MCI_STATUS_POSITION;
if (SendMCI (info->mciDevice, MCI_STATUS, MCI_STATUS_ITEM, (DWORD)&statusParms))
return;
info->unpausePosition = statusParms.dwReturn;
SendMCI (info->mciDevice, MCI_STOP, 0, (DWORD)NULL);
info->status = STATE_PAUSED;
}
break;
case TYPE_MOD:
break;
}
}
void I_ResumeSong (int handle)
{
info_t *info = (info_t *)handle;
if (!info || info->status != STATE_PAUSED)
return;
switch (info->type) {
case TYPE_MIDI: {
MCI_SET_PARMS setParms;
MCI_PLAY_PARMS playParms;
setParms.dwTimeFormat = MCI_FORMAT_MILLISECONDS;
if (SendMCI (info->mciDevice, MCI_SET, MCI_SET_TIME_FORMAT, (DWORD)&setParms))
return;
playParms.dwCallback = (DWORD)Window;
playParms.dwTo = 0;
playParms.dwFrom = info->unpausePosition;
if (SendMCI (info->mciDevice, MCI_PLAY, MCI_NOTIFY | MCI_FROM, (DWORD)&playParms))
return;
info->status = STATE_PLAYING;
}
break;
case TYPE_MOD:
break;
}
}
void I_StopSong(int handle)
{
info_t *info = (info_t *)handle;
if (!info || info->status == STATE_STOPPED)
return;
info->status = STATE_STOPPED;
switch (info->type) {
case TYPE_MIDI:
SendMCI (info->mciDevice, MCI_STOP, 0, (DWORD)NULL);
SendMCI (info->mciDevice, MCI_CLOSE, 0, (DWORD)NULL);
info->mciDevice = 0;
break;
case TYPE_MOD:
MIDASstopModule (info->handle);
info->handle = 0;
break;
}
if (info == currSong)
currSong = NULL;
}
void I_UnRegisterSong(int handle)
{
info_t *info = (info_t *)handle;
if (info) {
I_StopSong (handle);
switch (info->type) {
case TYPE_MIDI:
if (info->filename)
remove (info->filename);
break;
case TYPE_MOD:
MIDASfreeModule (info->module);
break;
}
free (info);
}
}
extern int convert( const char *mus, const char *mid, int nodisplay, int div,
int size, int nocomp, int *ow );
int I_RegisterSong(void* data, int musicLen)
{
FILE *f;
int ow = 2;
info_t *info;
if (!(info = malloc (sizeof(info_t))))
return 0;
info->status = STATE_STOPPED;
info->unpausePosition = 0;
if ( (f = fopen(musName, "wb")) == NULL ) {
Printf ("Unable to open temporary music file %s", musName);
free (info);
return 0;
}
if ( fwrite(data, musicLen, 1, f) != 1 ) {
fclose (f);
Printf ("Unable to write temporary music file\n");
free (info);
return 0;
}
fclose(f);
if (*(int *)data == (('M')|(('U')<<8)|(('S')<<16)|((0x1a)<<24))) {
// This is a mus file
info->type = TYPE_MIDI;
convert(musName, midName, 1, 89, 0, 1, &ow);
remove (musName);
info->filename = midName;
} else if (*(int *)data == (('M')|(('T')<<8)|(('h')<<16)|(('d')<<24))) {
// This is a midi file
info->type = TYPE_MIDI;
remove (midName);
rename (musName, midName);
info->filename = midName;
} else {
if (info->module = MIDASloadModule (musName)) {
// This is a module
info->type = TYPE_MOD;
remove (musName);
info->filename = NULL;
} else {
// This is not any known music format
// (or could not load mod)
remove (musName);
free (info);
info = NULL;
}
}
return (int)info;
}
// Is the song playing?
int I_QrySongPlaying(int handle)
{
info_t *info = (info_t *)handle;
if (!info)
return 0;
else if (info->looping == 1)
return 1;
else
return info->status;
}

File diff suppressed because it is too large Load diff

View file

@ -167,6 +167,7 @@ typedef enum
SPR_BRS1, SPR_BRS1,
SPR_TLMP, SPR_TLMP,
SPR_TLP2, SPR_TLP2,
SPR_TNT1,
// [RH] Gibs // [RH] Gibs
SPR_GIB0, SPR_GIB0,
SPR_GIB1, SPR_GIB1,
@ -178,6 +179,7 @@ typedef enum
SPR_GIB7, SPR_GIB7,
// [RH] Dummy for unknown mapthing // [RH] Dummy for unknown mapthing
SPR_UNKN, SPR_UNKN,
SPR_TLGL,
NUMSPRITES NUMSPRITES
} spritenum_t; } spritenum_t;
@ -1151,6 +1153,7 @@ typedef enum
S_TECH2LAMP2, S_TECH2LAMP2,
S_TECH2LAMP3, S_TECH2LAMP3,
S_TECH2LAMP4, S_TECH2LAMP4,
S_TNT1,
// [RH] gibs // [RH] gibs
S_GIB0, S_GIB0,
S_GIB1, S_GIB1,
@ -1162,6 +1165,12 @@ typedef enum
S_GIB7, S_GIB7,
S_AMBIENTSOUND, S_AMBIENTSOUND,
S_UNKNOWNTHING, S_UNKNOWNTHING,
S_BRIDGE1,
S_BRIDGE2,
S_BRIDGE3,
S_BRIDGE4,
S_BRIDGE5,
S_SWITCHTEMP,
NUMSTATES NUMSTATES
} statenum_t; } statenum_t;
@ -1333,7 +1342,7 @@ typedef enum {
MT_STEALTHUNDEAD, MT_STEALTHUNDEAD,
MT_STEALTHSHOTGUY, MT_STEALTHSHOTGUY,
MT_STEALTHZOMBIE, MT_STEALTHZOMBIE,
// [RH] Gibs // [RH] Gibs (code is disabled)
MT_GIB0, MT_GIB0,
MT_GIB1, MT_GIB1,
MT_GIB2, MT_GIB2,
@ -1342,72 +1351,18 @@ typedef enum {
MT_GIB5, MT_GIB5,
MT_GIB6, MT_GIB6,
MT_GIB7, MT_GIB7,
// [RH] Miscellaneous things
MT_UNKNOWNTHING, MT_UNKNOWNTHING,
// [RH] Ambient sounds (up to 64) MT_MAPSPOT,
MT_AMBIENT0, MT_MAPSPOTGRAV,
MT_AMBIENT1, MT_BRIDGE,
MT_AMBIENT2, MT_PUSH, // Boom's push thing
MT_AMBIENT3, MT_PULL, // Boom's pull thing
MT_AMBIENT4, MT_PATHNODE,
MT_AMBIENT5, MT_AMBIENT, // Ambient sounds
MT_AMBIENT6, MT_SWITCHTEMP, // Temporary mobj for switch sounds
MT_AMBIENT7, MT_TELEPORTMAN2,// Teleport destination that pays attention to its height
MT_AMBIENT8, MT_CAMERA, // Camera used for "cutscenes"
MT_AMBIENT9,
MT_AMBIENT10,
MT_AMBIENT11,
MT_AMBIENT12,
MT_AMBIENT13,
MT_AMBIENT14,
MT_AMBIENT15,
MT_AMBIENT16,
MT_AMBIENT17,
MT_AMBIENT18,
MT_AMBIENT19,
MT_AMBIENT20,
MT_AMBIENT21,
MT_AMBIENT22,
MT_AMBIENT23,
MT_AMBIENT24,
MT_AMBIENT25,
MT_AMBIENT26,
MT_AMBIENT27,
MT_AMBIENT28,
MT_AMBIENT29,
MT_AMBIENT30,
MT_AMBIENT31,
MT_AMBIENT32,
MT_AMBIENT33,
MT_AMBIENT34,
MT_AMBIENT35,
MT_AMBIENT36,
MT_AMBIENT37,
MT_AMBIENT38,
MT_AMBIENT39,
MT_AMBIENT40,
MT_AMBIENT41,
MT_AMBIENT42,
MT_AMBIENT43,
MT_AMBIENT44,
MT_AMBIENT45,
MT_AMBIENT46,
MT_AMBIENT47,
MT_AMBIENT48,
MT_AMBIENT49,
MT_AMBIENT50,
MT_AMBIENT51,
MT_AMBIENT52,
MT_AMBIENT53,
MT_AMBIENT54,
MT_AMBIENT55,
MT_AMBIENT56,
MT_AMBIENT57,
MT_AMBIENT58,
MT_AMBIENT59,
MT_AMBIENT60,
MT_AMBIENT61,
MT_AMBIENT62,
MT_AMBIENT63,
NUMMOBJTYPES NUMMOBJTYPES
} mobjtype_t; } mobjtype_t;
@ -1418,23 +1373,23 @@ typedef struct
int spawnstate; int spawnstate;
int spawnhealth; int spawnhealth;
int seestate; int seestate;
int seesound; char *seesound; // [RH] not int
int reactiontime; int reactiontime;
int attacksound; char *attacksound; // [RH] not int
int painstate; int painstate;
int painchance; int painchance;
int painsound; char *painsound; // [RH] not int
int meleestate; int meleestate;
int missilestate; int missilestate;
int deathstate; int deathstate;
int xdeathstate; int xdeathstate;
int deathsound; char *deathsound; // [RH] not int
int speed; int speed;
int radius; int radius;
int height; int height;
int mass; int mass;
int damage; int damage;
int activesound; char *activesound; // [RH] not int
int flags; int flags;
int raisestate; int raisestate;

View file

@ -114,9 +114,9 @@ void cht_DoCheat (player_t *player, int cheat)
case CHT_IDDQD: case CHT_IDDQD:
if (!(player->cheats & CF_GODMODE)) { if (!(player->cheats & CF_GODMODE)) {
if (player->mo) if (player->mo)
player->mo->health = deh_GodHealth; player->mo->health = deh.GodHealth;
player->health = deh_GodHealth; player->health = deh.GodHealth;
} }
case CHT_GOD: case CHT_GOD:
player->cheats ^= CF_GODMODE; player->cheats ^= CF_GODMODE;
@ -153,8 +153,8 @@ void cht_DoCheat (player_t *player, int cheat)
cht_Give (player, "weapons"); cht_Give (player, "weapons");
cht_Give (player, "ammo"); cht_Give (player, "ammo");
cht_Give (player, "keys"); cht_Give (player, "keys");
player->armorpoints = deh_KFAArmor; player->armorpoints = deh.KFAArmor;
player->armortype = deh_KFAAC; player->armortype = deh.KFAAC;
msg = STSTR_KFAADDED; msg = STSTR_KFAADDED;
break; break;
@ -162,8 +162,8 @@ void cht_DoCheat (player_t *player, int cheat)
cht_Give (player, "backpack"); cht_Give (player, "backpack");
cht_Give (player, "weapons"); cht_Give (player, "weapons");
cht_Give (player, "ammo"); cht_Give (player, "ammo");
player->armorpoints = deh_FAArmor; player->armorpoints = deh.FAArmor;
player->armortype = deh_FAAC; player->armortype = deh.FAAC;
msg = STSTR_FAADDED; msg = STSTR_FAADDED;
break; break;
@ -201,10 +201,15 @@ void cht_DoCheat (player_t *player, int cheat)
if (currentthinker->function.acp1 == (actionf_p1) P_MobjThinker && if (currentthinker->function.acp1 == (actionf_p1) P_MobjThinker &&
(((mobj_t *) currentthinker)->flags & MF_COUNTKILL || (((mobj_t *) currentthinker)->flags & MF_COUNTKILL ||
((mobj_t *) currentthinker)->type == MT_SKULL)) ((mobj_t *) currentthinker)->type == MT_SKULL))
{ // killough 3/6/98: kill even if PE is dead {
if (((mobj_t *) currentthinker)->flags2 & MF2_INDESTRUCTABLE)
continue; // [RH] Don't kill if indestructable
// killough 3/6/98: kill even if PE is dead
if (((mobj_t *) currentthinker)->health > 0) if (((mobj_t *) currentthinker)->health > 0)
{ {
killcount++; killcount++;
((mobj_t *)currentthinker)->flags2 &= ~MF2_INVULNERABLE;
P_DamageMobj((mobj_t *)currentthinker, NULL, NULL, 10000, MOD_UNKNOWN); P_DamageMobj((mobj_t *)currentthinker, NULL, NULL, 10000, MOD_UNKNOWN);
} }
if (((mobj_t *) currentthinker)->type == MT_PAIN) if (((mobj_t *) currentthinker)->type == MT_PAIN)
@ -223,7 +228,7 @@ void cht_DoCheat (player_t *player, int cheat)
if (player == &players[consoleplayer]) if (player == &players[consoleplayer])
Printf ("%s\n", msg); Printf ("%s\n", msg);
else else
Printf ("%s is cheating: %s\n", player->userinfo->netname, msg); Printf ("%s is a cheater: %s\n", player->userinfo.netname, msg);
} }
void cht_Give (player_t *player, char *name) void cht_Give (player_t *player, char *name)
@ -233,7 +238,7 @@ void cht_Give (player_t *player, char *name)
gitem_t *it; gitem_t *it;
if (player != &players[consoleplayer]) if (player != &players[consoleplayer])
Printf ("%s is cheating: give %s\n", player->userinfo->netname, name); Printf ("%s is a cheater: give %s\n", player->userinfo.netname, name);
if (stricmp (name, "all") == 0) if (stricmp (name, "all") == 0)
giveall = true; giveall = true;
@ -252,9 +257,9 @@ void cht_Give (player_t *player, char *name)
} }
} else { } else {
if (player->mo) if (player->mo)
player->mo->health = deh_GodHealth; player->mo->health = deh.GodHealth;
player->health = deh_GodHealth; player->health = deh.GodHealth;
} }
if (!giveall) if (!giveall)
@ -332,7 +337,7 @@ void cht_Give (player_t *player, char *name)
P_GiveWeapon (player, it->offset, 0); P_GiveWeapon (player, it->offset, 0);
} else if (it->flags & IT_KEY) { } else if (it->flags & IT_KEY) {
P_GiveCard (player, it->offset); P_GiveCard (player, it->offset);
} else if (it->flags & IT_POWER) { } else if (it->flags & IT_POWERUP) {
P_GivePower (player, it->offset); P_GivePower (player, it->offset);
} else if (it->flags & IT_ARMOR) { } else if (it->flags & IT_ARMOR) {
P_GiveArmor (player, it->offset); P_GiveArmor (player, it->offset);

File diff suppressed because it is too large Load diff

View file

@ -26,6 +26,7 @@
#include "d_event.h" #include "d_event.h"
#include "c_cvars.h"
// //
// MENUS // MENUS
@ -37,7 +38,6 @@
// Does all the real work of the menu interaction. // Does all the real work of the menu interaction.
BOOL M_Responder (event_t *ev); BOOL M_Responder (event_t *ev);
// Called by main loop, // Called by main loop,
// only used for menu (skull cursor) animation. // only used for menu (skull cursor) animation.
void M_Ticker (void); void M_Ticker (void);
@ -66,8 +66,102 @@ void M_OptDrawer (void);
// [RH] Initialize options menu // [RH] Initialize options menu
void M_OptInit (void); void M_OptInit (void);
void M_SwitchMenu (struct menu_s *menu);
//
// MENU TYPEDEFS
//
typedef enum {
whitetext,
redtext,
more,
slider,
discrete,
control,
screenres,
bitflag,
listelement
} itemtype;
typedef struct menuitem_s {
itemtype type;
char *label;
union {
cvar_t **cvar;
int selmode;
int flagmask;
} a;
union {
float min; /* aka numvalues aka invflag */
int key1;
char *res1;
} b;
union {
float max;
int key2;
char *res2;
} c;
union {
float step;
char *res3;
} d;
union {
struct value_s *values;
char *command;
void (*cfunc)(cvar_t *cvar, float newval);
void (*mfunc)(void);
void (*lfunc)(int);
int highlight;
int *flagint;
} e;
} menuitem_t;
typedef struct menu_s {
char title[8];
int lastOn;
int numitems;
int indent;
menuitem_t *items;
struct menu_s *prevmenu;
} menu_t;
typedef struct value_s {
float value;
char *name;
} value_t;
typedef struct
{
// -1 = no cursor here, 1 = ok, 2 = arrows ok
short status;
char name[10];
// choice = menu item #.
// if status = 2,
// choice=0:leftarrow,1:rightarrow
void (*routine)(int choice);
// hotkey in menu
char alphaKey;
} oldmenuitem_t;
typedef struct oldmenu_s
{
short numitems; // # of menu items
struct oldmenu_s* prevMenu; // previous menu
oldmenuitem_t *menuitems; // menu items
void (*routine)(); // draw routine
short x;
short y; // x,y of menu
short lastOn; // last item user was on in menu
} oldmenu_t;
extern value_t YesNo[2];
extern value_t NoYes[2];
extern value_t OnOff[2];
#endif #endif
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// //

View file

@ -26,6 +26,7 @@
#include "doomtype.h" #include "doomtype.h"
#include "version.h"
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/types.h> #include <sys/types.h>
@ -146,6 +147,9 @@ char *GetConfigPath (void)
return copystring (myargv[p+1]); return copystring (myargv[p+1]);
} }
if (M_CheckParm ("-cdrom"))
return copystring ("c:\\zdoomdat\\zdoom.cfg");
path = Malloc (strlen (progdir) + 11); path = Malloc (strlen (progdir) + 11);
strcpy (path, progdir); strcpy (path, progdir);
@ -156,24 +160,36 @@ char *GetConfigPath (void)
char *GetAutoexecPath (void) char *GetAutoexecPath (void)
{ {
cvar_t *autovar; cvar_t *autovar;
char *path = Malloc (strlen (progdir) + 13);
strcpy (path, progdir); if (M_CheckParm ("-cdrom")) {
strcat (path, "autoexec.cfg"); return copystring ("c:\\zdoomdat\\autoexec.cfg");
} else {
char *path = Malloc (strlen (progdir) + 13);
autovar = cvar ("autoexec", path, CVAR_ARCHIVE); strcpy (path, progdir);
free (path); strcat (path, "autoexec.cfg");
return autovar->string; autovar = cvar ("autoexec", path, CVAR_ARCHIVE);
free (path);
return autovar->string;
}
} }
// //
// M_SaveDefaults // M_SaveDefaults
// //
// [RH] Don't write a config file if M_LoadDefaults hasn't been called.
static BOOL DefaultsLoaded;
void M_SaveDefaults (void) void M_SaveDefaults (void)
{ {
FILE* f; FILE *f;
char* configfile; char *configfile;
if (!DefaultsLoaded)
return;
configfile = GetConfigPath (); configfile = GetConfigPath ();
@ -201,7 +217,8 @@ void M_SaveDefaults (void)
// //
// M_LoadDefaults // M_LoadDefaults
// //
extern byte scantokey[128]; extern byte scantokey[128];
extern int cvar_defflags;
void M_LoadDefaults (void) void M_LoadDefaults (void)
{ {
@ -220,15 +237,17 @@ void M_LoadDefaults (void)
configver = cvar ("configver", VERSIONSTR, CVAR_ARCHIVE); configver = cvar ("configver", VERSIONSTR, CVAR_ARCHIVE);
configfile = GetConfigPath (); configfile = GetConfigPath ();
execcommand = Malloc (strlen (configfile) + 6); execcommand = Malloc (strlen (configfile) + 8);
sprintf (execcommand, "exec %s", configfile); sprintf (execcommand, "exec \"%s\"", configfile);
free (configfile); free (configfile);
cvar_defflags = CVAR_ARCHIVE;
AddCommandString (execcommand); AddCommandString (execcommand);
cvar_defflags = 0;
free (execcommand); free (execcommand);
configfile = GetAutoexecPath (); configfile = GetAutoexecPath ();
execcommand = Malloc (strlen (configfile) + 6); execcommand = Malloc (strlen (configfile) + 8);
sprintf (execcommand, "exec %s", configfile); sprintf (execcommand, "exec \"%s\"", configfile);
AddCommandString (execcommand); AddCommandString (execcommand);
free (execcommand); free (execcommand);
@ -237,6 +256,8 @@ void M_LoadDefaults (void)
if (!stricmp (C_GetBinding (KEY_F5), "menu_video")) if (!stricmp (C_GetBinding (KEY_F5), "menu_video"))
AddCommandString ("bind f5 menu_display"); AddCommandString ("bind f5 menu_display");
} }
DefaultsLoaded = true;
} }
@ -354,16 +375,23 @@ extern unsigned IndexedPalette[256];
void M_ScreenShot (char *filename) void M_ScreenShot (char *filename)
{ {
byte* linear; byte *linear;
char lbmname[16]; char autoname[32];
char *lbmname;
// find a file name to save it to // find a file name to save it to
if (!filename) { if (!filename) {
if (M_CheckParm ("-cdrom")) {
strcpy (autoname, "C:\\ZDOOMDAT\\");
lbmname = autoname + 12;
} else {
lbmname = autoname;
}
if (!FindFreeName (lbmname, "tga\0pcx" + (screens[0].is8bit << 2))) { if (!FindFreeName (lbmname, "tga\0pcx" + (screens[0].is8bit << 2))) {
Printf ("M_ScreenShot: Delete some screenshots\n"); Printf ("M_ScreenShot: Delete some screenshots\n");
return; return;
} }
filename = lbmname; filename = autoname;
} }
if (screens[0].is8bit) { if (screens[0].is8bit) {

476
code/P_ceilng.c Normal file
View file

@ -0,0 +1,476 @@
// Emacs style mode select -*- C++ -*-
//-----------------------------------------------------------------------------
//
// $Id:$
//
// Copyright (C) 1993-1996 by id Software, Inc.
//
// This source is available for distribution and/or modification
// only under the terms of the DOOM Source Code License as
// published by id Software. All rights reserved.
//
// The source is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
// for more details.
//
// $Log:$
//
// DESCRIPTION: Ceiling aninmation (lowering, crushing, raising)
//
//-----------------------------------------------------------------------------
#include "m_alloc.h"
#include "z_zone.h"
#include "doomdef.h"
#include "p_local.h"
#include "s_sound.h"
// State.
#include "doomstat.h"
#include "r_state.h"
//
// CEILINGS
//
// [RH] Active ceilings are now linked together in a list instead
// of stored in an array. Similar to what Lee Killough did
// with BOOM except I link the ceilings themselves together.
ceiling_t *activeceilings;
//
// T_MoveCeiling
//
void T_MoveCeiling (ceiling_t* ceiling)
{
result_e res;
switch(ceiling->direction)
{
case 0:
// IN STASIS
break;
case 1:
// UP
res = T_MovePlane(ceiling->sector,
ceiling->speed,
ceiling->topheight,
-1,1,ceiling->direction);
// Make moving sound
if (!(level.time&7) && (ceiling->silent == 0))
S_StartSound ((mobj_t *)&ceiling->sector->soundorg, "plats/pt1_mid", 119);
if (res == pastdest)
{
switch (ceiling->type)
{
case ceilCrushAndRaise:
if (ceiling->silent == 1)
S_StartSound((mobj_t *)&ceiling->sector->soundorg, "plats/pt1_stop", 100);
ceiling->direction = -1;
ceiling->speed = ceiling->speed1;
break;
// movers with texture change, change the texture then get removed
case genCeilingChgT:
case genCeilingChg0:
ceiling->sector->special = ceiling->newspecial;
case genCeilingChg:
ceiling->sector->ceilingpic = ceiling->texture;
// fall through
default:
P_RemoveActiveCeiling(ceiling);
break;
}
}
break;
case -1:
// DOWN
res = T_MovePlane(ceiling->sector,
ceiling->speed,
ceiling->bottomheight,
ceiling->crush,1,ceiling->direction);
// Make moving noise
if (!(level.time&7) && !ceiling->silent)
S_StartSound((mobj_t *)&ceiling->sector->soundorg, "plats/pt1_mid", 119);
if (res == pastdest)
{
switch (ceiling->type)
{
case ceilCrushAndRaise:
case ceilCrushRaiseAndStay:
if (ceiling->silent == 1)
S_StartSound ((mobj_t *)&ceiling->sector->soundorg, "plats/pt1_stop", 100);
ceiling->speed = ceiling->speed2;
ceiling->direction = 1;
break;
// in the case of ceiling mover/changer, change the texture
// then remove the active ceiling
case genCeilingChgT:
case genCeilingChg0:
ceiling->sector->special = ceiling->newspecial;
case genCeilingChg:
ceiling->sector->ceilingpic = ceiling->texture;
// fall through
default:
P_RemoveActiveCeiling(ceiling);
break;
}
}
else // ( res != pastdest )
{
if (res == crushed)
{
switch (ceiling->type)
{
case ceilCrushAndRaise:
case ceilLowerAndCrush:
if (ceiling->speed1 == FRACUNIT && ceiling->speed2 == FRACUNIT)
ceiling->speed = FRACUNIT / 8;
break;
default:
break;
}
}
}
break;
}
}
//
// EV_DoCeiling
// Move a ceiling up/down and all around!
//
// [RH] Added tag, speed, speed2, height, crush, silent, change params
BOOL EV_DoCeiling (ceiling_e type, line_t *line,
int tag, fixed_t speed, fixed_t speed2, fixed_t height,
int crush, int silent, int change)
{
int secnum;
BOOL rtn;
sector_t* sec;
ceiling_t* ceiling;
BOOL manual = false;
fixed_t targheight;
rtn = false;
// check if a manual trigger, if so do just the sector on the backside
if (tag == 0)
{
if (!line || !(sec = line->backsector))
return rtn;
secnum = sec-sectors;
manual = true;
// [RH] Hack to let manual crushers be retriggerable, too
tag ^= secnum | 0x1000000;
P_ActivateInStasisCeiling (tag);
goto manual_ceiling;
}
// Reactivate in-stasis ceilings...for certain types.
// This restarts a crusher after it has been stopped
if (type == ceilCrushAndRaise)
{
P_ActivateInStasisCeiling (tag);
}
secnum = -1;
// affects all sectors with the same tag as the linedef
while ((secnum = P_FindSectorFromTag (tag, secnum)) >= 0)
{
sec = &sectors[secnum];
manual_ceiling:
// if ceiling already moving, don't start a second function on it
if (P_SectorActive (ceiling_special,sec)) //jff 2/22/98
continue;
// new door thinker
rtn = 1;
ceiling = Z_Malloc (sizeof(*ceiling), PU_LEVSPEC, 0);
P_AddThinker (&ceiling->thinker);
sec->ceilingdata = ceiling; //jff 2/22/98
ceiling->thinker.function.acp1 = (actionf_p1)T_MoveCeiling;
ceiling->sector = sec;
ceiling->crush = -1;
ceiling->speed = ceiling->speed1 = speed;
ceiling->speed2 = speed2;
ceiling->silent = silent;
switch(type)
{
case ceilCrushAndRaise:
case ceilCrushRaiseAndStay:
ceiling->topheight = sec->ceilingheight;
case ceilLowerAndCrush:
ceiling->crush = crush;
targheight = ceiling->bottomheight = sec->floorheight + 8*FRACUNIT;
ceiling->direction = -1;
break;
case ceilRaiseToHighest:
targheight = ceiling->topheight = P_FindHighestCeilingSurrounding (sec);
ceiling->direction = 1;
break;
case ceilLowerByValue:
targheight = ceiling->bottomheight = sec->ceilingheight - height;
ceiling->direction = -1;
break;
case ceilRaiseByValue:
targheight = ceiling->topheight = sec->ceilingheight + height;
ceiling->direction = 1;
break;
case ceilMoveToValue:
{
int diff = height - sec->ceilingheight;
if (diff < 0) {
targheight = ceiling->bottomheight = height;
ceiling->direction = -1;
} else {
targheight = ceiling->topheight = height;
ceiling->direction = 1;
}
}
break;
case ceilLowerToHighestFloor:
targheight = ceiling->bottomheight = P_FindHighestFloorSurrounding (sec);
ceiling->direction = -1;
break;
case ceilRaiseToHighestFloor:
targheight = ceiling->topheight = P_FindHighestFloorSurrounding (sec);
ceiling->direction = 1;
break;
case ceilLowerInstant:
targheight = ceiling->bottomheight = sec->ceilingheight - height;
ceiling->direction = -1;
ceiling->speed = height;
break;
case ceilRaiseInstant:
targheight = ceiling->topheight = sec->ceilingheight + height;
ceiling->direction = 1;
ceiling->speed = height;
break;
case ceilLowerToNearest:
targheight = ceiling->bottomheight =
P_FindNextLowestCeiling (sec, sec->ceilingheight);
ceiling->direction = 1;
break;
case ceilRaiseToNearest:
targheight = ceiling->topheight =
P_FindNextHighestCeiling (sec, sec->ceilingheight);
ceiling->direction = 1;
break;
case ceilLowerToLowest:
targheight = ceiling->bottomheight = P_FindLowestCeilingSurrounding (sec);
ceiling->direction = -1;
break;
case ceilRaiseToLowest:
targheight = ceiling->topheight = P_FindLowestCeilingSurrounding (sec);
ceiling->direction = -1;
break;
case ceilLowerToFloor:
targheight = ceiling->bottomheight = sec->floorheight;
ceiling->direction = -1;
break;
case ceilRaiseToFloor:
targheight = ceiling->topheight = sec->floorheight;
ceiling->direction = 1;
break;
case ceilLowerToHighest:
targheight = ceiling->bottomheight = P_FindHighestCeilingSurrounding (sec);
ceiling->direction = -1;
break;
case ceilLowerByTexture:
targheight = ceiling->bottomheight =
sec->ceilingheight - P_FindShortestUpperAround (secnum);
ceiling->direction = -1;
break;
case ceilRaiseByTexture:
targheight = ceiling->topheight =
sec->ceilingheight + P_FindShortestUpperAround (secnum);
ceiling->direction = 1;
break;
}
ceiling->tag = tag;
ceiling->type = type;
// set texture/type change properties
if (change & 3) // if a texture change is indicated
{
if (change & 4) // if a numeric model change
{
sector_t *sec;
//jff 5/23/98 find model with floor at target height if target
//is a floor type
sec = (type == ceilRaiseToHighest ||
type == ceilRaiseToFloor ||
type == ceilLowerToHighest ||
type == ceilLowerToFloor) ?
P_FindModelFloorSector (targheight, secnum) :
P_FindModelCeilingSector (targheight, secnum);
if (sec)
{
ceiling->texture = sec->ceilingpic;
switch (change & 3)
{
case 1: // type is zeroed
ceiling->newspecial = 0;
ceiling->type = genCeilingChg0;
break;
case 2: // type is copied
ceiling->newspecial = sec->special;
ceiling->type = genCeilingChgT;
break;
case 3: // type is left alone
ceiling->type = genCeilingChg;
break;
}
}
}
else if (line) // else if a trigger model change
{
ceiling->texture = line->frontsector->ceilingpic;
switch (change & 3)
{
case 1: // type is zeroed
ceiling->newspecial = 0;
ceiling->type = genCeilingChg0;
break;
case 2: // type is copied
ceiling->newspecial = line->frontsector->special;
ceiling->type = genCeilingChgT;
break;
case 3: // type is left alone
ceiling->type = genCeilingChg;
break;
}
}
}
P_AddActiveCeiling(ceiling);
if (manual)
return rtn;
}
return rtn;
}
//
// Add an active ceiling
// [RH] Rewritten to use list
//
void P_AddActiveCeiling (ceiling_t *c)
{
c->next = activeceilings;
c->prev = NULL;
activeceilings = c;
}
//
// Remove a ceiling's thinker
// [RH] Rewritten to use list
//
void P_RemoveActiveCeiling (ceiling_t *c)
{
ceiling_t *scan = activeceilings;
while (scan) {
if (scan == c) {
c->sector->ceilingdata = NULL;
if (c == activeceilings) {
activeceilings = c->next;
} else {
if (c->prev)
c->prev->next = c->next;
if (c->next)
c->next->prev = c->prev;
}
P_RemoveThinker (&c->thinker);
break;
}
scan = scan->next;
}
}
//
// Restart a ceiling that's in-stasis
// [RH] Passed a tag instead of a line and rewritten to use list
//
void P_ActivateInStasisCeiling (int tag)
{
ceiling_t *scan = activeceilings;
while (scan) {
if (scan->tag == tag && scan->direction == 0) {
scan->direction = scan->olddirection;
scan->thinker.function.acp1 = (actionf_p1) T_MoveCeiling;
}
scan = scan->next;
}
}
//
// EV_CeilingCrushStop
// Stop a ceiling from crushing!
// [RH] Passed a tag instead of a line and rewritten to use list
//
BOOL EV_CeilingCrushStop (int tag)
{
BOOL rtn = false;
ceiling_t *scan = activeceilings;
while (scan) {
if (scan->tag == tag && scan->direction != 0) {
scan->olddirection = scan->direction;
scan->thinker.function.acv = (actionf_v) NULL;
scan->direction = 0; // in-stasis;
rtn = true;
}
scan = scan->next;
}
return rtn;
}

View file

@ -17,6 +17,7 @@
// $Log:$ // $Log:$
// //
// DESCRIPTION: Door animation code (opening/closing) // DESCRIPTION: Door animation code (opening/closing)
// [RH] Removed sliding door code and simplified for Hexen-ish specials
// //
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -35,36 +36,35 @@
// Data. // Data.
#include "dstrings.h" #include "dstrings.h"
#include "sounds.h"
#include "c_consol.h" #include "c_consol.h"
#if 0
//
// Sliding door frame information
//
slidename_t slideFrameNames[MAXSLIDEDOORS] =
{
{"GDOORF1","GDOORF2","GDOORF3","GDOORF4", // front
"GDOORB1","GDOORB2","GDOORB3","GDOORB4"}, // back
{"\0","\0","\0","\0"}
};
#endif
// //
// VERTICAL DOORS // VERTICAL DOORS
// //
// [RH] DoorSound: Plays door sound depending on its direction and speed
static void DoorSound (vldoor_t *door, fixed_t speed, BOOL raise)
{
char *snd;
if (raise)
snd = (speed >= FRACUNIT*8) ? "doors/dr2_open" : "doors/dr1_open";
else
snd = (speed >= FRACUNIT*8) ? "doors/dr2_clos" : "doors/dr1_clos";
S_StartSound ((mobj_t *)&door->sector->soundorg, snd, 100);
}
// //
// T_VerticalDoor // T_VerticalDoor
// //
void T_VerticalDoor (vldoor_t* door) void T_VerticalDoor (vldoor_t *door)
{ {
result_e res; result_e res;
switch(door->direction) switch (door->direction)
{ {
case 0: case 0:
// WAITING // WAITING
@ -72,22 +72,14 @@ void T_VerticalDoor (vldoor_t* door)
{ {
switch(door->type) switch(door->type)
{ {
case blazeRaise: case doorRaise:
door->direction = -1; // time to go back down door->direction = -1; // time to go back down
S_StartSound((mobj_t *)&door->sector->soundorg, DoorSound (door, door->speed, false);
sfx_bdcls);
break; break;
case normal: case doorCloseWaitOpen:
door->direction = -1; // time to go back down
S_StartSound((mobj_t *)&door->sector->soundorg,
sfx_dorcls);
break;
case close30ThenOpen:
door->direction = 1; door->direction = 1;
S_StartSound((mobj_t *)&door->sector->soundorg, DoorSound (door, door->speed, true);
sfx_doropn);
break; break;
default: default:
@ -102,11 +94,10 @@ void T_VerticalDoor (vldoor_t* door)
{ {
switch(door->type) switch(door->type)
{ {
case raiseIn5Mins: case doorRaiseIn5Mins:
door->direction = 1; door->direction = 1;
door->type = normal; door->type = doorRaise;
S_StartSound((mobj_t *)&door->sector->soundorg, DoorSound (door, door->speed, true);
sfx_doropn);
break; break;
default: default:
@ -120,27 +111,20 @@ void T_VerticalDoor (vldoor_t* door)
res = T_MovePlane(door->sector, res = T_MovePlane(door->sector,
door->speed, door->speed,
door->sector->floorheight, door->sector->floorheight,
false,1,door->direction); -1,1,door->direction);
if (res == pastdest) if (res == pastdest)
{ {
switch(door->type) switch(door->type)
{ {
case blazeRaise: case doorRaise:
case blazeClose: case doorClose:
door->sector->ceilingdata = NULL; //jff 2/22/98
P_RemoveThinker (&door->thinker); // unlink and free
S_StartSound((mobj_t *)&door->sector->soundorg, sfx_bdcls);
break;
case normal:
case close:
door->sector->ceilingdata = NULL; //jff 2/22/98 door->sector->ceilingdata = NULL; //jff 2/22/98
P_RemoveThinker (&door->thinker); // unlink and free P_RemoveThinker (&door->thinker); // unlink and free
break; break;
case close30ThenOpen: case doorCloseWaitOpen:
door->direction = 0; door->direction = 0;
door->topcountdown = TICRATE*30; door->topcountdown = door->topwait;
break; break;
default: default:
@ -151,14 +135,12 @@ void T_VerticalDoor (vldoor_t* door)
{ {
switch(door->type) switch(door->type)
{ {
case blazeClose: case doorClose: // DO NOT GO BACK UP!
case close: // DO NOT GO BACK UP!
break; break;
default: default:
door->direction = 1; door->direction = 1;
S_StartSound((mobj_t *)&door->sector->soundorg, DoorSound (door, door->speed, true);
sfx_doropn);
break; break;
} }
} }
@ -169,21 +151,19 @@ void T_VerticalDoor (vldoor_t* door)
res = T_MovePlane(door->sector, res = T_MovePlane(door->sector,
door->speed, door->speed,
door->topheight, door->topheight,
false,1,door->direction); -1,1,door->direction);
if (res == pastdest) if (res == pastdest)
{ {
switch(door->type) switch(door->type)
{ {
case blazeRaise: case doorRaise:
case normal:
door->direction = 0; // wait at top door->direction = 0; // wait at top
door->topcountdown = door->topwait; door->topcountdown = door->topwait;
break; break;
case close30ThenOpen: case doorCloseWaitOpen:
case blazeOpen: case doorOpen:
case open:
door->sector->ceilingdata = NULL; //jff 2/22/98 door->sector->ceilingdata = NULL; //jff 2/22/98
P_RemoveThinker (&door->thinker); // unlink and free P_RemoveThinker (&door->thinker); // unlink and free
break; break;
@ -197,139 +177,110 @@ void T_VerticalDoor (vldoor_t* door)
} }
// // [RH] Merged EV_VerticalDoor and EV_DoLockedDoor into EV_DoDoor
// EV_DoLockedDoor // and made them more general to support the new specials.
// Move a locked door up/down
//
int // [RH] SpawnDoor: Helper function for EV_DoDoor
EV_DoLockedDoor static BOOL SpawnDoor (sector_t *sec, vldoor_e type, fixed_t speed, int delay)
( line_t* line,
vldoor_e type,
mobj_t* thing )
{ {
player_t* p; // new door thinker
vldoor_t *door = Z_Malloc (sizeof(*door), PU_LEVSPEC, 0);
p = thing->player; P_AddThinker (&door->thinker);
sec->ceilingdata = door; //jff 2/22/98
if (!p)
return 0; door->thinker.function.acp1 = (actionf_p1) T_VerticalDoor;
door->sector = sec;
switch(line->special) door->type = type;
door->topwait = delay;
door->speed = speed;
switch(type)
{ {
case 99: // Blue Lock case doorClose:
case 133: door->topheight = P_FindLowestCeilingSurrounding (sec) - 4*FRACUNIT;
if (!p->cards[it_bluecard] && !p->cards[it_blueskull])
{
C_MidPrint (PD_BLUEO);
S_StartSound(ORIGIN_AMBIENT,sfx_oof);
return 0;
}
break;
case 134: // Red Lock
case 135:
if (!p->cards[it_redcard] && !p->cards[it_redskull])
{
C_MidPrint (PD_REDO);
S_StartSound(ORIGIN_AMBIENT,sfx_oof);
return 0;
}
break;
case 136: // Yellow Lock
case 137:
if (!p->cards[it_yellowcard] &&
!p->cards[it_yellowskull])
{
C_MidPrint (PD_YELLOWO);
S_StartSound(ORIGIN_AMBIENT,sfx_oof);
return 0;
}
break;
}
return EV_DoDoor(line,type);
}
int EV_DoDoor (line_t *line, vldoor_e type)
{
int secnum,rtn;
sector_t* sec;
vldoor_t* door;
secnum = -1;
rtn = 0;
while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0)
{
sec = &sectors[secnum];
// if the ceiling already moving, don't start the door action
if (P_SectorActive(ceiling_special,sec)) //jff 2/22/98
continue;
// new door thinker
rtn = 1;
door = Z_Malloc (sizeof(*door), PU_LEVSPEC, 0);
P_AddThinker (&door->thinker);
sec->ceilingdata = door; //jff 2/22/98
door->thinker.function.acp1 = (actionf_p1) T_VerticalDoor;
door->sector = sec;
door->type = type;
door->topwait = VDOORWAIT;
door->speed = VDOORSPEED;
switch(type)
{
case blazeClose:
door->topheight = P_FindLowestCeilingSurrounding(sec);
door->topheight -= 4*FRACUNIT; door->topheight -= 4*FRACUNIT;
door->direction = -1; door->direction = -1;
door->speed = VDOORSPEED * 4; DoorSound (door, speed, false);
S_StartSound((mobj_t *)&door->sector->soundorg,
sfx_bdcls);
break; break;
case close: case doorOpen:
door->topheight = P_FindLowestCeilingSurrounding(sec); case doorRaise:
door->topheight -= 4*FRACUNIT; door->direction = 1;
door->direction = -1; door->topheight = P_FindLowestCeilingSurrounding (sec) - 4*FRACUNIT;
S_StartSound((mobj_t *)&door->sector->soundorg, if (door->topheight != sec->ceilingheight)
sfx_dorcls); DoorSound (door, speed, true);
break; break;
case close30ThenOpen: case doorCloseWaitOpen:
door->topheight = sec->ceilingheight; door->topheight = sec->ceilingheight;
door->direction = -1; door->direction = -1;
S_StartSound((mobj_t *)&door->sector->soundorg, DoorSound (door, speed, false);
sfx_dorcls);
break;
case blazeRaise:
case blazeOpen:
door->direction = 1;
door->topheight = P_FindLowestCeilingSurrounding(sec);
door->topheight -= 4*FRACUNIT;
door->speed = VDOORSPEED * 4;
if (door->topheight != sec->ceilingheight)
S_StartSound((mobj_t *)&door->sector->soundorg,
sfx_bdopn);
break;
case normal:
case open:
door->direction = 1;
door->topheight = P_FindLowestCeilingSurrounding(sec);
door->topheight -= 4*FRACUNIT;
if (door->topheight != sec->ceilingheight)
S_StartSound((mobj_t *)&door->sector->soundorg,
sfx_doropn);
break;
default:
break; break;
}
return true;
}
BOOL EV_DoDoor (vldoor_e type, line_t *line, mobj_t *thing,
int tag, int speed, int delay, keytype_t lock)
{
BOOL rtn = false;
int secnum;
sector_t* sec;
if (lock && !P_CheckKeys (thing->player, lock, tag))
return false;
if (tag == 0) { // [RH] manual door
if (!line)
return false;
// if the wrong side of door is pushed, give oof sound
if (line->sidenum[1]==-1) // killough
{
S_StartSound (thing, "*grunt1", 78);
return false;
}
// get the sector on the second side of activating linedef
sec = sides[line->sidenum[1]].sector;
secnum = sec-sectors;
// if door already has a thinker, use it
if (sec->ceilingdata) //jff 2/22/98
{
vldoor_t *door = sec->ceilingdata; //jff 2/22/98
if (type == doorRaise) {
// ONLY FOR "RAISE" DOORS, NOT "OPEN"s
if (door->direction == -1) {
door->direction = 1; // go back up
}
else if ((line->flags & ML_ACTIVATIONMASK) != ML_ACTIVATEPUSH)
// [RH] activate push doors don't go back down when you
// run into them (otherwise opening them would be
// a real pain).
{
if (!thing->player)
return false; // JDC: bad guys never close doors
door->direction = -1; // start going down immediately
}
return true;
}
}
rtn = SpawnDoor (sec, type, speed, delay);
} else { // [RH] Remote door
secnum = -1;
while ((secnum = P_FindSectorFromTag (tag,secnum)) >= 0)
{
sec = &sectors[secnum];
// if the ceiling already moving, don't start the door action
if (P_SectorActive (ceiling_special,sec)) //jff 2/22/98
continue;
rtn |= SpawnDoor (sec, type, speed, delay);
} }
} }
@ -337,171 +288,14 @@ int EV_DoDoor (line_t *line, vldoor_e type)
} }
//
// EV_VerticalDoor : open a door manually, no tag value
//
void EV_VerticalDoor (line_t *line, mobj_t *thing)
{
player_t* player;
int secnum;
sector_t* sec;
vldoor_t* door;
int side;
side = 0; // only front sides can be used
// Check for locks
player = thing->player;
switch(line->special)
{
case 26: // Blue Lock
case 32:
if ( !player )
return;
if (!player->cards[it_bluecard] && !player->cards[it_blueskull])
{
C_MidPrint (PD_BLUEK);
S_StartSound(ORIGIN_AMBIENT,sfx_oof);
return;
}
break;
case 27: // Yellow Lock
case 34:
if ( !player )
return;
if (!player->cards[it_yellowcard] &&
!player->cards[it_yellowskull])
{
C_MidPrint (PD_YELLOWK);
S_StartSound(ORIGIN_AMBIENT,sfx_oof);
return;
}
break;
case 28: // Red Lock
case 33:
if ( !player )
return;
if (!player->cards[it_redcard] && !player->cards[it_redskull])
{
C_MidPrint (PD_REDK);
S_StartSound(ORIGIN_AMBIENT,sfx_oof);
return;
}
break;
}
// if the wrong side of door is pushed, give oof sound
if (line->sidenum[1]==-1) // killough
{
S_StartSound(player->mo,sfx_oof); // killough 3/20/98
return /*0*/;
}
// get the sector on the second side of activating linedef
sec = sides[line->sidenum[1]].sector;
secnum = sec-sectors;
// if door already has a thinker, use it
if (sec->ceilingdata) //jff 2/22/98
{
door = sec->ceilingdata; //jff 2/22/98
switch(line->special)
{
case 1: // ONLY FOR "RAISE" DOORS, NOT "OPEN"s
case 26:
case 27:
case 28:
case 117:
if (door->direction == -1)
door->direction = 1; // go back up
else
{
if (!thing->player)
return; // JDC: bad guys never close doors
door->direction = -1; // start going down immediately
}
return;
}
}
// for proper sound
switch(line->special)
{
case 117: // BLAZING DOOR RAISE
case 118: // BLAZING DOOR OPEN
S_StartSound((mobj_t *)&sec->soundorg,sfx_bdopn);
break;
case 1: // NORMAL DOOR SOUND
case 31:
S_StartSound((mobj_t *)&sec->soundorg,sfx_doropn);
break;
default: // LOCKED DOOR SOUND
S_StartSound((mobj_t *)&sec->soundorg,sfx_doropn);
break;
}
// new door thinker
door = Z_Malloc (sizeof(*door), PU_LEVSPEC, 0);
P_AddThinker (&door->thinker);
sec->ceilingdata = door; //jff 2/22/98
door->thinker.function.acp1 = (actionf_p1) T_VerticalDoor;
door->sector = sec;
door->direction = 1;
door->speed = VDOORSPEED;
door->topwait = VDOORWAIT;
switch(line->special)
{
case 1:
case 26:
case 27:
case 28:
door->type = normal;
break;
case 31:
case 32:
case 33:
case 34:
door->type = open;
line->special = 0;
break;
case 117: // blazing door raise
door->type = blazeRaise;
door->speed = VDOORSPEED*4;
break;
case 118: // blazing door open
door->type = blazeOpen;
line->special = 0;
door->speed = VDOORSPEED*4;
break;
}
// find the top and bottom of the movement range
door->topheight = P_FindLowestCeilingSurrounding(sec);
door->topheight -= 4*FRACUNIT;
}
// //
// Spawn a door that closes after 30 seconds // Spawn a door that closes after 30 seconds
// //
void P_SpawnDoorCloseIn30 (sector_t* sec) void P_SpawnDoorCloseIn30 (sector_t* sec)
{ {
vldoor_t* door; vldoor_t *door;
door = Z_Malloc ( sizeof(*door), PU_LEVSPEC, 0); door = Z_Malloc (sizeof(*door), PU_LEVSPEC, 0);
P_AddThinker (&door->thinker); P_AddThinker (&door->thinker);
@ -511,17 +305,17 @@ void P_SpawnDoorCloseIn30 (sector_t* sec)
door->thinker.function.acp1 = (actionf_p1)T_VerticalDoor; door->thinker.function.acp1 = (actionf_p1)T_VerticalDoor;
door->sector = sec; door->sector = sec;
door->direction = 0; door->direction = 0;
door->type = normal; door->type = doorRaise;
door->speed = VDOORSPEED; door->speed = FRACUNIT*2;
door->topcountdown = 30 * TICRATE; door->topcountdown = 30 * TICRATE;
} }
// //
// Spawn a door that opens after 5 minutes // Spawn a door that opens after 5 minutes
// //
void P_SpawnDoorRaiseIn5Mins (sector_t *sec, int secnum) void P_SpawnDoorRaiseIn5Mins (sector_t *sec)
{ {
vldoor_t* door; vldoor_t *door;
door = Z_Malloc ( sizeof(*door), PU_LEVSPEC, 0); door = Z_Malloc ( sizeof(*door), PU_LEVSPEC, 0);
@ -533,221 +327,10 @@ void P_SpawnDoorRaiseIn5Mins (sector_t *sec, int secnum)
door->thinker.function.acp1 = (actionf_p1)T_VerticalDoor; door->thinker.function.acp1 = (actionf_p1)T_VerticalDoor;
door->sector = sec; door->sector = sec;
door->direction = 2; door->direction = 2;
door->type = raiseIn5Mins; door->type = doorRaiseIn5Mins;
door->speed = VDOORSPEED; door->speed = FRACUNIT * 2;
door->topheight = P_FindLowestCeilingSurrounding(sec); door->topheight = P_FindLowestCeilingSurrounding(sec);
door->topheight -= 4*FRACUNIT; door->topheight -= 4*FRACUNIT;
door->topwait = VDOORWAIT; door->topwait = (150*TICRATE)/35;
door->topcountdown = 5 * 60 * TICRATE; door->topcountdown = 5 * 60 * TICRATE;
} }
// UNUSED
// Separate into p_slidoor.c?
#if 0 // ABANDONED TO THE MISTS OF TIME!!!
//
// EV_SlidingDoor : slide a door horizontally
// (animate midtexture, then set noblocking line)
//
slideframe_t slideFrames[MAXSLIDEDOORS];
void P_InitSlidingDoorFrames (void)
{
int i;
int f1;
int f2;
int f3;
int f4;
// DOOM II ONLY...
if ( gamemode != commercial)
return;
for (i = 0;i < MAXSLIDEDOORS; i++)
{
if (!slideFrameNames[i].frontFrame1[0])
break;
f1 = R_TextureNumForName(slideFrameNames[i].frontFrame1);
f2 = R_TextureNumForName(slideFrameNames[i].frontFrame2);
f3 = R_TextureNumForName(slideFrameNames[i].frontFrame3);
f4 = R_TextureNumForName(slideFrameNames[i].frontFrame4);
slideFrames[i].frontFrames[0] = f1;
slideFrames[i].frontFrames[1] = f2;
slideFrames[i].frontFrames[2] = f3;
slideFrames[i].frontFrames[3] = f4;
f1 = R_TextureNumForName(slideFrameNames[i].backFrame1);
f2 = R_TextureNumForName(slideFrameNames[i].backFrame2);
f3 = R_TextureNumForName(slideFrameNames[i].backFrame3);
f4 = R_TextureNumForName(slideFrameNames[i].backFrame4);
slideFrames[i].backFrames[0] = f1;
slideFrames[i].backFrames[1] = f2;
slideFrames[i].backFrames[2] = f3;
slideFrames[i].backFrames[3] = f4;
}
}
//
// Return index into "slideFrames" array
// for which door type to use
//
int P_FindSlidingDoorType (line_t *line)
{
int i;
int val;
for (i = 0;i < MAXSLIDEDOORS;i++)
{
val = sides[line->sidenum[0]].midtexture;
if (val == slideFrames[i].frontFrames[0])
return i;
}
return -1;
}
void T_SlidingDoor (slidedoor_t *door)
{
switch(door->status)
{
case sd_opening:
if (!door->timer--)
{
if (++door->frame == SNUMFRAMES)
{
// IF DOOR IS DONE OPENING...
sides[door->line->sidenum[0]].midtexture = 0;
sides[door->line->sidenum[1]].midtexture = 0;
door->line->flags &= ML_BLOCKING^0xff;
if (door->type == sdt_openOnly)
{
door->frontsector->specialdata = NULL;
P_RemoveThinker (&door->thinker);
break;
}
door->timer = SDOORWAIT;
door->status = sd_waiting;
}
else
{
// IF DOOR NEEDS TO ANIMATE TO NEXT FRAME...
door->timer = SWAITTICS;
sides[door->line->sidenum[0]].midtexture =
slideFrames[door->whichDoorIndex].
frontFrames[door->frame];
sides[door->line->sidenum[1]].midtexture =
slideFrames[door->whichDoorIndex].
backFrames[door->frame];
}
}
break;
case sd_waiting:
// IF DOOR IS DONE WAITING...
if (!door->timer--)
{
// CAN DOOR CLOSE?
if (door->frontsector->thinglist != NULL ||
door->backsector->thinglist != NULL)
{
door->timer = SDOORWAIT;
break;
}
//door->frame = SNUMFRAMES-1;
door->status = sd_closing;
door->timer = SWAITTICS;
}
break;
case sd_closing:
if (!door->timer--)
{
if (--door->frame < 0)
{
// IF DOOR IS DONE CLOSING...
door->line->flags |= ML_BLOCKING;
door->frontsector->specialdata = NULL;
P_RemoveThinker (&door->thinker);
break;
}
else
{
// IF DOOR NEEDS TO ANIMATE TO NEXT FRAME...
door->timer = SWAITTICS;
sides[door->line->sidenum[0]].midtexture =
slideFrames[door->whichDoorIndex].
frontFrames[door->frame];
sides[door->line->sidenum[1]].midtexture =
slideFrames[door->whichDoorIndex].
backFrames[door->frame];
}
}
break;
}
}
void EV_SlidingDoor (line_t *line, mobj_t *thing)
{
sector_t* sec;
slidedoor_t* door;
// DOOM II ONLY...
if (gamemode != commercial)
return;
// Make sure door isn't already being animated
sec = line->frontsector;
door = NULL;
if (sec->specialdata)
{
if (!thing->player)
return;
door = sec->specialdata;
if (door->type == sdt_openAndClose)
{
if (door->status == sd_waiting)
door->status = sd_closing;
}
else
return;
}
// Init sliding door vars
if (!door)
{
door = Z_Malloc (sizeof(*door), PU_LEVSPEC, 0);
P_AddThinker (&door->thinker);
sec->specialdata = door;
door->type = sdt_openAndClose;
door->status = sd_opening;
door->whichDoorIndex = P_FindSlidingDoorType(line);
if (door->whichDoorIndex < 0)
I_Error("EV_SlidingDoor: Can't use texture for sliding door!");
door->frontsector = sec;
door->backsector = line->backsector;
door->thinker.function = T_SlidingDoor;
door->timer = SWAITTICS;
door->frame = 0;
door->line = line;
}
}
#endif

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -27,7 +27,6 @@
// Data. // Data.
#include "doomdef.h" #include "doomdef.h"
#include "dstrings.h" #include "dstrings.h"
#include "sounds.h"
#include "doomstat.h" #include "doomstat.h"
@ -43,6 +42,7 @@
#include "s_sound.h" #include "s_sound.h"
#include "p_inter.h" #include "p_inter.h"
#include "p_lnspec.h"
#define BONUSADD 6 #define BONUSADD 6
@ -177,8 +177,8 @@ BOOL P_GiveWeapon (player_t *player, weapontype_t weapon, BOOL dropped)
P_GiveAmmo (player, weaponinfo[weapon].ammo, 2); P_GiveAmmo (player, weaponinfo[weapon].ammo, 2);
player->pendingweapon = weapon; player->pendingweapon = weapon;
if (player == &players[displayplayer]) // [RH] Not consoleplayer if (player->mo == players[consoleplayer].camera) // [RH] Use camera
S_StartSound (ORIGIN_AMBIENT, sfx_wpnup); S_StartSound (ORIGIN_AMBIENT, "misc/w_pkup", 78);
return false; return false;
} }
@ -327,7 +327,7 @@ void P_TouchSpecialThing (mobj_t *special, mobj_t *toucher)
} }
sound = sfx_itemup; sound = 0;
player = toucher->player; player = toucher->player;
// Dead thing touching. // Dead thing touching.
@ -340,13 +340,13 @@ void P_TouchSpecialThing (mobj_t *special, mobj_t *toucher)
{ {
// armor // armor
case SPR_ARM1: case SPR_ARM1:
if (!P_GiveArmor (player, deh_GreenAC)) if (!P_GiveArmor (player, deh.GreenAC))
return; return;
player->message = GOTARMOR; player->message = GOTARMOR;
break; break;
case SPR_ARM2: case SPR_ARM2:
if (!P_GiveArmor (player, deh_BlueAC)) if (!P_GiveArmor (player, deh.BlueAC))
return; return;
player->message = GOTMEGA; player->message = GOTMEGA;
break; break;
@ -354,38 +354,38 @@ void P_TouchSpecialThing (mobj_t *special, mobj_t *toucher)
// bonus items // bonus items
case SPR_BON1: case SPR_BON1:
player->health++; // can go over 100% player->health++; // can go over 100%
if (player->health > deh_MaxSoulsphere) if (player->health > deh.MaxSoulsphere)
player->health = deh_MaxSoulsphere; player->health = deh.MaxSoulsphere;
player->mo->health = player->health; player->mo->health = player->health;
player->message = GOTHTHBONUS; player->message = GOTHTHBONUS;
break; break;
case SPR_BON2: case SPR_BON2:
player->armorpoints++; // can go over 100% player->armorpoints++; // can go over 100%
if (player->armorpoints > deh_MaxArmor) if (player->armorpoints > deh.MaxArmor)
player->armorpoints = deh_MaxArmor; player->armorpoints = deh.MaxArmor;
if (!player->armortype) if (!player->armortype)
player->armortype = deh_GreenAC; player->armortype = deh.GreenAC;
player->message = GOTARMBONUS; player->message = GOTARMBONUS;
break; break;
case SPR_SOUL: case SPR_SOUL:
player->health += deh_SoulsphereHealth; player->health += deh.SoulsphereHealth;
if (player->health > deh_MaxSoulsphere) if (player->health > deh.MaxSoulsphere)
player->health = deh_MaxSoulsphere; player->health = deh.MaxSoulsphere;
player->mo->health = player->health; player->mo->health = player->health;
player->message = GOTSUPER; player->message = GOTSUPER;
sound = sfx_getpow; sound = 1;
break; break;
case SPR_MEGA: case SPR_MEGA:
if (gamemode != commercial) if (gamemode != commercial)
return; return;
player->health = deh_MegasphereHealth; player->health = deh.MegasphereHealth;
player->mo->health = player->health; player->mo->health = player->health;
P_GiveArmor (player,deh_BlueAC); P_GiveArmor (player,deh.BlueAC);
player->message = GOTMSPHERE; player->message = GOTMSPHERE;
sound = sfx_getpow; sound = 1;
break; break;
// cards // cards
@ -394,6 +394,7 @@ void P_TouchSpecialThing (mobj_t *special, mobj_t *toucher)
if (!player->cards[it_bluecard]) if (!player->cards[it_bluecard])
player->message = GOTBLUECARD; player->message = GOTBLUECARD;
P_GiveCard (player, it_bluecard); P_GiveCard (player, it_bluecard);
sound = 3;
if (!netgame) if (!netgame)
break; break;
return; return;
@ -402,6 +403,7 @@ void P_TouchSpecialThing (mobj_t *special, mobj_t *toucher)
if (!player->cards[it_yellowcard]) if (!player->cards[it_yellowcard])
player->message = GOTYELWCARD; player->message = GOTYELWCARD;
P_GiveCard (player, it_yellowcard); P_GiveCard (player, it_yellowcard);
sound = 3;
if (!netgame) if (!netgame)
break; break;
return; return;
@ -410,6 +412,7 @@ void P_TouchSpecialThing (mobj_t *special, mobj_t *toucher)
if (!player->cards[it_redcard]) if (!player->cards[it_redcard])
player->message = GOTREDCARD; player->message = GOTREDCARD;
P_GiveCard (player, it_redcard); P_GiveCard (player, it_redcard);
sound = 3;
if (!netgame) if (!netgame)
break; break;
return; return;
@ -418,6 +421,7 @@ void P_TouchSpecialThing (mobj_t *special, mobj_t *toucher)
if (!player->cards[it_blueskull]) if (!player->cards[it_blueskull])
player->message = GOTBLUESKUL; player->message = GOTBLUESKUL;
P_GiveCard (player, it_blueskull); P_GiveCard (player, it_blueskull);
sound = 3;
if (!netgame) if (!netgame)
break; break;
return; return;
@ -426,6 +430,7 @@ void P_TouchSpecialThing (mobj_t *special, mobj_t *toucher)
if (!player->cards[it_yellowskull]) if (!player->cards[it_yellowskull])
player->message = GOTYELWSKUL; player->message = GOTYELWSKUL;
P_GiveCard (player, it_yellowskull); P_GiveCard (player, it_yellowskull);
sound = 3;
if (!netgame) if (!netgame)
break; break;
return; return;
@ -434,6 +439,7 @@ void P_TouchSpecialThing (mobj_t *special, mobj_t *toucher)
if (!player->cards[it_redskull]) if (!player->cards[it_redskull])
player->message = GOTREDSKULL; player->message = GOTREDSKULL;
P_GiveCard (player, it_redskull); P_GiveCard (player, it_redskull);
sound = 3;
if (!netgame) if (!netgame)
break; break;
return; return;
@ -461,7 +467,7 @@ void P_TouchSpecialThing (mobj_t *special, mobj_t *toucher)
if (!P_GivePower (player, pw_invulnerability)) if (!P_GivePower (player, pw_invulnerability))
return; return;
player->message = GOTINVUL; player->message = GOTINVUL;
sound = sfx_getpow; sound = 1;
break; break;
case SPR_PSTR: case SPR_PSTR:
@ -470,35 +476,35 @@ void P_TouchSpecialThing (mobj_t *special, mobj_t *toucher)
player->message = GOTBERSERK; player->message = GOTBERSERK;
if (player->readyweapon != wp_fist) if (player->readyweapon != wp_fist)
player->pendingweapon = wp_fist; player->pendingweapon = wp_fist;
sound = sfx_getpow; sound = 1;
break; break;
case SPR_PINS: case SPR_PINS:
if (!P_GivePower (player, pw_invisibility)) if (!P_GivePower (player, pw_invisibility))
return; return;
player->message = GOTINVIS; player->message = GOTINVIS;
sound = sfx_getpow; sound = 1;
break; break;
case SPR_SUIT: case SPR_SUIT:
if (!P_GivePower (player, pw_ironfeet)) if (!P_GivePower (player, pw_ironfeet))
return; return;
player->message = GOTSUIT; player->message = GOTSUIT;
sound = sfx_getpow; sound = 1;
break; break;
case SPR_PMAP: case SPR_PMAP:
if (!P_GivePower (player, pw_allmap)) if (!P_GivePower (player, pw_allmap))
return; return;
player->message = GOTMAP; player->message = GOTMAP;
sound = sfx_getpow; sound = 1;
break; break;
case SPR_PVIS: case SPR_PVIS:
if (!P_GivePower (player, pw_infrared)) if (!P_GivePower (player, pw_infrared))
return; return;
player->message = GOTVISOR; player->message = GOTVISOR;
sound = sfx_getpow; sound = 1;
break; break;
// ammo // ammo
@ -575,49 +581,49 @@ void P_TouchSpecialThing (mobj_t *special, mobj_t *toucher)
if (!P_GiveWeapon (player, wp_bfg, false) ) if (!P_GiveWeapon (player, wp_bfg, false) )
return; return;
player->message = GOTBFG9000; player->message = GOTBFG9000;
sound = sfx_wpnup; sound = 2;
break; break;
case SPR_MGUN: case SPR_MGUN:
if (!P_GiveWeapon (player, wp_chaingun, special->flags&MF_DROPPED) ) if (!P_GiveWeapon (player, wp_chaingun, special->flags&MF_DROPPED) )
return; return;
player->message = GOTCHAINGUN; player->message = GOTCHAINGUN;
sound = sfx_wpnup; sound = 2;
break; break;
case SPR_CSAW: case SPR_CSAW:
if (!P_GiveWeapon (player, wp_chainsaw, false) ) if (!P_GiveWeapon (player, wp_chainsaw, false) )
return; return;
player->message = GOTCHAINSAW; player->message = GOTCHAINSAW;
sound = sfx_wpnup; sound = 2;
break; break;
case SPR_LAUN: case SPR_LAUN:
if (!P_GiveWeapon (player, wp_missile, false) ) if (!P_GiveWeapon (player, wp_missile, false) )
return; return;
player->message = GOTLAUNCHER; player->message = GOTLAUNCHER;
sound = sfx_wpnup; sound = 2;
break; break;
case SPR_PLAS: case SPR_PLAS:
if (!P_GiveWeapon (player, wp_plasma, false) ) if (!P_GiveWeapon (player, wp_plasma, false) )
return; return;
player->message = GOTPLASMA; player->message = GOTPLASMA;
sound = sfx_wpnup; sound = 2;
break; break;
case SPR_SHOT: case SPR_SHOT:
if (!P_GiveWeapon (player, wp_shotgun, special->flags&MF_DROPPED ) ) if (!P_GiveWeapon (player, wp_shotgun, special->flags&MF_DROPPED ) )
return; return;
player->message = GOTSHOTGUN; player->message = GOTSHOTGUN;
sound = sfx_wpnup; sound = 2;
break; break;
case SPR_SGN2: case SPR_SGN2:
if (!P_GiveWeapon (player, wp_supershotgun, special->flags&MF_DROPPED ) ) if (!P_GiveWeapon (player, wp_supershotgun, special->flags&MF_DROPPED ) )
return; return;
player->message = GOTSHOTGUN2; player->message = GOTSHOTGUN2;
sound = sfx_wpnup; sound = 2;
break; break;
default: default:
@ -630,259 +636,329 @@ void P_TouchSpecialThing (mobj_t *special, mobj_t *toucher)
} }
P_RemoveMobj (special); P_RemoveMobj (special);
player->bonuscount += BONUSADD; player->bonuscount += BONUSADD;
if (player == &players[displayplayer]) { // [RH] Not consoleplayer if (player->mo == players[consoleplayer].camera) { // [RH] Use camera
if (sound == sfx_getpow) switch (sound) {
S_StartSound (ORIGIN_SURROUND3, sound); case 0:
else case 3:
S_StartSound (ORIGIN_AMBIENT, sound); S_StartSound (ORIGIN_AMBIENT, "misc/i_pkup", 78);
break;
case 1:
S_StartSound (ORIGIN_SURROUND3, "misc/p_pkup", 78);
break;
case 2:
S_StartSound (ORIGIN_AMBIENT, "misc/w_pkup", 78);
break;
}
} }
} }
// [RH]
// SexMessage: Replace parts of strings with gender-specific phrases
//
// The following expansions are performed:
// %g -> he/she/it
// %h -> him/her/it
// %p -> his/her/its
//
void SexMessage (const char *from, char *to, int gender)
{
static const char *genderstuff[3][3] = {
{ "he", "him", "his" },
{ "she", "her", "her" },
{ "it", "it", "its" }
};
static const int gendershift[3][3] = {
{ 2, 3, 3 },
{ 3, 3, 3 },
{ 2, 2, 3 }
};
int gendermsg;
do {
if (*from != '%') {
*to++ = *from;
} else {
switch (from[1]) {
case 'g': gendermsg = 0; break;
case 'h': gendermsg = 1; break;
case 'p': gendermsg = 2; break;
default: gendermsg = -1; break;
}
if (gendermsg < 0) {
*to++ = '%';
} else {
strcpy (to, genderstuff[gender][gendermsg]);
to += gendershift[gender][gendermsg];
from++;
}
}
} while (*from++);
}
// [RH] // [RH]
// ClientObituary: Show a message when a player dies // ClientObituary: Show a message when a player dies
// //
void ClientObituary (mobj_t *self, mobj_t *inflictor, mobj_t *attacker) void ClientObituary (mobj_t *self, mobj_t *inflictor, mobj_t *attacker)
{ {
int mod; int mod;
char *message; char *message;
char *message2; char gendermessage[1024];
BOOL friendly; BOOL friendly;
int gender;
if (1) { if (!self->player)
friendly = MeansOfDeath & MOD_FRIENDLY_FIRE; return;
mod = MeansOfDeath & ~MOD_FRIENDLY_FIRE;
message = NULL;
message2 = "";
switch (mod) { gender = self->player->userinfo.gender;
case MOD_SUICIDE:
message = "suicides";
break;
case MOD_FALLING:
message = "fell too far";
break;
case MOD_CRUSH:
message = "was squished";
break;
case MOD_EXIT:
message = "tried to leave";
break;
case MOD_WATER:
message = "has no gills";
break;
case MOD_SLIME:
message = "mutated";
break;
case MOD_LAVA:
message = "melted";
break;
case MOD_BARREL:
message = "went boom";
break;
case MOD_SPLASH:
message = "stood in the wrong spot";
break;
}
if (attacker && !message) { if (netgame && !deathmatch->value)
if (attacker == self) { MeansOfDeath |= MOD_FRIENDLY_FIRE;
switch (mod) {
case MOD_R_SPLASH:
case MOD_ROCKET:
message = "should have stood back";
break;
default:
message = "killed himself";
break;
}
} else if (!attacker->player) {
switch (attacker->type) {
case MT_STEALTHBABY:
message = "thought he saw an arachnotron";
break;
case MT_STEALTHVILE:
message = "thought he saw an archvile";
break;
case MT_STEALTHBRUISER:
message = "thought he saw a Baron of Hell";
break;
case MT_STEALTHHEAD:
message = "thought he saw a mancubus";
break;
case MT_STEALTHCHAINGUY:
message = "thought he saw a chaingunner";
break;
case MT_STEALTHSERGEANT:
message = "thought he saw a demon";
break;
case MT_STEALTHKNIGHT:
message = "thought he saw a Hell Knight";
break;
case MT_STEALTHIMP:
message = "thought he saw an imp";
break;
case MT_STEALTHFATSO:
message = "thought he saw a mancubus";
break;
case MT_STEALTHUNDEAD:
message = "thought he saw a revenant";
break;
case MT_STEALTHSHOTGUY:
message = "thought he saw a sargeant";
break;
case MT_STEALTHZOMBIE:
message = "thought he saw a zombieman";
break;
default:
if (mod == MOD_HIT) {
switch (attacker->type) {
case MT_UNDEAD:
message = "was punched by a revenant";
break;
case MT_TROOP:
message = "was slashed by an imp";
break;
case MT_HEAD:
message = "got too close to a mancubus";
break;
case MT_SERGEANT:
message = "was bit by a demon";
break;
case MT_SHADOWS:
message = "was eaten by a spectre";
break;
case MT_BRUISER:
message = "was ripped open by a Baron of Hell";
break;
case MT_KNIGHT:
message = "was gutted by a Hell Knight";
break;
default:
break;
}
} else {
switch (attacker->type) {
case MT_POSSESSED:
message = "was killed by a zombieman";
break;
case MT_SHOTGUY:
message = "was shot by a sargeant";
break;
case MT_VILE:
message = "was incinerated by an archvile";
break;
case MT_UNDEAD:
message = "couldn't evade a revenant's fireball";
break;
case MT_FATSO:
message = "was squashed by a mancubus";
break;
case MT_CHAINGUY:
message = "was perforated by a chaingunner";
break;
case MT_SKULL:
message = "was spooked by a lost soul";
break;
case MT_TROOP:
message = "was burned by an imp";
break;
case MT_HEAD:
message = "was mesmerized by a cacodemon";
break;
case MT_BRUISER:
message = "was bruised by a Baron of Hell";
break;
case MT_KNIGHT:
message = "was splayed by a Hell Knight";
break;
case MT_SPIDER:
message = "stood in awe of the spider mastermind";
break;
case MT_BABY:
message = "let an arachnotron get him";
break;
case MT_CYBORG:
message = "was splattered by a cyberdemon";
break;
case MT_WOLFSS:
message = "becomes Hitler's personal slave";
break;
default:
break;
}
}
break;
}
}
}
if (message) { friendly = MeansOfDeath & MOD_FRIENDLY_FIRE;
Printf ("%s %s.\n", self->player->userinfo->netname, message); mod = MeansOfDeath & ~MOD_FRIENDLY_FIRE;
return; message = NULL;
}
if (attacker && attacker->player) { switch (mod) {
case MOD_SUICIDE:
message = OB_SUICIDE;
break;
case MOD_FALLING:
message = OB_FALLING;
break;
case MOD_CRUSH:
message = OB_CRUSH;
break;
case MOD_EXIT:
message = OB_EXIT;
break;
case MOD_WATER:
message = OB_WATER;
break;
case MOD_SLIME:
message = OB_SLIME;
break;
case MOD_LAVA:
message = OB_LAVA;
break;
case MOD_BARREL:
message = OB_BARREL;
break;
case MOD_SPLASH:
message = OB_SPLASH;
break;
}
if (attacker && !message) {
if (attacker == self) {
switch (mod) { switch (mod) {
case MOD_FIST: case MOD_R_SPLASH:
message = "chewed on"; message = OB_R_SPLASH;
message2 = "'s fist";
break;
case MOD_CHAINSAW:
message = "was mowed over by";
message2 = "'s chainsaw";
break;
case MOD_PISTOL:
message = "was tickled by";
break;
case MOD_SHOTGUN:
message = "chewed on";
message2 = "'s boomstick";
break;
case MOD_SSHOTGUN:
message = "was splattered by";
message2 = "'s super shotgun";
break;
case MOD_CHAINGUN:
message = "was mowed down by";
break; break;
case MOD_ROCKET: case MOD_ROCKET:
message = "rode"; message = OB_ROCKET;
message2 = "'s rocket";
break; break;
case MOD_R_SPLASH: default:
message = "almost dodged"; message = OB_KILLEDSELF;
message2 = "'s rocket"; break;
break; }
case MOD_PLASMARIFLE: } else if (!attacker->player) {
message = "was melted by"; switch (attacker->type) {
break; case MT_STEALTHBABY:
case MOD_BFG_BOOM: message = OB_STEALTHBABY;
message = "was splintered by"; break;
message2 = "'s BFG"; case MT_STEALTHVILE:
break; message = OB_STEALTHVILE;
case MOD_BFG_SPLASH: break;
message = "couldn't hide from"; case MT_STEALTHBRUISER:
message2 = "'s BFG"; message = OB_STEALTHBARON;
break; break;
case MOD_TELEFRAG: case MT_STEALTHHEAD:
message = "was stepped on by"; message = OB_STEALTHCACO;
break; break;
case MOD_FALLXFER: case MT_STEALTHCHAINGUY:
message = "was"; message = OB_STEALTHCHAINGUY;
message2 = "'s cushion"; break;
case MT_STEALTHSERGEANT:
message = OB_STEALTHDEMON;
break;
case MT_STEALTHKNIGHT:
message = OB_STEALTHKNIGHT;
break;
case MT_STEALTHIMP:
message = OB_STEALTHIMP;
break;
case MT_STEALTHFATSO:
message = OB_STEALTHFATSO;
break;
case MT_STEALTHUNDEAD:
message = OB_STEALTHUNDEAD;
break;
case MT_STEALTHSHOTGUY:
message = OB_STEALTHSHOTGUY;
break;
case MT_STEALTHZOMBIE:
message = OB_STEALTHZOMBIE;
break;
default:
if (mod == MOD_HIT) {
switch (attacker->type) {
case MT_UNDEAD:
message = OB_UNDEADHIT;
break;
case MT_TROOP:
message = OB_IMPHIT;
break;
case MT_HEAD:
message = OB_CACOHIT;
break;
case MT_SERGEANT:
message = OB_DEMONHIT;
break;
case MT_SHADOWS:
message = OB_SPECTREHIT;
break;
case MT_BRUISER:
message = OB_BARONHIT;
break;
case MT_KNIGHT:
message = OB_KNIGHTHIT;
break;
default:
break;
}
} else {
switch (attacker->type) {
case MT_POSSESSED:
message = OB_ZOMBIE;
break;
case MT_SHOTGUY:
message = OB_SHOTGUY;
break;
case MT_VILE:
message = OB_VILE;
break;
case MT_UNDEAD:
message = OB_UNDEAD;
break;
case MT_FATSO:
message = OB_FATSO;
break;
case MT_CHAINGUY:
message = OB_CHAINGUY;
break;
case MT_SKULL:
message = OB_SKULL;
break;
case MT_TROOP:
message = OB_IMP;
break;
case MT_HEAD:
message = OB_CACO;
break;
case MT_BRUISER:
message = OB_BARON;
break;
case MT_KNIGHT:
message = OB_KNIGHT;
break;
case MT_SPIDER:
message = OB_SPIDER;
break;
case MT_BABY:
message = OB_BABY;
break;
case MT_CYBORG:
message = OB_CYBORG;
break;
case MT_WOLFSS:
message = OB_WOLFSS;
break;
default:
break;
}
}
break; break;
} }
}
if (message) {
Printf ("%s %s %s%s\n", self->player->userinfo->netname, message,
attacker->player->userinfo->netname, message2);
return;
} }
} }
Printf ("%s died.\n", self->player->userinfo->netname); if (message) {
SexMessage (message, gendermessage, gender);
Printf ("%s %s.\n", self->player->userinfo.netname, gendermessage);
return;
}
if (attacker && attacker->player) {
if (friendly) {
int rnum = P_Random (pr_obituary);
attacker->player->fragcount -= 2;
attacker->player->frags[attacker->player-players]++;
self = attacker;
if (rnum < 64)
message = OB_FRIENDLY1;
else if (rnum < 128)
message = OB_FRIENDLY2;
else if (rnum < 192)
message = OB_FRIENDLY3;
else
message = OB_FRIENDLY4;
} else {
switch (mod) {
case MOD_FIST:
message = OB_MPFIST;
break;
case MOD_CHAINSAW:
message = OB_MPCHAINSAW;
break;
case MOD_PISTOL:
message = OB_MPPISTOL;
break;
case MOD_SHOTGUN:
message = OB_MPSHOTGUN;
break;
case MOD_SSHOTGUN:
message = OB_MPSSHOTGUN;
break;
case MOD_CHAINGUN:
message = OB_MPCHAINGUN;
break;
case MOD_ROCKET:
message = OB_MPROCKET;
break;
case MOD_R_SPLASH:
message = OB_MPR_SPLASH;
break;
case MOD_PLASMARIFLE:
message = OB_MPPLASMARIFLE;
break;
case MOD_BFG_BOOM:
message = OB_MPBFG_BOOM;
break;
case MOD_BFG_SPLASH:
message = OB_MPBFG_SPLASH;
break;
case MOD_TELEFRAG:
message = OB_MPTELEFRAG;
break;
}
}
}
if (message) {
char work[256];
SexMessage (message, gendermessage, gender);
sprintf (work, "%%s %s\n", gendermessage);
Printf (work, self->player->userinfo.netname,
attacker->player->userinfo.netname);
return;
}
SexMessage (OB_DEFAULT, gendermessage, gender);
Printf ("%s %s.\n", self->player->userinfo.netname, gendermessage);
} }
@ -904,6 +980,18 @@ void P_KillMobj (mobj_t *source, mobj_t *target, mobj_t *inflictor)
target->flags |= MF_CORPSE|MF_DROPOFF; target->flags |= MF_CORPSE|MF_DROPOFF;
target->height >>= 2; target->height >>= 2;
// [RH] If the thing has a special, execute and remove it
// Note that the thing that killed it is considered
// the activator of the script.
if (target->special) {
LineSpecials[target->special] (NULL, source, target->args[0],
target->args[1], target->args[2],
target->args[3], target->args[4]);
target->special = 0;
}
// [RH] Also set the thing's tid to 0.
target->tid = 0;
if (source && source->player) if (source && source->player)
{ {
// count for intermission // count for intermission
@ -912,7 +1000,10 @@ void P_KillMobj (mobj_t *source, mobj_t *target, mobj_t *inflictor)
level.killed_monsters++; level.killed_monsters++;
} }
if (target->player) { // Don't count any frags at level start, because they're just telefrags
// resulting from insufficient deathmatch starts, and it wouldn't be
// fair to count them toward a player's score.
if (target->player && level.time) {
source->player->frags[target->player-players]++; source->player->frags[target->player-players]++;
if (target->player == source->player) // [RH] Cumulative frag count if (target->player == source->player) // [RH] Cumulative frag count
source->player->fragcount--; source->player->fragcount--;
@ -922,8 +1013,8 @@ void P_KillMobj (mobj_t *source, mobj_t *target, mobj_t *inflictor)
// [RH] Implement fraglimit // [RH] Implement fraglimit
if (deathmatch->value && fraglimit->value && if (deathmatch->value && fraglimit->value &&
(int)fraglimit->value == source->player->fragcount) { (int)fraglimit->value == source->player->fragcount) {
Printf ("%s got %d frags.\n", source->player->userinfo->netname, source->player->fragcount); Printf ("Fraglimit hit.\n");
G_ExitLevel (); G_ExitLevel (0);
} }
} }
} }
@ -973,10 +1064,8 @@ void P_KillMobj (mobj_t *source, mobj_t *target, mobj_t *inflictor)
if (target->tics < 1) if (target->tics < 1)
target->tics = 1; target->tics = 1;
// I_StartSound (&actor->r, actor->info->deathsound);
// [RH] Death messages // [RH] Death messages
if (target->player) if (target->player && level.time && !olddemo)
ClientObituary (target, inflictor, source); ClientObituary (target, inflictor, source);
// Drop stuff. // Drop stuff.
@ -1003,7 +1092,6 @@ void P_KillMobj (mobj_t *source, mobj_t *target, mobj_t *inflictor)
mo = P_SpawnMobj (target->x,target->y,0, item, ONFLOORZ); mo = P_SpawnMobj (target->x,target->y,0, item, ONFLOORZ);
mo->flags |= MF_DROPPED; // special versions of items mo->flags |= MF_DROPPED; // special versions of items
} }
@ -1052,7 +1140,6 @@ void P_DamageMobj (mobj_t *target, mobj_t *inflictor, mobj_t *source, int damage
player = target->player; player = target->player;
if (player && gameskill->value == sk_baby) if (player && gameskill->value == sk_baby)
damage >>= 1; // take half damage in trainer mode damage >>= 1; // take half damage in trainer mode
// Some close combat weapons should not // Some close combat weapons should not
// inflict thrust and push the victim out of reach, // inflict thrust and push the victim out of reach,
@ -1079,22 +1166,21 @@ void P_DamageMobj (mobj_t *target, mobj_t *inflictor, mobj_t *source, int damage
ang += ANG180; ang += ANG180;
thrust *= 4; thrust *= 4;
} }
ang >>= ANGLETOFINESHIFT; ang >>= ANGLETOFINESHIFT;
target->momx += FixedMul (thrust, finecosine[ang]); target->momx += FixedMul (thrust, finecosine[ang]);
target->momy += FixedMul (thrust, finesine[ang]); target->momy += FixedMul (thrust, finesine[ang]);
} }
// player specific // player specific
if (player) if (player)
{ {
// end of game hell hack // end of game hell hack
if (target->subsector->sector->special == 11 if (target->subsector->sector->special & 255 == dDamage_End
&& damage >= target->health) && damage >= target->health)
{ {
damage = target->health - 1; damage = target->health - 1;
} }
// Below certain threshold, // Below certain threshold,
// ignore damage in GOD mode, or with INVUL power. // ignore damage in GOD mode, or with INVUL power.
@ -1104,10 +1190,20 @@ void P_DamageMobj (mobj_t *target, mobj_t *inflictor, mobj_t *source, int damage
{ {
return; return;
} }
// [RH] Avoid friendly fire if enabled
if (teamplay->value && source && source->player &&
source->player->userinfo.team[0] &&
!stricmp (player->userinfo.team, source->player->userinfo.team)) {
if (dmflags & DF_NO_FRIENDLY_FIRE)
return;
else
MeansOfDeath |= MOD_FRIENDLY_FIRE;
}
if (player->armortype) if (player->armortype)
{ {
if (player->armortype == deh_GreenAC) if (player->armortype == deh.GreenAC)
saved = damage/3; saved = damage/3;
else else
saved = damage/2; saved = damage/2;
@ -1137,37 +1233,49 @@ void P_DamageMobj (mobj_t *target, mobj_t *inflictor, mobj_t *source, int damage
I_Tactile (40,10,40+temp*2); I_Tactile (40,10,40+temp*2);
} }
// do the damage // do the damage
target->health -= damage; // [RH] Only if not immune
if (target->health <= 0) if (!(target->flags2 & (MF2_INVULNERABLE | MF2_INDESTRUCTABLE))) {
{ target->health -= damage;
P_KillMobj (source, target, inflictor); if (target->health <= 0)
return; {
P_KillMobj (source, target, inflictor);
return;
}
} }
if ( (P_Random (pr_damagemobj) < target->info->painchance) if (!(target->flags2 & MF2_DORMANT)) {
&& !(target->flags&MF_SKULLFLY) ) // [RH] Only react if not dormant
{ if ( (P_Random (pr_damagemobj) < target->info->painchance)
target->flags |= MF_JUSTHIT; // fight back! && !(target->flags&MF_SKULLFLY) )
{
P_SetMobjState (target, target->info->painstate); target->flags |= MF_JUSTHIT; // fight back!
}
P_SetMobjState (target, target->info->painstate);
target->reactiontime = 0; // we're awake now... }
target->reactiontime = 0; // we're awake now...
if ( (!target->threshold || target->type == MT_VILE) if ( (!target->threshold || target->type == MT_VILE)
&& source && source != target && source && source != target
&& source->type != MT_VILE) && source->type != MT_VILE)
{ {
// if not intent on another player, // if not intent on another player, chase after this one
// chase after this one
target->target = source; // killough 2/15/98: remember last enemy, to prevent
target->threshold = BASETHRESHOLD; // sleeping early; 2/21/98: Place priority on players
if (target->state == &states[target->info->spawnstate]
&& target->info->seestate != S_NULL) if (!target->lastenemy || !target->lastenemy->player ||
P_SetMobjState (target, target->info->seestate); target->lastenemy->health <= 0)
target->lastenemy = target->target; // remember last enemy - killough
target->target = source;
target->threshold = BASETHRESHOLD;
if (target->state == &states[target->info->spawnstate]
&& target->info->seestate != S_NULL)
P_SetMobjState (target, target->info->seestate);
}
} }
} }
BOOL CheckCheatmode (void); BOOL CheckCheatmode (void);

530
code/P_lights.c Normal file
View file

@ -0,0 +1,530 @@
// Emacs style mode select -*- C++ -*-
//-----------------------------------------------------------------------------
//
// $Id:$
//
// Copyright (C) 1993-1996 by id Software, Inc.
//
// This source is available for distribution and/or modification
// only under the terms of the DOOM Source Code License as
// published by id Software. All rights reserved.
//
// The source is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
// for more details.
//
// $Log:$
//
// DESCRIPTION:
// Handle Sector base lighting effects.
//
//-----------------------------------------------------------------------------
#include "z_zone.h"
#include "m_random.h"
#include "doomdef.h"
#include "p_local.h"
#include "p_lnspec.h"
// State.
#include "r_state.h"
// [RH] These functions only change the sector special in
// demo compatibility mode.
extern BOOL olddemo;
// [RH] Make sure the light level is in bounds.
#define CLIPLIGHT(l) (((l) < 0) ? 0 : (((l) > 255) ? 255 : (l)))
//
// FIRELIGHT FLICKER
//
//
// T_FireFlicker
//
void T_FireFlicker (fireflicker_t *flick)
{
int amount;
if (--flick->count)
return;
amount = (P_Random (pr_fireflicker) & 3) << 4;
if (flick->sector->lightlevel - amount < flick->minlight)
flick->sector->lightlevel = (short)flick->minlight;
else
flick->sector->lightlevel = (short)(flick->maxlight - amount);
flick->count = 4;
}
//
// P_SpawnFireFlicker
//
void P_SpawnFireFlicker (sector_t *sector)
{
fireflicker_t *flick;
if (olddemo)
sector->special &= 0xff00;
flick = Z_Malloc ( sizeof(*flick), PU_LEVSPEC, 0);
P_AddThinker (&flick->thinker);
flick->thinker.function.acp1 = (actionf_p1) T_FireFlicker;
flick->sector = sector;
flick->maxlight = sector->lightlevel;
flick->minlight = P_FindMinSurroundingLight(sector,sector->lightlevel)+16;
flick->count = 4;
}
//
// BROKEN LIGHT FLASHING
//
//
// T_LightFlash
// Do flashing lights.
//
void T_LightFlash (lightflash_t* flash)
{
if (--flash->count)
return;
if (flash->sector->lightlevel == flash->maxlight)
{
flash-> sector->lightlevel = flash->minlight;
flash->count = (P_Random (pr_lightflash) & flash->mintime) + 1;
}
else
{
flash-> sector->lightlevel = flash->maxlight;
flash->count = (P_Random (pr_lightflash) & flash->maxtime) + 1;
}
}
//
// P_SpawnLightFlash
// [RH] Added min and max parameters
//
void P_SpawnLightFlash (sector_t *sector, int min, int max)
{
lightflash_t *flash;
if (olddemo)
sector->special &= 0xff00;
flash = Z_Malloc ( sizeof(*flash), PU_LEVSPEC, 0);
P_AddThinker (&flash->thinker);
flash->thinker.function.acp1 = (actionf_p1) T_LightFlash;
flash->sector = sector;
if (min < 0) {
// If min is negative, find light levels like Doom.
flash->maxlight = sector->lightlevel;
flash->minlight = P_FindMinSurroundingLight(sector,sector->lightlevel);
} else {
// Otherwise, use the ones provided.
flash->maxlight = CLIPLIGHT(max);
flash->minlight = CLIPLIGHT(min);
}
flash->maxtime = 64;
flash->mintime = 7;
flash->count = (P_Random (pr_spawnlightflash) & flash->maxtime) + 1;
}
// [RH] New function to start light flashing on-demand.
void EV_StartLightFlashing (int tag, int upper, int lower)
{
int secnum;
secnum = -1;
while ((secnum = P_FindSectorFromTag (tag,secnum)) >= 0)
{
sector_t *sec = &sectors[secnum];
if (P_SectorActive (lighting_special, sec))
continue;
P_SpawnLightFlash (sec, lower, upper);
}
}
//
// STROBE LIGHT FLASHING
//
//
// T_StrobeFlash
//
void T_StrobeFlash (strobe_t *flash)
{
if (--flash->count)
return;
if (flash->sector->lightlevel == flash->minlight)
{
flash-> sector->lightlevel = (short)flash->maxlight;
flash->count = flash->brighttime;
}
else
{
flash-> sector->lightlevel = (short)flash->minlight;
flash->count = flash->darktime;
}
}
//
// P_SpawnStrobeFlash
// After the map has been loaded, scan each sector
// for specials that spawn thinkers
// [RH] brighttime is also adjustable
//
void P_SpawnStrobeFlash (sector_t *sector, int upper, int lower,
int utics, int ltics, int inSync)
{
strobe_t *flash;
flash = Z_Malloc ( sizeof(*flash), PU_LEVSPEC, 0);
P_AddThinker (&flash->thinker);
flash->sector = sector;
flash->darktime = ltics;
flash->brighttime = utics;
flash->thinker.function.acp1 = (actionf_p1) T_StrobeFlash;
// [RH] If the upper light level is -1, we use Doom's mechanism
// for setting this up. Otherwise, we use Hexen's.
if (upper < 0) {
flash->maxlight = sector->lightlevel;
flash->minlight = P_FindMinSurroundingLight(sector, sector->lightlevel);
if (flash->minlight == flash->maxlight)
flash->minlight = 0;
flash->count = inSync ? 1 : (P_Random (pr_spawnstrobeflash) & 7) + 1;
} else {
flash->maxlight = CLIPLIGHT(upper);
flash->minlight = CLIPLIGHT(lower);
flash->count = 1; // Hexen-style is always in sync.
}
if (olddemo)
sector->special &= 0xff00;
}
//
// Start strobing lights (usually from a trigger)
// [RH] Made it more configurable.
//
void EV_StartLightStrobing (int tag, int upper, int lower, int utics, int ltics)
{
int secnum;
secnum = -1;
while ((secnum = P_FindSectorFromTag (tag,secnum)) >= 0)
{
sector_t *sec = &sectors[secnum];
if (P_SectorActive (lighting_special, sec)) //jff 2/22/98
continue;
P_SpawnStrobeFlash (sec, upper, lower, utics, ltics, 0);
}
}
//
// TURN LINE'S TAG LIGHTS OFF
// [RH] Takes a tag instead of a line
//
void EV_TurnTagLightsOff (int tag)
{
int i;
int secnum;
// [RH] Don't do a linear search
for (secnum = -1; (secnum = P_FindSectorFromTag (tag, secnum)) >= 0; )
{
sector_t *sector = sectors + secnum;
int min = sector->lightlevel;
for (i = 0; i < sector->linecount; i++)
{
sector_t *tsec = getNextSector (sector->lines[i],sector);
if (!tsec)
continue;
if (tsec->lightlevel < min)
min = tsec->lightlevel;
}
sector->lightlevel = min;
}
}
//
// TURN LINE'S TAG LIGHTS ON
// [RH] Takes a tag instead of a line
//
void EV_LightTurnOn (int tag, int bright)
{
int secnum = -1;
// [RH] Don't do a linear search
while ((secnum = P_FindSectorFromTag (tag, secnum)) >= 0)
{
sector_t *sector = sectors + secnum;
// bright = -1 means to search ([RH] Not 0)
// for highest light level
// surrounding sector
if (bright < 0)
{
int j;
bright = 0;
for (j = 0; j < sector->linecount; j++)
{
sector_t *temp = getNextSector (sector->lines[j], sector);
if (!temp)
continue;
if (temp->lightlevel > bright)
bright = temp->lightlevel;
}
}
sector->lightlevel = CLIPLIGHT(bright);
}
}
//
// [RH] New function to adjust tagged sectors' light levels
// by a relative amount. Light levels are clipped to
// within the range 0-255 inclusive.
//
void EV_LightChange (int tag, int value)
{
int secnum = -1;
while ((secnum = P_FindSectorFromTag (tag, secnum)) >= 0) {
int newlight = sectors[secnum].lightlevel + value;
sectors[secnum].lightlevel = CLIPLIGHT(newlight);
}
}
//
// Spawn glowing light
//
void T_Glow (glow_t *g)
{
switch(g->direction)
{
case -1:
// DOWN
g->sector->lightlevel -= GLOWSPEED;
if (g->sector->lightlevel <= g->minlight)
{
g->sector->lightlevel += GLOWSPEED;
g->direction = 1;
}
break;
case 1:
// UP
g->sector->lightlevel += GLOWSPEED;
if (g->sector->lightlevel >= g->maxlight)
{
g->sector->lightlevel -= GLOWSPEED;
g->direction = -1;
}
break;
}
}
void P_SpawnGlowingLight (sector_t *sector)
{
glow_t *g;
g = Z_Malloc( sizeof(*g), PU_LEVSPEC, 0);
P_AddThinker(&g->thinker);
g->sector = sector;
g->minlight = P_FindMinSurroundingLight(sector,sector->lightlevel);
g->maxlight = sector->lightlevel;
g->thinker.function.acp1 = (actionf_p1) T_Glow;
g->direction = -1;
if (olddemo)
sector->special &= 0xff00;
}
//
// [RH] More glowing light, this time appropriate for Hexen-ish uses.
//
void T_Glow2 (glow2_t *g)
{
if (g->tics++ >= g->maxtics) {
if (g->oneshot) {
g->sector->lightlevel = g->end;
P_RemoveThinker (&g->thinker);
return;
} else {
int temp = g->start;
g->start = g->end;
g->end = temp;
g->tics -= g->maxtics;
}
}
g->sector->lightlevel = ((g->end - g->start) * g->tics) / g->maxtics + g->start;
}
static void P_SpawnGlowingLight2 (sector_t *sector, int start, int end,
int tics, BOOL oneshot)
{
glow2_t *g;
g = Z_Malloc( sizeof(*g), PU_LEVSPEC, 0);
P_AddThinker(&g->thinker);
g->sector = sector;
g->start = CLIPLIGHT(start);
g->end = CLIPLIGHT(end);
g->maxtics = tics;
g->tics = -1;
g->oneshot = oneshot;
g->thinker.function.acp1 = (actionf_p1) T_Glow2;
}
void EV_StartLightGlowing (int tag, int upper, int lower, int tics)
{
int secnum;
if (upper < lower) {
int temp = upper;
upper = lower;
lower = temp;
}
secnum = -1;
while ((secnum = P_FindSectorFromTag (tag,secnum)) >= 0)
{
sector_t *sec = &sectors[secnum];
if (P_SectorActive (lighting_special, sec))
continue;
P_SpawnGlowingLight2 (sec, upper, lower, tics, false);
}
}
void EV_StartLightFading (int tag, int value, int tics)
{
int secnum;
secnum = -1;
while ((secnum = P_FindSectorFromTag (tag,secnum)) >= 0)
{
sector_t *sec = &sectors[secnum];
if (P_SectorActive (lighting_special, sec))
continue;
// No need to fade if lightlevel is already at desired value.
if (sec->lightlevel == value)
continue;
P_SpawnGlowingLight2 (sec, sec->lightlevel, value, tics, true);
}
}
// [RH] Phased lighting ala Hexen
void T_PhasedLight (phased_t *l)
{
const int steps = 12;
if (l->phase < steps) {
l->sector->lightlevel = ((255 - l->baselevel) * l->phase) / steps + l->baselevel;
} else if (l->phase < 2*steps) {
l->sector->lightlevel = ((255 - l->baselevel) * (2*steps - l->phase - 1) / steps
+ l->baselevel);
} else {
l->sector->lightlevel = l->baselevel;
}
if (l->phase-- == 0)
l->phase = 63;
}
static int phasehelper (sector_t *sector, int index, int light, sector_t *prev)
{
if (!sector) {
return index;
} else {
phased_t *l = Z_Malloc (sizeof(*l), PU_LEVSPEC, 0);
int numsteps;
l->sector = sector;
l->baselevel = sector->lightlevel ? sector->lightlevel : light;
numsteps = phasehelper (P_NextSpecialSector (sector,
(sector->special & 0x00ff) == LightSequenceSpecial1 ?
LightSequenceSpecial2 : LightSequenceSpecial1, prev),
index + 1, l->baselevel, sector);
l->phase = ((numsteps - index - 1) * 64) / numsteps;
l->thinker.function.acp1 = (actionf_p1) T_PhasedLight;
P_AddThinker (&l->thinker);
sector->special &= 0xff00;
return numsteps;
}
}
void P_SpawnLightSequence (sector_t *sector)
{
phasehelper (sector, 0, 0, NULL);
}
void P_SpawnLightPhased (sector_t *sector)
{
phased_t *l = Z_Malloc (sizeof(*l), PU_LEVSPEC, 0);
l->sector = sector;
l->baselevel = 48;
l->phase = 63 - (sector->lightlevel & 63);
l->thinker.function.acp1 = (actionf_p1) T_PhasedLight;
P_AddThinker (&l->thinker);
sector->special &= 0xff00;
}

1362
code/P_lnspec.c Normal file

File diff suppressed because it is too large Load diff

293
code/P_lnspec.h Normal file
View file

@ -0,0 +1,293 @@
// p_lnspec.h: New line and sector specials (Using Hexen as a base.)
#ifndef __P_LNSPEC_H__
#define __P_LNSPEC_H__
#include "doomtype.h"
typedef enum {
Polyobj_StartLine = 1,
Polyobj_RotateLeft = 2,
Polyobj_RotateRight = 3,
Polyobj_Move = 4,
Polyobj_ExplicitLine = 5,
Polyobj_MoveTimes8 = 6,
Polyobj_DoorSwing = 7,
Polyobj_DoorSlide = 8,
Door_Close = 10,
Door_Open = 11,
Door_Raise = 12,
Door_LockedRaise = 13,
Floor_LowerByValue = 20,
Floor_LowerToLowest = 21,
Floor_LowerToNearest = 22,
Floor_RaiseByValue = 23,
Floor_RaiseToHighest = 24,
Floor_RaiseToNearest = 25,
Stairs_BuildDown = 26,
Stairs_BuildUp = 27,
Floor_RaiseAndCrush = 28,
Pillar_Build = 29,
Pillar_Open = 30,
Stairs_BuildDownSync = 31,
Stairs_BuildUpSync = 32,
Floor_RaiseByValueTimes8 = 35,
Floor_LowerByValueTimes8 = 36,
Ceiling_LowerByValue = 40,
Ceiling_RaiseByValue = 41,
Ceiling_CrushAndRaise = 42,
Ceiling_LowerAndCrush = 43,
Ceiling_CrushStop = 44,
Ceiling_CrushRaiseAndStay = 45,
Floor_CrushStop = 46,
Plat_PerpetualRaise = 60,
Plat_Stop = 61,
Plat_DownWaitUpStay = 62,
Plat_DownByValue = 63,
Plat_UpWaitDownStay = 64,
Plat_UpByValue = 65,
Floor_LowerInstant = 66,
Floor_RaiseInstant = 67,
Floor_MoveToValueTimes8 = 68,
Ceiling_MoveToValueTimes8 = 69,
Teleport = 70,
Teleport_NoFog = 71,
ThrustThing = 72,
DamageThing = 73,
Teleport_NewMap = 74,
Teleport_EndGame = 75,
ACS_Execute = 80,
ACS_Suspend = 81,
ACS_Terminate = 82,
ACS_LockedExecute = 83,
Polyobj_OR_RotateLeft = 90,
Polyobj_OR_RotateRight = 91,
Polyobj_OR_Move = 92,
Polyobj_OR_MoveTimes8 = 93,
Pillar_BuildAndCrush = 94,
FloorAndCeiling_LowerByValue = 95,
FloorAndCeiling_RaiseByValue = 96,
Scroll_Texture_Left = 100,
Scroll_Texture_Right = 101,
Scroll_Texture_Up = 102,
Scroll_Texture_Down = 103,
Light_ForceLightning = 109,
Light_RaiseByValue = 110,
Light_LowerByValue = 111,
Light_ChangeToValue = 112,
Light_Fade = 113,
Light_Glow = 114,
Light_Flicker = 115,
Light_Strobe = 116,
Radius_Quake = 120, // Earthquake
Line_SetIdentification = 121,
UsePuzzleItem = 129,
Thing_Activate = 130,
Thing_Deactivate = 131,
Thing_Remove = 132,
Thing_Destroy = 133,
Thing_Projectile = 134,
Thing_Spawn = 135,
Thing_ProjectileGravity = 136,
Thing_SpawnNoFog = 137,
Floor_Waggle = 138,
Sector_ChangeSound = 140,
// [RH] Begin new specials for ZDoom
Ceiling_LowerToHighestFloor = 192,
Ceiling_LowerInstant = 193,
Ceiling_RaiseInstant = 194,
Ceiling_CrushRaiseAndStayA = 195,
Ceiling_CrushAndRaiseA = 196,
Ceiling_CrushAndRaiseSilentA = 197,
Ceiling_RaiseByValueTimes8 = 198,
Ceiling_LowerByValueTimes8 = 199,
Generic_Floor = 200,
Generic_Ceiling = 201,
Generic_Door = 202,
Generic_Lift = 203,
Generic_Stairs = 204,
Generic_Crusher = 205,
Plat_DownWaitUpStayLip = 206,
Plat_PerpetualRaiseLip = 207,
TranslucentLine = 208,
Transfer_Heights = 209,
Transfer_FloorLight = 210,
Transfer_CeilingLight = 211,
Sector_SetColor = 212,
Sector_SetFade = 213,
Sector_SetDamage = 214,
Teleport_Line = 215,
Sector_SetGravity = 216,
Stairs_BuildUpDoom = 217,
Sector_SetWind = 218,
Sector_SetFriction = 219,
Sector_SetCurrent = 220,
Scroll_Texture_Both = 221,
Scroll_Texture_Model = 222,
Scroll_Floor = 223,
Scroll_Ceiling = 224,
Scroll_Texture_Offsets = 225,
ACS_ExecuteAlways = 226,
PointPush_SetForce = 227,
Plat_RaiseAndStayTx0 = 228,
Thing_SetGoal = 229,
Plat_UpByValueStayTx = 230,
Plat_ToggleCeiling = 231,
Light_StrobeDoom = 232,
Light_MinNeighbor = 233,
Light_MaxNeighbor = 234,
Floor_TransferTrigger = 235,
Floor_TransferNumeric = 236,
ChangeCamera = 237,
Floor_RaiseToLowestCeiling = 238,
Floor_RaiseByValueTxTy = 239,
Floor_RaiseByTexture = 240,
Floor_LowerToLowestTxTy = 241,
Floor_LowerToHighest = 242,
Exit_Normal = 243,
Exit_Secret = 244,
Elevator_RaiseToNearest = 245,
Elevator_MoveToFloor = 246,
Elevator_LowerToNearest = 247,
HealThing = 248,
Door_CloseWaitOpen = 249,
Floor_Donut = 250,
FloorAndCeiling_LowerRaise = 251,
Ceiling_RaiseToNearest = 252,
Ceiling_LowerToLowest = 253,
Ceiling_LowerToFloor = 254,
Ceiling_CrushRaiseAndStaySilA = 255
} linespecial_t;
typedef enum {
Light_Phased = 1,
LightSequenceStart = 2,
LightSequenceSpecial1 = 3,
LightSequenceSpecial2 = 4,
Stairs_Special1 = 26,
Stairs_Special2 = 27,
// [RH] Equivalents for DOOM's sector specials
dLight_Flicker = 65,
dLight_StrobeFast = 66,
dLight_StrobeSlow = 67,
dLight_Strobe_Hurt = 68,
dDamage_Hellslime = 69,
dDamage_Nukage = 71,
dLight_Glow = 72,
dSector_DoorCloseIn30 = 74,
dDamage_End = 75,
dLight_StrobeSlowSync = 76,
dLight_StrobeFastSync = 77,
dSector_DoorRaiseIn5Mins = 78,
dDamage_SuperHellslime = 80,
dLight_FireFlicker = 81,
Light_IndoorLightning2 = 198,
Light_IndoorLightning1 = 199,
Sky2 = 200,
Scroll_North_Slow = 201,
Scroll_North_Medium = 202,
Scroll_North_Fast = 203,
Scroll_East_Slow = 204,
Scroll_East_Medium = 205,
Scroll_East_Fast = 206,
Scroll_South_Slow = 207,
Scroll_South_Medium = 208,
Scroll_South_Fast = 209,
Scroll_West_Slow = 210,
Scroll_West_Medium = 211,
Scroll_West_Fast = 212,
Scroll_NorthWest_Slow = 213,
Scroll_NorthWest_Medium = 214,
Scroll_NorthWest_Fast = 215,
Scroll_NorthEast_Slow = 216,
Scroll_NorthEast_Medium = 217,
Scroll_NorthEast_Fast = 218,
Scroll_SouthEast_Slow = 219,
Scroll_SouthEast_Medium = 220,
Scroll_SouthEast_Fast = 221,
Scroll_SouthWest_Slow = 222,
Scroll_SouthWest_Medium = 223,
Scroll_SouthWest_Fast = 224,
} sectorspecial_t;
// [RH] Equivalents for BOOM's generalized sector types
#define DAMAGE_MASK 0x0300
#define SECRET_MASK 0x0400
#define FRICTION_MASK 0x0800
#define PUSH_MASK 0x1000
struct line_s;
struct mobj_s;
typedef BOOL (*lnSpecFunc)(struct line_s *line,
struct mobj_s *activator,
int arg1,
int arg2,
int arg3,
int arg4,
int arg5);
extern lnSpecFunc LineSpecials[256];
extern int TeleportSide;
#endif //__P_LNSPEC_H__

View file

@ -91,7 +91,8 @@ void P_DropWeapon (player_t* player);
// //
// P_USER // P_USER
// //
void P_PlayerThink (player_t* player); void P_FallingDamage (mobj_t *ent);
void P_PlayerThink (player_t *player);
// //
@ -109,7 +110,15 @@ extern int iquehead;
extern int iquetail; extern int iquetail;
void P_RespawnSpecials (void); // [RH] Functions to work with ThingIDs.
void P_ClearTidHashes (void);
void P_AddMobjToHash (mobj_t *mobj);
void P_RemoveMobjFromHash (mobj_t *mobj);
mobj_t *P_FindMobjByTid (mobj_t *mobj, int tid);
mobj_t *P_FindGoal (mobj_t *mobj, int tid, int type);
void P_RespawnSpecials (void);
mobj_t *P_SpawnMobj (fixed_t x, fixed_t y, fixed_t z, mobjtype_t type, int onfloor); mobj_t *P_SpawnMobj (fixed_t x, fixed_t y, fixed_t z, mobjtype_t type, int onfloor);
@ -126,10 +135,28 @@ void P_SpawnPlayerMissile (mobj_t* source, mobjtype_t type);
void ThrowGib (mobj_t *self, mobjtype_t gibtype, int damage); void ThrowGib (mobj_t *self, mobjtype_t gibtype, int damage);
//
// [RH] P_THINGS
//
extern int SpawnableThings[];
extern const int NumSpawnableThings;
BOOL P_Thing_Spawn (int tid, int type, angle_t angle, BOOL fog);
BOOL P_Thing_Projectile (int tid, int type, angle_t angle,
fixed_t speed, fixed_t vspeed, BOOL gravity);
BOOL P_ActivateMobj (mobj_t *mobj);
BOOL P_DeactivateMobj (mobj_t *mobj);
// //
// P_ENEMY // P_ENEMY
// //
void P_NoiseAlert (mobj_t* target, mobj_t* emmiter); void P_NoiseAlert (mobj_t* target, mobj_t* emmiter);
void P_SpawnBrainTargets(void); // killough 3/26/98: spawn icon landings
extern struct brain_s { // killough 3/26/98: global state of boss brain
int easy, targeton;
} brain;
// [RH] Andy Baker's stealth monsters // [RH] Andy Baker's stealth monsters
void P_BecomeVisible (mobj_t *actor); void P_BecomeVisible (mobj_t *actor);
@ -212,17 +239,18 @@ extern BOOL floatok;
extern fixed_t tmfloorz; extern fixed_t tmfloorz;
extern fixed_t tmceilingz; extern fixed_t tmceilingz;
extern msecnode_t *sector_list; // phares 3/16/98 extern msecnode_t *sector_list; // phares 3/16/98
extern BOOL oldshootactivation; // [RH]
extern line_t* ceilingline; extern line_t* ceilingline;
BOOL P_CheckPosition (mobj_t *thing, fixed_t x, fixed_t y); BOOL P_CheckPosition (mobj_t *thing, fixed_t x, fixed_t y);
BOOL P_TryMove (mobj_t* thing, fixed_t x, fixed_t y); BOOL P_TryMove (mobj_t* thing, fixed_t x, fixed_t y, BOOL dropoff);
BOOL P_TeleportMove (mobj_t* thing, fixed_t x, fixed_t y, fixed_t z, BOOL telefrag); // [RH] Added z and telefrag parameters BOOL P_TeleportMove (mobj_t* thing, fixed_t x, fixed_t y, fixed_t z, BOOL telefrag); // [RH] Added z and telefrag parameters
void P_SlideMove (mobj_t* mo); void P_SlideMove (mobj_t* mo);
BOOL P_CheckSight (const mobj_t* t1, const mobj_t* t2); BOOL P_CheckSight (const mobj_t* t1, const mobj_t* t2, BOOL ignoreInvisibility);
void P_UseLines (player_t* player); void P_UseLines (player_t* player);
BOOL P_ChangeSector (sector_t* sector, BOOL crunch); BOOL P_ChangeSector (sector_t* sector, int crunch);
extern mobj_t* linetarget; // who got hit (or NULL) extern mobj_t* linetarget; // who got hit (or NULL)
@ -234,7 +262,7 @@ void P_LineAttack (mobj_t *t1, angle_t angle, fixed_t distance, fixed_t slope, i
void P_RadiusAttack (mobj_t *spot, mobj_t *source, int damage, int mod); void P_RadiusAttack (mobj_t *spot, mobj_t *source, int damage, int mod);
//jff 3/19/98 P_CheckSector(): new routine to replace P_ChangeSector() //jff 3/19/98 P_CheckSector(): new routine to replace P_ChangeSector()
BOOL P_CheckSector(sector_t *sector, BOOL crunch); BOOL P_CheckSector(sector_t *sector, int crunch);
void P_DelSeclist(msecnode_t *); // phares 3/16/98 void P_DelSeclist(msecnode_t *); // phares 3/16/98
void P_CreateSecNodeList(mobj_t*,fixed_t,fixed_t); // phares 3/14/98 void P_CreateSecNodeList(mobj_t*,fixed_t,fixed_t); // phares 3/14/98
int P_GetMoveFactor(mobj_t* mo); // phares 3/6/98 int P_GetMoveFactor(mobj_t* mo); // phares 3/6/98
@ -306,7 +334,6 @@ void P_DamageMobj (mobj_t *target, mobj_t *inflictor, mobj_t *source, int damage
#define MOD_EXIT 20 #define MOD_EXIT 20
#define MOD_SPLASH 21 #define MOD_SPLASH 21
#define MOD_HIT 22 #define MOD_HIT 22
#define MOD_FALLXFER 23
#define MOD_FRIENDLY_FIRE 0x80000000 #define MOD_FRIENDLY_FIRE 0x80000000
extern int MeansOfDeath; extern int MeansOfDeath;

View file

@ -41,22 +41,26 @@
// State. // State.
#include "doomstat.h" #include "doomstat.h"
#include "r_state.h" #include "r_state.h"
// Data.
#include "sounds.h"
#include "z_zone.h" #include "z_zone.h"
fixed_t tmbbox[4]; fixed_t tmbbox[4];
mobj_t* tmthing; static mobj_t *tmthing;
int tmflags; static int tmflags;
fixed_t tmx; static fixed_t tmx;
fixed_t tmy; static fixed_t tmy;
fixed_t tmz; // [RH] Needed for third dimension of teleporters static fixed_t tmz; // [RH] Needed for third dimension of teleporters
static int pe_x; // Pain Elemental position for Lost Soul checks // phares
static int pe_y; // Pain Elemental position for Lost Soul checks // phares
static int ls_x; // Lost Soul position for Lost Soul checks // phares
static int ls_y; // Lost Soul position for Lost Soul checks // phares
BOOL oldshootactivation; // [RH] True if no distinction is made between
// projectile cross and projectile hit
// If "floatok" true, move would be ok // If "floatok" true, move would be ok
// if within "tmfloorz - tmceilingz". // if within "tmfloorz - tmceilingz".
BOOL floatok; BOOL floatok;
fixed_t tmfloorz; fixed_t tmfloorz;
fixed_t tmceilingz; fixed_t tmceilingz;
@ -68,7 +72,7 @@ line_t* ceilingline;
// keep track of special lines as they are hit, // keep track of special lines as they are hit,
// but don't process them until the move is proven valid // but don't process them until the move is proven valid
// [RH] MaxSpecialCross grows as needed in increments of 8 // [RH] MaxSpecialCross grows as needed
int MaxSpecialCross = 0; int MaxSpecialCross = 0;
line_t** spechit; line_t** spechit;
@ -90,19 +94,18 @@ static BOOL StompAlwaysFrags;
BOOL PIT_StompThing (mobj_t* thing) BOOL PIT_StompThing (mobj_t* thing)
{ {
fixed_t blockdist; fixed_t blockdist;
if (!(thing->flags & MF_SHOOTABLE) ) if (!(thing->flags & MF_SHOOTABLE))
return true; return true;
// don't clip against self // don't clip against self
if (thing == tmthing) if (thing == tmthing)
return true; return true;
blockdist = thing->radius + tmthing->radius; blockdist = thing->radius + tmthing->radius;
if ( abs(thing->x - tmx) >= blockdist if (abs(thing->x - tmx) >= blockdist || abs(thing->y - tmy) >= blockdist)
|| abs(thing->y - tmy) >= blockdist )
{ {
// didn't hit it // didn't hit it
return true; return true;
@ -193,25 +196,117 @@ BOOL P_TeleportMove (mobj_t *thing, fixed_t x, fixed_t y, fixed_t z, BOOL telefr
thing->ceilingz = tmceilingz; thing->ceilingz = tmceilingz;
thing->x = x; thing->x = x;
thing->y = y; thing->y = y;
thing->z = z;
P_SetThingPosition (thing); P_SetThingPosition (thing);
thing->z = z;
return true; return true;
} }
// P_GetMoveFactor() returns the value by which the x,y // phares 3/19/98
// movements are multiplied to add to player movement. // |
// V
int P_GetMoveFactor(mobj_t* mo)
{
int movefactor = ORIG_FRICTION_FACTOR;
// If the floor is icy or muddy, it's harder to get moving. This is where
// the different friction factors are applied to 'trying to move'. In
// p_mobj.c, the friction factors are applied as you coast and slow down.
int momentum, friction;
if (!olddemo && boom_friction->value &&
!(mo->flags & (MF_NOGRAVITY | MF_NOCLIP)))
{
friction = mo->friction;
if (friction == ORIG_FRICTION) // normal floor
;
else if (friction > ORIG_FRICTION) // ice
{
movefactor = mo->movefactor;
mo->movefactor = ORIG_FRICTION_FACTOR; // reset
}
else // sludge
{
// phares 3/11/98: you start off slowly, then increase as
// you get better footing
momentum = (P_AproxDistance (mo->momx, mo->momy));
movefactor = mo->movefactor;
if (momentum > MORE_FRICTION_MOMENTUM<<2)
movefactor <<= 3;
else if (momentum > MORE_FRICTION_MOMENTUM<<1)
movefactor <<= 2;
else if (momentum > MORE_FRICTION_MOMENTUM)
movefactor <<= 1;
mo->movefactor = ORIG_FRICTION_FACTOR; // reset
}
} // ^
return (movefactor); // |
} // phares 3/19/98
// //
// MOVEMENT ITERATOR FUNCTIONS // MOVEMENT ITERATOR FUNCTIONS
// //
// // phares
// PIT_CrossLine // |
// Checks to see if a PE->LS trajectory line crosses a blocking // V
// line. Returns false if it does.
//
// tmbbox holds the bounding box of the trajectory. If that box
// does not touch the bounding box of the line in question,
// then the trajectory is not blocked. If the PE is on one side
// of the line and the LS is on the other side, then the
// trajectory is blocked.
//
// Currently this assumes an infinite line, which is not quite
// correct. A more correct solution would be to check for an
// intersection of the trajectory and the line, but that takes
// longer and probably really isn't worth the effort.
//
static // killough 3/26/98: make static
BOOL PIT_CrossLine (line_t* ld)
{
if (!(ld->flags & ML_TWOSIDED) ||
(ld->flags & (ML_BLOCKING|ML_BLOCKMONSTERS|ML_BLOCKEVERYTHING)))
if (!(tmbbox[BOXLEFT] > ld->bbox[BOXRIGHT] ||
tmbbox[BOXRIGHT] < ld->bbox[BOXLEFT] ||
tmbbox[BOXTOP] < ld->bbox[BOXBOTTOM] ||
tmbbox[BOXBOTTOM] > ld->bbox[BOXTOP]))
if (P_PointOnLineSide(pe_x,pe_y,ld) != P_PointOnLineSide(ls_x,ls_y,ld))
return(false); // line blocks trajectory // ^
return(true); // line doesn't block trajectory // |
} // phares
// //
// PIT_CheckLine // PIT_CheckLine
// Adjusts tmfloorz and tmceilingz as lines are contacted // Adjusts tmfloorz and tmceilingz as lines are contacted
// //
BOOL PIT_CheckLine (line_t* ld)
// [RH] Moved this out of PIT_CheckLine()
static void AddSpecialLine (line_t *ld)
{
if (ld->special)
{
// [RH] Grow the spechit array as needed
if (numspechit >= MaxSpecialCross) {
MaxSpecialCross = MaxSpecialCross ? MaxSpecialCross * 2 : 8;
spechit = Realloc (spechit, MaxSpecialCross * sizeof(*spechit));
DPrintf ("MaxSpecialCross increased to %d\n", MaxSpecialCross);
}
spechit[numspechit++] = ld;
}
}
static // killough 3/26/98: make static
BOOL PIT_CheckLine (line_t *ld)
{ {
if (tmbbox[BOXRIGHT] <= ld->bbox[BOXLEFT] if (tmbbox[BOXRIGHT] <= ld->bbox[BOXLEFT]
|| tmbbox[BOXLEFT] >= ld->bbox[BOXRIGHT] || tmbbox[BOXLEFT] >= ld->bbox[BOXRIGHT]
@ -233,16 +328,22 @@ BOOL PIT_CheckLine (line_t* ld)
// so two special lines that are only 8 pixels apart // so two special lines that are only 8 pixels apart
// could be crossed in either order. // could be crossed in either order.
if (!ld->backsector) if (!ld->backsector) {
// [RH] Let somebody push it if they want to
if ((ld->flags & ML_ACTIVATIONMASK) == ML_ACTIVATEPUSH)
AddSpecialLine (ld);
return false; // one sided line return false; // one sided line
}
if (!(tmthing->flags & MF_MISSILE) ) if (!(tmthing->flags & MF_MISSILE) || (ld->flags & ML_BLOCKEVERYTHING))
{ {
if ( ld->flags & ML_BLOCKING ) if ((ld->flags & (ML_BLOCKING|ML_BLOCKEVERYTHING)) || // explicitly blocking everything
return false; // explicitly blocking everything (!tmthing->player && ld->flags & ML_BLOCKMONSTERS)) { // block monsters only
// [RH] Add pushable lines to the special list
if ( !tmthing->player && ld->flags & ML_BLOCKMONSTERS ) if ((ld->flags & ML_ACTIVATIONMASK) == ML_ACTIVATEPUSH)
return false; // block monsters only AddSpecialLine (ld);
return false;
}
} }
// set openrange, opentop, openbottom // set openrange, opentop, openbottom
@ -262,17 +363,7 @@ BOOL PIT_CheckLine (line_t* ld)
tmdropoffz = lowfloor; tmdropoffz = lowfloor;
// if contacted a special line, add it to the list // if contacted a special line, add it to the list
if (ld->special) AddSpecialLine (ld);
{
// [RH] Grow the spechit array as needed
if (numspechit >= MaxSpecialCross) {
MaxSpecialCross += 8;
spechit = Realloc (spechit, MaxSpecialCross * sizeof(line_t *));
DPrintf ("MaxSpecialCross increased to %d\n", MaxSpecialCross);
}
spechit[numspechit] = ld;
numspechit++;
}
return true; return true;
} }
@ -280,23 +371,23 @@ BOOL PIT_CheckLine (line_t* ld)
// //
// PIT_CheckThing // PIT_CheckThing
// //
static // killough 3/26/98: make static
BOOL PIT_CheckThing (mobj_t *thing) BOOL PIT_CheckThing (mobj_t *thing)
{ {
fixed_t blockdist; fixed_t blockdist;
BOOL solid; BOOL solid;
int damage; int damage;
if (!(thing->flags & (MF_SOLID|MF_SPECIAL|MF_SHOOTABLE) ))
return true;
// don't clip against self // don't clip against self
if (thing == tmthing) if (thing == tmthing)
return true; return true;
if (!(thing->flags & (MF_SOLID|MF_SPECIAL|MF_SHOOTABLE)) )
return true;
blockdist = thing->radius + tmthing->radius; blockdist = thing->radius + tmthing->radius;
if ( abs(thing->x - tmx) >= blockdist if (abs(thing->x - tmx) >= blockdist || abs(thing->y - tmy) >= blockdist)
|| abs(thing->y - tmy) >= blockdist )
{ {
// didn't hit it // didn't hit it
return true; return true;
@ -348,7 +439,7 @@ BOOL PIT_CheckThing (mobj_t *thing)
return true; return true;
// [RH] DeHackEd infighting is here. // [RH] DeHackEd infighting is here.
if (!deh_Infight && thing->type != MT_PLAYER) if (!deh.Infight && thing->type != MT_PLAYER)
{ {
// Explode, but do no damage. // Explode, but do no damage.
// Let players missile other players. // Let players missile other players.
@ -400,10 +491,77 @@ BOOL PIT_CheckThing (mobj_t *thing)
} }
return !solid; return !solid;
} }
return !(thing->flags & MF_SOLID); // [RH] Allow step up on top of things up to 24 units (like stairs)
// The movement code will automatically place the moving object
// on top of the other one.
if (!olddemo
&& !(tmthing->z & MF2_JUMPING)
&& tmthing->z < thing->z + thing->height
&& thing->z + thing->height - tmthing->z <= 24 * FRACUNIT
&& thing->z + thing->height + tmthing->height < thing->subsector->sector->ceilingheight
) {
tmthing->z = thing->z;
tmthing->momz = 1;
return true;
}
// killough 3/16/98: Allow non-solid moving objects to move through solid
// ones, by allowing the moving thing (tmthing) to move if it's non-solid,
// despite another solid thing being in the way.
// killough 4/11/98: Treat no-clipping things as not blocking
return !((thing->flags & MF_SOLID && !(thing->flags & MF_NOCLIP))
&& (tmthing->flags & MF_SOLID || olddemo));
// return !(thing->flags & MF_SOLID); // old code -- killough
} }
// This routine checks for Lost Souls trying to be spawned // phares
// across 1-sided lines, impassible lines, or "monsters can't // |
// cross" lines. Draw an imaginary line between the PE // V
// and the new Lost Soul spawn spot. If that line crosses
// a 'blocking' line, then disallow the spawn. Only search
// lines in the blocks of the blockmap where the bounding box
// of the trajectory line resides. Then check bounding box
// of the trajectory vs. the bounding box of each blocking
// line to see if the trajectory and the blocking line cross.
// Then check the PE and LS to see if they're on different
// sides of the blocking line. If so, return true, otherwise
// false.
BOOL Check_Sides(mobj_t* actor, int x, int y)
{
int bx,by,xl,xh,yl,yh;
pe_x = actor->x;
pe_y = actor->y;
ls_x = x;
ls_y = y;
// Here is the bounding box of the trajectory
tmbbox[BOXLEFT] = pe_x < x ? pe_x : x;
tmbbox[BOXRIGHT] = pe_x > x ? pe_x : x;
tmbbox[BOXTOP] = pe_y > y ? pe_y : y;
tmbbox[BOXBOTTOM] = pe_y < y ? pe_y : y;
// Determine which blocks to look in for blocking lines
xl = (tmbbox[BOXLEFT] - bmaporgx)>>MAPBLOCKSHIFT;
xh = (tmbbox[BOXRIGHT] - bmaporgx)>>MAPBLOCKSHIFT;
yl = (tmbbox[BOXBOTTOM] - bmaporgy)>>MAPBLOCKSHIFT;
yh = (tmbbox[BOXTOP] - bmaporgy)>>MAPBLOCKSHIFT;
// xl->xh, yl->yh determine the mapblock set to search
validcount++; // prevents checking same line twice
for (bx = xl ; bx <= xh ; bx++)
for (by = yl ; by <= yh ; by++)
if (!P_BlockLinesIterator(bx,by,PIT_CrossLine))
return true; // ^
return(false); // |
} // phares
// //
// MOVEMENT CLIPPING // MOVEMENT CLIPPING
@ -435,13 +593,10 @@ BOOL PIT_CheckThing (mobj_t *thing)
// //
BOOL P_CheckPosition (mobj_t *thing, fixed_t x, fixed_t y) BOOL P_CheckPosition (mobj_t *thing, fixed_t x, fixed_t y)
{ {
int xl; int xl, xh;
int xh; int yl, yh;
int yl; int bx, by;
int yh; subsector_t *newsubsec;
int bx;
int by;
subsector_t* newsubsec;
tmthing = thing; tmthing = thing;
tmflags = thing->flags; tmflags = thing->flags;
@ -505,7 +660,8 @@ BOOL P_CheckPosition (mobj_t *thing, fixed_t x, fixed_t y)
// Attempt to move to a new position, // Attempt to move to a new position,
// crossing special lines unless MF_TELEPORT is set. // crossing special lines unless MF_TELEPORT is set.
// //
BOOL P_TryMove (mobj_t *thing, fixed_t x, fixed_t y) BOOL P_TryMove (mobj_t *thing, fixed_t x, fixed_t y,
BOOL dropoff) // killough 3/15/98: allow dropoff as option
{ {
fixed_t oldx; fixed_t oldx;
fixed_t oldy; fixed_t oldy;
@ -519,6 +675,13 @@ BOOL P_TryMove (mobj_t *thing, fixed_t x, fixed_t y)
if ( !(thing->flags & MF_NOCLIP) ) if ( !(thing->flags & MF_NOCLIP) )
{ {
#ifdef CEILCARRY
// killough 4/11/98: if the thing hangs from
// a ceiling, don't worry about it fitting
if (!(thing->flags & MF_SPAWNCEILING) || demo_compatibility)
#endif
if (tmceilingz - tmfloorz < thing->height) if (tmceilingz - tmfloorz < thing->height)
return false; // doesn't fit return false; // doesn't fit
@ -530,8 +693,12 @@ BOOL P_TryMove (mobj_t *thing, fixed_t x, fixed_t y)
if ( !(thing->flags&MF_TELEPORT) && tmfloorz - thing->z > 24*FRACUNIT ) if ( !(thing->flags&MF_TELEPORT) && tmfloorz - thing->z > 24*FRACUNIT )
return false; // too big a step up return false; // too big a step up
if ( !(thing->flags&(MF_DROPOFF|MF_FLOAT)) && tmfloorz - tmdropoffz > 24*FRACUNIT ) // killough 3/15/98: Allow certain objects to drop off
return false; // don't stand over a dropoff
if (olddemo || !dropoff)
if ( !(thing->flags&(MF_DROPOFF|MF_FLOAT))
&& tmfloorz - tmdropoffz > 24*FRACUNIT )
return false; // don't stand over a dropoff
} }
// the move is ok, // the move is ok,
@ -556,11 +723,8 @@ BOOL P_TryMove (mobj_t *thing, fixed_t x, fixed_t y)
ld = spechit[numspechit]; ld = spechit[numspechit];
side = P_PointOnLineSide (thing->x, thing->y, ld); side = P_PointOnLineSide (thing->x, thing->y, ld);
oldside = P_PointOnLineSide (oldx, oldy, ld); oldside = P_PointOnLineSide (oldx, oldy, ld);
if (side != oldside) if (side != oldside && ld->special)
{ P_CrossSpecialLine (ld-lines, oldside, thing);
if (ld->special)
P_CrossSpecialLine (ld-lines, oldside, thing);
}
} }
} }
@ -628,59 +792,111 @@ mobj_t* slidemo;
fixed_t tmxmove; fixed_t tmxmove;
fixed_t tmymove; fixed_t tmymove;
extern mobj_t *onground;
// //
// P_HitSlideLine // P_HitSlideLine
// Adjusts the xmove / ymove // Adjusts the xmove / ymove
// so that the next move will slide along the wall. // so that the next move will slide along the wall.
// If the floor is icy, then you can bounce off a wall. // phares
// //
void P_HitSlideLine (line_t* ld) void P_HitSlideLine (line_t* ld)
{ {
int side; int side;
angle_t lineangle; angle_t lineangle;
angle_t moveangle; angle_t moveangle;
angle_t deltaangle; angle_t deltaangle;
fixed_t movelen; fixed_t movelen;
fixed_t newlen; fixed_t newlen;
BOOL icyfloor; // is floor icy? // phares
// |
// Under icy conditions, if the angle of approach to the wall // V
// is more than 45 degrees, then you'll bounce and lose half
// your momentum. If less than 45 degrees, you'll slide along
// the wall. 45 is arbitrary and is believable.
// Check for the special cases of horz or vert walls.
if (!olddemo && boom_friction->value && slidemo->player)
// player must be on ground
icyfloor = ((onground == (mobj_t *)-1) && (slidemo->friction > ORIG_FRICTION));
else
icyfloor = false;
if (ld->slopetype == ST_HORIZONTAL) if (ld->slopetype == ST_HORIZONTAL)
{ {
tmymove = 0; if (icyfloor && (abs(tmymove) > abs(tmxmove)))
{
tmxmove /= 2; // absorb half the momentum
tmymove = -tmymove/2;
S_StartSound (slidemo, "*grunt1", 78); // oooff!
}
else
tmymove = 0; // no more movement in the Y direction
return; return;
} }
if (ld->slopetype == ST_VERTICAL) if (ld->slopetype == ST_VERTICAL)
{ {
tmxmove = 0; if (icyfloor && (abs(tmxmove) > abs(tmymove)))
{
tmxmove = -tmxmove/2; // absorb half the momentum
tmymove /= 2;
S_StartSound (slidemo, "*grunt1", 78); // oooff! // ^
} // |
else // phares
tmxmove = 0; // no more movement in the X direction
return; return;
} }
// The wall is angled. Bounce if the angle of approach is // phares
// less than 45 degrees. // phares
side = P_PointOnLineSide (slidemo->x, slidemo->y, ld); side = P_PointOnLineSide (slidemo->x, slidemo->y, ld);
lineangle = R_PointToAngle2 (0,0, ld->dx, ld->dy); lineangle = R_PointToAngle2 (0,0, ld->dx, ld->dy);
if (side == 1) if (side == 1)
lineangle += ANG180; lineangle += ANG180;
moveangle = R_PointToAngle2 (0,0, tmxmove, tmymove); moveangle = R_PointToAngle2 (0,0, tmxmove, tmymove);
deltaangle = moveangle-lineangle;
if (deltaangle > ANG180) // killough 3/2/98:
deltaangle += ANG180; // The moveangle+=10 breaks v1.9 demo compatibility in
// I_Error ("SlideLine: ang>ANG180"); // some demos, so it needs demo_compatibility switch.
lineangle >>= ANGLETOFINESHIFT; if (!olddemo)
deltaangle >>= ANGLETOFINESHIFT; moveangle += 10; // prevents sudden path reversal due to // phares
// rounding error // |
deltaangle = moveangle-lineangle; // V
movelen = P_AproxDistance (tmxmove, tmymove); movelen = P_AproxDistance (tmxmove, tmymove);
newlen = FixedMul (movelen, finecosine[deltaangle]); if (icyfloor && (deltaangle > ANG45) && (deltaangle < ANG90+ANG45))
{
moveangle = lineangle - deltaangle;
movelen /= 2; // absorb
S_StartSound (slidemo, "*grunt1", 78); // oooff!
moveangle >>= ANGLETOFINESHIFT;
tmxmove = FixedMul (movelen, finecosine[moveangle]);
tmymove = FixedMul (movelen, finesine[moveangle]);
} // ^
else // |
{ // phares
if (deltaangle > ANG180)
deltaangle += ANG180;
// I_Error ("SlideLine: ang>ANG180");
tmxmove = FixedMul (newlen, finecosine[lineangle]); lineangle >>= ANGLETOFINESHIFT;
tmymove = FixedMul (newlen, finesine[lineangle]); deltaangle >>= ANGLETOFINESHIFT;
movelen = P_AproxDistance (tmxmove, tmymove);
newlen = FixedMul (movelen, finecosine[deltaangle]);
tmxmove = FixedMul (newlen, finecosine[lineangle]);
tmymove = FixedMul (newlen, finesine[lineangle]);
} // phares
} }
@ -801,8 +1017,17 @@ void P_SlideMove (mobj_t* mo)
{ {
// the move most have hit the middle, so stairstep // the move most have hit the middle, so stairstep
stairstep: stairstep:
if (!P_TryMove (mo, mo->x, mo->y + mo->momy)) // killough 3/15/98: Allow objects to drop off ledges
P_TryMove (mo, mo->x + mo->momx, mo->y);
if (!P_TryMove (mo, mo->x, mo->y + mo->momy, true))
// phares 5/4/98: kill momentum if you can't move at all
// This eliminates player bobbing if pressed against a wall
// while on ice.
if (!P_TryMove (mo, mo->x + mo->momx, mo->y, true))
if (!olddemo)
mo->momx = mo->momy = 0;
return; return;
} }
@ -813,7 +1038,9 @@ void P_SlideMove (mobj_t* mo)
newx = FixedMul (mo->momx, bestslidefrac); newx = FixedMul (mo->momx, bestslidefrac);
newy = FixedMul (mo->momy, bestslidefrac); newy = FixedMul (mo->momy, bestslidefrac);
if (!P_TryMove (mo, mo->x+newx, mo->y+newy)) // killough 3/15/98: Allow objects to drop off ledges
if (!P_TryMove (mo, mo->x+newx, mo->y+newy, true))
goto stairstep; goto stairstep;
} }
@ -835,10 +1062,10 @@ void P_SlideMove (mobj_t* mo)
mo->momx = tmxmove; mo->momx = tmxmove;
mo->momy = tmymove; mo->momy = tmymove;
if (!P_TryMove (mo, mo->x+tmxmove, mo->y+tmymove)) // killough 3/15/98: Allow objects to drop off ledges
{
if (!P_TryMove (mo, mo->x+tmxmove, mo->y+tmymove, true))
goto retry; goto retry;
}
} }
@ -858,16 +1085,17 @@ fixed_t attackrange;
fixed_t aimslope; fixed_t aimslope;
// slopes to top and bottom of target // slopes to top and bottom of target
extern fixed_t topslope; // killough 4/20/98: make static instead of using ones in p_sight.c
extern fixed_t bottomslope;
static fixed_t topslope;
static fixed_t bottomslope;
// //
// PTR_AimTraverse // PTR_AimTraverse
// Sets linetaget and aimslope when a target is aimed at. // Sets linetaget and aimslope when a target is aimed at.
// //
BOOL BOOL PTR_AimTraverse (intercept_t* in)
PTR_AimTraverse (intercept_t* in)
{ {
line_t* li; line_t* li;
mobj_t* th; mobj_t* th;
@ -970,10 +1198,10 @@ BOOL PTR_ShootTraverse (intercept_t* in)
{ {
li = in->d.line; li = in->d.line;
if (li->special) if (oldshootactivation && li->special)
P_ShootSpecialLine (shootthing, li); P_ShootSpecialLine (shootthing, li);
if ( !(li->flags & ML_TWOSIDED) ) if ( !(li->flags & ML_TWOSIDED) || (li->flags & ML_BLOCKEVERYTHING))
goto hitline; goto hitline;
// crosses a two sided line // crosses a two sided line
@ -990,21 +1218,27 @@ BOOL PTR_ShootTraverse (intercept_t* in)
if (li->frontsector->ceilingheight != li->backsector->ceilingheight) if (li->frontsector->ceilingheight != li->backsector->ceilingheight)
{ {
slope = FixedDiv (opentop - shootz , dist); slope = FixedDiv (opentop - shootz, dist);
if (slope < aimslope) if (slope < aimslope)
goto hitline; goto hitline;
} }
// shot continues // shot continues
// [RH] Possibly trigger activation
if (!oldshootactivation && li->special)
P_ShotCrossSpecialLine (shootthing, li);
return true; return true;
// hit line // hit line
hitline: hitline:
// [RH] Possibly trigger activation
if (!oldshootactivation && li->special)
P_ShootSpecialLine (shootthing, li);
// position a bit closer // position a bit closer
frac = in->frac - FixedDiv (4*FRACUNIT,attackrange); frac = in->frac - FixedDiv (4*FRACUNIT,attackrange);
x = trace.x + FixedMul (trace.dx, frac);
y = trace.y + FixedMul (trace.dy, frac);
z = shootz + FixedMul (aimslope, FixedMul(frac, attackrange)); z = shootz + FixedMul (aimslope, FixedMul(frac, attackrange));
if (li->frontsector->ceilingpic == skyflatnum) if (li->frontsector->ceilingpic == skyflatnum)
@ -1015,11 +1249,42 @@ BOOL PTR_ShootTraverse (intercept_t* in)
// it's a sky hack wall // it's a sky hack wall
if (li->backsector && li->backsector->ceilingpic == skyflatnum) if (li->backsector && li->backsector->ceilingpic == skyflatnum)
return false; // fix bullet-eaters -- killough:
// WARNING: Almost all demos will lose sync without this
// demo_compatibility flag check!!! killough 1/18/98
if (olddemo || li->backsector->ceilingheight < z)
return false;
} }
// [RH] If the trace went below/above the floor/ceiling, make the puff
// appear in the right place and not on a wall.
{
fixed_t ceilingheight, floorheight;
if (!li->backsector || !P_PointOnLineSide (trace.x, trace.y, li)) {
ceilingheight = li->frontsector->ceilingheight;
floorheight = li->frontsector->floorheight;
} else {
ceilingheight = li->backsector->ceilingheight;
floorheight = li->backsector->floorheight;
}
if (z < floorheight) {
frac = FixedDiv (FixedMul (floorheight - shootz, frac), z - shootz);
z = floorheight;
} else if (z > ceilingheight) {
// Puffs on the ceiling need to be lowered to compensate for the height of the puff
ceilingheight -= mobjinfo[MT_PUFF].height;
frac = FixedDiv (FixedMul (ceilingheight - shootz, frac), z - shootz);
z = ceilingheight;
}
}
x = trace.x + FixedMul (trace.dx, frac);
y = trace.y + FixedMul (trace.dy, frac);
// Spawn bullet puffs. // Spawn bullet puffs.
P_SpawnPuff (x,y,z); P_SpawnPuff (x, y, z);
// don't go any farther // don't go any farther
return false; return false;
@ -1056,17 +1321,20 @@ BOOL PTR_ShootTraverse (intercept_t* in)
// Spawn bullet puffs or blod spots, // Spawn bullet puffs or blod spots,
// depending on target type. // depending on target type.
if (in->d.thing->flags & MF_NOBLOOD) if ((in->d.thing->flags & MF_NOBLOOD) || (in->d.thing->flags2 & MF2_INVULNERABLE))
P_SpawnPuff (x,y,z); P_SpawnPuff (x,y,z);
else else
P_SpawnBlood (x,y,z, la_damage); P_SpawnBlood (x,y,z, la_damage);
if (la_damage) { if (la_damage) {
// [RH] figure out means of death; // [RH] try and figure out means of death;
int mod = MOD_UNKNOWN; int mod = MOD_UNKNOWN;
if (shootthing->player) { if (shootthing->player) {
switch (shootthing->player->readyweapon) { switch (shootthing->player->readyweapon) {
case wp_fist:
mod = MOD_FIST;
break;
case wp_pistol: case wp_pistol:
mod = MOD_PISTOL; mod = MOD_PISTOL;
break; break;
@ -1096,11 +1364,7 @@ BOOL PTR_ShootTraverse (intercept_t* in)
// //
// P_AimLineAttack // P_AimLineAttack
// //
fixed_t fixed_t P_AimLineAttack (mobj_t *t1, angle_t angle, fixed_t distance)
P_AimLineAttack
( mobj_t* t1,
angle_t angle,
fixed_t distance )
{ {
fixed_t x2; fixed_t x2;
fixed_t y2; fixed_t y2;
@ -1165,7 +1429,7 @@ void P_LineAttack (mobj_t *t1, angle_t angle, fixed_t distance,
// //
mobj_t *usething; mobj_t *usething;
BOOL PTR_UseTraverse (intercept_t* in) BOOL PTR_UseTraverse (intercept_t *in)
{ {
int side; int side;
@ -1174,7 +1438,7 @@ BOOL PTR_UseTraverse (intercept_t* in)
P_LineOpening (in->d.line); P_LineOpening (in->d.line);
if (openrange <= 0) if (openrange <= 0)
{ {
S_StartSound (usething, sfx_noway); S_StartSound (usething, "*grunt1", 78);
// can't use through a wall // can't use through a wall
return false; return false;
@ -1197,6 +1461,29 @@ BOOL PTR_UseTraverse (intercept_t* in)
return (!olddemo && (in->d.line->flags & ML_PASSUSE)) ? true : false; return (!olddemo && (in->d.line->flags & ML_PASSUSE)) ? true : false;
} }
// Returns false if a "oof" sound should be made because of a blocking
// linedef. Makes 2s middles which are impassable, as well as 2s uppers
// and lowers which block the player, cause the sound effect when the
// player tries to activate them. Specials are excluded, although it is
// assumed that all special linedefs within reach have been considered
// and rejected already (see P_UseLines).
//
// by Lee Killough
//
BOOL PTR_NoWayTraverse(intercept_t* in)
{
line_t *ld = in->d.line; // This linedef
return ld->special || !( // Ignore specials
ld->flags & (ML_BLOCKING|ML_BLOCKEVERYTHING) || ( // Always blocking
P_LineOpening(ld), // Find openings
openrange <= 0 || // No opening
openbottom > usething->z+24*FRACUNIT || // Too high it blocks
opentop < usething->z+usething->height // Too low it blocks
)
);
}
// //
// P_UseLines // P_UseLines
@ -1218,8 +1505,16 @@ void P_UseLines (player_t* player)
y1 = player->mo->y; y1 = player->mo->y;
x2 = x1 + (USERANGE>>FRACBITS)*finecosine[angle]; x2 = x1 + (USERANGE>>FRACBITS)*finecosine[angle];
y2 = y1 + (USERANGE>>FRACBITS)*finesine[angle]; y2 = y1 + (USERANGE>>FRACBITS)*finesine[angle];
P_PathTraverse ( x1, y1, x2, y2, PT_ADDLINES, PTR_UseTraverse ); // old code:
//
// P_PathTraverse ( x1, y1, x2, y2, PT_ADDLINES, PTR_UseTraverse );
//
// This added test makes the "oof" sound work on 2s lines -- killough:
if (P_PathTraverse ( x1, y1, x2, y2, PT_ADDLINES, PTR_UseTraverse ))
if (!P_PathTraverse ( x1, y1, x2, y2, PT_ADDLINES, PTR_NoWayTraverse ))
S_StartSound (usething, "*grunt1", 78);
} }
@ -1389,6 +1684,9 @@ void P_StandOnThing (mobj_t *thing, mobj_t *spot)
thing->z = spot->z + spot->height; thing->z = spot->z + spot->height;
else else
thing->z = thing->floorz; thing->z = thing->floorz;
if (thing->flags2 & MF2_JUMPING)
thing->flags2 &= ~MF2_JUMPING;
} }
// [RH] Z-Check <- // [RH] Z-Check <-
@ -1411,6 +1709,19 @@ vec3_t bombvec;
// [RH] Now it knows about vertical distances and // [RH] Now it knows about vertical distances and
// can thrust things vertically, too. // can thrust things vertically, too.
// //
// [RH] Damage scale to apply to thing that shot the missile.
cvar_t *splashfactor;
static float selfthrustscale;
void SplashFactorCallback (cvar_t *var) {
if (var->value <= 0.0f) {
SetCVarFloat (var, 1.0f);
} else {
selfthrustscale = 1.0f / var->value;
}
}
BOOL PIT_RadiusAttack (mobj_t *thing) BOOL PIT_RadiusAttack (mobj_t *thing)
{ {
if (!(thing->flags & MF_SHOOTABLE) ) if (!(thing->flags & MF_SHOOTABLE) )
@ -1439,9 +1750,9 @@ BOOL PIT_RadiusAttack (mobj_t *thing)
points = bombdamagefloat - len; points = bombdamagefloat - len;
} }
if (thing == bombsource) if (thing == bombsource)
points = points * 0.5f; points = points * splashfactor->value;
if (points > 0) { if (points > 0) {
if (P_CheckSight (thing, bombspot)) { if (P_CheckSight (thing, bombspot, true)) {
vec3_t dir; vec3_t dir;
float thrust; float thrust;
fixed_t momx = thing->momx; fixed_t momx = thing->momx;
@ -1449,11 +1760,16 @@ BOOL PIT_RadiusAttack (mobj_t *thing)
P_DamageMobj (thing, bombspot, bombsource, (int)points, bombmod); P_DamageMobj (thing, bombspot, bombsource, (int)points, bombmod);
thrust = points * 70000.0f / (float)thing->info->mass; thrust = points * 35000.0f / (float)thing->info->mass;
VectorSubtract (thingvec, bombvec, dir); VectorSubtract (thingvec, bombvec, dir);
VectorScale (dir, thrust, dir); VectorScale (dir, thrust, dir);
if (bombsource != thing) if (bombsource != thing) {
dir[2] *= 0.5f; dir[2] *= 0.5f;
} else if (splashfactor->value) {
dir[0] *= selfthrustscale;
dir[1] *= selfthrustscale;
dir[2] *= selfthrustscale;
}
thing->momx = momx + (fixed_t)(dir[0]); thing->momx = momx + (fixed_t)(dir[0]);
thing->momy = momy + (fixed_t)(dir[1]); thing->momy = momy + (fixed_t)(dir[1]);
thing->momz += (fixed_t)(dir[2]); thing->momz += (fixed_t)(dir[2]);
@ -1477,7 +1793,7 @@ BOOL PIT_RadiusAttack (mobj_t *thing)
if (dist < 0) if (dist < 0)
dist = 0; dist = 0;
if ( P_CheckSight (thing, bombspot) ) if ( P_CheckSight (thing, bombspot, true) )
{ {
// must be in direct path // must be in direct path
P_DamageMobj (thing, bombspot, bombsource, bombdamage - dist, bombmod); P_DamageMobj (thing, bombspot, bombsource, bombdamage - dist, bombmod);
@ -1530,14 +1846,19 @@ void P_RadiusAttack (mobj_t *spot, mobj_t *source, int damage, int mod)
// of all things that touch the sector. // of all things that touch the sector.
// //
// If anything doesn't fit anymore, true will be returned. // If anything doesn't fit anymore, true will be returned.
// If crunch is true, they will take damage
// as they are being crushed.
// If Crunch is false, you should set the sector height back
// the way it was and call P_ChangeSector again
// to undo the changes.
// //
BOOL crushchange; // [RH] If crushchange is non-negative, they will take the
BOOL nofit; // specified amount of damage as they are being crushed.
// If crushchange is negative, you should set the sector
// height back the way it was and call P_ChangeSector
// again to undo the changes.
// Note that this is very different from the original
// true/false usage of crushchange! If you want regular
// DOOM crushing behavior set crushchange to 10 or -1
// if no crushing is desired.
//
int crushchange;
BOOL nofit;
// //
@ -1585,9 +1906,9 @@ BOOL PIT_ChangeSector (mobj_t *thing)
nofit = true; nofit = true;
if (crushchange && !(level.time&3) ) if ((crushchange >= 0) && !(level.time&3) )
{ {
P_DamageMobj(thing,NULL,NULL,10,MOD_CRUSH); P_DamageMobj (thing, NULL, NULL, crushchange, MOD_CRUSH);
// spray blood in a random direction // spray blood in a random direction
mo = P_SpawnMobj (thing->x, mo = P_SpawnMobj (thing->x,
@ -1609,14 +1930,18 @@ BOOL PIT_ChangeSector (mobj_t *thing)
// //
// P_ChangeSector // P_ChangeSector
// //
BOOL P_ChangeSector (sector_t *sector, BOOL crunch) BOOL P_ChangeSector (sector_t *sector, int crunch)
{ {
int x; int x;
int y; int y;
nofit = false; nofit = false;
crushchange = crunch; crushchange = crunch;
// ARRGGHHH!!!!
// This is horrendously slow!!!
// killough 3/14/98
// re-check heights for all things near the moving sector // re-check heights for all things near the moving sector
for (x=sector->blockbox[BOXLEFT] ; x<= sector->blockbox[BOXRIGHT] ; x++) for (x=sector->blockbox[BOXLEFT] ; x<= sector->blockbox[BOXRIGHT] ; x++)
for (y=sector->blockbox[BOXBOTTOM];y<= sector->blockbox[BOXTOP] ; y++) for (y=sector->blockbox[BOXBOTTOM];y<= sector->blockbox[BOXTOP] ; y++)
@ -1632,12 +1957,12 @@ BOOL P_ChangeSector (sector_t *sector, BOOL crunch)
// sector. Both more accurate and faster. // sector. Both more accurate and faster.
// //
BOOL P_CheckSector (sector_t *sector, BOOL crunch) BOOL P_CheckSector (sector_t *sector, int crunch)
{ {
msecnode_t *n; msecnode_t *n;
if (olddemo) // use the old routine for old demos though if (olddemo) // use the old routine for old demos though
return P_ChangeSector(sector,crunch); return P_ChangeSector (sector, crunch);
nofit = false; nofit = false;
crushchange = crunch; crushchange = crunch;

View file

@ -67,14 +67,14 @@ int P_PointOnLineSide (fixed_t x, fixed_t y, const line_t *line)
return line->dy < 0; return line->dy < 0;
} }
if (!line->dy) else if (!line->dy)
{ {
if (y <= line->v1->y) if (y <= line->v1->y)
return line->dx < 0; return line->dx < 0;
return line->dx > 0; return line->dx > 0;
} }
else
{ {
fixed_t left = FixedMul ( line->dy>>FRACBITS , (x - line->v1->x) ); fixed_t left = FixedMul ( line->dy>>FRACBITS , (x - line->v1->x) );
fixed_t right = FixedMul ( (y - line->v1->y) , line->dx>>FRACBITS ); fixed_t right = FixedMul ( (y - line->v1->y) , line->dx>>FRACBITS );
@ -142,11 +142,6 @@ int P_BoxOnLineSide (const fixed_t *tmbox, const line_t *ld)
// //
int P_PointOnDivlineSide (fixed_t x, fixed_t y, const divline_t *line) int P_PointOnDivlineSide (fixed_t x, fixed_t y, const divline_t *line)
{ {
fixed_t dx;
fixed_t dy;
fixed_t left;
fixed_t right;
if (!line->dx) if (!line->dx)
{ {
if (x <= line->x) if (x <= line->x)
@ -154,31 +149,35 @@ int P_PointOnDivlineSide (fixed_t x, fixed_t y, const divline_t *line)
return line->dy < 0; return line->dy < 0;
} }
if (!line->dy) else if (!line->dy)
{ {
if (y <= line->y) if (y <= line->y)
return line->dx < 0; return line->dx < 0;
return line->dx > 0; return line->dx > 0;
} }
else
dx = (x - line->x);
dy = (y - line->y);
// try to quickly decide by looking at sign bits
if ( (line->dy ^ line->dx ^ dx ^ dy)&0x80000000 )
{ {
if ( (line->dy ^ dx) & 0x80000000 ) fixed_t dx = (x - line->x);
return 1; // (left is negative) fixed_t dy = (y - line->y);
return 0;
// try to quickly decide by looking at sign bits
if ( (line->dy ^ line->dx ^ dx ^ dy)&0x80000000 )
{
if ( (line->dy ^ dx) & 0x80000000 )
return 1; // (left is negative)
return 0;
}
else
{
fixed_t left = FixedMul ( line->dy>>8, dx>>8 );
fixed_t right = FixedMul ( dy>>8 , line->dx>>8 );
if (right < left)
return 0; // front side
return 1; // back side
}
} }
left = FixedMul ( line->dy>>8, dx>>8 );
right = FixedMul ( dy>>8 , line->dx>>8 );
if (right < left)
return 0; // front side
return 1; // back side
} }
@ -198,10 +197,8 @@ void P_MakeDivline (const line_t *li, divline_t *dl)
// //
// P_InterceptVector // P_InterceptVector
// Returns the fractional intercept point // Returns the fractional intercept point along the first divline.
// along the first divline. // This is only called by the addthings and addlines traversers.
// This is only called by the addthings
// and addlines traversers.
// //
fixed_t P_InterceptVector (const divline_t *v2, const divline_t *v1) fixed_t P_InterceptVector (const divline_t *v2, const divline_t *v1)
{ {
@ -284,10 +281,9 @@ void P_LineOpening (const line_t *linedef)
front = linedef->frontsector; front = linedef->frontsector;
back = linedef->backsector; back = linedef->backsector;
if (front->ceilingheight < back->ceilingheight) opentop = (front->ceilingheight < back->ceilingheight) ?
opentop = front->ceilingheight; opentop = front->ceilingheight :
else back->ceilingheight;
opentop = back->ceilingheight;
if (front->floorheight > back->floorheight) if (front->floorheight > back->floorheight)
{ {
@ -313,14 +309,11 @@ void P_LineOpening (const line_t *linedef)
// P_UnsetThingPosition // P_UnsetThingPosition
// Unlinks a thing from block map and sectors. // Unlinks a thing from block map and sectors.
// On each position change, BLOCKMAP and other // On each position change, BLOCKMAP and other
// lookups maintaining lists ot things inside // lookups maintaining lists of things inside
// these structures need to be updated. // these structures need to be updated.
// //
void P_UnsetThingPosition (mobj_t *thing) void P_UnsetThingPosition (mobj_t *thing)
{ {
int blockx;
int blocky;
if (!(thing->flags & MF_NOSECTOR)) if (!(thing->flags & MF_NOSECTOR))
{ {
// inert things don't need to be in blockmap? // inert things don't need to be in blockmap?
@ -361,8 +354,8 @@ void P_UnsetThingPosition (mobj_t *thing)
thing->bprev->bnext = thing->bnext; thing->bprev->bnext = thing->bnext;
else else
{ {
blockx = (thing->x - bmaporgx)>>MAPBLOCKSHIFT; int blockx = (thing->x - bmaporgx)>>MAPBLOCKSHIFT;
blocky = (thing->y - bmaporgy)>>MAPBLOCKSHIFT; int blocky = (thing->y - bmaporgy)>>MAPBLOCKSHIFT;
if (blockx>=0 && blockx < bmapwidth if (blockx>=0 && blockx < bmapwidth
&& blocky>=0 && blocky <bmapheight) && blocky>=0 && blocky <bmapheight)
@ -476,7 +469,7 @@ BOOL P_BlockLinesIterator (int x, int y, BOOL(*func)(line_t*))
{ {
if (x<0 || y<0 || x>=bmapwidth || y>=bmapheight) if (x<0 || y<0 || x>=bmapwidth || y>=bmapheight)
return true; return true;
else
{ {
int offset = *(blockmap+(y*bmapwidth+x)); int offset = *(blockmap+(y*bmapwidth+x));
int *list = blockmaplump + offset; int *list = blockmaplump + offset;
@ -490,13 +483,12 @@ BOOL P_BlockLinesIterator (int x, int y, BOOL(*func)(line_t*))
{ {
line_t *ld = &lines[*list]; line_t *ld = &lines[*list];
if (ld->validcount == validcount) if (ld->validcount != validcount) {
continue; // line has already been checked ld->validcount = validcount;
ld->validcount = validcount;
if ( !func(ld) ) if ( !func(ld) )
return false; return false;
}
} }
} }
return true; // everything was checked return true; // everything was checked
@ -510,7 +502,7 @@ BOOL P_BlockThingsIterator (int x, int y, BOOL(*func)(mobj_t*))
{ {
if (x<0 || y<0 || x>=bmapwidth || y>=bmapheight) if (x<0 || y<0 || x>=bmapwidth || y>=bmapheight)
return true; return true;
else
{ {
mobj_t *mobj; mobj_t *mobj;
@ -603,19 +595,19 @@ BOOL PIT_AddLineIntercepts (line_t *ld)
// //
BOOL PIT_AddThingIntercepts (mobj_t* thing) BOOL PIT_AddThingIntercepts (mobj_t* thing)
{ {
fixed_t x1; fixed_t x1;
fixed_t y1; fixed_t y1;
fixed_t x2; fixed_t x2;
fixed_t y2; fixed_t y2;
int s1; int s1;
int s2; int s2;
BOOL tracepositive; BOOL tracepositive;
divline_t dl; divline_t dl;
fixed_t frac; fixed_t frac;
tracepositive = (trace.dx ^ trace.dy)>0; tracepositive = (trace.dx ^ trace.dy)>0;
@ -834,8 +826,7 @@ BOOL P_PathTraverse (fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2, int flags,
return false; // early out return false; // early out
} }
if (mapx == xt2 if (mapx == xt2 && mapy == yt2)
&& mapy == yt2)
{ {
break; break;
} }

View file

@ -30,7 +30,7 @@
#include "doomdef.h" #include "doomdef.h"
#include "p_local.h" #include "p_local.h"
#include "sounds.h" #include "p_lnspec.h"
#include "st_stuff.h" #include "st_stuff.h"
#include "hu_stuff.h" #include "hu_stuff.h"
@ -47,7 +47,6 @@ cvar_t *sv_friction;
void G_PlayerReborn (int player); void G_PlayerReborn (int player);
void P_SpawnMapThing (mapthing2_t *mthing);
// //
@ -83,7 +82,8 @@ BOOL P_SetMobjState (mobj_t *mobj, statenum_t state)
st = &states[state]; st = &states[state];
mobj->state = st; mobj->state = st;
mobj->tics = st->tics; mobj->tics = st->tics;
mobj->sprite = st->sprite; if (!mobj->player) // [RH] Only change sprite if not a player
mobj->sprite = st->sprite;
mobj->frame = st->frame; mobj->frame = st->frame;
// Modified handling. // Modified handling.
@ -129,13 +129,16 @@ void P_ExplodeMissile (mobj_t* mo)
mo->flags &= ~MF_MISSILE; mo->flags &= ~MF_MISSILE;
if (mo->info->deathsound) if (mo->info->deathsound)
S_StartSound (mo, mo->info->deathsound); S_StartSound (mo, mo->info->deathsound, 70);
} }
// //
// P_XYMovement // P_XYMovement
// //
extern int numspechit;
extern line_t **spechit;
#define STOPSPEED 0x1000 #define STOPSPEED 0x1000
#define FRICTION 0xe800 #define FRICTION 0xe800
@ -146,7 +149,9 @@ void P_XYMovement (mobj_t* mo)
player_t* player; player_t* player;
fixed_t xmove; fixed_t xmove;
fixed_t ymove; fixed_t ymove;
fixed_t oldx,oldy; // phares 9/10/98: reducing bobbing/momentum on ice
// when up against walls
if (!mo->momx && !mo->momy) if (!mo->momx && !mo->momy)
{ {
if (mo->flags & MF_SKULLFLY) if (mo->flags & MF_SKULLFLY)
@ -175,6 +180,9 @@ void P_XYMovement (mobj_t* mo)
xmove = mo->momx; xmove = mo->momx;
ymove = mo->momy; ymove = mo->momy;
oldx = mo->x; // phares 9/10/98: new code to reduce bobbing/momentum
oldy = mo->y; // when on ice & up against wall. These will be compared
// to your x,y values later to see if you were able to move
do do
{ {
if (xmove > MAXMOVE/2 || ymove > MAXMOVE/2) if (xmove > MAXMOVE/2 || ymove > MAXMOVE/2)
@ -191,15 +199,28 @@ void P_XYMovement (mobj_t* mo)
xmove = ymove = 0; xmove = ymove = 0;
} }
if (!P_TryMove (mo, ptryx, ptryy)) // killough 3/15/98: Allow objects to drop off
if (!P_TryMove (mo, ptryx, ptryy, true))
{ {
// blocked move // blocked move
if (mo->player) if (mo->player)
{ // try to slide along it {
// [RH] Activate any potential special lines
while (numspechit-- > 0)
P_PushSpecialLine (mo,
P_PointOnLineSide (mo->x, mo->y, spechit[numspechit]),
spechit[numspechit]);
// try to slide along it
P_SlideMove (mo); P_SlideMove (mo);
} }
else if (mo->flags & MF_MISSILE) else if (mo->flags & MF_MISSILE)
{ {
// [RH] missiles can activate projectile hit lines, too
if (!olddemo)
while (numspechit > 0)
P_ShootSpecialLine (mo, spechit[--numspechit]);
// explode a missile // explode a missile
if (ceilingline && if (ceilingline &&
ceilingline->backsector && ceilingline->backsector &&
@ -269,20 +290,42 @@ void P_XYMovement (mobj_t* mo)
} }
else else
{ {
mo->momx = FixedMul (mo->momx, FRICTION); // phares 3/17/98
mo->momy = FixedMul (mo->momy, FRICTION); // Friction will have been adjusted by friction thinkers for icy
// or muddy floors. Otherwise it was never touched and
// remained set at ORIG_FRICTION
// phares 9/10/98: reduce bobbing/momentum when on ice & up against wall
if ((oldx == mo->x) && (oldy == mo->y)) // Did you go anywhere?
{ // No. Use original friction. This allows you to not bob so much
// if you're on ice, but keeps enough momentum around to break free
// when you're mildly stuck in a wall.
mo->momx = FixedMul(mo->momx,ORIG_FRICTION);
mo->momy = FixedMul(mo->momy,ORIG_FRICTION);
}
else
{ // Yes. Use stored friction.
mo->momx = FixedMul(mo->momx,mo->friction);
mo->momy = FixedMul(mo->momy,mo->friction);
}
mo->friction = ORIG_FRICTION; // reset to normal for next tic
} }
} }
// //
// P_ZMovement // P_ZMovement
// //
void P_ZMovement (mobj_t* mo) void P_ZMovement (mobj_t *mo)
{ {
fixed_t dist; fixed_t dist;
fixed_t delta; fixed_t delta;
mobj_t *other; mobj_t *other;
fixed_t movez;
if (mo->flags2 & MF2_NOADJUST)
return;
// check for smooth step up // check for smooth step up
if (mo->player && mo->z < mo->floorz) if (mo->player && mo->z < mo->floorz)
{ {
@ -293,14 +336,13 @@ void P_ZMovement (mobj_t* mo)
} }
// adjust height // adjust height
mo->z += mo->momz; mo->z += (movez = mo->momz);
if ( mo->flags & MF_FLOAT if ( mo->flags & MF_FLOAT
&& mo->target) && mo->target)
{ {
// float down towards target if too close // float down towards target if too close
if ( !(mo->flags & MF_SKULLFLY) if ( !(mo->flags & MF_SKULLFLY) && !(mo->flags & MF_INFLOAT) )
&& !(mo->flags & MF_INFLOAT) )
{ {
dist = P_AproxDistance (mo->x - mo->target->x, dist = P_AproxDistance (mo->x - mo->target->x,
mo->y - mo->target->y); mo->y - mo->target->y);
@ -323,7 +365,7 @@ void P_ZMovement (mobj_t* mo)
other = NULL; other = NULL;
} else { } else {
other = P_FindFloor (mo); // [RH] Z-Check other = P_FindFloor (mo); // [RH] Z-Check
if ((mo->flags & MF_MISSILE) && (other == mo->target) && (gametic < (signed)mo->targettic)) if ((mo->flags & MF_MISSILE) && (other == mo->target) && mo->targettic)
other = NULL; other = NULL;
} }
@ -342,48 +384,14 @@ void P_ZMovement (mobj_t* mo)
if (mo->momz < 0) if (mo->momz < 0)
{ {
if (mo->player if (mo->player
&& mo->momz < (fixed_t)(sv_gravity->value * -655.36)) && mo->momz < (fixed_t)(sv_gravity->value * mo->subsector->sector->gravity * -655.36f))
{ {
// [RH] Andy Kempling's fall damage mod.
// (adapted to work with ZDoom)
// calculate the number of broken bones... (joke)
// damage player according to the height fallen.
//
if (dmflags & (DF_YES_FALLING|DF_YES_FALLING_LOTS)) {
fixed_t minvelocity;
fixed_t damage;
float divisor;
if (dmflags & DF_YES_FALLING_LOTS) {
// Original values
minvelocity = -741455*4/3;
divisor = -26214400.0f;
} else {
// Not-quite-so-damaging values
minvelocity = -741455*5/3;
divisor = -39321600.0f;
}
if (mo->momz < minvelocity) {
damage = (fixed_t)((float)(mo->momz) * sv_gravity->value / divisor);
if (other != (mobj_t *)-1) {
// [RH] We landed on another thing. Give half the damage to it.
damage >>= 1;
P_DamageMobj (other, mo, mo, damage, MOD_FALLXFER);
}
if (mo->player) {
// Monsters don't take falling damage
P_DamageMobj(mo, mo, mo, damage, MOD_FALLING);
}
}
}
// Squat down. // Squat down.
// Decrease viewheight for a moment // Decrease viewheight for a moment
// after hitting the ground (hard), // after hitting the ground (hard),
// and utter appropriate sound. // and utter appropriate sound.
mo->player->deltaviewheight = mo->momz>>3; mo->player->deltaviewheight = mo->momz>>3;
S_StartSound (mo, sfx_oof); S_StartSound (mo, "*land1", 96);
} }
mo->momz = 0; mo->momz = 0;
} }
@ -401,15 +409,14 @@ void P_ZMovement (mobj_t* mo)
P_ExplodeMissile (mo); P_ExplodeMissile (mo);
return; return;
} }
P_StandOnThing (mo, other); P_StandOnThing (mo, other);
} }
else if (! (mo->flags & MF_NOGRAVITY) ) else if (! (mo->flags & MF_NOGRAVITY) )
{ {
if (mo->momz == 0) if (mo->momz == 0)
mo->momz = (fixed_t)(sv_gravity->value * -163.84); mo->momz = (fixed_t)(sv_gravity->value * mo->subsector->sector->gravity * -163.84);
else else
mo->momz -= (fixed_t)(sv_gravity->value * 81.92); mo->momz -= (fixed_t)(sv_gravity->value * mo->subsector->sector->gravity * 81.92);
} }
if (olddemo) { if (olddemo) {
@ -419,7 +426,7 @@ void P_ZMovement (mobj_t* mo)
other = NULL; other = NULL;
} else { } else {
other = P_FindCeiling (mo); // [RH] Z-Check other = P_FindCeiling (mo); // [RH] Z-Check
if ((mo->flags & MF_MISSILE) && (other == mo->target) && (gametic < (signed)mo->targettic)) if ((mo->flags & MF_MISSILE) && (other == mo->target) && mo->targettic)
other = NULL; other = NULL;
} }
@ -464,7 +471,7 @@ void P_ZMovement (mobj_t* mo)
// //
// P_NightmareRespawn // P_NightmareRespawn
// //
void P_NightmareRespawn (mobj_t* mobj) void P_NightmareRespawn (mobj_t *mobj)
{ {
fixed_t x; fixed_t x;
fixed_t y; fixed_t y;
@ -488,7 +495,7 @@ void P_NightmareRespawn (mobj_t* mobj)
mobj->y, mobj->y,
0, MT_TFOG, ONFLOORZ); 0, MT_TFOG, ONFLOORZ);
// initiate teleport sound // initiate teleport sound
S_StartSound (mo, sfx_telept); S_StartSound (mo, "misc/teleport", 32);
ss = R_PointInSubsector (x,y); ss = R_PointInSubsector (x,y);
@ -500,7 +507,7 @@ void P_NightmareRespawn (mobj_t* mobj)
mo = P_SpawnMobj (x, y, z, MT_TFOG, onfloor); mo = P_SpawnMobj (x, y, z, MT_TFOG, onfloor);
S_StartSound (mo, sfx_telept); S_StartSound (mo, "misc/teleport", 32);
// spawn the new monster // spawn the new monster
mthing = &mobj->spawnpoint; mthing = &mobj->spawnpoint;
@ -521,15 +528,134 @@ void P_NightmareRespawn (mobj_t* mobj)
} }
//
// [RH] Some new functions to work with Thing IDs. ------->
//
static mobj_t *tidhash[128];
#define TIDHASH(i) ((i)&127)
//
// P_ClearTidHashes
//
// Clears the tid hashtable.
//
void P_ClearTidHashes (void)
{
int i;
for (i = 0; i < 128; i++)
tidhash[i] = NULL;
}
//
// P_AddMobjToHash
//
// Inserts an mobj into the correct chain based on its tid.
// If its tid is 0, this function does nothing.
//
void P_AddMobjToHash (mobj_t *mobj)
{
if (mobj->tid == 0) {
mobj->inext = mobj->iprev = NULL;
return;
} else {
int hash = TIDHASH(mobj->tid);
mobj->inext = tidhash[hash];
mobj->iprev = NULL;
tidhash[hash] = mobj;
}
}
//
// P_RemoveMobjFromHash
//
// Removes an mobj from its hash chain.
//
void P_RemoveMobjFromHash (mobj_t *mobj)
{
if (mobj->tid == 0)
return;
else {
if (mobj->iprev == NULL) {
// First mobj in the chain (probably)
int hash = TIDHASH(mobj->tid);
if (tidhash[hash] == mobj)
tidhash[hash] = mobj->inext;
if (mobj->inext) {
mobj->inext->iprev = NULL;
mobj->inext = NULL;
}
} else {
// Not the first mobj in the chain
mobj->iprev->inext = mobj->inext;
if (mobj->inext) {
mobj->inext->iprev = mobj->iprev;
mobj->inext = NULL;
}
mobj->iprev = NULL;
}
}
}
//
// P_FindMobjByTid
//
// Returns the next mobj with the tid after the one given,
// or the first with that tid if no mobj is passed. Returns
// NULL if there are no more.
//
mobj_t *P_FindMobjByTid (mobj_t *mobj, int tid)
{
// Mobjs without tid are never stored.
if (tid == 0)
return NULL;
if (!mobj)
mobj = tidhash[TIDHASH(tid)];
else
mobj = mobj->inext;
while (mobj && mobj->tid != tid)
mobj = mobj->inext;
return mobj;
}
//
// P_FindGoal
//
// Like P_FindMobjByTid except it also matcheds on type.
//
mobj_t *P_FindGoal (mobj_t *mobj, int tid, int kind)
{
mobj_t *goal;
do {
goal = P_FindMobjByTid (mobj, tid);
} while (goal && goal->type != kind);
return goal;
}
// <------- [RH] End new functions
// //
// P_MobjThinker // P_MobjThinker
// //
void P_MobjThinker (mobj_t* mobj) void P_MobjThinker (mobj_t *mobj)
{ {
if (mobj == (mobj_t *)0x0131E0D8) {
int foo = 50;
}
// [RH] Decrement targettic
if (mobj->targettic)
mobj->targettic--;
// momentum movement // momentum movement
if (mobj->momx if (mobj->momx || mobj->momy || (mobj->flags&MF_SKULLFLY) )
|| mobj->momy
|| (mobj->flags&MF_SKULLFLY) )
{ {
P_XYMovement (mobj); P_XYMovement (mobj);
@ -537,8 +663,7 @@ void P_MobjThinker (mobj_t* mobj)
if (mobj->thinker.function.acv == (actionf_v) (-1)) if (mobj->thinker.function.acv == (actionf_v) (-1))
return; // mobj was removed return; // mobj was removed
} }
if ( (mobj->z != mobj->floorz) if ( (mobj->z != mobj->floorz) || mobj->momz )
|| mobj->momz )
{ {
P_ZMovement (mobj); P_ZMovement (mobj);
@ -547,6 +672,9 @@ void P_MobjThinker (mobj_t* mobj)
return; // mobj was removed return; // mobj was removed
} }
// [RH] Dormant things do no state changes
if (mobj->flags2 & MF2_DORMANT)
return;
// cycle through states, // cycle through states,
// calling action functions at transitions // calling action functions at transitions
@ -581,7 +709,6 @@ void P_MobjThinker (mobj_t* mobj)
P_NightmareRespawn (mobj); P_NightmareRespawn (mobj);
} }
} }
@ -609,6 +736,10 @@ mobj_t *P_SpawnMobj (fixed_t x, fixed_t y, fixed_t z, mobjtype_t type, int onflo
mobj->height = info->height; mobj->height = info->height;
mobj->flags = info->flags; mobj->flags = info->flags;
mobj->health = info->spawnhealth; mobj->health = info->spawnhealth;
if (type == MT_BRIDGE) // [RH] Floating bridge never adjusts its Z-position
mobj->flags2 |= MF2_NOADJUST;
if (mobj->flags & MF_STEALTH) // [RH] Stealth monsters start out invisible
mobj->flags2 |= MF2_INVISIBLE;
if (gameskill->value != sk_nightmare) if (gameskill->value != sk_nightmare)
mobj->reactiontime = info->reactiontime; mobj->reactiontime = info->reactiontime;
@ -637,13 +768,10 @@ mobj_t *P_SpawnMobj (fixed_t x, fixed_t y, fixed_t z, mobjtype_t type, int onflo
else else
mobj->z = z; mobj->z = z;
mobj->thinker.function.acp1 = (actionf_p1)P_MobjThinker; mobj->friction = ORIG_FRICTION; // phares 3/17/98
P_AddThinker (&mobj->thinker);
// [RH] If it's an ambient sound, activate it mobj->thinker.function.acp1 = (actionf_p1)P_MobjThinker;
if (type >= MT_AMBIENT0 && type <= MT_AMBIENT63) P_AddThinker (&mobj->thinker);
S_ActivateAmbient (mobj, type - MT_AMBIENT0);
return mobj; return mobj;
} }
@ -677,6 +805,9 @@ void P_RemoveMobj (mobj_t* mobj)
// unlink from sector and block lists // unlink from sector and block lists
P_UnsetThingPosition (mobj); P_UnsetThingPosition (mobj);
// [RH] Unlink from tid chain
P_RemoveMobjFromHash (mobj);
// Delete all nodes on the current sector_list phares 3/16/98 // Delete all nodes on the current sector_list phares 3/16/98
if (sector_list) if (sector_list)
@ -744,7 +875,7 @@ void P_RespawnSpecials (void)
// spawn a teleport fog at the new spot // spawn a teleport fog at the new spot
ss = R_PointInSubsector (x,y); ss = R_PointInSubsector (x,y);
mo = P_SpawnMobj (x, y, z, MT_IFOG, onfloor); mo = P_SpawnMobj (x, y, z, MT_IFOG, onfloor);
S_StartSound (mo, sfx_itmbk); S_StartSound (mo, "misc/spawn", 100);
// spawn it // spawn it
mo = P_SpawnMobj (x,y,z, i, onfloor); mo = P_SpawnMobj (x,y,z, i, onfloor);
@ -766,50 +897,39 @@ void P_RespawnSpecials (void)
// //
void P_SpawnPlayer (mapthing2_t *mthing) void P_SpawnPlayer (mapthing2_t *mthing)
{ {
int playernum;
player_t *p; player_t *p;
fixed_t x;
fixed_t y;
fixed_t z;
mobj_t *mobj; mobj_t *mobj;
int i; int i;
// not playing? // [RH] Things 4001-? are also multiplayer starts. Just like 1-4.
// [RH] Things 4001-? are also multiplayer starts. // To make things simpler, figure out which player is being
if (mthing->type > 4000) { // spawned here.
if (!playeringame[mthing->type - 4001 + 4]) playernum = (mthing->type > 4000) ? mthing->type - 4001 + 4 : mthing->type - 1;
return;
else {
p = &players[mthing->type - 4001 + 4];
if (p->playerstate == PST_REBORN)
G_PlayerReborn (mthing->type - 4001 + 4);
}
} else {
if (!playeringame[mthing->type-1])
return;
else {
p = &players[mthing->type-1];
if (p->playerstate == PST_REBORN)
G_PlayerReborn (mthing->type - 1);
}
}
x = mthing->x << FRACBITS; // not playing?
y = mthing->y << FRACBITS; if (playernum >= MAXPLAYERS || !playeringame[playernum])
z = mthing->z << FRACBITS; return;
mobj = P_SpawnMobj (x,y,z, MT_PLAYER, ONFLOORZ);
p = &players[playernum];
if (p->playerstate == PST_REBORN)
G_PlayerReborn (playernum);
mobj = P_SpawnMobj (mthing->x << FRACBITS, mthing->y << FRACBITS, 0, MT_PLAYER, ONFLOORZ);
// set color translations for player sprites // set color translations for player sprites
// [RH] Different now: MF_TRANSLATION is not used. // [RH] Different now: MF_TRANSLATION is not used.
mobj->palette = (struct palette_s *)(translationtables + (mthing->type-1)*256); mobj->palette = (struct palette_s *)(translationtables + 256*playernum);
mobj->angle = ANG45 * (mthing->angle/45); mobj->angle = ANG45 * (mthing->angle/45);
mobj->pitch = mobj->roll = 0; mobj->pitch = mobj->roll = 0;
mobj->player = p; mobj->player = p;
mobj->health = p->health; mobj->health = p->health;
p->mo = mobj; // [RH] Set player sprite based on skin
mobj->sprite = skins[p->userinfo.skin].sprite;
p->camera = p->mo = mobj; // [RH]
p->playerstate = PST_LIVE; p->playerstate = PST_LIVE;
p->refire = 0; p->refire = 0;
p->message = NULL; p->message = NULL;
@ -827,14 +947,17 @@ void P_SpawnPlayer (mapthing2_t *mthing)
for (i=0 ; i<NUMCARDS ; i++) for (i=0 ; i<NUMCARDS ; i++)
p->cards[i] = true; p->cards[i] = true;
if (consoleplayer == if (consoleplayer == playernum)
(mthing->type > 4000 ? mthing->type - 4001 + 4 : mthing->type - 1))
{ {
// wake up the status bar // wake up the status bar
ST_Start (); ST_Start ();
// wake up the heads up text // wake up the heads up text
HU_Start (); HU_Start ();
} }
// [RH] If someone is in the way, kill them
if (!olddemo)
P_TeleportMove (mobj, mobj->x, mobj->y, mobj->z, true);
} }
@ -843,7 +966,8 @@ void P_SpawnPlayer (mapthing2_t *mthing)
// The fields of the mapthing should // The fields of the mapthing should
// already be in host byte order. // already be in host byte order.
// //
void P_SpawnMapThing (mapthing2_t *mthing) // [RH] position is used to weed out unwanted start spots
void P_SpawnMapThing (mapthing2_t *mthing, int position)
{ {
int i; int i;
int bit; int bit;
@ -858,7 +982,7 @@ void P_SpawnMapThing (mapthing2_t *mthing)
{ {
if (deathmatch_p == &deathmatchstarts[MaxDeathmatchStarts]) { if (deathmatch_p == &deathmatchstarts[MaxDeathmatchStarts]) {
// [RH] Get more deathmatchstarts // [RH] Get more deathmatchstarts
MaxDeathmatchStarts += 8; MaxDeathmatchStarts *= 2;
deathmatchstarts = Realloc (deathmatchstarts, MaxDeathmatchStarts * sizeof(mapthing2_t)); deathmatchstarts = Realloc (deathmatchstarts, MaxDeathmatchStarts * sizeof(mapthing2_t));
deathmatch_p = &deathmatchstarts[MaxDeathmatchStarts - 8]; deathmatch_p = &deathmatchstarts[MaxDeathmatchStarts - 8];
} }
@ -870,6 +994,10 @@ void P_SpawnMapThing (mapthing2_t *mthing)
// check for players specially // check for players specially
if (mthing->type <= 4 && mthing->type > 0) if (mthing->type <= 4 && mthing->type > 0)
{ {
// [RH] Only spawn spots that match position.
if (mthing->args[0] != position)
return;
// save spots for respawning in network games // save spots for respawning in network games
playerstarts[mthing->type-1] = *mthing; playerstarts[mthing->type-1] = *mthing;
if (!deathmatch->value) if (!deathmatch->value)
@ -878,6 +1006,11 @@ void P_SpawnMapThing (mapthing2_t *mthing)
return; return;
} else if (mthing->type >= 4001 && mthing->type <= 4001 + MAXPLAYERS - 4) { } else if (mthing->type >= 4001 && mthing->type <= 4001 + MAXPLAYERS - 4) {
// [RH] Multiplayer starts for players 5-? // [RH] Multiplayer starts for players 5-?
// [RH] Only spawn spots that match position.
if (mthing->args[0] != position)
return;
playerstarts[mthing->type - 4001 + 4] = *mthing; playerstarts[mthing->type - 4001 + 4] = *mthing;
if (!deathmatch->value) if (!deathmatch->value)
P_SpawnPlayer (mthing); P_SpawnPlayer (mthing);
@ -892,8 +1025,10 @@ void P_SpawnMapThing (mapthing2_t *mthing)
if (!(mthing->flags & MTF_COOPERATIVE)) if (!(mthing->flags & MTF_COOPERATIVE))
return; return;
} }
} else if (!(mthing->flags & MTF_SINGLE)) } else {
return; if (!(mthing->flags & MTF_SINGLE))
return;
}
// check for apropriate skill level // check for apropriate skill level
if (gameskill->value == sk_baby) if (gameskill->value == sk_baby)
@ -906,10 +1041,18 @@ void P_SpawnMapThing (mapthing2_t *mthing)
if (!(mthing->flags & bit) ) if (!(mthing->flags & bit) )
return; return;
// find which type to spawn // [RH] Determine if it is an old ambient thing, and if so,
for (i=0 ; i< NUMMOBJTYPES ; i++) // map it to MT_AMBIENT with the proper parameter.
if (mthing->type == mobjinfo[i].doomednum) if (mthing->type >= 14001 && mthing->type <= 14064) {
break; mthing->args[0] = mthing->type - 14000;
mthing->type = 14065;
i = MT_AMBIENT;
} else {
// find which type to spawn
for (i=0 ; i< NUMMOBJTYPES ; i++)
if (mthing->type == mobjinfo[i].doomednum)
break;
}
if (i==NUMMOBJTYPES) { if (i==NUMMOBJTYPES) {
// [RH] Don't die if the map tries to spawn an unknown thing // [RH] Don't die if the map tries to spawn an unknown thing
@ -994,6 +1137,14 @@ void P_SpawnMapThing (mapthing2_t *mthing)
mobj = P_SpawnMobj (x,y,z, i, onfloor); mobj = P_SpawnMobj (x,y,z, i, onfloor);
mobj->spawnpoint = *mthing; mobj->spawnpoint = *mthing;
// [RH] Set the thing's special
mobj->special = mthing->special;
memcpy (mobj->args, mthing->args, sizeof(mobj->args));
// [RH] If it's an ambient sound, activate it
if (i == MT_AMBIENT)
S_ActivateAmbient (mobj, mobj->args[0]);
if (mobj->tics > 0) if (mobj->tics > 0)
mobj->tics = 1 + (P_Random (pr_spawnmapthing) % mobj->tics); mobj->tics = 1 + (P_Random (pr_spawnmapthing) % mobj->tics);
if (mobj->flags & MF_COUNTKILL) if (mobj->flags & MF_COUNTKILL)
@ -1004,6 +1155,14 @@ void P_SpawnMapThing (mapthing2_t *mthing)
mobj->angle = ANG45 * (mthing->angle/45); mobj->angle = ANG45 * (mthing->angle/45);
if (mthing->flags & MTF_AMBUSH) if (mthing->flags & MTF_AMBUSH)
mobj->flags |= MF_AMBUSH; mobj->flags |= MF_AMBUSH;
// [RH] Add ThingID to mobj and link it in with the others
mobj->tid = mthing->thingid;
P_AddMobjToHash (mobj);
// [RH] Go dormant as needed
if (mthing->flags & MTF_DORMANT)
P_DeactivateMobj (mobj);
} }
@ -1043,8 +1202,7 @@ void P_SpawnPuff (fixed_t x, fixed_t y, fixed_t z)
// //
// P_SpawnBlood // P_SpawnBlood
// //
void void P_SpawnBlood (fixed_t x, fixed_t y, fixed_t z, int damage)
P_SpawnBlood (fixed_t x, fixed_t y, fixed_t z, int damage)
{ {
mobj_t *th; mobj_t *th;
int t; int t;
@ -1077,8 +1235,9 @@ void P_CheckMissileSpawn (mobj_t* th)
if (th->tics < 1) if (th->tics < 1)
th->tics = 1; th->tics = 1;
// Give the missile time to get away from the shooter // [RH] Give the missile time to get away from the shooter
th->targettic = gametic + 10; if (!olddemo)
th->targettic = 10;
// move a little forward so an angle can // move a little forward so an angle can
// be computed if it immediately explodes // be computed if it immediately explodes
@ -1086,9 +1245,10 @@ void P_CheckMissileSpawn (mobj_t* th)
th->y += th->momy>>1; th->y += th->momy>>1;
th->z += th->momz>>1; th->z += th->momz>>1;
if (!P_TryMove (th, th->x, th->y)) { // killough 3/15/98: no dropoff (really = don't care for missiles)
if (!P_TryMove (th, th->x, th->y, false))
P_ExplodeMissile (th); P_ExplodeMissile (th);
}
} }
@ -1106,7 +1266,7 @@ mobj_t *P_SpawnMissile (mobj_t *source, mobj_t *dest, mobjtype_t type)
source->z + 4*8*FRACUNIT, type, 0); source->z + 4*8*FRACUNIT, type, 0);
if (th->info->seesound) if (th->info->seesound)
S_StartSound (th, th->info->seesound); S_StartSound (th, th->info->seesound, 70);
th->target = source; // where it came from th->target = source; // where it came from
an = R_PointToAngle2 (source->x, source->y, dest->x, dest->y); an = R_PointToAngle2 (source->x, source->y, dest->x, dest->y);
@ -1178,7 +1338,7 @@ void P_SpawnPlayerMissile (mobj_t *source, mobjtype_t type)
if (linetarget && source->player) if (linetarget && source->player)
if (!(dmflags & DF_NO_FREELOOK) if (!(dmflags & DF_NO_FREELOOK)
&& abs(slope - pitchslope) > source->player->userinfo->aimdist) { && abs(slope - pitchslope) > source->player->userinfo.aimdist) {
an = source->angle; an = source->angle;
slope = pitchslope; slope = pitchslope;
} }
@ -1190,7 +1350,7 @@ void P_SpawnPlayerMissile (mobj_t *source, mobjtype_t type)
th = P_SpawnMobj (x,y,z, type, 0); th = P_SpawnMobj (x,y,z, type, 0);
if (th->info->seesound) if (th->info->seesound)
S_StartSound (th, th->info->seesound); S_StartSound (th, th->info->seesound, 70);
th->target = source; th->target = source;
th->angle = an; th->angle = an;

View file

@ -207,6 +207,40 @@ typedef enum
MF_TRANSLUC50 = 0x40000000, MF_TRANSLUC50 = 0x40000000,
MF_TRANSLUC75 = 0x60000000, MF_TRANSLUC75 = 0x60000000,
// [RH] These are all based on Hexen's. Very few are used.
MF2_LOWGRAVITY = 0x00000001,
MF2_BLOWN = 0x00000002,
MF2_BOUNCES = 0x00000004,
MF2_PROJECTILEPUSH = 0x00000008,
MF2_DROPUP = 0x00000010,
MF2_INLIQUID = 0x00000020,
MF2_STARTONFLOOR = 0x00000040,
MF2_NOTELEPORT = 0x00000080,
MF2_PIERCING = 0x00000100,
MF2_PUSHABLE = 0x00000200,
MF2_DONTHURTPLAYERS = 0x00000400,
MF2_NOADJUST = 0x00000800,
MF2_POTSOMETHING = 0x00001000,
MF2_PARTICLE = 0x00002000,
MF2_DORMANT = 0x00004000,
MF2_BOSS = 0x00008000,
MF2_XDEATHONLY = 0x00010000,
MF2_DOESNOTPUSH = 0x00020000,
MF2_TELEFRAGS = 0x00040000,
MF2_BOB = 0x00080000,
MF2_INVISIBLE = 0x00100000,
MF2_ACTIVATEIMPACT = 0x00200000,
MF2_JUMPING = 0x00400000,
MF2_ACTIVATEMCROSS = 0x00800000,
MF2_ACTIVATEPCROSS = 0x01000000,
MF2_PASSPROJECTILES = 0x02000000,
MF2_STALKERSOMETHING= 0x04000000,
MF2_INVULNERABLE = 0x08000000,
MF2_INDESTRUCTABLE = 0x10000000,
MF2_ICYDEATH = 0x20000000,
MF2_HOMINGSOMETHING = 0x40000000,
MF2_REFLECTIVE = 0x80000000
} mobjflag_t; } mobjflag_t;
@ -221,6 +255,10 @@ typedef struct mobj_s
fixed_t y; fixed_t y;
fixed_t z; fixed_t z;
int tid; // [RH] Thing ID
struct mobj_s* inext; // [RH] links to other mobjs whose
struct mobj_s* iprev; // tid hash to the same value.
// More list: links in sector (if needed) // More list: links in sector (if needed)
struct mobj_s* snext; struct mobj_s* snext;
struct mobj_s* sprev; struct mobj_s* sprev;
@ -261,6 +299,7 @@ typedef struct mobj_s
int tics; // state tic counter int tics; // state tic counter
state_t* state; state_t* state;
int flags; int flags;
int flags2; // [RH] more flags
int health; int health;
// Movement direction, movement generation (zig-zagging). // Movement direction, movement generation (zig-zagging).
@ -273,7 +312,7 @@ typedef struct mobj_s
// Reaction time: if non 0, don't attack yet. // Reaction time: if non 0, don't attack yet.
// Used by player to freeze a bit after teleporting. // Used by player to freeze a bit after teleporting.
int reactiontime; int reactiontime;
// If >0, the target will be chased // If >0, the target will be chased
// no matter what (even if shot) // no matter what (even if shot)
@ -292,11 +331,14 @@ typedef struct mobj_s
// Thing being chased/attacked for tracers. // Thing being chased/attacked for tracers.
struct mobj_s* tracer; struct mobj_s* tracer;
// [RH] Andy Baker's stealth monsters // new field: last known enemy -- killough 2/15/98
BOOL invisible; struct mobj_s* lastenemy;
// [RH] The goal this monster is moving toward (if target is NULL)
struct mobj_s* goal;
// [RH] Z-Check // [RH] Z-Check
// Gametic when a missile will be able to impact // Time until a missile will be able to impact
// whoever shot it. Used to prevent the missile // whoever shot it. Used to prevent the missile
// from blowing up in the shooter's face before // from blowing up in the shooter's face before
// it gets anywhere. // it gets anywhere.
@ -308,8 +350,16 @@ typedef struct mobj_s
// than a full-fledged palette. // than a full-fledged palette.
struct palette_s *palette; struct palette_s *palette;
// a linked list of sectors where this object appears // Friction values for the sector the object is in
struct msecnode_s *touching_sectorlist; // phares 3/14/98 int friction; // phares 3/17/98
int movefactor;
// a linked list of sectors where this object appears
struct msecnode_s *touching_sectorlist; // phares 3/14/98
// [RH] Thing special
byte special;
byte args[5];
} mobj_t; } mobj_t;

399
code/P_plats.c Normal file
View file

@ -0,0 +1,399 @@
// Emacs style mode select -*- C++ -*-
//-----------------------------------------------------------------------------
//
// $Id:$
//
// Copyright (C) 1993-1996 by id Software, Inc.
//
// This source is available for distribution and/or modification
// only under the terms of the DOOM Source Code License as
// published by id Software. All rights reserved.
//
// The source is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
// for more details.
//
// $Log:$
//
// DESCRIPTION:
// Plats (i.e. elevator platforms) code, raising/lowering.
//
//-----------------------------------------------------------------------------
#include "m_alloc.h"
#include "i_system.h"
#include "z_zone.h"
#include "m_random.h"
#include "doomdef.h"
#include "p_local.h"
#include "s_sound.h"
// State.
#include "doomstat.h"
#include "r_state.h"
// [RH] Active plats are now linked together in a list instead of
// stored in an array. Similar to what Lee Killough did with
// BOOM except I link the plats themselves together.
plat_t *activeplats;
//
// Move a plat up and down
//
void T_PlatRaise(plat_t* plat)
{
result_e res;
switch (plat->status)
{
case up:
res = T_MovePlane(plat->sector,
plat->speed,
plat->high,
plat->crush,0,1);
if (plat->type == platUpByValueStay
|| plat->type == platRaiseAndStay)
{
if (!(level.time&7))
S_StartSound((mobj_t *)&plat->sector->soundorg, "plats/pt1_mid", 119);
}
if (res == crushed && (!plat->crush))
{
plat->count = plat->wait;
plat->status = down;
S_StartSound((mobj_t *)&plat->sector->soundorg, "plats/pt1_strt", 100);
}
else
{
if (res == pastdest)
{
if (plat->type != platToggle) {
plat->count = plat->wait;
plat->status = waiting;
S_StartSound((mobj_t *)&plat->sector->soundorg, "plats/pt1_stop", 100);
switch(plat->type)
{
case platDownWaitUpStay:
case platRaiseAndStay:
case platUpByValueStay:
case platDownToNearestFloor:
case platDownToLowestCeiling:
P_RemoveActivePlat(plat);
break;
default:
break;
}
} else {
plat->oldstatus = plat->status;//jff 3/14/98 after action wait
plat->status = in_stasis; //for reactivation of toggle
}
}
}
break;
case down:
res = T_MovePlane (plat->sector, plat->speed, plat->low, -1, 0, -1);
if (res == pastdest)
{
// if not an instant toggle, start waiting, make plat stop sound
if (plat->type != platToggle) //jff 3/14/98 toggle up down
{ // is silent, instant, no waiting
plat->count = plat->wait;
plat->status = waiting;
S_StartSound((mobj_t *)&plat->sector->soundorg, "plats/pt1_stop", 100);
switch (plat->type) {
case platUpWaitDownStay:
case platUpByValue:
P_RemoveActivePlat (plat);
break;
default:
break;
}
} else { // instant toggles go into stasis awaiting next activation
plat->oldstatus = plat->status; //jff 3/14/98 after action wait
plat->status = in_stasis; //for reactivation of toggle
}
}
//jff 1/26/98 remove the plat if it bounced so it can be tried again
//only affects plats that raise and bounce
//killough 1/31/98: relax compatibility to demo_compatibility
// remove the plat if it's a pure raise type
if (!olddemo)
{
switch (plat->type)
{
case platUpByValueStay:
case platRaiseAndStay:
P_RemoveActivePlat(plat);
default:
break;
}
}
break;
case waiting:
if (!--plat->count)
{
if (plat->sector->floorheight == plat->low)
plat->status = up;
else
plat->status = down;
S_StartSound((mobj_t *)&plat->sector->soundorg, "plats/pt1_strt", 100);
}
break;
case in_stasis:
break;
}
}
//
// Do Platforms
// [RH] Changed amount to height and added delay,
// lip, change, tag, and speed parameters.
//
BOOL EV_DoPlat (int tag, line_t *line, plattype_e type, int height,
int speed, int delay, int lip, int change)
{
plat_t* plat;
int secnum;
sector_t *sec;
int rtn = false;
BOOL manual = false;
// [RH] If tag is zero, use the sector on the back side
// of the activating line (if any).
if (!tag && !olddemo) {
if (!line || !(sec = line->backsector))
return false;
secnum = sec - sectors;
manual = true;
goto manual_plat;
}
// Activate all <type> plats that are in_stasis
switch (type)
{
case platToggle:
rtn = true;
case platPerpetualRaise:
P_ActivateInStasis (tag);
break;
default:
break;
}
secnum = -1;
while ((secnum = P_FindSectorFromTag (tag, secnum)) >= 0)
{
sec = &sectors[secnum];
manual_plat:
if (P_SectorActive (floor_special, sec)) //jff 2/23/98 multiple thinkers
continue;
// Find lowest & highest floors around sector
rtn = true;
plat = Z_Malloc( sizeof(*plat), PU_LEVSPEC, 0);
P_AddThinker(&plat->thinker);
plat->type = type;
plat->sector = sec;
plat->sector->floordata = plat; //jff 2/23/98 multiple thinkers
plat->thinker.function.acp1 = (actionf_p1) T_PlatRaise;
plat->crush = -1;
plat->tag = tag;
plat->speed = speed;
plat->wait = delay;
//jff 1/26/98 Avoid raise plat bouncing a head off a ceiling and then
//going down forever -- default low to plat height when triggered
plat->low = sec->floorheight;
if (change) {
if (line)
sec->floorpic = sides[line->sidenum[0]].sector->floorpic;
if (change == 1)
sec->special = 0; // Stop damage and other stuff, if any
}
switch (type)
{
case platRaiseAndStay:
plat->high = P_FindNextHighestFloor (sec, sec->floorheight);
plat->status = up;
S_StartSound ((mobj_t *)&sec->soundorg, "plats/pt1_mid", 119);
break;
case platUpByValue:
case platUpByValueStay:
plat->high = sec->floorheight + height;
plat->status = up;
S_StartSound ((mobj_t *)&sec->soundorg, "plats/pt1_mid", 119);
break;
case platDownByValue:
plat->low = sec->floorheight - height;
plat->status = down;
S_StartSound ((mobj_t *)&sec->soundorg, "plats/pt1_mid", 119);
break;
case platDownWaitUpStay:
plat->low = P_FindLowestFloorSurrounding (sec) + lip*FRACUNIT;
if (plat->low > sec->floorheight)
plat->low = sec->floorheight;
plat->high = sec->floorheight;
plat->status = down;
S_StartSound ((mobj_t *)&sec->soundorg, "plats/pt1_strt", 100);
break;
case platUpWaitDownStay:
plat->high = P_FindHighestFloorSurrounding (sec);
if (plat->high < sec->floorheight)
plat->high = sec->floorheight;
plat->status = up;
S_StartSound ((mobj_t *)&sec->soundorg, "plats/pt1_strt", 100);
break;
case platPerpetualRaise:
plat->low = P_FindLowestFloorSurrounding (sec) + lip*FRACUNIT;
if (plat->low > sec->floorheight)
plat->low = sec->floorheight;
plat->high = P_FindHighestFloorSurrounding (sec);
if (plat->high < sec->floorheight)
plat->high = sec->floorheight;
plat->status = P_Random (pr_doplat) & 1;
S_StartSound((mobj_t *)&sec->soundorg, "plats/pt1_strt", 100);
break;
case platToggle: //jff 3/14/98 add new type to support instant toggle
plat->crush = 10; //jff 3/14/98 crush anything in the way
// set up toggling between ceiling, floor inclusive
plat->low = sec->ceilingheight;
plat->high = sec->floorheight;
plat->status = down;
break;
case platDownToNearestFloor:
plat->low = P_FindNextLowestFloor (sec, sec->floorheight) + lip*FRACUNIT;
plat->status = down;
plat->high = sec->floorheight;
S_StartSound((mobj_t *)&sec->soundorg, "plats/pt1_strt", 100);
break;
case platDownToLowestCeiling:
plat->low = P_FindLowestCeilingSurrounding(sec);
plat->high = sec->floorheight;
if (plat->low > sec->floorheight)
plat->low = sec->floorheight;
plat->status = down;
S_StartSound((mobj_t *)&sec->soundorg, "plats/pt1_strt", 100);
break;
default:
break;
}
P_AddActivePlat (plat);
if (manual)
return rtn;
}
return rtn;
}
// [RH] Rewritten to use list
void P_ActivateInStasis (int tag)
{
plat_t *scan = activeplats;
while (scan) {
if (scan->tag == tag && scan->status == in_stasis) {
if (scan->type == platToggle) //jff 3/14/98 reactivate toggle type
scan->status = scan->oldstatus == up ? down : up;
else
scan->status = scan->oldstatus;
scan->thinker.function.acp1 = (actionf_p1) T_PlatRaise;
}
scan = scan->next;
}
}
// [RH] Passed a tag instead of a line and rewritten to use list
void EV_StopPlat (int tag)
{
plat_t *scan = activeplats;
while (scan) {
if (scan->status != in_stasis && scan->tag == tag) {
scan->oldstatus = scan->status;
scan->status = in_stasis;
scan->thinker.function.acv = (actionf_v)NULL;
}
}
}
// [RH] Rewritten to use list
void P_AddActivePlat (plat_t *plat)
{
if (activeplats)
activeplats->prev = plat;
plat->next = activeplats;
plat->prev = NULL;
activeplats = plat;
}
// [RH] Rewritten to use list
void P_RemoveActivePlat (plat_t *plat)
{
plat_t *scan = activeplats;
while (scan) {
if (scan == plat) {
scan->sector->floordata = NULL;
if (scan == activeplats) {
activeplats = scan->next;
} else {
if (scan->prev)
scan->prev->next = scan->next;
if (scan->next)
scan->next->prev = scan->prev;
}
P_RemoveThinker (&scan->thinker);
break;
}
scan = scan->next;
}
}

View file

@ -37,9 +37,6 @@
// State. // State.
#include "doomstat.h" #include "doomstat.h"
// Data.
#include "sounds.h"
#include "p_pspr.h" #include "p_pspr.h"
#define LOWERSPEED FRACUNIT*6 #define LOWERSPEED FRACUNIT*6
@ -137,7 +134,7 @@ void P_BringUpWeapon (player_t *player)
player->pendingweapon = player->readyweapon; player->pendingweapon = player->readyweapon;
if (player->pendingweapon == wp_chainsaw) if (player->pendingweapon == wp_chainsaw)
S_StartSound (player->mo, sfx_sawup); S_StartSound (player->mo, "weapons/sawup", 64);
newstate = weaponinfo[player->pendingweapon].upstate; newstate = weaponinfo[player->pendingweapon].upstate;
@ -161,7 +158,7 @@ BOOL P_CheckAmmo (player_t *player)
// Minimal amount for one shot varies. // Minimal amount for one shot varies.
if (player->readyweapon == wp_bfg) if (player->readyweapon == wp_bfg)
count = deh_BFGCells; count = deh.BFGCells;
else if (player->readyweapon == wp_supershotgun) else if (player->readyweapon == wp_supershotgun)
count = 2; // Double barrel. count = 2; // Double barrel.
else else
@ -287,7 +284,7 @@ void A_WeaponReady (player_t *player, pspdef_t *psp)
if (player->readyweapon == wp_chainsaw if (player->readyweapon == wp_chainsaw
&& psp->state == &states[S_SAW]) && psp->state == &states[S_SAW])
{ {
S_StartSound (player->mo, sfx_sawidl); S_StartSound (player->mo, "weapons/sawidle", 118);
} }
// check for change // check for change
@ -463,7 +460,7 @@ void A_Punch (player_t *player, pspdef_t *psp)
// turn to face target // turn to face target
if (linetarget) if (linetarget)
{ {
S_StartSound (player->mo, sfx_punch); S_StartSound (player->mo, "*fist", 64);
player->mo->angle = R_PointToAngle2 (player->mo->x, player->mo->angle = R_PointToAngle2 (player->mo->x,
player->mo->y, player->mo->y,
linetarget->x, linetarget->x,
@ -493,10 +490,10 @@ void A_Saw (player_t *player, pspdef_t *psp)
if (!linetarget) if (!linetarget)
{ {
S_StartSound (player->mo, sfx_sawful); S_StartSound (player->mo, "weapons/sawfull", 64);
return; return;
} }
S_StartSound (player->mo, sfx_sawhit); S_StartSound (player->mo, "weapons/sawhit", 64);
// turn to face target // turn to face target
angle = R_PointToAngle2 (player->mo->x, player->mo->y, angle = R_PointToAngle2 (player->mo->x, player->mo->y,
@ -534,11 +531,24 @@ void A_FireMissile (player_t *player, pspdef_t *psp)
// //
// A_FireBFG // A_FireBFG
// //
cvar_t *nobfgaim;
void A_FireBFG (player_t *player, pspdef_t *psp) void A_FireBFG (player_t *player, pspdef_t *psp)
{ {
// [RH] bfg can be forced to not use freeaim
fixed_t storedpitch = player->mo->pitch;
int storedaimdist = player->userinfo.aimdist;
if (!(dmflags & DF_INFINITE_AMMO)) if (!(dmflags & DF_INFINITE_AMMO))
player->ammo[weaponinfo[player->readyweapon].ammo] -= deh_BFGCells; player->ammo[weaponinfo[player->readyweapon].ammo] -= deh.BFGCells;
if (nobfgaim->value) {
player->mo->pitch = 0;
player->userinfo.aimdist = 81920000;
}
P_SpawnPlayerMissile (player->mo, MT_BFG); P_SpawnPlayerMissile (player->mo, MT_BFG);
player->mo->pitch = storedpitch;
player->userinfo.aimdist = storedaimdist;
} }
@ -596,7 +606,7 @@ void P_BulletSlope (mobj_t *mo)
} }
if (linetarget && mo->player) if (linetarget && mo->player)
if (!(dmflags & DF_NO_FREELOOK) if (!(dmflags & DF_NO_FREELOOK)
&& abs(bulletslope - pitchslope) > mo->player->userinfo->aimdist) { && abs(bulletslope - pitchslope) > mo->player->userinfo.aimdist) {
bulletslope = pitchslope; bulletslope = pitchslope;
an = mo->angle; an = mo->angle;
} }
@ -626,12 +636,9 @@ void P_GunShot (mobj_t *mo, BOOL accurate)
// //
// A_FirePistol // A_FirePistol
// //
void void A_FirePistol (player_t *player, pspdef_t *psp)
A_FirePistol
( player_t* player,
pspdef_t* psp )
{ {
S_StartSound (player->mo, sfx_pistol); S_StartSound (player->mo, "weapons/pistol", 64);
P_SetMobjState (player->mo, S_PLAY_ATK2); P_SetMobjState (player->mo, S_PLAY_ATK2);
if (!(dmflags & DF_INFINITE_AMMO)) if (!(dmflags & DF_INFINITE_AMMO))
@ -649,14 +656,11 @@ A_FirePistol
// //
// A_FireShotgun // A_FireShotgun
// //
void void A_FireShotgun (player_t *player, pspdef_t *psp)
A_FireShotgun
( player_t* player,
pspdef_t* psp )
{ {
int i; int i;
S_StartSound (player->mo, sfx_shotgn); S_StartSound (player->mo, "weapons/shotgf", 64);
P_SetMobjState (player->mo, S_PLAY_ATK2); P_SetMobjState (player->mo, S_PLAY_ATK2);
if (!(dmflags & DF_INFINITE_AMMO)) if (!(dmflags & DF_INFINITE_AMMO))
@ -677,10 +681,7 @@ A_FireShotgun
// //
// A_FireShotgun2 // A_FireShotgun2
// //
void void A_FireShotgun2 (player_t *player, pspdef_t *psp)
A_FireShotgun2
( player_t* player,
pspdef_t* psp )
{ {
int i; int i;
angle_t angle; angle_t angle;
@ -688,7 +689,7 @@ A_FireShotgun2
int t; int t;
S_StartSound (player->mo, sfx_dshtgn); S_StartSound (player->mo, "weapons/sshotf", 64);
P_SetMobjState (player->mo, S_PLAY_ATK2); P_SetMobjState (player->mo, S_PLAY_ATK2);
if (!(dmflags & DF_INFINITE_AMMO)) if (!(dmflags & DF_INFINITE_AMMO))
@ -718,12 +719,9 @@ A_FireShotgun2
// //
// A_FireCGun // A_FireCGun
// //
void void A_FireCGun (player_t *player, pspdef_t *psp)
A_FireCGun
( player_t* player,
pspdef_t* psp )
{ {
S_StartSound (player->mo, sfx_pistol); S_StartSound (player->mo, "weapons/chngun", 64);
if (!player->ammo[weaponinfo[player->readyweapon].ammo]) if (!player->ammo[weaponinfo[player->readyweapon].ammo])
return; return;
@ -768,14 +766,14 @@ void A_Light2 (player_t *player, pspdef_t *psp)
// A_BFGSpray // A_BFGSpray
// Spawn a BFG explosion on every monster in view // Spawn a BFG explosion on every monster in view
// //
void A_BFGSpray (mobj_t* mo) void A_BFGSpray (mobj_t *mo)
{ {
int i; int i;
int j; int j;
int damage; int damage;
angle_t an; angle_t an;
// [RH] Needed for The New Breed // [RH] Don't crash if no target
if (!mo->target) if (!mo->target)
return; return;
@ -809,12 +807,9 @@ void A_BFGSpray (mobj_t* mo)
// //
// A_BFGsound // A_BFGsound
// //
void void A_BFGsound (player_t *player, pspdef_t *psp)
A_BFGsound
( player_t* player,
pspdef_t* psp )
{ {
S_StartSound (player->mo, sfx_bfg); S_StartSound (player->mo, "weapons/bfgf", 64);
} }

File diff suppressed because it is too large Load diff

View file

@ -32,15 +32,24 @@ void P_UnArchivePlayers (void);
void P_ArchiveWorld (void); void P_ArchiveWorld (void);
void P_UnArchiveWorld (void); void P_UnArchiveWorld (void);
void P_ArchiveThinkers (void); void P_ArchiveThinkers (void);
void P_UnArchiveThinkers (void); void P_UnArchiveThinkers (BOOL keepPlayers); // [RH] added parameter
void P_ArchiveSpecials (void); void P_ArchiveSpecials (void);
void P_UnArchiveSpecials (void); void P_UnArchiveSpecials (void);
void P_ArchiveRNGState (void); // [RH] void P_ArchiveRNGState (void); // [RH]
void P_UnArchiveRNGState (void); // [RH] void P_UnArchiveRNGState (void); // [RH]
void P_ArchiveLevelLocals (void); // [RH] void P_ArchiveScripts (void); // [RH]
void P_UnArchiveLevelLocals (void); // [RH] void P_UnArchiveScripts (void); // [RH]
void P_ArchiveACSDefereds (void); // [RH]
void P_UnArchiveACSDefereds (void); // [RH]
extern byte *save_p; extern byte *save_p, *savebuffer;
extern size_t savegamesize;
void CheckSaveGame (size_t); // killough
// Pads save_p to a 4-byte boundary
// so that the load/save works on SGI&Gecko.
#define PADSAVEP() save_p += (4 - ((int) save_p & 3)) & 3
#endif #endif

File diff suppressed because it is too large Load diff

View file

@ -27,6 +27,7 @@
#include "i_system.h" #include "i_system.h"
#include "p_local.h" #include "p_local.h"
#include "m_random.h" #include "m_random.h"
#include "m_bbox.h"
// State. // State.
#include "r_state.h" #include "r_state.h"
@ -34,63 +35,41 @@
// //
// P_CheckSight // P_CheckSight
// //
fixed_t sightzstart; // eye z of looker // killough 4/19/98:
fixed_t topslope; // Convert LOS info to struct for reentrancy and efficiency of data locality
fixed_t bottomslope; // slopes to top and bottom of target
divline_t strace; // from t1 to t2 typedef struct {
fixed_t t2x; fixed_t sightzstart; // eye z of looker
fixed_t t2y; fixed_t t2x, t2y;
divline_t strace; // from t1 to t2
int sightcounts[2]; fixed_t topslope, bottomslope; // slopes to top and bottom of target
fixed_t bbox[4];
} los_t;
// //
// P_DivlineSide // P_DivlineSide
// Returns side 0 (front), 1 (back), or 2 (on). // Returns side 0 (front), 1 (back), or 2 (on).
// //
int P_DivlineSide (const fixed_t x, const fixed_t y, const divline_t *node) static int P_DivlineSide (const fixed_t x, const fixed_t y, const divline_t *node)
{ {
fixed_t dx;
fixed_t dy;
fixed_t left;
fixed_t right;
if (!node->dx) if (!node->dx)
{ {
if (x==node->x) return (x==node->x) ? 2 : ((x < node->x) ? node->dy > 0 : node->dy < 0);
return 2;
if (x <= node->x)
return node->dy > 0;
return node->dy < 0;
} }
else if (!node->dy)
if (!node->dy)
{ {
return (y==node->y) ? 2 : ((y < node->y) ? node->dx < 0 : node->dx > 0);
// ^^^^^^^^^^^^
// [RH] Original code was (x==node->y), but that's obviously not right. // [RH] Original code was (x==node->y), but that's obviously not right.
if (y==node->y)
return 2;
if (y <= node->y)
return node->dx < 0;
return node->dx > 0;
} }
else
dx = (x - node->x); {
dy = (y - node->y); fixed_t left = (node->dy>>FRACBITS) * ((x - node->x)>>FRACBITS);
fixed_t right = ((y - node->y)>>FRACBITS) * (node->dx>>FRACBITS);
left = (node->dy>>FRACBITS) * (dx>>FRACBITS); return (right < left) ? 0 : ((left == right) ? 2 : 1);
right = (dy>>FRACBITS) * (node->dx>>FRACBITS); }
if (right < left)
return 0; // front side
if (left == right)
return 2;
return 1; // back side
} }
@ -100,23 +79,15 @@ int P_DivlineSide (const fixed_t x, const fixed_t y, const divline_t *node)
// along the first divline. // along the first divline.
// This is only called by the addthings and addlines traversers. // This is only called by the addthings and addlines traversers.
// //
fixed_t P_InterceptVector2 (const divline_t *v2, const divline_t *v1) //
// killough 4/19/98: made static, cleaned up
static fixed_t P_InterceptVector2(const divline_t *v2, const divline_t *v1)
{ {
fixed_t frac; fixed_t den;
fixed_t num; return (den = FixedMul(v1->dy>>8, v2->dx) - FixedMul(v1->dx>>8, v2->dy)) ?
fixed_t den; FixedDiv(FixedMul((v1->x - v2->x)>>8, v1->dy) +
FixedMul((v2->y - v1->y)>>8, v1->dx), den) : 0;
den = FixedMul (v1->dy>>8,v2->dx) - FixedMul(v1->dx>>8,v2->dy);
if (den == 0)
return 0;
// I_Error ("P_InterceptVector: parallel");
num = FixedMul ( (v1->x - v2->x)>>8 ,v1->dy) +
FixedMul ( (v2->y - v1->y)>>8 , v1->dx);
frac = FixedDiv (num , den);
return frac;
} }
// //
@ -124,122 +95,103 @@ fixed_t P_InterceptVector2 (const divline_t *v2, const divline_t *v1)
// Returns true // Returns true
// if strace crosses the given subsector successfully. // if strace crosses the given subsector successfully.
// //
BOOL P_CrossSubsector (const int num) //
// killough 4/19/98: made static and cleaned up
static BOOL P_CrossSubsector(int num, register los_t *los)
{ {
seg_t* seg; seg_t *seg = segs + subsectors[num].firstline;
line_t* line; int count;
int s1;
int s2;
int count;
subsector_t* sub;
sector_t* front;
sector_t* back;
fixed_t opentop;
fixed_t openbottom;
divline_t divl;
vertex_t* v1;
vertex_t* v2;
fixed_t frac;
fixed_t slope;
#ifdef RANGECHECK #ifdef RANGECHECK
if (num>=numsubsectors) if (num >= numsubsectors)
I_Error ("P_CrossSubsector: ss %i with numss = %i", I_Error("P_CrossSubsector: ss %i with numss = %i", num, numsubsectors);
num,
numsubsectors);
#endif #endif
sub = &subsectors[num]; for (count = subsectors[num].numlines; --count >= 0; seg++) // check lines
// check lines
count = sub->numlines;
seg = &segs[sub->firstline];
for ( ; count ; seg++, count--)
{ {
line = seg->linedef; line_t *line = seg->linedef;
divline_t divl;
fixed_t opentop, openbottom;
const sector_t *front, *back;
const vertex_t *v1,*v2;
fixed_t frac;
// allready checked other side? // already checked other side?
if (line->validcount == validcount) if (line->validcount == validcount)
continue; continue;
line->validcount = validcount; line->validcount = validcount;
// OPTIMIZE: killough 4/20/98: Added quick bounding-box rejection test
if (line->bbox[BOXLEFT ] > los->bbox[BOXRIGHT ] ||
line->bbox[BOXRIGHT ] < los->bbox[BOXLEFT ] ||
line->bbox[BOXBOTTOM] > los->bbox[BOXTOP ] ||
line->bbox[BOXTOP] < los->bbox[BOXBOTTOM])
continue;
v1 = line->v1; v1 = line->v1;
v2 = line->v2; v2 = line->v2;
s1 = P_DivlineSide (v1->x,v1->y, &strace);
s2 = P_DivlineSide (v2->x, v2->y, &strace);
// line isn't crossed? // line isn't crossed?
if (s1 == s2) if (P_DivlineSide(v1->x, v1->y, &los->strace) ==
P_DivlineSide(v2->x, v2->y, &los->strace))
continue; continue;
divl.x = v1->x; divl.dx = v2->x - (divl.x = v1->x);
divl.y = v1->y; divl.dy = v2->y - (divl.y = v1->y);
// [RH] This is already calculated. Why calculate it again?
divl.dx = line->dx;
divl.dy = line->dy;
/* divl.dx = v2->x - v1->x;
divl.dy = v2->y - v1->y; */
s1 = P_DivlineSide (strace.x, strace.y, &divl);
s2 = P_DivlineSide (t2x, t2y, &divl);
// line isn't crossed? // line isn't crossed?
if (s1 == s2) if (P_DivlineSide(los->strace.x, los->strace.y, &divl) ==
continue; P_DivlineSide(los->t2x, los->t2y, &divl))
continue;
// stop because it is not two sided anyway // stop because it is not two sided anyway
// might do this after updating validcount? if (!(line->flags & ML_TWOSIDED) || (line->flags & ML_BLOCKEVERYTHING))
if ( !(line->flags & ML_TWOSIDED) )
return false; return false;
// crosses a two sided line
front = seg->frontsector;
back = seg->backsector;
// crosses a two sided line
// no wall to block sight with? // no wall to block sight with?
if (front->floorheight == back->floorheight if ((front = seg->frontsector)->floorheight ==
&& front->ceilingheight == back->ceilingheight) (back = seg->backsector)->floorheight &&
continue; front->ceilingheight == back->ceilingheight)
continue;
// possible occluder // possible occluder
// because of ceiling height differences // because of ceiling height differences
if (front->ceilingheight < back->ceilingheight) opentop = front->ceilingheight < back->ceilingheight ?
opentop = front->ceilingheight; front->ceilingheight : back->ceilingheight ;
else
opentop = back->ceilingheight;
// because of floor height differences // because of floor height differences
if (front->floorheight > back->floorheight) openbottom = front->floorheight > back->floorheight ?
openbottom = front->floorheight; front->floorheight : back->floorheight ;
else
openbottom = back->floorheight;
// quick test for totally closed doors // quick test for totally closed doors
if (openbottom >= opentop) if (openbottom >= opentop)
return false; // stop return false; // stop
frac = P_InterceptVector2 (&strace, &divl); frac = P_InterceptVector2(&los->strace, &divl);
if (front->floorheight != back->floorheight) if (front->floorheight != back->floorheight)
{ {
slope = FixedDiv (openbottom - sightzstart , frac); fixed_t slope = FixedDiv(openbottom - los->sightzstart , frac);
if (slope > bottomslope) if (slope > los->bottomslope)
bottomslope = slope; los->bottomslope = slope;
}
if (front->ceilingheight != back->ceilingheight)
{
slope = FixedDiv (opentop - sightzstart , frac);
if (slope < topslope)
topslope = slope;
} }
if (topslope <= bottomslope) if (front->ceilingheight != back->ceilingheight)
return false; // stop {
fixed_t slope = FixedDiv(opentop - los->sightzstart , frac);
if (slope < los->topslope)
los->topslope = slope;
}
if (los->topslope <= los->bottomslope)
return false; // stop
} }
// passed the subsector ok // passed the subsector ok
return true; return true;
} }
@ -249,39 +201,24 @@ BOOL P_CrossSubsector (const int num)
// Returns true // Returns true
// if strace crosses the given node successfully. // if strace crosses the given node successfully.
// //
BOOL P_CrossBSPNode (const int bspnum) // killough 4/20/98: rewritten to remove tail recursion, clean up, and optimize
static BOOL P_CrossBSPNode(int bspnum, register los_t *los)
{ {
node_t* bsp; while (!(bspnum & NF_SUBSECTOR))
int side;
if (bspnum & NF_SUBSECTOR)
{ {
if (bspnum == -1) register const node_t *bsp = nodes + bspnum;
return P_CrossSubsector (0); int side = P_DivlineSide(los->strace.x,los->strace.y,(divline_t *)bsp)&1;
else if (side == P_DivlineSide(los->t2x, los->t2y, (divline_t *) bsp))
return P_CrossSubsector (bspnum&(~NF_SUBSECTOR)); bspnum = bsp->children[side]; // doesn't touch the other side
else { // the partition plane is crossed here
if (!P_CrossBSPNode(bsp->children[side], los))
return 0; // cross the starting side
else
bspnum = bsp->children[side^1]; // cross the ending side
}
} }
return P_CrossSubsector(bspnum == -1 ? 0 : bspnum & ~NF_SUBSECTOR, los);
bsp = &nodes[bspnum];
// decide which side the start point is on
side = P_DivlineSide (strace.x, strace.y, (divline_t *)bsp);
if (side == 2)
side = 0; // an "on" should cross both sides
// cross the starting side
if (!P_CrossBSPNode (bsp->children[side]) )
return false;
// the partition plane is crossed here
if (side == P_DivlineSide (t2x, t2y,(divline_t *)bsp))
{
// the line doesn't touch the other side
return true;
}
// cross the ending side
return P_CrossBSPNode (bsp->children[side^1]);
} }
@ -291,57 +228,64 @@ BOOL P_CrossBSPNode (const int bspnum)
// if a straight line between t1 and t2 is unobstructed. // if a straight line between t1 and t2 is unobstructed.
// Uses REJECT. // Uses REJECT.
// //
BOOL P_CheckSight (const mobj_t *t1, const mobj_t *t2) // killough 4/20/98: cleaned up, made to use new LOS struct
BOOL P_CheckSight (const mobj_t *t1, const mobj_t *t2, BOOL ignoreInvisibility)
{ {
int s1; const sector_t *s1 = t1->subsector->sector;
int s2; const sector_t *s2 = t2->subsector->sector;
int pnum; int pnum = (s1-sectors)*numsectors + (s2-sectors);
int bytenum; los_t los;
int bitnum;
// First check for trivial rejection.
// Determine subsector entries in REJECT table.
// Check in REJECT table.
if (rejectmatrix[pnum>>3] & (1 << (pnum&7))) // can't possibly be connected
return false;
// [RH] Andy Baker's stealth monsters // [RH] Andy Baker's stealth monsters
// Cannot see an invisible object // Cannot see an invisible object
if (t2->invisible) if (!ignoreInvisibility && (t2->flags2 & MF2_INVISIBLE)
{ && P_Random (pr_checksight) > 50) //^^^^^^^^ small chance of an attack being made anyway
if (P_Random (pr_checksight) > 50) // small chance of an attack being made anyway return false;
return false;
}
// First check for trivial rejection. // killough 4/19/98: make fake floors and ceilings block monster view
// Determine subsector entries in REJECT table. if ((s1->heightsec != -1 &&
s1 = (t1->subsector->sector - sectors); ((t1->z + t1->height <= sectors[s1->heightsec].floorheight &&
s2 = (t2->subsector->sector - sectors); t2->z >= sectors[s1->heightsec].floorheight) ||
pnum = s1*numsectors + s2; (t1->z >= sectors[s1->heightsec].ceilingheight &&
bytenum = pnum>>3; t2->z + t1->height <= sectors[s1->heightsec].ceilingheight)))
bitnum = 1 << (pnum&7); ||
(s2->heightsec != -1 &&
// Check in REJECT table. ((t2->z + t2->height <= sectors[s2->heightsec].floorheight &&
if (rejectmatrix[bytenum]&bitnum) t1->z >= sectors[s2->heightsec].floorheight) ||
{ (t2->z >= sectors[s2->heightsec].ceilingheight &&
sightcounts[0]++; t1->z + t2->height <= sectors[s2->heightsec].ceilingheight))))
return false;
// can't possibly be connected
return false;
}
// An unobstructed LOS is possible. // An unobstructed LOS is possible.
// Now look from eyes of t1 to any part of t2. // Now look from eyes of t1 to any part of t2.
sightcounts[1]++;
validcount++; validcount++;
sightzstart = t1->z + t1->height - (t1->height>>2); los.topslope = (los.bottomslope = t2->z - (los.sightzstart =
topslope = (t2->z+t2->height) - sightzstart; t1->z + t1->height -
bottomslope = (t2->z) - sightzstart; (t1->height>>2))) + t2->height;
los.strace.dx = (los.t2x = t2->x) - (los.strace.x = t1->x);
strace.x = t1->x; los.strace.dy = (los.t2y = t2->y) - (los.strace.y = t1->y);
strace.y = t1->y;
t2x = t2->x; if (t1->x > t2->x)
t2y = t2->y; los.bbox[BOXRIGHT] = t1->x, los.bbox[BOXLEFT] = t2->x;
strace.dx = t2->x - t1->x; else
strace.dy = t2->y - t1->y; los.bbox[BOXRIGHT] = t2->x, los.bbox[BOXLEFT] = t1->x;
if (t1->y > t2->y)
los.bbox[BOXTOP] = t1->y, los.bbox[BOXBOTTOM] = t2->y;
else
los.bbox[BOXTOP] = t2->y, los.bbox[BOXBOTTOM] = t1->y;
// the head node is the last node output // the head node is the last node output
return P_CrossBSPNode (numnodes-1); return P_CrossBSPNode (numnodes-1, &los);
} }

File diff suppressed because it is too large Load diff

View file

@ -56,6 +56,54 @@ typedef struct {
} type; // Type of scroll effect } type; // Type of scroll effect
} scroll_t; } scroll_t;
// phares 3/12/98: added new model of friction for ice/sludge effects
typedef struct {
thinker_t thinker; // Thinker structure for friction
int friction; // friction value (E800 = normal)
int movefactor; // inertia factor when adding to momentum
int affectee; // Number of affected sector
} friction_t;
// phares 3/20/98: added new model of Pushers for push/pull effects
typedef struct {
thinker_t thinker; // Thinker structure for Pusher
enum
{
p_push,
p_pull,
p_wind,
p_current,
} type;
mobj_t* source; // Point source if point pusher
int x_mag; // X Strength
int y_mag; // Y Strength
int magnitude; // Vector strength for point pusher
int radius; // Effective radius for point pusher
int x; // X of point source if point pusher
int y; // Y of point source if point pusher
int affectee; // Number of affected sector
} pusher_t;
// [RH] Types of keys used by locked doors and scripts
typedef enum
{
NoKey,
RCard,
BCard,
YCard,
RSkull,
BSkull,
YSkull,
AnyKey = 100,
AllKeys = 101,
CardIsSkull = 128
} keytype_t;
BOOL P_CheckKeys (player_t *p, keytype_t lock, BOOL remote);
// Define values for map objects // Define values for map objects
#define MO_TELEPORTMAN 14 #define MO_TELEPORTMAN 14
@ -77,10 +125,10 @@ void P_UpdateSpecials (void);
// when needed // when needed
BOOL P_UseSpecialLine (mobj_t *thing, line_t *line, int side); BOOL P_UseSpecialLine (mobj_t *thing, line_t *line, int side);
void P_ShootSpecialLine (mobj_t *thing, line_t *line); void P_ShootSpecialLine (mobj_t *thing, line_t *line);
void P_ShotCrossSpecialLine (mobj_t *thing, line_t *line); // [RH]
void P_CrossSpecialLine (int linenum, int side, mobj_t *thing); void P_CrossSpecialLine (int linenum, int side, mobj_t *thing);
BOOL P_PushSpecialLine (mobj_t *thing, int side, line_t *line); // [RH]
void P_PlayerInSpecialSector (player_t *player); void P_PlayerInSpecialSector (player_t *player);
@ -96,23 +144,35 @@ fixed_t P_FindHighestFloorSurrounding (sector_t *sec);
fixed_t P_FindNextHighestFloor (sector_t *sec, int currentheight); fixed_t P_FindNextHighestFloor (sector_t *sec, int currentheight);
fixed_t P_FindNextLowestFloor (sector_t* sec, int currentheight); fixed_t P_FindNextLowestFloor (sector_t* sec, int currentheight);
fixed_t P_FindLowestCeilingSurrounding (sector_t *sec); fixed_t P_FindLowestCeilingSurrounding (sector_t *sec); // jff 2/04/98
fixed_t P_FindHighestCeilingSurrounding (sector_t *sec); fixed_t P_FindHighestCeilingSurrounding (sector_t *sec); // jff 2/04/98
int P_FindSectorFromLineTag (line_t *line, int start); fixed_t P_FindNextLowestCeiling (sector_t *sec, int currentheight); // jff 2/04/98
fixed_t P_FindNextHighestCeiling (sector_t *sec, int currentheight); // jff 2/04/98
fixed_t P_FindShortestTextureAround (int secnum); // jff 2/04/98
fixed_t P_FindShortestUpperAround (int secnum); // jff 2/04/98
sector_t* P_FindModelFloorSector (fixed_t floordestheight, int secnum); //jff 02/04/98
sector_t* P_FindModelCeilingSector (fixed_t ceildestheight, int secnum); //jff 02/04/98
int P_FindSectorFromTag (int tag, int start);
int P_FindLineFromID (int id, int start);
int P_FindMinSurroundingLight (sector_t *sector, int max); int P_FindMinSurroundingLight (sector_t *sector, int max);
sector_t *getNextSector (line_t *line, sector_t *sec); sector_t *getNextSector (line_t *line, sector_t *sec);
sector_t *P_NextSpecialSector (sector_t *sec, int type, sector_t *back2); // [RH]
void T_Scroll (scroll_t *); // killough 3/7/98: scroll effect thinker void T_Scroll (scroll_t *); // killough 3/7/98: scroll effect thinker
void T_Friction (friction_t *); // phares 3/12/98: friction thinker
void T_Pusher (pusher_t *); // phares 3/20/98: Push thinker
// //
// SPECIAL // SPECIAL
// //
int EV_DoDonut (line_t *line); int EV_DoDonut (int tag, fixed_t pillarspeed, fixed_t slimespeed);
@ -166,29 +226,58 @@ typedef struct
int direction; int direction;
} glow_t; } glow_t;
// [RH] Glow from Light_Glow and Light_Fade specials
typedef struct
{
thinker_t thinker;
sector_t *sector;
int start;
int end;
int maxtics;
int tics;
BOOL oneshot;
} glow2_t;
#define GLOWSPEED ((TICRATE*8)/35) // [RH] Phased light thinker
#define STROBEBRIGHT (TICRATE/7) typedef struct
#define FASTDARK ((TICRATE*3)/7) {
thinker_t thinker;
sector_t *sector;
byte baselevel;
byte phase;
} phased_t;
#define GLOWSPEED 8
#define STROBEBRIGHT 5
#define FASTDARK 15
#define SLOWDARK TICRATE #define SLOWDARK TICRATE
void T_FireFlicker (fireflicker_t *flick); void T_FireFlicker (fireflicker_t *flick);
void P_SpawnFireFlicker (sector_t *sector); void P_SpawnFireFlicker (sector_t *sector);
void T_LightFlash (lightflash_t *flash); void T_LightFlash (lightflash_t *flash);
void P_SpawnLightFlash (sector_t *sector); void P_SpawnLightFlash (sector_t *sector, int min, int max);
void T_StrobeFlash (strobe_t *flash); void T_StrobeFlash (strobe_t *flash);
void P_SpawnStrobeFlash (sector_t *sector, int fastOrSlow, int inSync); void P_SpawnStrobeFlash (sector_t *sector, int upper, int lower,
int utics, int ltics, int inSync);
void EV_StartLightStrobing(line_t *line); void EV_StartLightFlashing (int tag, int upper, int lower);
void EV_TurnTagLightsOff(line_t *line); void EV_StartLightStrobing (int tag, int upper, int lower,
int utics, int ltics);
void EV_LightTurnOn (line_t *line, int bright); void EV_TurnTagLightsOff (int tag);
void EV_LightTurnOn (int tag, int bright);
void EV_LightChange (int tag, int value);
void T_Glow (glow_t *g); void T_Glow (glow_t *g);
void P_SpawnGlowingLight (sector_t *sector); void P_SpawnGlowingLight (sector_t *sector);
void T_Glow2 (glow2_t *g);
void EV_StartLightGlowing (int tag, int upper, int lower, int tics);
void EV_StartLightFading (int tag, int value, int tics);
void T_PhasedLight (phased_t *l);
void P_SpawnLightSequence (sector_t *sector);
void P_SpawnLightPhased (sector_t *sector);
// //
@ -212,8 +301,9 @@ typedef enum
} bwhere_e; } bwhere_e;
typedef struct typedef struct button_s
{ {
struct button_s *next; // [RH] make buttons a singly-linked list
line_t* line; line_t* line;
bwhere_e where; bwhere_e where;
int btexture; int btexture;
@ -225,13 +315,10 @@ typedef struct
// 4 players, 4 buttons each at once, max.
#define MAXBUTTONS (MAXPLAYERS*4)
// 1 second, in ticks. // 1 second, in ticks.
#define BUTTONTIME TICRATE #define BUTTONTIME TICRATE
extern button_t buttonlist[MAXBUTTONS]; extern button_t *buttonlist;
void P_ChangeSwitchTexture (line_t *line, int useAgain); void P_ChangeSwitchTexture (line_t *line, int useAgain);
@ -254,19 +341,29 @@ typedef enum
typedef enum typedef enum
{ {
perpetualRaise, // [RH] Changed these
downWaitUpStay, platPerpetualRaise,
raiseAndChange, platDownWaitUpStay,
raiseToNearestAndChange, platUpWaitDownStay,
blazeDWUS platDownByValue,
platUpByValue,
platUpByValueStay,
platRaiseAndStay,
platToggle,
platDownToNearestFloor,
platDownToLowestCeiling
} plattype_e; } plattype_e;
typedef struct typedef struct plat_s
{ {
thinker_t thinker; thinker_t thinker;
// [RH] Added next and prev links
struct plat_s *next, *prev;
sector_t* sector; sector_t* sector;
fixed_t speed; fixed_t speed;
fixed_t low; fixed_t low;
@ -283,40 +380,62 @@ typedef struct
#define PLATWAIT 3 extern plat_t *activeplats;
#define PLATSPEED FRACUNIT
extern int MaxPlats;
extern plat_t **activeplats;
void T_PlatRaise(plat_t *plat); void T_PlatRaise(plat_t *plat);
int EV_DoPlat (line_t *line, plattype_e type, int amount); BOOL EV_DoPlat (int tag, line_t *line, plattype_e type, int height,
int speed, int delay, int lip, int change);
void P_AddActivePlat (plat_t *plat); void P_AddActivePlat (plat_t *plat);
void P_RemoveActivePlat (plat_t *plat); void P_RemoveActivePlat (plat_t *plat);
void EV_StopPlat (line_t *line); void EV_StopPlat (int tag);
void P_ActivateInStasis (int tag); void P_ActivateInStasis (int tag);
//
// [RH]
// P_PILLAR
//
typedef enum
{
pillarBuild,
pillarOpen
} pillar_e;
typedef struct
{
thinker_t thinker;
sector_t *sector;
pillar_e type;
fixed_t floorspeed;
fixed_t ceilingspeed;
fixed_t floortarget;
fixed_t ceilingtarget;
int crush;
} pillar_t;
BOOL EV_DoPillar (pillar_e type, int tag, fixed_t speed, fixed_t height,
fixed_t height2, int crush);
void T_Pillar (pillar_t *pillar);
// //
// P_DOORS // P_DOORS
// //
typedef enum typedef enum
{ {
normal, // [RH] Changed for new specials
close30ThenOpen, doorClose,
close, doorOpen,
open, doorRaise,
raiseIn5Mins, doorRaiseIn5Mins,
blazeRaise, doorCloseWaitOpen,
blazeOpen,
blazeClose
} vldoor_e; } vldoor_e;
typedef struct typedef struct
{ {
thinker_t thinker; thinker_t thinker;
@ -337,133 +456,78 @@ typedef struct
} vldoor_t; } vldoor_t;
BOOL EV_DoDoor (vldoor_e type, line_t *line, mobj_t *thing,
#define VDOORSPEED (FRACUNIT*2) int tag, int speed, int delay, keytype_t lock);
#define VDOORWAIT ((TICRATE*30)/7)
void EV_VerticalDoor (line_t *line, mobj_t *thing);
int EV_DoDoor (line_t *line, vldoor_e type);
int EV_DoLockedDoor (line_t *line, vldoor_e type, mobj_t *thing);
void T_VerticalDoor (vldoor_t *door); void T_VerticalDoor (vldoor_t *door);
void P_SpawnDoorCloseIn30 (sector_t *sec); void P_SpawnDoorCloseIn30 (sector_t *sec);
void P_SpawnDoorRaiseIn5Mins (sector_t *sec, int secnum); void P_SpawnDoorRaiseIn5Mins (sector_t *sec);
#if 0 // UNUSED
//
// Sliding doors...
//
typedef enum
{
sd_opening,
sd_waiting,
sd_closing
} sd_e;
typedef enum
{
sdt_openOnly,
sdt_closeOnly,
sdt_openAndClose
} sdt_e;
typedef struct
{
thinker_t thinker;
sdt_e type;
line_t* line;
int frame;
int whichDoorIndex;
int timer;
sector_t* frontsector;
sector_t* backsector;
sd_e status;
} slidedoor_t;
typedef struct
{
char frontFrame1[9];
char frontFrame2[9];
char frontFrame3[9];
char frontFrame4[9];
char backFrame1[9];
char backFrame2[9];
char backFrame3[9];
char backFrame4[9];
} slidename_t;
typedef struct
{
int frontFrames[4];
int backFrames[4];
} slideframe_t;
// how many frames of animation
#define SNUMFRAMES 4
#define SDOORWAIT (3*TICRATE)
#define SWAITTICS 4
// how many diff. types of anims
#define MAXSLIDEDOORS 5
void P_InitSlidingDoorFrames(void);
void EV_SlidingDoor (line_t *line, mobj_t *thing);
#endif
// //
// P_CEILNG // P_CEILNG
// //
// [RH] Changed these
typedef enum typedef enum
{ {
lowerToFloor, ceilLowerByValue,
raiseToHighest, ceilRaiseByValue,
lowerAndCrush, ceilMoveToValue,
crushAndRaise, ceilLowerToHighestFloor,
fastCrushAndRaise, ceilLowerInstant,
silentCrushAndRaise ceilRaiseInstant,
ceilCrushAndRaise,
ceilLowerAndCrush,
ceilCrushRaiseAndStay,
ceilRaiseToNearest,
ceilLowerToLowest,
ceilLowerToFloor,
// The following are only used by Generic_Ceiling
ceilRaiseToHighest,
ceilLowerToHighest,
ceilRaiseToLowest,
ceilLowerToNearest,
ceilRaiseToHighestFloor,
ceilRaiseToFloor,
ceilRaiseByTexture,
ceilLowerByTexture,
genCeilingChg0,
genCeilingChgT,
genCeilingChg
} ceiling_e; } ceiling_e;
typedef struct typedef struct ceiling_s
{ {
thinker_t thinker; thinker_t thinker;
// [RH] Added next and prev links
struct ceiling_s *next, *prev;
ceiling_e type; ceiling_e type;
sector_t* sector; sector_t* sector;
fixed_t bottomheight; fixed_t bottomheight;
fixed_t topheight; fixed_t topheight;
fixed_t speed; fixed_t speed;
BOOL crush; fixed_t speed1; // [RH] dnspeed of crushers
fixed_t speed2; // [RH] upspeed of crushers
int crush;
int silent; // [RH] 1=noise at stops, 2=no noise at all
// 1 = up, 0 = waiting, -1 = down // 1 = up, 0 = waiting, -1 = down
int direction; int direction;
// [RH] Need these for BOOM-ish transfering ceilings
int texture;
int newspecial;
// ID // ID
int tag; int tag;
int olddirection; int olddirection;
@ -474,48 +538,74 @@ typedef struct
#define CEILSPEED FRACUNIT extern ceiling_t *activeceilings;
#define CEILWAIT ((TICRATE*30)/7)
extern int MaxCeilings; BOOL EV_DoCeiling (ceiling_e type, line_t *line,
extern ceiling_t **activeceilings; int tag, fixed_t speed, fixed_t speed2, fixed_t height,
int crush, int silent, int change);
int EV_DoCeiling (line_t *line, ceiling_e type);
void T_MoveCeiling (ceiling_t *ceiling); void T_MoveCeiling (ceiling_t *ceiling);
void P_AddActiveCeiling(ceiling_t *c); void P_AddActiveCeiling (ceiling_t *c);
void P_RemoveActiveCeiling(ceiling_t *c); void P_RemoveActiveCeiling (ceiling_t *c);
int EV_CeilingCrushStop(line_t *line); BOOL EV_CeilingCrushStop (int tag);
void P_ActivateInStasisCeiling(line_t *line); void P_ActivateInStasisCeiling(int tag);
// //
// P_FLOOR // P_FLOOR
// //
// [RH] Changed these enums
typedef enum typedef enum
{ {
lowerFloor, // lower floor to highest surrounding floor floorLowerToLowest,
lowerFloorToLowest, // lower floor to lowest surrounding floor floorLowerToNearest,
turboLower, // lower floor to highest surrounding floor VERY FAST floorLowerToHighest,
raiseFloor, // raise floor to lowest surrounding CEILING floorLowerByValue,
raiseFloorToNearest, // raise floor to next highest surrounding floor floorRaiseByValue,
raiseToTexture, // raise floor to shortest height texture around it floorRaiseToHighest,
lowerAndChange, // lower floor to lowest surrounding floor and change floorpic floorRaiseToNearest,
floorRaiseAndCrush,
floorCrushStop,
floorLowerInstant,
floorRaiseInstant,
floorMoveToValue,
floorRaiseToLowestCeiling,
floorRaiseByTexture,
raiseFloor24, floorLowerAndChange,
raiseFloor24AndChange, floorRaiseAndChange,
raiseFloorCrush,
raiseFloorTurbo, // raise to next highest floor, turbo-speed floorRaiseToLowest,
floorRaiseToCeiling,
floorLowerToLowestCeiling,
floorLowerByTexture,
floorLowerToCeiling,
donutRaise, donutRaise,
raiseFloor512
buildStair,
waitStair,
resetStair,
// Not to be used as parameters to EV_DoFloor()
genFloorChg0,
genFloorChgT,
genFloorChg
} floor_e; } floor_e;
//jff 3/15/98 pure texture/type change for better generalized support
typedef enum typedef enum
{ {
build8, // slowly build by 8 trigChangeOnly,
turbo16 // quickly build by 16 numChangeOnly,
} change_e;
// [RH] Changed to use Hexen-ish specials
typedef enum
{
buildUp,
buildDown
} stair_e; } stair_e;
@ -524,36 +614,56 @@ typedef enum
elevateUp, elevateUp,
elevateDown, elevateDown,
elevateCurrent, elevateCurrent,
// [RH] For FloorAndCeiling_Raise/Lower
elevateRaise,
elevateLower
} elevator_e; } elevator_e;
typedef struct typedef struct
{ {
thinker_t thinker; thinker_t thinker;
floor_e type; floor_e type;
BOOL crush; int crush;
sector_t* sector; sector_t* sector;
int direction; int direction;
int newspecial; short newspecial;
short texture; short texture;
fixed_t floordestheight; fixed_t floordestheight;
fixed_t speed; fixed_t speed;
// [RH] New parameters use to reset and delayed stairs
int resetcount;
int orgheight;
int delay;
int pausetime;
int steptime;
int persteptime;
} floormove_t; } floormove_t;
typedef struct typedef struct
{ {
thinker_t thinker; thinker_t thinker;
elevator_e type; elevator_e type;
sector_t* sector; sector_t* sector;
int direction; int direction;
fixed_t floordestheight; fixed_t floordestheight;
fixed_t ceilingdestheight; fixed_t ceilingdestheight;
fixed_t speed; fixed_t speed;
} elevator_t; } elevator_t;
typedef struct {
thinker_t thinker;
sector_t *sector;
int x;
int amp;
int freq;
int timetodie;
fixed_t baseline;
int stage;
int ampfactor;
} waggle_t;
#define ELEVATORSPEED (FRACUNIT*4)
#define FLOORSPEED FRACUNIT
typedef enum typedef enum
{ {
@ -564,25 +674,65 @@ typedef enum
} result_e; } result_e;
result_e T_MovePlane (sector_t *sector, fixed_t speed, fixed_t dest, result_e T_MovePlane (sector_t *sector, fixed_t speed, fixed_t dest,
BOOL crush, int floorOrCeiling, int direction); int crush, int floorOrCeiling, int direction);
int EV_DoElevator (line_t *line, ceiling_e type); BOOL EV_DoElevator (line_t *line, ceiling_e type, fixed_t speed, fixed_t height, int tag);
int EV_BuildStairs (line_t *line, stair_e type); BOOL EV_BuildStairs (int tag, stair_e type, line_t *line,
fixed_t stairsize, fixed_t speed, int delay, int reset, int igntxt,
int usespecials);
int EV_DoFloor (line_t *line, floor_e floortype); BOOL EV_DoFloor (floor_e floortype, line_t *line, int tag,
fixed_t speed, fixed_t height, int crush, int change);
BOOL EV_FloorCrushStop (int tag);
BOOL EV_DoChange (line_t *line, change_e changetype, int tag);
BOOL EV_DoFloorWaggle (int tag, fixed_t amplitude, fixed_t speed, int delay, int count);
void T_Waggle (waggle_t *w);
void T_MoveFloor (floormove_t *floor); void T_MoveFloor (floormove_t *floor);
void T_MoveElevator (elevator_t *elevator); void T_MoveElevator (elevator_t *elevator);
// //
// P_TELEPT // P_TELEPT
// //
int EV_Teleport (line_t *line, int side, mobj_t *thing); BOOL EV_Teleport (int tid, int side, mobj_t *thing);
BOOL EV_SilentTeleport (int tid, line_t *line, int side, mobj_t *thing);
BOOL EV_SilentLineTeleport (line_t *line, int side, mobj_t *thing, int id,
BOOL reverse);
int P_SectorActive (special_e t, sector_t *s); // [RH] from BOOM int P_SectorActive (special_e t, sector_t *s); // [RH] from BOOM
//
// [RH] ACS (see also p_acs.h)
//
void P_ClearScripts (void);
BOOL P_StartScript (mobj_t *who, line_t *where, int script, char *map, int lineSide,
int arg0, int arg1, int arg2, int always);
void P_SuspendScript (int script, char *map);
void P_TerminateScript (int script, char *map);
void P_StartOpenScripts (void);
void P_DoDeferedScripts (void);
//
// [RH] p_quake.c
//
typedef struct quake_s {
struct quake_s *next;
mobj_t *quakespot;
fixed_t tremorbox[4];
fixed_t damagebox[4];
int intensity;
int countdown;
} quake_t;
extern quake_t *ActiveQuakes;
void P_RunQuakes (void);
BOOL P_StartQuake (int tid, int intensity, int duration, int damrad, int tremrad);
#endif #endif

View file

@ -15,8 +15,6 @@
// for more details. // for more details.
// //
// //
// $Log:$
//
// DESCRIPTION: // DESCRIPTION:
// Switches, buttons. Two-state animation. Exits. // Switches, buttons. Two-state animation. Exits.
// //
@ -27,14 +25,12 @@
#include "i_system.h" #include "i_system.h"
#include "doomdef.h" #include "doomdef.h"
#include "p_local.h" #include "p_local.h"
#include "p_lnspec.h"
#include "g_game.h" #include "g_game.h"
#include "s_sound.h" #include "s_sound.h"
// Data.
#include "sounds.h"
// State. // State.
#include "doomstat.h" #include "doomstat.h"
#include "r_state.h" #include "r_state.h"
@ -49,7 +45,7 @@
static int *switchlist; static int *switchlist;
static int numswitches; static int numswitches;
button_t buttonlist[MAXBUTTONS]; button_t *buttonlist; // [RH] remove limit on number of buttons
// //
// P_InitSwitchList // P_InitSwitchList
@ -100,58 +96,44 @@ void P_InitSwitchList(void)
Z_Free (alphSwitchList); Z_Free (alphSwitchList);
} }
// //
// Start a button counting down till it turns off. // Start a button counting down till it turns off.
// [RH] Rewritten to remove MAXBUTTONS limit and use temporary soundorgs.
// //
void P_StartButton (line_t *line, bwhere_e w, int texture, int time) void P_StartButton (line_t *line, bwhere_e w, int texture, int time, mobj_t *soundorg)
{ {
int i; button_t *button;
// See if button is already pressed // See if button is already pressed
for (i = 0;i < MAXBUTTONS;i++) button = buttonlist;
{ while (button) {
if (buttonlist[i].btimer if (button->line == line)
&& buttonlist[i].line == line)
{
return; return;
} button = button->next;
} }
button = Z_Malloc (sizeof(*button), PU_LEVEL, 0);
button->line = line;
for (i = 0;i < MAXBUTTONS;i++) button->where = w;
{ button->btexture = texture;
if (!buttonlist[i].btimer) button->btimer = time;
{ button->soundorg = soundorg;
buttonlist[i].line = line; button->next = buttonlist;
buttonlist[i].where = w; buttonlist = button;
buttonlist[i].btexture = texture;
buttonlist[i].btimer = time;
buttonlist[i].soundorg = (mobj_t *)&line->frontsector->soundorg;
return;
}
}
I_Error("P_StartButton: no button slots left!");
} }
// //
// Function that changes wall texture. // Function that changes wall texture.
// Tell it if switch is ok to use again (1=yes, it's a button). // Tell it if switch is ok to use again (1=yes, it's a button).
// //
void P_ChangeSwitchTexture (line_t *line, int useAgain) void P_ChangeSwitchTexture (line_t *line, int useAgain)
{ {
int texTop; int texTop;
int texMid; int texMid;
int texBot; int texBot;
int i; int i;
int sound; char *sound;
if (!useAgain) if (!useAgain)
line->special = 0; line->special = 0;
@ -160,58 +142,53 @@ void P_ChangeSwitchTexture (line_t *line, int useAgain)
texMid = sides[line->sidenum[0]].midtexture; texMid = sides[line->sidenum[0]].midtexture;
texBot = sides[line->sidenum[0]].bottomtexture; texBot = sides[line->sidenum[0]].bottomtexture;
sound = sfx_swtchn;
// EXIT SWITCH? // EXIT SWITCH?
if (line->special == 11) if (line->special == Exit_Normal ||
sound = sfx_swtchx; line->special == Exit_Secret ||
line->special == Teleport_NewMap ||
line->special == Teleport_EndGame)
sound = "switches/exitbutn";
else
sound = "switches/normbutn";
for (i = 0;i < numswitches*2;i++) for (i = 0; i < numswitches*2; i++)
{ {
if (switchlist[i] == texTop) // [RH] Rewritten slightly to be more compact
{ short *texture = NULL;
S_StartSound(buttonlist->soundorg,sound); bwhere_e where;
sides[line->sidenum[0]].toptexture = (short)switchlist[i^1];
if (useAgain) if (switchlist[i] == texTop) {
P_StartButton(line,top,switchlist[i],BUTTONTIME); texture = &sides[line->sidenum[0]].toptexture;
where = top;
return; } else if (switchlist[i] == texMid) {
texture = &sides[line->sidenum[0]].midtexture;
where = middle;
} else if (switchlist[i] == texBot) {
texture = &sides[line->sidenum[0]].bottomtexture;
where = bottom;
} }
else
{
if (switchlist[i] == texMid)
{
S_StartSound(buttonlist->soundorg,sound);
sides[line->sidenum[0]].midtexture = (short)switchlist[i^1];
if (useAgain) if (texture) {
P_StartButton(line, middle,switchlist[i],BUTTONTIME); // [RH] The original code played the sound at buttonlist->soundorg.
// I spawn a temporary mobj on the button's line to play the
return; // sound. It automatically removes itself after 60 seconds.
} mobj_t *soundorg = P_SpawnMobj (
else line->v1->x + (line->dx >> 1),
{ line->v1->y + (line->dy >> 1),
if (switchlist[i] == texBot) 0, // z doesn't matter
{ MT_SWITCHTEMP,
S_StartSound(buttonlist->soundorg,sound); 0);
sides[line->sidenum[0]].bottomtexture = (short)switchlist[i^1]; S_StartSound (soundorg, sound, 78);
*texture = (short)switchlist[i^1];
if (useAgain) if (useAgain)
P_StartButton(line, bottom,switchlist[i],BUTTONTIME); P_StartButton (line, where, switchlist[i], BUTTONTIME, soundorg);
break;
return;
}
}
} }
} }
} }
// //
// P_UseSpecialLine // P_UseSpecialLine
// Called when a thing uses a special line. // Called when a thing uses a special line.
@ -219,381 +196,34 @@ void P_ChangeSwitchTexture (line_t *line, int useAgain)
// //
BOOL P_UseSpecialLine (mobj_t *thing, line_t *line, int side) BOOL P_UseSpecialLine (mobj_t *thing, line_t *line, int side)
{ {
BOOL result;
// Err... // [RH] Line needs to be setup for use activation
// Use the back sides of VERY SPECIAL lines... if ((line->flags & ML_ACTIVATIONMASK) != ML_ACTIVATEUSE)
if (side) return false;
{
switch(line->special)
{
case 124:
// Sliding door open&close
// UNUSED?
break;
default: // [RH] Don't let monsters activate the special unless the line says they can.
return false; // (Some lines automatically imply ML_MONSTERSCANACTIVATE)
break; if (!thing->player) {
}
}
// Switches that other things can activate.
if (!thing->player)
{
// never open secret doors
if (line->flags & ML_SECRET) if (line->flags & ML_SECRET)
return false; // monsters never activate secrets
if (!(line->flags & ML_MONSTERSCANACTIVATE) &&
(line->special != Door_Raise || line->args[0] != 0) &&
line->special != Teleport &&
line->special != Teleport_NoFog)
return false; return false;
switch(line->special)
{
case 1: // MANUAL DOOR RAISE
case 32: // MANUAL BLUE
case 33: // MANUAL RED
case 34: // MANUAL YELLOW
break;
default:
return false;
break;
}
} }
// [RH] Use LineSpecials[] dispatcher table.
result = LineSpecials[line->special] (line, thing, line->args[0],
line->args[1], line->args[2],
line->args[3], line->args[4]);
// do something // [RH] It's possible for a script to render the line unusable even if it has the
switch (line->special) // repeatable flag set by calling clearlinespecial().
{ if (result)
// MANUALS P_ChangeSwitchTexture (line, (line->flags & ML_REPEATABLE) && line->special);
case 1: // Vertical Door
case 26: // Blue Door/Locked
case 27: // Yellow Door /Locked
case 28: // Red Door /Locked
case 31: // Manual door open return result;
case 32: // Blue locked door open
case 33: // Red locked door open
case 34: // Yellow locked door open
case 117: // Blazing door raise
case 118: // Blazing door open
EV_VerticalDoor (line, thing);
break;
//UNUSED - Door Slide Open&Close
// case 124:
// EV_SlidingDoor (line, thing);
// break;
// SWITCHES
case 7:
// Build Stairs
if (EV_BuildStairs(line,build8))
P_ChangeSwitchTexture(line,0);
break;
case 9:
// Change Donut
if (EV_DoDonut(line))
P_ChangeSwitchTexture(line,0);
break;
case 11:
// Exit level
if (CheckIfExitIsGood (thing)) {
P_ChangeSwitchTexture(line,0);
G_ExitLevel ();
}
break;
case 14:
// Raise Floor 32 and change texture
if (EV_DoPlat(line,raiseAndChange,32))
P_ChangeSwitchTexture(line,0);
break;
case 15:
// Raise Floor 24 and change texture
if (EV_DoPlat(line,raiseAndChange,24))
P_ChangeSwitchTexture(line,0);
break;
case 18:
// Raise Floor to next highest floor
if (EV_DoFloor(line, raiseFloorToNearest))
P_ChangeSwitchTexture(line,0);
break;
case 20:
// Raise Plat next highest floor and change texture
if (EV_DoPlat(line,raiseToNearestAndChange,0))
P_ChangeSwitchTexture(line,0);
break;
case 21:
// PlatDownWaitUpStay
if (EV_DoPlat(line,downWaitUpStay,0))
P_ChangeSwitchTexture(line,0);
break;
case 23:
// Lower Floor to Lowest
if (EV_DoFloor(line,lowerFloorToLowest))
P_ChangeSwitchTexture(line,0);
break;
case 29:
// Raise Door
if (EV_DoDoor(line,normal))
P_ChangeSwitchTexture(line,0);
break;
case 41:
// Lower Ceiling to Floor
if (EV_DoCeiling(line,lowerToFloor))
P_ChangeSwitchTexture(line,0);
break;
case 71:
// Turbo Lower Floor
if (EV_DoFloor(line,turboLower))
P_ChangeSwitchTexture(line,0);
break;
case 49:
// Ceiling Crush And Raise
if (EV_DoCeiling(line,crushAndRaise))
P_ChangeSwitchTexture(line,0);
break;
case 50:
// Close Door
if (EV_DoDoor(line,close))
P_ChangeSwitchTexture(line,0);
break;
case 51:
// Secret EXIT
if (CheckIfExitIsGood (thing)) {
P_ChangeSwitchTexture(line,0);
G_SecretExitLevel ();
}
break;
case 55:
// Raise Floor Crush
if (EV_DoFloor(line,raiseFloorCrush))
P_ChangeSwitchTexture(line,0);
break;
case 101:
// Raise Floor
if (EV_DoFloor(line,raiseFloor))
P_ChangeSwitchTexture(line,0);
break;
case 102:
// Lower Floor to Surrounding floor height
if (EV_DoFloor(line,lowerFloor))
P_ChangeSwitchTexture(line,0);
break;
case 103:
// Open Door
if (EV_DoDoor(line,open))
P_ChangeSwitchTexture(line,0);
break;
case 111:
// Blazing Door Raise (faster than TURBO!)
if (EV_DoDoor (line,blazeRaise))
P_ChangeSwitchTexture(line,0);
break;
case 112:
// Blazing Door Open (faster than TURBO!)
if (EV_DoDoor (line,blazeOpen))
P_ChangeSwitchTexture(line,0);
break;
case 113:
// Blazing Door Close (faster than TURBO!)
if (EV_DoDoor (line,blazeClose))
P_ChangeSwitchTexture(line,0);
break;
case 122:
// Blazing PlatDownWaitUpStay
if (EV_DoPlat(line,blazeDWUS,0))
P_ChangeSwitchTexture(line,0);
break;
case 127:
// Build Stairs Turbo 16
if (EV_BuildStairs(line,turbo16))
P_ChangeSwitchTexture(line,0);
break;
case 131:
// Raise Floor Turbo
if (EV_DoFloor(line,raiseFloorTurbo))
P_ChangeSwitchTexture(line,0);
break;
case 133:
// BlzOpenDoor BLUE
case 135:
// BlzOpenDoor RED
case 137:
// BlzOpenDoor YELLOW
if (EV_DoLockedDoor (line,blazeOpen,thing))
P_ChangeSwitchTexture(line,0);
break;
case 140:
// Raise Floor 512
if (EV_DoFloor(line,raiseFloor512))
P_ChangeSwitchTexture(line,0);
break;
// BUTTONS
case 42:
// Close Door
if (EV_DoDoor(line,close))
P_ChangeSwitchTexture(line,1);
break;
case 43:
// Lower Ceiling to Floor
if (EV_DoCeiling(line,lowerToFloor))
P_ChangeSwitchTexture(line,1);
break;
case 45:
// Lower Floor to Surrounding floor height
if (EV_DoFloor(line,lowerFloor))
P_ChangeSwitchTexture(line,1);
break;
case 60:
// Lower Floor to Lowest
if (EV_DoFloor(line,lowerFloorToLowest))
P_ChangeSwitchTexture(line,1);
break;
case 61:
// Open Door
if (EV_DoDoor(line,open))
P_ChangeSwitchTexture(line,1);
break;
case 62:
// PlatDownWaitUpStay
if (EV_DoPlat(line,downWaitUpStay,1))
P_ChangeSwitchTexture(line,1);
break;
case 63:
// Raise Door
if (EV_DoDoor(line,normal))
P_ChangeSwitchTexture(line,1);
break;
case 64:
// Raise Floor to ceiling
if (EV_DoFloor(line,raiseFloor))
P_ChangeSwitchTexture(line,1);
break;
case 66:
// Raise Floor 24 and change texture
if (EV_DoPlat(line,raiseAndChange,24))
P_ChangeSwitchTexture(line,1);
break;
case 67:
// Raise Floor 32 and change texture
if (EV_DoPlat(line,raiseAndChange,32))
P_ChangeSwitchTexture(line,1);
break;
case 65:
// Raise Floor Crush
if (EV_DoFloor(line,raiseFloorCrush))
P_ChangeSwitchTexture(line,1);
break;
case 68:
// Raise Plat to next highest floor and change texture
if (EV_DoPlat(line,raiseToNearestAndChange,0))
P_ChangeSwitchTexture(line,1);
break;
case 69:
// Raise Floor to next highest floor
if (EV_DoFloor(line, raiseFloorToNearest))
P_ChangeSwitchTexture(line,1);
break;
case 70:
// Turbo Lower Floor
if (EV_DoFloor(line,turboLower))
P_ChangeSwitchTexture(line,1);
break;
case 114:
// Blazing Door Raise (faster than TURBO!)
if (EV_DoDoor (line,blazeRaise))
P_ChangeSwitchTexture(line,1);
break;
case 115:
// Blazing Door Open (faster than TURBO!)
if (EV_DoDoor (line,blazeOpen))
P_ChangeSwitchTexture(line,1);
break;
case 116:
// Blazing Door Close (faster than TURBO!)
if (EV_DoDoor (line,blazeClose))
P_ChangeSwitchTexture(line,1);
break;
case 123:
// Blazing PlatDownWaitUpStay
if (EV_DoPlat(line,blazeDWUS,0))
P_ChangeSwitchTexture(line,1);
break;
case 132:
// Raise Floor Turbo
if (EV_DoFloor(line,raiseFloorTurbo))
P_ChangeSwitchTexture(line,1);
break;
case 99:
// BlzOpenDoor BLUE
case 134:
// BlzOpenDoor RED
case 136:
// BlzOpenDoor YELLOW
if (EV_DoLockedDoor (line,blazeOpen,thing))
P_ChangeSwitchTexture(line,1);
break;
case 138:
// Light Turn On
EV_LightTurnOn(line,255);
P_ChangeSwitchTexture(line,1);
break;
case 139:
// Light Turn Off
EV_LightTurnOn(line,35);
P_ChangeSwitchTexture(line,1);
break;
}
return true;
} }

View file

@ -25,10 +25,13 @@
#include "z_zone.h" #include "z_zone.h"
#include "p_local.h" #include "p_local.h"
#include "p_acs.h"
#include "c_consol.h"
#include "doomstat.h" #include "doomstat.h"
extern int ConsoleState; extern constate_e ConsoleState;
extern gamestate_t wipegamestate;
// //
// THINKERS // THINKERS
@ -41,7 +44,7 @@ extern int ConsoleState;
// Both the head and tail of the thinker list. // Both the head and tail of the thinker list.
thinker_t thinkercap; thinker_t thinkercap;
// //
@ -49,7 +52,7 @@ thinker_t thinkercap;
// //
void P_InitThinkers (void) void P_InitThinkers (void)
{ {
thinkercap.prev = thinkercap.next = &thinkercap; thinkercap.prev = thinkercap.next = &thinkercap;
} }
@ -130,7 +133,7 @@ void P_RunThinkers (void)
void P_Ticker (void) void P_Ticker (void)
{ {
int i; int i;
// run the tic // run the tic
if (paused) if (paused)
@ -138,23 +141,36 @@ void P_Ticker (void)
// pause if in menu or console and at least one tic has been run // pause if in menu or console and at least one tic has been run
if ( !netgame if ( !netgame
&& (menuactive || ConsoleState == 1 || ConsoleState == 2) && (menuactive || ConsoleState == c_down || ConsoleState == c_falling)
&& !demoplayback && !demoplayback
&& !demorecording && !demorecording
&& players[consoleplayer].viewz != 1) && players[consoleplayer].viewz != 1
&& wipegamestate == gamestate)
{ {
return; return;
} }
for (i=0 ; i<MAXPLAYERS ; i++) for (i = 0; i<MAXPLAYERS; i++)
if (playeringame[i]) if (playeringame[i])
P_PlayerThink (&players[i]); P_PlayerThink (&players[i]);
P_RunThinkers (); P_RunThinkers ();
P_RunScripts (); // [RH] Execute any active scripts
P_RunQuakes (); // [RH] Shake the earth a little
P_UpdateSpecials (); P_UpdateSpecials ();
P_RespawnSpecials (); P_RespawnSpecials ();
// [RH] Apply falling damage
for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i]) {
P_FallingDamage (players[i].mo);
players[i].oldvelocity[0] = players[i].mo->momx;
players[i].oldvelocity[1] = players[i].mo->momy;
players[i].oldvelocity[2] = players[i].mo->momz;
}
// for par times // for par times
level.time++; level.time++;
} }

View file

@ -28,10 +28,9 @@
#include "doomdef.h" #include "doomdef.h"
#include "d_event.h" #include "d_event.h"
#include "p_local.h" #include "p_local.h"
#include "doomstat.h" #include "doomstat.h"
#include "s_sound.h"
@ -80,14 +79,20 @@ void P_CalcHeight (player_t* player)
// OPTIMIZE: tablify angle // OPTIMIZE: tablify angle
// Note: a LUT allows for effects // Note: a LUT allows for effects
// like a ramp with low health. // like a ramp with low health.
player->bob = player->bob = FixedMul(player->mo->momx,player->mo->momx)
FixedMul (player->mo->momx, player->mo->momx) + FixedMul(player->mo->momy,player->mo->momy);
+ FixedMul (player->mo->momy,player->mo->momy);
player->bob >>= 2; player->bob >>= 2;
if (player->bob>MAXBOB) // phares 9/9/98: If player is standing on ice, reduce his bobbing.
player->bob = MAXBOB;
if (player->mo->friction > ORIG_FRICTION) // ice?
{
if (player->bob > (MAXBOB>>2))
player->bob = MAXBOB>>2;
}
else // ^
if (player->bob > MAXBOB) // |
player->bob = MAXBOB; // phares 2/26/98
if ((player->cheats & CF_NOMOMENTUM) || !onground) if ((player->cheats & CF_NOMOMENTUM) || !onground)
{ {
@ -96,7 +101,11 @@ void P_CalcHeight (player_t* player)
if (player->viewz > player->mo->ceilingz-4*FRACUNIT) if (player->viewz > player->mo->ceilingz-4*FRACUNIT)
player->viewz = player->mo->ceilingz-4*FRACUNIT; player->viewz = player->mo->ceilingz-4*FRACUNIT;
player->viewz = player->mo->z + player->viewheight; // The following line was in the Id source and appears // phares 2/25/98
// to be a bug. player->viewz is checked in a similar
// manner at a different exit below.
// player->viewz = player->mo->z + player->viewheight;
return; return;
} }
@ -143,26 +152,33 @@ void P_CalcHeight (player_t* player)
void P_MovePlayer (player_t *player) void P_MovePlayer (player_t *player)
{ {
ticcmd_t *cmd = &player->cmd; ticcmd_t *cmd = &player->cmd;
int movefactor; // movement factor // phares
fixed_t forwardmove;
fixed_t sidemove;
player->mo->angle += (cmd->ucmd.yaw<<16); player->mo->angle += (cmd->ucmd.yaw<<16);
// [RH] allow very limited movement if not on ground.
onground = P_FindFloor (player->mo); onground = P_FindFloor (player->mo);
if (onground) { movefactor = P_GetMoveFactor (player->mo);
if (cmd->ucmd.forwardmove) if (!onground) {
P_Thrust (player, player->mo->angle, cmd->ucmd.forwardmove*8); if (!olddemo) {
// [RH] allow very limited movement if not on ground.
if (cmd->ucmd.sidemove) movefactor >>= 8;
P_Thrust (player, player->mo->angle-ANG90, cmd->ucmd.sidemove*8); } else {
} else if (!olddemo) { movefactor = 0;
if (cmd->ucmd.forwardmove) }
P_Thrust (player, player->mo->angle, cmd->ucmd.forwardmove/8);
if (cmd->ucmd.sidemove)
P_Thrust (player, player->mo->angle-ANG90, cmd->ucmd.sidemove/8);
} }
forwardmove = (cmd->ucmd.forwardmove * movefactor) >> 8;
sidemove = (cmd->ucmd.sidemove * movefactor) >> 8;
if (forwardmove)
P_Thrust (player, player->mo->angle, forwardmove);
if (sidemove)
P_Thrust (player, player->mo->angle-ANG90, sidemove);
if ( (cmd->ucmd.forwardmove || cmd->ucmd.sidemove) if ( (cmd->ucmd.forwardmove || cmd->ucmd.sidemove)
&& player->mo->state == &states[S_PLAY] ) && player->mo->state == &states[S_PLAY] )
{ {
@ -170,6 +186,60 @@ void P_MovePlayer (player_t *player)
} }
} }
// [RH] (Adapted from Q2)
// P_FallingDamage
//
void P_FallingDamage (mobj_t *ent)
{
mobj_t *groundentity;
float delta;
int damage;
if (!ent->player)
return; // not a player
if (ent->flags & MF_NOCLIP)
return;
groundentity = P_FindFloor (ent);
if ((ent->player->oldvelocity[2] < 0) && (ent->momz > ent->player->oldvelocity[2]) && (!groundentity))
{
delta = (float)ent->player->oldvelocity[2];
}
else
{
if (!groundentity)
return;
delta = (float)(ent->momz - ent->player->oldvelocity[2]);
}
delta = delta*delta * 2.03904313e-11f;
if (delta < 1)
return;
if (delta < 15)
{
//ent->s.event = EV_FOOTSTEP;
return;
}
if (delta > 30)
{
damage = (int)((delta-30)/2);
if (damage < 1)
damage = 1;
if (dmflags & DF_YES_FALLING)
P_DamageMobj (ent, NULL, NULL, damage, MOD_FALLING);
}
else
{
//ent->s.event = EV_FALLSHORT;
return;
}
}
// //
@ -237,11 +307,13 @@ void P_DeathThink (player_t* player)
// //
// P_PlayerThink // P_PlayerThink
// //
void P_PlayerThink (player_t* player) void P_PlayerThink (player_t *player)
{ {
ticcmd_t* cmd; ticcmd_t *cmd;
weapontype_t newweapon; weapontype_t newweapon;
player->xviewshift = 0; // [RH] Make sure view is in right place
// fixme: do this in the cheat code // fixme: do this in the cheat code
if (player->cheats & CF_NOCLIP) if (player->cheats & CF_NOCLIP)
player->mo->flags |= MF_NOCLIP; player->mo->flags |= MF_NOCLIP;
@ -299,7 +371,7 @@ void P_PlayerThink (player_t* player)
P_CalcHeight (player); P_CalcHeight (player);
if (player->mo->subsector->sector->special) if (player->mo->subsector->sector->special || player->mo->subsector->sector->damage)
P_PlayerInSpecialSector (player); P_PlayerInSpecialSector (player);
// Check for weapon change. // Check for weapon change.
@ -307,45 +379,64 @@ void P_PlayerThink (player_t* player)
// A special event has no other buttons. // A special event has no other buttons.
if (cmd->ucmd.buttons & BT_SPECIAL) if (cmd->ucmd.buttons & BT_SPECIAL)
cmd->ucmd.buttons = 0; cmd->ucmd.buttons = 0;
if (cmd->ucmd.buttons & BT_CHANGE) if ((cmd->ucmd.buttons & BT_CHANGE) || cmd->ucmd.impulse >= 50)
{ {
// The actual changing of the weapon is done // [RH] Support direct weapon changes
// when the weapon psprite can do it if (cmd->ucmd.impulse) {
// (read: not in the middle of an attack). newweapon = cmd->ucmd.impulse - 50;
newweapon = (cmd->ucmd.buttons&BT_WEAPONMASK)>>BT_WEAPONSHIFT; } else {
// The actual changing of the weapon is done
if (newweapon == wp_fist // when the weapon psprite can do it
&& player->weaponowned[wp_chainsaw] // (read: not in the middle of an attack).
&& !(player->readyweapon == wp_chainsaw newweapon = (cmd->ucmd.buttons&BT_WEAPONMASK)>>BT_WEAPONSHIFT;
&& player->powers[pw_strength]))
{ if (newweapon == wp_fist
newweapon = wp_chainsaw; && player->weaponowned[wp_chainsaw]
} && !(player->readyweapon == wp_chainsaw
&& player->powers[pw_strength]))
if ( (gamemode == commercial)
&& newweapon == wp_shotgun
&& player->weaponowned[wp_supershotgun]
&& player->readyweapon != wp_supershotgun)
{
newweapon = wp_supershotgun;
}
if (player->weaponowned[newweapon]
&& newweapon != player->readyweapon)
{
// Do not go to plasma or BFG in shareware,
// even if cheated.
if ((newweapon != wp_plasma
&& newweapon != wp_bfg)
|| (gamemode != shareware) )
{ {
player->pendingweapon = newweapon; newweapon = wp_chainsaw;
}
if ( (gamemode == commercial)
&& newweapon == wp_shotgun
&& player->weaponowned[wp_supershotgun]
&& player->readyweapon != wp_supershotgun)
{
newweapon = wp_supershotgun;
}
}
if (newweapon >= 0 && newweapon < NUMWEAPONS) {
if (player->weaponowned[newweapon]
&& newweapon != player->readyweapon)
{
// Do not go to plasma or BFG in shareware,
// even if cheated.
if ((newweapon != wp_plasma
&& newweapon != wp_bfg)
|| (gamemode != shareware) )
{
player->pendingweapon = newweapon;
}
} }
} }
} }
// [RH] check for jump
if ((cmd->ucmd.buttons & BT_JUMP) == BT_JUMP) {
if (!player->jumpdown && !(dmflags & DF_NO_JUMP)) {
// only jump if we are on the ground
if (P_FindFloor (player->mo)) {
player->mo->momz += 8 * FRACUNIT;
player->mo->flags2 |= MF2_JUMPING;
S_StartSound (player->mo, "*jump1", 100);
}
player->jumpdown = true;
}
} else player->jumpdown = false;
// check for use // check for use
if (cmd->ucmd.buttons & BT_USE) if (cmd->ucmd.buttons & BT_USE)
{ {
@ -358,16 +449,6 @@ void P_PlayerThink (player_t* player)
else else
player->usedown = false; player->usedown = false;
// [RH] check for jump
if ((cmd->ucmd.buttons & BT_JUMP) == BT_JUMP) {
if (!player->jumpdown && !(dmflags & DF_NO_JUMP)) {
// only jump if we are on the ground
if (P_FindFloor (player->mo))
player->mo->momz += 8 * FRACUNIT;
player->jumpdown = true;
}
} else player->jumpdown = false;
// cycle psprites // cycle psprites
P_MovePsprites (player); P_MovePsprites (player);
@ -421,4 +502,3 @@ void P_PlayerThink (player_t* player)
player->fixedcolormap = 0; player->fixedcolormap = 0;
} }

613
code/P_xlat.c Normal file
View file

@ -0,0 +1,613 @@
// p_xlat.c: Translate old linedefs to new linedefs
#include "doomtype.h"
#include "p_lnspec.h"
#include "doomdata.h"
#include "r_data.h"
#include "m_swap.h"
#include "p_spec.h"
#include "p_local.h"
// Speeds for ceilings/crushers (x/8 units per tic)
// (Hexen crushers go up at half the speed that they go down)
#define C_SLOW 8
#define C_NORMAL 16
#define C_FAST 32
#define C_TURBO 64
#define CEILWAIT 150
// Speeds for floors (x/8 units per tic)
#define F_SLOW 8
#define F_NORMAL 16
#define F_FAST 32
#define F_TURBO 64
// Speeds for doors (x/8 units per tic)
#define D_SLOW 16
#define D_NORMAL 32
#define D_FAST 64
#define D_TURBO 128
#define VDOORWAIT 150
// Speeds for stairs (x/8 units per tic)
#define S_SLOW 2
#define S_NORMAL 4
#define S_FAST 16
#define S_TURBO 32
// Speeds for plats (Hexen plats stop 8 units above the floor)
#define P_SLOW 8
#define P_NORMAL 16
#define P_FAST 32
#define P_TURBO 64
#define PLATWAIT 105
#define ELEVATORSPEED 32
// Speeds for donut slime and pillar (x/8 units per tic)
#define DORATE 4
// Texture scrollers operate at a rate of x/64 units per tic.
#define SCROLL_UNIT 64
//Define masks, shifts, for fields in generalized linedef types
// (from BOOM's p_psec.h file)
#define GenFloorBase 0x6000
#define GenCeilingBase 0x4000
#define GenDoorBase 0x3c00
#define GenLockedBase 0x3800
#define GenLiftBase 0x3400
#define GenStairsBase 0x3000
#define GenCrusherBase 0x2F80
// define names for the TriggerType field of the general linedefs
typedef enum
{
WalkOnce,
WalkMany,
SwitchOnce,
SwitchMany,
GunOnce,
GunMany,
PushOnce,
PushMany,
} triggertype_e;
// Line special translation structure
typedef struct {
byte flags;
byte newspecial;
byte args[5];
} xlat_t;
#define TAG 123 // Special value that gets replaced with the line tag
#define WALK (ML_ACTIVATECROSS>>8)
#define USE (ML_ACTIVATEUSE>>8)
#define SHOOT (ML_ACTIVATEPROJECTILEHIT>>8)
#define MONST (ML_MONSTERSCANACTIVATE>>8)
#define MONWALK (ML_ACTIVATEMONSTERCROSS>>8)
#define REP (ML_REPEATABLE>>8)
static const xlat_t SpecialTranslation[] = {
/* 0 */ { 0 },
/* 1 */ { USE|MONST|REP, Door_Raise, { 0, D_SLOW, VDOORWAIT } },
/* 2 */ { WALK, Door_Open, { TAG, D_SLOW } },
/* 3 */ { WALK, Door_Close, { TAG, D_SLOW } },
/* 4 */ { WALK|MONST, Door_Raise, { TAG, D_SLOW, VDOORWAIT } },
/* 5 */ { WALK, Floor_RaiseToLowestCeiling, { TAG, F_SLOW } },
/* 6 */ { WALK, Ceiling_CrushAndRaiseA, { TAG, C_NORMAL, C_NORMAL, 10 } },
/* 7 */ { USE, Stairs_BuildUpDoom, { TAG, S_SLOW, 8 } },
/* 8 */ { WALK, Stairs_BuildUpDoom, { TAG, S_SLOW, 8 } },
/* 9 */ { USE, Floor_Donut, { TAG, DORATE, DORATE } },
/* 10 */ { WALK|MONST, Plat_DownWaitUpStayLip, { TAG, P_FAST, PLATWAIT, 0 } },
/* 11 */ { USE, Exit_Normal, { 0 } },
/* 12 */ { WALK, Light_MaxNeighbor, { TAG } },
/* 13 */ { WALK, Light_ChangeToValue, { TAG, 255 } },
/* 14 */ { USE, Plat_UpByValueStayTx, { TAG, P_SLOW/2, 4 } },
/* 15 */ { USE, Plat_UpByValueStayTx, { TAG, P_SLOW/2, 3 } },
/* 16 */ { WALK, Door_CloseWaitOpen, { TAG, D_SLOW, 240 } },
/* 17 */ { WALK, Light_StrobeDoom, { TAG, 5, 35 } },
/* 18 */ { USE, Floor_RaiseToNearest, { TAG, F_SLOW } },
/* 19 */ { WALK, Floor_LowerToHighest, { TAG, F_SLOW, 128 } },
/* 20 */ { USE, Plat_RaiseAndStayTx0, { TAG, P_SLOW/2 } },
/* 21 */ { USE, Plat_DownWaitUpStayLip, { TAG, P_FAST, PLATWAIT } },
/* 22 */ { WALK, Plat_RaiseAndStayTx0, { TAG, P_SLOW/2 } },
/* 23 */ { USE, Floor_LowerToLowest, { TAG, F_SLOW } },
/* 24 */ { SHOOT, Floor_RaiseToLowestCeiling, { TAG, F_SLOW } },
/* 25 */ { WALK, Ceiling_CrushAndRaiseA, { TAG, C_SLOW, C_SLOW, 10 } },
/* 26 */ { USE|REP, Door_LockedRaise, { TAG, D_SLOW, VDOORWAIT, BCard | CardIsSkull } },
/* 27 */ { USE|REP, Door_LockedRaise, { TAG, D_SLOW, VDOORWAIT, YCard | CardIsSkull } },
/* 28 */ { USE|REP, Door_LockedRaise, { TAG, D_SLOW, VDOORWAIT, RCard | CardIsSkull } },
/* 29 */ { USE, Door_Raise, { TAG, D_SLOW, VDOORWAIT } },
/* 30 */ { WALK, Floor_RaiseByTexture, { TAG, F_SLOW } },
/* 31 */ { USE, Door_Open, { 0, D_SLOW } },
/* 32 */ { USE|MONST, Door_LockedRaise, { 0, D_SLOW, 0, BCard | CardIsSkull } },
/* 33 */ { USE|MONST, Door_LockedRaise, { 0, D_SLOW, 0, RCard | CardIsSkull } },
/* 34 */ { USE|MONST, Door_LockedRaise, { 0, D_SLOW, 0, YCard | CardIsSkull } },
/* 35 */ { WALK, Light_ChangeToValue, { TAG, 35 } },
/* 36 */ { WALK, Floor_LowerToHighest, { TAG, F_FAST, 136 } },
/* 37 */ { WALK, Floor_LowerToLowestTxTy, { TAG, F_SLOW } },
/* 38 */ { WALK, Floor_LowerToLowest, { TAG, F_SLOW } },
/* 39 */ { WALK|MONST, Teleport, { TAG } },
/* 40 */ { WALK, Generic_Ceiling, { TAG, C_SLOW, 0, 1, 8 } },
/* 41 */ { USE, Ceiling_LowerToFloor, { TAG, C_SLOW } },
/* 42 */ { USE|REP, Door_Close, { TAG, D_SLOW } },
/* 43 */ { USE|REP, Ceiling_LowerToFloor, { TAG, C_SLOW } },
/* 44 */ { WALK, Ceiling_LowerAndCrush, { TAG, C_SLOW, 0 } },
/* 45 */ { USE|REP, Floor_LowerToHighest, { TAG, F_SLOW, 128 } },
/* 46 */ { SHOOT|REP|MONST,Door_Open, { TAG, D_SLOW } },
/* 47 */ { SHOOT, Plat_RaiseAndStayTx0, { TAG, P_SLOW/2 } },
/* 48 */ { 0, Scroll_Texture_Left, { SCROLL_UNIT } },
/* 49 */ { USE, Ceiling_CrushAndRaiseA, { TAG, C_SLOW, C_SLOW, 10 } },
/* 50 */ { USE, Door_Close, { TAG, D_SLOW } },
/* 51 */ { USE, Exit_Secret, { 0 } },
/* 52 */ { WALK, Exit_Normal, { 0 } },
/* 53 */ { WALK, Plat_PerpetualRaiseLip, { TAG, P_SLOW, PLATWAIT, 0 } },
/* 54 */ { WALK, Plat_Stop, { TAG } },
/* 55 */ { USE, Floor_RaiseAndCrush, { TAG, F_SLOW, 10 } },
/* 56 */ { WALK, Floor_RaiseAndCrush, { TAG, F_SLOW, 10 } },
/* 57 */ { WALK, Ceiling_CrushStop, { TAG } },
/* 58 */ { WALK, Floor_RaiseByValue, { TAG, F_SLOW, 24 } },
/* 59 */ { WALK, Floor_RaiseByValueTxTy, { TAG, F_SLOW, 24 } },
/* 60 */ { USE|REP, Floor_LowerToLowest, { TAG, F_SLOW } },
/* 61 */ { USE|REP, Door_Open, { TAG, D_SLOW } },
/* 62 */ { USE|REP, Plat_DownWaitUpStayLip, { TAG, P_FAST, PLATWAIT, 0 } },
/* 63 */ { USE|REP, Door_Raise, { TAG, D_SLOW, VDOORWAIT } },
/* 64 */ { USE|REP, Floor_RaiseToLowestCeiling, { TAG, F_SLOW } },
/* 65 */ { USE|REP, Floor_RaiseAndCrush, { TAG, F_SLOW, 10 } },
/* 66 */ { USE|REP, Plat_UpByValueStayTx, { TAG, P_SLOW/2, 3 } },
/* 67 */ { USE|REP, Plat_UpByValueStayTx, { TAG, P_SLOW/2, 4 } },
/* 68 */ { USE|REP, Plat_RaiseAndStayTx0, { TAG, P_SLOW/2 } },
/* 69 */ { USE|REP, Floor_RaiseToNearest, { TAG, F_SLOW } },
/* 70 */ { USE|REP, Floor_LowerToHighest, { TAG, F_FAST, 136 } },
/* 71 */ { USE, Floor_LowerToHighest, { TAG, F_FAST, 136 } },
/* 72 */ { WALK|REP, Ceiling_LowerAndCrush, { TAG, C_SLOW, 0 } },
/* 73 */ { WALK|REP, Ceiling_CrushAndRaiseA, { TAG, C_SLOW, C_SLOW, 10 } },
/* 74 */ { WALK|REP, Ceiling_CrushStop, { TAG } },
/* 75 */ { WALK|REP, Door_Close, { TAG, D_SLOW } },
/* 76 */ { WALK|REP, Door_CloseWaitOpen, { TAG, D_SLOW, 240 } },
/* 77 */ { WALK|REP, Ceiling_CrushAndRaiseA, { TAG, C_NORMAL, C_NORMAL, 10 } },
/* 78 */ { USE|REP, Floor_TransferNumeric, { TAG } }, // <- BOOM special
/* 79 */ { WALK|REP, Light_ChangeToValue, { TAG, 35 } },
/* 80 */ { WALK|REP, Light_MaxNeighbor, { TAG } },
/* 81 */ { WALK|REP, Light_ChangeToValue, { TAG, 255 } },
/* 82 */ { WALK|REP, Floor_LowerToLowest, { TAG, F_SLOW } },
/* 83 */ { WALK|REP, Floor_LowerToHighest, { TAG, F_SLOW, 128 } },
/* 84 */ { WALK|REP, Floor_LowerToLowestTxTy, { TAG, F_SLOW } },
/* 85 */ { 0, Scroll_Texture_Right, { SCROLL_UNIT } }, // <- BOOM special
/* 86 */ { WALK|REP, Door_Open, { TAG, D_SLOW } },
/* 87 */ { WALK|REP, Plat_PerpetualRaiseLip, { TAG, P_SLOW, PLATWAIT, 0 } },
/* 88 */ { WALK|REP|MONST, Plat_DownWaitUpStayLip, { TAG, P_FAST, PLATWAIT, 0 } },
/* 89 */ { WALK|REP, Plat_Stop, { TAG } },
/* 90 */ { WALK|REP, Door_Raise, { TAG, D_SLOW, VDOORWAIT } },
/* 91 */ { WALK|REP, Floor_RaiseToLowestCeiling, { TAG, F_SLOW } },
/* 92 */ { WALK|REP, Floor_RaiseByValue, { TAG, F_SLOW, 24 } },
/* 93 */ { WALK|REP, Floor_RaiseByValueTxTy, { TAG, F_SLOW, 24 } },
/* 94 */ { WALK|REP, Floor_RaiseAndCrush, { TAG, F_SLOW, 10 } },
/* 95 */ { WALK|REP, Plat_RaiseAndStayTx0, { TAG, P_SLOW/2 } },
/* 96 */ { WALK|REP, Floor_RaiseByTexture, { TAG, F_SLOW } },
/* 97 */ { WALK|REP|MONST, Teleport, { TAG } },
/* 98 */ { WALK|REP, Floor_LowerToHighest, { TAG, F_FAST, 136 } },
/* 99 */ { USE|REP, Door_LockedRaise, { TAG, D_FAST, 0, BCard | CardIsSkull } },
/* 100 */ { WALK, Stairs_BuildUpDoom, { TAG, S_TURBO, 16, 0, 0 } },
/* 101 */ { USE, Floor_RaiseToLowestCeiling, { TAG, F_SLOW } },
/* 102 */ { USE, Floor_LowerToHighest, { TAG, F_SLOW, 128 } },
/* 103 */ { USE, Door_Open, { TAG, D_SLOW } },
/* 104 */ { WALK, Light_MinNeighbor, { TAG } },
/* 105 */ { WALK|REP, Door_Raise, { TAG, D_FAST, VDOORWAIT } },
/* 106 */ { WALK|REP, Door_Open, { TAG, D_FAST } },
/* 107 */ { WALK|REP, Door_Close, { TAG, D_FAST } },
/* 108 */ { WALK, Door_Raise, { TAG, D_FAST, VDOORWAIT } },
/* 109 */ { WALK, Door_Open, { TAG, D_FAST } },
/* 110 */ { WALK, Door_Close, { TAG, D_FAST } },
/* 111 */ { USE, Door_Raise, { TAG, D_FAST, VDOORWAIT } },
/* 112 */ { USE, Door_Open, { TAG, D_FAST } },
/* 113 */ { USE, Door_Close, { TAG, D_FAST } },
/* 114 */ { USE|REP, Door_Raise, { TAG, D_FAST, VDOORWAIT } },
/* 115 */ { USE|REP, Door_Open, { TAG, D_FAST } },
/* 116 */ { USE|REP, Door_Close, { TAG, D_FAST } },
/* 117 */ { USE|REP, Door_Raise, { 0, D_FAST, VDOORWAIT } },
/* 118 */ { USE, Door_Open, { 0, D_FAST } },
/* 119 */ { WALK, Floor_RaiseToNearest, { TAG, F_SLOW } },
/* 120 */ { WALK|REP, Plat_DownWaitUpStayLip, { TAG, P_TURBO, PLATWAIT, 0 } },
/* 121 */ { WALK, Plat_DownWaitUpStayLip, { TAG, P_TURBO, PLATWAIT, 0 } },
/* 122 */ { USE, Plat_DownWaitUpStayLip, { TAG, P_TURBO, PLATWAIT, 0 } },
/* 123 */ { USE|REP, Plat_DownWaitUpStayLip, { TAG, P_TURBO, PLATWAIT, 0 } },
/* 124 */ { WALK, Exit_Secret, { 0 } },
/* 125 */ { MONWALK, Teleport, { TAG } },
/* 126 */ { MONWALK|REP, Teleport, { TAG } },
/* 127 */ { USE, Stairs_BuildUpDoom, { TAG, S_TURBO, 16, 0, 0 } },
/* 128 */ { WALK|REP, Floor_RaiseToNearest, { TAG, F_SLOW } },
/* 129 */ { WALK|REP, Floor_RaiseToNearest, { TAG, F_FAST } },
/* 130 */ { WALK, Floor_RaiseToNearest, { TAG, F_FAST } },
/* 131 */ { USE, Floor_RaiseToNearest, { TAG, F_FAST } },
/* 132 */ { USE|REP, Floor_RaiseToNearest, { TAG, F_FAST } },
/* 133 */ { USE, Door_LockedRaise, { TAG, D_FAST, 0, BCard | CardIsSkull } },
/* 134 */ { USE|REP, Door_LockedRaise, { TAG, D_FAST, 0, BCard | CardIsSkull } },
/* 135 */ { USE, Door_LockedRaise, { TAG, D_FAST, 0, RCard | CardIsSkull } },
/* 136 */ { USE|REP, Door_LockedRaise, { TAG, D_FAST, 0, YCard | CardIsSkull } },
/* 137 */ { USE, Door_LockedRaise, { TAG, D_FAST, 0, YCard | CardIsSkull } },
/* 138 */ { USE|REP, Light_ChangeToValue, { TAG, 255 } },
/* 139 */ { USE|REP, Light_ChangeToValue, { TAG, 35 } },
/* 140 */ { USE, Floor_RaiseByValueTimes8, { TAG, F_SLOW, 64 } },
/* 141 */ { WALK, Ceiling_CrushAndRaiseSilentA,{ TAG, C_SLOW, C_SLOW, 10 } },
/****** The following are all new to BOOM ******/
/* 142 */ { WALK, Floor_RaiseByValueTimes8, { TAG, F_SLOW, 64 } },
/* 143 */ { WALK, Plat_UpByValueStayTx, { TAG, P_SLOW/2, 3 } },
/* 144 */ { WALK, Plat_UpByValueStayTx, { TAG, P_SLOW/2, 4 } },
/* 145 */ { WALK, Ceiling_LowerToFloor, { TAG, C_SLOW } },
/* 146 */ { WALK, Floor_Donut, { TAG, DORATE, DORATE } },
/* 147 */ { WALK|REP, Floor_RaiseByValueTimes8, { TAG, F_SLOW, 64 } },
/* 148 */ { WALK|REP, Plat_UpByValueStayTx, { TAG, P_SLOW/2, 3 } },
/* 149 */ { WALK|REP, Plat_UpByValueStayTx, { TAG, P_SLOW/2, 4 } },
/* 150 */ { WALK|REP, Ceiling_CrushAndRaiseSilentA,{ TAG, C_SLOW, C_SLOW, 10 } },
/* 151 */ { WALK|REP, FloorAndCeiling_LowerRaise, { TAG, F_SLOW, C_SLOW } },
/* 152 */ { WALK|REP, Ceiling_LowerToFloor, { TAG, C_SLOW } },
/* 153 */ { WALK, Floor_TransferTrigger, { TAG } },
/* 154 */ { WALK|REP, Floor_TransferTrigger, { TAG } },
/* 155 */ { WALK|REP, Floor_Donut, { TAG, DORATE, DORATE } },
/* 156 */ { WALK|REP, Light_StrobeDoom, { TAG, 5, 35 } },
/* 157 */ { WALK|REP, Light_MinNeighbor, { TAG } },
/* 158 */ { USE, Floor_RaiseByTexture, { TAG, F_SLOW } },
/* 159 */ { USE, Floor_LowerToLowestTxTy, { TAG, F_SLOW } },
/* 160 */ { USE, Floor_RaiseByValueTxTy, { TAG, F_SLOW, 24 } },
/* 161 */ { USE, Floor_RaiseByValue, { TAG, F_SLOW, 24 } },
/* 162 */ { USE, Plat_PerpetualRaiseLip, { TAG, P_SLOW, PLATWAIT, 0 } },
/* 163 */ { USE, Plat_Stop, { TAG } },
/* 164 */ { USE, Ceiling_CrushAndRaiseA, { TAG, C_NORMAL, C_NORMAL, 10 } },
/* 165 */ { USE, Ceiling_CrushAndRaiseSilentA,{ TAG, C_SLOW, C_SLOW, 10 } },
/* 166 */ { USE, FloorAndCeiling_LowerRaise, { TAG, F_SLOW, C_SLOW } },
/* 167 */ { USE, Ceiling_LowerAndCrush, { TAG, C_SLOW, 0 } },
/* 168 */ { USE, Ceiling_CrushStop, { TAG } },
/* 169 */ { USE, Light_MaxNeighbor, { TAG } },
/* 170 */ { USE, Light_ChangeToValue, { TAG, 35 } },
/* 171 */ { USE, Light_ChangeToValue, { TAG, 255 } },
/* 172 */ { USE, Light_StrobeDoom, { TAG, 5, 35 } },
/* 173 */ { USE, Light_MinNeighbor, { TAG } },
/* 174 */ { USE|MONST, Teleport, { TAG } },
/* 175 */ { USE, Door_CloseWaitOpen, { TAG, F_SLOW, 240 } },
/* 176 */ { USE|REP, Floor_RaiseByTexture, { TAG, F_SLOW } },
/* 177 */ { USE|REP, Floor_LowerToLowestTxTy, { TAG, F_SLOW } },
/* 178 */ { USE|REP, Floor_RaiseByValueTimes8, { TAG, F_SLOW, 64 } },
/* 179 */ { USE|REP, Floor_RaiseByValueTxTy, { TAG, F_SLOW, 24 } },
/* 180 */ { USE|REP, Floor_RaiseByValue, { TAG, F_SLOW, 24 } },
/* 181 */ { USE|REP, Plat_PerpetualRaiseLip, { TAG, P_SLOW, PLATWAIT, 0 } },
/* 182 */ { USE|REP, Plat_Stop, { TAG } },
/* 183 */ { USE|REP, Ceiling_CrushAndRaiseA, { TAG, C_NORMAL, C_NORMAL, 10 } },
/* 184 */ { USE|REP, Ceiling_CrushAndRaiseA, { TAG, C_SLOW, C_SLOW, 10 } },
/* 185 */ { USE|REP, Ceiling_CrushAndRaiseSilentA,{ TAG, C_SLOW, C_SLOW, 10 } },
/* 186 */ { USE|REP, FloorAndCeiling_LowerRaise, { TAG, F_SLOW, C_SLOW } },
/* 187 */ { USE|REP, Ceiling_LowerAndCrush, { TAG, C_SLOW, 0 } },
/* 188 */ { USE|REP, Ceiling_CrushStop, { TAG } },
/* 189 */ { USE, Floor_TransferTrigger, { TAG } },
/* 190 */ { USE|REP, Floor_TransferTrigger, { TAG } },
/* 191 */ { USE|REP, Floor_Donut, { TAG, DORATE, DORATE } },
/* 192 */ { USE|REP, Light_MaxNeighbor, { TAG } },
/* 193 */ { USE|REP, Light_StrobeDoom, { TAG, 5, 35 } },
/* 194 */ { USE|REP, Light_MinNeighbor, { TAG } },
/* 195 */ { USE|REP|MONST, Teleport, { TAG } },
/* 196 */ { USE|REP, Door_CloseWaitOpen, { TAG, D_SLOW, 240 } },
/* 197 */ { SHOOT, Exit_Normal, { 0 } },
/* 198 */ { SHOOT, Exit_Secret, { 0 } },
/* 199 */ { WALK, Ceiling_LowerToLowest, { TAG, C_SLOW } },
/* 200 */ { WALK, Ceiling_LowerToHighestFloor, { TAG, C_SLOW } },
/* 201 */ { WALK|REP, Ceiling_LowerToLowest, { TAG, C_SLOW } },
/* 202 */ { WALK|REP, Ceiling_LowerToHighestFloor, { TAG, C_SLOW } },
/* 203 */ { USE, Ceiling_LowerToLowest, { TAG, C_SLOW } },
/* 204 */ { USE, Ceiling_LowerToHighestFloor, { TAG, C_SLOW } },
/* 205 */ { USE|REP, Ceiling_LowerToLowest, { TAG, C_SLOW } },
/* 206 */ { USE|REP, Ceiling_LowerToHighestFloor, { TAG, C_SLOW } },
/* 207 */ { WALK|MONST, Teleport_NoFog, { TAG } },
/* 208 */ { WALK|REP|MONST, Teleport_NoFog, { TAG } },
/* 209 */ { USE|MONST, Teleport_NoFog, { TAG } },
/* 210 */ { USE|REP|MONST, Teleport_NoFog, { TAG } },
/* 211 */ { USE|REP, Plat_ToggleCeiling, { TAG } },
/* 212 */ { WALK|REP, Plat_ToggleCeiling, { TAG } },
/* 213 */ { 0, Transfer_FloorLight, { TAG } },
/* 214 */ { 0, Scroll_Ceiling, { TAG, 6, 0, 0, 0 } },
/* 215 */ { 0, Scroll_Floor, { TAG, 6, 0, 0, 0 } },
/* 216 */ { 0, Scroll_Floor, { TAG, 6, 1, 0, 0 } },
/* 217 */ { 0, Scroll_Floor, { TAG, 6, 2, 0, 0 } },
/* 218 */ { 0, Scroll_Texture_Model, { TAG, 2 } },
/* 219 */ { WALK, Floor_LowerToNearest, { TAG, F_SLOW } },
/* 220 */ { WALK|REP, Floor_LowerToNearest, { TAG, F_SLOW } },
/* 221 */ { USE, Floor_LowerToNearest, { TAG, F_SLOW } },
/* 222 */ { USE|REP, Floor_LowerToNearest, { TAG, F_SLOW } },
/* 223 */ { 0, Sector_SetFriction, { TAG, 0 } },
/* 224 */ { 0, Sector_SetWind, { TAG, 0, 0, 1 } },
/* 225 */ { 0, Sector_SetCurrent, { TAG, 0, 0, 1 } },
/* 226 */ { 0, PointPush_SetForce, { TAG, 0, 0, 1 } },
/* 227 */ { WALK, Elevator_RaiseToNearest, { TAG, ELEVATORSPEED } },
/* 228 */ { WALK|REP, Elevator_RaiseToNearest, { TAG, ELEVATORSPEED } },
/* 229 */ { USE, Elevator_RaiseToNearest, { TAG, ELEVATORSPEED } },
/* 230 */ { USE|REP, Elevator_RaiseToNearest, { TAG, ELEVATORSPEED } },
/* 231 */ { WALK, Elevator_LowerToNearest, { TAG, ELEVATORSPEED } },
/* 232 */ { WALK|REP, Elevator_LowerToNearest, { TAG, ELEVATORSPEED } },
/* 233 */ { USE, Elevator_LowerToNearest, { TAG, ELEVATORSPEED } },
/* 234 */ { USE|REP, Elevator_LowerToNearest, { TAG, ELEVATORSPEED } },
/* 235 */ { WALK, Elevator_MoveToFloor, { TAG, ELEVATORSPEED } },
/* 236 */ { WALK|REP, Elevator_MoveToFloor, { TAG, ELEVATORSPEED } },
/* 237 */ { USE, Elevator_MoveToFloor, { TAG, ELEVATORSPEED } },
/* 238 */ { USE|REP, Elevator_MoveToFloor, { TAG, ELEVATORSPEED } },
/* 239 */ { WALK, Floor_TransferNumeric, { TAG } },
/* 240 */ { WALK|REP, Floor_TransferNumeric, { TAG } },
/* 241 */ { USE, Floor_TransferNumeric, { TAG } },
/* 242 */ { 0, Transfer_Heights, { TAG } },
/* 243 */ { WALK|MONST, Teleport_Line, { TAG, TAG, 0 } },
/* 244 */ { WALK|REP|MONST, Teleport_Line, { TAG, TAG, 0 } },
/* 245 */ { 0, Scroll_Ceiling, { TAG, 5, 0, 0, 0 } },
/* 246 */ { 0, Scroll_Floor, { TAG, 5, 0, 0, 0 } },
/* 247 */ { 0, Scroll_Floor, { TAG, 5, 1, 0, 0 } },
/* 248 */ { 0, Scroll_Floor, { TAG, 5, 2, 0, 0 } },
/* 249 */ { 0, Scroll_Texture_Model, { TAG, 1 } },
/* 250 */ { 0, Scroll_Ceiling, { TAG, 4, 0, 0, 0 } },
/* 251 */ { 0, Scroll_Floor, { TAG, 4, 0, 0, 0 } },
/* 252 */ { 0, Scroll_Floor, { TAG, 4, 1, 0, 0 } },
/* 253 */ { 0, Scroll_Floor, { TAG, 4, 2, 0, 0 } },
/* 254 */ { 0, Scroll_Texture_Model, { TAG, 0 } },
/* 255 */ { 0, Scroll_Texture_Offsets },
/* 256 */ { WALK|REP, Stairs_BuildUpDoom, { TAG, S_SLOW, 8, 0, 0 } },
/* 257 */ { WALK|REP, Stairs_BuildUpDoom, { TAG, S_TURBO, 16, 0, 0 } },
/* 258 */ { USE|REP, Stairs_BuildUpDoom, { TAG, S_SLOW, 8, 0, 0 } },
/* 259 */ { USE|REP, Stairs_BuildUpDoom, { TAG, S_TURBO, 16, 0, 0 } },
/* 260 */ { 0, TranslucentLine, { TAG, 128 } },
/* 261 */ { 0, Transfer_CeilingLight, { TAG } },
/* 262 */ { WALK|MONST, Teleport_Line, { TAG, TAG, 1 } },
/* 263 */ { WALK|REP|MONST, Teleport_Line, { TAG, TAG, 1 } },
/* 264 */ { MONWALK, Teleport_Line, { TAG, TAG, 1 } },
/* 265 */ { MONWALK|REP, Teleport_Line, { TAG, TAG, 1 } },
/* 266 */ { MONWALK, Teleport_Line, { TAG, TAG, 0 } },
/* 267 */ { MONWALK|REP, Teleport_Line, { TAG, TAG, 0 } },
/* 268 */ { MONWALK, Teleport_NoFog, { TAG } },
/* 269 */ { MONWALK|REP, Teleport_NoFog, { TAG } }
};
#define NUM_SPECIALS 269
void P_TranslateLineDef (line_t *ld, maplinedef_t *mld)
{
short special = SHORT(mld->special);
short tag = SHORT(mld->tag);
short flags = SHORT(mld->flags);
int i;
if (flags & ML_PASSUSEORG) // Remap ML_PASSUSE flag from BOOM.
flags = (flags & ~ML_PASSUSEORG) | ML_PASSUSE;
flags = flags & 0x41ff; // Ignore flags unknown in DOOM.
if (special <= NUM_SPECIALS) {
// This is a regular special; translate thru LUT
flags = flags | (SpecialTranslation[special].flags << 8);
ld->special = SpecialTranslation[special].newspecial;
for (i = 0; i < 5; i++)
ld->args[i] = SpecialTranslation[special].args[i] == TAG ? tag :
SpecialTranslation[special].args[i];
} else if (special <= GenCrusherBase) {
// This is an unknown special. Just zero it.
ld->special = 0;
memset (ld->args, 0, sizeof(ld->args));
} else {
// Anything else is a BOOM generalized linedef type
switch (special & 0x0007) {
case WalkMany:
flags |= ML_REPEATABLE;
case WalkOnce:
flags |= ML_ACTIVATECROSS;
break;
case SwitchMany:
case PushMany:
flags |= ML_REPEATABLE;
case SwitchOnce:
case PushOnce:
flags |= ML_ACTIVATEUSE;
break;
case GunMany:
flags |= ML_REPEATABLE;
case GunOnce:
flags |= ML_ACTIVATEPROJECTILEHIT;
break;
}
// We treat push triggers like switch triggers with zero tags.
if ((special & 0x0007) == PushMany ||
(special & 0x0007) == PushOnce)
ld->args[0] = 0;
else
ld->args[0] = tag;
if (special <= GenStairsBase) {
// Generalized crusher (tag, dnspeed, upspeed, silent, damage)
ld->special = Generic_Crusher;
if (special & 0x0020)
flags |= ML_MONSTERSCANACTIVATE;
switch (special & 0x0018) {
case 0x0000: ld->args[1] = C_SLOW; break;
case 0x0008: ld->args[1] = C_NORMAL; break;
case 0x0010: ld->args[1] = C_FAST; break;
case 0x0018: ld->args[1] = C_TURBO; break;
}
ld->args[2] = ld->args[1];
ld->args[3] = (special & 0x0040) >> 6;
ld->args[4] = 10;
} else if (special <= GenLiftBase) {
// Generalized stairs (tag, speed, step, dir/igntxt, reset)
ld->special = Generic_Stairs;
if (special & 0x0020)
flags |= ML_MONSTERSCANACTIVATE;
switch (special & 0x0018) {
case 0x0000: ld->args[1] = S_SLOW; break;
case 0x0008: ld->args[1] = S_NORMAL; break;
case 0x0010: ld->args[1] = S_FAST; break;
case 0x0018: ld->args[1] = S_TURBO; break;
}
switch (special & 0x00c0) {
case 0x0000: ld->args[2] = 4; break;
case 0x0040: ld->args[2] = 8; break;
case 0x0080: ld->args[2] = 16; break;
case 0x00c0: ld->args[2] = 24; break;
}
ld->args[3] = (special & 0x0300) >> 8;
ld->args[4] = 0;
} else if (special <= GenLockedBase) {
// Generalized lift (tag, speed, delay, target, height)
ld->special = Generic_Lift;
if (special & 0x0020)
flags |= ML_MONSTERSCANACTIVATE;
switch (special & 0x0018) {
case 0x0000: ld->args[1] = P_SLOW*2; break;
case 0x0008: ld->args[1] = P_NORMAL*2; break;
case 0x0010: ld->args[1] = P_FAST*2; break;
case 0x0018: ld->args[1] = P_TURBO*2; break;
}
switch (special & 0x00c0) {
case 0x0000: ld->args[2] = 8; break;
case 0x0040: ld->args[2] = 24; break;
case 0x0080: ld->args[2] = 40; break;
case 0x00c0: ld->args[2] = 80; break;
}
ld->args[3] = ((special & 0x0300) >> 8) + 1;
ld->args[4] = 0;
} else if (special <= GenDoorBase) {
// Generalized locked door (tag, speed, kind, delay, lock)
ld->special = Generic_Door;
if (special & 0x0080)
flags |= ML_MONSTERSCANACTIVATE;
switch (special & 0x0018) {
case 0x0000: ld->args[1] = D_SLOW; break;
case 0x0008: ld->args[1] = D_NORMAL; break;
case 0x0010: ld->args[1] = D_FAST; break;
case 0x0018: ld->args[1] = D_TURBO; break;
}
ld->args[2] = (special & 0x0020) >> 5;
ld->args[3] = 0;
ld->args[4] = (special & 0x01c0) >> 6;
if (ld->args[4] == 0)
ld->args[4] = AnyKey;
else if (ld->args[4] == 7)
ld->args[4] = AllKeys;
ld->args[4] |= (special & 0x0200) >> 2;
} else if (special <= GenCeilingBase) {
// Generalized door (tag, speed, kind, delay, lock)
ld->special = Generic_Door;
switch (special & 0x0018) {
case 0x0000: ld->args[1] = D_SLOW; break;
case 0x0008: ld->args[1] = D_NORMAL; break;
case 0x0010: ld->args[1] = D_FAST; break;
case 0x0018: ld->args[1] = D_TURBO; break;
}
ld->args[2] = (special & 0x0060) >> 5;
switch (special & 0x0300) {
case 0x0000: ld->args[3] = 8; break;
case 0x0100: ld->args[3] = 32; break;
case 0x0200: ld->args[3] = 72; break;
case 0x0300: ld->args[3] = 240; break;
}
ld->args[4] = 0;
} else {
// Generalized ceiling (tag, speed, height, target, change/model/direct/crush)
// Generalized floor (tag, speed, height, target, change/model/direct/crush)
if (special <= GenFloorBase)
ld->special = Generic_Ceiling;
else
ld->special = Generic_Floor;
switch (special & 0x0018) {
case 0x0000: ld->args[1] = F_SLOW; break;
case 0x0008: ld->args[1] = F_NORMAL; break;
case 0x0010: ld->args[1] = F_FAST; break;
case 0x0018: ld->args[1] = F_TURBO; break;
}
ld->args[3] = ((special & 0x0380) >> 7) + 1;
if (ld->args[3] >= 7) {
ld->args[2] = 24 + (ld->args[3] - 7) * 8;
ld->args[3] = 0;
} else {
ld->args[2] = 0;
}
ld->args[4] = ((special & 0x0c00) >> 10) |
((special & 0x0060) >> 2) |
((special & 0x1000) >> 8);
}
}
ld->flags = flags;
// For purposes of maintaining BOOM compatibility, each
// line also needs to have its ID set to the same as its tag.
// An external conversion program would need to do this more
// intelligently.
ld->id = tag;
}
// The teleport specials that use things as destinations also require
// that their TIDs be set to the tags of their containing sectors. We
// do that after the rest of the level has been loaded.
void P_TranslateTeleportThings (void)
{
int i, j;
thinker_t *thinker;
mobj_t *m;
for (i = 0; i < numlines; i++) {
if (lines[i].special == Teleport ||
lines[i].special == Teleport_NoFog) {
// The sector tag hash table hasn't been set up yet,
// so we need to use this linear search.
for (j = 0; j < numsectors; j++) {
if (sectors[j].tag == lines[i].args[0]) {
thinker = thinkercap.next;
for (thinker = thinkercap.next;
thinker != &thinkercap;
thinker = thinker->next)
{
// not a mobj
if (thinker->function.acp1 != (actionf_p1)P_MobjThinker)
continue;
m = (mobj_t *)thinker;
// not a teleportman
if (m->type != MT_TELEPORTMAN && m->type != MT_TELEPORTMAN2)
continue;
// wrong sector
if (m->subsector->sector - sectors != j)
continue;
// It's a teleportman, so set it's tid to match
// the sector's tag.
m->tid = lines[i].args[0];
P_AddMobjToHash (m);
// We only bother with the first teleportman
break;
}
if (thinker != &thinkercap)
break;
}
}
}
}
}
int P_TranslateSectorSpecial (int special)
{
// This supports phased lighting with specials 21-24
return (special == 9) ? SECRET_MASK :
((special & 0xfe0) << 3) |
((special & 0x01f) + (((special & 0x1f) < 21) ? 64 : -20));
}

View file

@ -20,6 +20,7 @@
*/ */
/* Hacked for DOOM Win32 port by Petteri Kangaslampi <pekangas@sci.fi> */ /* Hacked for DOOM Win32 port by Petteri Kangaslampi <pekangas@sci.fi> */
// [RH] And then further to not use any intermediate files
//#define MSDOG //#define MSDOG
@ -63,14 +64,14 @@ char tmp[MAXPATH] ;
size_t fwrite2(const int2 *ptr, size_t size, FILE *file) size_t fwrite2(const int2 *ptr, size_t size, FILE *file)
{ {
int4 rev = 0, work; int4 rev = 0;
int i; int i;
for( i = 0 ; (size_t)i < size ; i++ ) { for( i = 0 ; (size_t)i < size ; i++ ) {
// VC++ didn't like this magic (but only for the release build!) // VC++ didn't like this magic (but only for the release build!)
// rev = (rev << 8) + (((*ptr) >> (i*8)) & 0xFF) ; // rev = (rev << 8) + (((*ptr) >> (i*8)) & 0xFF) ;
int4 work = (*ptr) >> (i << 3);
rev <<= 8; rev <<= 8;
work = (*ptr) >> (i << 3);
rev |= (work & 0xFF); rev |= (work & 0xFF);
} }
@ -629,54 +630,3 @@ int convert( const char *mus, const char *mid, int nodisplay, int div,
return 0 ; return 0 ;
} }
int CheckParm( char *check, int argc, char *argv[] )
{
int i;
for ( i = 1 ; i<argc ; i++ )
#ifdef MSDOG
if( !stricmp( check, argv[i] ) )
#else
if( !strcmp( check, argv[i] ) )
#endif
return i ;
return 0;
}
void PrintHeader( void )
{
/* Print( "===============================================================================\n"
" Quick MUS->MID v2.0 ! (C) 1995,96 Sebastien Bacquet\n"
" E-mail : bacquet@iie.cnam.fr\n"
"===============================================================================\n" ) ;*/
}
void PrintSyntax( void )
{
PrintHeader() ;
Printf(
#ifdef MSDOG
"\nSyntax : QMUS2MID musfile1[.mus] {musfile2[.mus] ... | "
"midifile.mid} [options]\n"
" Wildcards are accepted.\n"
" Options are :\n"
" -query : Query before processing\n"
" -ow : OK, overwrite (without query)\n"
#else
"\nSyntax : QMUS2MID musfile midifile [options]\n"
" Options are :\n"
#endif
" -noow : Don't overwrite !\n"
" -nodisp : Display nothing ! (except errors)\n"
" -nocomp : Don't compress !\n"
" -size ### : Set the track buffer size to ### (in KB). "
"Default = 64 KB\n"
" -t ### : Ticks per quarter note. Default = 89\n"
) ;
}

View file

@ -38,6 +38,7 @@
// State. // State.
#include "doomstat.h" #include "doomstat.h"
#include "r_state.h" #include "r_state.h"
#include "v_palett.h"
//#include "r_local.h" //#include "r_local.h"
@ -302,7 +303,7 @@ sector_t *R_FakeFlat(sector_t *sec, sector_t *tempsec,
if (sec->heightsec != -1) if (sec->heightsec != -1)
{ {
const sector_t *s = &sectors[sec->heightsec]; const sector_t *s = &sectors[sec->heightsec];
int heightsec = viewplayer->mo->subsector->sector->heightsec; int heightsec = camera->subsector->sector->heightsec;
int underwater = heightsec!=-1 && viewz<=sectors[heightsec].floorheight; int underwater = heightsec!=-1 && viewz<=sectors[heightsec].floorheight;
// Replace sector being drawn, with a copy to be hacked // Replace sector being drawn, with a copy to be hacked
@ -320,7 +321,7 @@ sector_t *R_FakeFlat(sector_t *sec, sector_t *tempsec,
tempsec->floor_xoffs = s->floor_xoffs; tempsec->floor_xoffs = s->floor_xoffs;
tempsec->floor_yoffs = s->floor_yoffs; tempsec->floor_yoffs = s->floor_yoffs;
if (underwater) if (underwater) {
if (s->ceilingpic == skyflatnum) if (s->ceilingpic == skyflatnum)
{ {
tempsec->floorheight = tempsec->ceilingheight+1; tempsec->floorheight = tempsec->ceilingheight+1;
@ -334,6 +335,7 @@ sector_t *R_FakeFlat(sector_t *sec, sector_t *tempsec,
tempsec->ceiling_xoffs = s->ceiling_xoffs; tempsec->ceiling_xoffs = s->ceiling_xoffs;
tempsec->ceiling_yoffs = s->ceiling_yoffs; tempsec->ceiling_yoffs = s->ceiling_yoffs;
} }
}
tempsec->lightlevel = s->lightlevel; tempsec->lightlevel = s->lightlevel;
@ -480,9 +482,9 @@ void R_AddLine (seg_t* line)
// Identical floor and ceiling on both sides, // Identical floor and ceiling on both sides,
// identical light levels on both sides, // identical light levels on both sides,
// and no middle texture. // and no middle texture.
if (backsector->ceilingpic == frontsector->ceilingpic if (backsector->lightlevel == frontsector->lightlevel
&& backsector->floorpic == frontsector->floorpic && backsector->floorpic == frontsector->floorpic
&& backsector->lightlevel == frontsector->lightlevel && backsector->ceilingpic == frontsector->ceilingpic
&& curline->sidedef->midtexture == 0 && curline->sidedef->midtexture == 0
// killough 3/7/98: Take flats offsets into account: // killough 3/7/98: Take flats offsets into account:
@ -494,6 +496,9 @@ void R_AddLine (seg_t* line)
// killough 4/16/98: consider altered lighting // killough 4/16/98: consider altered lighting
&& backsector->floorlightsec == frontsector->floorlightsec && backsector->floorlightsec == frontsector->floorlightsec
&& backsector->ceilinglightsec == frontsector->ceilinglightsec && backsector->ceilinglightsec == frontsector->ceilinglightsec
// [RH] Also consider colormaps
&& backsector->colormap == frontsector->colormap
) )
{ {
return; return;
@ -655,7 +660,7 @@ void R_Subsector (int num)
sector_t tempsec; // killough 3/7/98: deep water hack sector_t tempsec; // killough 3/7/98: deep water hack
int floorlightlevel; // killough 3/16/98: set floor lightlevel int floorlightlevel; // killough 3/16/98: set floor lightlevel
int ceilinglightlevel; // killough 4/11/98 int ceilinglightlevel; // killough 4/11/98
#ifdef RANGECHECK #ifdef RANGECHECK
if (num>=numsubsectors) if (num>=numsubsectors)
I_Error ("R_Subsector: ss %i with numss = %i", num, numsubsectors); I_Error ("R_Subsector: ss %i with numss = %i", num, numsubsectors);
@ -666,6 +671,8 @@ void R_Subsector (int num)
count = sub->numlines; count = sub->numlines;
line = &segs[sub->firstline]; line = &segs[sub->firstline];
basecolormap = frontsector->colormap->maps; // [RH] set basecolormap
// killough 3/8/98, 4/4/98: Deep water / fake ceiling effect // killough 3/8/98, 4/4/98: Deep water / fake ceiling effect
frontsector = R_FakeFlat(frontsector, &tempsec, &floorlightlevel, frontsector = R_FakeFlat(frontsector, &tempsec, &floorlightlevel,
&ceilinglightlevel, false); // killough 4/11/98 &ceilinglightlevel, false); // killough 4/11/98
@ -694,7 +701,9 @@ void R_Subsector (int num)
frontsector->ceiling_yoffs frontsector->ceiling_yoffs
) : NULL; ) : NULL;
R_AddSprites (frontsector); // [RH] Fix BOOM bug where things in deep water sectors with
// several subsectors caused massive slowdown.
R_AddSprites (sub->sector);
while (count--) while (count--)
{ {

View file

@ -154,13 +154,6 @@ static byte** texturecomposite;
int* flattranslation; int* flattranslation;
int* texturetranslation; int* texturetranslation;
// needed for pre rendering
fixed_t* spritewidth;
fixed_t* spriteoffset;
fixed_t* spritetopoffset;
//lighttable_t *colormaps;
// //
// MAPTEXTURE_T CACHING // MAPTEXTURE_T CACHING
@ -502,21 +495,8 @@ void R_InitTextures (void)
#undef ALLOC #undef ALLOC
totalwidth = 0; totalwidth = 0;
// Really complex printing shit...
{
int temp3 = (((W_GetNumForName ("S_END") - 1) -
W_GetNumForName ("S_START") + 127) >> 7) +
((numtextures+127) >> 8);
Printf("["); // [RH] Removed the complex printing shit
for (i = temp3; i > 0; i--)
Printf(" ");
Printf(" ]");
for (i = temp3; i > 0; i--)
Printf("\x8");
Printf("\x8\x8\x8\x8\x8\x8\x8\x8\x8\x8");
}
for (i = 0; i < numtextures; i++, directory++) for (i = 0; i < numtextures; i++, directory++)
{ {
@ -534,7 +514,7 @@ void R_InitTextures (void)
offset = LONG(*directory); offset = LONG(*directory);
if (offset > maxoff) if (offset > maxoff)
I_Error ("R_InitTextures: bad texture directory"); I_FatalError ("R_InitTextures: bad texture directory");
mtexture = (maptexture_t *) ( (byte *)maptex + offset); mtexture = (maptexture_t *) ( (byte *)maptex + offset);
@ -589,7 +569,7 @@ void R_InitTextures (void)
Z_Free (maptex2); Z_Free (maptex2);
if (errors) if (errors)
I_Error ("%d errors in R_InitTextures.", errors); I_FatalError ("%d errors in R_InitTextures.", errors);
// [RH] Setup hash chains. Go from back to front so that if // [RH] Setup hash chains. Go from back to front so that if
// duplicates are found, the first one gets used instead // duplicates are found, the first one gets used instead
@ -609,7 +589,7 @@ void R_InitTextures (void)
R_GenerateLookup (i, &errors); R_GenerateLookup (i, &errors);
if (errors) if (errors)
I_Error ("%d errors encountered during texture generation.", errors); I_FatalError ("%d errors encountered during texture generation.", errors);
// Create translation table for global animation. // Create translation table for global animation.
texturetranslation = Z_Malloc ((numtextures+1)*sizeof(*texturetranslation), PU_STATIC, 0); texturetranslation = Z_Malloc ((numtextures+1)*sizeof(*texturetranslation), PU_STATIC, 0);
@ -648,51 +628,112 @@ void R_InitFlats (void)
// //
void R_InitSpriteLumps (void) void R_InitSpriteLumps (void)
{ {
int i;
patch_t *patch;
firstspritelump = W_GetNumForName ("S_START") + 1; firstspritelump = W_GetNumForName ("S_START") + 1;
lastspritelump = W_GetNumForName ("S_END") - 1; lastspritelump = W_GetNumForName ("S_END") - 1;
numspritelumps = lastspritelump - firstspritelump + 1;
spritewidth = Z_Malloc (numspritelumps*4, PU_STATIC, 0);
spriteoffset = Z_Malloc (numspritelumps*4, PU_STATIC, 0);
spritetopoffset = Z_Malloc (numspritelumps*4, PU_STATIC, 0);
for (i = 0; i < numspritelumps; i++)
{
if (!(i&127))
Printf (".");
patch = W_CacheLumpNum (firstspritelump+i, PU_CACHE); numspritelumps = lastspritelump - firstspritelump + 1;
spritewidth[i] = SHORT(patch->width)<<FRACBITS;
spriteoffset[i] = SHORT(patch->leftoffset)<<FRACBITS; // [RH] Rather than maintaining separate spritewidth, spriteoffset,
spritetopoffset[i] = SHORT(patch->topoffset)<<FRACBITS; // and spritetopoffset arrays, this data has now been moved into
} // the sprite frame definition and gets initialized by
// R_InstallSpriteLump(), so there really isn't anything to do here.
} }
static struct {
char name[8];
unsigned int blend;
} *fakecmaps;
size_t numfakecmaps;
int firstfakecmap;
byte *realcolormaps;
int lastusedcolormap;
void R_SetDefaultColormap (const char *name)
{
if (strnicmp (fakecmaps[0].name, name, 8)) {
byte *data = W_CacheLumpName (name, PU_CACHE);
memcpy (realcolormaps, data, (NUMCOLORMAPS+1)*256);
uppercopy (fakecmaps[0].name, name);
fakecmaps[0].blend = 0;
}
}
// //
// R_InitColormaps // R_InitColormaps
// //
void R_InitColormaps (void) void R_InitColormaps (void)
{ {
// [RH] This is all done dynamically in v_palette.c // [RH] Try and convert BOOM colormaps into blending values.
#if 0 // This is a really rough hack, but it's better than
int lump, length; // not doing anything with them at all (right?)
int lastfakecmap = W_CheckNumForName ("C_END");
firstfakecmap = W_CheckNumForName ("C_START");
// Load in the light tables, if (firstfakecmap == -1 || lastfakecmap == -1)
// 256 byte align tables. numfakecmaps = 1;
lump = W_GetNumForName("COLORMAP"); else
length = W_LumpLength (lump) + 255; numfakecmaps = lastfakecmap - firstfakecmap;
colormaps = Z_Malloc (length, PU_STATIC, 0); realcolormaps = Z_Malloc (256*(NUMCOLORMAPS+1)*numfakecmaps+255,PU_STATIC,0);
colormaps = (byte *)( ((int)colormaps + 255)&~0xff); realcolormaps = (byte *)((int)(realcolormaps + 255) & ~255);
W_ReadLump (lump,colormaps); fakecmaps = Z_Malloc (sizeof(*fakecmaps) * numfakecmaps, PU_STATIC, 0);
#endif
fakecmaps[0].name[0] = 0;
R_SetDefaultColormap ("COLORMAP");
if (numfakecmaps > 1)
{
int i;
size_t j;
palette_t *pal = GetDefaultPalette ();
for (i = ++firstfakecmap, j = 1; j < numfakecmaps; i++, j++) {
if (W_LumpLength (i) >= (NUMCOLORMAPS+1)*256) {
int k, r, g, b;
byte *map = W_CacheLumpNum (i, PU_CACHE);
memcpy (realcolormaps+(NUMCOLORMAPS+1)*256*j,
map, (NUMCOLORMAPS+1)*256);
r = RPART(pal->basecolors[*map]);
g = GPART(pal->basecolors[*map]);
b = BPART(pal->basecolors[*map]);
W_GetLumpName (fakecmaps[j].name, i);
for (k = 1; k < 256; k++) {
r = (r + RPART(pal->basecolors[map[k]])) >> 1;
g = (g + GPART(pal->basecolors[map[k]])) >> 1;
b = (b + BPART(pal->basecolors[map[k]])) >> 1;
}
fakecmaps[j].blend = MAKEARGB (255, r, g, b);
}
}
}
} }
// [RH] Returns an index into realcolormaps. Multiply it by
// 256*(NUMCOLORMAPS+1) to find the start of the colormap to use.
// WATERMAP is an exception and returns a blending value instead.
int R_ColormapNumForName (const char *name)
{
int lump, blend = 0;
if (strnicmp (name, "COLORMAP", 8)) { // COLORMAP always returns 0
if (-1 != (lump = (W_CheckNumForName)(name, ns_colormaps)) )
blend = lump - firstfakecmap + 1;
else if (!strnicmp (name, "WATERMAP", 8))
blend = MAKEARGB (128,0,0x4f,0xa5);
}
return blend;
}
unsigned int R_BlendForColormap (int map)
{
return APART(map) ? map :
(unsigned)map < numfakecmaps ? fakecmaps[map].blend : 0;
}
// //
// R_InitData // R_InitData
@ -882,7 +923,7 @@ void R_PrecacheLevel (void)
int k; int k;
for (k = 7; k >= 0; k--) for (k = 7; k >= 0; k--)
W_CacheLumpNum(firstspritelump + sflumps[k], PU_CACHE); W_CacheLumpNum(sflumps[k], PU_CACHE);
} }
} }
} }

View file

@ -41,6 +41,7 @@
// Silhouette, needed for clipping Segs (mainly) // Silhouette, needed for clipping Segs (mainly)
// and sprites representing things. // and sprites representing things.
#define SIL_NONE 0 #define SIL_NONE 0
@ -90,10 +91,13 @@ struct degenmobj_s
}; };
typedef struct degenmobj_s degenmobj_t; typedef struct degenmobj_s degenmobj_t;
// //
// The SECTORS record, at runtime. // The SECTORS record, at runtime.
// Stores things/mobjs. // Stores things/mobjs.
// //
struct dyncolormap_s;
struct sector_s struct sector_s
{ {
fixed_t floorheight; fixed_t floorheight;
@ -103,6 +107,7 @@ struct sector_s
short lightlevel; short lightlevel;
short special; short special;
short tag; short tag;
int nexttag,firsttag; // killough 1/30/98: improves searches for tags.
int soundtraversed; // 0 = untraversed, 1,2 = sndlines -1 int soundtraversed; // 0 = untraversed, 1,2 = sndlines -1
mobj_t* soundtarget; // thing that made a sound (or null) mobj_t* soundtarget; // thing that made a sound (or null)
@ -131,6 +136,10 @@ struct sector_s
// killough 4/11/98: support for lightlevels coming from another sector // killough 4/11/98: support for lightlevels coming from another sector
int floorlightsec, ceilinglightsec; int floorlightsec, ceilinglightsec;
unsigned int bottommap, midmap, topmap; // killough 4/4/98: dynamic colormaps
// [RH] these can also be blend values if
// the alpha mask is non-zero
// list of mobjs that are at least partially in the sector // list of mobjs that are at least partially in the sector
// thinglist is a subset of touching_thinglist // thinglist is a subset of touching_thinglist
struct msecnode_s *touching_thinglist; // phares 3/14/98 struct msecnode_s *touching_thinglist; // phares 3/14/98
@ -138,6 +147,10 @@ struct sector_s
int linecount; int linecount;
struct line_s **lines; // [linecount] size struct line_s **lines; // [linecount] size
float gravity; // [RH] Sector gravity (1.0 is normal)
short damage; // [RH] Damage to do while standing on floor
short mod; // [RH] Means-of-death for applied damage
struct dyncolormap_s *colormap; // [RH] Per-sector colormap
}; };
typedef struct sector_s sector_t; typedef struct sector_s sector_t;
@ -161,6 +174,9 @@ struct side_s
short bottomtexture; short bottomtexture;
short midtexture; short midtexture;
// [RH] Bah. Had to add this for BOOM
byte special;
// Sector the SideDef is facing. // Sector the SideDef is facing.
sector_t* sector; sector_t* sector;
@ -194,9 +210,13 @@ struct line_s
// Animation related. // Animation related.
short flags; short flags;
short special; byte special; // [RH] Only one byte per special.
short tag; byte lucency; // <--- Translucency (0-255/255=opaque)
byte args[5]; // [RH] Hexen-style arguments short id; // <--- Same as tag or set with Line_SetIdentification.
short args[5]; // <--- Hexen-style arguments
// Note that these are shorts in order to support
// the tag parameter from DOOM.
int firstid, nextid;
// Visual appearance: SideDefs. // Visual appearance: SideDefs.
// sidenum[1] will be -1 if one sided // sidenum[1] will be -1 if one sided
@ -216,9 +236,6 @@ struct line_s
// if == validcount, already checked // if == validcount, already checked
int validcount; int validcount;
// thinker_t for reversable actions
void* specialdata;
}; };
typedef struct line_s line_t; typedef struct line_s line_t;
@ -377,7 +394,6 @@ struct drawseg_s
short* sprtopclip; short* sprtopclip;
short* sprbottomclip; short* sprbottomclip;
short* maskedtexturecol; short* maskedtexturecol;
}; };
typedef struct drawseg_s drawseg_t; typedef struct drawseg_s drawseg_t;
@ -430,8 +446,7 @@ struct vissprite_s
fixed_t texturemid; fixed_t texturemid;
int patch; int patch;
// for color translation and shadow draw, // for color translation and maxbright frames as well
// maxbright frames as well
lighttable_t* colormap; lighttable_t* colormap;
int mobjflags; int mobjflags;
@ -471,13 +486,18 @@ struct spriteframe_s
// Lump to use for view angles 0-7. // Lump to use for view angles 0-7.
short lump[8]; short lump[8];
// [RH] Move some data out of spritewidth, spriteoffset,
// and spritetopoffset arrays.
fixed_t width[8];
fixed_t topoffset[8];
fixed_t offset[8];
// Flip bit (1 = flip) to use for view angles 0-7. // Flip bit (1 = flip) to use for view angles 0-7.
byte flip[8]; byte flip[8];
}; };
typedef struct spriteframe_s spriteframe_t; typedef struct spriteframe_s spriteframe_t;
// //
// A sprite definition: // A sprite definition:
// a number of animation frames. // a number of animation frames.
@ -490,28 +510,36 @@ struct spritedef_s
}; };
typedef struct spritedef_s spritedef_t; typedef struct spritedef_s spritedef_t;
//
// [RH] Internal "skin" definition.
//
struct playerskin_s
{
char name[17]; // 16 chars + NULL
char face[3];
int sprite;
int namespc; // namespace for this skin
int gender; // This skin's gender (not used)
};
typedef struct playerskin_s playerskin_t;
// //
// Now what is a visplane, anyway? // The infamous visplane
// //
struct visplane_s struct visplane_s
{ {
fixed_t height; struct visplane_s *next; // Next visplane in hash chain -- killough
int picnum;
int lightlevel;
fixed_t xoffs;
fixed_t yoffs;
int minx;
int maxx;
// leave pads for [minx-1]/[maxx+1]
// Here lies the rub for all
// dynamic resize/change of resolution.
// These actually point one short past the memory fixed_t height;
// area allocated (for padding) int picnum;
unsigned short *top, *bottom; int lightlevel;
fixed_t xoffs, yoffs; // killough 2/28/98: Support scrolling flats
int minx, maxx;
byte *colormap; // [RH] Support multiple colormaps
unsigned short *bottom; // [RH] bottom and top arrays are dynamically
unsigned short pad; // allocated immediately after the
unsigned short top[3]; // visplane.
}; };
typedef struct visplane_s visplane_t; typedef struct visplane_s visplane_t;

View file

@ -254,7 +254,7 @@ void R_DrawFuzzColumnP_C (void)
if (count < 0) if (count < 0)
return; return;
map = DefaultPalette->colormaps + 6*256; map = DefaultPalette->maps.colormaps + 6*256;
#ifdef RANGECHECK #ifdef RANGECHECK
if (dc_x >= screens[0].width if (dc_x >= screens[0].width
@ -494,6 +494,8 @@ void R_DrawSpanP (void)
/* */ /* */
/****************************************/ /****************************************/
#define dc_shademap ((unsigned int *)dc_colormap)
void R_DrawColumnD_C (void) void R_DrawColumnD_C (void)
{ {
int count; int count;
@ -523,7 +525,7 @@ void R_DrawColumnD_C (void)
do do
{ {
*dest = V_Palette[dc_colormap[dc_source[(frac>>FRACBITS)&dc_mask]]]; *dest = dc_shademap[dc_source[(frac>>FRACBITS)&dc_mask]];
dest += dc_pitch >> 2; dest += dc_pitch >> 2;
frac += fracstep; frac += fracstep;
@ -608,7 +610,7 @@ void R_DrawTranslucentColumnD_C (void)
do do
{ {
*dest = ((*dest >> 1) & 0x7f7f7f) + *dest = ((*dest >> 1) & 0x7f7f7f) +
((V_Palette[dc_colormap[dc_source[(frac>>FRACBITS)&dc_mask]]] >> 1) & 0x7f7f7f); ((dc_shademap[dc_source[(frac>>FRACBITS)&dc_mask]] >> 1) & 0x7f7f7f);
dest += dc_pitch >> 2; dest += dc_pitch >> 2;
frac += fracstep; frac += fracstep;
@ -646,7 +648,7 @@ void R_DrawTranslatedColumnD_C (void)
// Here we do an additional index re-mapping. // Here we do an additional index re-mapping.
do do
{ {
*dest = V_Palette[dc_colormap[dc_translation[dc_source[(frac>>FRACBITS) & dc_mask]]]]; *dest = dc_shademap[dc_translation[dc_source[(frac>>FRACBITS) & dc_mask]]];
dest += dc_pitch >> 2; dest += dc_pitch >> 2;
frac += fracstep; frac += fracstep;
@ -686,7 +688,7 @@ void R_DrawSpanD (void)
// Lookup pixel from flat texture tile, // Lookup pixel from flat texture tile,
// re-index using light/colormap. // re-index using light/colormap.
*dest = V_Palette[ds_colormap[ds_source[spot]]]; *dest = ((unsigned int *)ds_colormap)[ds_source[spot]];
dest += ds_colsize >> 2; dest += ds_colsize >> 2;
// Next step in u,v. // Next step in u,v.

View file

@ -28,6 +28,7 @@
extern int dc_pitch; // [RH] Distance between rows extern int dc_pitch; // [RH] Distance between rows
extern lighttable_t* dc_colormap; extern lighttable_t* dc_colormap;
extern unsigned int* dc_shademap; // [RH] For high/true color modes
extern int dc_x; extern int dc_x;
extern int dc_yl; extern int dc_yl;
extern int dc_yh; extern int dc_yh;

View file

@ -50,7 +50,7 @@ cvar_t *r_viewsize;
extern int dmflags; extern int dmflags;
// Fineangles in the SCREENWIDTH wide window. // Fineangles in the SCREENWIDTH wide window.
#define FIELDOFVIEW 2048 #define FIELDOFVIEW 2048
@ -59,9 +59,10 @@ int viewangleoffset;
// increment every time a check is made // increment every time a check is made
int validcount = 1; int validcount = 1;
lighttable_t* basecolormap; // [RH] colormap currently drawing with
lighttable_t* fixedcolormap; lighttable_t* fixedcolormap;
extern lighttable_t** walllights; extern int* walllights; // [RH] changed from lighttable_t** to int*
int centerx; int centerx;
int centery; int centery;
@ -89,7 +90,7 @@ angle_t viewangle;
fixed_t viewcos; fixed_t viewcos;
fixed_t viewsin; fixed_t viewsin;
player_t* viewplayer; mobj_t* camera; // [RH] camera to draw from. doesn't have to be a player
// //
// precalculated math tables // precalculated math tables
@ -117,13 +118,15 @@ angle_t *xtoviewangle;
// fixed_t finesine[5*FINEANGLES/4]; // fixed_t finesine[5*FINEANGLES/4];
fixed_t* finecosine = &finesine[FINEANGLES/4]; fixed_t* finecosine = &finesine[FINEANGLES/4];
// [RH] Changed these from lighttable_t* to int.
int scalelight[LIGHTLEVELS][MAXLIGHTSCALE];
int scalelightfixed[MAXLIGHTSCALE];
int zlight[LIGHTLEVELS][MAXLIGHTZ];
lighttable_t* scalelight[LIGHTLEVELS][MAXLIGHTSCALE]; int lightscalexmul; // [RH] used to keep hires modes dark enough
lighttable_t* scalelightfixed[MAXLIGHTSCALE]; int lightscaleymul;
lighttable_t* zlight[LIGHTLEVELS][MAXLIGHTZ];
// bumped light from gun blasts int extralight; // bumped light from gun blasts
int extralight;
extern BOOL DrawNewHUD; // [RH] Defined in d_main.c. extern BOOL DrawNewHUD; // [RH] Defined in d_main.c.
@ -144,11 +147,7 @@ void (*spanfunc) (void);
// Expand a given bbox // Expand a given bbox
// so that it encloses a given point. // so that it encloses a given point.
// //
void void R_AddPointToBox (int x, int y, fixed_t *box)
R_AddPointToBox
( int x,
int y,
fixed_t* box )
{ {
if (x< box[BOXLEFT]) if (x< box[BOXLEFT])
box[BOXLEFT] = x; box[BOXLEFT] = x;
@ -163,123 +162,87 @@ R_AddPointToBox
// //
// R_PointOnSide // R_PointOnSide
// Traverse BSP (sub) tree, // Traverse BSP (sub) tree, check point against partition plane.
// check point against partition plane.
// Returns side 0 (front) or 1 (back). // Returns side 0 (front) or 1 (back).
// [RH] Re-arranged slightly.
// //
int int R_PointOnSide (fixed_t x, fixed_t y, node_t *node)
R_PointOnSide
( fixed_t x,
fixed_t y,
node_t* node )
{ {
fixed_t dx;
fixed_t dy;
fixed_t left;
fixed_t right;
if (!node->dx) if (!node->dx)
{ {
if (x <= node->x) return (x <= node->x) ? (node->dy > 0) : (node->dy < 0);
return node->dy > 0;
return node->dy < 0;
} }
if (!node->dy) else if (!node->dy)
{ {
if (y <= node->y) return (y <= node->y) ? (node->dx < 0) : (node->dx > 0);
return node->dx < 0;
return node->dx > 0;
} }
else
dx = (x - node->x);
dy = (y - node->y);
// Try to quickly decide by looking at sign bits.
if ( (node->dy ^ node->dx ^ dx ^ dy)&0x80000000 )
{ {
if ( (node->dy ^ dx) & 0x80000000 ) fixed_t dx = (x - node->x);
fixed_t dy = (y - node->y);
// Try to quickly decide by looking at sign bits.
if ( (node->dy ^ node->dx ^ dx ^ dy)&0x80000000 )
{ {
// (left is negative) if ( (node->dy ^ dx) & 0x80000000 )
return 1; {
// (left is negative)
return 1;
}
return 0;
} }
return 0;
}
left = FixedMul ( node->dy>>FRACBITS , dx ); if (FixedMul (dy, node->dx>>FRACBITS) < FixedMul (node->dy>>FRACBITS, dx))
right = FixedMul ( dy , node->dx>>FRACBITS ); {
// front side
if (right < left) return 0;
{ }
// front side // back side
return 0; return 1;
} }
// back side
return 1;
} }
// [RH] Rearranged this slightly, too.
int int R_PointOnSegSide (fixed_t x, fixed_t y, seg_t *line)
R_PointOnSegSide
( fixed_t x,
fixed_t y,
seg_t* line )
{ {
fixed_t lx; fixed_t lx = line->v1->x;
fixed_t ly; fixed_t ly = line->v1->y;
fixed_t ldx;
fixed_t ldy; fixed_t ldx = line->v2->x - lx;
fixed_t dx; fixed_t ldy = line->v2->y - ly;
fixed_t dy;
fixed_t left;
fixed_t right;
lx = line->v1->x;
ly = line->v1->y;
ldx = line->v2->x - lx;
ldy = line->v2->y - ly;
if (!ldx) if (!ldx)
{ {
if (x <= lx) return (x <= lx) ? (ldy > 0) : (ldy < 0);
return ldy > 0;
return ldy < 0;
} }
if (!ldy) else if (!ldy)
{ {
if (y <= ly) return (y <= ly) ? (ldx < 0) : (ldx > 0);
return ldx < 0;
return ldx > 0;
} }
else
dx = (x - lx);
dy = (y - ly);
// Try to quickly decide by looking at sign bits.
if ( (ldy ^ ldx ^ dx ^ dy)&0x80000000 )
{ {
if ( (ldy ^ dx) & 0x80000000 ) fixed_t dx = (x - lx);
{ fixed_t dy = (y - ly);
// (left is negative)
return 1;
}
return 0;
}
left = FixedMul ( ldy>>FRACBITS , dx ); // Try to quickly decide by looking at sign bits.
right = FixedMul ( dy , ldx>>FRACBITS ); if ( (ldy ^ ldx ^ dx ^ dy)&0x80000000 )
{
if (right < left) if ( (ldy ^ dx) & 0x80000000 )
{ {
// front side // (left is negative)
return 0; return 1;
}
return 0;
}
if (FixedMul (dy, ldx>>FRACBITS) < FixedMul (ldy>>FRACBITS, dx))
{
// front side
return 0;
}
// back side
return 1;
} }
// back side
return 1;
} }
@ -293,10 +256,6 @@ R_PointOnSegSide
// tantoangle[] table. // tantoangle[] table.
// //
angle_t R_PointToAngle (fixed_t x, fixed_t y) angle_t R_PointToAngle (fixed_t x, fixed_t y)
{ {
x -= viewx; x -= viewx;
@ -379,12 +338,7 @@ angle_t R_PointToAngle (fixed_t x, fixed_t y)
} }
angle_t angle_t R_PointToAngle2 (fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2)
R_PointToAngle2
( fixed_t x1,
fixed_t y1,
fixed_t x2,
fixed_t y2 )
{ {
viewx = x1; viewx = x1;
viewy = y1; viewy = y1;
@ -398,7 +352,10 @@ R_PointToAngle2
// //
void R_InitPointToAngle (void) void R_InitPointToAngle (void)
{ {
// UNUSED - now getting from tables.c [or are we? -RH] // UNUSED - now getting from tables.c
// [RH] Actually, if you define CALC_TABLES, the game will use the FPU
// to calculate these tables at runtime so that a little space
// can be saved on disk.
#ifdef CALC_TABLES #ifdef CALC_TABLES
double i, f; double i, f;
// //
@ -480,7 +437,9 @@ fixed_t R_ScaleFromGlobalAngle (angle_t visangle)
// //
void R_InitTables (void) void R_InitTables (void)
{ {
// UNUSED: now getting from tables.c [or are we? -RH] // UNUSED: now getting from tables.c
// [RH] As with R_InitPointToAngle, you can #define CALC_TABLES
// to generate these tables at runtime.
#ifdef CALC_TABLES #ifdef CALC_TABLES
int i; int i;
double a; double a;
@ -512,10 +471,10 @@ void R_InitTables (void)
// //
void R_InitTextureMapping (void) void R_InitTextureMapping (void)
{ {
int i; int i;
int x; int x;
int t; int t;
fixed_t focallength; fixed_t focallength;
// Use tangent table to generate viewangletox: // Use tangent table to generate viewangletox:
// viewangletox will give the next greatest x // viewangletox will give the next greatest x
@ -526,7 +485,7 @@ void R_InitTextureMapping (void)
focallength = FixedDiv (centerxfrac, focallength = FixedDiv (centerxfrac,
finetangent[FINEANGLES/4+FIELDOFVIEW/2] ); finetangent[FINEANGLES/4+FIELDOFVIEW/2] );
for (i=0 ; i<FINEANGLES/2 ; i++) for (i = 0; i < FINEANGLES/2; i++)
{ {
if (finetangent[i] > FRACUNIT*2) if (finetangent[i] > FRACUNIT*2)
t = -1; t = -1;
@ -548,7 +507,7 @@ void R_InitTextureMapping (void)
// Scan viewangletox[] to generate xtoviewangle[]: // Scan viewangletox[] to generate xtoviewangle[]:
// xtoviewangle will give the smallest view angle // xtoviewangle will give the smallest view angle
// that maps to x. // that maps to x.
for (x=0;x<=viewwidth;x++) for (x = 0; x <= viewwidth; x++)
{ {
i = 0; i = 0;
while (viewangletox[i]>x) while (viewangletox[i]>x)
@ -557,7 +516,7 @@ void R_InitTextureMapping (void)
} }
// Take out the fencepost cases from viewangletox. // Take out the fencepost cases from viewangletox.
for (i=0 ; i<FINEANGLES/2 ; i++) for (i = 0; i < FINEANGLES/2; i++)
{ {
t = FixedMul (finetangent[i], focallength); t = FixedMul (finetangent[i], focallength);
t = centerx - t; t = centerx - t;
@ -577,37 +536,43 @@ void R_InitTextureMapping (void)
// R_InitLightTables // R_InitLightTables
// Only inits the zlight table, // Only inits the zlight table,
// because the scalelight table changes with view size. // because the scalelight table changes with view size.
// [RH] This now setups indices into a colormap rather than pointers into the
// colormap, because the colormap can vary by sector, but the indices
// into it don't.
// //
#define DISTMAP 2 #define DISTMAP 2
void R_InitLightTables (void) void R_InitLightTables (void)
{ {
int i; int i;
int j; int j;
int level; int level;
int startmap; int startmap;
int scale; int scale;
int lightmapsize = 8 + (screens[0].is8bit ? 0 : 2);
// Calculate the light levels to use // Calculate the light levels to use
// for each level / distance combination. // for each level / distance combination.
for (i=0 ; i< LIGHTLEVELS ; i++) for (i = 0; i < LIGHTLEVELS; i++)
{ {
startmap = ((LIGHTLEVELS-1-i)*2)*NUMCOLORMAPS/LIGHTLEVELS; startmap = ((LIGHTLEVELS-1-i)*2)*NUMCOLORMAPS/LIGHTLEVELS;
for (j=0 ; j<MAXLIGHTZ ; j++) for (j=0 ; j<MAXLIGHTZ ; j++)
{ {
scale = FixedDiv ((screens[0].width/2*FRACUNIT), (j+1)<<LIGHTZSHIFT); scale = FixedDiv ((160*FRACUNIT), (j+1)<<LIGHTZSHIFT);
scale >>= LIGHTSCALESHIFT; scale >>= LIGHTSCALESHIFT-LIGHTSCALEMULBITS;
level = startmap - scale/DISTMAP; level = startmap - scale/DISTMAP;
if (level < 0) if (level < 0)
level = 0; level = 0;
else if (level >= NUMCOLORMAPS)
if (level >= NUMCOLORMAPS)
level = NUMCOLORMAPS-1; level = NUMCOLORMAPS-1;
zlight[i][j] = DefaultPalette->maps.colormaps + level*256; zlight[i][j] = level << lightmapsize;
} }
} }
lightscalexmul = 320 * (1<<LIGHTSCALEMULBITS) / screens[0].width;
lightscaleymul = 200 * (1<<LIGHTSCALEMULBITS) / screens[0].height;
} }
@ -618,9 +583,9 @@ void R_InitLightTables (void)
// because it might be in the middle of a refresh. // because it might be in the middle of a refresh.
// The change will take effect next refresh. // The change will take effect next refresh.
// //
BOOL setsizeneeded; BOOL setsizeneeded;
int setblocks; int setblocks;
int setdetail = -1; int setdetail = -1;
void R_SetViewSize (int blocks) void R_SetViewSize (int blocks)
@ -667,6 +632,7 @@ void R_ExecuteSetViewSize (void)
int startmap; int startmap;
int aspectx; int aspectx;
int virtheight, virtwidth; int virtheight, virtwidth;
int lightmapsize = 8 + (screens[0].is8bit ? 0 : 2);
setsizeneeded = false; setsizeneeded = false;
@ -685,7 +651,8 @@ void R_ExecuteSetViewSize (void)
realviewwidth = screens[0].width; realviewwidth = screens[0].width;
realviewheight = ST_Y; realviewheight = ST_Y;
freelookviewheight = screens[0].height; freelookviewheight = screens[0].height;
} else }
else
{ {
realviewwidth = ((setblocks*screens[0].width)/10) & (~(15>>(screens[0].is8bit ? 0 : 2))); realviewwidth = ((setblocks*screens[0].width)/10) & (~(15>>(screens[0].is8bit ? 0 : 2)));
realviewheight = ((setblocks*ST_Y)/10)&~7; realviewheight = ((setblocks*ST_Y)/10)&~7;
@ -717,7 +684,7 @@ void R_ExecuteSetViewSize (void)
virtwidth = screens[0].width >> detailxshift; virtwidth = screens[0].width >> detailxshift;
virtheight = screens[0].height >> detailyshift; virtheight = screens[0].height >> detailyshift;
// [RH] aspect ratio stuff (based Doom Legacy's) // [RH] aspect ratio stuff (based on Doom Legacy's)
aspectx = ((virtheight * centerx * 320) / 200) / virtwidth * FRACUNIT; aspectx = ((virtheight * centerx * 320) / 200) / virtwidth * FRACUNIT;
projection = centerxfrac; projection = centerxfrac;
@ -768,8 +735,8 @@ void R_ExecuteSetViewSize (void)
distscale[i] = FixedDiv (FRACUNIT,cosadj); distscale[i] = FixedDiv (FRACUNIT,cosadj);
} }
// Calculate the light levels to use // Calculate the light levels to use for each level / scale combination.
// for each level / scale combination. // [RH] This just stores indices into the colormap rather than pointers into it.
for (i=0 ; i< LIGHTLEVELS ; i++) for (i=0 ; i< LIGHTLEVELS ; i++)
{ {
startmap = ((LIGHTLEVELS-1-i)*2)*NUMCOLORMAPS/LIGHTLEVELS; startmap = ((LIGHTLEVELS-1-i)*2)*NUMCOLORMAPS/LIGHTLEVELS;
@ -779,13 +746,15 @@ void R_ExecuteSetViewSize (void)
if (level < 0) if (level < 0)
level = 0; level = 0;
else if (level >= NUMCOLORMAPS)
if (level >= NUMCOLORMAPS)
level = NUMCOLORMAPS-1; level = NUMCOLORMAPS-1;
scalelight[i][j] = DefaultPalette->maps.colormaps + level*256; scalelight[i][j] = level << lightmapsize;
} }
} }
// [RH] Initialize z-light tables here
R_InitLightTables ();
} }
@ -820,29 +789,14 @@ void R_Init (void)
R_DetailCallback (r_detail); R_DetailCallback (r_detail);
R_InitData (); R_InitData ();
Printf (".");
// Printf ("\nR_InitData");
R_InitPointToAngle (); R_InitPointToAngle ();
Printf (".");
// Printf ("\nR_InitPointToAngle");
R_InitTables (); R_InitTables ();
// viewwidth / viewheight are set by the defaults // viewwidth / viewheight are set by the defaults
Printf (".");
// Printf ("\nR_InitTables");
R_SetViewSize ((int)screenblocks->value); R_SetViewSize ((int)screenblocks->value);
R_InitPlanes (); R_InitPlanes ();
Printf (".");
// Printf ("\nR_InitPlanes");
R_InitLightTables (); R_InitLightTables ();
Printf (".");
// Printf ("\nR_InitLightTables");
// R_InitSkyMap ();
Printf (".");
// Printf ("\nR_InitSkyMap");
R_InitTranslationTables (); R_InitTranslationTables ();
Printf (".");
// Printf ("\nR_InitTranslationsTables");
framecount = 0; framecount = 0;
} }
@ -851,10 +805,7 @@ void R_Init (void)
// //
// R_PointInSubsector // R_PointInSubsector
// //
subsector_t* subsector_t *R_PointInSubsector (fixed_t x, fixed_t y)
R_PointInSubsector
( fixed_t x,
fixed_t y )
{ {
node_t* node; node_t* node;
int side; int side;
@ -881,38 +832,79 @@ R_PointInSubsector
// //
// R_SetupFrame // R_SetupFrame
// //
void R_SetupFrame (player_t* player) extern dyncolormap_t NormalLight;
void R_SetupFrame (player_t *player)
{ {
int i; static unsigned int oldblend = ~0;
unsigned int newblend;
int dy; int dy;
viewplayer = player; camera = player->camera; // [RH] Use camera instead of viewplayer
viewx = player->mo->x; viewx = camera->x;
viewy = player->mo->y; viewy = camera->y;
viewangle = player->mo->angle + viewangleoffset; viewangle = camera->angle + viewangleoffset;
extralight = player->extralight; extralight = camera == player->mo ? player->extralight : 0;
viewz = camera->player ? camera->player->viewz : camera->z;
viewz = player->viewz;
viewsin = finesine[viewangle>>ANGLETOFINESHIFT]; viewsin = finesine[viewangle>>ANGLETOFINESHIFT];
viewcos = finecosine[viewangle>>ANGLETOFINESHIFT]; viewcos = finecosine[viewangle>>ANGLETOFINESHIFT];
if (player->fixedcolormap) // killough 3/20/98, 4/4/98: select colormap based on player status
// [RH] Can also select a blend
if (camera->subsector->sector->heightsec != -1)
{ {
fixedcolormap = const sector_t *s = camera->subsector->sector->heightsec + sectors;
DefaultPalette->maps.colormaps newblend = viewz < s->floorheight ? s->bottommap : viewz > s->ceilingheight ?
+ player->fixedcolormap*256*sizeof(lighttable_t); s->topmap : s->midmap;
if (!screens[0].is8bit)
newblend = R_BlendForColormap (newblend);
else if (APART(newblend) == 0 && newblend >= numfakecmaps)
newblend = 0;
} else {
newblend = 0;
}
// [RH] Don't override testblend unless entering a sector with a
// blend different from the previous sector's. Same goes with
// NormalLight's maps pointer.
if (oldblend != newblend) {
oldblend = newblend;
if (APART(newblend)) {
BaseBlendR = RPART(newblend);
BaseBlendG = GPART(newblend);
BaseBlendB = BPART(newblend);
BaseBlendA = APART(newblend) / 255.0f;
NormalLight.maps = realcolormaps;
} else {
NormalLight.maps = realcolormaps + (NUMCOLORMAPS+1)*256*newblend;
BaseBlendR = BaseBlendG = BaseBlendB = 0;
BaseBlendA = 0.0f;
}
}
if (camera == player->mo && player->fixedcolormap)
{
if (screens[0].is8bit)
fixedcolormap =
DefaultPalette->maps.colormaps
+ player->fixedcolormap*256;
else
fixedcolormap = (lighttable_t *)
(DefaultPalette->maps.shades
+ player->fixedcolormap*256);
walllights = scalelightfixed; walllights = scalelightfixed;
for (i=0 ; i<MAXLIGHTSCALE ; i++) // [RH] scalelightfixed is an int* now, not a lighttable_t**
scalelightfixed[i] = fixedcolormap; memset (scalelightfixed, 0, MAXLIGHTSCALE*sizeof(*scalelightfixed));
} }
else else
fixedcolormap = 0; fixedcolormap = NULL;
// [RH] freelook stuff // [RH] freelook stuff
dy = FixedMul (freelookviewheight << (FRACBITS/2), player->mo->pitch) >> 9; dy = FixedMul (freelookviewheight << (FRACBITS/2), camera->pitch) >> 9;
yslope = yslopetab + (freelookviewheight >> 1) + dy + freediff; yslope = yslopetab + (freelookviewheight >> 1) + dy + freediff;
centery = (viewheight >> 1) - dy; centery = (viewheight >> 1) - dy;
centeryfrac = centery << FRACBITS; centeryfrac = centery << FRACBITS;
@ -927,8 +919,16 @@ void R_SetupFrame (player_t* player)
// //
// R_RenderView // R_RenderView
// //
void R_RenderPlayerView (player_t* player) void R_RenderPlayerView (player_t *player)
{ {
angle_t an;
// [RH] Shift view for earthquakes
if (player->xviewshift) {
an = (player->mo->angle-ANG90) >> ANGLETOFINESHIFT;
player->mo->x += finecosine[an]*player->xviewshift;
player->mo->y += finesine[an]*player->xviewshift;
}
R_SetupFrame (player); R_SetupFrame (player);
// Clear buffers. // Clear buffers.
@ -958,6 +958,12 @@ void R_RenderPlayerView (player_t* player)
// [RH] Apply detail mode doubling // [RH] Apply detail mode doubling
R_DetailDouble (); R_DetailDouble ();
// [RH] Undo view shift
if (player->xviewshift) {
player->mo->x -= finecosine[an]*player->xviewshift;
player->mo->y -= finesine[an]*player->xviewshift;
}
} }
// [RH] Do all multires stuff. Called from V_SetResolution() // [RH] Do all multires stuff. Called from V_SetResolution()

View file

@ -50,7 +50,7 @@ extern fixed_t projection;
extern fixed_t projectiony; // [RH] fix aspect ratio (from doom3) extern fixed_t projectiony; // [RH] fix aspect ratio (from doom3)
extern fixed_t skytopfrac; // [RH] virtual top of the sky (for freelooking) extern fixed_t skytopfrac; // [RH] virtual top of the sky (for freelooking)
extern byte* basecolormap; // [RH] Colormap for sector currently being drawn
extern int validcount; extern int validcount;
@ -70,17 +70,22 @@ extern int loopcount;
#define LIGHTSEGSHIFT 4 #define LIGHTSEGSHIFT 4
#define MAXLIGHTSCALE 48 #define MAXLIGHTSCALE 48
#define LIGHTSCALESHIFT 12 #define LIGHTSCALEMULBITS 8 // [RH] for hires lighting fix
#define LIGHTSCALESHIFT (12+LIGHTSCALEMULBITS)
#define MAXLIGHTZ 128 #define MAXLIGHTZ 128
#define LIGHTZSHIFT 20 #define LIGHTZSHIFT 20
extern lighttable_t* scalelight[LIGHTLEVELS][MAXLIGHTSCALE]; // [RH] Changed from lighttable_t* to int.
extern lighttable_t* scalelightfixed[MAXLIGHTSCALE]; extern int scalelight[LIGHTLEVELS][MAXLIGHTSCALE];
extern lighttable_t* zlight[LIGHTLEVELS][MAXLIGHTZ]; extern int scalelightfixed[MAXLIGHTSCALE];
extern int zlight[LIGHTLEVELS][MAXLIGHTZ];
extern int extralight; extern int extralight;
extern lighttable_t* fixedcolormap; extern lighttable_t* fixedcolormap;
extern int lightscalexmul; // [RH] for hires lighting fix
extern int lightscaleymul;
// Number of diminishing brightness levels. // Number of diminishing brightness levels.
// There a 0-31, i.e. 32 LUT in the COLORMAP lump. // There a 0-31, i.e. 32 LUT in the COLORMAP lump.
@ -130,11 +135,6 @@ R_PointToAngle2
fixed_t x2, fixed_t x2,
fixed_t y2 ); fixed_t y2 );
fixed_t
R_PointToDist
( fixed_t x,
fixed_t y );
fixed_t R_ScaleFromGlobalAngle (angle_t visangle); fixed_t R_ScaleFromGlobalAngle (angle_t visangle);

View file

@ -21,6 +21,17 @@
// while maintaining a per column clipping list only. // while maintaining a per column clipping list only.
// Moreover, the sky areas have to be determined. // Moreover, the sky areas have to be determined.
// //
// MAXVISPLANES is no longer a limit on the number of visplanes,
// but a limit on the number of hash slots; larger numbers mean
// better performance usually but after a point they are wasted,
// and memory and time overheads creep in.
//
// For more information on visplanes, see:
//
// http://classicgaming.com/doom/editing/
//
// Lee Killough
//
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -43,18 +54,26 @@
planefunction_t floorfunc; planefunction_t floorfunc;
planefunction_t ceilingfunc; planefunction_t ceilingfunc;
// Here comes the obnoxious "visplane".
#define MAXVISPLANES 128 /* must be a power of 2 */
static visplane_t *visplanes[MAXVISPLANES]; // killough
static visplane_t *freetail; // killough
static visplane_t **freehead = &freetail; // killough
visplane_t *floorplane;
visplane_t *ceilingplane;
// killough -- hash function for visplanes
// Empirically verified to be fairly uniform:
#define visplane_hash(picnum,lightlevel,height) \
((unsigned)((picnum)*3+(lightlevel)+(height)*7) & (MAXVISPLANES-1))
// //
// opening // opening
// //
// Here comes the obnoxious "visplane".
int MaxVisPlanes;
visplane_t *visplanes;
visplane_t *lastvisplane;
visplane_t *floorplane;
visplane_t *ceilingplane;
// ?
size_t maxopenings; size_t maxopenings;
short *openings; short *openings;
short *lastopening; short *lastopening;
@ -78,7 +97,7 @@ int *spanstop;
// //
// texture mapping // texture mapping
// //
lighttable_t** planezlight; int* planezlight; // [RH] Changed from lighttable_t** to int*
fixed_t planeheight; fixed_t planeheight;
fixed_t *yslopetab; // [RH] Added for freelook. ylook points into it fixed_t *yslopetab; // [RH] Added for freelook. ylook points into it
@ -94,52 +113,12 @@ fixed_t *cachedxstep;
fixed_t *cachedystep; fixed_t *cachedystep;
static void PrepVisPlanes (int min)
{
int i;
unsigned short *stuff;
for (i = min; i < MaxVisPlanes; i++) {
stuff = (unsigned short *)Calloc (screens[0].width * 2 + 4, sizeof(unsigned short));
visplanes[i].top = stuff + 1;
visplanes[i].bottom = stuff + screens[0].width + 3;
}
}
// //
// R_InitPlanes // R_InitPlanes
// Only at game startup. // Only at game startup.
// [RH] This function is actually used now.
// //
void R_InitPlanes (void) void R_InitPlanes (void)
{ {
MaxVisPlanes = 128; // Default. Increased as needed.
visplanes = (visplane_t *)Calloc (MaxVisPlanes, sizeof(visplane_t));
PrepVisPlanes (0);
}
static void GetMoreVisPlanes (visplane_t **toupdate)
{
int oldMax;
visplane_t *old = visplanes;
oldMax = MaxVisPlanes;
MaxVisPlanes += 32;
visplanes = (visplane_t *)Realloc (visplanes, (MaxVisPlanes) * sizeof(visplane_t));
DPrintf ("MaxVisPlanes increased to %d\n", MaxVisPlanes);
PrepVisPlanes (oldMax);
if (visplanes == old)
return;
*toupdate = &visplanes[*toupdate - old];
lastvisplane = &visplanes[lastvisplane - old];
if (floorplane)
floorplane = &visplanes[floorplane - old];
if (ceilingplane)
ceilingplane = &visplanes[ceilingplane - old];
} }
// //
@ -154,6 +133,7 @@ static void GetMoreVisPlanes (visplane_t **toupdate)
// viewy // viewy
// xoffs // xoffs
// yoffs // yoffs
// basecolormap // [RH]
// //
// BASIC PRIMITIVE // BASIC PRIMITIVE
// //
@ -200,17 +180,16 @@ void R_MapPlane (int y, int x1, int x2)
{ {
index = distance >> LIGHTZSHIFT; index = distance >> LIGHTZSHIFT;
if (index >= MAXLIGHTZ ) if (index >= MAXLIGHTZ)
index = MAXLIGHTZ-1; index = MAXLIGHTZ-1;
ds_colormap = planezlight[index]; ds_colormap = planezlight[index] + basecolormap; // [RH] add basecolormap
} }
ds_y = y; ds_y = y;
ds_x1 = x1; ds_x1 = x1;
ds_x2 = x2; ds_x2 = x2;
// high or low detail
spanfunc (); spanfunc ();
} }
@ -225,27 +204,47 @@ void R_ClearPlanes (void)
angle_t angle; angle_t angle;
// opening / clipping determination // opening / clipping determination
for (i=0 ; i<viewwidth ; i++) for (i = 0; i < viewwidth ; i++)
{ {
floorclip[i] = (short)viewheight; floorclip[i] = (short)viewheight;
ceilingclip[i] = -1; ceilingclip[i] = -1;
} }
lastvisplane = visplanes; for (i = 0; i < MAXVISPLANES; i++) // new code -- killough
for (*freehead = visplanes[i], visplanes[i] = NULL; *freehead; )
freehead = &(*freehead)->next;
lastopening = openings; lastopening = openings;
// texture calculation // texture calculation
memset (cachedheight, 0, sizeof(fixed_t) * screens[0].height); memset (cachedheight, 0, sizeof(*cachedheight) * screens[0].height);
// left to right mapping // left to right mapping
angle = (viewangle-ANG90)>>ANGLETOFINESHIFT; angle = (viewangle - ANG90)>>ANGLETOFINESHIFT;
// scale will be unit scale at SCREENWIDTH/2 distance // scale will be unit scale at SCREENWIDTH/2 distance
basexscale = FixedDiv (finecosine[angle],centerxfrac); basexscale = FixedDiv (finecosine[angle],centerxfrac);
baseyscale = -FixedDiv (finesine[angle],centerxfrac); baseyscale = -FixedDiv (finesine[angle],centerxfrac);
} }
// New function, by Lee Killough
// [RH] top and bottom buffers get allocated immediately
// after the visplane.
static visplane_t *new_visplane(unsigned hash)
{
visplane_t *check = freetail;
if (!check) {
check = Calloc (1, sizeof(*check) + sizeof(*check->top)*(screens[0].width*2));
check->bottom = &check->top[screens[0].width+2];
} else
if (!(freetail = freetail->next))
freehead = &freetail;
check->next = visplanes[hash];
visplanes[hash] = check;
return check;
}
// //
@ -257,40 +256,35 @@ visplane_t *R_FindPlane (fixed_t height, int picnum, int lightlevel,
fixed_t xoffs, fixed_t yoffs) fixed_t xoffs, fixed_t yoffs)
{ {
visplane_t *check; visplane_t *check;
unsigned hash; // killough
if (picnum == skyflatnum) if (picnum == skyflatnum)
height = lightlevel = 0; // all skys map together height = lightlevel = 0; // all skys map together
for (check=visplanes; check<lastvisplane; check++) // New visplane algorithm uses hash table -- killough
{ hash = visplane_hash (picnum, lightlevel, height);
if (height == check->height
&& picnum == check->picnum
&& lightlevel == check->lightlevel
&& xoffs == check->xoffs
&& yoffs == check->yoffs
)
{
break;
}
}
if (check < lastvisplane) for (check = visplanes[hash]; check; check = check->next) // killough
return check; if (height == check->height &&
picnum == check->picnum &&
if (lastvisplane - visplanes == MaxVisPlanes) lightlevel == check->lightlevel &&
GetMoreVisPlanes (&check); xoffs == check->xoffs && // killough 2/28/98: Add offset checks
yoffs == check->yoffs &&
lastvisplane++; basecolormap == check->colormap) // [RH] Add colormap check
return check;
check = new_visplane (hash); // killough
check->height = height; check->height = height;
check->picnum = picnum; check->picnum = picnum;
check->lightlevel = lightlevel; check->lightlevel = lightlevel;
check->xoffs = xoffs; // killough 2/28/98: Save offsets check->xoffs = xoffs; // killough 2/28/98: Save offsets
check->yoffs = yoffs; check->yoffs = yoffs;
check->colormap = basecolormap; // [RH] Save colormap
check->minx = screens[0].width; check->minx = screens[0].width;
check->maxx = -1; check->maxx = -1;
memset (check->top,0xff,sizeof(short) * screens[0].width); memset (check->top, 0xff, sizeof(*check->top) * screens[0].width);
return check; return check;
} }
@ -329,37 +323,30 @@ visplane_t *R_CheckPlane (visplane_t *pl, int start, int stop)
intrh = stop; intrh = stop;
} }
for (x=intrl ; x<= intrh ; x++) for (x=intrl ; x <= intrh && pl->top[x] == 0xffff; x++)
if (pl->top[x] != 0xffff) ;
break;
if (x > intrh) if (x > intrh)
{ {
pl->minx = unionl; pl->minx = unionl;
pl->maxx = unionh; pl->maxx = unionh;
// use the same one
return pl;
} }
else
// [RH] Need to make sure we actually have this lastvisplane {
if (lastvisplane - visplanes == MaxVisPlanes) unsigned hash = visplane_hash (pl->picnum, pl->lightlevel, pl->height);
GetMoreVisPlanes (&pl); visplane_t *new_pl = new_visplane (hash);
// make a new visplane new_pl->height = pl->height;
lastvisplane->height = pl->height; new_pl->picnum = pl->picnum;
lastvisplane->picnum = pl->picnum; new_pl->lightlevel = pl->lightlevel;
lastvisplane->lightlevel = pl->lightlevel; new_pl->xoffs = pl->xoffs; // killough 2/28/98
lastvisplane->xoffs = pl->xoffs; // killough 2/28/98 new_pl->yoffs = pl->yoffs;
lastvisplane->yoffs = pl->yoffs; new_pl->colormap = pl->colormap; // [RH] Copy colormap
pl = new_pl;
pl = lastvisplane++; pl->minx = start;
pl->maxx = stop;
pl->minx = start; memset (pl->top, 0xff, sizeof(*pl->top) * screens[0].width);
pl->maxx = stop; }
memset (pl->top,0xff,sizeof(short) * screens[0].width);
return pl; return pl;
} }
@ -369,37 +356,20 @@ visplane_t *R_CheckPlane (visplane_t *pl, int start, int stop)
// //
void R_MakeSpans (int x, int t1, int b1, int t2, int b2) void R_MakeSpans (int x, int t1, int b1, int t2, int b2)
{ {
//if (t1 != 0xffff) for (; t1 < t2 && t1 <= b1; t1++)
while (t1 < t2 && t1<=b1) R_MapPlane(t1, spanstart[t1], x-1);
{ for (; b1 > b2 && b1 >= t1; b1--)
R_MapPlane (t1,spanstart[t1],x-1); R_MapPlane(b1, spanstart[b1] ,x-1);
t1++; while (t2 < t1 && t2 <= b2)
} spanstart[t2++] = x;
//if (b1 != 0xffff) while (b2 > b1 && b2 >= t2)
while (b1 > b2 && b1>=t1) spanstart[b2--] = x;
{
R_MapPlane (b1,spanstart[b1],x-1);
b1--;
}
//if (t2 != 0xffff)
while (t2 < t1 && t2<=b2)
{
spanstart[t2] = x;
t2++;
}
//if (b2 != 0xffff)
while (b2 > b1 && b2>=t2)
{
spanstart[b2] = x;
b2--;
}
} }
// [RH] This was separated from R_DrawPlanes() on 11.5.1998. // [RH] This was separated from R_DrawPlanes() on 11.5.1998.
// Also added support for columns with holes since double skies // Also added support for columns with holes since double skies
// opens up that possibility (modified from R_DrawMaskedColumn). // opens up that possibility (modified from R_DrawMaskedColumn).
// One implication of this is that the sky will always wrap // One implication of this is that the sky should always wrap
// properly, provided that it is tall enough. // properly, provided that it is tall enough.
static void R_DrawMaskedSky (int skytexture, int skypos, fixed_t scale, fixed_t height, visplane_t *pl) static void R_DrawMaskedSky (int skytexture, int skypos, fixed_t scale, fixed_t height, visplane_t *pl)
@ -492,77 +462,78 @@ static void R_DrawSky (int skytexture, int skypos, visplane_t *pl)
// //
void R_DrawPlanes (void) void R_DrawPlanes (void)
{ {
visplane_t* pl; visplane_t *pl;
int light; int i;
int x;
int stop;
for (pl = visplanes ; pl < lastvisplane ; pl++) for (i = 0; i < MAXVISPLANES; i++)
{ for (pl = visplanes[i]; pl; pl = pl->next)
if (pl->minx > pl->maxx)
continue;
// sky flat
if (pl->picnum == skyflatnum)
{ {
// Sky is allways drawn full bright, if (pl->minx > pl->maxx)
// i.e. colormaps[0] is used. continue;
// Because of this hack, sky is not affected
// by INVUL inverse mapping. // sky flat
dc_colormap = DefaultPalette->maps.colormaps; if (pl->picnum == skyflatnum)
{
// Sky is allways drawn full bright,
// i.e. colormaps[0] is used.
// Because of this hack, sky is not affected
// by INVUL inverse mapping.
dc_colormap = DefaultPalette->maps.colormaps;
if (level.flags & LEVEL_DOUBLESKY) { if (level.flags & LEVEL_DOUBLESKY) {
dc_iscale = sky2iscale >> sky2stretch; dc_iscale = sky2iscale >> sky2stretch;
dc_texturemid = sky2texturemid; dc_texturemid = sky2texturemid;
if (textureheight[sky2texture] == (128<<FRACBITS)) if (textureheight[sky2texture] == (128<<FRACBITS))
R_DrawSky (sky2texture, sky2pos, pl); R_DrawSky (sky2texture, sky2pos, pl);
else
R_DrawMaskedSky (sky2texture, sky2pos, sky2scale, sky2height, pl);
}
dc_iscale = sky1iscale >> sky1stretch;
dc_texturemid = sky1texturemid;
if ((level.flags & LEVEL_DOUBLESKY) || (textureheight[sky1texture] != (128<<FRACBITS)))
R_DrawMaskedSky (sky1texture, sky1pos, sky1scale, sky1height, pl);
else else
R_DrawMaskedSky (sky2texture, sky2pos, sky2scale, sky2height, pl); R_DrawSky (sky1texture, sky1pos, pl);
} }
dc_iscale = sky1iscale >> sky1stretch;
dc_texturemid = sky1texturemid;
if ((level.flags & LEVEL_DOUBLESKY) || (textureheight[sky1texture] != (128<<FRACBITS)))
R_DrawMaskedSky (sky1texture, sky1pos, sky1scale, sky1height, pl);
else else
R_DrawSky (sky1texture, sky1pos, pl); {
// regular flat
int light, stop, x;
continue; ds_source = W_CacheLumpNum(firstflat +
} flattranslation[pl->picnum],
PU_STATIC);
// regular flat
ds_source = W_CacheLumpNum(firstflat +
flattranslation[pl->picnum],
PU_STATIC);
xoffs = pl->xoffs; // killough 2/28/98: Add offsets
yoffs = pl->yoffs;
planeheight = abs(pl->height-viewz);
light = (pl->lightlevel >> LIGHTSEGSHIFT)+extralight;
if (light >= LIGHTLEVELS)
light = LIGHTLEVELS-1;
if (light < 0)
light = 0;
planezlight = zlight[light];
pl->top[pl->maxx+1] = 0xffff;
pl->top[pl->minx-1] = 0xffff;
stop = pl->maxx + 1; xoffs = pl->xoffs; // killough 2/28/98: Add offsets
yoffs = pl->yoffs;
basecolormap = pl->colormap; // [RH] set basecolormap
planeheight = abs(pl->height-viewz);
light = (pl->lightlevel >> LIGHTSEGSHIFT) + extralight;
for (x=pl->minx ; x<= stop ; x++) if (light >= LIGHTLEVELS)
{ light = LIGHTLEVELS-1;
R_MakeSpans(x,pl->top[x-1], else if (light < 0)
pl->bottom[x-1], light = 0;
pl->top[x],
pl->bottom[x]); planezlight = zlight[light];
pl->top[pl->maxx+1] = 0xffff;
pl->top[pl->minx-1] = 0xffff;
stop = pl->maxx + 1;
for (x = pl->minx; x <= stop; x++)
{
R_MakeSpans(x,pl->top[x-1],
pl->bottom[x-1],
pl->top[x],
pl->bottom[x]);
}
Z_ChangeTag (ds_source, PU_CACHE);
}
} }
Z_ChangeTag (ds_source, PU_CACHE);
}
} }
BOOL R_PlaneInitData (void) BOOL R_PlaneInitData (void)
@ -577,26 +548,41 @@ BOOL R_PlaneInitData (void)
if (cachedxstep) free (cachedxstep); if (cachedxstep) free (cachedxstep);
if (cachedystep) free (cachedystep); if (cachedystep) free (cachedystep);
floorclip = Calloc (screens[0].width, sizeof(short)); floorclip = Calloc (screens[0].width, sizeof(*floorclip));
ceilingclip = Calloc (screens[0].width, sizeof(short)); ceilingclip = Calloc (screens[0].width, sizeof(*ceilingclip));
spanstart = Calloc (screens[0].height, sizeof(int)); spanstart = Calloc (screens[0].height, sizeof(*spanstart));
spanstop = Calloc (screens[0].height, sizeof(int)); spanstop = Calloc (screens[0].height, sizeof(*spanstop));
yslopetab = Calloc ((screens[0].height<<1)+(screens[0].height>>1), sizeof(fixed_t)); yslopetab = Calloc ((screens[0].height<<1)+(screens[0].height>>1), sizeof(*yslopetab));
distscale = Calloc (screens[0].width, sizeof(fixed_t)); distscale = Calloc (screens[0].width, sizeof(*distscale));
cachedheight = Calloc (screens[0].height, sizeof(fixed_t)); cachedheight = Calloc (screens[0].height, sizeof(*cachedheight));
cacheddistance = Calloc (screens[0].height, sizeof(fixed_t)); cacheddistance = Calloc (screens[0].height, sizeof(*cacheddistance));
cachedxstep = Calloc (screens[0].height, sizeof(fixed_t)); cachedxstep = Calloc (screens[0].height, sizeof(*cachedxstep));
cachedystep = Calloc (screens[0].height, sizeof(fixed_t)); cachedystep = Calloc (screens[0].height, sizeof(*cachedystep));
if (visplanes) { // Free all visplanes and let them be re-allocated as needed.
{
int i; int i;
visplane_t *pl = freetail;
for (i = 0; i < MaxVisPlanes; i++) while (pl) {
free (visplanes[i].top - 1); visplane_t *next = pl->next;
free (pl);
pl = next;
}
freetail = NULL;
freehead = &freetail;
PrepVisPlanes (0); for (i = 0; i < MAXVISPLANES; i++) {
pl = visplanes[i];
visplanes[i] = NULL;
while (pl) {
visplane_t *next = pl->next;
free (pl);
pl = next;
}
}
} }
return true; return true;

View file

@ -68,7 +68,7 @@ R_FindPlane
int picnum, int picnum,
int lightlevel, int lightlevel,
fixed_t xoffs, // killough 2/28/98: add x-y offsets fixed_t xoffs, // killough 2/28/98: add x-y offsets
fixed_t yoffs); fixed_t yoffs );
visplane_t* visplane_t*
R_CheckPlane R_CheckPlane

View file

@ -28,6 +28,7 @@
#include "m_alloc.h" #include "m_alloc.h"
#include <stdlib.h> #include <stdlib.h>
#include <stddef.h>
#include "i_system.h" #include "i_system.h"
@ -54,7 +55,7 @@ static int midtexture;
angle_t rw_normalangle; // angle to line origin angle_t rw_normalangle; // angle to line origin
int rw_angle1; int rw_angle1;
fixed_t rw_distance; fixed_t rw_distance;
lighttable_t** walllights; int* walllights; // [RH] Changed from lighttable_t** to int*
// //
// regular wall // regular wall
@ -104,11 +105,24 @@ void R_RenderMaskedSegRange (drawseg_t *ds, int x1, int x2)
// OPTIMIZE: get rid of LIGHTSEGSHIFT globally // OPTIMIZE: get rid of LIGHTSEGSHIFT globally
curline = ds->curline; curline = ds->curline;
// killough 4/11/98: draw translucent 2s normal textures
// [RH] modified because we don't use user-definable
// translucency maps
colfunc = basecolfunc;
if (curline->linedef->lucency < 240)
{
colfunc = lucentcolfunc;
dc_transmap = TransTable + ((curline->linedef->lucency << 10) & 0x30000);
}
// killough 4/11/98: end translucent 2s normal code
frontsector = curline->frontsector; frontsector = curline->frontsector;
backsector = curline->backsector; backsector = curline->backsector;
texnum = texturetranslation[curline->sidedef->midtexture]; texnum = texturetranslation[curline->sidedef->midtexture];
basecolormap = frontsector->colormap->maps; // [RH] Set basecolormap
// killough 4/13/98: get correct lightlevel for 2s normal textures // killough 4/13/98: get correct lightlevel for 2s normal textures
lightnum = (R_FakeFlat(frontsector, &tempsec, NULL, NULL, false) lightnum = (R_FakeFlat(frontsector, &tempsec, NULL, NULL, false)
->lightlevel >> LIGHTSEGSHIFT)+extralight; ->lightlevel >> LIGHTSEGSHIFT)+extralight;
@ -154,12 +168,12 @@ void R_RenderMaskedSegRange (drawseg_t *ds, int x1, int x2)
// calculate lighting // calculate lighting
if (!fixedcolormap) if (!fixedcolormap)
{ {
unsigned index = spryscale>>LIGHTSCALESHIFT; unsigned index = (spryscale*lightscalexmul)>>LIGHTSCALESHIFT; // [RH]
if (index >= MAXLIGHTSCALE) if (index >= MAXLIGHTSCALE)
index = MAXLIGHTSCALE-1; index = MAXLIGHTSCALE-1;
dc_colormap = walllights[index]; dc_colormap = walllights[index] + basecolormap; // [RH] add basecolormap
} }
// killough 3/2/98: // killough 3/2/98:
@ -175,7 +189,7 @@ void R_RenderMaskedSegRange (drawseg_t *ds, int x1, int x2)
{ {
__int64 t = ((__int64) centeryfrac << FRACBITS) - __int64 t = ((__int64) centeryfrac << FRACBITS) -
(__int64) dc_texturemid * spryscale; (__int64) dc_texturemid * spryscale;
// [RH] This doesn't work properly as-is with freelook // [RH] This doesn't work properly as-is with freelook. Probably just me.
// if (t + (__int64) textureheight[texnum] * spryscale < 0 || // if (t + (__int64) textureheight[texnum] * spryscale < 0 ||
// t > (__int64) screens[0].height << FRACBITS*2) // t > (__int64) screens[0].height << FRACBITS*2)
// continue; // skip if the texture is out of screen's range // continue; // skip if the texture is out of screen's range
@ -219,17 +233,13 @@ void R_RenderMaskedSegRange (drawseg_t *ds, int x1, int x2)
void R_RenderSegLoop (void) void R_RenderSegLoop (void)
{ {
angle_t angle; int yl;
unsigned index; int yh;
int yl; fixed_t texturecolumn;
int yh;
int mid; if (fixedcolormap)
fixed_t texturecolumn; dc_colormap = fixedcolormap;
int top;
int bottom;
//texturecolumn = 0; // shut up compiler warning
for ( ; rw_x < rw_stopx ; rw_x++) for ( ; rw_x < rw_stopx ; rw_x++)
{ {
// mark floor / ceiling areas // mark floor / ceiling areas
@ -241,8 +251,8 @@ void R_RenderSegLoop (void)
if (markceiling) if (markceiling)
{ {
top = ceilingclip[rw_x]+1; int top = ceilingclip[rw_x]+1;
bottom = yl-1; int bottom = yl-1;
if (bottom >= floorclip[rw_x]) if (bottom >= floorclip[rw_x])
bottom = floorclip[rw_x]-1; bottom = floorclip[rw_x]-1;
@ -261,8 +271,8 @@ void R_RenderSegLoop (void)
if (markfloor) if (markfloor)
{ {
top = yh+1; int top = yh+1;
bottom = floorclip[rw_x]-1; int bottom = floorclip[rw_x]-1;
if (top <= ceilingclip[rw_x]) if (top <= ceilingclip[rw_x])
top = ceilingclip[rw_x]+1; top = ceilingclip[rw_x]+1;
if (top <= bottom) if (top <= bottom)
@ -276,16 +286,19 @@ void R_RenderSegLoop (void)
if (segtextured) if (segtextured)
{ {
// calculate texture offset // calculate texture offset
angle = (rw_centerangle + xtoviewangle[rw_x])>>ANGLETOFINESHIFT; texturecolumn = rw_offset-FixedMul(finetangent[(rw_centerangle + xtoviewangle[rw_x])>>ANGLETOFINESHIFT],rw_distance);
texturecolumn = rw_offset-FixedMul(finetangent[angle],rw_distance);
texturecolumn >>= FRACBITS; texturecolumn >>= FRACBITS;
// calculate lighting
index = rw_scale>>LIGHTSCALESHIFT;
if (index >= MAXLIGHTSCALE ) if (!fixedcolormap) {
index = MAXLIGHTSCALE-1; // calculate lighting
unsigned index = (rw_scale*lightscalexmul)>>LIGHTSCALESHIFT;
if (index >= MAXLIGHTSCALE)
index = MAXLIGHTSCALE-1;
dc_colormap = walllights[index] + basecolormap; // [RH] add basecolormap
}
dc_colormap = walllights[index];
dc_x = rw_x; dc_x = rw_x;
dc_iscale = 0xffffffffu / (unsigned)rw_scale; dc_iscale = 0xffffffffu / (unsigned)rw_scale;
} }
@ -308,7 +321,7 @@ void R_RenderSegLoop (void)
if (toptexture) if (toptexture)
{ {
// top wall // top wall
mid = pixhigh>>HEIGHTBITS; int mid = pixhigh>>HEIGHTBITS;
pixhigh += pixhighstep; pixhigh += pixhighstep;
if (mid >= floorclip[rw_x]) if (mid >= floorclip[rw_x])
@ -336,7 +349,7 @@ void R_RenderSegLoop (void)
if (bottomtexture) if (bottomtexture)
{ {
// bottom wall // bottom wall
mid = (pixlow+HEIGHTUNIT-1)>>HEIGHTBITS; int mid = (pixlow+HEIGHTUNIT-1)>>HEIGHTBITS;
pixlow += pixlowstep; pixlow += pixlowstep;
// no space above wall? // no space above wall?
@ -411,7 +424,7 @@ void R_StoreWallRange (int start, int stop)
angle_t distangle, offsetangle; angle_t distangle, offsetangle;
fixed_t vtop; fixed_t vtop;
int lightnum; int lightnum;
#ifdef RANGECHECK #ifdef RANGECHECK
if (start >=viewwidth || start > stop) if (start >=viewwidth || start > stop)
I_Error ("Bad R_RenderWallRange: %i to %i", start , stop); I_Error ("Bad R_RenderWallRange: %i to %i", start , stop);
@ -419,11 +432,11 @@ void R_StoreWallRange (int start, int stop)
// don't overflow and crash // don't overflow and crash
if (ds_p == &drawsegs[MaxDrawSegs]) { if (ds_p == &drawsegs[MaxDrawSegs]) {
unsigned pos = ds_p - drawsegs;
// [RH] Grab some more drawsegs // [RH] Grab some more drawsegs
MaxDrawSegs = MaxDrawSegs ? MaxDrawSegs*2 : 32; size_t newdrawsegs = MaxDrawSegs ? MaxDrawSegs*2 : 32;
drawsegs = Realloc (drawsegs, MaxDrawSegs * sizeof(drawseg_t)); drawsegs = Realloc (drawsegs, newdrawsegs * sizeof(drawseg_t));
ds_p = drawsegs + pos; ds_p = drawsegs + MaxDrawSegs;
MaxDrawSegs = newdrawsegs;
DPrintf ("MaxDrawSegs increased to %d\n", MaxDrawSegs); DPrintf ("MaxDrawSegs increased to %d\n", MaxDrawSegs);
} }
@ -441,18 +454,18 @@ void R_StoreWallRange (int start, int stop)
offsetangle = ANG90; offsetangle = ANG90;
distangle = ANG90 - offsetangle; distangle = ANG90 - offsetangle;
hyp = R_PointToDist (curline->v1->x, curline->v1->y); hyp = (viewx == curline->v1->x && viewy == curline->v1->y) ?
0 : R_PointToDist (curline->v1->x, curline->v1->y);
sineval = finesine[distangle>>ANGLETOFINESHIFT]; sineval = finesine[distangle>>ANGLETOFINESHIFT];
rw_distance = FixedMul (hyp, sineval); rw_distance = FixedMul (hyp, sineval);
ds_p->x1 = rw_x = start; ds_p->x1 = rw_x = start;
ds_p->x2 = stop; ds_p->x2 = stop;
ds_p->curline = curline; ds_p->curline = curline;
rw_stopx = stop+1; rw_stopx = stop+1;
{ // killough 1/6/98, 2/1/98: remove limit on openings { // killough 1/6/98, 2/1/98: remove limit on openings
size_t pos = lastopening - openings; ptrdiff_t pos = lastopening - openings;
size_t need = (rw_stopx - start)*4 + pos; size_t need = (rw_stopx - start)*4 + pos;
if (need > maxopenings) if (need > maxopenings)
@ -464,7 +477,7 @@ void R_StoreWallRange (int start, int stop)
do do
maxopenings = maxopenings ? maxopenings*2 : 16384; maxopenings = maxopenings ? maxopenings*2 : 16384;
while (need > maxopenings); while (need > maxopenings);
openings = Realloc(openings, maxopenings * sizeof(*openings)); openings = Realloc (openings, maxopenings * sizeof(*openings));
lastopening = openings + pos; lastopening = openings + pos;
DPrintf ("MaxOpenings increased to %u\n", maxopenings); DPrintf ("MaxOpenings increased to %u\n", maxopenings);
@ -485,7 +498,7 @@ void R_StoreWallRange (int start, int stop)
ds_p->scale1 = rw_scale = ds_p->scale1 = rw_scale =
R_ScaleFromGlobalAngle (viewangle + xtoviewangle[start]); R_ScaleFromGlobalAngle (viewangle + xtoviewangle[start]);
if (stop > start ) if (stop > start)
{ {
ds_p->scale2 = R_ScaleFromGlobalAngle (viewangle + xtoviewangle[stop]); ds_p->scale2 = R_ScaleFromGlobalAngle (viewangle + xtoviewangle[stop]);
ds_p->scalestep = rw_scalestep = ds_p->scalestep = rw_scalestep =
@ -612,16 +625,14 @@ void R_StoreWallRange (int start, int stop)
worldlow = backsector->floorheight - viewz; worldlow = backsector->floorheight - viewz;
// hack to allow height changes in outdoor areas // hack to allow height changes in outdoor areas
if (frontsector->ceilingpic == skyflatnum if (frontsector->ceilingpic == skyflatnum && backsector->ceilingpic == skyflatnum)
&& backsector->ceilingpic == skyflatnum)
{ {
worldtop = worldhigh; worldtop = worldhigh;
} }
markfloor = worldlow != worldbottom markfloor = worldlow != worldbottom
|| backsector->floorpic != frontsector->floorpic
|| backsector->lightlevel != frontsector->lightlevel || backsector->lightlevel != frontsector->lightlevel
|| backsector->floorpic != frontsector->floorpic
// killough 3/7/98: Add checks for (x,y) offsets // killough 3/7/98: Add checks for (x,y) offsets
|| backsector->floor_xoffs != frontsector->floor_xoffs || backsector->floor_xoffs != frontsector->floor_xoffs
@ -633,11 +644,14 @@ void R_StoreWallRange (int start, int stop)
// killough 4/17/98: draw floors if different light levels // killough 4/17/98: draw floors if different light levels
|| backsector->floorlightsec != frontsector->floorlightsec || backsector->floorlightsec != frontsector->floorlightsec
// [RH] Add checks for colormaps
|| backsector->colormap != frontsector->colormap
; ;
markceiling = worldhigh != worldtop markceiling = worldhigh != worldtop
|| backsector->ceilingpic != frontsector->ceilingpic
|| backsector->lightlevel != frontsector->lightlevel || backsector->lightlevel != frontsector->lightlevel
|| backsector->ceilingpic != frontsector->ceilingpic
// killough 3/7/98: Add checks for (x,y) offsets // killough 3/7/98: Add checks for (x,y) offsets
|| backsector->ceiling_xoffs != frontsector->ceiling_xoffs || backsector->ceiling_xoffs != frontsector->ceiling_xoffs
@ -650,6 +664,9 @@ void R_StoreWallRange (int start, int stop)
// killough 4/17/98: draw ceilings if different light levels // killough 4/17/98: draw ceilings if different light levels
|| backsector->ceilinglightsec != frontsector->ceilinglightsec || backsector->ceilinglightsec != frontsector->ceilinglightsec
// [RH] Add check for colormaps
|| backsector->colormap != frontsector->colormap
; ;
if (backsector->ceilingheight <= frontsector->floorheight if (backsector->ceilingheight <= frontsector->floorheight
@ -773,8 +790,7 @@ void R_StoreWallRange (int start, int stop)
// if a floor / ceiling plane is on the wrong side // if a floor / ceiling plane is on the wrong side
// of the view plane, it is definitely invisible // of the view plane, it is definitely invisible
// and doesn't need to be marked. // and doesn't need to be marked.
// killough 3/7/98: add deep water check // killough 3/7/98: add deep water check
if (frontsector->heightsec == -1) if (frontsector->heightsec == -1)
{ {
@ -814,17 +830,19 @@ void R_StoreWallRange (int start, int stop)
} }
// render it // render it
if (markceiling) if (markceiling) {
if (ceilingplane) // killough 4/11/98: add NULL ptr checks if (ceilingplane) // killough 4/11/98: add NULL ptr checks
ceilingplane = R_CheckPlane (ceilingplane, rw_x, rw_stopx-1); ceilingplane = R_CheckPlane (ceilingplane, rw_x, rw_stopx-1);
else else
markceiling = 0; markceiling = 0;
}
if (markfloor) if (markfloor) {
if (floorplane) // killough 4/11/98: add NULL ptr checks if (floorplane) // killough 4/11/98: add NULL ptr checks
floorplane = R_CheckPlane (floorplane, rw_x, rw_stopx-1); floorplane = R_CheckPlane (floorplane, rw_x, rw_stopx-1);
else else
markfloor = 0; markfloor = 0;
}
R_RenderSegLoop (); R_RenderSegLoop ();

View file

@ -74,7 +74,7 @@ void R_InitSkyMap (cvar_t *var)
sky1texturemid = 200/2*FRACUNIT; sky1texturemid = 200/2*FRACUNIT;
sky1stretch = (var->value && !(dmflags & DF_NO_FREELOOK)) ? 1 : 0; sky1stretch = (var->value && !(dmflags & DF_NO_FREELOOK)) ? 1 : 0;
} else { } else {
sky1texturemid = 240/2*FRACUNIT; sky1texturemid = 200*FRACUNIT;
sky1stretch = 0; sky1stretch = 0;
} }
sky1height = textureheight[sky1texture] << sky1stretch; sky1height = textureheight[sky1texture] << sky1stretch;
@ -83,18 +83,19 @@ void R_InitSkyMap (cvar_t *var)
sky2texturemid = 200/2*FRACUNIT; sky2texturemid = 200/2*FRACUNIT;
sky2stretch = (var->value && !(dmflags & DF_NO_FREELOOK)) ? 1 : 0; sky2stretch = (var->value && !(dmflags & DF_NO_FREELOOK)) ? 1 : 0;
} else { } else {
sky2texturemid = 240/2*FRACUNIT; sky2texturemid = 200*FRACUNIT;
sky2stretch = 0; sky2stretch = 0;
} }
sky2height = textureheight[sky2texture] << sky2stretch; sky2height = textureheight[sky2texture] << sky2stretch;
if (viewwidth && viewheight) {
sky1iscale = (sky1texturemid << 1) / (((freelookviewheight<<detailxshift) * viewwidth) / (viewwidth<<detailxshift));
sky1scale = ((((freelookviewheight<<detailxshift) * viewwidth) / (viewwidth<<detailxshift)) << FRACBITS) /
(sky1texturemid>>(FRACBITS-1));
sky2iscale = (sky2texturemid << FRACBITS) / (((viewheight<<detailxshift) * viewwidth) / (viewwidth<<detailxshift)); if (viewwidth && viewheight) {
sky2scale = ((((viewheight<<detailxshift) * viewwidth) / (viewwidth<<detailxshift)) << FRACBITS) / sky1iscale = (200*FRACUNIT) / (((freelookviewheight<<detailxshift) * viewwidth) / (viewwidth<<detailxshift));
(sky2texturemid>>(FRACBITS-1)); sky1scale = ((((freelookviewheight<<detailxshift) * viewwidth) / (viewwidth<<detailxshift)) << FRACBITS) /
(200);
sky2iscale = (200*FRACUNIT) / (((viewheight<<detailxshift) * viewwidth) / (viewwidth<<detailxshift));
sky2scale = ((((freelookviewheight<<detailxshift) * viewwidth) / (viewwidth<<detailxshift)) << FRACBITS) /
(200);
} }
} }

View file

@ -46,6 +46,9 @@
#include "v_video.h" #include "v_video.h"
#include "cmdlib.h"
#include "s_sound.h"
#define MINZ (FRACUNIT*4) #define MINZ (FRACUNIT*4)
@ -58,19 +61,6 @@ cvar_t *crosshair;
cvar_t *r_drawfuzz; cvar_t *r_drawfuzz;
typedef struct
{
int x1;
int x2;
int column;
int topclip;
int bottomclip;
} maskdraw_t;
// //
// Sprite rotation 0 is facing the viewer, // Sprite rotation 0 is facing the viewer,
// rotation 1 is one angle turn CLOCKWISE around the axis. // rotation 1 is one angle turn CLOCKWISE around the axis.
@ -80,11 +70,11 @@ typedef struct
// //
fixed_t pspritescale; fixed_t pspritescale;
fixed_t pspriteiscale; fixed_t pspriteiscale;
fixed_t pspriteyscale; // [RH] Aspect ratio handling (from doom3) fixed_t pspriteyscale; // [RH] Aspect ratio handling (from doom legacy)
fixed_t sky1scale; // [RH] Sky 1 scale factor fixed_t sky1scale; // [RH] Sky 1 scale factor
fixed_t sky2scale; // [RH] Sky 2 scale factor fixed_t sky2scale; // [RH] Sky 2 scale factor
lighttable_t** spritelights; int* spritelights; // [RH] Changed from lighttable_t** to int*
// constant arrays // constant arrays
// used for psprite clipping and initializing clipping // used for psprite clipping and initializing clipping
@ -109,6 +99,9 @@ spriteframe_t sprtemp[MAX_SPRITE_FRAMES];
int maxframe; int maxframe;
char* spritename; char* spritename;
// [RH] skin globals
playerskin_t *skins;
size_t numskins;
// //
@ -118,11 +111,20 @@ char* spritename;
// [RH] Removed checks for coexistance of rotation 0 with other // [RH] Removed checks for coexistance of rotation 0 with other
// rotations and made it look more like BOOM's version. // rotations and made it look more like BOOM's version.
// //
void R_InstallSpriteLump (int lump, unsigned frame, unsigned rotation, BOOL flipped) static void R_InstallSpriteLump (int lump, unsigned frame, unsigned rotation, BOOL flipped)
{ {
// [RH] Record the sprite's width, offset, and topoffset here
// instead of in R_InitSpriteLumps().
patch_t *patch;
if (frame >= MAX_SPRITE_FRAMES || rotation > 8) if (frame >= MAX_SPRITE_FRAMES || rotation > 8)
I_Error("R_InstallSpriteLump: Bad frame characters in lump %i", lump); I_FatalError ("R_InstallSpriteLump: Bad frame characters in lump %i", lump);
patch = W_CacheLumpNum (lump, PU_CACHE);
if (!(lump & 127))
Printf ("."); // [RH] Print ticker
if ((int)frame > maxframe) if ((int)frame > maxframe)
maxframe = frame; maxframe = frame;
@ -134,19 +136,78 @@ void R_InstallSpriteLump (int lump, unsigned frame, unsigned rotation, BOOL flip
for (r = 7; r >= 0; r--) for (r = 7; r >= 0; r--)
if (sprtemp[frame].lump[r] == -1) { if (sprtemp[frame].lump[r] == -1) {
sprtemp[frame].lump[r] = (short)(lump - firstspritelump); sprtemp[frame].lump[r] = (short)(lump);
sprtemp[frame].flip[r] = (byte)flipped; sprtemp[frame].flip[r] = (byte)flipped;
sprtemp[frame].rotate = false; sprtemp[frame].rotate = false;
// [RH] Need to set these, too.
sprtemp[frame].width[r] = SHORT(patch->width)<<FRACBITS;
sprtemp[frame].offset[r] = SHORT(patch->leftoffset)<<FRACBITS;
sprtemp[frame].topoffset[r] = SHORT(patch->topoffset)<<FRACBITS;
} }
} else if (sprtemp[frame].lump[--rotation] == -1) { } else if (sprtemp[frame].lump[--rotation] == -1) {
// the lump is only used for one rotation // the lump is only used for one rotation
sprtemp[frame].lump[rotation] = (short)(lump - firstspritelump); sprtemp[frame].lump[rotation] = (short)(lump);
sprtemp[frame].flip[rotation] = (byte)flipped; sprtemp[frame].flip[rotation] = (byte)flipped;
sprtemp[frame].rotate = true; sprtemp[frame].rotate = true;
// [RH] Need to set these, too.
sprtemp[frame].width[rotation] = SHORT(patch->width)<<FRACBITS;
sprtemp[frame].offset[rotation] = SHORT(patch->leftoffset)<<FRACBITS;
sprtemp[frame].topoffset[rotation] = SHORT(patch->topoffset)<<FRACBITS;
} }
} }
// [RH] Seperated out of R_InitSpriteDefs()
static void R_InstallSprite (const char *name, int num)
{
char sprname[5];
int frame;
if (maxframe == -1) {
sprites[num].numframes = 0;
return;
}
strncpy (sprname, name, 4);
sprname[4] = 0;
maxframe++;
for (frame = 0 ; frame < maxframe ; frame++)
{
switch ((int)sprtemp[frame].rotate)
{
case -1:
// no rotations were found for that frame at all
I_FatalError ("R_InstallSprite: No patches found for %s frame %c", sprname, frame+'A');
break;
case 0:
// only the first rotation is needed
break;
case 1:
// must have all 8 frames
{
int rotation;
for (rotation = 0; rotation < 8; rotation++)
if (sprtemp[frame].lump[rotation] == -1)
I_FatalError ("R_InstallSprite: Sprite %s frame %c is missing rotations",
sprname, frame+'A');
}
break;
}
}
// allocate space for the frames present and copy sprtemp to it
sprites[num].numframes = maxframe;
sprites[num].spriteframes =
Z_Malloc (maxframe * sizeof(spriteframe_t), PU_STATIC, NULL);
memcpy (sprites[num].spriteframes, sprtemp, maxframe * sizeof(spriteframe_t));
}
// //
@ -164,21 +225,25 @@ void R_InstallSpriteLump (int lump, unsigned frame, unsigned rotation, BOOL flip
// letter/number appended. // letter/number appended.
// The rotation character can be 0 to signify no rotations. // The rotation character can be 0 to signify no rotations.
// //
void R_InitSpriteDefs (char** namelist) void R_InitSpriteDefs (char **namelist)
{ {
int i; int i;
int l; int l;
int intname; int intname;
int start; int start;
int end; int end;
int realsprites;
// count the number of sprite names // count the number of sprite names
for (numsprites = 0; namelist[numsprites]; numsprites++) for (numsprites = 0; namelist[numsprites]; numsprites++)
; ;
// [RH] include skins in the count
realsprites = numsprites;
numsprites += numskins - 1;
if (!numsprites) if (!numsprites)
return; return;
sprites = Z_Malloc (numsprites * sizeof(*sprites), PU_STATIC, NULL); sprites = Z_Malloc (numsprites * sizeof(*sprites), PU_STATIC, NULL);
start = firstspritelump - 1; start = firstspritelump - 1;
@ -187,7 +252,7 @@ void R_InitSpriteDefs (char** namelist)
// scan all the lump names for each of the names, // scan all the lump names for each of the names,
// noting the highest frame letter. // noting the highest frame letter.
// Just compare 4 characters as ints // Just compare 4 characters as ints
for (i = 0; i < numsprites; i++) for (i = 0; i < realsprites; i++)
{ {
spritename = namelist[i]; spritename = namelist[i];
memset (sprtemp, -1, sizeof(sprtemp)); memset (sprtemp, -1, sizeof(sprtemp));
@ -214,59 +279,213 @@ void R_InitSpriteDefs (char** namelist)
} }
} }
// check the frames that were found for completeness R_InstallSprite (namelist[i], i);
if (maxframe == -1) }
{ }
sprites[i].numframes = 0;
// [RH]
// R_InitSkins
// Reads in everything applicable to a skin. The skins should have already
// been counted and had their identifiers assigned to namespaces.
//
static const char *skinsoundnames[8][2] = {
"dsplpain", NULL,
"dspldeth", NULL,
"dspdiehi", "xdeath1",
"dsoof", "land1",
"dsnoway", "grunt1",
"dsslop", "gibbed",
"dspunch", "fist",
"dsjump", "jump1",
};
static char facenames[7][8] = {
"xxxTR", "xxxTL", "xxxOUCH", "xxxEVL", "xxxKILL", "xxxGOD0", "xxxDEAD0"
};
static const int facelens[7] = {
5, 5, 7, 6, 7, 7, 8
};
void R_InitSkins (void)
{
char sndname[128];
int sndlumps[8];
char key[10];
int intname;
size_t i;
int j, k, base;
int stop;
char *def;
key[9] = 0;
for (i = 1; i < numskins; i++) {
for (j = 0; j < 8; j++)
sndlumps[j] = -1;
base = (W_CheckNumForName) ("S_SKIN", skins[i].namespc);
// The player sprite has 23 frames. This means that the S_SKIN
// marker needs a minimum of 23 lumps after it (probably more).
if (base >= numlumps - 23 || base == -1)
continue; continue;
} def = W_CacheLumpNum (base, PU_CACHE);
intname = 0;
maxframe++;
{
int frame;
for (frame = 0 ; frame < maxframe ; frame++) // Data is stored as "key = data". Don't see why the =
{ // is necessary, but that's the way the Doom Legacy
switch ((int)sprtemp[frame].rotate) // guys decided to do it.
{ while (def = COM_Parse (def)) {
case -1: strncpy (key, com_token, 9);
// no rotations were found for that frame at all def = COM_Parse (def);
I_Error ("R_InitSprites: No patches found " if (com_token[0] != '=') {
"for %s frame %c", namelist[i], frame+'A'); Printf ("Bad format for skin %d: %s %s", i, key, com_token);
break; break;
}
case 0: def = COM_Parse (def);
// only the first rotation is needed if (!stricmp (key, "name")) {
break; strncpy (skins[i].name, com_token, 16);
} else if (!stricmp (key, "sprite")) {
case 1: for (j = 3; j >= 0; j--)
// must have all 8 frames com_token[j] = toupper (com_token[j]);
{ intname = *((int *)com_token);
int rotation; } else if (!stricmp (key, "face")) {
for (j = 2; j >= 0; j--)
for (rotation=0 ; rotation<8 ; rotation++) skins[i].face[j] = toupper (com_token[j]);
if (sprtemp[frame].lump[rotation] == -1) } else {
I_Error ("R_InitSprites: Sprite %s frame %c " for (j = 0; j < 8; j++) {
"is missing rotations", if (!stricmp (key, skinsoundnames[j][0])) {
namelist[i], frame+'A'); // Can't use W_CheckNumForName because skin sounds
// haven't been assigned a namespace yet.
for (k = base + 1; k < numlumps &&
lumpinfo[k].handle == lumpinfo[base].handle; k++) {
if (!strnicmp (com_token, lumpinfo[k].name, 8)) {
W_SetLumpNamespace (k, skins[i].namespc);
sndlumps[j] = k;
break;
}
}
if (sndlumps[j] == -1) {
// Replacement not found, try finding it in the global namespace
sndlumps[j] = S_FindSoundByLump (W_CheckNumForName (com_token));
}
break;
} }
break; }
//if (j == 8)
// Printf ("Funny info for skin %i: %s = %s\n", i, key, com_token);
}
}
if (skins[i].name[0] == 0)
sprintf (skins[i].name, "skin%i", i);
// Register any sounds this skin provides
for (j = 0; j < 8; j++) {
if (sndlumps[j] != -1) {
if (j > 1) {
sprintf (sndname, "player/%s/%s", skins[i].name, skinsoundnames[j][1]);
S_AddSoundLump (sndname, sndlumps[j]);
} else if (j == 1) {
int r;
for (r = 1; r <= 4; r++) {
sprintf (sndname, "player/%s/death%d", skins[i].name, r);
S_AddSoundLump (sndname, sndlumps[j]);
}
} else { // j == 0
int l, r;
for (l = 1; l <= 4; l++)
for (r = 1; r <= 2; r++) {
sprintf (sndname, "player/%s/pain%d_%d", skins[i].name, l*25, r);
S_AddSoundLump (sndname, sndlumps[j]);
}
} }
} }
} }
// allocate space for the frames present and copy sprtemp to it
sprites[i].numframes = maxframe;
sprites[i].spriteframes =
Z_Malloc (maxframe * sizeof(spriteframe_t), PU_STATIC, NULL);
memcpy (sprites[i].spriteframes, sprtemp, maxframe*sizeof(spriteframe_t));
}
// Now collect the sprite frames for this skin. If the sprite name was not
// specified, use whatever immediately follows the specifier lump.
if (intname == 0) {
intname = *(int *)(lumpinfo[base+1].name);
for (stop = base + 2; stop < numlumps &&
lumpinfo[stop].handle == lumpinfo[base].handle &&
*(int *)lumpinfo[stop].name == intname; stop++)
;
} else {
stop = numlumps;
}
memset (sprtemp, -1, sizeof(sprtemp));
maxframe = -1;
for (k = base + 1;
k < stop && lumpinfo[k].handle == lumpinfo[base].handle;
k++) {
if (*(int *)lumpinfo[k].name == intname)
{
R_InstallSpriteLump (k,
lumpinfo[k].name[4] - 'A',
lumpinfo[k].name[5] - '0',
false);
if (lumpinfo[k].name[6])
R_InstallSpriteLump (k,
lumpinfo[k].name[6] - 'A',
lumpinfo[k].name[7] - '0',
true);
W_SetLumpNamespace (k, skins[i].namespc);
}
}
R_InstallSprite ((char *)&intname, (skins[i].sprite = numsprites - numskins + i));
// Now go back and check for face graphics (if necessary)
if (skins[i].face[0] == 0 || skins[i].face[1] == 0 || skins[i].face[2] == 0) {
// No face name specified, so this skin doesn't replace it
skins[i].face[0] = 0;
} else {
// Need to go through and find all face graphics for the skin
// and assign them to the skin's namespace.
for (j = 0; j < 7; j++)
strncpy (facenames[j], skins[i].face, 3);
for (k = base + 1;
k < numlumps && lumpinfo[k].handle == lumpinfo[base].handle;
k++) {
for (j = 0; j < 7; j++)
if (!strncmp (facenames[j], lumpinfo[k].name, facelens[j])) {
W_SetLumpNamespace (k, skins[i].namespc);
break;
}
}
}
}
// Grrk. May have changed sound table. Fix it.
if (numskins > 1)
S_HashSounds ();
} }
// [RH] Find a skin by name
int R_FindSkin (char *name)
{
int i;
for (i = 0; i < numskins; i++)
if (!strnicmp (skins[i].name, name, 16))
return i;
return 0;
}
// [RH] List the names of all installed skins
void Cmd_Skins (player_t *plyr, int argc, char **argv)
{
int i;
for (i = 0; i < numskins; i++)
Printf ("% 3d %s\n", i, skins[i].name);
}
// //
// GAME FUNCTIONS // GAME FUNCTIONS
@ -283,13 +502,48 @@ int newvissprite;
// R_InitSprites // R_InitSprites
// Called at program start. // Called at program start.
// //
void R_InitSprites (char** namelist) void R_InitSprites (char **namelist)
{ {
int i;
MaxVisSprites = 128; // [RH] This is the initial default value. It grows as needed. MaxVisSprites = 128; // [RH] This is the initial default value. It grows as needed.
vissprites = Malloc (MaxVisSprites * sizeof(vissprite_t)); vissprites = Malloc (MaxVisSprites * sizeof(vissprite_t));
lastvissprite = &vissprites[MaxVisSprites]; lastvissprite = &vissprites[MaxVisSprites];
// [RH] Count the number of skins, rename each S_SKIN?? identifier
// to just S_SKIN, and assign it a unique namespace.
for (i = 0; i < numlumps; i++) {
if (!strncmp (lumpinfo[i].name, "S_SKIN", 6)) {
numskins++;
lumpinfo[i].name[6] = lumpinfo[i].name[7] = 0;
W_SetLumpNamespace (i, ns_skinbase + numskins);
}
}
// [RH] We always have a default "base" skin.
numskins++;
// [RH] We may have just renamed some lumps, so we need to create the
// hash chains again.
W_InitHashChains ();
// [RH] Do some preliminary setup
skins = Z_Malloc (sizeof(*skins) * numskins, PU_STATIC, 0);
memset (skins, 0, sizeof(*skins) * numskins);
for (i = 1; i < numskins; i++) {
skins[i].namespc = i + ns_skinbase;
}
R_InitSpriteDefs (namelist); R_InitSpriteDefs (namelist);
R_InitSkins (); // [RH] Finish loading skin data
// [RH] Set up base skin
strcpy (skins[0].name, "Base");
skins[0].face[0] = 'S';
skins[0].face[1] = 'T';
skins[0].face[2] = 'F';
skins[0].sprite = SPR_PLAY;
skins[0].namespc = ns_global;
} }
@ -307,12 +561,12 @@ void R_ClearSprites (void)
// //
// R_NewVisSprite // R_NewVisSprite
// //
vissprite_t* R_NewVisSprite (void) vissprite_t *R_NewVisSprite (void)
{ {
if (vissprite_p == lastvissprite) { if (vissprite_p == lastvissprite) {
int prevvisspritenum = vissprite_p - vissprites; int prevvisspritenum = vissprite_p - vissprites;
MaxVisSprites += 64; MaxVisSprites *= 2;
vissprites = Realloc (vissprites, MaxVisSprites * sizeof(vissprite_t)); vissprites = Realloc (vissprites, MaxVisSprites * sizeof(vissprite_t));
lastvissprite = &vissprites[MaxVisSprites]; lastvissprite = &vissprites[MaxVisSprites];
vissprite_p = &vissprites[prevvisspritenum]; vissprite_p = &vissprites[prevvisspritenum];
@ -324,7 +578,6 @@ vissprite_t* R_NewVisSprite (void)
} }
// //
// R_DrawMaskedColumn // R_DrawMaskedColumn
// Used for sprites and masked mid textures. // Used for sprites and masked mid textures.
@ -391,20 +644,18 @@ void R_DrawVisSprite (vissprite_t *vis, int x1, int x2)
// [RH] Tutti-Frutti fix (also allows sprites up to 256 pixels tall) // [RH] Tutti-Frutti fix (also allows sprites up to 256 pixels tall)
dc_mask = 0xff; dc_mask = 0xff;
patch = W_CacheLumpNum (vis->patch+firstspritelump, PU_CACHE); patch = W_CacheLumpNum (vis->patch, PU_CACHE);
dc_colormap = vis->colormap; dc_colormap = vis->colormap;
if (!dc_colormap) if (vis->mobjflags & MF_SHADOW)
{ {
// NULL colormap = shadow draw // NULL colormap = shadow draw
if (!r_drawfuzz->value && TransTable) { // [RH] I use MF_SHADOW to recognize fuzz effect now instead of
dc_colormap = DefaultPalette->maps.colormaps; // a NULL colormap. This allow proper substition of
colfunc = lucentcolfunc; // MF_TRANSLUC25 with light levels if desired.
dc_transmap = TransTable + 65536; dc_transmap = TransTable + 65536; // Just in case
} else { colfunc = r_drawfuzz->value ? fuzzcolfunc : lucentcolfunc;
colfunc = fuzzcolfunc;
}
} }
else if (vis->palette) else if (vis->palette)
{ {
@ -425,6 +676,10 @@ void R_DrawVisSprite (vissprite_t *vis, int x1, int x2)
colfunc = lucentcolfunc; colfunc = lucentcolfunc;
dc_transmap = TransTable + ((vis->mobjflags & MF_TRANSLUCBITS) >> (MF_TRANSLUCSHIFT - 16)); dc_transmap = TransTable + ((vis->mobjflags & MF_TRANSLUCBITS) >> (MF_TRANSLUCSHIFT - 16));
} }
else
{
colfunc = basecolfunc;
}
//dc_iscale = abs(vis->xiscale)>>detailshift; //dc_iscale = abs(vis->xiscale)>>detailshift;
dc_iscale = FixedDiv (FRACUNIT, vis->scale); // [RH] from Doom Legacy dc_iscale = FixedDiv (FRACUNIT, vis->scale); // [RH] from Doom Legacy
@ -459,7 +714,7 @@ void R_DrawVisSprite (vissprite_t *vis, int x1, int x2)
// Generates a vissprite for a thing // Generates a vissprite for a thing
// if it might be visible. // if it might be visible.
// //
void R_ProjectSprite (mobj_t* thing) void R_ProjectSprite (mobj_t *thing)
{ {
fixed_t tr_x; fixed_t tr_x;
fixed_t tr_y; fixed_t tr_y;
@ -495,7 +750,7 @@ void R_ProjectSprite (mobj_t* thing)
// [RH] Andy Baker's stealth monsters // [RH] Andy Baker's stealth monsters
if (thing->invisible == true) if (thing->flags2 & MF2_INVISIBLE)
return; return;
// transform the origin point // transform the origin point
@ -550,26 +805,26 @@ void R_ProjectSprite (mobj_t* thing)
else else
{ {
// use single rotation for all views // use single rotation for all views
lump = sprframe->lump[0]; lump = sprframe->lump[rot = 0];
flip = (BOOL)sprframe->flip[0]; flip = (BOOL)sprframe->flip[0];
} }
// calculate edges of the shape // calculate edges of the shape
tx -= spriteoffset[lump]; tx -= sprframe->offset[rot]; // [RH] Moved out of spriteoffset[]
x1 = (centerxfrac + FixedMul (tx,xscale) ) >>FRACBITS; x1 = (centerxfrac + FixedMul (tx,xscale) ) >>FRACBITS;
// off the right side? // off the right side?
if (x1 > viewwidth) if (x1 > viewwidth)
return; return;
tx += spritewidth[lump]; tx += sprframe->width[rot]; // [RH] Moved out of spritewidth[]
x2 = ((centerxfrac + FixedMul (tx,xscale) ) >>FRACBITS) - 1; x2 = ((centerxfrac + FixedMul (tx,xscale) ) >>FRACBITS) - 1;
// off the left side // off the left side
if (x2 < 0) if (x2 < 0)
return; return;
gzt = thing->z + spritetopoffset[lump]; gzt = thing->z + sprframe->topoffset[rot]; // [RH] Moved out of spritetopoffset[]
// killough 4/9/98: clip things which are out of view due to height // killough 4/9/98: clip things which are out of view due to height
// [RH] This doesn't work too well with freelook // [RH] This doesn't work too well with freelook
@ -585,7 +840,7 @@ void R_ProjectSprite (mobj_t* thing)
if (heightsec != -1) // only clip things which are in special sectors if (heightsec != -1) // only clip things which are in special sectors
{ {
int phs = viewplayer->mo->subsector->sector->heightsec; int phs = camera->subsector->sector->heightsec;
if (phs != -1 && viewz < sectors[phs].floorheight ? if (phs != -1 && viewz < sectors[phs].floorheight ?
thing->z >= sectors[heightsec].floorheight : thing->z >= sectors[heightsec].floorheight :
@ -618,7 +873,7 @@ void R_ProjectSprite (mobj_t* thing)
if (flip) if (flip)
{ {
vis->startfrac = spritewidth[lump]-1; vis->startfrac = sprframe->width[rot]-1; // [RH] Moved out of spritewidth
vis->xiscale = -iscale; vis->xiscale = -iscale;
} }
else else
@ -632,12 +887,7 @@ void R_ProjectSprite (mobj_t* thing)
vis->patch = lump; vis->patch = lump;
// get light level // get light level
if (thing->flags & MF_SHADOW) if (fixedcolormap)
{
// shadow draw
vis->colormap = NULL;
}
else if (fixedcolormap)
{ {
// fixed map // fixed map
vis->colormap = fixedcolormap; vis->colormap = fixedcolormap;
@ -645,29 +895,26 @@ void R_ProjectSprite (mobj_t* thing)
else if (thing->frame & FF_FULLBRIGHT) else if (thing->frame & FF_FULLBRIGHT)
{ {
// full bright // full bright
vis->colormap = DefaultPalette->maps.colormaps; vis->colormap = basecolormap; // [RH] Use basecolormap
} }
else else
{ {
// diminished light // diminished light
index = xscale>>LIGHTSCALESHIFT; index = (xscale*lightscalexmul)>>LIGHTSCALESHIFT; // [RH]
if (index >= MAXLIGHTSCALE) if (index >= MAXLIGHTSCALE)
index = MAXLIGHTSCALE-1; index = MAXLIGHTSCALE-1;
vis->colormap = spritelights[index]; vis->colormap = spritelights[index] + basecolormap; // [RH] Use basecolormap
} }
} }
// //
// R_AddSprites // R_AddSprites
// During BSP traversal, this adds sprites by sector. // During BSP traversal, this adds sprites by sector.
// //
void R_AddSprites (sector_t* sec) void R_AddSprites (sector_t *sec)
{ {
mobj_t *thing; mobj_t *thing;
int lightnum; int lightnum;
@ -722,7 +969,7 @@ void R_DrawPSprite (pspdef_t* psp, unsigned flags)
sprdef = &sprites[psp->state->sprite]; sprdef = &sprites[psp->state->sprite];
#ifdef RANGECHECK #ifdef RANGECHECK
if ( (psp->state->frame & FF_FRAMEMASK) >= sprdef->numframes) { if ( (psp->state->frame & FF_FRAMEMASK) >= sprdef->numframes) {
DPrintf ("R_ProjectSprite: invalid sprite frame %i : %i\n", psp->state->sprite, psp->state->frame); DPrintf ("R_DrawPSprite: invalid sprite frame %i : %i\n", psp->state->sprite, psp->state->frame);
return; return;
} }
#endif #endif
@ -734,14 +981,14 @@ void R_DrawPSprite (pspdef_t* psp, unsigned flags)
// calculate edges of the shape // calculate edges of the shape
tx = psp->sx-((320/2)<<FRACBITS); tx = psp->sx-((320/2)<<FRACBITS);
tx -= spriteoffset[lump]; tx -= sprframe->offset[0]; // [RH] Moved out of spriteoffset[]
x1 = (centerxfrac + FixedMul (tx,pspritescale) ) >>FRACBITS; x1 = (centerxfrac + FixedMul (tx,pspritescale) ) >>FRACBITS;
// off the right side // off the right side
if (x1 > viewwidth) if (x1 > viewwidth)
return; return;
tx += spritewidth[lump]; tx += sprframe->width[0]; // [RH] Moved out of spritewidth[]
x2 = ((centerxfrac + FixedMul (tx, pspritescale) ) >>FRACBITS) - 1; x2 = ((centerxfrac + FixedMul (tx, pspritescale) ) >>FRACBITS) - 1;
// off the left side // off the left side
@ -751,7 +998,8 @@ void R_DrawPSprite (pspdef_t* psp, unsigned flags)
// store information in a vissprite // store information in a vissprite
vis = &avis; vis = &avis;
vis->mobjflags = flags; vis->mobjflags = flags;
vis->texturemid = (BASEYCENTER<<FRACBITS)+FRACUNIT/2-(psp->sy-spritetopoffset[lump]); vis->texturemid = (BASEYCENTER<<FRACBITS)+FRACUNIT/2-
(psp->sy-sprframe->topoffset[0]); // [RH] Moved out of spritetopoffset[]
vis->x1 = x1 < 0 ? 0 : x1; vis->x1 = x1 < 0 ? 0 : x1;
vis->x2 = x2 >= viewwidth ? viewwidth-1 : x2; vis->x2 = x2 >= viewwidth ? viewwidth-1 : x2;
vis->scale = pspriteyscale; vis->scale = pspriteyscale;
@ -760,7 +1008,7 @@ void R_DrawPSprite (pspdef_t* psp, unsigned flags)
if (flip) if (flip)
{ {
vis->xiscale = -pspriteiscale; vis->xiscale = -pspriteiscale;
vis->startfrac = spritewidth[lump]-1; vis->startfrac = sprframe->width[0]-1; // [RH] Moved out of spritewidth[]
} }
else else
{ {
@ -773,13 +1021,7 @@ void R_DrawPSprite (pspdef_t* psp, unsigned flags)
vis->patch = lump; vis->patch = lump;
if (viewplayer->powers[pw_invisibility] > 4*32 if (fixedcolormap)
|| viewplayer->powers[pw_invisibility] & 8)
{
// shadow draw
vis->colormap = NULL;
}
else if (fixedcolormap)
{ {
// fixed color // fixed color
vis->colormap = fixedcolormap; vis->colormap = fixedcolormap;
@ -787,12 +1029,19 @@ void R_DrawPSprite (pspdef_t* psp, unsigned flags)
else if (psp->state->frame & FF_FULLBRIGHT) else if (psp->state->frame & FF_FULLBRIGHT)
{ {
// full bright // full bright
vis->colormap = DefaultPalette->maps.colormaps; vis->colormap = basecolormap; // [RH] use basecolormap
} }
else else
{ {
// local light // local light
vis->colormap = spritelights[MAXLIGHTSCALE-1]; vis->colormap = spritelights[MAXLIGHTSCALE-1] + basecolormap; // [RH] add basecolormap
if (camera->player &&
(camera->player->powers[pw_invisibility] > 4*32
|| camera->player->powers[pw_invisibility] & 8))
{
// shadow draw
vis->mobjflags = MF_SHADOW;
}
} }
R_DrawVisSprite (vis, vis->x1, vis->x2); R_DrawVisSprite (vis, vis->x1, vis->x2);
@ -810,10 +1059,12 @@ void R_DrawPlayerSprites (void)
pspdef_t* psp; pspdef_t* psp;
if (r_drawplayersprites->value) { if (r_drawplayersprites->value) {
// [RH] set basecolormap
basecolormap = camera->subsector->sector->colormap->maps;
// get light level // get light level
lightnum = lightnum =
(viewplayer->mo->subsector->sector->lightlevel >> LIGHTSEGSHIFT) (camera->subsector->sector->lightlevel >> LIGHTSEGSHIFT) + extralight;
+extralight;
if (lightnum < 0) if (lightnum < 0)
spritelights = scalelight[0]; spritelights = scalelight[0];
@ -834,17 +1085,18 @@ void R_DrawPlayerSprites (void)
centeryfrac = centery << FRACBITS; centeryfrac = centery << FRACBITS;
// add all active psprites // add all active psprites
for (i=0, psp=viewplayer->psprites; if (camera->player)
i<NUMPSPRITES; for (i=0, psp=camera->player->psprites;
i++,psp++) i<NUMPSPRITES;
{ i++,psp++)
if (psp->state) { {
if (i == 1) if (psp->state) {
R_DrawPSprite (psp, MF_TRANSLUC75); if (i == 1)
else R_DrawPSprite (psp, MF_TRANSLUC75);
R_DrawPSprite (psp, 0); else
R_DrawPSprite (psp, 0);
}
} }
}
centery = centerhack; centery = centerhack;
centeryfrac = centerhack << FRACBITS; centeryfrac = centerhack << FRACBITS;
@ -902,6 +1154,13 @@ void R_SortVisSprites (void)
// [RH] Allocated in R_MultiresInit() to // [RH] Allocated in R_MultiresInit() to
// SCREENWIDTH entries each. // SCREENWIDTH entries each.
short *r_dsclipbot, *r_dscliptop; short *r_dsclipbot, *r_dscliptop;
// [RH] The original code used -2 to indicate that a sprite was not clipped.
// With ZDoom's freelook, it's possible that the rendering process
// could actually generate a clip value of -2, and the rendering code
// would mistake this to indicate the the sprite wasn't clipped.
#define NOT_CLIPPED (-32768)
// //
// R_DrawSprite // R_DrawSprite
// //
@ -915,7 +1174,7 @@ void R_DrawSprite (vissprite_t* spr)
fixed_t lowscale; fixed_t lowscale;
for (x = spr->x1 ; x<=spr->x2 ; x++) for (x = spr->x1 ; x<=spr->x2 ; x++)
r_dsclipbot[x] = r_dscliptop[x] = -2; r_dsclipbot[x] = r_dscliptop[x] = NOT_CLIPPED;
// Scan drawsegs from end to start for obscuring segs. // Scan drawsegs from end to start for obscuring segs.
// The first drawseg that has a greater scale is the clip seg. // The first drawseg that has a greater scale is the clip seg.
@ -968,13 +1227,13 @@ void R_DrawSprite (vissprite_t* spr)
if (ds->silhouette&SIL_BOTTOM && spr->gz < ds->bsilheight) //bottom sil if (ds->silhouette&SIL_BOTTOM && spr->gz < ds->bsilheight) //bottom sil
for (x=r1 ; x<=r2 ; x++) for (x=r1 ; x<=r2 ; x++)
if (r_dsclipbot[x] == -2) if (r_dsclipbot[x] == NOT_CLIPPED)
r_dsclipbot[x] = ds->sprbottomclip[x]; r_dsclipbot[x] = ds->sprbottomclip[x];
if (ds->silhouette&SIL_TOP && spr->gzt > ds->tsilheight) // top sil if (ds->silhouette&SIL_TOP && spr->gzt > ds->tsilheight) // top sil
for (x=r1 ; x<=r2 ; x++) for (x=r1 ; x<=r2 ; x++)
if (r_dscliptop[x] == -2) if (r_dscliptop[x] == NOT_CLIPPED)
r_dscliptop[x] = ds->sprtopclip[x]; r_dscliptop[x] = ds->sprtopclip[x];
} }
// killough 3/27/98: // killough 3/27/98:
@ -985,20 +1244,24 @@ void R_DrawSprite (vissprite_t* spr)
if (spr->heightsec != -1) // only things in specially marked sectors if (spr->heightsec != -1) // only things in specially marked sectors
{ {
fixed_t h,mh; fixed_t h,mh;
int phs = viewplayer->mo->subsector->sector->heightsec; int phs = camera->subsector->sector->heightsec;
if ((mh = sectors[spr->heightsec].floorheight) > spr->gz && if ((mh = sectors[spr->heightsec].floorheight) > spr->gz &&
(h = centeryfrac - FixedMul(mh-=viewz, spr->scale)) >= 0 && (h = centeryfrac - FixedMul(mh-=viewz, spr->scale)) >= 0 &&
(h >>= FRACBITS) < viewheight) (h >>= FRACBITS) < viewheight)
if (mh <= 0 || (phs != -1 && viewz > sectors[phs].floorheight)) {
{ // clip bottom if (mh <= 0 || (phs != -1 && viewz > sectors[phs].floorheight))
for (x=spr->x1 ; x<=spr->x2 ; x++) { // clip bottom
if (r_dsclipbot[x] == -2 || h < r_dsclipbot[x]) for (x=spr->x1 ; x<=spr->x2 ; x++)
r_dsclipbot[x] = h; if (r_dsclipbot[x] == NOT_CLIPPED || h < r_dsclipbot[x])
r_dsclipbot[x] = h;
}
else
{ // clip top
for (x=spr->x1 ; x<=spr->x2 ; x++)
if (r_dscliptop[x] == NOT_CLIPPED || h > r_dscliptop[x])
r_dscliptop[x] = h;
}
} }
else // clip top
for (x=spr->x1 ; x<=spr->x2 ; x++)
if (r_dscliptop[x] == -2 || h > r_dscliptop[x])
r_dscliptop[x] = h;
if ((mh = sectors[spr->heightsec].ceilingheight) < spr->gzt && if ((mh = sectors[spr->heightsec].ceilingheight) < spr->gzt &&
(h = centeryfrac - FixedMul(mh-viewz, spr->scale)) >= 0 && (h = centeryfrac - FixedMul(mh-viewz, spr->scale)) >= 0 &&
@ -1007,13 +1270,13 @@ void R_DrawSprite (vissprite_t* spr)
if (phs != -1 && viewz >= sectors[phs].ceilingheight) if (phs != -1 && viewz >= sectors[phs].ceilingheight)
{ // clip bottom { // clip bottom
for (x=spr->x1 ; x<=spr->x2 ; x++) for (x=spr->x1 ; x<=spr->x2 ; x++)
if (r_dsclipbot[x] == -2 || h < r_dsclipbot[x]) if (r_dsclipbot[x] == NOT_CLIPPED || h < r_dsclipbot[x])
r_dsclipbot[x] = h; r_dsclipbot[x] = h;
} }
else else
{ // clip top { // clip top
for (x=spr->x1 ; x<=spr->x2 ; x++) for (x=spr->x1 ; x<=spr->x2 ; x++)
if (r_dscliptop[x] == -2 || h > r_dscliptop[x]) if (r_dscliptop[x] == NOT_CLIPPED || h > r_dscliptop[x])
r_dscliptop[x] = h; r_dscliptop[x] = h;
} }
} }
@ -1025,10 +1288,10 @@ void R_DrawSprite (vissprite_t* spr)
// check for unclipped columns // check for unclipped columns
for (x = spr->x1 ; x<=spr->x2 ; x++) for (x = spr->x1 ; x<=spr->x2 ; x++)
{ {
if (r_dsclipbot[x] == -2) if (r_dsclipbot[x] == NOT_CLIPPED)
r_dsclipbot[x] = (short)viewheight; r_dsclipbot[x] = (short)viewheight;
if (r_dscliptop[x] == -2) if (r_dscliptop[x] == NOT_CLIPPED)
r_dscliptop[x] = -1; r_dscliptop[x] = -1;
} }
@ -1122,6 +1385,3 @@ void R_DrawMasked (void)
R_DrawPlayerSprites (); R_DrawPlayerSprites ();
} }
} }

View file

@ -20,9 +20,6 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include "m_alloc.h" #include "m_alloc.h"
@ -30,8 +27,8 @@
#include "i_system.h" #include "i_system.h"
#include "i_sound.h" #include "i_sound.h"
#include "i_music.h" #include "i_music.h"
#include "sounds.h"
#include "s_sound.h" #include "s_sound.h"
#include "c_dispch.h"
#include "z_zone.h" #include "z_zone.h"
#include "m_random.h" #include "m_random.h"
@ -42,6 +39,8 @@
#include "doomstat.h" #include "doomstat.h"
#include "cmdlib.h" #include "cmdlib.h"
#include "v_video.h"
#include "v_text.h"
#define S_MAX_VOLUME 255 #define S_MAX_VOLUME 255
@ -72,27 +71,32 @@ typedef struct
void* origin; // origin of sound void* origin; // origin of sound
int handle; // handle of the sound being played int handle; // handle of the sound being played
int volume; // [RH] volume of sound at origin int volume; // [RH] volume of sound at origin
int priority; // [RH] priority of sound
} channel_t; } channel_t;
// [RH] Hacks for pitch variance
int sfx_sawup, sfx_sawidl, sfx_sawful, sfx_sawhit;
int sfx_itemup, sfx_tink;
typedef struct sndname_s // [RH] Use surround sounds?
{ cvar_t *snd_surround;
struct sndname_s *left, *right;
int sfxid;
char name[1];
} sndname_t;
// [RH] Print sound debugging info?
cvar_t *noisedebug;
// the set of channels available // the set of channels available
static channel_t* channels; static channel_t *channels;
// Maximum volume of a sound effect. // Maximum volume of a sound effect.
// Internal default is max out of 0-15. // Internal default is max out of 0-15.
cvar_t *snd_SfxVolume; cvar_t *snd_SfxVolume;
// Maximum volume of music. Almost useless so far. // Maximum volume of MOD music.
cvar_t *snd_MusicVolume; cvar_t *snd_MusicVolume;
// Maximum volume of MIDI/MUS music.
cvar_t *snd_MidiVolume;
// whether songs are mus_paused // whether songs are mus_paused
static BOOL mus_paused; static BOOL mus_paused;
@ -105,31 +109,80 @@ static struct {
// following is set // following is set
// by the defaults code in M_misc: // by the defaults code in M_misc:
// number of channels available // number of channels available
cvar_t *snd_channels; cvar_t *snd_channels;
int numChannels; int numChannels;
static int nextcleanup; static int nextcleanup;
//
// [RH] Separated out of S_UpdateSoundParams
//
static fixed_t P_ApproxDistance (mobj_t *one, mobj_t *two)
{
// calculate the distance to sound origin
// and clip it if necessary
fixed_t adx = abs (one->x - two->x);
fixed_t ady = abs (one->y - two->y);
// From _GG1_ p.428. Appox. eucledian distance fast.
return adx + ady - ((adx < ady ? adx : ady)>>1);
}
//
// [RH] Print sound debug info. Called from D_Display()
//
void S_NoiseDebug (void)
{
int i, y;
y = 32;
if (level.time & 16)
V_DrawText (0, y, "*** SOUND DEBUG INFO ***");
y += 8;
V_DrawText (0, y, "name");
V_DrawText (100, y, "mo.x");
V_DrawText (150, y, "mo.y");
V_DrawText (200, y, "id");
V_DrawText (230, y, "pri");
V_DrawText (260, y, "dist");
y += 8;
for (i = 0; i < numChannels && y < screens[0].height - 16; i++, y += 8) {
if (channels[i].sfxinfo) {
char temp[16];
mobj_t *origin = (mobj_t *)channels[i].origin;
if ((unsigned int)origin < (unsigned int)ORIGIN_STARTOFNORMAL)
origin = players[consoleplayer].camera;
strcpy (temp, lumpinfo[channels[i].sfxinfo->lumpnum].name);
temp[8] = 0;
V_DrawText (0, y, temp);
sprintf (temp, "%d", origin->x / FRACUNIT);
V_DrawText (100, y, temp);
sprintf (temp, "%d", origin->y / FRACUNIT);
V_DrawText (150, y, temp);
sprintf (temp, "%d", channels[i].sfxinfo - S_sfx);
V_DrawText (200, y, temp);
sprintf (temp, "%d", channels[i].priority);
V_DrawText (230, y, temp);
sprintf (temp, "%d", P_ApproxDistance (players[consoleplayer].camera, origin) / FRACUNIT);
V_DrawText (260, y, temp);
} else {
V_DrawText (0, y, "------");
}
}
}
// //
// Internals. // Internals.
// //
int static int S_getChannel (void *origin, sfxinfo_t *sfxinfo, int pri);
S_getChannel static int S_AdjustSoundParams (mobj_t *listener, mobj_t *source,
( void* origin, int *vol, int *sep, int *pitch );
sfxinfo_t* sfxinfo ); static void S_StopChannel (int cnum);
int
S_AdjustSoundParams
( mobj_t* listener,
mobj_t* source,
int* vol,
int* sep,
int* pitch );
void S_StopChannel(int cnum);
static void ChangeMusicVol (cvar_t *var) static void ChangeMusicVol (cvar_t *var)
@ -142,6 +195,10 @@ static void ChangeSfxVol (cvar_t *var)
S_SetSfxVolume ((int)var->value); S_SetSfxVolume ((int)var->value);
} }
static void ChangeMidiVol (cvar_t *var)
{
I_SetMIDIVolume (var->value);
}
// //
// Initializes sound stuff, including volume // Initializes sound stuff, including volume
@ -152,24 +209,27 @@ void S_Init (int sfxVolume, int musicVolume)
{ {
int i; int i;
snd_MidiVolume->u.callback = ChangeMidiVol;
snd_MusicVolume->u.callback = ChangeMusicVol; snd_MusicVolume->u.callback = ChangeMusicVol;
snd_SfxVolume->u.callback = ChangeSfxVol; snd_SfxVolume->u.callback = ChangeSfxVol;
ChangeMidiVol (snd_MidiVolume);
Printf ("S_Init: default sfx volume %d\n", sfxVolume); Printf ("S_Init: default sfx volume %d\n", sfxVolume);
// [RH] Read in sound sequences (TODO)
//S_ParseSndSeq ();
// Whatever these did with DMX, these are rather dummies now. // Whatever these did with DMX, these are rather dummies now.
I_SetChannels(); I_SetChannels();
S_SetSfxVolume(sfxVolume); S_SetSfxVolume(sfxVolume);
// No music with Linux - another dummy.
S_SetMusicVolume(musicVolume); S_SetMusicVolume(musicVolume);
// Allocating the internal channels for mixing // Allocating the internal channels for mixing
// (the maximum numer of sounds rendered // (the maximum numer of sounds rendered
// simultaneously) within zone memory. // simultaneously) within zone memory.
numChannels = (int)snd_channels->value; numChannels = (int)snd_channels->value;
channels = channels = (channel_t *) Z_Malloc(numChannels*sizeof(channel_t), PU_STATIC, 0);
(channel_t *) Z_Malloc(numChannels*sizeof(channel_t), PU_STATIC, 0);
// Free all channels for use // Free all channels for use
for (i=0 ; i<numChannels ; i++) for (i=0 ; i<numChannels ; i++)
@ -179,13 +239,12 @@ void S_Init (int sfxVolume, int musicVolume)
mus_paused = 0; mus_paused = 0;
// Note that sounds have not been cached (yet). // Note that sounds have not been cached (yet).
for (i=1 ; i<NUMSFX ; i++) for (i=1; i < numsfx; i++)
S_sfx[i].lumpnum = S_sfx[i].usefulness = -1; S_sfx[i].usefulness = -1;
} }
// //
// Per level startup code. // Per level startup code.
// Kills playing sounds at start of level, // Kills playing sounds at start of level,
@ -197,118 +256,125 @@ void S_Start(void)
// kill all playing sounds at start of level // kill all playing sounds at start of level
// (trust me - a good idea) // (trust me - a good idea)
for (cnum=0 ; cnum<numChannels ; cnum++) for (cnum = 0; cnum < numChannels; cnum++)
if (channels[cnum].sfxinfo) if (channels[cnum].sfxinfo)
S_StopChannel(cnum); S_StopChannel (cnum);
// start new music for the level // start new music for the level
mus_paused = 0; mus_paused = 0;
// [RH] This is a lot simpler now. // [RH] This is a lot simpler now.
S_ChangeMusic(level.music, true); S_ChangeMusic (level.music, true);
nextcleanup = 15; nextcleanup = 15;
} }
// [RH] Split S_StartSoundAtVolume into two parts so that sounds can
// be specified both by id and by name.
void S_StartSfxAtVolume (void *origin_p, int sfx_id, int pri, int volume)
void S_StartSoundAtVolume (void *origin_p, int sfx_id, int volume)
{ {
int rc;
int rc; int sep;
int sep; int pitch;
int pitch; int priority;
int priority; sfxinfo_t* sfx;
sfxinfo_t* sfx; int cnum;
int cnum;
mobj_t* origin = (mobj_t *) origin_p; mobj_t* origin = (mobj_t *) origin_p;
if (sfx_id == -1) {
S_StopSound (origin);
return;
}
// Debug. // Debug.
/*fprintf( stderr, /*fprintf( stderr,
"S_StartSoundAtVolume: playing sound %d (%s)\n", "S_StartSoundAtVolume: playing sound %d (%s)\n",
sfx_id, S_sfx[sfx_id].name );*/ sfx_id, S_sfx[sfx_id].name );*/
// check for bogus sound #
if (sfx_id < 1 || sfx_id > NUMSFX)
I_Error("Bad sfx #: %d", sfx_id);
sfx = &S_sfx[sfx_id]; sfx = &S_sfx[sfx_id];
// Initialize sound parameters // Initialize sound parameters
if (sfx->link) pitch = NORM_PITCH;
{ priority = NORM_PRIORITY;
pitch = sfx->pitch;
priority = sfx->priority;
volume += sfx->volume;
if (volume < 1)
return;
}
else
{
pitch = NORM_PITCH;
priority = NORM_PRIORITY;
}
// Check to see if it is audible, // Check to see if it is audible,
// and if not, modify the params // and if not, modify the params
if (((unsigned int)origin >= (unsigned int)ORIGIN_STARTOFNORMAL) && if (((unsigned int)origin >= (unsigned int)ORIGIN_STARTOFNORMAL) &&
origin != players[displayplayer].mo) origin != players[consoleplayer].camera) // [RH] Use camera
{ {
rc = S_AdjustSoundParams(players[displayplayer].mo, rc = S_AdjustSoundParams(players[consoleplayer].camera, // [RH] Use camera
origin, origin,
&volume, &volume,
&sep, &sep,
&pitch); &pitch);
if ( origin->x == players[displayplayer].mo->x if (!rc)
&& origin->y == players[displayplayer].mo->y) return;
if ( origin->x == players[consoleplayer].camera->x // [RH] use camera
&& origin->y == players[consoleplayer].camera->y)
{ {
sep = NORM_SEP; sep = NORM_SEP;
} }
#if 0
if (!rc) else
return; {
// [RH] Don't play more than two sounds w/ approximately
// the same origin. (Doesn't work.)
int similarseps = 0;
int i;
for (i = 0; i < numChannels; i++) {
if (channels[i].sfxinfo && channels[i].origin &&
P_ApproxDistance (channels[i].origin, origin) < 64)
similarseps++;
}
if (similarseps > 1)
return;
}
#endif
} else if (((unsigned int)origin < (unsigned int)ORIGIN_STARTOFNORMAL) && } else if (((unsigned int)origin < (unsigned int)ORIGIN_STARTOFNORMAL) &&
((unsigned int)origin) & 128) { (((unsigned int)origin) & 128) &&
snd_surround->value) {
sep = -1; sep = -1;
} else { } else {
sep = NORM_SEP; sep = NORM_SEP;
} }
// hacks to vary the sfx pitches // hacks to vary the sfx pitches
if (sfx_id >= sfx_sawup && sfx_id <= sfx_sawhit) if (sfx_id == sfx_sawup || sfx_id == sfx_sawhit ||
sfx_id == sfx_sawidl || sfx_id == sfx_sawful)
pitch += 8 - (M_Random()&15); pitch += 8 - (M_Random()&15);
else if (sfx_id != sfx_itemup && sfx_id != sfx_tink) else if (sfx_id != sfx_itemup && sfx_id != sfx_tink)
pitch += 16 - (M_Random()&31); pitch += 16 - (M_Random()&31);
// kill old sound // kill old sound
S_StopSound(origin); S_StopSound (origin);
// try to find a channel // try to find a channel
cnum = S_getChannel(origin, sfx); cnum = S_getChannel (origin, sfx, pri);
if (cnum<0) if (cnum < 0)
return; return;
if (sfx->link)
sfx = sfx->link;
// //
// This is supposed to handle the loading/caching. // This is supposed to handle the loading/caching.
// For some odd reason, the caching is done nearly // For some odd reason, the caching is done nearly
// each time the sound is needed? // each time the sound is needed?
// //
// get lumpnum if necessary
if (sfx->lumpnum < 0)
sfx->lumpnum = I_GetSfxLumpNum(sfx);
// cache data if necessary // cache data if necessary
if (!sfx->data) if (!sfx->data)
{ {
Printf ("S_StartSoundAtVolume: 16bit and not pre-cached - wtf?\n"); //Printf ("S_StartSoundAtVolume: 16bit and not pre-cached - wtf?\n");
I_LoadSound (sfx);
if (sfx->link)
sfx = sfx->link;
// DOS remains, 8bit handling // DOS remains, 8bit handling
//sfx->data = (void *) W_CacheLumpNum(sfx->lumpnum, PU_MUSIC); //sfx->data = (void *) W_CacheLumpNum(sfx->lumpnum, PU_MUSIC);
@ -327,7 +393,7 @@ void S_StartSoundAtVolume (void *origin_p, int sfx_id, int volume)
// Assigns the handle to one of the channels in the // Assigns the handle to one of the channels in the
// mix/output buffer. // mix/output buffer.
channels[cnum].handle = I_StartSound(sfx_id, channels[cnum].handle = I_StartSound(sfx,
/*sfx->data,*/ /*sfx->data,*/
volume, volume,
sep, sep,
@ -335,20 +401,45 @@ void S_StartSoundAtVolume (void *origin_p, int sfx_id, int volume)
priority); priority);
} }
void S_StartSound (void *origin, int sfx_id) void S_StartSoundAtVolume (void *origin_p, char *name, int pri, int volume)
{ {
S_StartSoundAtVolume(origin, sfx_id, 255); int sfx_id;
if (*name == '*') {
// Sexed sound
char nametemp[128];
const char templat[] = "player/%s/%s";
const char *genders[] = { "male", "female", "neuter" };
player_t *player;
sfx_id = -1;
if (origin_p >= ORIGIN_STARTOFNORMAL && (player = ((mobj_t *)origin_p)->player)) {
sprintf (nametemp, templat, skins[player->userinfo.skin].name, name + 1);
sfx_id = S_FindSound (nametemp);
if (sfx_id == -1) {
sprintf (nametemp, templat, genders[player->userinfo.gender], name + 1);
sfx_id = S_FindSound (nametemp);
}
}
if (sfx_id == -1) {
sprintf (nametemp, templat, "male", name + 1);
sfx_id = S_FindSound (nametemp);
}
} else
sfx_id = S_FindSound (name);
if (sfx_id == -1)
DPrintf ("Unknown sound %s\n", name);
S_StartSfxAtVolume (origin_p, sfx_id, pri, volume);
} }
void S_StopSound (void *origin)
void S_StopSound(void *origin)
{ {
int cnum; int cnum;
for (cnum=0 ; cnum<numChannels ; cnum++) for (cnum = 0; cnum < numChannels; cnum++)
{ {
if (channels[cnum].sfxinfo && channels[cnum].origin == origin) if (channels[cnum].sfxinfo && channels[cnum].origin == origin)
{ {
@ -359,13 +450,6 @@ void S_StopSound(void *origin)
} }
// //
// Stop and resume music, during game PAUSE. // Stop and resume music, during game PAUSE.
// //
@ -378,11 +462,11 @@ void S_PauseSound(void)
} }
} }
void S_ResumeSound(void) void S_ResumeSound (void)
{ {
if (mus_playing.handle && mus_paused) if (mus_playing.handle && mus_paused)
{ {
I_ResumeSong(mus_playing.handle); I_ResumeSong (mus_playing.handle);
mus_paused = false; mus_paused = false;
} }
} }
@ -391,7 +475,7 @@ void S_ResumeSound(void)
// //
// Updates music & sounds // Updates music & sounds
// //
void S_UpdateSounds(void* listener_p) void S_UpdateSounds (void *listener_p)
{ {
int audible; int audible;
int cnum; int cnum;
@ -412,8 +496,7 @@ void S_UpdateSounds(void* listener_p)
{ {
for (i=1 ; i<NUMSFX ; i++) for (i=1 ; i<NUMSFX ; i++)
{ {
if (S_sfx[i].usefulness < 1 if (S_sfx[i].usefulness < 1 && S_sfx[i].usefulness > -1)
&& S_sfx[i].usefulness > -1)
{ {
if (--S_sfx[i].usefulness == -1) if (--S_sfx[i].usefulness == -1)
{ {
@ -425,31 +508,20 @@ void S_UpdateSounds(void* listener_p)
nextcleanup = gametic + 15; nextcleanup = gametic + 15;
}*/ }*/
for (cnum=0 ; cnum<numChannels ; cnum++) for (cnum = 0; cnum < numChannels; cnum++)
{ {
c = &channels[cnum]; c = &channels[cnum];
sfx = c->sfxinfo; sfx = c->sfxinfo;
if (c->sfxinfo) if (c->sfxinfo)
{ {
if (I_SoundIsPlaying(c->handle)) if (I_SoundIsPlaying (c->handle))
{ {
// initialize parameters // initialize parameters
volume = c->volume; volume = c->volume;
pitch = NORM_PITCH; pitch = NORM_PITCH;
sep = NORM_SEP; sep = NORM_SEP;
if (sfx->link)
{
pitch = sfx->pitch;
volume += sfx->volume;
if (volume < 1)
{
S_StopChannel(cnum);
continue;
}
}
// check non-local sounds for distance clipping // check non-local sounds for distance clipping
// or modify their params // or modify their params
if (c->origin >= ORIGIN_STARTOFNORMAL && listener_p != c->origin) if (c->origin >= ORIGIN_STARTOFNORMAL && listener_p != c->origin)
@ -462,10 +534,10 @@ void S_UpdateSounds(void* listener_p)
if (!audible) if (!audible)
{ {
S_StopChannel(cnum); S_StopChannel (cnum);
} }
else else
I_UpdateSoundParams(c->handle, volume, sep, pitch); I_UpdateSoundParams (c->handle, volume, sep, pitch);
} }
} }
else else
@ -589,7 +661,7 @@ void S_StopMusic(void)
void S_StopChannel(int cnum) static void S_StopChannel(int cnum)
{ {
int i; int i;
@ -629,20 +701,13 @@ void S_StopChannel(int cnum)
// If the sound is not audible, returns a 0. // If the sound is not audible, returns a 0.
// Otherwise, modifies parameters and returns 1. // Otherwise, modifies parameters and returns 1.
// //
int S_AdjustSoundParams (mobj_t *listener, mobj_t *source, int *vol, int *sep, int *pitch) static int S_AdjustSoundParams (mobj_t *listener, mobj_t *source,
int *vol, int *sep, int *pitch)
{ {
fixed_t approx_dist; fixed_t approx_dist;
fixed_t adx;
fixed_t ady;
angle_t angle; angle_t angle;
// calculate the distance to sound origin approx_dist = P_ApproxDistance (listener, source);
// and clip it if necessary
adx = abs(listener->x - source->x);
ady = abs(listener->y - source->y);
// From _GG1_ p.428. Appox. eucledian distance fast.
approx_dist = adx + ady - ((adx < ady ? adx : ady)>>1);
if (!(level.flags & LEVEL_NOSOUNDCLIPPING) && approx_dist > S_CLIPPING_DIST) if (!(level.flags & LEVEL_NOSOUNDCLIPPING) && approx_dist > S_CLIPPING_DIST)
{ {
@ -694,18 +759,14 @@ int S_AdjustSoundParams (mobj_t *listener, mobj_t *source, int *vol, int *sep, i
// S_getChannel : // S_getChannel :
// If none available, return -1. Otherwise channel #. // If none available, return -1. Otherwise channel #.
// //
int static int S_getChannel (void *origin, sfxinfo_t *sfxinfo, int pri)
S_getChannel
( void* origin,
sfxinfo_t* sfxinfo )
{ {
// channel number to use // channel number to use
int cnum; int cnum;
channel_t *c;
channel_t* c;
// Find an open channel // Find an open channel
for (cnum=0 ; cnum<numChannels ; cnum++) for (cnum = 0; cnum < numChannels; cnum++)
{ {
if (!channels[cnum].sfxinfo) if (!channels[cnum].sfxinfo)
break; break;
@ -720,8 +781,8 @@ S_getChannel
if (cnum == numChannels) if (cnum == numChannels)
{ {
// Look for lower priority // Look for lower priority
for (cnum=0 ; cnum<numChannels ; cnum++) for (cnum = 0; cnum < numChannels; cnum++)
if (channels[cnum].sfxinfo->priority >= sfxinfo->priority) break; if (channels[cnum].priority >= pri) break;
if (cnum == numChannels) if (cnum == numChannels)
{ {
@ -740,6 +801,7 @@ S_getChannel
// channel is decided to be cnum. // channel is decided to be cnum.
c->sfxinfo = sfxinfo; c->sfxinfo = sfxinfo;
c->origin = origin; c->origin = origin;
c->priority = pri;
return cnum; return cnum;
} }
@ -750,110 +812,105 @@ S_getChannel
// //
// =============================== [RH] // =============================== [RH]
typedef struct { sfxinfo_t *S_sfx; // [RH] This is no longer defined in sounds.c
thinker_t thinker; static int maxsfx; // [RH] Current size of S_sfx array.
struct AmbientSound *ambient; int numsfx; // [RH] Current number of sfx defined.
int ticker;
} ambientthinker_t;
static struct AmbientSound { static struct AmbientSound {
unsigned type; // type of ambient sound unsigned type; // type of ambient sound
int periodmin; // # of tics between repeats int periodmin; // # of tics between repeats
int periodmax; // max # of tics for random ambients int periodmax; // max # of tics for random ambients
int volume; // relative volume of sound int volume; // relative volume of sound
int sfxid; // ID of attached real sound char sound[MAX_SNDNAME+1]; // Logical name of sound to play
ambientthinker_t *thinker; // thinker for world sound } Ambients[256];
} Ambients[64];
#define RANDOM 1 #define RANDOM 1
#define PERIODIC 2 #define PERIODIC 2
#define POSITIONAL 4 #define POSITIONAL 4
#define SURROUND 16 #define SURROUND 16
static sndname_t *LogicalNames; void S_HashSounds (void)
int S_GetFreeSoundIndex (void)
{ {
static int freeIndex = sfx_ambient0; int i;
unsigned j;
if (freeIndex <= sfx_ambient63) // Mark all buckets as empty
return freeIndex++; for (i = 0; i < numsfx; i++)
else S_sfx[i].index = -1;
return sfx_None;
// Now set up the chains
for (i = 0; i < numsfx; i++) {
j = MakeKey (S_sfx[i].name) % (unsigned)numsfx;
S_sfx[i].next = S_sfx[j].index;
S_sfx[j].index = i;
}
} }
int S_GetSoundIndexFromLumpName (char *lumpname) int S_FindSound (const char *logicalname)
{ {
int i; int i;
for (i = sfx_ambient0; i <= sfx_ambient63; i++) i = S_sfx[MakeKey (logicalname) % (unsigned)numsfx].index;
if (S_sfx[i].name)
if (!stricmp (S_sfx[i].name, lumpname))
return i;
return sfx_None; while ((i != -1) && strnicmp (S_sfx[i].name, logicalname, MAX_SNDNAME))
i = S_sfx[i].next;
return i;
} }
static sndname_t **InsertionPoint; int S_FindSoundByLump (int lump)
sndname_t *S_FindLogicalName (char *logicalname)
{ {
sndname_t *sound; if (lump != -1) {
int cmpval; int i;
InsertionPoint = &LogicalNames; for (i = 0; i < numsfx; i++)
sound = LogicalNames; if (S_sfx[i].lumpnum == lump)
return i;
}
return -1;
}
while (sound) { int S_AddSoundLump (char *logicalname, int lump)
cmpval = strcmp (sound->name, logicalname); {
if (cmpval == 0) { if (numsfx == maxsfx) {
return sound; maxsfx = maxsfx ? maxsfx*2 : 128;
} else if (cmpval < 0) { S_sfx = Realloc (S_sfx, maxsfx * sizeof(*S_sfx));
InsertionPoint = &sound->left;
sound = sound->left;
} else {
InsertionPoint = &sound->right;
sound = sound->right;
}
} }
return NULL; // logicalname MUST be < MAX_SNDNAME chars long
strcpy (S_sfx[numsfx].name, logicalname);
S_sfx[numsfx].data = NULL;
S_sfx[numsfx].link = NULL;
S_sfx[numsfx].usefulness = 0;
S_sfx[numsfx].lumpnum = lump;
return numsfx++;
} }
void S_AddLogicalName (char *logicalname, char *lumpname) int S_AddSound (char *logicalname, char *lumpname)
{ {
sndname_t *sound;
int sfxid; int sfxid;
lumpname += 2; // Skip ds header // If the sound has already been defined, change the old definition.
for (sfxid = 0; sfxid < numsfx; sfxid++)
if (0 == stricmp (logicalname, S_sfx[sfxid].name))
break;
if (!(sound = S_FindLogicalName (logicalname))) { // Otherwise, prepare a new one.
sound = Malloc (sizeof(sndname_t) + strlen (logicalname)); if (sfxid == numsfx) {
sound->left = NULL; sfxid = S_AddSoundLump (logicalname, W_CheckNumForName (lumpname));
sound->right = NULL; } else {
strcpy (sound->name, logicalname); S_sfx[sfxid].lumpnum = W_CheckNumForName (lumpname);
*InsertionPoint = sound;
} }
if ((sfxid = S_GetSoundIndexFromLumpName (lumpname)) == sfx_None) { return sfxid;
if ((sfxid = S_GetFreeSoundIndex ()) == sfx_None) {
Printf ("no room to add %s to sound table\n", lumpname);
} else {
S_sfx[sfxid].name = copystring (lumpname);
}
}
sound->sfxid = sfxid;
} }
// S_ParseSndInfo // S_ParseSndInfo
// Parses all loaded SNDINFO lumps. Currently, this is only used // Parses all loaded SNDINFO lumps.
// to gather information for ambient sounds.
void S_ParseSndInfo (void) void S_ParseSndInfo (void)
{ {
int lastlump, lump; int lastlump, lump;
char *sndinfo; char *sndinfo;
char *logicalname;
char *data; char *data;
lastlump = 0; lastlump = 0;
@ -876,41 +933,31 @@ void S_ParseSndInfo (void)
if (!stricmp (com_token + 1, "ambient")) { if (!stricmp (com_token + 1, "ambient")) {
// $ambient <num> <logical name> [point|surround] <type> [secs] <relative volume> // $ambient <num> <logical name> [point|surround] <type> [secs] <relative volume>
struct AmbientSound *ambient, dummy; struct AmbientSound *ambient, dummy;
sndname_t *logicalinfo;
int index; int index;
sndinfo = COM_Parse (sndinfo); sndinfo = COM_Parse (sndinfo);
index = atoi (com_token); index = atoi (com_token);
if (index < 1 || index > 64) { if (index < 0 || index > 255) {
Printf ("Bad ambient index (%d)\n", index); Printf ("Bad ambient index (%d)\n", index);
ambient = &dummy; ambient = &dummy;
} else { } else {
index--;
ambient = Ambients + index; ambient = Ambients + index;
} }
memset (ambient, 0, sizeof(struct AmbientSound)); memset (ambient, 0, sizeof(struct AmbientSound));
sndinfo = COM_Parse (sndinfo); sndinfo = COM_Parse (sndinfo);
logicalinfo = S_FindLogicalName (com_token); strncpy (ambient->sound, com_token, MAX_SNDNAME);
if (logicalinfo) ambient->sound[MAX_SNDNAME] = 0;
ambient->sfxid = logicalinfo->sfxid;
else
ambient->sfxid = sfx_None;
sndinfo = COM_Parse (sndinfo); sndinfo = COM_Parse (sndinfo);
if (!stricmp (com_token, "point")) { if (!stricmp (com_token, "point")) {
ambient->type = POSITIONAL; ambient->type = POSITIONAL;
sndinfo = COM_Parse (sndinfo); sndinfo = COM_Parse (sndinfo);
if (ambient != &dummy) {
mobjinfo[MT_AMBIENT0 + index].spawnstate = S_AMBIENTSOUND;
}
} else { } else {
if (!stricmp (com_token, "surround")) { if (!stricmp (com_token, "surround")) {
ambient->type = SURROUND; ambient->type = SURROUND;
sndinfo = COM_Parse (sndinfo); sndinfo = COM_Parse (sndinfo);
} }
if (ambient != &dummy)
mobjinfo[MT_AMBIENT0 + index].spawnstate = S_NULL;
} }
if (!stricmp (com_token, "continuous")) { if (!stricmp (com_token, "continuous")) {
@ -951,14 +998,57 @@ void S_ParseSndInfo (void)
} }
} else { } else {
// com_token is a logical sound mapping // com_token is a logical sound mapping
char name[MAX_SNDNAME+1];
logicalname = copystring (com_token); strncpy (name, com_token, MAX_SNDNAME);
name[MAX_SNDNAME] = 0;
sndinfo = COM_Parse (sndinfo); sndinfo = COM_Parse (sndinfo);
S_AddLogicalName (logicalname, com_token); S_AddSound (name, com_token);
free (logicalname);
} }
} }
} }
S_HashSounds ();
// [RH] Hack for pitch varying
sfx_sawup = S_FindSound ("weapons/sawup");
sfx_sawidl = S_FindSound ("weapons/sawidle");
sfx_sawful = S_FindSound ("weapons/sawfull");
sfx_sawhit = S_FindSound ("weapons/sawhit");
sfx_itemup = S_FindSound ("misc/i_pkup");
sfx_tink = S_FindSound ("misc/chat2");
}
void Cmd_Soundlist (void *plyr, int argc, char **argv)
{
char lumpname[9];
int i;
lumpname[8] = 0;
for (i = 0; i < numsfx; i++)
if (S_sfx[i].lumpnum != -1) {
strncpy (lumpname, lumpinfo[S_sfx[i].lumpnum].name, 8);
Printf ("%3d. %s (%s)\n", i+1, S_sfx[i].name, lumpname);
} else
Printf ("%3d. %s **not present**\n", i+1, S_sfx[i].name);
}
void Cmd_Soundlinks (void *plyr, int argc, char **argv)
{
int i;
for (i = 0; i < numsfx; i++)
if (S_sfx[i].link)
Printf ("%s -> %s\n", S_sfx[i].name, S_sfx[i].link->name);
}
void S_StartAmbient (char *name, int volume, BOOL surround)
{
static int last = -1;
if (++last >= 64)
last = 0;
S_StartSoundAtVolume ((mobj_t *)((8+last)|(surround?128:0)), name, 32, volume);
} }
static void SetTicker (int *tics, struct AmbientSound *ambient) static void SetTicker (int *tics, struct AmbientSound *ambient)
@ -974,12 +1064,13 @@ static void SetTicker (int *tics, struct AmbientSound *ambient)
void A_Ambient (mobj_t *actor) void A_Ambient (mobj_t *actor)
{ {
struct AmbientSound *ambient; struct AmbientSound *ambient = &Ambients[actor->args[0]];
ambient = &Ambients[actor->type - MT_AMBIENT0]; if (ambient->sound[0]) {
if (ambient->type & POSITIONAL)
if (ambient->sfxid) { S_StartSoundAtVolume (actor, ambient->sound, 32, ambient->volume);
S_StartSoundAtVolume (actor, ambient->sfxid, ambient->volume); else
S_StartAmbient (ambient->sound, ambient->volume, ambient->type & SURROUND);
SetTicker (&actor->tics, ambient); SetTicker (&actor->tics, ambient);
} else { } else {
@ -987,58 +1078,21 @@ void A_Ambient (mobj_t *actor)
} }
} }
void T_WorldAmbient (ambientthinker_t *thinker) void S_ActivateAmbient (mobj_t *origin, int ambient)
{
struct AmbientSound *ambient;
int channel;
if (thinker->ticker) {
thinker->ticker--;
return;
}
ambient = thinker->ambient;
channel = ambient - Ambients + 8;
if (ambient->type & SURROUND)
channel |= 128;
S_StartSoundAtVolume ((void *)channel, ambient->sfxid, ambient->volume);
SetTicker (&thinker->ticker, ambient);
}
void S_ActivateAmbient (void *origin, int ambient)
{ {
struct AmbientSound *amb = &Ambients[ambient]; struct AmbientSound *amb = &Ambients[ambient];
if (!(amb->type & 3) && !amb->periodmin) if (!(amb->type & 3) && !amb->periodmin) {
amb->periodmin = (S_sfx[amb->sfxid].ms * TICRATE) / 1000; sfxinfo_t *sfx = S_sfx + S_FindSound (amb->sound);
if (amb->type & POSITIONAL) { // Make sure the sound has been loaded so we know how long it is
// Point sounds if (!sfx->data)
} else { I_LoadSound (sfx);
// World sounds amb->periodmin = (sfx->ms * TICRATE) / 1000;
DPrintf ("ActivateAmbient %d\n", ambient);
if (!amb->thinker) {
Z_Malloc (sizeof(ambientthinker_t), PU_LEVSPEC, &amb->thinker);
P_AddThinker (&amb->thinker->thinker);
amb->thinker->ambient = amb;
amb->thinker->thinker.function.acp1 = (actionf_p1) T_WorldAmbient;
if (amb->type & 3)
SetTicker (&amb->thinker->ticker, amb);
else
amb->thinker->ticker = 0;
}
} }
if (amb->type & (RANDOM|PERIODIC))
SetTicker (&origin->tics, amb);
else
origin->tics = 1;
} }
void S_ClearAmbients (void)
{
int i;
for (i = 0; i < 64; i++)
if (Ambients[i].thinker) {
P_RemoveThinker ((thinker_t *)Ambients[i].thinker);
Ambients[i].thinker = NULL;
}
}

View file

@ -25,38 +25,56 @@
#define MAX_SNDNAME 63
// //
// SoundFX struct.
//
typedef struct sfxinfo_struct sfxinfo_t;
struct sfxinfo_struct
{
char name[MAX_SNDNAME+1]; // [RH] Sound name defined in SNDINFO
void* data; // sound data
struct sfxinfo_struct *link;
// this is checked every second to see if sound
// can be thrown out (if 0, then decrement, if -1,
// then throw out, if > 0, then it is in use)
int usefulness;
int lumpnum; // lump number of sfx
unsigned int ms; // [RH] length of sfx in milliseconds
unsigned int next, index; // [RH] For hashing
};
// the complete set of sound effects
extern sfxinfo_t *S_sfx;
// [RH] Number of defined sounds
extern int numsfx;
// Initializes sound stuff, including volume // Initializes sound stuff, including volume
// Sets channels, SFX and music volume, // Sets channels, SFX and music volume,
// allocates channel buffer, sets S_sfx lookup. // allocates channel buffer, sets S_sfx lookup.
// //
void void S_Init (int sfxVolume, int musicVolume);
S_Init
( int sfxVolume,
int musicVolume );
//
// Per level startup code. // Per level startup code.
// Kills playing sounds at start of level, // Kills playing sounds at start of level,
// determines music if any, changes music. // determines music if any, changes music.
// //
void S_Start(void); void S_Start(void);
// Start sound for thing at <origin> using <sound_id> from sounds.h
// // [RH] macro-fied
// Start sound for thing at <origin> #define S_StartSound(o,n,p) S_StartSoundAtVolume (o,n,p,255)
// using <sound_id> from sounds.h #define S_StartSfx(o,n,p) S_StartSfxAtVolume (o,n,p,255)
//
void S_StartSound (void *origin, int sound_id);
// Will start a sound at a given volume. // Will start a sound at a given volume.
void S_StartSoundAtVolume (void *origin, int sound_id, int volume); void S_StartSoundAtVolume (void *origin, char *name, int pri, int volume);
void S_StartSfxAtVolume (void *origin, int sfxid, int pri, int volume);
#define ORIGIN_SURROUNDBIT (128) #define ORIGIN_SURROUNDBIT (128)
#define ORIGIN_AMBIENT (NULL) // Sound is not attenuated #define ORIGIN_AMBIENT (NULL) // Sound is not attenuated
@ -71,11 +89,14 @@ void S_StartSoundAtVolume (void *origin, int sound_id, int volume);
#define ORIGIN_STARTOFNORMAL ((void *)256) // [RH] Used internally #define ORIGIN_STARTOFNORMAL ((void *)256) // [RH] Used internally
// [RH] Simplified world ambient playing. Will cycle through all
// ORIGIN_WORLDAMBIENTS positions automatically.
void S_StartAmbient (char *name, int volume, int surround);
// Stop sound for thing at <origin> // Stop sound for thing at <origin>
void S_StopSound (void *origin); void S_StopSound (void *origin);
// Start music using <music_name> // Start music using <music_name>
void S_StartMusic (char *music_name); void S_StartMusic (char *music_name);
@ -100,15 +121,25 @@ void S_SetMusicVolume (int volume);
void S_SetSfxVolume (int volume); void S_SetSfxVolume (int volume);
// [RH] Parses all SNDINFO lumps. Should be called from I_InitSound()
void S_ParseSndInfo (void);
// [RH] Activates an ambient sound. Called when the thing is added to the map. // [RH] Activates an ambient sound. Called when the thing is added to the map.
// (0-biased) // (0-biased)
void S_ActivateAmbient (void *mobj, int ambient); void S_ActivateAmbient (void *mobj, int ambient);
// [RH] Deactivates all ambient sounds. // [RH] S_sfx "maintenance" routines
void S_ClearAmbients (void); void S_ParseSndInfo (void);
void S_HashSounds (void);
int S_FindSound (const char *logicalname);
int S_FindSoundByLump (int lump);
int S_AddSound (char *logicalname, char *lumpname); // Add sound by lumpname
int S_AddSoundLump (char *logicalname, int lump); // Add sound by lump index
// [RH] Prints sound debug info to the screen.
// Modelled after Hexen's noise cheat.
void S_NoiseDebug (void);
extern struct cvar_s *noisedebug;
#endif #endif
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------

View file

@ -31,6 +31,7 @@
// //
// Information about all the sfx // Information about all the sfx
// //
#if 0
sfxinfo_t S_sfx[] = sfxinfo_t S_sfx[] =
{ {
@ -212,4 +213,5 @@ sfxinfo_t S_sfx[] =
{ 0L, false, 32, 0, -1, -1, 0 }, { 0L, false, 32, 0, -1, -1, 0 },
{ 0L, false, 32, 0, -1, -1, 0 } { 0L, false, 32, 0, -1, -1, 0 }
}; };
#endif

View file

@ -1,264 +0,0 @@
// Emacs style mode select -*- C++ -*-
//-----------------------------------------------------------------------------
//
// $Id:$
//
// Copyright (C) 1993-1996 by id Software, Inc.
//
// This source is available for distribution and/or modification
// only under the terms of the DOOM Source Code License as
// published by id Software. All rights reserved.
//
// The source is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
// for more details.
//
// DESCRIPTION:
// Created by the sound utility written by Dave Taylor.
// Kept as a sample, DOOM2 sounds. Frozen.
//
//-----------------------------------------------------------------------------
#ifndef __SOUNDS__
#define __SOUNDS__
//
// SoundFX struct.
//
typedef struct sfxinfo_struct sfxinfo_t;
struct sfxinfo_struct
{
// up to 6-character name
char *name;
// Sfx singularity (only one at a time)
int singularity;
// Sfx priority
int priority;
// referenced sound if a link
sfxinfo_t* link;
// pitch if a link
int pitch;
// volume if a link
int volume;
// sound data
void* data;
// this is checked every second to see if sound
// can be thrown out (if 0, then decrement, if -1,
// then throw out, if > 0, then it is in use)
int usefulness;
// lump number of sfx
int lumpnum;
// [RH] length of sfx in milliseconds
unsigned ms;
};
// the complete set of sound effects
extern sfxinfo_t S_sfx[];
//
// Identifiers for all sfx in game.
//
typedef enum
{
sfx_None,
sfx_pistol,
sfx_shotgn,
sfx_sgcock,
sfx_dshtgn,
sfx_dbopn,
sfx_dbcls,
sfx_dbload,
sfx_plasma,
sfx_bfg,
sfx_sawup,
sfx_sawidl,
sfx_sawful,
sfx_sawhit,
sfx_rlaunc,
sfx_rxplod,
sfx_firsht,
sfx_firxpl,
sfx_pstart,
sfx_pstop,
sfx_doropn,
sfx_dorcls,
sfx_stnmov,
sfx_swtchn,
sfx_swtchx,
sfx_plpain,
sfx_dmpain,
sfx_popain,
sfx_vipain,
sfx_mnpain,
sfx_pepain,
sfx_slop,
sfx_itemup,
sfx_wpnup,
sfx_oof,
sfx_telept,
sfx_posit1,
sfx_posit2,
sfx_posit3,
sfx_bgsit1,
sfx_bgsit2,
sfx_sgtsit,
sfx_cacsit,
sfx_brssit,
sfx_cybsit,
sfx_spisit,
sfx_bspsit,
sfx_kntsit,
sfx_vilsit,
sfx_mansit,
sfx_pesit,
sfx_sklatk,
sfx_sgtatk,
sfx_skepch,
sfx_vilatk,
sfx_claw,
sfx_skeswg,
sfx_pldeth,
sfx_pdiehi,
sfx_podth1,
sfx_podth2,
sfx_podth3,
sfx_bgdth1,
sfx_bgdth2,
sfx_sgtdth,
sfx_cacdth,
sfx_skldth,
sfx_brsdth,
sfx_cybdth,
sfx_spidth,
sfx_bspdth,
sfx_vildth,
sfx_kntdth,
sfx_pedth,
sfx_skedth,
sfx_posact,
sfx_bgact,
sfx_dmact,
sfx_bspact,
sfx_bspwlk,
sfx_vilact,
sfx_noway,
sfx_barexp,
sfx_punch,
sfx_hoof,
sfx_metal,
sfx_chgun,
sfx_tink,
sfx_bdopn,
sfx_bdcls,
sfx_itmbk,
sfx_flame,
sfx_flamst,
sfx_getpow,
sfx_bospit,
sfx_boscub,
sfx_bossit,
sfx_bospn,
sfx_bosdth,
sfx_manatk,
sfx_mandth,
sfx_sssit,
sfx_ssdth,
sfx_keenpn,
sfx_keendt,
sfx_skeact,
sfx_skesit,
sfx_skeatk,
sfx_radio,
// [RH] Sound played when entering secret sector
sfx_secret,
// [RH] Up to 64 ambient sounds
sfx_ambient0,
sfx_ambient1,
sfx_ambient2,
sfx_ambient3,
sfx_ambient4,
sfx_ambient5,
sfx_ambient6,
sfx_ambient7,
sfx_ambient8,
sfx_ambient9,
sfx_ambient10,
sfx_ambient11,
sfx_ambient12,
sfx_ambient13,
sfx_ambient14,
sfx_ambient15,
sfx_ambient16,
sfx_ambient17,
sfx_ambient18,
sfx_ambient19,
sfx_ambient20,
sfx_ambient21,
sfx_ambient22,
sfx_ambient23,
sfx_ambient24,
sfx_ambient25,
sfx_ambient26,
sfx_ambient27,
sfx_ambient28,
sfx_ambient29,
sfx_ambient30,
sfx_ambient31,
sfx_ambient32,
sfx_ambient33,
sfx_ambient34,
sfx_ambient35,
sfx_ambient36,
sfx_ambient37,
sfx_ambient38,
sfx_ambient39,
sfx_ambient40,
sfx_ambient41,
sfx_ambient42,
sfx_ambient43,
sfx_ambient44,
sfx_ambient45,
sfx_ambient46,
sfx_ambient47,
sfx_ambient48,
sfx_ambient49,
sfx_ambient50,
sfx_ambient51,
sfx_ambient52,
sfx_ambient53,
sfx_ambient54,
sfx_ambient55,
sfx_ambient56,
sfx_ambient57,
sfx_ambient58,
sfx_ambient59,
sfx_ambient60,
sfx_ambient61,
sfx_ambient62,
sfx_ambient63,
NUMSFX
} sfxenum_t;
#endif
//-----------------------------------------------------------------------------
//
// $Log:$
//
//-----------------------------------------------------------------------------

View file

@ -58,7 +58,6 @@
// Data. // Data.
#include "dstrings.h" #include "dstrings.h"
#include "sounds.h"
// Cheats and cvars // Cheats and cvars
#include "c_cmds.h" #include "c_cmds.h"
@ -84,20 +83,16 @@ void ST_initNew (void);
void ST_unloadNew (void); void ST_unloadNew (void);
void ST_newDraw (void); void ST_newDraw (void);
// [RH] Base blending values (for e.g. underwater)
int BaseBlendR, BaseBlendG, BaseBlendB;
float BaseBlendA;
// //
// STATUS BAR DATA // STATUS BAR DATA
// //
// Palette indices.
// For damage/bonus red-/gold-shifts
#define STARTREDPALS 1
#define STARTBONUSPALS 9
#define NUMREDPALS 8
#define NUMBONUSPALS 4
// Radiation suit, green shift.
#define RADIATIONPAL 13
// N/256*100% probability // N/256*100% probability
// that the normal face state will change // that the normal face state will change
#define ST_FACEPROBABILITY 96 #define ST_FACEPROBABILITY 96
@ -106,10 +101,7 @@ void ST_newDraw (void);
#define ST_TOGGLECHAT KEY_ENTER #define ST_TOGGLECHAT KEY_ENTER
// Location of status bar // Location of status bar
#define ST_X2 (104)
#define ST_FX (143) #define ST_FX (143)
#define ST_FY (1)
// Should be set to patch width // Should be set to patch width
// for tall numbers later on // for tall numbers later on
@ -298,9 +290,6 @@ BOOL st_firsttime;
// used to execute ST_Init() only once // used to execute ST_Init() only once
static int veryfirsttime = 1; static int veryfirsttime = 1;
// lump number for PLAYPAL
static int lu_palette;
// used for timing // used for timing
static unsigned int st_clock; static unsigned int st_clock;
@ -348,11 +337,10 @@ patch_t* tallpercent;
// 0-9, short, yellow (,different!) numbers // 0-9, short, yellow (,different!) numbers
static patch_t* shortnum[10]; static patch_t* shortnum[10];
// 3 key-cards, 3 skulls // 3 key-cards, 3 skulls, [RH] 3 combined
static patch_t* keys[NUMCARDS]; static patch_t* keys[NUMCARDS+NUMCARDS/2];
// face status patches // face status patches [RH] no longer static
// [RH] no longer static
patch_t* faces[ST_NUMFACES]; patch_t* faces[ST_NUMFACES];
// face background // face background
@ -535,8 +523,7 @@ void ST_refreshBackground(void)
if (netgame) { if (netgame) {
// [RH] Always draw faceback with the player's color // [RH] Always draw faceback with the player's color
// using a translation rather than a different patch. // using a translation rather than a different patch.
// Use displayplayer instead of consoleplayer. V_ColorMap = translationtables + (plyr - players)*256;
V_ColorMap = translationtables + displayplayer*256;
V_DrawTranslatedPatch (ST_FX, 0, &BG, faceback); V_DrawTranslatedPatch (ST_FX, 0, &BG, faceback);
} }
@ -552,15 +539,15 @@ void ST_refreshBackground(void)
BOOL CheckCheatmode (void); BOOL CheckCheatmode (void);
// Respond to keyboard input events, // Respond to keyboard input events, intercept cheats.
// intercept cheats. // [RH] Cheats eat the last keypress used to trigger them
BOOL ST_Responder (event_t *ev) BOOL ST_Responder (event_t *ev)
{ {
BOOL eat = false;
int i; int i;
// Filter automap on/off. // Filter automap on/off.
if (ev->type == ev_keyup if (ev->type == ev_keyup && ((ev->data1 & 0xffff0000) == AM_MSGHEADER))
&& ((ev->data1 & 0xffff0000) == AM_MSGHEADER))
{ {
switch(ev->data1) switch(ev->data1)
{ {
@ -570,7 +557,6 @@ BOOL ST_Responder (event_t *ev)
break; break;
case AM_MSGEXITED: case AM_MSGEXITED:
// fprintf(stderr, "AM exited\n");
st_gamestate = FirstPersonState; st_gamestate = FirstPersonState;
break; break;
} }
@ -590,6 +576,7 @@ BOOL ST_Responder (event_t *ev)
Net_WriteByte (DEM_GENERICCHEAT); Net_WriteByte (DEM_GENERICCHEAT);
Net_WriteByte (CHT_IDDQD); Net_WriteByte (CHT_IDDQD);
eat = true;
} }
// 'fa' cheat for killer fucking arsenal // 'fa' cheat for killer fucking arsenal
@ -600,6 +587,7 @@ BOOL ST_Responder (event_t *ev)
Net_WriteByte (DEM_GENERICCHEAT); Net_WriteByte (DEM_GENERICCHEAT);
Net_WriteByte (CHT_IDFA); Net_WriteByte (CHT_IDFA);
eat = true;
} }
// 'kfa' cheat for key full ammo // 'kfa' cheat for key full ammo
@ -610,6 +598,7 @@ BOOL ST_Responder (event_t *ev)
Net_WriteByte (DEM_GENERICCHEAT); Net_WriteByte (DEM_GENERICCHEAT);
Net_WriteByte (CHT_IDKFA); Net_WriteByte (CHT_IDKFA);
eat = true;
} }
// Simplified, accepting both "noclip" and "idspispopd". // Simplified, accepting both "noclip" and "idspispopd".
@ -622,6 +611,7 @@ BOOL ST_Responder (event_t *ev)
Net_WriteByte (DEM_GENERICCHEAT); Net_WriteByte (DEM_GENERICCHEAT);
Net_WriteByte (CHT_NOCLIP); Net_WriteByte (CHT_NOCLIP);
eat = true;
} }
// 'behold?' power-up cheats // 'behold?' power-up cheats
for (i=0;i<6;i++) for (i=0;i<6;i++)
@ -633,6 +623,7 @@ BOOL ST_Responder (event_t *ev)
Net_WriteByte (DEM_GENERICCHEAT); Net_WriteByte (DEM_GENERICCHEAT);
Net_WriteByte ((byte)(CHT_BEHOLDV + i)); Net_WriteByte ((byte)(CHT_BEHOLDV + i));
eat = true;
} }
} }
@ -650,12 +641,14 @@ BOOL ST_Responder (event_t *ev)
{ {
Net_WriteByte (DEM_GENERICCHEAT); Net_WriteByte (DEM_GENERICCHEAT);
Net_WriteByte (CHT_CHAINSAW); Net_WriteByte (CHT_CHAINSAW);
eat = true;
} }
// 'mypos' for player position // 'mypos' for player position
else if (cht_CheckCheat(&cheat_mypos, (char)ev->data2)) else if (cht_CheckCheat(&cheat_mypos, (char)ev->data2))
{ {
AddCommandString ("toggle idmypos"); AddCommandString ("toggle idmypos");
eat = true;
} }
// 'clev' change-level cheat // 'clev' change-level cheat
@ -670,6 +663,7 @@ BOOL ST_Responder (event_t *ev)
argv[0] = "idclev"; argv[0] = "idclev";
argv[1] = buf; argv[1] = buf;
Cmd_idclev (plyr, 2, argv); Cmd_idclev (plyr, 2, argv);
eat = true;
} }
// 'idmus' change-music cheat // 'idmus' change-music cheat
@ -682,10 +676,11 @@ BOOL ST_Responder (event_t *ev)
sprintf (buf + 3, "idmus %s\n", buf); sprintf (buf + 3, "idmus %s\n", buf);
AddCommandString (buf + 3); AddCommandString (buf + 3);
eat = true;
} }
} }
return false; return eat;
} }
@ -918,8 +913,9 @@ void ST_updateWidgets(void)
{ {
keyboxes[i] = plyr->cards[i] ? i : -1; keyboxes[i] = plyr->cards[i] ? i : -1;
// [RH] show multiple keys per box, too
if (plyr->cards[i+3]) if (plyr->cards[i+3])
keyboxes[i] = i+3; keyboxes[i] = (keyboxes[i] == -1) ? i+3 : i+6;
} }
// refresh everything if this is him coming back to life // refresh everything if this is him coming back to life
@ -951,21 +947,66 @@ void ST_Ticker (void)
} }
static int st_palette = 0; static float st_palette[4];
// [RH] Amount of red flash for up to 114 damage points. Calculated by hand
// using a logarithmic scale and my trusty HP48G.
static byte damageToAlpha[114] = {
0, 8, 16, 23, 30, 36, 42, 47, 53, 58, 62, 67, 71, 75, 79,
83, 87, 90, 94, 97, 100, 103, 107, 109, 112, 115, 118, 120, 123, 125,
128, 130, 133, 135, 137, 139, 141, 143, 145, 147, 149, 151, 153, 155, 157,
159, 160, 162, 164, 165, 167, 169, 170, 172, 173, 175, 176, 178, 179, 181,
182, 183, 185, 186, 187, 189, 190, 191, 192, 194, 195, 196, 197, 198, 200,
201, 202, 203, 204, 205, 206, 207, 209, 210, 211, 212, 213, 214, 215, 216,
217, 218, 219, 220, 221, 221, 222, 223, 224, 225, 226, 227, 228, 229, 229,
230, 231, 232, 233, 234, 235, 235, 236, 237
};
/*
=============
SV_AddBlend
[RH] This is from Q2.
=============
*/
void SV_AddBlend (float r, float g, float b, float a, float *v_blend)
{
float a2, a3;
if (a <= 0)
return;
a2 = v_blend[3] + (1-v_blend[3])*a; // new total alpha
a3 = v_blend[3]/a2; // fraction of color from old
v_blend[0] = v_blend[0]*a3 + r*(1-a3);
v_blend[1] = v_blend[1]*a3 + g*(1-a3);
v_blend[2] = v_blend[2]*a3 + b*(1-a3);
v_blend[3] = a2;
}
void ST_doPaletteStuff (void) void ST_doPaletteStuff (void)
{ {
float blend[4];
int cnt;
int palette; blend[0] = blend[1] = blend[2] = blend[3] = 0;
int cnt;
int bzc;
cnt = plyr->damagecount << 1; SV_AddBlend (BaseBlendR / 255.0f, BaseBlendG / 255.0f, BaseBlendB / 255.0f, BaseBlendA, blend);
if (plyr->powers[pw_ironfeet] > 4*32 || plyr->powers[pw_ironfeet]&8)
SV_AddBlend (0.0f, 1.0f, 0.0f, 0.125f, blend);
if (plyr->bonuscount) {
cnt = plyr->bonuscount << 3;
SV_AddBlend (0.8431f, 0.7294f, 0.2706f, cnt > 128 ? 0.5f : cnt / 255.0f, blend);
}
if (plyr->damagecount < 114)
cnt = damageToAlpha[plyr->damagecount];
else
cnt = damageToAlpha[113];
if (plyr->powers[pw_strength]) if (plyr->powers[pw_strength])
{ {
// slowly fade the berzerk out // slowly fade the berzerk out
bzc = 128 - ((plyr->powers[pw_strength]>>3) & (~0x1f)); int bzc = 128 - ((plyr->powers[pw_strength]>>3) & (~0x1f));
if (bzc > cnt) if (bzc > cnt)
cnt = bzc; cnt = bzc;
@ -975,31 +1016,14 @@ void ST_doPaletteStuff (void)
{ {
if (cnt > 228) if (cnt > 228)
cnt = 228; cnt = 228;
else if (cnt < 28)
cnt = 28;
palette = MAKEARGB(cnt,255,0,0); SV_AddBlend (1.0f, 0.0f, 0.0f, cnt / 255.0f, blend);
} }
else if (plyr->bonuscount) if (memcmp (blend, st_palette, sizeof(blend))) {
{ memcpy (st_palette, blend, sizeof(blend));
cnt = plyr->bonuscount << 3; V_SetBlend ((int)(blend[0] * 255.0f), (int)(blend[1] * 255.0f),
(int)(blend[2] * 255.0f), (int)(blend[3] * 256.0f));
palette = MAKEARGB((cnt > 128) ? 128 : cnt,215,186,69);
}
else if ( plyr->powers[pw_ironfeet] > 4*32
|| plyr->powers[pw_ironfeet]&8)
{
palette = MAKEARGB(32,0,255,0);
}
else
palette = MAKEARGB(0,0,0,0);
if (palette != st_palette) {
st_palette = palette;
V_SetBlend (RPART(palette), GPART(palette), BPART(palette), APART(palette));
} }
} }
@ -1062,7 +1086,7 @@ void ST_diffDraw(void)
void ST_Drawer (BOOL fullscreen, BOOL refresh) void ST_Drawer (BOOL fullscreen, BOOL refresh)
{ {
st_statusbaron = (!fullscreen) || automapactive; st_statusbaron = (!fullscreen) || automapactive;
st_firsttime = st_firsttime || refresh; st_firsttime = st_firsttime || refresh;
@ -1081,22 +1105,26 @@ void ST_Drawer (BOOL fullscreen, BOOL refresh)
V_UnlockScreen (&stbarscreen); V_UnlockScreen (&stbarscreen);
// [RH] Hey, it's somewhere to put the idmypos stuff! // [RH] Hey, it's somewhere to put the idmypos stuff!
// Use displayplayer instead of consoleplayer
if (idmypos->value) if (idmypos->value)
Printf ("ang=%d;x,y=(%d,%d)\n", Printf ("ang=%d;x,y=(%d,%d)\n",
players[displayplayer].mo->angle/FRACUNIT, players[consoleplayer].camera->angle/FRACUNIT,
players[displayplayer].mo->x/FRACUNIT, players[consoleplayer].camera->x/FRACUNIT,
players[displayplayer].mo->y/FRACUNIT); players[consoleplayer].camera->y/FRACUNIT);
} }
void ST_loadGraphics(void) void ST_loadGraphics(void)
{ {
playerskin_t *skin;
int i; int i, j;
int j; int namespc;
int facenum; int facenum;
char namebuf[9]; char namebuf[9];
if (plyr)
skin = &skins[plyr->userinfo.skin];
else
skin = &skins[players[consoleplayer].userinfo.skin];
// Load the numbers, tall and short // Load the numbers, tall and short
for (i=0;i<10;i++) for (i=0;i<10;i++)
@ -1113,7 +1141,7 @@ void ST_loadGraphics(void)
tallpercent = (patch_t *) W_CacheLumpName("STTPRCNT", PU_STATIC); tallpercent = (patch_t *) W_CacheLumpName("STTPRCNT", PU_STATIC);
// key cards // key cards
for (i=0;i<NUMCARDS;i++) for (i=0;i<NUMCARDS+NUMCARDS/2;i++)
{ {
sprintf(namebuf, "STKEYS%d", i); sprintf(namebuf, "STKEYS%d", i);
keys[i] = (patch_t *) W_CacheLumpName(namebuf, PU_STATIC); keys[i] = (patch_t *) W_CacheLumpName(namebuf, PU_STATIC);
@ -1144,32 +1172,44 @@ void ST_loadGraphics(void)
// face states // face states
facenum = 0; facenum = 0;
for (i=0;i<ST_NUMPAINFACES;i++)
// [RH] Use face specified by "skin"
if (skin->face[0]) {
// The skin has its own face
strncpy (namebuf, skin->face, 3);
namespc = skin->namespc;
} else {
// The skin doesn't have its own face; use the normal one
namebuf[0] = 'S'; namebuf[1] = 'T'; namebuf[2] = 'F';
namespc = ns_global;
}
for (i = 0; i < ST_NUMPAINFACES; i++)
{ {
for (j=0;j<ST_NUMSTRAIGHTFACES;j++) for (j = 0; j < ST_NUMSTRAIGHTFACES; j++)
{ {
sprintf(namebuf, "STFST%d%d", i, j); sprintf(namebuf+3, "ST%d%d", i, j);
faces[facenum++] = W_CacheLumpName(namebuf, PU_STATIC); faces[facenum++] = W_CacheLumpName(namebuf, PU_STATIC);
} }
sprintf(namebuf, "STFTR%d0", i); // turn right sprintf(namebuf+3, "TR%d0", i); // turn right
faces[facenum++] = W_CacheLumpName(namebuf, PU_STATIC); faces[facenum++] = W_CacheLumpNum ((W_CheckNumForName)(namebuf, namespc), PU_STATIC);
sprintf(namebuf, "STFTL%d0", i); // turn left sprintf(namebuf+3, "TL%d0", i); // turn left
faces[facenum++] = W_CacheLumpName(namebuf, PU_STATIC); faces[facenum++] = W_CacheLumpNum ((W_CheckNumForName)(namebuf, namespc), PU_STATIC);
sprintf(namebuf, "STFOUCH%d", i); // ouch! sprintf(namebuf+3, "OUCH%d", i); // ouch!
faces[facenum++] = W_CacheLumpName(namebuf, PU_STATIC); faces[facenum++] = W_CacheLumpNum ((W_CheckNumForName)(namebuf, namespc), PU_STATIC);
sprintf(namebuf, "STFEVL%d", i); // evil grin ;) sprintf(namebuf+3, "EVL%d", i); // evil grin ;)
faces[facenum++] = W_CacheLumpName(namebuf, PU_STATIC); faces[facenum++] = W_CacheLumpNum ((W_CheckNumForName)(namebuf, namespc), PU_STATIC);
sprintf(namebuf, "STFKILL%d", i); // pissed off sprintf(namebuf+3, "KILL%d", i); // pissed off
faces[facenum++] = W_CacheLumpName(namebuf, PU_STATIC); faces[facenum++] = W_CacheLumpNum ((W_CheckNumForName)(namebuf, namespc), PU_STATIC);
} }
faces[facenum++] = W_CacheLumpName("STFGOD0", PU_STATIC); strcpy (namebuf+3, "GOD0");
faces[facenum++] = W_CacheLumpName("STFDEAD0", PU_STATIC); faces[facenum++] = W_CacheLumpNum ((W_CheckNumForName)(namebuf, namespc), PU_STATIC);
strcpy (namebuf+3, "DEAD0");
faces[facenum++] = W_CacheLumpNum ((W_CheckNumForName)(namebuf, namespc), PU_STATIC);
} }
void ST_loadData(void) void ST_loadData(void)
{ {
lu_palette = W_GetNumForName ("PLAYPAL");
ST_loadGraphics(); ST_loadGraphics();
} }
@ -1195,7 +1235,7 @@ void ST_unloadGraphics(void)
Z_ChangeTag(arms[i][0], PU_CACHE); Z_ChangeTag(arms[i][0], PU_CACHE);
// unload the key cards // unload the key cards
for (i=0;i<NUMCARDS;i++) for (i=0;i<NUMCARDS+NUMCARDS/2;i++)
Z_ChangeTag(keys[i], PU_CACHE); Z_ChangeTag(keys[i], PU_CACHE);
Z_ChangeTag(sbar, PU_CACHE); Z_ChangeTag(sbar, PU_CACHE);
@ -1222,7 +1262,10 @@ void ST_initData(void)
int i; int i;
st_firsttime = true; st_firsttime = true;
plyr = &players[displayplayer]; // [RH] Not consoleplayer if (players[consoleplayer].camera && players[consoleplayer].camera->player)
plyr = players[consoleplayer].camera->player; // [RH] use camera
else
plyr = &players[consoleplayer];
st_clock = 0; st_clock = 0;
st_chatstate = StartChatState; st_chatstate = StartChatState;
@ -1233,7 +1276,7 @@ void ST_initData(void)
st_cursoron = false; st_cursoron = false;
st_faceindex = 0; st_faceindex = 0;
st_palette = -1; memset (st_palette, 255, sizeof(st_palette));
st_oldhealth = -1; st_oldhealth = -1;

View file

@ -58,6 +58,9 @@ void ST_Init (void);
// Draw the HUD (only if old status bar is not drawn) // Draw the HUD (only if old status bar is not drawn)
void ST_newDraw (void); void ST_newDraw (void);
// Called on init and whenever player's skin changes
void ST_loadGraphics (void);
// States for status bar code. // States for status bar code.
typedef enum typedef enum
@ -80,6 +83,9 @@ typedef enum
BOOL ST_Responder(event_t* ev); BOOL ST_Responder(event_t* ev);
// [RH] Base blending values (for e.g. underwater)
extern int BaseBlendR, BaseBlendG, BaseBlendB;
extern float BaseBlendA;
#endif #endif

View file

@ -25,6 +25,12 @@
#include <stdio.h> #include <stdio.h>
#include "minilzo.h"
// [RH] Output buffer size for LZO compression.
// Extra space in case uncompressable.
#define OUT_LEN(a) ((a) + (a) / 64 + 16 + 3)
#include "m_alloc.h" #include "m_alloc.h"
#include "i_system.h" #include "i_system.h"
@ -38,6 +44,7 @@
#include "doomdata.h" #include "doomdata.h"
#include "doomstat.h" #include "doomstat.h"
#include "c_consol.h"
#include "hu_stuff.h" #include "hu_stuff.h"
#include "m_argv.h" #include "m_argv.h"
@ -57,13 +64,17 @@
extern void STACK_ARGS DimScreenPLoop (byte *colormap, byte *screen, int width, int modulo, int height); extern void STACK_ARGS DimScreenPLoop (byte *colormap, byte *screen, int width, int modulo, int height);
extern char *IdStrings[22];
extern int DisplayID;
// [RH] Screens are no longer mere byte arrays. // [RH] Screens are no longer mere byte arrays.
screen_t screens[2]; screen_t screens[2];
int dirtybox[4]; int dirtybox[4];
cvar_t *vid_defwidth, *vid_defheight, *vid_defbpp; cvar_t *vid_defwidth, *vid_defheight, *vid_defid;
cvar_t *dimamount, *dimcolor; cvar_t *dimamount, *dimcolor;
byte *TransTable; byte *TransTable;
@ -74,7 +85,7 @@ palette_t *DefaultPalette;
// [RH] Set true when vid_setmode command has been executed // [RH] Set true when vid_setmode command has been executed
BOOL setmodeneeded = false; BOOL setmodeneeded = false;
// [RH] Resolution to change to when setmodeneeded is true // [RH] Resolution to change to when setmodeneeded is true
int NewWidth, NewHeight, NewBpp; int NewWidth, NewHeight, NewID;
// //
@ -485,9 +496,10 @@ void V_Blit (screen_t *src, int srcx, int srcy, int srcwidth, int srcheight,
// //
// V_SetResolution // V_SetResolution
// //
BOOL V_DoModeSetup (int width, int height, int bpp) BOOL V_DoModeSetup (int width, int height, int id)
{ {
int i; int i;
int bpp;
CleanXfac = width / 320; CleanXfac = width / 320;
CleanYfac = height / 200; CleanYfac = height / 200;
@ -499,8 +511,8 @@ BOOL V_DoModeSetup (int width, int height, int bpp)
if (screens[i].impdata) if (screens[i].impdata)
V_FreeScreen (&screens[i]); V_FreeScreen (&screens[i]);
I_SetMode (width, height, bpp); I_SetMode (width, height, id);
bpp = (bpp == 8) ? bpp : 32; bpp = (id == 1010) ? 8 : 32;
for (i = 0; i < 2; i++) { for (i = 0; i < 2; i++) {
if (!I_AllocateScreen (&screens[i], width, height, bpp)) if (!I_AllocateScreen (&screens[i], width, height, bpp))
@ -517,98 +529,127 @@ BOOL V_DoModeSetup (int width, int height, int bpp)
return true; return true;
} }
BOOL V_SetResolution (int width, int height, int Bpp) BOOL V_SetResolution (int width, int height, int id)
{ {
int oldwidth, oldheight; int oldwidth, oldheight;
int oldBpp; int oldID;
if (screens[0].impdata) { if (screens[0].impdata) {
oldwidth = screens[0].width; oldwidth = screens[0].width;
oldheight = screens[0].height; oldheight = screens[0].height;
oldBpp = screens[0].Bpp * 8; oldID = DisplayID;
} else { } else {
// Harmless if screens[0] wasn't allocated // Harmless if screens[0] wasn't allocated
oldwidth = width; oldwidth = width;
oldheight = height; oldheight = height;
oldBpp = Bpp; oldID = id;
} }
if (!I_CheckResolution (width, height, Bpp)) { // Try specified resolution if (!I_CheckResolution (width, height, id)) { // Try specified resolution
if (!I_CheckResolution (oldwidth, oldheight, oldBpp)) { // Try previous resolution (if any) if (!I_CheckResolution (oldwidth, oldheight, oldID)) { // Try previous resolution (if any)
if (!I_CheckResolution (320, 200, 8)) { // Try "standard" resolution if (!I_CheckResolution (320, 200, 1010)) { // Try "standard" resolution
if (!I_CheckResolution (640, 480, 8)) { // Try a resolution that *should* be available if (!I_CheckResolution (640, 480, 1010)) { // Try a resolution that *should* be available
return false; return false;
} else { } else {
width = 640; width = 640;
height = 480; height = 480;
Bpp = 8; id = 1010;
} }
} else { } else {
width = 320; width = 320;
height = 200; height = 200;
Bpp = 8; id = 1010;
} }
} else { } else {
width = oldwidth; width = oldwidth;
height = oldheight; height = oldheight;
Bpp = oldBpp; id = oldID;
} }
} }
return V_DoModeSetup (width, height, Bpp); return V_DoModeSetup (width, height, id);
} }
void Cmd_Vid_SetMode (void *plyr, int argc, char **argv) void Cmd_Vid_SetMode (void *plyr, int argc, char **argv)
{ {
BOOL goodmode = false; BOOL goodmode = false;
int width = 0, height = screens[0].height, bpp = screens[0].Bpp * 8; int width = 0, height = screens[0].height;
int id = DisplayID;
if (argc > 1) { if (argc > 1) {
width = atoi (argv[1]); width = atoi (argv[1]);
if (argc > 2) { if (argc > 2) {
height = atoi (argv[2]); height = atoi (argv[2]);
if (argc > 3) if (argc > 3) {
bpp = atoi (argv[3]); int i;
for (i = 0; i < 22; i++)
if (!stricmp (IdStrings[i], argv[3]))
break;
if (i < 22)
id = 1000 + i;
}
} }
} }
if (width) { if (width) {
if (I_CheckResolution (width, height, bpp)) if (I_CheckResolution (width, height, id))
goodmode = true; goodmode = true;
} }
if (goodmode) { if (goodmode) {
// The actual change of resolution will take place // The actual change of resolution will take place
// near the beginning of D_Display(). // near the beginning of D_Display().
setmodeneeded = true; if (gamestate != GS_STARTUP) {
NewWidth = width; setmodeneeded = true;
NewHeight = height; NewWidth = width;
NewBpp = bpp; NewHeight = height;
NewID = id;
}
} else if (width) { } else if (width) {
Printf ("Unknown resolution %d x %d x %d\n", width, height, bpp); Printf ("Unknown resolution %d x %d (%s)\n", width, height, IdStrings[id-1000]);
} else { } else {
Printf ("Usage: vid_setmode <width> <height> <bpp>\n"); Printf ("Usage: vid_setmode <width> <height> <mode>\n");
} }
} }
// //
// V_Init // V_Init
// //
extern char *IdStrings[22];
extern int DisplayID;
static int IdNameToId (char *name)
{
int i;
for (i = 0; i < 22; i++) {
if (!stricmp (IdStrings[0], name))
break;
}
if (i < 22)
return i + 1000;
else
return 1010; // INDEX8
}
void V_Init (void) void V_Init (void)
{ {
static const char tag[] = "LZO-Compressed ZDoom Translucency Cache File v01";
int i; int i;
int width, height, bpp; int width, height, id;
// [RH] Setup gamma callback // [RH] Setup gamma callback
gammalevel->u.callback = GammaCallback; gammalevel->u.callback = GammaCallback;
GammaCallback (gammalevel); GammaCallback (gammalevel);
// [RH] Initialize palette subsystem // [RH] Initialize palette subsystem
Printf ("InitPalettes\n");
if (!(DefaultPalette = InitPalettes ("PLAYPAL"))) if (!(DefaultPalette = InitPalettes ("PLAYPAL")))
I_FatalError ("Could not start palette subsystem"); I_FatalError ("Could not initialize palette");
width = height = bpp = 0; width = height = id = 0;
if ( (i = M_CheckParm ("-width")) ) if ( (i = M_CheckParm ("-width")) )
if (i < myargc - 1) if (i < myargc - 1)
@ -616,11 +657,11 @@ void V_Init (void)
if ( (i = M_CheckParm ("-height")) ) if ( (i = M_CheckParm ("-height")) )
if (i < myargc - 1) if (i < myargc - 1)
height = atoi (myargv[i + 1]); height = atoi (myargv[i + 1]);
if ( (i = M_CheckParm ("-bpp")) ) if ( (i = M_CheckParm ("-mode")) )
if (i < myargc - 1) if (i < myargc - 1)
bpp = atoi (myargv[i + 1]); id = IdNameToId (myargv[i + 1]);
if (width == 0) { if (width == 0) {
if (height == 0) { if (height == 0) {
@ -633,19 +674,20 @@ void V_Init (void)
height = (width * 6) / 8; height = (width * 6) / 8;
} }
if (bpp == 0) { if (id == 0) {
bpp = (int)(vid_defbpp->value); id = IdNameToId (vid_defid->string);
} }
if (!V_SetResolution (width, height, bpp)) { if (!V_SetResolution (width, height, id)) {
I_FatalError ("Could not set resolution to %d x %d x %d", width, height, bpp); I_FatalError ("Could not set resolution to %d x %d (%s)", width, height, IdStrings[id-1000]);
} else { } else {
Printf ("Resolution: %d x %d x %d\n", screens[0].width, screens[0].height, screens[0].Bpp * 8); Printf ("Resolution: %d x %d (%s)\n", screens[0].width, screens[0].height, IdStrings[id-1000]);
} }
V_InitConChars (0xf7); V_InitConChars (0xf7);
C_InitConsole (screens[0].width, screens[0].height, true);
{ {/*
static int palpoop[256]; static int palpoop[256];
byte *palette = W_CacheLumpName ("PLAYPAL", PU_CACHE); byte *palette = W_CacheLumpName ("PLAYPAL", PU_CACHE);
int i; int i;
@ -656,15 +698,14 @@ void V_Init (void)
(palette[2]); (palette[2]);
palette += 3; palette += 3;
} }
*/
V_Palette = palpoop; V_Palette = DefaultPalette->colors;
} }
if (!M_CheckParm ("-notrans")) { if (!M_CheckParm ("-notrans")) {
char cachename[256]; char cachename[256];
byte *palette; byte *palette;
BOOL isCached = false; FILE *cache;
FILE *cached;
int i; int i;
// Align TransTable on a 64k boundary // Align TransTable on a 64k boundary
@ -674,6 +715,7 @@ void V_Init (void)
i = M_CheckParm("-transfile"); i = M_CheckParm("-transfile");
if (i && i < myargc - 1) { if (i && i < myargc - 1) {
strcpy (cachename, myargv[i+1]); strcpy (cachename, myargv[i+1]);
FixPathSeperator (cachename);
DefaultExtension (cachename, ".tch"); DefaultExtension (cachename, ".tch");
} else { } else {
sprintf (cachename, "%stranstab.tch", progdir); sprintf (cachename, "%stranstab.tch", progdir);
@ -681,36 +723,109 @@ void V_Init (void)
palette = W_CacheLumpName ("PLAYPAL", PU_CACHE); palette = W_CacheLumpName ("PLAYPAL", PU_CACHE);
{ // Check for cached translucency table { // Check for cached translucency table
byte cachepal[768]; byte *cachemem;
byte *out;
int newlen;
int cachelen;
int insidelen;
int r;
cached = fopen (cachename, "rb"); cache = fopen (cachename, "rb");
if (cached) { if (cache) {
if (fread (cachepal, 1, 768, cached) == 768) { fseek (cache, 0, SEEK_END);
if (memcmp (cachepal, palette, 768)) { cachelen = ftell (cache);
Printf ("Translucency cache was generated with a different palette\n"); fseek (cache, 0, SEEK_SET);
} else {
isCached = (fread (TransTable, 1, 65536*3, cached) == 65536*3); if (cachelen <= strlen(tag) + sizeof(int)) {
} fclose (cache);
cache = NULL;
goto maketable;
} }
if (!isCached) {
Printf ("Bad translucency cache file\n"); cachemem = Z_Malloc (cachelen, PU_STATIC, 0);
if (fread (cachemem, 1, cachelen, cache) != cachelen) {
fclose (cache);
cache = NULL;
Printf ("Trouble reading tranlucency cache\n");
goto maketable;
} }
fclose (cache);
if (strncmp (tag, cachemem, strlen(tag)) != 0) {
Printf ("Regenerating old translucency cache\n");
cache = NULL;
goto maketable;
}
// So far, so good. Try expanding the cached data.
memcpy (&insidelen, cachemem + strlen(tag), sizeof(int));
if (insidelen != cachelen - strlen(tag) - sizeof(int)) {
Printf ("Translucency cache wrong size\n");
cache = NULL;
goto maketable;
}
out = Z_Malloc (65536*3+768, PU_STATIC, 0);
r = lzo1x_decompress (cachemem + strlen(tag) + sizeof(int),
insidelen, out, &newlen, NULL);
if (r != LZO_E_OK || newlen != 65536*3+768) {
Printf ("Bad translucency cache\n");
cache = NULL;
Z_Free (out);
goto maketable;
}
// Check to make sure if the cache was generated from the
// current PLAYPAL. If not, we need to generate it, but
// don't bother replacing this one.
if (memcmp (out, palette, 768)) {
Printf ("Translucency cache was generated with a different palette\n");
Z_Free (out);
goto maketable;
}
// Everything's good. Use the cached data.
memcpy (TransTable, out+768, 65536*3);
TransTable -= 65536;
Z_Free (out);
return;
} }
} }
if (!isCached) { maketable:
Printf ("Creating translucency tables\n"); Printf ("Creating translucency tables\n");
BuildTransTable (TransTable, DefaultPalette->basecolors); BuildTransTable (TransTable, DefaultPalette->basecolors);
if (!cached) { if (!cache) {
cached = fopen (cachename, "wb"); byte *out, *wrkmem, *in;
if (cached) { int outlen, r;
fwrite (palette, 1, 768, cached);
fwrite (TransTable, 1, 65536*3, cached); wrkmem = Z_Malloc (LZO1X_1_MEM_COMPRESS, PU_STATIC, 0);
in = Z_Malloc (768 + 65536*3, PU_STATIC, 0);
out = Z_Malloc (768 + 65536*3, PU_STATIC, 0);
strncpy (in, tag, strlen (tag));
memcpy (in, palette, 768);
memcpy (in+768, TransTable, 65536*3);
r = lzo1x_1_compress (in, 768+65536*3, out, &outlen, wrkmem);
Z_Free (wrkmem);
Z_Free (in);
if (r == LZO_E_OK) {
cache = fopen (cachename, "wb");
if (cache) {
fwrite (tag, 1, strlen(tag), cache);
fwrite (&outlen, sizeof(outlen), 1, cache);
fwrite (out, 1, outlen, cache);
fclose (cache);
} }
} }
} }
if (cached)
fclose (cached);
TransTable -= 65536; TransTable -= 65536;
} }

View file

@ -18,6 +18,7 @@
// //
// DESCRIPTION: // DESCRIPTION:
// Handles WAD file header, directory, lump I/O. // Handles WAD file header, directory, lump I/O.
// [RH] Changed to use buffered I/O (fread, etc)
// //
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -57,14 +58,19 @@ int numlumps;
void** lumpcache; void** lumpcache;
int W_filelength (int handle) int W_filelength (FILE *handle)
{ {
struct stat fileinfo; int len;
if (fstat (handle,&fileinfo) == -1) if (fseek (handle, 0, SEEK_END))
I_Error ("Error fstating"); I_Error ("Error fseeking");
return fileinfo.st_size; len = ftell (handle);
if (fseek (handle, 0, SEEK_SET))
I_Error ("Error fseeking");
return len;
} }
// [RH] Copy up to 8 chars, upper-casing them in the process // [RH] Copy up to 8 chars, upper-casing them in the process
@ -102,7 +108,7 @@ void W_AddFile (char *filename)
wadinfo_t header; wadinfo_t header;
lumpinfo_t* lump_p; lumpinfo_t* lump_p;
unsigned i; unsigned i;
int handle; FILE *handle;
int length; int length;
int startlump; int startlump;
filelump_t* fileinfo, *fileinfo2free; filelump_t* fileinfo, *fileinfo2free;
@ -116,17 +122,17 @@ void W_AddFile (char *filename)
// open the file and add to directory // open the file and add to directory
if ((handle = open (name, O_RDONLY | O_BINARY)) == -1) if ((handle = fopen (name, "rb")) == NULL)
{ {
Printf (" couldn't open %s\n",filename); Printf (" couldn't open %s\n",filename);
return; return;
} }
Printf (" adding %s",filename); Printf (" adding %s", name);
startlump = numlumps; startlump = numlumps;
// [RH] Determine if file is a WAD based on its signature, not its name. // [RH] Determine if file is a WAD based on its signature, not its name.
read (handle, &header, sizeof(header)); fread (&header, sizeof(header), 1, handle);
if (header.identification == IWAD_ID || if (header.identification == IWAD_ID ||
header.identification == PWAD_ID) { header.identification == PWAD_ID) {
@ -136,8 +142,8 @@ void W_AddFile (char *filename)
header.infotableofs = LONG(header.infotableofs); header.infotableofs = LONG(header.infotableofs);
length = header.numlumps * sizeof(filelump_t); length = header.numlumps * sizeof(filelump_t);
fileinfo = fileinfo2free = Z_Malloc (length, PU_STATIC, 0); fileinfo = fileinfo2free = Z_Malloc (length, PU_STATIC, 0);
lseek (handle, header.infotableofs, SEEK_SET); fseek (handle, header.infotableofs, SEEK_SET);
read (handle, fileinfo, length); fread (fileinfo, 1, length, handle);
numlumps += header.numlumps; numlumps += header.numlumps;
Printf (" (%d lumps)", header.numlumps); Printf (" (%d lumps)", header.numlumps);
} else { } else {
@ -188,7 +194,7 @@ void W_AddFile (char *filename)
// The name searcher looks backwards, so a later file // The name searcher looks backwards, so a later file
// does override all earlier ones. // does override all earlier ones.
// //
void W_InitMultipleFiles (char** filenames) void W_InitMultipleFiles (wadlist_t **filenames)
{ {
int i; int i;
@ -198,11 +204,16 @@ void W_InitMultipleFiles (char** filenames)
// will be realloced as lumps are added // will be realloced as lumps are added
lumpinfo = NULL; // [RH] Start out as NULL lumpinfo = NULL; // [RH] Start out as NULL
for ( ; *filenames ; filenames++) while (*filenames) {
W_AddFile (*filenames); wadlist_t *next = (*filenames)->next;
W_AddFile ((*filenames)->name);
Z_Free (*filenames);
*filenames = next;
}
if (!numlumps) if (!numlumps)
I_Error ("W_InitFiles: no files found"); I_FatalError ("W_InitFiles: no files found");
// [RH] Set namespace markers to global for everything // [RH] Set namespace markers to global for everything
for (i = 0; i < numlumps; i++) for (i = 0; i < numlumps; i++)
@ -232,13 +243,13 @@ void W_InitMultipleFiles (char** filenames)
// W_InitFile // W_InitFile
// Just initialize from a single file. // Just initialize from a single file.
// //
void W_InitFile (char* filename) void W_InitFile (char *filename)
{ {
char *names[2]; wadlist_t *names = Z_Malloc (sizeof(*names)+strlen(filename), PU_STATIC, 0);
names[0] = filename; names->next = NULL;
names[1] = NULL; strcpy (names->name, filename);
W_InitMultipleFiles (names); W_InitMultipleFiles (&names);
} }
@ -328,8 +339,8 @@ void W_ReadLump (int lump, void *dest)
l = lumpinfo + lump; l = lumpinfo + lump;
lseek (l->handle, l->position, SEEK_SET); fseek (l->handle, l->position, SEEK_SET);
c = read (l->handle, dest, l->size); c = fread (dest, 1, l->size, l->handle);
if (c < l->size) if (c < l->size)
I_Error ("W_ReadLump: only read %i of %i on lump %i", I_Error ("W_ReadLump: only read %i of %i on lump %i",
@ -348,7 +359,7 @@ void *W_CacheLumpNum (int lump, int tag)
int lumplen; int lumplen;
if ((unsigned)lump >= numlumps) if ((unsigned)lump >= numlumps)
I_Error ("W_CacheLumpNum: %i >= numlumps",lump); I_Error ("W_CacheLumpNum: %u >= numlumps",lump);
if (!lumpcache[lump]) if (!lumpcache[lump])
{ {
@ -463,8 +474,8 @@ void W_MergeLumps (const char *start, const char *end, int space)
if (!newlumps) { if (!newlumps) {
newlumps++; newlumps++;
strncpy (newlumpinfos[0].name, ustart, 8); strncpy (newlumpinfos[0].name, ustart, 8);
newlumpinfos[0].handle = newlumpinfos[0].handle = NULL;
newlumpinfos[0].position = newlumpinfos[0].position =
newlumpinfos[0].size = 0; newlumpinfos[0].size = 0;
newlumpinfos[0].namespc = ns_global; newlumpinfos[0].namespc = ns_global;
} }
@ -492,8 +503,8 @@ void W_MergeLumps (const char *start, const char *end, int space)
// Only create an end marker if there was one in the original list. // Only create an end marker if there was one in the original list.
if (haveEndMarker) { if (haveEndMarker) {
strncpy (newlumpinfos[newlumps].name, uend, 8); strncpy (newlumpinfos[newlumps].name, uend, 8);
newlumpinfos[newlumps].handle = newlumpinfos[newlumps].handle = NULL;
newlumpinfos[newlumps].position = newlumpinfos[newlumps].position =
newlumpinfos[newlumps].size = 0; newlumpinfos[newlumps].size = 0;
newlumpinfos[newlumps].namespc = ns_global; newlumpinfos[newlumps].namespc = ns_global;
newlumps++; newlumps++;
@ -623,4 +634,29 @@ BOOL W_CheckLumpName (int lump, const char *name)
return false; return false;
return !strnicmp (lumpinfo[lump].name, name, 8); return !strnicmp (lumpinfo[lump].name, name, 8);
}
// [RH] Copies the lump name to to using uppercopy
void W_GetLumpName (char *to, int lump)
{
if (lump >= numlumps)
*to = 0;
else
uppercopy (to, lumpinfo[lump].name);
}
// [RH] Returns file ptr for specified lump
FILE *W_GetLumpFile (int lump)
{
if (lump >= numlumps)
return NULL;
else
return lumpinfo[lump].handle;
}
// [RH] Put a lump in a certain namespace
void W_SetLumpNamespace (int lump, int nmspace)
{
if (lump < numlumps)
lumpinfo[lump].namespc = nmspace;
} }

View file

@ -42,9 +42,6 @@
#include "doomstat.h" #include "doomstat.h"
// Data.
#include "sounds.h"
// Needs access to LFB. // Needs access to LFB.
#include "v_video.h" #include "v_video.h"
@ -976,7 +973,7 @@ void WI_updateDeathmatchStats(void)
} }
S_StartSound(ORIGIN_AMBIENT, sfx_barexp); S_StartSound (ORIGIN_AMBIENT, "weapons/rocklx", 60);
dm_state = 4; dm_state = 4;
} }
@ -984,7 +981,7 @@ void WI_updateDeathmatchStats(void)
if (dm_state == 2) if (dm_state == 2)
{ {
if (!(bcnt&3)) if (!(bcnt&3))
S_StartSound(ORIGIN_AMBIENT, sfx_pistol); S_StartSound (ORIGIN_AMBIENT, "weapons/pistol", 64);
stillticking = false; stillticking = false;
@ -1023,7 +1020,7 @@ void WI_updateDeathmatchStats(void)
} }
if (!stillticking) if (!stillticking)
{ {
S_StartSound(ORIGIN_AMBIENT, sfx_barexp); S_StartSound(ORIGIN_AMBIENT, "weapons/rocklx", 60);
dm_state++; dm_state++;
} }
@ -1032,7 +1029,7 @@ void WI_updateDeathmatchStats(void)
{ {
if (acceleratestage) if (acceleratestage)
{ {
S_StartSound(ORIGIN_AMBIENT, sfx_slop); S_StartSound(ORIGIN_AMBIENT, "players/male/gibbed", 78);
if ( gamemode == commercial) if ( gamemode == commercial)
WI_initNoState(); WI_initNoState();
@ -1206,16 +1203,16 @@ void WI_updateNetgameStats(void)
cnt_secret[i] = plrs[i].ssecret; cnt_secret[i] = plrs[i].ssecret;
if (dofrags) if (dofrags)
cnt_frags[i] = WI_fragSum(i); cnt_frags[i] = WI_fragSum (i);
} }
S_StartSound(ORIGIN_AMBIENT, sfx_barexp); S_StartSound (ORIGIN_AMBIENT, "weapons/rocklx", 60);
ng_state = 10; ng_state = 10;
} }
if (ng_state == 2) if (ng_state == 2)
{ {
if (!(bcnt&3)) if (!(bcnt&3))
S_StartSound(ORIGIN_AMBIENT, sfx_pistol); S_StartSound (ORIGIN_AMBIENT, "weapons/pistol", 64);
stillticking = false; stillticking = false;
@ -1234,14 +1231,14 @@ void WI_updateNetgameStats(void)
if (!stillticking) if (!stillticking)
{ {
S_StartSound(ORIGIN_AMBIENT, sfx_barexp); S_StartSound (ORIGIN_AMBIENT, "weapons/rocklx", 60);
ng_state++; ng_state++;
} }
} }
else if (ng_state == 4) else if (ng_state == 4)
{ {
if (!(bcnt&3)) if (!(bcnt&3))
S_StartSound(ORIGIN_AMBIENT, sfx_pistol); S_StartSound (ORIGIN_AMBIENT, "weapons/pistol", 64);
stillticking = false; stillticking = false;
@ -1258,14 +1255,14 @@ void WI_updateNetgameStats(void)
} }
if (!stillticking) if (!stillticking)
{ {
S_StartSound(ORIGIN_AMBIENT, sfx_barexp); S_StartSound (ORIGIN_AMBIENT, "weapons/rocklx", 60);
ng_state++; ng_state++;
} }
} }
else if (ng_state == 6) else if (ng_state == 6)
{ {
if (!(bcnt&3)) if (!(bcnt&3))
S_StartSound(ORIGIN_AMBIENT, sfx_pistol); S_StartSound (ORIGIN_AMBIENT, "weapons/pistol", 64);
stillticking = false; stillticking = false;
@ -1284,14 +1281,14 @@ void WI_updateNetgameStats(void)
if (!stillticking) if (!stillticking)
{ {
S_StartSound(ORIGIN_AMBIENT, sfx_barexp); S_StartSound (ORIGIN_AMBIENT, "weapons/rocklx", 60);
ng_state += 1 + 2*!dofrags; ng_state += 1 + 2*!dofrags;
} }
} }
else if (ng_state == 8) else if (ng_state == 8)
{ {
if (!(bcnt&3)) if (!(bcnt&3))
S_StartSound(ORIGIN_AMBIENT, sfx_pistol); S_StartSound (ORIGIN_AMBIENT, "weapons/pistol", 64);
stillticking = false; stillticking = false;
@ -1310,7 +1307,7 @@ void WI_updateNetgameStats(void)
if (!stillticking) if (!stillticking)
{ {
S_StartSound(ORIGIN_AMBIENT, sfx_pldeth); S_StartSound (ORIGIN_AMBIENT, "player/male/death1", 32);
ng_state++; ng_state++;
} }
} }
@ -1318,7 +1315,7 @@ void WI_updateNetgameStats(void)
{ {
if (acceleratestage) if (acceleratestage)
{ {
S_StartSound(ORIGIN_AMBIENT, sfx_sgcock); S_StartSound (ORIGIN_AMBIENT, "weapons/shotgr", 64);
if ( gamemode == commercial ) if ( gamemode == commercial )
WI_initNoState(); WI_initNoState();
else else
@ -1425,7 +1422,7 @@ void WI_updateStats(void)
cnt_secret[0] = plrs[me].ssecret; cnt_secret[0] = plrs[me].ssecret;
cnt_time = plrs[me].stime / TICRATE; cnt_time = plrs[me].stime / TICRATE;
cnt_par = wbs->partime / TICRATE; cnt_par = wbs->partime / TICRATE;
S_StartSound(ORIGIN_AMBIENT, sfx_barexp); S_StartSound (ORIGIN_AMBIENT, "weapons/rocklx", 60);
sp_state = 10; sp_state = 10;
} }
@ -1434,12 +1431,12 @@ void WI_updateStats(void)
cnt_kills[0] += 2; cnt_kills[0] += 2;
if (!(bcnt&3)) if (!(bcnt&3))
S_StartSound(ORIGIN_AMBIENT, sfx_pistol); S_StartSound (ORIGIN_AMBIENT, "weapons/pistol", 64);
if (cnt_kills[0] >= plrs[me].skills) if (cnt_kills[0] >= plrs[me].skills)
{ {
cnt_kills[0] = plrs[me].skills; cnt_kills[0] = plrs[me].skills;
S_StartSound(ORIGIN_AMBIENT, sfx_barexp); S_StartSound (ORIGIN_AMBIENT, "weapons/rocklx", 60);
sp_state++; sp_state++;
} }
} }
@ -1448,12 +1445,12 @@ void WI_updateStats(void)
cnt_items[0] += 2; cnt_items[0] += 2;
if (!(bcnt&3)) if (!(bcnt&3))
S_StartSound(ORIGIN_AMBIENT, sfx_pistol); S_StartSound (ORIGIN_AMBIENT, "weapons/pistol", 64);
if (cnt_items[0] >= plrs[me].sitems) if (cnt_items[0] >= plrs[me].sitems)
{ {
cnt_items[0] = plrs[me].sitems; cnt_items[0] = plrs[me].sitems;
S_StartSound(ORIGIN_AMBIENT, sfx_barexp); S_StartSound (ORIGIN_AMBIENT, "weapons/rocklx", 60);
sp_state++; sp_state++;
} }
} }
@ -1462,12 +1459,12 @@ void WI_updateStats(void)
cnt_secret[0] += 2; cnt_secret[0] += 2;
if (!(bcnt&3)) if (!(bcnt&3))
S_StartSound(ORIGIN_AMBIENT, sfx_pistol); S_StartSound (ORIGIN_AMBIENT, "weapons/pistol", 64);
if (cnt_secret[0] >= plrs[me].ssecret) if (cnt_secret[0] >= plrs[me].ssecret)
{ {
cnt_secret[0] = plrs[me].ssecret; cnt_secret[0] = plrs[me].ssecret;
S_StartSound(ORIGIN_AMBIENT, sfx_barexp); S_StartSound (ORIGIN_AMBIENT, "weapons/rocklx", 60);
sp_state++; sp_state++;
} }
} }
@ -1475,7 +1472,7 @@ void WI_updateStats(void)
else if (sp_state == 8) else if (sp_state == 8)
{ {
if (!(bcnt&3)) if (!(bcnt&3))
S_StartSound(ORIGIN_AMBIENT, sfx_pistol); S_StartSound (ORIGIN_AMBIENT, "weapons/pistol", 64);
cnt_time += 3; cnt_time += 3;
@ -1490,7 +1487,7 @@ void WI_updateStats(void)
if (cnt_time >= plrs[me].stime / TICRATE) if (cnt_time >= plrs[me].stime / TICRATE)
{ {
S_StartSound(ORIGIN_AMBIENT, sfx_barexp); S_StartSound (ORIGIN_AMBIENT, "weapons/rocklx", 60);
sp_state++; sp_state++;
} }
} }
@ -1499,7 +1496,7 @@ void WI_updateStats(void)
{ {
if (acceleratestage) if (acceleratestage)
{ {
S_StartSound(ORIGIN_AMBIENT, sfx_sgcock); S_StartSound (ORIGIN_AMBIENT, "weapons/shotgr", 64);
if (gamemode == commercial) if (gamemode == commercial)
WI_initNoState(); WI_initNoState();

View file

@ -3,6 +3,8 @@
#include "cmdlib.h" #include "cmdlib.h"
#include "c_dispch.h" #include "c_dispch.h"
#include "c_bind.h" #include "c_bind.h"
#include "g_level.h"
#include "dstrings.h"
#include <math.h> #include <math.h>
#include <stdlib.h> #include <stdlib.h>
@ -57,7 +59,7 @@ char DefBindings[] =
"bind \\ +showscores; " // <- Another new command "bind \\ +showscores; " // <- Another new command
"bind f12 spynext"; "bind f12 spynext";
static const char *KeyNames[256+8+32] = { static const char *KeyNames[NUM_KEYS] = {
// This array is dependant on the particular keyboard input // This array is dependant on the particular keyboard input
// codes generated in i_input.c. If they change there, they // codes generated in i_input.c. If they change there, they
// also need to change here. In this case, we use the // also need to change here. In this case, we use the
@ -98,9 +100,9 @@ static const char *KeyNames[256+8+32] = {
NULL, NULL, NULL, NULL, NULL, NULL, NULL, "pause", //F8 NULL, NULL, NULL, NULL, NULL, NULL, NULL, "pause", //F8
// non-keyboard buttons that can be bound // non-keyboard buttons that can be bound
"mouse1", "mouse2", "mouse3", "mouse4", // DInput has four of these... "mouse1", "mouse2", "mouse3", "mouse4", // 4 mouse buttons
NULL, NULL, NULL, NULL, // Space for double clicking if I feel like it "mwheelup", "mwheeldown",NULL, NULL, // the wheel and some extra space
"joy1", "joy2", "joy3", "joy4", // 32 joystick buttons! "joy1", "joy2", "joy3", "joy4", // 32 joystick buttons
"joy5", "joy6", "joy7", "joy8", "joy5", "joy6", "joy7", "joy8",
"joy9", "joy10", "joy11", "joy12", "joy9", "joy10", "joy11", "joy12",
"joy13", "joy14", "joy15", "joy16", "joy13", "joy14", "joy15", "joy16",
@ -110,7 +112,10 @@ static const char *KeyNames[256+8+32] = {
"joy29", "joy30", "joy31", "joy32" "joy29", "joy30", "joy31", "joy32"
}; };
static char *Bindings[256+8+32]; static char *Bindings[NUM_KEYS];
static char *DoubleBindings[NUM_KEYS];
static int DClickTime[NUM_KEYS];
static byte DClicked[(NUM_KEYS+7)/8];
static int GetKeyFromName (const char *name) static int GetKeyFromName (const char *name)
{ {
@ -122,7 +127,7 @@ static int GetKeyFromName (const char *name)
} }
// Otherwise, we scan the KeyNames[] array for a matching name // Otherwise, we scan the KeyNames[] array for a matching name
for (i = 0; i < 256+8+32; i++) { for (i = 0; i < NUM_KEYS; i++) {
if (KeyNames[i] && !stricmp (KeyNames[i], name)) if (KeyNames[i] && !stricmp (KeyNames[i], name))
return i; return i;
} }
@ -144,12 +149,17 @@ void Cmd_Unbindall (void *plyr, int argc, char **argv)
{ {
int i; int i;
for (i = 0; i < 256+8+32; i++) { for (i = 0; i < NUM_KEYS; i++)
if (Bindings[i]) { if (Bindings[i]) {
free (Bindings[i]); free (Bindings[i]);
Bindings[i] = NULL; Bindings[i] = NULL;
} }
}
for (i = 0; i < NUM_KEYS; i++)
if (DoubleBindings[i]) {
free (DoubleBindings[i]);
DoubleBindings[i] = NULL;
}
} }
void Cmd_Unbind (void *plyr, int argc, char **argv) void Cmd_Unbind (void *plyr, int argc, char **argv)
@ -183,43 +193,115 @@ void Cmd_Bind (void *plyr, int argc, char **argv)
if (argc == 2) { if (argc == 2) {
Printf ("\"%s\" = \"%s\"\n", argv[1], (Bindings[i] ? Bindings[i] : "")); Printf ("\"%s\" = \"%s\"\n", argv[1], (Bindings[i] ? Bindings[i] : ""));
} else { } else {
if (Bindings[i]) ReplaceString (&Bindings[i], argv[2]);
free (Bindings[i]);
Bindings[i] = copystring (argv[2]);
} }
} else { } else {
Printf ("Current key bindings:\n"); Printf ("Current key bindings:\n");
for (i = 0; i < 256+8+32; i++) { for (i = 0; i < NUM_KEYS; i++) {
if (Bindings[i]) if (Bindings[i])
Printf ("%s \"%s\"\n", KeyName (i), Bindings[i]); Printf ("%s \"%s\"\n", KeyName (i), Bindings[i]);
} }
} }
} }
void Cmd_UnDoubleBind (void *plyr, int argc, char **argv)
{
int i;
if (argc > 1) {
if ( (i = GetKeyFromName (argv[1])) ) {
if (DoubleBindings[i]) {
free (DoubleBindings[i]);
DoubleBindings[i] = NULL;
}
} else {
Printf ("Unknown key \"%s\"\n", argv[1]);
return;
}
}
}
void Cmd_DoubleBind (void *plyr, int argc, char **argv)
{
int i;
if (argc > 1) {
i = GetKeyFromName (argv[1]);
if (!i) {
Printf ("Unknown key \"%s\"\n", argv[1]);
return;
}
if (argc == 2) {
Printf ("\"%s\" = \"%s\"\n", argv[1], (DoubleBindings[i] ? DoubleBindings[i] : ""));
} else {
ReplaceString (&DoubleBindings[i], argv[2]);
}
} else {
Printf ("Current key doublebindings:\n");
for (i = 0; i < NUM_KEYS; i++) {
if (DoubleBindings[i])
Printf ("%s \"%s\"\n", KeyName (i), DoubleBindings[i]);
}
}
}
void Cmd_BindDefaults (void *plyr, int argc, char **argv) void Cmd_BindDefaults (void *plyr, int argc, char **argv)
{ {
AddCommandString (DefBindings); AddCommandString (DefBindings);
} }
BOOL C_DoKey (int key, BOOL up) BOOL C_DoKey (event_t *ev)
{ {
extern BOOL chat_on; extern BOOL chat_on;
char *binding = NULL;
int dclickspot;
byte dclickmask;
if (Bindings[key] && (!chat_on || key < 256)) { if (ev->type != ev_keydown && ev->type != ev_keyup)
if (!up) { return false;
AddCommandString (Bindings[key]);
dclickspot = ev->data1 >> 3;
dclickmask = 1 << (ev->data1 & 7);
if (DClickTime[ev->data1] > level.time && ev->type == ev_keydown) {
// Key pressed for a double click
binding = DoubleBindings[ev->data1];
DClicked[dclickspot] |= dclickmask;
} else {
if (ev->type == ev_keydown) {
// 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
binding = DoubleBindings[ev->data1];
DClicked[dclickspot] &= ~dclickmask;
DClickTime[ev->data1] = 0;
} else {
// Key released from a normal press
binding = Bindings[ev->data1];
}
}
if (!binding)
binding = Bindings[ev->data1];
if (binding && (!chat_on || ev->data1 < 256)) {
if (ev->type == ev_keydown) {
AddCommandString (binding);
} else { } else {
char *achar; char *achar;
achar = strchr (Bindings[key], '+'); achar = strchr (binding, '+');
if (!achar) if (!achar)
return false; return false;
if ((achar == Bindings[key]) || (*(achar - 1) <= ' ')) { if ((achar == binding) || (*(achar - 1) <= ' ')) {
*achar = '-'; *achar = '-';
AddCommandString (Bindings[key]); AddCommandString (binding);
*achar = '+'; *achar = '+';
} }
} }
@ -233,11 +315,12 @@ void C_ArchiveBindings (FILE *f)
int i; int i;
fprintf (f, "unbindall\n"); fprintf (f, "unbindall\n");
for (i = 0; i < 256+8+32; i++) { for (i = 0; i < NUM_KEYS; i++)
if (Bindings[i]) { if (Bindings[i])
fprintf (f, "bind \"%s\" \"%s\"\n", KeyName (i), Bindings[i]); fprintf (f, "bind \"%s\" \"%s\"\n", KeyName (i), Bindings[i]);
} for (i = 0; i < NUM_KEYS; i++)
} if (DoubleBindings[i])
fprintf (f, "doublebind \"%s\" \"%s\"\n", KeyName (i), DoubleBindings[i]);
} }
int C_GetKeysForCommand (char *cmd, int *first, int *second) int C_GetKeysForCommand (char *cmd, int *first, int *second)
@ -246,7 +329,7 @@ int C_GetKeysForCommand (char *cmd, int *first, int *second)
*first = *second = c = i = 0; *first = *second = c = i = 0;
while (i < 256+8+32 && c < 2) { while (i < NUM_KEYS && c < 2) {
if (Bindings[i] && !stricmp (cmd, Bindings[i])) { if (Bindings[i] && !stricmp (cmd, Bindings[i])) {
if (c++ == 0) if (c++ == 0)
*first = i; *first = i;
@ -283,7 +366,7 @@ void C_UnbindACommand (char *str)
{ {
int i; int i;
for (i = 0; i < 256+8+32; i++) { for (i = 0; i < NUM_KEYS; i++) {
if (Bindings[i] && !stricmp (str, Bindings[i])) { if (Bindings[i] && !stricmp (str, Bindings[i])) {
free (Bindings[i]); free (Bindings[i]);
Bindings[i] = NULL; Bindings[i] = NULL;

View file

@ -2,9 +2,10 @@
#define __C_BINDINGS_H__ #define __C_BINDINGS_H__
#include "doomtype.h" #include "doomtype.h"
#include "d_event.h"
#include <stdio.h> #include <stdio.h>
BOOL C_DoKey (int key, BOOL up); BOOL C_DoKey (event_t *ev);
void C_ArchiveBindings (FILE *f); void C_ArchiveBindings (FILE *f);
// Stuff used by the customize controls menu // Stuff used by the customize controls menu

View file

@ -7,6 +7,9 @@ void C_InstallCommands (void);
// am_map.c // am_map.c
CMD(Cmd_Togglemap) CMD(Cmd_Togglemap)
// d_main.c
CMD(Cmd_Endgame)
// m_menu.c // m_menu.c
CMD(Cmd_Menu_Main) CMD(Cmd_Menu_Main)
CMD(Cmd_Menu_Load) CMD(Cmd_Menu_Load)
@ -34,9 +37,12 @@ CMD(Cmd_Menu_Gameplay)
CMD(Cmd_Impulse) CMD(Cmd_Impulse)
CMD(Cmd_CenterView) CMD(Cmd_CenterView)
CMD(Cmd_Pause) CMD(Cmd_Pause)
CMD(Cmd_WeapNext)
CMD(Cmd_WeapPrev)
CMD(Cmd_Stop) CMD(Cmd_Stop)
CMD(Cmd_SpyNext) CMD(Cmd_SpyNext)
CMD(Cmd_SpyPrev) CMD(Cmd_SpyPrev)
CMD(Cmd_Turn180)
// g_level.c // g_level.c
CMD(Cmd_Map) CMD(Cmd_Map)
@ -51,6 +57,8 @@ CMD(Cmd_Bind)
CMD(Cmd_BindDefaults) CMD(Cmd_BindDefaults)
CMD(Cmd_Unbind) CMD(Cmd_Unbind)
CMD(Cmd_Unbindall) CMD(Cmd_Unbindall)
CMD(Cmd_DoubleBind)
CMD(Cmd_UnDoubleBind)
// c_consol.c // c_consol.c
void C_ToggleConsole (void); void C_ToggleConsole (void);
@ -78,6 +86,12 @@ CMD(Cmd_DumpHeap)
CMD(Cmd_Logfile) CMD(Cmd_Logfile)
CMD(Cmd_Limits) CMD(Cmd_Limits)
CMD(Cmd_ChangeMap) CMD(Cmd_ChangeMap)
CMD(Cmd_Quit)
CMD(Cmd_Puke)
CMD(Cmd_Error)
// d_net.c
CMD(Cmd_Pings)
// p_inter.c // p_inter.c
CMD(Cmd_Kill) CMD(Cmd_Kill)
@ -92,5 +106,17 @@ CMD(Cmd_Screenshot)
// hu_stuff.c // hu_stuff.c
CMD(Cmd_MessageMode) CMD(Cmd_MessageMode)
CMD(Cmd_Say) CMD(Cmd_Say)
CMD(Cmd_MessageMode2)
CMD(Cmd_Say_Team)
// r_things.c
CMD(Cmd_Skins)
// s_sounds.c
CMD(Cmd_Soundlist)
CMD(Cmd_Soundlinks)
// z_zone.c
CMD(Cmd_Mem)
#undef CMD #undef CMD

View file

@ -4,13 +4,16 @@
#include <math.h> #include <math.h>
#include <stdlib.h> #include <stdlib.h>
#include "version.h"
#include "dstrings.h" #include "dstrings.h"
#include "g_game.h"
#include "c_consol.h" #include "c_consol.h"
#include "c_cvars.h" #include "c_cvars.h"
#include "c_dispch.h" #include "c_dispch.h"
#include "hu_stuff.h" #include "hu_stuff.h"
#include "i_input.h" #include "i_input.h"
#include "i_system.h" #include "i_system.h"
#include "i_video.h"
#include "m_swap.h" #include "m_swap.h"
#include "v_video.h" #include "v_video.h"
#include "v_text.h" #include "v_text.h"
@ -19,6 +22,7 @@
#include "r_main.h" #include "r_main.h"
#include "r_draw.h" #include "r_draw.h"
#include "st_stuff.h" #include "st_stuff.h"
#include "s_sound.h"
#include "doomstat.h" #include "doomstat.h"
@ -31,11 +35,7 @@ static screen_t conback; // As of 1.13, Console backdrop is just another screen
extern int gametic; extern int gametic;
extern BOOL automapactive; // in AM_map.c extern BOOL automapactive; // in AM_map.c
extern BOOL advancedemo;
typedef enum cstate_t {
up=0, down=1, falling=2, rising=3
} constate;
int ConRows, ConCols, PhysRows; int ConRows, ConCols, PhysRows;
char *Lines, *Last = NULL; char *Lines, *Last = NULL;
@ -43,7 +43,7 @@ BOOL vidactive = false, gotconback = false;
BOOL cursoron = false; BOOL cursoron = false;
int ShowRows, SkipRows, ConsoleTicker, ConBottom, ConScroll, RowAdjust; int ShowRows, SkipRows, ConsoleTicker, ConBottom, ConScroll, RowAdjust;
int CursorTicker, ScrollState = 0; int CursorTicker, ScrollState = 0;
int ConsoleState = up; constate_e ConsoleState = c_up;
char VersionString[8]; char VersionString[8];
event_t RepeatEvent; // always type ev_keydown event_t RepeatEvent; // always type ev_keydown
@ -56,8 +56,7 @@ BOOL KeysShifted;
#define SCROLLNO 0 #define SCROLLNO 0
extern cvar_t *showMessages; extern cvar_t *showMessages;
extern BOOL message_dontfuckwithme; // Who came up with this name? extern BOOL message_dontfuckwithme;
extern BOOL chat_on; extern BOOL chat_on;
struct History { struct History {
@ -86,7 +85,7 @@ FILE *Logfile = NULL;
extern patch_t *hu_font[HU_FONTSIZE]; // from hu_stuff.c extern patch_t *hu_font[HU_FONTSIZE]; // from hu_stuff.c
void C_HandleKey (event_t *ev, byte *buffer, int len); BOOL C_HandleKey (event_t *ev, byte *buffer, int len);
static int C_hu_CharWidth (int c) static int C_hu_CharWidth (int c)
@ -152,8 +151,15 @@ void C_InitConsole (int width, int height, BOOL ingame)
} }
} }
} }
sprintf (VersionString, "v%d.%d", VERSION / 100, VERSION % 100);
{
int i;
VersionString[0] = 0x11;
for (i = 0; i < strlen(DOTVERSIONSTR); i++)
VersionString[i+1] = DOTVERSIONSTR[i]-30;
VersionString[i+1] = 0;
}
V_UnlockScreen (&conback); V_UnlockScreen (&conback);
gotconback = true; gotconback = true;
@ -179,9 +185,10 @@ void C_InitConsole (int width, int height, BOOL ingame)
if (old) { if (old) {
char string[256]; char string[256];
FILE *templog; gamestate_t oldstate = gamestate; // Don't print during reformatting
FILE *templog = Logfile; // Don't log our reformatting pass
templog = Logfile; // Don't log our reformatting pass gamestate = -1;
Logfile = NULL; Logfile = NULL;
for (row = 0, zap = old; row < rows; row++, zap += cols + 2) { for (row = 0, zap = old; row < rows; row++, zap += cols + 2) {
@ -198,7 +205,11 @@ void C_InitConsole (int width, int height, BOOL ingame)
ShowRows = 0; ShowRows = 0;
Logfile = templog; Logfile = templog;
gamestate = oldstate;
} }
if (ingame && gamestate == GS_STARTUP)
C_FullConsole ();
} }
void C_AddNotifyString (const char *source) void C_AddNotifyString (const char *source)
@ -303,13 +314,31 @@ int PrintString (const char *outline) {
printxormask = 0; printxormask = 0;
if (vidactive &&
((gameaction != ga_nothing && ConsoleState == c_down)
|| gamestate == GS_STARTUP)) {
static size_t lastprinttime = 0;
size_t nowtime = I_GetTime();
if (nowtime - lastprinttime > 1) {
I_BeginUpdate ();
C_DrawConsole ();
I_FinishUpdate ();
lastprinttime = nowtime;
}
}
return strlen (outline); return strlen (outline);
} }
extern BOOL gameisdead;
int VPrintf (const char *format, va_list parms) int VPrintf (const char *format, va_list parms)
{ {
char outline[8192]; char outline[8192];
if (gameisdead)
return 0;
vsprintf (outline, format, parms); vsprintf (outline, format, parms);
return PrintString (outline); return PrintString (outline);
} }
@ -359,12 +388,19 @@ void C_FlushDisplay (void)
ShowRows = 0; ShowRows = 0;
} }
void C_AdjustBottom (void)
{
if (gamestate == GS_FULLCONSOLE || gamestate == GS_STARTUP)
ConBottom = screens[0].height / 8;
else if (ConBottom > screens[0].height / 16 || ConsoleState == c_down)
ConBottom = screens[0].height / 16;
}
void C_NewModeAdjust (void) void C_NewModeAdjust (void)
{ {
C_InitConsole (screens[0].width, screens[0].height, true); C_InitConsole (screens[0].width, screens[0].height, true);
ShowRows = 0; ShowRows = 0;
if (ConBottom > screens[0].height / 16 || ConsoleState == down) C_AdjustBottom ();
ConBottom = screens[0].height / 16;
} }
void C_Ticker (void) void C_Ticker (void)
@ -374,7 +410,7 @@ void C_Ticker (void)
if (lasttic == 0) if (lasttic == 0)
lasttic = gametic - 1; lasttic = gametic - 1;
if (ConsoleState != up) { if (ConsoleState != c_up) {
// Handle repeating keys // Handle repeating keys
switch (ScrollState) { switch (ScrollState) {
case SCROLLUP: case SCROLLUP:
@ -396,16 +432,16 @@ void C_Ticker (void)
break; break;
} }
if (ConsoleState == falling) { if (ConsoleState == c_falling) {
ConBottom += (gametic - lasttic) * (screens[0].height / 100); ConBottom += (gametic - lasttic) * (screens[0].height / 100);
if (ConBottom >= screens[0].height / 16) { if (ConBottom >= screens[0].height / 16) {
ConBottom = screens[0].height / 16; ConBottom = screens[0].height / 16;
ConsoleState = down; ConsoleState = c_down;
} }
} else if (ConsoleState == rising) { } else if (ConsoleState == c_rising) {
ConBottom -= (gametic - lasttic) * (screens[0].height / 100); ConBottom -= (gametic - lasttic) * (screens[0].height / 100);
if (ConBottom <= 0) { if (ConBottom <= 0) {
ConsoleState = up; ConsoleState = c_up;
ConBottom = 0; ConBottom = 0;
} }
} }
@ -474,7 +510,7 @@ void C_DrawConsole (void)
oldbottom = ConBottom; oldbottom = ConBottom;
if (ConsoleState == up) { if (ConsoleState == c_up) {
C_DrawNotifyText (); C_DrawNotifyText ();
return; return;
} else if (ConBottom) { } else if (ConBottom) {
@ -486,60 +522,88 @@ void C_DrawConsole (void)
V_Blit (&conback, 0, conback.height - realheight, conback.width, realheight, V_Blit (&conback, 0, conback.height - realheight, conback.width, realheight,
&screens[0], 0, 0, screens[0].width, visheight); &screens[0], 0, 0, screens[0].width, visheight);
if (ConBottom >= 2) if (ConBottom >= 2) {
V_PrintStr (screens[0].width - 8 - strlen(VersionString) * 8, V_PrintStr (screens[0].width - 8 - strlen(VersionString) * 8,
ConBottom * 8 - 16, ConBottom * 8 - 16,
VersionString, strlen(VersionString), 0x80); VersionString, strlen (VersionString));
if (gamestate == GS_STARTUP)
V_PrintStr (8, ConBottom * 8 - 16, DoomStartupTitle, strlen (DoomStartupTitle));
}
} }
if (menuactive)
return;
if (lines > 0) { if (lines > 0) {
for (; lines; lines--) { for (; lines; lines--) {
V_PrintStr (left, -8 + lines * 8, &zap[2], zap[1], 0); V_PrintStr (left, -8 + lines * 8, &zap[2], zap[1]);
zap -= ConCols + 2; zap -= ConCols + 2;
} }
if (ConBottom > 1) { if (ConBottom > 1) {
V_PrintStr (left, (ConBottom - 2) * 8, "]", 1, 0x80); if (gamestate != GS_STARTUP)
V_PrintStr (left, (ConBottom - 2) * 8, "\x8c", 1);
#define MIN(a,b) (((a)<(b))?(a):(b)) #define MIN(a,b) (((a)<(b))?(a):(b))
V_PrintStr (left + 8, (ConBottom - 2) * 8, V_PrintStr (left + 8, (ConBottom - 2) * 8,
&CmdLine[2+CmdLine[259]], &CmdLine[2+CmdLine[259]],
MIN(CmdLine[0] - CmdLine[259], ConCols - 1), 0); MIN(CmdLine[0] - CmdLine[259], ConCols - 1));
#undef MIN #undef MIN
if (cursoron) { if (cursoron) {
V_PrintStr (left + 8 + (CmdLine[1] - CmdLine[259])* 8, V_PrintStr (left + 8 + (CmdLine[1] - CmdLine[259])* 8,
(ConBottom - 2) * 8, "\xb", 1, 0); (ConBottom - 2) * 8, "\xb", 1);
} }
if (RowAdjust && ConBottom > 2) { if (RowAdjust && ConBottom > 2) {
char c; char c;
// Indicate that the view has been scrolled up... // Indicate that the view has been scrolled up (10)
if (SkipRows + RowAdjust + ConBottom != ConRows) // and if we can scroll no further (12)
c = '^'; c = (SkipRows + RowAdjust + ConBottom != ConRows) ? 10 : 12;
// and if we can scroll no further V_PrintStr (0, (ConBottom - 3) * 8 + 4, &c, 1);
else
c = '*';
V_PrintStr (0, (ConBottom - 3) * 8 + 6, &c, 1, 0x80);
} }
} }
} }
} }
void C_FullConsole (void)
{
if (demoplayback)
G_CheckDemoStatus ();
advancedemo = false;
ConsoleState = c_down;
HistPos = NULL;
TabbedLast = false;
if (gamestate != GS_STARTUP) {
gamestate = GS_FULLCONSOLE;
level.music[0] = '\0';
S_Start ();
I_PauseMouse ();
} else
C_AdjustBottom ();
}
void C_ToggleConsole (void) void C_ToggleConsole (void)
{ {
// Only let the console go up if chat mode is on if (gamestate == GS_DEMOSCREEN || demoplayback) {
if (!chat_on && (ConsoleState == up || ConsoleState == rising)) { gameaction = ga_fullconsole;
ConsoleState = falling; } else if (!chat_on && (ConsoleState == c_up || ConsoleState == c_rising)) {
ConsoleState = c_falling;
HistPos = NULL; HistPos = NULL;
TabbedLast = false; TabbedLast = false;
} else { I_PauseMouse ();
ConsoleState = rising; } else if (gamestate != GS_FULLCONSOLE && gamestate != GS_STARTUP) {
ConsoleState = c_rising;
I_ResumeMouse ();
} }
} }
void C_HideConsole (void) void C_HideConsole (void)
{ {
ConsoleState = up; if (gamestate != GS_FULLCONSOLE && gamestate != GS_STARTUP) {
ConBottom = 0; ConsoleState = c_up;
HistPos = NULL; ConBottom = 0;
HistPos = NULL;
if (!menuactive)
I_ResumeMouse ();
}
} }
static void makestartposgood (void) static void makestartposgood (void)
@ -571,7 +635,7 @@ static void makestartposgood (void)
CmdLine[259] = n; CmdLine[259] = n;
} }
void C_HandleKey (event_t *ev, byte *buffer, int len) BOOL C_HandleKey (event_t *ev, byte *buffer, int len)
{ {
switch (ev->data1) { switch (ev->data1) {
case KEY_TAB: case KEY_TAB:
@ -744,8 +808,11 @@ void C_HandleKey (event_t *ev, byte *buffer, int len)
AddCommandString (&buffer[2]); AddCommandString (&buffer[2]);
TabbedLast = false; TabbedLast = false;
} else if (ev->data2 == '`' || ev->data1 == KEY_ESCAPE) { } else if (ev->data2 == '`' || ev->data1 == KEY_ESCAPE) {
// Close console, both ` and ESC clear command line // Close console, clear command line, but if we're in the
// fullscreen console mode, there's nothing to fall back on
// if it's closed.
if (gamestate == GS_FULLCONSOLE || gamestate == GS_STARTUP)
return false;
buffer[0] = buffer[1] = buffer[len+4] = 0; buffer[0] = buffer[1] = buffer[len+4] = 0;
HistPos = NULL; HistPos = NULL;
C_ToggleConsole (); C_ToggleConsole ();
@ -779,11 +846,12 @@ void C_HandleKey (event_t *ev, byte *buffer, int len)
} }
break; break;
} }
return true;
} }
BOOL C_Responder (event_t *ev) BOOL C_Responder (event_t *ev)
{ {
if (ConsoleState == up || ConsoleState == rising) { if (ConsoleState == c_up || ConsoleState == c_rising || menuactive) {
return false; return false;
} }
@ -816,12 +884,9 @@ BOOL C_Responder (event_t *ev)
// Others do. // Others do.
RepeatCountdown = KeyRepeatDelay; RepeatCountdown = KeyRepeatDelay;
RepeatEvent = *ev; RepeatEvent = *ev;
C_HandleKey (ev, CmdLine, 255); return C_HandleKey (ev, CmdLine, 255);
} else } else
return false; return false;
return true;
} }
void Cmd_History (player_t *plyr, int argc, char **argv) void Cmd_History (player_t *plyr, int argc, char **argv)
@ -880,11 +945,11 @@ void C_DrawMid (void)
int i, line, x, y; int i, line, x, y;
byte *holdwhite = WhiteMap; byte *holdwhite = WhiteMap;
// Hack! Hack! I need to get mult-colored text output written... // Hack! Hack! I need to get multi-colored text output written (still)...
WhiteMap = Ranges + 5 * 256; WhiteMap = Ranges + 5 * 256;
y = 8 * CleanYfac; y = 8 * CleanYfac;
x = screens[0].width >> 1; x = screens[0].width >> 1;
for (i = 0, line = (ST_Y >> 1) - MidLines * 4 * CleanYfac; i < MidLines; i++, line += y) { for (i = 0, line = (ST_Y * 3) / 8 - MidLines * 4 * CleanYfac; i < MidLines; i++, line += y) {
V_DrawTextClean (x - (MidMsg[i].width >> 1) * CleanXfac, line, MidMsg[i].string); V_DrawTextClean (x - (MidMsg[i].width >> 1) * CleanXfac, line, MidMsg[i].string);
} }

View file

@ -11,6 +11,10 @@
#define C_BLINKRATE (TICRATE/2) #define C_BLINKRATE (TICRATE/2)
typedef enum cstate_t {
c_up=0, c_down=1, c_falling=2, c_rising=3
} constate_e;
// Initialize the console // Initialize the console
void C_InitConsole (int width, int height, BOOL ingame); void C_InitConsole (int width, int height, BOOL ingame);
@ -26,7 +30,9 @@ int Printf_Bold (const char *format, ...);
void C_AddNotifyString (const char *s); void C_AddNotifyString (const char *s);
void C_DrawConsole (void); void C_DrawConsole (void);
void C_ToggleConsole (void); void C_ToggleConsole (void);
void C_FullConsole (void);
void C_HideConsole (void); void C_HideConsole (void);
void C_AdjustBottom (void);
void C_FlushDisplay (void); void C_FlushDisplay (void);
void C_MidPrint (char *message); void C_MidPrint (char *message);

View file

@ -21,24 +21,24 @@ struct CmdData *Commands[HASH_SIZE];
struct CmdData *Aliases[HASH_SIZE]; struct CmdData *Aliases[HASH_SIZE];
struct ActionBits actionbits[NUM_ACTIONS] = { struct ActionBits actionbits[NUM_ACTIONS] = {
{ 0x116716a2, ACTION_SPEED, "speed" }, { 0x00409, ACTION_USE, "use" },
{ 0x1e60dad4, ACTION_RIGHT, "right" }, { 0x0074d, ACTION_BACK, "back" },
{ 0x206c10aa, ACTION_KLOOK, "klook" }, { 0x007e4, ACTION_LEFT, "left" },
{ 0x226a20ae, ACTION_MLOOK, "mlook" }, { 0x00816, ACTION_JUMP, "jump" },
{ 0x4d63cc88, ACTION_USE, "use" }, { 0x0106d, ACTION_KLOOK, "klook" },
{ 0x50183a64, ACTION_SHOWSCORES, "showscores" }, { 0x0109d, ACTION_MLOOK, "mlook" },
{ 0x620a3c5e, ACTION_MOVELEFT, "moveleft" }, { 0x010d8, ACTION_RIGHT, "right" },
{ 0x6d157234, ACTION_LOOKDOWN, "lookdown" }, { 0x0110a, ACTION_SPEED, "speed" },
{ 0x6f03745a, ACTION_MOVEDOWN, "movedown" }, { 0x01fc5, ACTION_ATTACK, "attack" },
{ 0x78086cf0, ACTION_ATTACK, "attack" }, { 0x021ae, ACTION_LOOKUP, "lookup" },
{ 0x8517869e, ACTION_STRAFE, "strafe" }, { 0x021fe, ACTION_MOVEUP, "moveup" },
{ 0x910b0cac, ACTION_BACK, "back" }, { 0x02315, ACTION_STRAFE, "strafe" },
{ 0x9a02b460, ACTION_LOOKUP, "lookup" }, { 0x041c4, ACTION_FORWARD, "forward" },
{ 0x9c14ae86, ACTION_MOVEUP, "moveup" }, { 0x08788, ACTION_LOOKDOWN, "lookdown" },
{ 0xab1b201e, ACTION_LEFT, "left" }, { 0x088c4, ACTION_MOVELEFT, "moveleft" },
{ 0xbc02544e, ACTION_JUMP, "jump" }, { 0x088c8, ACTION_MOVEDOWN, "movedown" },
{ 0xd571f880, ACTION_MOVERIGHT, "moveright" }, { 0x11268, ACTION_MOVERIGHT, "moveright" },
{ 0xf57be8e2, ACTION_FORWARD, "forward" } { 0x2314d, ACTION_SHOWSCORES, "showscores" }
}; };
int Actions; int Actions;
@ -53,21 +53,18 @@ static int ListActionCommands (void)
return NUM_ACTIONS * 2; return NUM_ACTIONS * 2;
} }
unsigned int MakeKey (char *s) unsigned int MakeKey (const char *s)
{ {
byte a,b,c,d,e; register unsigned int v = 0;
a = b = c = d = 0; if (*s)
v = tolower(*s++);
if (*s)
v = (v*3) + tolower(*s++);
while (*s)
v = (v << 1) + tolower(*s++);
while (*s) { return v;
e = tolower (*s++);
a += e;
b ^= e;
c += a - b;
d += a + b;
}
return (a << 24) | (b << 16) | (c << 8) | d;
} }
// GetActionBit scans through the actionbits[] array // GetActionBit scans through the actionbits[] array

View file

@ -68,4 +68,6 @@ struct ActionBits {
char name[12]; char name[12];
}; };
extern unsigned int MakeKey (const char *s);
#endif //__C_DISPATCH_H__ #endif //__C_DISPATCH_H__

View file

@ -13,7 +13,6 @@ typedef struct {
extern cvar_t *gammalevel, extern cvar_t *gammalevel,
*st_scale, *st_scale,
*var_language,
*gameskill, *gameskill,
*crosshair, *crosshair,
*WI_Percents, *WI_Percents,
@ -27,17 +26,21 @@ extern cvar_t *gammalevel,
*idmypos, *idmypos,
*vid_defwidth, *vid_defwidth,
*vid_defheight, *vid_defheight,
*vid_defbpp, *vid_defid,
*i_remapkeypad, *i_remapkeypad,
*cl_run, *cl_run,
*chat_macros[10], *chat_macros[10],
*showMessages, *showMessages,
*nobfgaim,
*snd_surround,
*snd_samplerate, *snd_samplerate,
*snd_pitched, *snd_pitched,
*snd_channels, *snd_channels,
*snd_SfxVolume, *snd_SfxVolume,
*snd_MusicVolume, *snd_MusicVolume,
*snd_MidiVolume,
*noisedebug,
*sv_gravity, *sv_gravity,
*sv_friction, *sv_friction,
@ -72,14 +75,7 @@ extern cvar_t *gammalevel,
*am_gridcolor, *am_gridcolor,
*am_xhaircolor, *am_xhaircolor,
*am_notseencolor, *am_notseencolor,
*am_key1color, *am_lockedcolor,
*am_key2color,
*am_key3color,
/*
*am_key4color,
*am_key5color,
*am_key6color,
*/
*am_ovyourcolor, *am_ovyourcolor,
*am_ovwallcolor, *am_ovwallcolor,
*am_ovthingcolor, *am_ovthingcolor,
@ -89,6 +85,7 @@ extern cvar_t *gammalevel,
*dimamount, *dimamount,
*dimcolor, *dimcolor,
*teamplay,
*deathmatch, *deathmatch,
*dmflagsvar, *dmflagsvar,
*fraglimit, *fraglimit,
@ -97,25 +94,35 @@ extern cvar_t *gammalevel,
*autoaim, *autoaim,
*name, *name,
*color, *color,
*skin,
*team,
*gender,
*boom_pushers,
*boom_friction,
*splashfactor,
*testgibs; *testgibs;
static const cvarinit_t Initializers[] = { static const cvarinit_t Initializers[] = {
{ &gammalevel, "gamma", "1", CVAR_ARCHIVE|CVAR_CALLBACK }, { &gammalevel, "gamma", "1", CVAR_ARCHIVE|CVAR_CALLBACK },
{ &testgibs, "testgibs", "0", 0 }, { &testgibs, "testgibs", "0", 0 },
{ &st_scale, "st_scale", "0", CVAR_ARCHIVE|CVAR_CALLBACK }, { &st_scale, "st_scale", "0", CVAR_ARCHIVE|CVAR_CALLBACK },
{ &var_language, "language", "english", CVAR_ARCHIVE|CVAR_CALLBACK },
{ &dimamount, "dimamount", "1", CVAR_ARCHIVE }, { &dimamount, "dimamount", "1", CVAR_ARCHIVE },
{ &dimcolor, "dimcolor", "ffff d7d7 0000", CVAR_ARCHIVE }, { &dimcolor, "dimcolor", "ffff d7d7 0000", CVAR_ARCHIVE },
{ &crosshair, "crosshair", "0", CVAR_ARCHIVE }, { &crosshair, "crosshair", "0", CVAR_ARCHIVE },
{ &developer, "developer", "0", 0 }, { &developer, "developer", "0", 0 },
{ &snd_surround, "snd_surround", "1", CVAR_ARCHIVE },
{ &snd_SfxVolume, "snd_sfxvolume", "8", CVAR_ARCHIVE|CVAR_CALLBACK }, { &snd_SfxVolume, "snd_sfxvolume", "8", CVAR_ARCHIVE|CVAR_CALLBACK },
{ &snd_MusicVolume, "snd_musicvolume", "9", CVAR_ARCHIVE|CVAR_CALLBACK }, { &snd_MusicVolume, "snd_musicvolume", "9", CVAR_ARCHIVE|CVAR_CALLBACK },
{ &snd_MidiVolume, "snd_midivolume", "0.5", CVAR_ARCHIVE|CVAR_CALLBACK },
{ &snd_channels, "snd_channels", "8", CVAR_ARCHIVE }, { &snd_channels, "snd_channels", "8", CVAR_ARCHIVE },
{ &snd_pitched, "snd_pitched", "0", CVAR_ARCHIVE }, { &snd_pitched, "snd_pitched", "0", CVAR_ARCHIVE },
{ &snd_samplerate, "snd_samplerate", "44100", CVAR_ARCHIVE }, { &snd_samplerate, "snd_samplerate", "44100", CVAR_ARCHIVE },
{ &noisedebug, "noise", "0", 0 },
{ &screenblocks, "screenblocks", "10", CVAR_ARCHIVE|CVAR_CALLBACK }, { &screenblocks, "screenblocks", "10", CVAR_ARCHIVE|CVAR_CALLBACK },
{ &usemouse, "use_mouse", "1", CVAR_ARCHIVE }, { &usemouse, "use_mouse", "1", CVAR_ARCHIVE },
@ -143,7 +150,7 @@ static const cvarinit_t Initializers[] = {
{ &idmypos, "idmypos", "0", 0 }, { &idmypos, "idmypos", "0", 0 },
{ &vid_defwidth, "vid_defwidth", "320", CVAR_ARCHIVE }, { &vid_defwidth, "vid_defwidth", "320", CVAR_ARCHIVE },
{ &vid_defheight, "vid_defheight", "200", CVAR_ARCHIVE }, { &vid_defheight, "vid_defheight", "200", CVAR_ARCHIVE },
{ &vid_defbpp, "vid_defbpp", "8", CVAR_ARCHIVE }, { &vid_defid, "vid_defid", "INDEX8", CVAR_ARCHIVE },
{ &i_remapkeypad, "i_remapkeypad", "1", CVAR_ARCHIVE }, { &i_remapkeypad, "i_remapkeypad", "1", CVAR_ARCHIVE },
{ &cl_run, "cl_run", "0", CVAR_ARCHIVE }, { &cl_run, "cl_run", "0", CVAR_ARCHIVE },
{ &showMessages, "show_messages", "1", CVAR_ARCHIVE }, { &showMessages, "show_messages", "1", CVAR_ARCHIVE },
@ -175,28 +182,31 @@ static const cvarinit_t Initializers[] = {
{ &am_gridcolor, "am_gridcolor", "8b8b 5a5a 2b2b", CVAR_ARCHIVE }, { &am_gridcolor, "am_gridcolor", "8b8b 5a5a 2b2b", CVAR_ARCHIVE },
{ &am_xhaircolor, "am_xhaircolor", "8080 8080 8080", CVAR_ARCHIVE }, { &am_xhaircolor, "am_xhaircolor", "8080 8080 8080", CVAR_ARCHIVE },
{ &am_notseencolor, "am_notseencolor", "6c6c 6c6c 6c6c", CVAR_ARCHIVE }, { &am_notseencolor, "am_notseencolor", "6c6c 6c6c 6c6c", CVAR_ARCHIVE },
{ &am_key1color, "am_key1color", "0000 0000 9898", CVAR_ARCHIVE }, { &am_lockedcolor, "am_lockedcolor", "0000 0000 9898", CVAR_ARCHIVE },
{ &am_key2color, "am_key2color", "9898 0000 0000", CVAR_ARCHIVE },
{ &am_key3color, "am_key3color", "e8e8 d8d8 5454", CVAR_ARCHIVE },
/*
&am_key4color, "am_key4color", "0000 0000 9898", CVAR_ARCHIVE,
&am_key5color, "am_key5color", "9898 0000 0000", CVAR_ARCHIVE,
&am_key6color, "am_key6color", "e8e8 d8d8 5454", CVAR_ARCHIVE,
*/
{ &am_ovyourcolor, "am_ovyourcolor", "fcfc e8e8 d8d8", CVAR_ARCHIVE }, { &am_ovyourcolor, "am_ovyourcolor", "fcfc e8e8 d8d8", CVAR_ARCHIVE },
{ &am_ovwallcolor, "am_ovwallcolor", "0000 ffff 0000", CVAR_ARCHIVE }, { &am_ovwallcolor, "am_ovwallcolor", "0000 ffff 0000", CVAR_ARCHIVE },
{ &am_ovthingcolor, "am_ovthingcolor", "e8e8 8888 0000", CVAR_ARCHIVE }, { &am_ovthingcolor, "am_ovthingcolor", "e8e8 8888 0000", CVAR_ARCHIVE },
{ &am_ovotherwallscolor,"am_ovotherwallscolor", "0000 8888 4444", CVAR_ARCHIVE }, { &am_ovotherwallscolor,"am_ovotherwallscolor", "0000 8888 4444", CVAR_ARCHIVE },
{ &am_ovunseencolor, "am_ovunseencolor", "0000 2222 6e6e", CVAR_ARCHIVE }, { &am_ovunseencolor, "am_ovunseencolor", "0000 2222 6e6e", CVAR_ARCHIVE },
{ &teamplay, "teamplay", "0", CVAR_SERVERINFO },
{ &deathmatch, "deathmatch", "0", CVAR_SERVERINFO|CVAR_LATCH }, { &deathmatch, "deathmatch", "0", CVAR_SERVERINFO|CVAR_LATCH },
{ &dmflagsvar, "dmflags", "0", CVAR_SERVERINFO|CVAR_CALLBACK }, { &dmflagsvar, "dmflags", "0", CVAR_SERVERINFO|CVAR_CALLBACK },
{ &timelimit, "timelimit", "0", CVAR_SERVERINFO }, { &timelimit, "timelimit", "0", CVAR_SERVERINFO },
{ &fraglimit, "fraglimit", "0", CVAR_SERVERINFO }, { &fraglimit, "fraglimit", "0", CVAR_SERVERINFO },
{ &nobfgaim, "nobfgaim", "0", CVAR_SERVERINFO },
{ &autoaim, "autoaim", "5000", CVAR_USERINFO|CVAR_ARCHIVE }, { &autoaim, "autoaim", "5000", CVAR_USERINFO|CVAR_ARCHIVE },
{ &name, "name", "Player", CVAR_USERINFO|CVAR_ARCHIVE }, { &name, "name", "Player", CVAR_USERINFO|CVAR_ARCHIVE },
{ &color, "color", "4040 cfcf 0000", CVAR_USERINFO|CVAR_ARCHIVE }, { &color, "color", "4040 cfcf 0000", CVAR_USERINFO|CVAR_ARCHIVE },
{ &skin, "skin", "base", CVAR_USERINFO|CVAR_ARCHIVE },
{ &team, "team", "", CVAR_USERINFO|CVAR_ARCHIVE },
{ &gender, "gender", "male", CVAR_USERINFO|CVAR_ARCHIVE },
{ &boom_friction, "var_friction", "1", CVAR_SERVERINFO },
{ &boom_pushers, "var_pushers", "1", CVAR_SERVERINFO },
{ &splashfactor, "splashfactor", "1.0", CVAR_SERVERINFO|CVAR_CALLBACK },
{ NULL } { NULL }
}; };

View file

@ -61,7 +61,8 @@ typedef enum
ga_completed, ga_completed,
ga_victory, ga_victory,
ga_worlddone, ga_worlddone,
ga_screenshot ga_screenshot,
ga_fullconsole
} gameaction_t; } gameaction_t;

View file

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

View file

@ -128,7 +128,7 @@ weaponinfo_t weaponinfo[NUMWEAPONS] =
int num_items; int num_items;
// [RH] Guess what. These next three functions are from Quake2: // [RH] Guess what. These next three functions are from Quake2:
// game/g_items.c // g_items.c
/* /*
=============== ===============
@ -140,7 +140,7 @@ gitem_t *GetItemByIndex (int index)
if (index == 0 || index >= num_items) if (index == 0 || index >= num_items)
return NULL; return NULL;
return &ItemList[index]; return &itemlist[index];
} }
@ -150,19 +150,15 @@ FindItemByClassname
=============== ===============
*/ */
gitem_t *FindItemByClassname (char *classname) gitem_t *FindItemByClassname (const char *classname)
{ {
int i; int i;
gitem_t *it; gitem_t *it;
it = ItemList; it = itemlist;
for (i=0 ; i<num_items ; i++, it++) for (i = 0; i < num_items; i++, it++)
{ if (it->classname && !stricmp(it->classname, classname))
if (!it->classname)
continue;
if (!stricmp(it->classname, classname))
return it; return it;
}
return NULL; return NULL;
} }
@ -173,19 +169,15 @@ FindItem
=============== ===============
*/ */
gitem_t *FindItem (char *pickup_name) gitem_t *FindItem (const char *pickup_name)
{ {
int i; int i;
gitem_t *it; gitem_t *it;
it = ItemList; it = itemlist;
for (i=0 ; i<num_items ; i++, it++) for (i = 0; i < num_items; i++, it++)
{ if (it->pickup_name && !stricmp(it->pickup_name, pickup_name))
if (!it->pickup_name)
continue;
if (!stricmp(it->pickup_name, pickup_name))
return it; return it;
}
return NULL; return NULL;
} }
@ -195,7 +187,7 @@ gitem_t *FindItem (char *pickup_name)
// Used mainly by the give command. Hopefully will // Used mainly by the give command. Hopefully will
// become more general-purpose later. // become more general-purpose later.
// (Yes, this was inspired by Quake 2) // (Yes, this was inspired by Quake 2)
gitem_t ItemList[] = { gitem_t itemlist[] = {
{ {
NULL NULL
}, // leave index 0 alone }, // leave index 0 alone
@ -240,6 +232,16 @@ gitem_t ItemList[] = {
"Fist" "Fist"
}, },
{
"weapon_chainsaw",
NULL,
NULL,
IT_WEAPON,
wp_chainsaw,
0,
"Chainsaw"
},
{ {
"weapon_pistol", "weapon_pistol",
NULL, NULL,
@ -260,6 +262,16 @@ gitem_t ItemList[] = {
"Shotgun" "Shotgun"
}, },
{
"weapon_supershotgun",
NULL,
NULL,
IT_WEAPON,
wp_supershotgun,
0,
"Super Shotgun"
},
{ {
"weapon_chaingun", "weapon_chaingun",
NULL, NULL,
@ -300,26 +312,6 @@ gitem_t ItemList[] = {
"BFG9000" "BFG9000"
}, },
{
"weapon_chainsaw",
NULL,
NULL,
IT_WEAPON,
wp_chainsaw,
0,
"Chainsaw"
},
{
"weapon_supershotgun",
NULL,
NULL,
IT_WEAPON,
wp_supershotgun,
0,
"Super Shotgun"
},
{ {
"ammo_bullets", "ammo_bullets",
NULL, NULL,
@ -367,7 +359,7 @@ gitem_t ItemList[] = {
"item_invulnerability", "item_invulnerability",
NULL, NULL,
NULL, NULL,
IT_POWER, IT_POWERUP,
pw_invulnerability, pw_invulnerability,
0, 0,
"Invulnerability" "Invulnerability"
@ -377,7 +369,7 @@ gitem_t ItemList[] = {
"item_berserk", "item_berserk",
NULL, NULL,
NULL, NULL,
IT_POWER, IT_POWERUP,
pw_strength, pw_strength,
0, 0,
"Berserk" "Berserk"
@ -387,7 +379,7 @@ gitem_t ItemList[] = {
"item_invisibility", "item_invisibility",
NULL, NULL,
NULL, NULL,
IT_POWER, IT_POWERUP,
pw_invisibility, pw_invisibility,
0, 0,
"Partial Invisibility" "Partial Invisibility"
@ -397,7 +389,7 @@ gitem_t ItemList[] = {
"item_ironfeet", "item_ironfeet",
NULL, NULL,
NULL, NULL,
IT_POWER, IT_POWERUP,
pw_ironfeet, pw_ironfeet,
0, 0,
"Iron Feet" "Iron Feet"
@ -407,7 +399,7 @@ gitem_t ItemList[] = {
"item_allmap", "item_allmap",
NULL, NULL,
NULL, NULL,
IT_POWER, IT_POWERUP,
pw_allmap, pw_allmap,
0, 0,
"Computer Map" "Computer Map"
@ -417,7 +409,7 @@ gitem_t ItemList[] = {
"item_visor", "item_visor",
NULL, NULL,
NULL, NULL,
IT_POWER, IT_POWERUP,
pw_infrared, pw_infrared,
0, 0,
"Light Amplification Visor" "Light Amplification Visor"
@ -493,5 +485,5 @@ gitem_t ItemList[] = {
void InitItems (void) void InitItems (void)
{ {
num_items = sizeof(ItemList)/sizeof(ItemList[0]) - 1; num_items = sizeof(itemlist)/sizeof(itemlist[0]) - 1;
} }

View file

@ -25,13 +25,10 @@
#ifndef __D_MAIN__ #ifndef __D_MAIN__
#define __D_MAIN__ #define __D_MAIN__
#include <setjmp.h>
#include "d_event.h" #include "d_event.h"
#define MAXWADFILES 20
extern char* wadfiles[MAXWADFILES];
void D_AddFile (char *file); void D_AddFile (char *file);
@ -47,7 +44,7 @@ void D_DoomMain (void);
// Called by IO functions when input is detected. // Called by IO functions when input is detected.
void D_PostEvent (const event_t* ev); void D_PostEvent (const event_t* ev);
// //
// BASE LEVEL // BASE LEVEL
@ -57,4 +54,13 @@ void D_PageDrawer (void);
void D_AdvanceDemo (void); void D_AdvanceDemo (void);
void D_StartTitle (void); void D_StartTitle (void);
// [RH] Set this to something to draw an icon during the next screen refresh.
extern char *D_DrawIcon;
// [RH] Allow for recoverable errors to drop to console only
extern char errortext[2048];
extern jmp_buf errorjmp;
extern BOOL errorjmpable;
#endif #endif

View file

@ -1,5 +1,6 @@
#include <math.h> #include <math.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h>
#include "doomtype.h" #include "doomtype.h"
#include "doomdef.h" #include "doomdef.h"
@ -11,28 +12,43 @@
#include "v_video.h" #include "v_video.h"
#include "i_system.h" #include "i_system.h"
#include "r_draw.h" #include "r_draw.h"
#include "r_state.h"
#include "st_stuff.h"
extern BOOL st_firsttime; extern BOOL st_firsttime;
cvar_t *autoaim; cvar_t *autoaim;
cvar_t *name; cvar_t *name;
cvar_t *color; cvar_t *color;
cvar_t *skin;
cvar_t *team;
cvar_t *gender;
static userinfo_t userinfos[MAXPLAYERS]; int D_GenderToInt (const char *gender)
{
if (!stricmp (gender, "female"))
return GENDER_FEMALE;
else if (!stricmp (gender, "neuter"))
return GENDER_NEUTER;
else
return GENDER_MALE;
}
void D_SetupUserInfo (void) void D_SetupUserInfo (void)
{ {
int i; int i;
userinfo_t *coninfo = &players[consoleplayer].userinfo;
for (i = 0; i < MAXPLAYERS; i++) { for (i = 0; i < MAXPLAYERS; i++)
memset (&userinfos[i], 0, sizeof(userinfo_t)); memset (&players[i].userinfo, 0, sizeof(userinfo_t));
players[i].userinfo = &userinfos[i];
}
strncpy (userinfos[consoleplayer].netname, name->string, MAXPLAYERNAME); strncpy (coninfo->netname, name->string, MAXPLAYERNAME);
userinfos[consoleplayer].aimdist = (fixed_t)(autoaim->value * 16384.0); strncpy (coninfo->team, team->string, MAXPLAYERNAME);
userinfos[consoleplayer].color = V_GetColorFromString (NULL, color->string); coninfo->aimdist = (fixed_t)(autoaim->value * 16384.0);
R_BuildPlayerTranslation (consoleplayer, userinfos[consoleplayer].color); coninfo->color = V_GetColorFromString (NULL, color->string);
coninfo->skin = R_FindSkin (skin->string);
coninfo->gender = D_GenderToInt (gender->string);
R_BuildPlayerTranslation (consoleplayer, coninfo->color);
} }
void D_UserInfoChanged (cvar_t *cvar) void D_UserInfoChanged (cvar_t *cvar)
@ -122,12 +138,15 @@ void D_WriteUserInfoStrings (int i, byte **stream)
if (i >= MAXPLAYERS) { if (i >= MAXPLAYERS) {
WriteByte (0, stream); WriteByte (0, stream);
} else { } else {
userinfo_t *info = players[i].userinfo; userinfo_t *info = &players[i].userinfo;
sprintf (*stream, "\\name\\%s\\autoaim\\%g\\color\\%x %x %x", sprintf (*stream, "\\name\\%s\\autoaim\\%g\\color\\%x %x %x\\skin\\%s\\team\\%s\\gender\\%s",
info->netname, info->netname,
(double)info->aimdist / 16384.0, (double)info->aimdist / 16384.0,
RPART(info->color), GPART(info->color), BPART(info->color) RPART(info->color), GPART(info->color), BPART(info->color),
skins[info->skin].name, info->team,
info->gender == GENDER_FEMALE ? "female" :
info->gender == GENDER_NEUTER ? "neuter" : "male"
); );
} }
@ -136,7 +155,7 @@ void D_WriteUserInfoStrings (int i, byte **stream)
void D_ReadUserInfoStrings (int i, byte **stream, BOOL update) void D_ReadUserInfoStrings (int i, byte **stream, BOOL update)
{ {
userinfo_t *info = players[i].userinfo; userinfo_t *info = &players[i].userinfo;
byte *ptr = *stream; byte *ptr = *stream;
byte *breakpt; byte *breakpt;
byte *value; byte *value;
@ -163,10 +182,27 @@ void D_ReadUserInfoStrings (int i, byte **stream, BOOL update)
if (update) if (update)
Printf ("%s is now known as %s\n", oldname, info->netname); Printf ("%s is now known as %s\n", oldname, info->netname);
} else if (!stricmp (ptr, "team")) {
strncpy (info->team, value, MAXPLAYERNAME);
info->team[MAXPLAYERNAME] = 0;
if (update) {
if (info->team[0])
Printf ("%s joined the %s team\n", info->netname, info->team);
else
Printf ("%s is not on a team\n", info->netname);
}
} else if (!stricmp (ptr, "color")) { } else if (!stricmp (ptr, "color")) {
info->color = V_GetColorFromString (NULL, value); info->color = V_GetColorFromString (NULL, value);
R_BuildPlayerTranslation (i, info->color); R_BuildPlayerTranslation (i, info->color);
st_firsttime = true; st_firsttime = true;
} else if (!stricmp (ptr, "skin")) {
info->skin = R_FindSkin (value);
if (players[i].mo)
players[i].mo->sprite = skins[info->skin].sprite;
ST_loadGraphics ();
st_firsttime = true;
} else if (!stricmp (ptr, "gender")) {
info->gender = D_GenderToInt (value);
} }
*(value - 1) = '\\'; *(value - 1) = '\\';

View file

@ -5,12 +5,19 @@
extern cvar_t *autoaim; extern cvar_t *autoaim;
#define MAXPLAYERNAME 23 #define MAXPLAYERNAME 15
#define GENDER_MALE 0
#define GENDER_FEMALE 1
#define GENDER_NEUTER 2
struct userinfo_s { struct userinfo_s {
char netname[MAXPLAYERNAME+1]; char netname[MAXPLAYERNAME+1];
char team[MAXPLAYERNAME+1];
fixed_t aimdist; fixed_t aimdist;
int color; int color;
int skin;
int gender;
}; };
typedef struct userinfo_s userinfo_t; typedef struct userinfo_s userinfo_t;

78
code/docs/README.Carmack Normal file
View file

@ -0,0 +1,78 @@
Here it is, at long last. The DOOM source code is released for your
non-profit use. You still need real DOOM data to work with this code.
If you don't actually own a real copy of one of the DOOMs, you should
still be able to find them at software stores.
Many thanks to Bernd Kreimeier for taking the time to clean up the
project and make sure that it actually works. Projects tends to rot if
you leave it alone for a few years, and it takes effort for someone to
deal with it again.
The bad news: this code only compiles and runs on linux. We couldn't
release the dos code because of a copyrighted sound library we used
(wow, was that a mistake -- I write my own sound code now), and I
honestly don't even know what happened to the port that microsoft did
to windows.
Still, the code is quite portable, and it should be straightforward to
bring it up on just about any platform.
I wrote this code a long, long time ago, and there are plenty of things
that seem downright silly in retrospect (using polar coordinates for
clipping comes to mind), but overall it should still be a usefull base
to experiment and build on.
The basic rendering concept -- horizontal and vertical lines of constant
Z with fixed light shading per band was dead-on, but the implementation
could be improved dramatically from the original code if it were
revisited. The way the rendering proceded from walls to floors to
sprites could be collapsed into a single front-to-back walk of the bsp
tree to collect information, then draw all the contents of a subsector
on the way back up the tree. It requires treating floors and ceilings
as polygons, rather than just the gaps between walls, and it requires
clipping sprite billboards into subsector fragments, but it would be
The Right Thing.
The movement and line of sight checking against the lines is one of the
bigger misses that I look back on. It is messy code that had some
failure cases, and there was a vastly simpler (and faster) solution
sitting in front of my face. I used the BSP tree for rendering things,
but I didn't realize at the time that it could also be used for
environment testing. Replacing the line of sight test with a bsp line
clip would be pretty easy. Sweeping volumes for movement gets a bit
tougher, and touches on many of the challenges faced in quake / quake2
with edge bevels on polyhedrons.
Some project ideas:
Port it to your favorite operating system.
Add some rendering features -- transparency, look up / down, slopes,
etc.
Add some game features -- weapons, jumping, ducking, flying, etc.
Create a packet server based internet game.
Create a client / server based internet game.
Do a 3D accelerated version. On modern hardware (fast pentium + 3DFX)
you probably wouldn't even need to be clever -- you could just draw the
entire level and get reasonable speed. With a touch of effort, it should
easily lock at 60 fps (well, there are some issues with DOOM's 35 hz
timebase...). The biggest issues would probably be the non-power of two
texture sizes and the walls composed of multiple textures.
I don't have a real good guess at how many people are going to be
playing with this, but if significant projects are undertaken, it would
be cool to see a level of community cooperation. I know that most early
projects are going to be rough hacks done in isolation, but I would be
very pleased to see a coordinated 'net release of an improved, backwards
compatable version of DOOM on multiple platforms next year.
Have fun.
John Carmack
12-23-97

136
code/docs/README.LZO Normal file
View file

@ -0,0 +1,136 @@
-----BEGIN PGP SIGNED MESSAGE-----
============================================================================
miniLZO -- mini subset of the LZO real-time data compression library
============================================================================
Author : Markus Franz Xaver Johannes Oberhumer
<markus.oberhumer@jk.uni-linz.ac.at>
http://wildsau.idv.uni-linz.ac.at/mfx/lzo.html
Version : 1.04
Date : 15-Mar-1998
I've created miniLZO for projects where it is inconvenient to
include (or require) the full LZO source code just because you
want to add a little bit of data compression to your application.
miniLZO implements the LZO1X-1 compressor and both the standard and
safe LZO1X decompressor. Apart from fast compression it also useful
for situations where you want to use pre-compressed data files (which
must have been compressed with LZO1X-999).
miniLZO consists of one C source file and two header files:
minilzo.c
minilzo.h
lzoconf.h
To use miniLZO just copy these files into your source directory, add
minilzo.c to your Makefile and #include minilzo.h from your program.
Note: you also must distribute this file (`README.LZO') with your project.
minilzo.o compiles to about 6 kB (using gcc or Watcom C on a i386), and
the sources are about 14 kB when packed with zip - so there's no more
excuse that your application doesn't support data compression :-)
For more information, documentation, example programs and other support
files (like Makefiles and build scripts) please download the full LZO
package from
http://wildsau.idv.uni-linz.ac.at/mfx/lzo.html
Have fun,
Markus
P.S. minilzo.c is generated automatically from the LZO sources and
therefore functionality is completely identical
Appendix A: building miniLZO
----------------------------
miniLZO is written such a way that it should compile and run
out-of-the-box on most machines.
If you are running on a very unusual architecture and lzo_init() fails then
you should first recompile with `-DLZO_DEBUG' to see what causes the failure.
The most probable case is something like `sizeof(char *) != sizeof(long)'.
After identifying the problem you can compile by adding some defines
like `-DSIZEOF_CHAR_P=8' to your Makefile.
The best solution is (of course) using Autoconf - if your project uses
Autoconf anyway just add `-DMINILZO_HAVE_CONFIG_H' to your compiler
flags when compiling minilzo.c. See the LZO distribution for an example
how to set up configure.in.
Appendix B: list of public functions available in miniLZO
---------------------------------------------------------
Library initialization
lzo_init()
Compression
lzo1x_1_compress()
Decompression
lzo1x_decompress()
lzo1x_decompress_safe()
Checksum functions
lzo_adler32()
Version functions
lzo_version()
lzo_version_string()
lzo_version_date()
Portable (but slow) string functions
lzo_memcmp()
lzo_memcpy()
lzo_memmove()
lzo_memset()
Appendix C: suggested macros for `configure.in' when using Autoconf
-------------------------------------------------------------------
Checks for typedefs and structures
AC_CHECK_TYPE(ptrdiff_t,long)
AC_TYPE_SIZE_T
AC_CHECK_SIZEOF(unsigned short)
AC_CHECK_SIZEOF(unsigned)
AC_CHECK_SIZEOF(unsigned long)
AC_CHECK_SIZEOF(char *)
AC_CHECK_SIZEOF(ptrdiff_t)
AC_CHECK_SIZEOF(size_t)
Checks for compiler characteristics
AC_C_CONST
Checks for library functions
AC_CHECK_FUNCS(memcmp memcpy memmove memset)
Appendix D: Copyright
---------------------
LZO and miniLZO are Copyright (C) 1996, 1997, 1998
Markus Franz Xaver Johannes Oberhumer
LZO and miniLZO are distributed under the terms of the GNU General
Public License (GPL). See the file COPYING.
Special licenses for commercial and other applications which
are not willing to accept the GNU General Public License
are available by contacting the author.
-----BEGIN PGP SIGNATURE-----
Version: 2.6.3ia
Charset: noconv
iQCVAwUBNQv2B210fyLu8beJAQFC8QQAzxteZ5VRs+iDmBz40HQmsfr+RZVnyccK
9vJ7BtFKaxAwpfa6AzothnHa1zmSaKqbltLzAQHQ6elAIYegELdpV9HRHddx0Q/y
ATDhaVlsSGJLiOazPRBpJq6ne0J9phIH9n2hZmNQFDTm3bKmcm6PYVxt39iDVgg0
hMwf5skDc+k=
=qpUY
-----END PGP SIGNATURE-----

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