ZDoom 1.14a.

This commit is contained in:
Randy Heit 1998-07-26 00:00:00 +00:00
parent 58c4b68204
commit 25f75d4f53
56 changed files with 2709 additions and 1177 deletions

View file

@ -261,7 +261,8 @@ void C_BackupCVars (void)
cvar_t *cvar = CVars;
while (cvar) {
if ((cvar->flags & CVAR_SERVERINFO) || (cvar->flags & CVAR_DEMOSAVE)) {
if (((cvar->flags & CVAR_SERVERINFO) || (cvar->flags & CVAR_DEMOSAVE))
&& !(cvar->flags & CVAR_LATCH)) {
if (backup == &CVarBackups[MAX_DEMOCVARS])
I_Error ("C_BackupDemoCVars: Too many cvars to save (%d)", MAX_DEMOCVARS);
backup->name = copystring (cvar->name);

View file

@ -179,6 +179,10 @@ BOOL FileExists (char *filename)
{
FILE *f;
// [RH] Empty filenames are never there
if (*filename == 0)
return false;
f = fopen (filename, "r");
if (!f)
return false;

View file

@ -1,6 +1,6 @@
#ifndef __D_DEHACK_H__
#define __D_DEHACK_H__
void DoDehPatch (char *patchfile);
void DoDehPatch (char *patchfile, BOOL autoloading);
#endif //__D_DEHACK_H__

View file

@ -700,16 +700,29 @@ donewithtext:
}
void DoDehPatch (char *patchfile)
void DoDehPatch (char *patchfile, BOOL autoloading)
{
char file[256];
int cont;
int filelen;
int lump;
BackUpData ();
PatchFile = NULL;
if (patchfile) {
lump = W_CheckNumForName ("DEHACKED");
if (lump >= 0 && autoloading) {
// Execute the DEHACKED lump as a patch.
filelen = W_LumpLength (lump);
if ( (PatchFile = malloc (filelen + 1)) ) {
W_ReadLump (lump, PatchFile);
} else {
Printf ("Not enough memory to apply internal DeHackEd patch\n");
return;
}
} else if (patchfile) {
// Try to execute patchfile as a patch.
FILE *deh;
strcpy (file, patchfile);
@ -728,22 +741,9 @@ void DoDehPatch (char *patchfile)
return;
}
} else {
int lump = W_CheckNumForName ("DEHACKED");
if (lump < 0)
return;
filelen = W_LumpLength (lump);
if ( (PatchFile = malloc (filelen + 1)) ) {
W_ReadLump (lump, PatchFile);
} else {
Printf ("Not enough memory to apply internal DeHackEd patch\n");
// Nothing to do.
return;
}
}
if (!PatchFile)
return;
// End lump with a NULL for our parser
PatchFile[filelen] = 0;

View file

@ -547,7 +547,11 @@ void D_AdvanceDemo (void)
// This cycles through the demo sequences.
// FIXME - version dependend demo numbers?
//
void D_DoAdvanceDemo (void)
// [RH] If M_DemoNoPlay is true, then any
// demos are skipped.
extern M_DemoNoPlay;
void D_DoAdvanceDemo (void)
{
players[consoleplayer].playerstate = PST_LIVE; // not reborn
advancedemo = false;
@ -575,16 +579,20 @@ void D_AdvanceDemo (void)
S_StartMusic ("d_intro");
break;
case 1:
if (!M_DemoNoPlay) {
G_DeferedPlayDemo ("demo1");
break;
}
case 2:
pagetic = 200;
gamestate = GS_DEMOSCREEN;
pagename = "CREDIT";
break;
case 3:
if (!M_DemoNoPlay) {
G_DeferedPlayDemo ("demo2");
break;
}
case 4:
gamestate = GS_DEMOSCREEN;
if ( gamemode == commercial)
@ -604,10 +612,16 @@ void D_AdvanceDemo (void)
}
break;
case 5:
if (M_DemoNoPlay)
advancedemo = true;
else
G_DeferedPlayDemo ("demo3");
break;
// THE DEFINITIVE DOOM Special Edition demo
case 6:
if (M_DemoNoPlay)
advancedemo = true;
else
G_DeferedPlayDemo ("demo4");
break;
}
@ -1094,12 +1108,21 @@ void D_DoomMain (void)
// [RH] Apply any DeHackEd patch
{
int hack;
cvar_t *autopatch;
hack = M_CheckParm ("-deh");
if (hack && hack < myargc - 1)
DoDehPatch (myargv[hack + 1]);
// Use patch from command line
DoDehPatch (myargv[hack + 1], false);
else {
autopatch = cvar ("def_patch", "", CVAR_ARCHIVE);
if (FileExists (autopatch->string))
// Use patch specified by def_patch.
// (Any patches in a PWAD take precedence.)
DoDehPatch (autopatch->string, true);
else
DoDehPatch (NULL); // See if there's a patch in a PWAD
DoDehPatch (NULL, true); // See if there's a patch in a PWAD
}
}
// [RH] Now that all text strings are set up,
@ -1138,7 +1161,8 @@ void D_DoomMain (void)
// but w/o all the lumps of the registered version.
if (gamemode == registered || gamemode == retail)
for (i = 0;i < 23; i++)
if (W_CheckNumForName(name[i])<0)
if (W_CheckNumForName(name[i])<0 &&
(W_CheckNumForName)(name[i],ns_sprites)<0)
I_Error("\nThis is not the registered version.");
}

View file

@ -986,7 +986,6 @@ void Net_DoCommand (int type, byte **stream, int player)
case DEM_CHANGEMAP:
// Change to another map without disconnecting other players
s = ReadString (stream);
strncpy (level.mapname, s, 8);
strncpy (level.nextmap, s, 8);
// Using LEVEL_NOINTERMISSION tends to throw the game out of sync.
level.flags |= LEVEL_CHANGEMAPCHEAT;

View file

@ -32,7 +32,7 @@ void ReplaceString (char **ptr, char *str);
// Misc. other strings.
#define SAVEGAMENAME "doomsav"
#define SAVEGAMENAME "zdoomsv"
// QuitDOOM messages
#define NUM_QUITMESSAGES 14

View file

@ -133,7 +133,7 @@ void F_Ticker (void)
// check for skipping
// [RH] Non-commercial can be skipped now, too
if (finalecount > 50) {
if (finalecount > 50 && finalestage != 1) {
// go on to the next level
// [RH] or just reveal the entire message if we're still ticking it
for (i=0 ; i<MAXPLAYERS ; i++)
@ -191,7 +191,11 @@ void F_TextWrite (void)
int cy;
// erase the entire screen to a tiled background
V_FlatFill (0,0,screens[0].width,screens[0].height,&screens[0],W_CacheLumpName (finaleflat , PU_CACHE));
{
int lump = R_FlatNumForName (finaleflat) + firstflat;
V_FlatFill (0,0,screens[0].width,screens[0].height,&screens[0],
W_CacheLumpNum (lump, PU_CACHE));
}
V_MarkRect (0, 0, screens[0].width, screens[0].height);
// draw some of the text onto the screen

View file

@ -1047,7 +1047,7 @@ void G_DoLoadGame (void)
// skip the description field
memset (vcheck,0,sizeof(vcheck));
sprintf (vcheck,"version %i",VERSION);
sprintf (vcheck,"version %ia",VERSION);
if (strcmp (save_p, vcheck))
return; // bad version
save_p += VERSIONSIZE;
@ -1116,7 +1116,7 @@ void G_DoSaveGame (void)
memcpy (save_p, description, SAVESTRINGSIZE);
save_p += SAVESTRINGSIZE;
memset (name2,0,sizeof(name2));
sprintf (name2,"version %i",VERSION);
sprintf (name2,"version %ia",VERSION);
memcpy (save_p, name2, VERSIONSIZE);
save_p += VERSIONSIZE;
@ -1583,8 +1583,17 @@ void G_TimeDemo (char* name)
===================
*/
extern cvar_t *name;
extern cvar_t *autoaim;
extern cvar_t *color;
BOOL G_CheckDemoStatus (void)
{
// [RH] Restore the player's userinfo settings.
D_UserInfoChanged (name);
D_UserInfoChanged (autoaim);
D_UserInfoChanged (color);
if (timingdemo)
{
extern int starttime;

View file

@ -88,6 +88,14 @@ void G_ParseMapInfo (void)
mapinfo = W_CacheLumpNum (lump, PU_CACHE);
while ( (data = COM_Parse (mapinfo)) ) {
if (com_token[0] == ';') {
// Handle comments from Hexen MAPINFO lumps
while (*mapinfo && *mapinfo != ';')
mapinfo++;
while (*mapinfo && *mapinfo != '\n')
mapinfo++;
continue;
}
if (!stricmp (com_token, "map")) {
// map <MAPNAME> <Nice Name>
if (levelindex > -1) {
@ -97,6 +105,12 @@ void G_ParseMapInfo (void)
levelflags = 0;
clusterindex = -1;
data = COM_Parse (data);
if (IsNum (com_token)) {
// Handle Hexen MAPINFO map commands
int map = atoi (com_token);
sprintf (com_token, "MAP%02u", map);
SKYFLATNAME[5] = 0;
}
if ((levelindex = FindWadLevelInfo (com_token)) == -1)
{
levelindex = numwadlevelinfos++;
@ -110,7 +124,8 @@ void G_ParseMapInfo (void)
mapinfo = data;
} else if (levelindex > -1) {
if (!stricmp (com_token, "levelnum")) {
if (!stricmp (com_token, "levelnum") ||
!stricmp (com_token, "warptrans")) {
// levelnum <levelnum>
mapinfo = COM_Parse (data);
levelinfo->levelnum = atoi (com_token);
@ -118,6 +133,11 @@ void G_ParseMapInfo (void)
} else if (!stricmp (com_token, "next")) {
// next <MAPNAME>
mapinfo = COM_Parse (data);
if (IsNum (com_token)) {
// Handle Hexen MAPINFO next entries
int map = atoi (com_token);
sprintf (com_token, "MAP%02u", map);
}
strncpy (levelinfo->nextmap, com_token, 8);
} else if (!stricmp (com_token, "secretnext")) {
@ -226,6 +246,20 @@ void G_ParseMapInfo (void)
mapinfo = data;
levelflags = (levelflags & (~LEVEL_SPECACTIONSMASK)) | LEVEL_SPECLOWERFLOOR;
} else if (!stricmp (com_token, "lightning")) {
// lightning
mapinfo = data;
} else if (!stricmp (com_token, "cdtrack") ||
!stricmp (com_token, "fadetable") ||
!stricmp (com_token, "cd_start_track") ||
!stricmp (com_token, "cd_end1_track") ||
!stricmp (com_token, "cd_end2_track") ||
!stricmp (com_token, "cd_end3_track") ||
!stricmp (com_token, "cd_intermission_track") ||
!stricmp (com_token, "cd_title_track")) {
mapinfo = COM_Parse (data);
}
}
@ -360,7 +394,7 @@ void G_InitNew (char *mapname)
I_Error ("Could not start map %s\n", mapname);
}
if (gameskill->value == sk_nightmare || dmflags & DF_MONSTERS_RESPAWN )
if ((gameskill->value == sk_nightmare) || (dmflags & DF_MONSTERS_RESPAWN) )
respawnmonsters = true;
else
respawnmonsters = false;
@ -450,7 +484,9 @@ void G_DoCompleted (void)
strncpy (wminfo.lname0, level.info->pname, 8);
strncpy (wminfo.current, level.mapname, 8);
if (deathmatch->value && dmflags & DF_SAME_LEVEL) {
if (deathmatch->value &&
(dmflags & DF_SAME_LEVEL) &&
!(level.flags & LEVEL_CHANGEMAPCHEAT)) {
strncpy (wminfo.next, level.mapname, 8);
strncpy (wminfo.lname1, level.info->pname, 8);
} else {
@ -546,6 +582,17 @@ void G_DoLoadLevel (void)
players[i].fragcount = 0;
}
// initialize the msecnode_t freelist. phares 3/25/98
// any nodes in the freelist are gone by now, cleared
// by Z_FreeTags() when the previous level ended or player
// died.
{
extern msecnode_t *headsecnode; // phares 3/25/98
headsecnode = NULL;
}
S_ClearAmbients (); // [RH] Clear all ambient sounds
P_SetupLevel (level.mapname);
displayplayer = consoleplayer; // view the guy you are playing
@ -715,6 +762,26 @@ level_info_t *FindLevelInfo (char *mapname)
return FindDefLevelInfo (mapname);
}
level_info_t *FindLevelByNum (int num)
{
{
int i;
for (i = 0; i < numwadlevelinfos; i++)
if (wadlevelinfos[i].levelnum == num)
return (level_info_t *)(wadlevelinfos + i);
}
{
level_info_t *i = LevelInfos;
while (i->level_name) {
if (i->levelnum == num)
return i;
i++;
}
return NULL;
}
}
static cluster_info_t *FindDefClusterInfo (int cluster)
{
cluster_info_t *i;

View file

@ -126,6 +126,7 @@ void G_SetLevelStrings (void);
cluster_info_t *FindClusterInfo (int cluster);
level_info_t *FindLevelInfo (char *mapname);
level_info_t *FindLevelByNum (int num);
char *CalcMapName (int episode, int level);

View file

@ -83,59 +83,29 @@ extern BOOL automapactive;
static BOOL headsupactive = false;
const char english_shiftxform[] =
{
0,
1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
31,
' ', '!', '"', '#', '$', '%', '&',
'"', // shift-'
'(', ')', '*', '+',
'<', // shift-,
'_', // shift--
'>', // shift-.
'?', // shift-/
')', // shift-0
'!', // shift-1
'@', // shift-2
'#', // shift-3
'$', // shift-4
'%', // shift-5
'^', // shift-6
'&', // shift-7
'*', // shift-8
'(', // shift-9
':',
':', // shift-;
'<',
'+', // shift-=
'>', '?', '@',
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
'[', // shift-[
'!', // shift-backslash - OH MY GOD DOES WATCOM SUCK
']', // shift-]
'"', '_',
'\'', // shift-`
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
'{', '|', '}', '~', 127
};
void HU_Init(void)
{
int i;
int j;
char buffer[9];
char *tplate;
int sub;
// load the heads-up font
j = HU_FONTSTART;
// [RH] Quick hack to handle the FONTA of Heretic and Hexen
if (W_CheckNumForName ("FONTA01") >= 0) {
tplate = "FONTA%02u";
sub = HU_FONTSTART - 1;
} else {
tplate = "STCFN%.3d";
sub = 0;
}
for (i=0;i<HU_FONTSIZE;i++)
{
sprintf(buffer, "STCFN%.3d", j++);
sprintf(buffer, tplate, j++ - sub);
hu_font[i] = (patch_t *) W_CacheLumpName(buffer, PU_STATIC);
}
}
@ -306,8 +276,7 @@ BOOL HU_Responder (event_t *ev)
}
else
{
if (shiftdown || (c >= 'a' && c <= 'z'))
c = english_shiftxform[c];
c = toupper (c);
eatkey = HUlib_keyInIText(&w_chat, c);

View file

@ -74,7 +74,9 @@ LPDIRECTINPUTDEVICE g_pKey;
LPDIRECTINPUTDEVICE g_pMouse;
//Other globals
int MouseCurX,MouseCurY,GDx,GDy;
int GDx,GDy;
extern int ConsoleState;
cvar_t *i_remapkeypad;
cvar_t *usejoystick;
@ -103,9 +105,15 @@ static const byte Convert []={
};
// Convert DIK_* code to ASCII using user keymap (built at run-time)
static byte Convert2[256];
// New on 19.7.1998 - Now has 8 tables for each possible combination
// of CTRL, ALT, and SHIFT.
static byte Convert2[256][8];
static BOOL altdown = FALSE;
#define SHIFT_SHIFT 0
#define CTRL_SHIFT 1
#define ALT_SHIFT 2
static BOOL altdown, shiftdown, ctrldown;
LRESULT CALLBACK WndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
@ -143,6 +151,18 @@ LRESULT CALLBACK WndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
event.data1 = DIK_LALT;
D_PostEvent (&event);
}
if (shiftdown) {
shiftdown = FALSE;
event.type = ev_keyup;
event.data1 = DIK_LSHIFT;
D_PostEvent (&event);
}
if (ctrldown) {
ctrldown = FALSE;
event.type = ev_keyup;
event.data1 = DIK_LCONTROL;
D_PostEvent (&event);
}
havefocus = FALSE;
if (!paused)
S_PauseSound ();
@ -194,15 +214,21 @@ LRESULT CALLBACK WndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
break;
case VK_TAB:
event.data1 = DIK_TAB;
event.data2 = '\t';
event.data3 = Convert2[DIK_TAB][(shiftdown << SHIFT_SHIFT) |
(ctrldown << CTRL_SHIFT) |
(altdown << ALT_SHIFT)];
break;
case VK_NUMLOCK:
event.data1 = DIK_NUMLOCK;
break;
case VK_SHIFT:
event.data1 = KEY_LSHIFT;
shiftdown = (event.type == ev_keydown);
break;
case VK_CONTROL:
event.data1 = KEY_LCTRL;
ctrldown = (event.type == ev_keydown);
break;
}
if (event.data1)
@ -221,6 +247,7 @@ LRESULT CALLBACK WndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
WPARAM cmdType = wParam & 0xfff0;
// Prevent activation of the window menu with Alt-Space
if (cmdType != SC_KEYMENU)
return DefWindowProc (hWnd, message, wParam, lParam);
}
@ -249,10 +276,19 @@ LRESULT CALLBACK WndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
static void BuildCvt2Table (void)
{
byte vk2scan[256];
int i;
memset (vk2scan, 0, 256);
for (i = 0; i < 256; i++)
Convert2[i] = tolower ((byte)MapVirtualKey (MapVirtualKey (i, 1), 2));
vk2scan[MapVirtualKey (i, 1)] = i;
vk2scan[0] = 0;
for (i = 0; i < 256; i++) {
int code = VkKeyScan ((TCHAR)i);
Convert2[vk2scan[code & 0xff]][(code >> 8) & 7] = i;
}
}
/****** Stuff from Andy Bay's myjoy.c ******/
@ -804,7 +840,6 @@ static void KeyRead (void) {
event.type = ev_keyup;
}
event.data3 = Convert2[key];
switch (key) {
case DIK_NUMPADENTER: // These keys always translated
key = DIK_RETURN;
@ -821,7 +856,9 @@ static void KeyRead (void) {
key = 0;
break;
default:
if (i_remapkeypad->value) {
// Don't remap the keypad if the console is accepting input.
if (i_remapkeypad->value &&
ConsoleState != 1 && ConsoleState != 2) {
switch (key) {
case DIK_NUMPAD4:
key = DIK_LEFT;
@ -860,7 +897,9 @@ static void KeyRead (void) {
if (key) {
event.data1 = key;
event.data2 = Convert[key];
event.data3 = Convert2[key];
event.data3 = Convert2[key][(altdown << ALT_SHIFT) |
(shiftdown << SHIFT_SHIFT) |
(ctrldown << CTRL_SHIFT)];
D_PostEvent (&event);
if (key == DIK_LALT)
altdown = (event.type == ev_keydown);

View file

@ -1212,7 +1212,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = {
sfx_vildth, // deathsound
15, // speed
20*FRACUNIT, // radius
76*FRACUNIT, // height
56*FRACUNIT, // height
500, // mass
0, // damage
sfx_vilact, // activesound
@ -1264,7 +1264,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = {
sfx_skedth, // deathsound
10, // speed
20*FRACUNIT, // radius
80*FRACUNIT, // height
56*FRACUNIT, // height
500, // mass
0, // damage
sfx_skeact, // activesound
@ -1394,7 +1394,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = {
sfx_podth2, // deathsound
8, // speed
20*FRACUNIT, // radius
60*FRACUNIT, // height
56*FRACUNIT, // height
100, // mass
0, // damage
sfx_posact, // activesound
@ -1524,7 +1524,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = {
sfx_brsdth, // deathsound
8, // speed
24*FRACUNIT, // radius
74*FRACUNIT, // height
64*FRACUNIT, // height
1000, // mass
0, // damage
sfx_dmact, // activesound
@ -1576,7 +1576,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = {
sfx_kntdth, // deathsound
8, // speed
24*FRACUNIT, // radius
74*FRACUNIT, // height
64*FRACUNIT, // height
1000, // mass
0, // damage
sfx_dmact, // activesound
@ -1628,7 +1628,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = {
sfx_spidth, // deathsound
12, // speed
128*FRACUNIT, // radius
110*FRACUNIT, // height
100*FRACUNIT, // height
1000, // mass
0, // damage
sfx_dmact, // activesound
@ -1654,7 +1654,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = {
sfx_bspdth, // deathsound
12, // speed
64*FRACUNIT, // radius
56*FRACUNIT, // height
64*FRACUNIT, // height
600, // mass
0, // damage
sfx_bspact, // activesound
@ -4698,7 +4698,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = {
sfx_bspdth, // deathsound
12, // speed
64*FRACUNIT, // radius
56*FRACUNIT, // height
64*FRACUNIT, // height
600, // mass
0, // damage
sfx_bspact, // activesound
@ -4724,7 +4724,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = {
sfx_vildth, // deathsound
15, // speed
20*FRACUNIT, // radius
76*FRACUNIT, // height
56*FRACUNIT, // height
500, // mass
0, // damage
sfx_vilact, // activesound
@ -4750,7 +4750,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = {
sfx_brsdth, // deathsound
8, // speed
24*FRACUNIT, // radius
74*FRACUNIT, // height
64*FRACUNIT, // height
1000, // mass
0, // damage
sfx_dmact, // activesound
@ -4802,7 +4802,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = {
sfx_podth2, // deathsound
8, // speed
20*FRACUNIT, // radius
60*FRACUNIT, // height
56*FRACUNIT, // height
100, // mass
0, // damage
sfx_posact, // activesound
@ -4854,7 +4854,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = {
sfx_kntdth, // deathsound
8, // speed
24*FRACUNIT, // radius
74*FRACUNIT, // height
64*FRACUNIT, // height
1000, // mass
0, // damage
sfx_dmact, // activesound
@ -4932,7 +4932,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = {
sfx_skedth, // deathsound
10, // speed
20*FRACUNIT, // radius
80*FRACUNIT, // height
56*FRACUNIT, // height
500, // mass
0, // damage
sfx_skeact, // activesound
@ -5222,7 +5222,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = {
100, // mass
0, // damage
sfx_None, // activesound
0, // flags
MF_NOGRAVITY, // flags
S_NULL // raisestate
},

View file

@ -219,10 +219,7 @@ static void M_SlidePlayerRed (int choice);
static void M_SlidePlayerGreen (int choice);
static void M_SlidePlayerBlue (int choice);
static void M_ChangeAutoAim (int choice);
// [RH] Used to make left and right arrows repeat.
static int Lefting = -1, Righting = -1;
BOOL M_DemoNoPlay;
//
@ -1121,6 +1118,9 @@ static void M_PlayerSetup (int choice)
choice = 0;
strncpy (savegamestrings[0], name->string, 23);
savegamestrings[0][23] = 0;
M_DemoNoPlay = true;
if (demoplayback)
G_CheckDemoStatus ();
M_SetupNextMenu (&PSetupDef);
PlayerState = &states[mobjinfo[MT_PLAYER].seestate];
PlayerTics = PlayerState->tics;
@ -1398,20 +1398,7 @@ BOOL M_Responder (event_t* ev)
ch2 = ev->data2; // ASCII
}
// [RH] Repeat left and right arrow keys
if (ev->type == ev_keydown) {
if (ev->data1 == KEY_LEFTARROW)
Lefting = KeyRepeatDelay >> 1;
else if (ev->data1 == KEY_RIGHTARROW)
Righting = KeyRepeatDelay >> 1;
} else if (ev->type == ev_keyup) {
if (ev->data1 == KEY_LEFTARROW)
Lefting = -1;
else if (ev->data1 == KEY_RIGHTARROW)
Righting = -1;
}
if (ch == -1 && !menuactive && Lefting == -1 && Righting == -1)
if (ch == -1 && !menuactive)
return false;
if (menuactive && OptionsActive) {
@ -1569,8 +1556,13 @@ BOOL M_Responder (event_t* ev)
currentMenu->lastOn = itemOn;
if (currentMenu->prevMenu)
{
M_DemoNoPlay = false;
currentMenu = currentMenu->prevMenu;
itemOn = currentMenu->lastOn;
// [RH] Make sure the skull is always visible on the
// main menu (for backing out of Read This!.
if (currentMenu == &MainDef)
drawSkull = true;
S_StartSound(ORIGIN_AMBIENT,sfx_swtchn);
} else {
M_ClearMenus ();
@ -1713,6 +1705,7 @@ void M_ClearMenus (void)
menuactive = 0;
drawSkull = true;
I_ResumeMouse (); // [RH] Recapture the mouse in windowed modes.
M_DemoNoPlay = false;
// if (!netgame && usergame && paused)
// sendpause = true;
}
@ -1743,23 +1736,6 @@ void M_Ticker (void)
}
if (currentMenu == &PSetupDef)
M_PlayerSetupTicker ();
// [RH] Make left and right arrow keys repeat
if (Lefting != -1 && --Lefting == 0) {
event_t ev;
ev.type = ev_keydown;
ev.data1 = KEY_LEFTARROW;
Lefting = 2;
M_Responder (&ev);
} else if (Righting != -1 && --Righting == 0) {
event_t ev;
ev.type = ev_keydown;
ev.data1 = KEY_RIGHTARROW;
Righting = 2;
M_Responder (&ev);
}
}

View file

@ -127,15 +127,14 @@ void T_VerticalDoor (vldoor_t* door)
{
case blazeRaise:
case blazeClose:
door->sector->specialdata = NULL;
door->sector->ceilingdata = NULL; //jff 2/22/98
P_RemoveThinker (&door->thinker); // unlink and free
S_StartSound((mobj_t *)&door->sector->soundorg,
sfx_bdcls);
S_StartSound((mobj_t *)&door->sector->soundorg, sfx_bdcls);
break;
case normal:
case close:
door->sector->specialdata = NULL;
door->sector->ceilingdata = NULL; //jff 2/22/98
P_RemoveThinker (&door->thinker); // unlink and free
break;
@ -185,7 +184,7 @@ void T_VerticalDoor (vldoor_t* door)
case close30ThenOpen:
case blazeOpen:
case open:
door->sector->specialdata = NULL;
door->sector->ceilingdata = NULL; //jff 2/22/98
P_RemoveThinker (&door->thinker); // unlink and free
break;
@ -254,10 +253,7 @@ EV_DoLockedDoor
}
int
EV_DoDoor
( line_t* line,
vldoor_e type )
int EV_DoDoor (line_t *line, vldoor_e type)
{
int secnum,rtn;
sector_t* sec;
@ -269,15 +265,15 @@ EV_DoDoor
while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0)
{
sec = &sectors[secnum];
if (sec->specialdata)
// 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->specialdata = door;
sec->ceilingdata = door; //jff 2/22/98
door->thinker.function.acp1 = (actionf_p1) T_VerticalDoor;
door->sector = sec;
@ -344,10 +340,7 @@ EV_DoDoor
//
// EV_VerticalDoor : open a door manually, no tag value
//
void
EV_VerticalDoor
( line_t* line,
mobj_t* thing )
void EV_VerticalDoor (line_t *line, mobj_t *thing)
{
player_t* player;
int secnum;
@ -403,13 +396,21 @@ EV_VerticalDoor
break;
}
// if the sector has an active thinker, use it
sec = sides[ line->sidenum[side^1]] .sector;
// 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 (sec->specialdata)
// if door already has a thinker, use it
if (sec->ceilingdata) //jff 2/22/98
{
door = sec->specialdata;
door = sec->ceilingdata; //jff 2/22/98
switch(line->special)
{
case 1: // ONLY FOR "RAISE" DOORS, NOT "OPEN"s
@ -452,7 +453,7 @@ EV_VerticalDoor
// new door thinker
door = Z_Malloc (sizeof(*door), PU_LEVSPEC, 0);
P_AddThinker (&door->thinker);
sec->specialdata = door;
sec->ceilingdata = door; //jff 2/22/98
door->thinker.function.acp1 = (actionf_p1) T_VerticalDoor;
door->sector = sec;
door->direction = 1;
@ -504,7 +505,7 @@ void P_SpawnDoorCloseIn30 (sector_t* sec)
P_AddThinker (&door->thinker);
sec->specialdata = door;
sec->ceilingdata = door; //jff 2/22/98
sec->special = 0;
door->thinker.function.acp1 = (actionf_p1)T_VerticalDoor;
@ -526,7 +527,7 @@ void P_SpawnDoorRaiseIn5Mins (sector_t *sec, int secnum)
P_AddThinker (&door->thinker);
sec->specialdata = door;
sec->ceilingdata = door; //jff 2/22/98
sec->special = 0;
door->thinker.function.acp1 = (actionf_p1)T_VerticalDoor;
@ -554,7 +555,7 @@ void P_SpawnDoorRaiseIn5Mins (sector_t *sec, int secnum)
slideframe_t slideFrames[MAXSLIDEDOORS];
void P_InitSlidingDoorFrames(void)
void P_InitSlidingDoorFrames (void)
{
int i;
int f1;
@ -598,7 +599,7 @@ void P_InitSlidingDoorFrames(void)
// Return index into "slideFrames" array
// for which door type to use
//
int P_FindSlidingDoorType(line_t* line)
int P_FindSlidingDoorType (line_t *line)
{
int i;
int val;
@ -613,7 +614,7 @@ int P_FindSlidingDoorType(line_t* line)
return -1;
}
void T_SlidingDoor (slidedoor_t* door)
void T_SlidingDoor (slidedoor_t *door)
{
switch(door->status)
{
@ -700,10 +701,7 @@ void T_SlidingDoor (slidedoor_t* door)
void
EV_SlidingDoor
( line_t* line,
mobj_t* thing )
void EV_SlidingDoor (line_t *line, mobj_t *thing)
{
sector_t* sec;
slidedoor_t* door;

View file

@ -1937,6 +1937,10 @@ void A_BrainSpit (mobj_t *mo)
static int easy = 0;
// [RH] Do nothing if there are no brain targets.
if (numbraintargets == 0)
return;
easy ^= 1;
if (gameskill->value <= sk_easy && (!easy))
return;
@ -2015,7 +2019,7 @@ void A_SpawnFly (mobj_t* mo)
P_SetMobjState (newmobj, newmobj->info->seestate);
// telefrag anything in this spot
P_TeleportMove (newmobj, newmobj->x, newmobj->y);
P_TeleportMove (newmobj, newmobj->x, newmobj->y, newmobj->z, true);
// remove self (i.e., cube).
P_RemoveMobj (mo);

View file

@ -67,11 +67,11 @@ T_MovePlane
{
lastpos = sector->floorheight;
sector->floorheight = dest;
flag = P_ChangeSector(sector,crush);
flag = P_CheckSector(sector,crush);
if (flag == true)
{
sector->floorheight =lastpos;
P_ChangeSector(sector,crush);
P_CheckSector(sector,crush);
//return crushed;
}
return pastdest;
@ -80,11 +80,11 @@ T_MovePlane
{
lastpos = sector->floorheight;
sector->floorheight -= speed;
flag = P_ChangeSector(sector,crush);
flag = P_CheckSector(sector,crush);
if (flag == true)
{
sector->floorheight = lastpos;
P_ChangeSector(sector,crush);
P_CheckSector(sector,crush);
return crushed;
}
}
@ -96,11 +96,11 @@ T_MovePlane
{
lastpos = sector->floorheight;
sector->floorheight = dest;
flag = P_ChangeSector(sector,crush);
flag = P_CheckSector(sector,crush);
if (flag == true)
{
sector->floorheight = lastpos;
P_ChangeSector(sector,crush);
P_CheckSector(sector,crush);
//return crushed;
}
return pastdest;
@ -110,13 +110,13 @@ T_MovePlane
// COULD GET CRUSHED
lastpos = sector->floorheight;
sector->floorheight += speed;
flag = P_ChangeSector(sector,crush);
flag = P_CheckSector(sector,crush);
if (flag == true)
{
if (crush == true)
return crushed;
sector->floorheight = lastpos;
P_ChangeSector(sector,crush);
P_CheckSector(sector,crush);
return crushed;
}
}
@ -134,12 +134,12 @@ T_MovePlane
{
lastpos = sector->ceilingheight;
sector->ceilingheight = dest;
flag = P_ChangeSector(sector,crush);
flag = P_CheckSector(sector,crush);
if (flag == true)
{
sector->ceilingheight = lastpos;
P_ChangeSector(sector,crush);
P_CheckSector(sector,crush);
//return crushed;
}
return pastdest;
@ -149,14 +149,14 @@ T_MovePlane
// COULD GET CRUSHED
lastpos = sector->ceilingheight;
sector->ceilingheight -= speed;
flag = P_ChangeSector(sector,crush);
flag = P_CheckSector(sector,crush);
if (flag == true)
{
if (crush == true)
return crushed;
sector->ceilingheight = lastpos;
P_ChangeSector(sector,crush);
P_CheckSector(sector,crush);
return crushed;
}
}
@ -168,11 +168,11 @@ T_MovePlane
{
lastpos = sector->ceilingheight;
sector->ceilingheight = dest;
flag = P_ChangeSector(sector,crush);
flag = P_CheckSector(sector,crush);
if (flag == true)
{
sector->ceilingheight = lastpos;
P_ChangeSector(sector,crush);
P_CheckSector(sector,crush);
//return crushed;
}
return pastdest;
@ -181,13 +181,13 @@ T_MovePlane
{
lastpos = sector->ceilingheight;
sector->ceilingheight += speed;
flag = P_ChangeSector(sector,crush);
flag = P_CheckSector(sector,crush);
// UNUSED
#if 0
if (flag == true)
{
sector->ceilingheight = lastpos;
P_ChangeSector(sector,crush);
P_CheckSector(sector,crush);
return crushed;
}
#endif
@ -204,7 +204,7 @@ T_MovePlane
//
// MOVE A FLOOR TO IT'S DESTINATION (UP OR DOWN)
//
void T_MoveFloor(floormove_t* floor)
void T_MoveFloor (floormove_t *floor)
{
result_e res;
@ -219,7 +219,7 @@ void T_MoveFloor(floormove_t* floor)
if (res == pastdest)
{
floor->sector->specialdata = NULL;
floor->sector->floordata = NULL;
if (floor->direction == 1)
{
@ -251,13 +251,86 @@ void T_MoveFloor(floormove_t* floor)
}
//
// T_MoveElevator()
//
// Move an elevator to it's destination (up or down)
// Called once per tick for each moving floor.
//
// Passed an elevator_t structure that contains all pertinent info about the
// move. See P_SPEC.H for fields.
// No return.
//
// jff 02/22/98 added to support parallel floor/ceiling motion
//
void T_MoveElevator (elevator_t* elevator)
{
result_e res;
if (elevator->direction<0) // moving down
{
res = T_MovePlane //jff 4/7/98 reverse order of ceiling/floor
(
elevator->sector,
elevator->speed,
elevator->ceilingdestheight,
0,
1, // move floor
elevator->direction
);
if (res==ok || res==pastdest) // jff 4/7/98 don't move ceil if blocked
T_MovePlane
(
elevator->sector,
elevator->speed,
elevator->floordestheight,
0,
0, // move ceiling
elevator->direction
);
}
else // up
{
res = T_MovePlane //jff 4/7/98 reverse order of ceiling/floor
(
elevator->sector,
elevator->speed,
elevator->floordestheight,
0,
0, // move ceiling
elevator->direction
);
if (res==ok || res==pastdest) // jff 4/7/98 don't move floor if blocked
T_MovePlane
(
elevator->sector,
elevator->speed,
elevator->ceilingdestheight,
0,
1, // move floor
elevator->direction
);
}
// make floor move sound
if (!(level.time&7))
S_StartSound((mobj_t *)&elevator->sector->soundorg, sfx_stnmov);
if (res == pastdest) // if destination height acheived
{
elevator->sector->floordata = NULL; //jff 2/22/98
elevator->sector->ceilingdata = NULL; //jff 2/22/98
P_RemoveThinker(&elevator->thinker); // remove elevator from actives
// make floor stop sound
S_StartSound((mobj_t *)&elevator->sector->soundorg, sfx_pstop);
}
}
//
// HANDLE FLOOR TYPES
//
int
EV_DoFloor
( line_t* line,
floor_e floortype )
int EV_DoFloor (line_t *line, floor_e floortype)
{
int secnum;
int rtn;
@ -272,14 +345,14 @@ EV_DoFloor
sec = &sectors[secnum];
// ALREADY MOVING? IF SO, KEEP GOING...
if (sec->specialdata)
if (P_SectorActive (floor_special, sec)) //jff 2/33/98
continue;
// new floor thinker
rtn = 1;
floor = Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0);
P_AddThinker (&floor->thinker);
sec->specialdata = floor;
sec->floordata = floor; //jff 2/22/98
floor->thinker.function.acp1 = (actionf_p1) T_MoveFloor;
floor->type = floortype;
floor->crush = false;
@ -442,10 +515,7 @@ EV_DoFloor
//
// BUILD A STAIRCASE!
//
int
EV_BuildStairs
( line_t* line,
stair_e type )
int EV_BuildStairs (line_t *line, stair_e type)
{
int secnum;
int height;
@ -470,14 +540,14 @@ EV_BuildStairs
sec = &sectors[secnum];
// ALREADY MOVING? IF SO, KEEP GOING...
if (sec->specialdata)
if (P_SectorActive (floor_special, sec)) //jff 2/22/98
continue;
// new floor thinker
rtn = 1;
floor = Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0);
P_AddThinker (&floor->thinker);
sec->specialdata = floor;
sec->floordata = floor; //jff 2/22/98
floor->thinker.function.acp1 = (actionf_p1) T_MoveFloor;
floor->direction = 1;
floor->sector = sec;
@ -523,7 +593,8 @@ EV_BuildStairs
height += stairsize;
if (tsec->specialdata)
// if sector's floor already moving, look for another
if (P_SectorActive(floor_special,tsec)) //jff 2/22/98
continue;
sec = tsec;
@ -532,7 +603,7 @@ EV_BuildStairs
P_AddThinker (&floor->thinker);
sec->specialdata = floor;
sec->floordata = floor;
floor->thinker.function.acp1 = (actionf_p1) T_MoveFloor;
floor->direction = 1;
floor->sector = sec;
@ -546,3 +617,81 @@ EV_BuildStairs
return rtn;
}
//
// EV_DoElevator
//
// Handle elevator linedef types
//
// Passed the linedef that triggered the elevator and the elevator action
//
// jff 2/22/98 new type to move floor and ceiling in parallel
//
int EV_DoElevator (line_t *line, elevator_e elevtype)
{
int secnum;
int rtn;
sector_t* sec;
elevator_t* elevator;
secnum = -1;
rtn = 0;
// act on all sectors with the same tag as the triggering linedef
while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0)
{
sec = &sectors[secnum];
// If either floor or ceiling is already activated, skip it
if (sec->floordata || sec->ceilingdata) //jff 2/22/98
continue;
// create and initialize new elevator thinker
rtn = 1;
elevator = Z_Malloc (sizeof(*elevator), PU_LEVSPEC, 0);
P_AddThinker (&elevator->thinker);
sec->floordata = elevator; //jff 2/22/98
sec->ceilingdata = elevator; //jff 2/22/98
elevator->thinker.function.acp1 = (actionf_p1) T_MoveElevator;
elevator->type = elevtype;
// set up the fields according to the type of elevator action
switch(elevtype)
{
// elevator down to next floor
case elevateDown:
elevator->direction = -1;
elevator->sector = sec;
elevator->speed = ELEVATORSPEED;
elevator->floordestheight =
P_FindNextLowestFloor(sec,sec->floorheight);
elevator->ceilingdestheight =
elevator->floordestheight + sec->ceilingheight - sec->floorheight;
break;
// elevator up to next floor
case elevateUp:
elevator->direction = 1;
elevator->sector = sec;
elevator->speed = ELEVATORSPEED;
elevator->floordestheight =
P_FindNextHighestFloor(sec,sec->floorheight);
elevator->ceilingdestheight =
elevator->floordestheight + sec->ceilingheight - sec->floorheight;
break;
// elevator to floor height of activating switch's front sector
case elevateCurrent:
elevator->sector = sec;
elevator->speed = ELEVATORSPEED;
elevator->floordestheight = line->frontsector->floorheight;
elevator->ceilingdestheight =
elevator->floordestheight + sec->ceilingheight - sec->floorheight;
elevator->direction =
elevator->floordestheight>sec->floorheight? 1 : -1;
break;
default:
break;
}
}
return rtn;
}

View file

@ -211,13 +211,13 @@ void P_SetThingPosition (mobj_t* thing);
extern BOOL floatok;
extern fixed_t tmfloorz;
extern fixed_t tmceilingz;
extern msecnode_t *sector_list; // phares 3/16/98
extern line_t* ceilingline;
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_TeleportMove (mobj_t* thing, fixed_t x, fixed_t y);
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);
BOOL P_CheckSight (const mobj_t* t1, const mobj_t* t2);
void P_UseLines (player_t* player);
@ -233,6 +233,14 @@ void P_LineAttack (mobj_t *t1, angle_t angle, fixed_t distance, fixed_t slope, i
// [RH] Means of death
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()
BOOL P_CheckSector(sector_t *sector, BOOL crunch);
void P_DelSeclist(msecnode_t *); // phares 3/16/98
void P_CreateSecNodeList(mobj_t*,fixed_t,fixed_t); // phares 3/14/98
int P_GetMoveFactor(mobj_t* mo); // phares 3/6/98
BOOL Check_Sides(mobj_t *, int, int); // phares
// [RH] Finds the mobj thing is standing on/in.
// Returns NULL if nothing, -1 if the ground,
// or a pointer to another mobj.

View file

@ -44,12 +44,14 @@
// Data.
#include "sounds.h"
#include "z_zone.h"
fixed_t tmbbox[4];
mobj_t* tmthing;
int tmflags;
fixed_t tmx;
fixed_t tmy;
fixed_t tmz; // [RH] Needed for third dimension of teleporters
// If "floatok" true, move would be ok
@ -72,6 +74,9 @@ int MaxSpecialCross = 0;
line_t** spechit;
int numspechit;
// Temporary holder for thing_sectorlist threads
msecnode_t* sector_list = NULL; // phares 3/16/98
//
@ -81,6 +86,8 @@ int numspechit;
//
// PIT_StompThing
//
static BOOL StompAlwaysFrags;
BOOL PIT_StompThing (mobj_t* thing)
{
fixed_t blockdist;
@ -102,25 +109,32 @@ BOOL PIT_StompThing (mobj_t* thing)
}
// [RH] Z-Check
if (tmthing->z > thing->z + thing->height)
if (!olddemo) {
if (tmz > thing->z + thing->height)
return true; // overhead
if (tmthing->z+tmthing->height < thing->z)
if (tmz+tmthing->height < thing->z)
return true; // underneath
}
// monsters don't stomp things except on boss level
if ( !tmthing->player && !(level.flags & LEVEL_MONSTERSTELEFRAG) )
return false;
if (StompAlwaysFrags) {
P_DamageMobj (thing, tmthing, tmthing, 10000, MOD_TELEFRAG);
return true;
}
return false;
}
//
// P_TeleportMove
//
BOOL P_TeleportMove (mobj_t *thing, fixed_t x, fixed_t y)
// [RH] Added telefrag parameter: When true, anything in the spawn spot
// will always be telefragged, and the move will be successful.
// Added z parameter. Originally, the thing's z was set *after* the
// move was made, so the height checking I added for 1.13 could
// potentially erroneously indicate the move was okay if the thing
// was being teleported between two non-overlapping height ranges.
BOOL P_TeleportMove (mobj_t *thing, fixed_t x, fixed_t y, fixed_t z, BOOL telefrag)
{
int xl;
int xh;
@ -137,6 +151,7 @@ BOOL P_TeleportMove (mobj_t *thing, fixed_t x, fixed_t y)
tmx = x;
tmy = y;
tmz = z;
tmbbox[BOXTOP] = y + tmthing->radius;
tmbbox[BOXBOTTOM] = y - tmthing->radius;
@ -156,6 +171,9 @@ BOOL P_TeleportMove (mobj_t *thing, fixed_t x, fixed_t y)
validcount++;
numspechit = 0;
StompAlwaysFrags = tmthing->player || (level.flags & LEVEL_MONSTERSTELEFRAG) ||
(!olddemo && telefrag);
// stomp on any things contacted
xl = (tmbbox[BOXLEFT] - bmaporgx - MAXRADIUS)>>MAPBLOCKSHIFT;
xh = (tmbbox[BOXRIGHT] - bmaporgx + MAXRADIUS)>>MAPBLOCKSHIFT;
@ -178,6 +196,8 @@ BOOL P_TeleportMove (mobj_t *thing, fixed_t x, fixed_t y)
P_SetThingPosition (thing);
thing->z = z;
return true;
}
@ -1401,7 +1421,9 @@ BOOL PIT_RadiusAttack (mobj_t *thing)
if (thing->type == MT_CYBORG || thing->type == MT_SPIDER)
return true;
if (!olddemo) {
// Barrels always use the original code, since this makes
// them far too "active."
if (!olddemo && bombspot->type != MT_BARREL && thing->type != MT_BARREL) {
// [RH] New code (based on stuff in Q2)
float points;
vec3_t thingvec;
@ -1410,8 +1432,11 @@ BOOL PIT_RadiusAttack (mobj_t *thing)
thingvec[2] += (float)(thing->height >> (FRACBITS+1));
{
vec3_t v;
float len;
VectorSubtract (bombvec, thingvec, v);
points = bombdamagefloat - VectorLength (v);
len = VectorLength (v);
points = bombdamagefloat - len;
}
if (thing == bombsource)
points = points * 0.5f;
@ -1518,7 +1543,7 @@ BOOL nofit;
//
// PIT_ChangeSector
//
BOOL PIT_ChangeSector (mobj_t* thing)
BOOL PIT_ChangeSector (mobj_t *thing)
{
mobj_t *mo;
int t;
@ -1584,10 +1609,7 @@ BOOL PIT_ChangeSector (mobj_t* thing)
//
// P_ChangeSector
//
BOOL
P_ChangeSector
( sector_t* sector,
BOOL crunch )
BOOL P_ChangeSector (sector_t *sector, BOOL crunch)
{
int x;
int y;
@ -1600,7 +1622,294 @@ P_ChangeSector
for (y=sector->blockbox[BOXBOTTOM];y<= sector->blockbox[BOXTOP] ; y++)
P_BlockThingsIterator (x, y, PIT_ChangeSector);
return nofit;
}
//
// P_CheckSector
// jff 3/19/98 added to just check monsters on the periphery
// of a moving sector instead of all in bounding box of the
// sector. Both more accurate and faster.
//
BOOL P_CheckSector (sector_t *sector, BOOL crunch)
{
msecnode_t *n;
if (olddemo) // use the old routine for old demos though
return P_ChangeSector(sector,crunch);
nofit = false;
crushchange = crunch;
// killough 4/4/98: scan list front-to-back until empty or exhausted,
// restarting from beginning after each thing is processed. Avoids
// crashes, and is sure to examine all things in the sector, and only
// the things which are in the sector, until a steady-state is reached.
// Things can arbitrarily be inserted and removed and it won't mess up.
//
// killough 4/7/98: simplified to avoid using complicated counter
// Mark all things invalid
for (n=sector->touching_thinglist; n; n=n->m_snext)
n->visited = false;
do
for (n=sector->touching_thinglist; n; n=n->m_snext) // go through list
if (!n->visited) // unprocessed thing found
{
n->visited = true; // mark thing as processed
if (!(n->m_thing->flags & MF_NOBLOCKMAP)) //jff 4/7/98 don't do these
PIT_ChangeSector(n->m_thing); // process it
break; // exit and start over
}
while (n); // repeat from scratch until all things left are marked valid
return nofit;
}
// phares 3/21/98
//
// Maintain a freelist of msecnode_t's to reduce memory allocs and frees.
msecnode_t *headsecnode = NULL;
// P_GetSecnode() retrieves a node from the freelist. The calling routine
// should make sure it sets all fields properly.
msecnode_t *P_GetSecnode()
{
msecnode_t *node;
if (headsecnode)
{
node = headsecnode;
headsecnode = headsecnode->m_snext;
}
else
node = Z_Malloc (sizeof(*node), PU_LEVEL, NULL);
return(node);
}
// P_PutSecnode() returns a node to the freelist.
void P_PutSecnode (msecnode_t* node)
{
node->m_snext = headsecnode;
headsecnode = node;
}
// phares 3/16/98
//
// P_AddSecnode() searches the current list to see if this sector is
// already there. If not, it adds a sector node at the head of the list of
// sectors this object appears in. This is called when creating a list of
// nodes that will get linked in later. Returns a pointer to the new node.
msecnode_t* P_AddSecnode(sector_t* s, mobj_t* thing, msecnode_t* nextnode)
{
msecnode_t* node;
node = nextnode;
while (node)
{
if (node->m_sector == s) // Already have a node for this sector?
{
node->m_thing = thing; // Yes. Setting m_thing says 'keep it'.
return(nextnode);
}
node = node->m_tnext;
}
// Couldn't find an existing node for this sector. Add one at the head
// of the list.
node = P_GetSecnode();
// killough 4/4/98, 4/7/98: mark new nodes unvisited.
node->visited = 0;
node->m_sector = s; // sector
node->m_thing = thing; // mobj
node->m_tprev = NULL; // prev node on Thing thread
node->m_tnext = nextnode; // next node on Thing thread
if (nextnode)
nextnode->m_tprev = node; // set back link on Thing
// Add new node at head of sector thread starting at s->touching_thinglist
node->m_sprev = NULL; // prev node on sector thread
node->m_snext = s->touching_thinglist; // next node on sector thread
if (s->touching_thinglist)
node->m_snext->m_sprev = node;
s->touching_thinglist = node;
return(node);
}
// P_DelSecnode() deletes a sector node from the list of
// sectors this object appears in. Returns a pointer to the next node
// on the linked list, or NULL.
msecnode_t* P_DelSecnode(msecnode_t* node)
{
msecnode_t* tp; // prev node on thing thread
msecnode_t* tn; // next node on thing thread
msecnode_t* sp; // prev node on sector thread
msecnode_t* sn; // next node on sector thread
if (node)
{
// Unlink from the Thing thread. The Thing thread begins at
// sector_list and not from mobj_t->touching_sectorlist.
tp = node->m_tprev;
tn = node->m_tnext;
if (tp)
tp->m_tnext = tn;
if (tn)
tn->m_tprev = tp;
// Unlink from the sector thread. This thread begins at
// sector_t->touching_thinglist.
sp = node->m_sprev;
sn = node->m_snext;
if (sp)
sp->m_snext = sn;
else
node->m_sector->touching_thinglist = sn;
if (sn)
sn->m_sprev = sp;
// Return this node to the freelist
P_PutSecnode(node);
return(tn);
}
return(NULL);
} // phares 3/13/98
// Delete an entire sector list
void P_DelSeclist(msecnode_t* node)
{
while (node)
node = P_DelSecnode(node);
}
// phares 3/14/98
//
// PIT_GetSectors
// Locates all the sectors the object is in by looking at the lines that
// cross through it. You have already decided that the object is allowed
// at this location, so don't bother with checking impassable or
// blocking lines.
BOOL PIT_GetSectors(line_t* ld)
{
if (tmbbox[BOXRIGHT] <= ld->bbox[BOXLEFT] ||
tmbbox[BOXLEFT] >= ld->bbox[BOXRIGHT] ||
tmbbox[BOXTOP] <= ld->bbox[BOXBOTTOM] ||
tmbbox[BOXBOTTOM] >= ld->bbox[BOXTOP])
return true;
if (P_BoxOnLineSide(tmbbox, ld) != -1)
return true;
// This line crosses through the object.
// Collect the sector(s) from the line and add to the
// sector_list you're examining. If the Thing ends up being
// allowed to move to this position, then the sector_list
// will be attached to the Thing's mobj_t at touching_sectorlist.
sector_list = P_AddSecnode(ld->frontsector,tmthing,sector_list);
// Don't assume all lines are 2-sided, since some Things
// like MT_TFOG are allowed regardless of whether their radius takes
// them beyond an impassable linedef.
// killough 3/27/98, 4/4/98:
// Use sidedefs instead of 2s flag to determine two-sidedness.
if (ld->backsector)
sector_list = P_AddSecnode(ld->backsector, tmthing, sector_list);
return true;
}
// phares 3/14/98
//
// P_CreateSecNodeList alters/creates the sector_list that shows what sectors
// the object resides in.
void P_CreateSecNodeList(mobj_t* thing,fixed_t x,fixed_t y)
{
int xl;
int xh;
int yl;
int yh;
int bx;
int by;
msecnode_t* node;
// First, clear out the existing m_thing fields. As each node is
// added or verified as needed, m_thing will be set properly. When
// finished, delete all nodes where m_thing is still NULL. These
// represent the sectors the Thing has vacated.
node = sector_list;
while (node)
{
node->m_thing = NULL;
node = node->m_tnext;
}
tmthing = thing;
tmflags = thing->flags;
tmx = x;
tmy = y;
tmbbox[BOXTOP] = y + tmthing->radius;
tmbbox[BOXBOTTOM] = y - tmthing->radius;
tmbbox[BOXRIGHT] = x + tmthing->radius;
tmbbox[BOXLEFT] = x - tmthing->radius;
validcount++; // used to make sure we only process a line once
xl = (tmbbox[BOXLEFT] - bmaporgx)>>MAPBLOCKSHIFT;
xh = (tmbbox[BOXRIGHT] - bmaporgx)>>MAPBLOCKSHIFT;
yl = (tmbbox[BOXBOTTOM] - bmaporgy)>>MAPBLOCKSHIFT;
yh = (tmbbox[BOXTOP] - bmaporgy)>>MAPBLOCKSHIFT;
for (bx=xl ; bx<=xh ; bx++)
for (by=yl ; by<=yh ; by++)
P_BlockLinesIterator(bx,by,PIT_GetSectors);
// Add the sector of the (x,y) point to sector_list.
sector_list = P_AddSecnode(thing->subsector->sector,thing,sector_list);
// Now delete any nodes that won't be used. These are the ones where
// m_thing is still NULL.
node = sector_list;
while (node)
{
if (node->m_thing == NULL)
{
if (node == sector_list)
sector_list = node->m_tnext;
node = P_DelSecnode(node);
}
else
node = node->m_tnext;
}
}

View file

@ -321,7 +321,7 @@ 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?
// unlink from subsector
@ -332,6 +332,22 @@ void P_UnsetThingPosition (mobj_t *thing)
thing->sprev->snext = thing->snext;
else
thing->subsector->sector->thinglist = thing->snext;
// phares 3/14/98
//
// Save the sector list pointed to by touching_sectorlist.
// In P_SetThingPosition, we'll keep any nodes that represent
// sectors the Thing still touches. We'll add new ones then, and
// delete any nodes for sectors the Thing has vacated. Then we'll
// put it back into touching_sectorlist. It's done this way to
// avoid a lot of deleting/creating for nodes, when most of the
// time you just get back what you deleted anyway.
//
// If this Thing is being removed entirely, then the calling
// routine will clear out the nodes in sector_list.
sector_list = thing->touching_sectorlist;
thing->touching_sectorlist = NULL; //to be restored by P_SetThingPosition
}
if ( ! (thing->flags & MF_NOBLOCKMAP) )
@ -389,6 +405,23 @@ void P_SetThingPosition (mobj_t *thing)
sec->thinglist->sprev = thing;
sec->thinglist = thing;
// phares 3/16/98
//
// If sector_list isn't NULL, it has a collection of sector
// nodes that were just removed from this Thing.
// Collect the sectors the object will live in by looking at
// the existing sector_list and adding new nodes and deleting
// obsolete ones.
// When a node is deleted, its sector links (the links starting
// at sector_t->touching_thinglist) are broken. When a node is
// added, new sector links are created.
P_CreateSecNodeList (thing, thing->x, thing->y);
thing->touching_sectorlist = sector_list; // Attach to Thing's mobj_t
sector_list = NULL; // clear for next time
}

View file

@ -230,8 +230,13 @@ void P_XYMovement (mobj_t* mo)
if (mo->flags & (MF_MISSILE | MF_SKULLFLY) )
return; // no friction for missiles ever
if (olddemo) { // no friction when airborne
if (mo->z > mo->floorz)
return;
} else {
if (!P_FindFloor (mo)) // [RH] Z-Check
return; // no friction when airborne
return;
}
if (mo->flags & MF_CORPSE)
{
@ -311,9 +316,16 @@ void P_ZMovement (mobj_t* mo)
}
// clip movement
if (olddemo) {
if (mo->z <= mo->floorz)
other = (mobj_t *)-1;
else
other = NULL;
} else {
other = P_FindFloor (mo); // [RH] Z-Check
if ((mo->flags & MF_MISSILE) && (other == mo->target) && (gametic < (signed)mo->targettic))
other = NULL;
}
if (other) {
// hit the floor ([RH] or something else)
@ -400,9 +412,16 @@ void P_ZMovement (mobj_t* mo)
mo->momz -= (fixed_t)(sv_gravity->value * 81.92);
}
if (olddemo) {
if (mo->z + mo->height > mo->ceilingz)
other = (mobj_t *) -1;
else
other = NULL;
} else {
other = P_FindCeiling (mo); // [RH] Z-Check
if ((mo->flags & MF_MISSILE) && (other == mo->target) && (gametic < (signed)mo->targettic))
other = NULL;
}
if (other)
{
@ -603,6 +622,7 @@ mobj_t *P_SpawnMobj (fixed_t x, fixed_t y, fixed_t z, mobjtype_t type, int onflo
mobj->tics = st->tics;
mobj->sprite = st->sprite;
mobj->frame = st->frame;
mobj->touching_sectorlist = NULL; // NULL head of sector list // phares 3/13/98
// set subsector and/or block links
P_SetThingPosition (mobj);
@ -657,6 +677,14 @@ void P_RemoveMobj (mobj_t* mobj)
// unlink from sector and block lists
P_UnsetThingPosition (mobj);
// Delete all nodes on the current sector_list phares 3/16/98
if (sector_list)
{
P_DelSeclist(sector_list);
sector_list = NULL;
}
// stop any playing sound
S_StopSound (mobj);

View file

@ -308,6 +308,9 @@ typedef struct mobj_s
// than a full-fledged palette.
struct palette_s *palette;
// a linked list of sectors where this object appears
struct msecnode_s *touching_sectorlist; // phares 3/14/98
} mobj_t;

View file

@ -184,9 +184,11 @@ void P_UnArchiveWorld (void)
sec->floorpic = *get++;
sec->ceilingpic = *get++;
sec->lightlevel = *get++;
sec->special = *get++; // needed?
sec->tag = *get++; // needed?
sec->specialdata = 0;
sec->special = *get++;
sec->tag = *get++;
sec->ceilingdata = 0; //jff 2/22/98 now three thinker fields not two
sec->floordata = 0;
sec->lightingdata = 0;
sec->soundtarget = 0;
}
@ -337,6 +339,8 @@ enum
tc_strobe,
tc_glow,
tc_fireflicker,
tc_elevator,
tc_scroll,
tc_endspecials
} specials_e;
@ -353,6 +357,8 @@ enum
// T_Glow, (glow_t: sector_t *),
// T_PlatRaise, (plat_t: sector_t *), - active list
// T_FireFlicker (fireflicker_t: sector_t * swizze), [RH] Was missed in original code
// T_MoveElevator, (plat_t: sector_t *), - active list // jff 2/22/98
// T_Scroll // killough 3/7/98
//
void P_ArchiveSpecials (void)
{
@ -462,6 +468,27 @@ void P_ArchiveSpecials (void)
save_p += sizeof(*flick);
flick->sector = (sector_t *)(flick->sector - sectors);
}
else if (th->function.acp1 == (actionf_p1) T_MoveElevator)
{ //jff 2/22/98 new case for elevators
elevator_t *elevator; //jff 2/22/98
*save_p++ = tc_elevator;
PADSAVEP();
elevator = (elevator_t *)save_p;
memcpy (elevator, th, sizeof(*elevator));
save_p += sizeof(*elevator);
elevator->sector = (sector_t *)(elevator->sector - sectors);
}
else if (th->function.acp1 == (actionf_p1) T_Scroll)
{ // killough 3/7/98: Scroll effect thinkers
*save_p++ = tc_scroll;
memcpy (save_p, th, sizeof(scroll_t));
save_p += sizeof(scroll_t);
continue;
}
}
// add a terminating marker
@ -501,7 +528,7 @@ void P_UnArchiveSpecials (void)
memcpy (ceiling, save_p, sizeof(*ceiling));
save_p += sizeof(*ceiling);
ceiling->sector = &sectors[(int)ceiling->sector];
ceiling->sector->specialdata = ceiling;
ceiling->sector->ceilingdata = ceiling; //jff 2/22/98
if (ceiling->thinker.function.acp1)
ceiling->thinker.function.acp1 = (actionf_p1)T_MoveCeiling;
@ -516,7 +543,7 @@ void P_UnArchiveSpecials (void)
memcpy (door, save_p, sizeof(*door));
save_p += sizeof(*door);
door->sector = &sectors[(int)door->sector];
door->sector->specialdata = door;
door->sector->ceilingdata = door; //jff 2/22/98
door->thinker.function.acp1 = (actionf_p1)T_VerticalDoor;
P_AddThinker (&door->thinker);
break;
@ -527,7 +554,7 @@ void P_UnArchiveSpecials (void)
memcpy (floor, save_p, sizeof(*floor));
save_p += sizeof(*floor);
floor->sector = &sectors[(int)floor->sector];
floor->sector->specialdata = floor;
floor->sector->floordata = floor; //jff 2/22/98
floor->thinker.function.acp1 = (actionf_p1)T_MoveFloor;
P_AddThinker (&floor->thinker);
break;
@ -538,7 +565,7 @@ void P_UnArchiveSpecials (void)
memcpy (plat, save_p, sizeof(*plat));
save_p += sizeof(*plat);
plat->sector = &sectors[(int)plat->sector];
plat->sector->specialdata = plat;
plat->sector->floordata = plat; //jff 2/22/98
if (plat->thinker.function.acp1)
plat->thinker.function.acp1 = (actionf_p1)T_PlatRaise;
@ -587,6 +614,31 @@ void P_UnArchiveSpecials (void)
P_AddThinker (&flick->thinker);
break;
//jff 2/22/98 new case for elevators
case tc_elevator:
PADSAVEP();
{
elevator_t *elevator = Z_Malloc (sizeof(*elevator), PU_LEVEL, NULL);
memcpy (elevator, save_p, sizeof(*elevator));
save_p += sizeof(*elevator);
elevator->sector = &sectors[(int)elevator->sector];
elevator->sector->floordata = elevator; //jff 2/22/98
elevator->sector->ceilingdata = elevator; //jff 2/22/98
elevator->thinker.function.acp1 = (actionf_p1) T_MoveElevator;
P_AddThinker (&elevator->thinker);
break;
}
case tc_scroll: // killough 3/7/98: scroll effect thinkers
{
scroll_t *scroll = Z_Malloc (sizeof(scroll_t), PU_LEVEL, NULL);
memcpy (scroll, save_p, sizeof(scroll_t));
save_p += sizeof(scroll_t);
scroll->thinker.function.acp1 = (actionf_p1) T_Scroll;
P_AddThinker(&scroll->thinker);
break;
}
default:
I_Error ("P_UnarchiveSpecials:Unknown tclass %i "
"in savegame",tclass);

View file

@ -253,6 +253,22 @@ void P_LoadSectors (int lump)
ss->special = SHORT(ms->special);
ss->tag = SHORT(ms->tag);
ss->thinglist = NULL;
ss->touching_thinglist = NULL; // phares 3/14/98
ss->nextsec = -1; //jff 2/26/98 add fields to support locking out
ss->prevsec = -1; // stair retriggering until build completes
// killough 3/7/98:
ss->floor_xoffs = 0;
ss->floor_yoffs = 0; // floor and ceiling flats offsets
ss->ceiling_xoffs = 0;
ss->ceiling_yoffs = 0;
ss->heightsec = -1; // sector used to get floor and ceiling height
ss->floorlightsec = -1; // sector used to get floor lighting
// killough 3/7/98: end changes
// killough 4/11/98 sector used to get ceiling lighting:
ss->ceilinglightsec = -1;
}
Z_Free (data);
@ -378,32 +394,13 @@ void P_LoadThings2 (int lump)
// P_LoadLineDefs
// Also counts secret lines for intermissions.
//
void P_LoadLineDefs (int lump)
static void P_AdjustLine (line_t *ld)
{
byte* data;
int i;
maplinedef_t* mld;
line_t* ld;
vertex_t* v1;
vertex_t* v2;
vertex_t *v1, *v2;
numlines = W_LumpLength (lump) / sizeof(maplinedef_t);
lines = Z_Malloc (numlines*sizeof(line_t),PU_LEVEL,0);
memset (lines, 0, numlines*sizeof(line_t));
data = W_CacheLumpNum (lump,PU_STATIC);
v1 = ld->v1;
v2 = ld->v2;
mld = (maplinedef_t *)data;
ld = lines;
for (i=0 ; i<numlines ; i++, mld++, ld++)
{
ld->flags = SHORT(mld->flags);
// [RH] Remap ML_PASSUSE flag from BOOM.
if (!HasBehavior && (ld->flags & ML_PASSUSEORG))
ld->flags = (ld->flags & ~ML_PASSUSEORG) | ML_PASSUSE;
ld->special = SHORT(mld->special);
ld->tag = SHORT(mld->tag);
v1 = ld->v1 = &vertexes[SHORT(mld->v1)];
v2 = ld->v2 = &vertexes[SHORT(mld->v2)];
ld->dx = v2->x - v1->x;
ld->dy = v2->y - v1->y;
@ -441,9 +438,6 @@ void P_LoadLineDefs (int lump)
ld->bbox[BOXTOP] = v1->y;
}
ld->sidenum[0] = SHORT(mld->sidenum[0]);
ld->sidenum[1] = SHORT(mld->sidenum[1]);
if (ld->sidenum[0] != -1)
ld->frontsector = sides[ld->sidenum[0]].sector;
else
@ -453,6 +447,70 @@ void P_LoadLineDefs (int lump)
ld->backsector = sides[ld->sidenum[1]].sector;
else
ld->backsector = 0;
}
void P_LoadLineDefs (int lump)
{
byte* data;
int i;
maplinedef_t* mld;
line_t* ld;
numlines = W_LumpLength (lump) / sizeof(maplinedef_t);
lines = Z_Malloc (numlines*sizeof(line_t),PU_LEVEL,0);
memset (lines, 0, numlines*sizeof(line_t));
data = W_CacheLumpNum (lump,PU_STATIC);
mld = (maplinedef_t *)data;
ld = lines;
for (i=0 ; i<numlines ; i++, mld++, ld++)
{
ld->flags = SHORT(mld->flags);
// [RH] Remap ML_PASSUSE flag from BOOM.
if (ld->flags & ML_PASSUSEORG)
ld->flags = (ld->flags & ~ML_PASSUSEORG) | ML_PASSUSE;
ld->special = SHORT(mld->special);
ld->tag = SHORT(mld->tag);
ld->v1 = &vertexes[SHORT(mld->v1)];
ld->v2 = &vertexes[SHORT(mld->v2)];
ld->sidenum[0] = SHORT(mld->sidenum[0]);
ld->sidenum[1] = SHORT(mld->sidenum[1]);
P_AdjustLine (ld);
}
Z_Free (data);
}
// [RH] Same as P_LoadLineDefs() except it uses Hexen-style LineDefs.
void P_LoadLineDefs2 (int lump)
{
byte* data;
int i;
maplinedef2_t* mld;
line_t* ld;
numlines = W_LumpLength (lump) / sizeof(maplinedef2_t);
lines = Z_Malloc (numlines*sizeof(line_t),PU_LEVEL,0);
memset (lines, 0, numlines*sizeof(line_t));
data = W_CacheLumpNum (lump,PU_STATIC);
mld = (maplinedef2_t *)data;
ld = lines;
for (i=0 ; i<numlines ; i++, mld++, ld++)
{
ld->flags = SHORT(mld->flags);
ld->special = mld->special;
memcpy (ld->args, mld->args, 5);
ld->tag = ld->args[0];
ld->v1 = &vertexes[SHORT(mld->v1)];
ld->v2 = &vertexes[SHORT(mld->v2)];
ld->sidenum[0] = SHORT(mld->sidenum[0]);
ld->sidenum[1] = SHORT(mld->sidenum[1]);
P_AdjustLine (ld);
}
Z_Free (data);
@ -677,7 +735,10 @@ void P_SetupLevel (char *lumpname)
P_LoadSectors (lumpnum+ML_SECTORS);
P_LoadSideDefs (lumpnum+ML_SIDEDEFS);
if (!HasBehavior)
P_LoadLineDefs (lumpnum+ML_LINEDEFS);
else
P_LoadLineDefs2 (lumpnum+ML_LINEDEFS); // [RH] Load Hexen-style linedefs
P_LoadSubsectors (lumpnum+ML_SSECTORS);
P_LoadNodes (lumpnum+ML_NODES);
P_LoadSegs (lumpnum+ML_SEGS);
@ -692,10 +753,10 @@ void P_SetupLevel (char *lumpname)
}
deathmatch_p = deathmatchstarts;
if (HasBehavior)
P_LoadThings2 (lumpnum+ML_THINGS); // [RH] Load Hexen-style Things
else
if (!HasBehavior)
P_LoadThings (lumpnum+ML_THINGS);
else
P_LoadThings2 (lumpnum+ML_THINGS); // [RH] Load Hexen-style things
// if deathmatch, randomly spawn the active players
if (deathmatch->value)

View file

@ -68,15 +68,17 @@ typedef struct
int basepic;
int numpics;
int speed;
} anim_t;
//
// source animation definition
//
// [RH] Note that in BOOM's ANIMATED lump, this is an array packed to
// byte boundaries. Total size: 23 bytes per entry.
//
typedef struct
{
BOOL istexture; // if false, it is a flat
byte istexture; // if false, it is a flat
char endname[9];
char startname[9];
int speed;
@ -84,110 +86,105 @@ typedef struct
#define MAXANIMS 32
extern anim_t anims[MAXANIMS];
extern anim_t* lastanim;
//
// P_InitPicAnims
//
// Floor/ceiling animation sequences,
// defined by first and last frame,
// i.e. the flat (64x64 tile) name to
// be used.
// The full animation sequence is given
// using all the flats between the start
// and end entry, in the order found in
// the WAD file.
//
animdef_t animdefs[] =
{
{false, "NUKAGE3", "NUKAGE1", 8},
{false, "FWATER4", "FWATER1", 8},
{false, "SWATER4", "SWATER1", 8},
{false, "LAVA4", "LAVA1", 8},
{false, "BLOOD3", "BLOOD1", 8},
// DOOM II flat animations.
{false, "RROCK08", "RROCK05", 8},
{false, "SLIME04", "SLIME01", 8},
{false, "SLIME08", "SLIME05", 8},
{false, "SLIME12", "SLIME09", 8},
{true, "BLODGR4", "BLODGR1", 8},
{true, "SLADRIP3", "SLADRIP1", 8},
{true, "BLODRIP4", "BLODRIP1", 8},
{true, "FIREWALL", "FIREWALA", 8},
{true, "GSTFONT3", "GSTFONT1", 8},
{true, "FIRELAVA", "FIRELAV3", 8},
{true, "FIREMAG3", "FIREMAG1", 8},
{true, "FIREBLU2", "FIREBLU1", 8},
{true, "ROCKRED3", "ROCKRED1", 8},
{true, "BFALL4", "BFALL1", 8},
{true, "SFALL4", "SFALL1", 8},
{true, "WFALL4", "WFALL1", 8},
{true, "DBRAIN4", "DBRAIN1", 8},
{-1}
};
anim_t anims[MAXANIMS];
anim_t* lastanim;
static anim_t* lastanim;
static anim_t* anims;
// killough 3/7/98: Initialize generalized scrolling
static void P_SpawnScrollers(void);
//
// Animating line specials
//
#define MAXLINEANIMS 64
extern short numlinespecials;
extern line_t* linespeciallist[MAXLINEANIMS];
//#define MAXLINEANIMS 64
//extern short numlinespecials;
//extern line_t* linespeciallist[MAXLINEANIMS];
//
// P_InitPicAnims
//
// Load the table of animation definitions, checking for existence of
// the start and end of each frame. If the start doesn't exist the sequence
// is skipped, if the last doesn't exist, BOOM exits.
//
// Wall/Flat animation sequences, defined by name of first and last frame,
// The full animation sequence is given using all lumps between the start
// and end entry, in the order found in the WAD file.
//
// This routine modified to read its data from a predefined lump or
// PWAD lump called ANIMATED rather than a static table in this module to
// allow wad designers to insert or modify animation sequences.
//
// Lump format is an array of byte packed animdef_t structures, terminated
// by a structure with istexture == -1. The lump can be generated from a
// text source file using SWANTBLS.EXE, distributed with the BOOM utils.
// The standard list of switches and animations is contained in the example
// source text file DEFSWANI.DAT also in the BOOM util distribution.
//
// [RH] Rewritten to support BOOM ANIMATED lump but also make absolutely
// no assumptions about how the compiler packs the animdefs array.
//
void P_InitPicAnims (void)
{
int i;
byte *animdefs = W_CacheLumpName ("ANIMATED", PU_STATIC);
byte *anim_p;
// Init animation
lastanim = anims;
for (i=0 ; animdefs[i].istexture != -1 ; i++)
// [RH] Figure out maximum size of anims array
{
if (animdefs[i].istexture)
int i;
for (i = 0, anim_p = animdefs; *anim_p != 255; anim_p += 23, i++)
;
if (i == 0) {
// No animdefs
anims = lastanim = NULL;
Z_Free (animdefs);
return;
}
lastanim = anims = Z_Malloc (i*sizeof(*anims), PU_STATIC, 0);
}
for (anim_p = animdefs; *anim_p != 255; anim_p += 23)
{
if (*anim_p /* .istexture */)
{
// different episode ?
if (R_CheckTextureNumForName(animdefs[i].startname) == -1)
if (R_CheckTextureNumForName (anim_p + 10 /* .startname */) == -1)
continue;
lastanim->picnum = R_TextureNumForName (animdefs[i].endname);
lastanim->basepic = R_TextureNumForName (animdefs[i].startname);
lastanim->picnum = R_TextureNumForName (anim_p + 1 /* .endname */);
lastanim->basepic = R_TextureNumForName (anim_p + 10 /* .startname */);
}
else
{
if (W_CheckNumForName(animdefs[i].startname) == -1)
if ((W_CheckNumForName)(anim_p + 10 /* .startname */, ns_flats) == -1)
continue;
lastanim->picnum = R_FlatNumForName (animdefs[i].endname);
lastanim->basepic = R_FlatNumForName (animdefs[i].startname);
lastanim->picnum = R_FlatNumForName (anim_p + 1 /* .endname */);
lastanim->basepic = R_FlatNumForName (anim_p + 10 /* .startname */);
}
lastanim->istexture = animdefs[i].istexture;
lastanim->istexture = *anim_p /* .istexture */;
lastanim->numpics = lastanim->picnum - lastanim->basepic + 1;
if (lastanim->numpics < 2)
I_Error ("P_InitPicAnims: bad cycle from %s to %s",
animdefs[i].startname,
animdefs[i].endname);
anim_p + 10 /* .startname */,
anim_p + 1 /* .endname */);
lastanim->speed = animdefs[i].speed;
lastanim->speed = /* .speed */
(anim_p[19] << 0) |
(anim_p[20] << 8) |
(anim_p[21] << 16) |
(anim_p[22] << 24);
lastanim++;
}
Z_Free (animdefs);
}
@ -263,6 +260,34 @@ sector_t *getNextSector (line_t *line, sector_t *sec)
return line->frontsector;
}
//
// P_SectorActive()
//
// Passed a linedef special class (floor, ceiling, lighting) and a sector
// returns whether the sector is already busy with a linedef special of the
// same class. If old demo compatibility true, all linedef special classes
// are the same.
//
// jff 2/23/98 added to prevent old demos from
// succeeding in starting multiple specials on one sector
//
int P_SectorActive(special_e t,sector_t *sec)
{
if (olddemo) { // return whether any thinker is active
return sec->floordata || sec->ceilingdata || sec->lightingdata;
} else {
switch (t) // return whether thinker of same type is active
{
case floor_special:
return (int)sec->floordata;
case ceiling_special:
return (int)sec->ceilingdata;
case lighting_special:
return (int)sec->lightingdata;
}
return 1; // don't know which special, must be active, shouldn't be here
}
}
//
@ -320,44 +345,75 @@ fixed_t P_FindHighestFloorSurrounding(sector_t *sec)
//
// P_FindNextHighestFloor
// FIND NEXT HIGHEST FLOOR IN SURROUNDING SECTORS
fixed_t
P_FindNextHighestFloor
( sector_t* sec,
int currentheight )
// P_FindNextHighestFloor()
//
// Passed a sector and a floor height, returns the fixed point value
// of the smallest floor height in a surrounding sector larger than
// the floor height passed. If no such height exists the floorheight
// passed is returned.
//
// Rewritten by Lee Killough to avoid fixed array and to be faster
//
fixed_t P_FindNextHighestFloor(sector_t *sec, int currentheight)
{
sector_t *other;
int i;
line_t* check;
sector_t* other;
fixed_t min;
min = MAXINT;
for (i = 0; i < sec->linecount; i++) {
check = sec->lines[i];
other = getNextSector (check, sec);
if ((other = getNextSector(sec->lines[i],sec)) &&
other->floorheight > currentheight) {
int height = other->floorheight;
if (!other)
continue;
if (other->floorheight > currentheight && other->floorheight < min)
min = other->floorheight;
while (++i < sec->linecount) {
if ((other = getNextSector(sec->lines[i],sec)) &&
other->floorheight < height &&
other->floorheight > currentheight) {
height = other->floorheight;
}
}
return height;
}
}
if (min == MAXINT)
return currentheight;
else
return min;
}
//
// P_FindNextLowestFloor()
//
// Passed a sector and a floor height, returns the fixed point value
// of the largest floor height in a surrounding sector smaller than
// the floor height passed. If no such height exists the floorheight
// passed is returned.
//
// jff 02/03/98 Twiddled Lee's P_FindNextHighestFloor to make this
//
fixed_t P_FindNextLowestFloor(sector_t *sec, int currentheight)
{
sector_t *other;
int i;
for (i = 0; i < sec->linecount; i++)
if ((other = getNextSector(sec->lines[i],sec)) &&
other->floorheight < currentheight) {
int height = other->floorheight;
while (++i < sec->linecount) {
if ((other = getNextSector(sec->lines[i],sec)) &&
other->floorheight > height &&
other->floorheight < currentheight) {
height = other->floorheight;
}
}
return height;
}
return currentheight;
}
//
// FIND LOWEST CEILING IN THE SURROUNDING SECTORS
//
fixed_t
P_FindLowestCeilingSurrounding(sector_t* sec)
fixed_t P_FindLowestCeilingSurrounding (sector_t *sec)
{
int i;
line_t* check;
@ -382,7 +438,7 @@ P_FindLowestCeilingSurrounding(sector_t* sec)
//
// FIND HIGHEST CEILING IN THE SURROUNDING SECTORS
//
fixed_t P_FindHighestCeilingSurrounding(sector_t* sec)
fixed_t P_FindHighestCeilingSurrounding (sector_t *sec)
{
int i;
line_t* check;
@ -408,10 +464,7 @@ fixed_t P_FindHighestCeilingSurrounding(sector_t* sec)
//
// RETURN NEXT SECTOR # THAT LINE TAG REFERS TO
//
int
P_FindSectorFromLineTag
( line_t* line,
int start )
int P_FindSectorFromLineTag (line_t *line, int start)
{
int i;
@ -422,16 +475,22 @@ P_FindSectorFromLineTag
return -1;
}
int P_FindLineFromLineTag (line_t *line, int start)
{
int i;
for (i = start+1; i < numlines; i++)
if (lines[i].tag == line->tag)
return i;
return -1;
}
//
// Find minimum light from an adjacent sector
//
int
P_FindMinSurroundingLight
( sector_t* sector,
int max )
int P_FindMinSurroundingLight (sector_t *sector, int max)
{
int i;
int min;
@ -466,11 +525,7 @@ P_FindMinSurroundingLight
// Called every time a thing origin is about
// to cross a line with a non 0 special.
//
void
P_CrossSpecialLine
( int linenum,
int side,
mobj_t* thing )
void P_CrossSpecialLine (int linenum, int side, mobj_t *thing)
{
line_t* line;
int ok;
@ -935,10 +990,7 @@ P_CrossSpecialLine
// P_ShootSpecialLine - IMPACT SPECIALS
// Called when a thing shoots a special line.
//
void
P_ShootSpecialLine
( mobj_t* thing,
line_t* line )
void P_ShootSpecialLine (mobj_t *thing, line_t *line)
{
int ok;
@ -1067,7 +1119,6 @@ void P_UpdateSpecials (void)
anim_t* anim;
int pic;
int i;
line_t* line;
// LEVEL TIMER
@ -1096,19 +1147,6 @@ void P_UpdateSpecials (void)
sky1pos = (sky1pos + level.skyspeed1) & 0xffffff;
sky2pos = (sky2pos + level.skyspeed2) & 0xffffff;
// ANIMATE LINE SPECIALS
for (i = 0; i < numlinespecials; i++)
{
line = linespeciallist[i];
switch(line->special)
{
case 48:
// EFFECT FIRSTCOL SCROLL +
sides[line->sidenum[0]].textureoffset += FRACUNIT;
break;
}
}
// DO BUTTONS
for (i = 0; i < MAXBUTTONS; i++)
@ -1160,14 +1198,17 @@ int EV_DoDonut(line_t* line)
rtn = 0;
while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0)
{
s1 = &sectors[secnum];
s1 = &sectors[secnum]; // s1 is pillar's sector
// ALREADY MOVING? IF SO, KEEP GOING...
if (s1->specialdata)
if (P_SectorActive (floor_special, s1)) //jff 2/22/98
continue;
rtn = 1;
s2 = getNextSector(s1->lines[0],s1);
s2 = getNextSector(s1->lines[0],s1); // s2 is pool's sector
if (!s2) // note lowest numbered line around
continue; // pillar must be two-sided
for (i = 0;i < s2->linecount;i++)
{
if ((!s2->lines[i]->flags & ML_TWOSIDED) ||
@ -1178,7 +1219,7 @@ int EV_DoDonut(line_t* line)
// Spawn rising slime
floor = Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0);
P_AddThinker (&floor->thinker);
s2->specialdata = floor;
s2->floordata = floor; //jff 2/22/98
floor->thinker.function.acp1 = (actionf_p1) T_MoveFloor;
floor->type = donutRaise;
floor->crush = false;
@ -1192,7 +1233,7 @@ int EV_DoDonut(line_t* line)
// Spawn lowering donut-hole
floor = Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0);
P_AddThinker (&floor->thinker);
s1->specialdata = floor;
s1->floordata = floor; //jff 2/22/98
floor->thinker.function.acp1 = (actionf_p1) T_MoveFloor;
floor->type = lowerFloor;
floor->crush = false;
@ -1217,11 +1258,7 @@ int EV_DoDonut(line_t* line)
// After the map has been loaded, scan for specials
// that spawn thinkers
//
short numlinespecials;
line_t* linespeciallist[MAXLINEANIMS];
// Parses command line parameters.
void P_SpawnSpecials (void)
{
sector_t* sector;
@ -1293,27 +1330,13 @@ void P_SpawnSpecials (void)
break;
case 17:
// fire flickering
P_SpawnFireFlicker(sector);
break;
}
}
// Init line EFFECTs
numlinespecials = 0;
for (i = 0;i < numlines; i++)
{
switch(lines[i].special)
{
case 48:
// EFFECT FIRSTCOL SCROLL+
linespeciallist[numlinespecials] = &lines[i];
numlinespecials++;
break;
}
}
// Init other misc stuff
if (!activeceilings) {
MaxCeilings = 30; // [RH] Default. Increased as needed.
@ -1334,4 +1357,281 @@ void P_SpawnSpecials (void)
// UNUSED: no horizonal sliders.
// P_InitSlidingDoorFrames();
P_SpawnScrollers(); // killough 3/7/98: Add generalized scrollers
for (i=0; i<numlines; i++)
switch (lines[i].special)
{
int s, sec;
// killough 3/7/98:
// support for drawn heights coming from different sector
case 242:
sec = sides[*lines[i].sidenum].sector-sectors;
for (s = -1; (s = P_FindSectorFromLineTag(lines+i,s)) >= 0;)
sectors[s].heightsec = sec;
break;
// killough 3/16/98: Add support for setting
// floor lighting independently (e.g. lava)
case 213:
sec = sides[*lines[i].sidenum].sector-sectors;
for (s = -1; (s = P_FindSectorFromLineTag(lines+i,s)) >= 0;)
sectors[s].floorlightsec = sec;
break;
// killough 4/11/98: Add support for setting
// ceiling lighting independently
case 261:
sec = sides[*lines[i].sidenum].sector-sectors;
for (s = -1; (s = P_FindSectorFromLineTag(lines+i,s)) >= 0;)
sectors[s].ceilinglightsec = sec;
break;
}
}
// killough 2/28/98:
//
// This function, with the help of r_plane.c and r_bsp.c, supports generalized
// scrolling floors and walls, with optional mobj-carrying properties, e.g.
// conveyor belts, rivers, etc. A linedef with a special type affects all
// tagged sectors the same way, by creating scrolling and/or object-carrying
// properties. Multiple linedefs may be used on the same sector and are
// cumulative, although the special case of scrolling a floor and carrying
// things on it, requires only one linedef. The linedef's direction determines
// the scrolling direction, and the linedef's length determines the scrolling
// speed. This was designed so that an edge around the sector could be used to
// control the direction of the sector's scrolling, which is usually what is
// desired.
//
// Process the active scrollers.
//
// This is the main scrolling code
// killough 3/7/98
void T_Scroll(scroll_t *s)
{
fixed_t dx = s->dx, dy = s->dy;
if (s->control != -1)
{ // compute scroll amounts based on a sector's height changes
fixed_t height = sectors[s->control].floorheight +
sectors[s->control].ceilingheight;
fixed_t delta = height - s->last_height;
s->last_height = height;
dx = FixedMul(dx, delta);
dy = FixedMul(dy, delta);
}
// killough 3/14/98: Add acceleration
if (s->accel)
{
s->vdx = dx += s->vdx;
s->vdy = dy += s->vdy;
}
if (!(dx | dy)) // no-op if both (x,y) offsets 0
return;
switch (s->type)
{
side_t *side;
sector_t *sec;
fixed_t height, waterheight; // killough 4/4/98: add waterheight
msecnode_t *node;
mobj_t *thing;
case sc_side: // killough 3/7/98: Scroll wall texture
side = sides + s->affectee;
side->textureoffset += dx;
side->rowoffset += dy;
break;
case sc_floor: // killough 3/7/98: Scroll floor texture
sec = sectors + s->affectee;
sec->floor_xoffs += dx;
sec->floor_yoffs += dy;
break;
case sc_ceiling: // killough 3/7/98: Scroll ceiling texture
sec = sectors + s->affectee;
sec->ceiling_xoffs += dx;
sec->ceiling_yoffs += dy;
break;
case sc_carry:
// killough 3/7/98: Carry things on floor
// killough 3/20/98: use new sector list which reflects true members
// killough 3/27/98: fix carrier bug
// killough 4/4/98: Underwater, carry things even w/o gravity
sec = sectors + s->affectee;
height = sec->floorheight;
waterheight = sec->heightsec != -1 &&
sectors[sec->heightsec].floorheight > height ?
sectors[sec->heightsec].floorheight : MININT;
for (node = sec->touching_thinglist; node; node = node->m_snext)
if (!((thing = node->m_thing)->flags & MF_NOCLIP) &&
(!(thing->flags & MF_NOGRAVITY || thing->z > height) ||
thing->z < waterheight))
{
// Move objects only if on floor or underwater,
// non-floating, and clipped.
thing->momx += dx;
thing->momy += dy;
}
break;
case sc_carry_ceiling: // to be added later
break;
}
}
//
// Add_Scroller()
//
// Add a generalized scroller to the thinker list.
//
// type: the enumerated type of scrolling: floor, ceiling, floor carrier,
// wall, floor carrier & scroller
//
// (dx,dy): the direction and speed of the scrolling or its acceleration
//
// control: the sector whose heights control this scroller's effect
// remotely, or -1 if no control sector
//
// affectee: the index of the affected object (sector or sidedef)
//
// accel: non-zero if this is an accelerative effect
//
static void Add_Scroller(int type, fixed_t dx, fixed_t dy,
int control, int affectee, int accel)
{
scroll_t *s = Z_Malloc(sizeof *s, PU_LEVSPEC, 0);
s->thinker.function.acp1 = (actionf_p1) T_Scroll;
s->type = type;
s->dx = dx;
s->dy = dy;
s->accel = accel;
s->vdx = s->vdy = 0;
if ((s->control = control) != -1)
s->last_height =
sectors[control].floorheight + sectors[control].ceilingheight;
s->affectee = affectee;
P_AddThinker(&s->thinker);
}
// Adds wall scroller. Scroll amount is rotated with respect to wall's
// linedef first, so that scrolling towards the wall in a perpendicular
// direction is translated into vertical motion, while scrolling along
// the wall in a parallel direction is translated into horizontal motion.
//
// killough 5/25/98: cleaned up arithmetic to avoid drift due to roundoff
static void Add_WallScroller(fixed_t dx, fixed_t dy, const line_t *l,
int control, int accel)
{
fixed_t x = abs(l->dx), y = abs(l->dy), d;
if (y > x)
d = x, x = y, y = d;
d = FixedDiv(x, finesine[(tantoangle[FixedDiv(y,x) >> DBITS] + ANG90)
>> ANGLETOFINESHIFT]);
x = -FixedDiv(FixedMul(dy, l->dy) + FixedMul(dx, l->dx), d);
y = -FixedDiv(FixedMul(dx, l->dy) - FixedMul(dy, l->dx), d);
Add_Scroller(sc_side, x, y, control, *l->sidenum, accel);
}
// Amount (dx,dy) vector linedef is shifted right to get scroll amount
#define SCROLL_SHIFT 5
// Factor to scale scrolling effect into mobj-carrying properties = 3/32.
// (This is so scrolling floors and objects on them can move at same speed.)
#define CARRYFACTOR ((fixed_t)(FRACUNIT*.09375))
// Initialize the scrollers
static void P_SpawnScrollers(void)
{
int i;
line_t *l = lines;
for (i=0;i<numlines;i++,l++)
{
fixed_t dx = l->dx >> SCROLL_SHIFT; // direction and speed of scrolling
fixed_t dy = l->dy >> SCROLL_SHIFT;
int control = -1, accel = 0; // no control sector or acceleration
int special = l->special;
// killough 3/7/98: Types 245-249 are same as 250-254 except that the
// first side's sector's heights cause scrolling when they change, and
// this linedef controls the direction and speed of the scrolling. The
// most complicated linedef since donuts, but powerful :)
//
// killough 3/15/98: Add acceleration. Types 214-218 are the same but
// are accelerative.
if (special >= 245 && special <= 249) // displacement scrollers
{
special += 250-245;
control = sides[*l->sidenum].sector - sectors;
}
else
if (special >= 214 && special <= 218) // accelerative scrollers
{
accel = 1;
special += 250-214;
control = sides[*l->sidenum].sector - sectors;
}
switch (special)
{
register int s;
case 250: // scroll effect ceiling
for (s=-1; (s = P_FindSectorFromLineTag(l,s)) >= 0;)
Add_Scroller(sc_ceiling, -dx, dy, control, s, accel);
break;
case 251: // scroll effect floor
case 253: // scroll and carry objects on floor
for (s=-1; (s = P_FindSectorFromLineTag(l,s)) >= 0;)
Add_Scroller(sc_floor, -dx, dy, control, s, accel);
if (special != 253)
break;
case 252: // carry objects on floor
dx = FixedMul(dx,CARRYFACTOR);
dy = FixedMul(dy,CARRYFACTOR);
for (s=-1; (s = P_FindSectorFromLineTag(l,s)) >= 0;)
Add_Scroller(sc_carry, dx, dy, control, s, accel);
break;
// killough 3/1/98: scroll wall according to linedef
// (same direction and speed as scrolling floors)
case 254:
for (s=-1; (s = P_FindLineFromLineTag(l,s)) >= 0;)
if (s != i)
Add_WallScroller(dx, dy, lines+s, control, accel);
break;
case 255: // killough 3/2/98: scroll according to sidedef offsets
s = lines[i].sidenum[0];
Add_Scroller(sc_side, -sides[s].textureoffset,
sides[s].rowoffset, -1, s, accel);
break;
case 48: // scroll first side
Add_Scroller(sc_side, FRACUNIT, 0, -1, lines[i].sidenum[0], accel);
break;
case 85: // jff 1/30/98 2-way scroll
Add_Scroller(sc_side, -FRACUNIT, 0, -1, lines[i].sidenum[0], accel);
break;
}
}
}
// killough 3/7/98 -- end generalized scroll effects

View file

@ -27,6 +27,36 @@
#define __P_SPEC__
//jff 2/23/98 identify the special classes that can share sectors
typedef enum
{
floor_special,
ceiling_special,
lighting_special,
} special_e;
// killough 3/7/98: Add generalized scroll effects
typedef struct {
thinker_t thinker; // Thinker structure for scrolling
fixed_t dx, dy; // (dx,dy) scroll speeds
int affectee; // Number of affected sidedef, sector, tag, or whatever
int control; // Control sector (-1 if none) used to control scrolling
fixed_t last_height; // Last known height of control sector
fixed_t vdx, vdy; // Accumulated velocity if accelerative
int accel; // Whether it's accelerative
enum
{
sc_side,
sc_floor,
sc_ceiling,
sc_carry,
sc_carry_ceiling, // killough 4/11/98: carry objects hanging on ceilings
} type; // Type of scroll effect
} scroll_t;
// Define values for map objects
#define MO_TELEPORTMAN 14
@ -64,6 +94,7 @@ fixed_t P_FindLowestFloorSurrounding (sector_t *sec);
fixed_t P_FindHighestFloorSurrounding (sector_t *sec);
fixed_t P_FindNextHighestFloor (sector_t *sec, int currentheight);
fixed_t P_FindNextLowestFloor (sector_t* sec, int currentheight);
fixed_t P_FindLowestCeilingSurrounding (sector_t *sec);
fixed_t P_FindHighestCeilingSurrounding (sector_t *sec);
@ -75,6 +106,9 @@ int P_FindMinSurroundingLight (sector_t *sector, int max);
sector_t *getNextSector (line_t *line, sector_t *sec);
void T_Scroll (scroll_t *); // killough 3/7/98: scroll effect thinker
//
// SPECIAL
//
@ -191,11 +225,8 @@ typedef struct
// max # of wall switches in a level
#define MAXSWITCHES 50
// 4 players, 4 buttons each at once, max.
#define MAXBUTTONS 16
#define MAXBUTTONS (MAXPLAYERS*4)
// 1 second, in ticks.
#define BUTTONTIME TICRATE
@ -463,42 +494,24 @@ void P_ActivateInStasisCeiling(line_t *line);
//
typedef enum
{
// lower floor to highest surrounding floor
lowerFloor,
// lower floor to lowest surrounding floor
lowerFloorToLowest,
// lower floor to highest surrounding floor VERY FAST
turboLower,
// raise floor to lowest surrounding CEILING
raiseFloor,
// raise floor to next highest surrounding floor
raiseFloorToNearest,
// raise floor to shortest height texture around it
raiseToTexture,
// lower floor to lowest surrounding floor
// and change floorpic
lowerAndChange,
lowerFloor, // lower floor to highest surrounding floor
lowerFloorToLowest, // lower floor to lowest surrounding floor
turboLower, // lower floor to highest surrounding floor VERY FAST
raiseFloor, // raise floor to lowest surrounding CEILING
raiseFloorToNearest, // raise floor to next highest surrounding floor
raiseToTexture, // raise floor to shortest height texture around it
lowerAndChange, // lower floor to lowest surrounding floor and change floorpic
raiseFloor24,
raiseFloor24AndChange,
raiseFloorCrush,
// raise to next highest floor, turbo-speed
raiseFloorTurbo,
raiseFloorTurbo, // raise to next highest floor, turbo-speed
donutRaise,
raiseFloor512
} floor_e;
typedef enum
{
build8, // slowly build by 8
@ -506,7 +519,12 @@ typedef enum
} stair_e;
typedef enum
{
elevateUp,
elevateDown,
elevateCurrent,
} elevator_e;
typedef struct
{
@ -522,8 +540,19 @@ typedef struct
} floormove_t;
typedef struct
{
thinker_t thinker;
elevator_e type;
sector_t* sector;
int direction;
fixed_t floordestheight;
fixed_t ceilingdestheight;
fixed_t speed;
} elevator_t;
#define ELEVATORSPEED (FRACUNIT*4)
#define FLOORSPEED FRACUNIT
typedef enum
@ -537,20 +566,23 @@ typedef enum
result_e T_MovePlane (sector_t *sector, fixed_t speed, fixed_t dest,
BOOL crush, int floorOrCeiling, int direction);
int EV_DoElevator (line_t *line, ceiling_e type);
int EV_BuildStairs (line_t *line, stair_e type);
int EV_DoFloor (line_t *line, floor_e floortype);
void T_MoveFloor (floormove_t *floor);
void T_MoveElevator (elevator_t *elevator);
//
// P_TELEPT
//
int EV_Teleport (line_t *line, int side, mobj_t *thing);
int P_SectorActive (special_e t, sector_t *s); // [RH] from BOOM
#endif
//-----------------------------------------------------------------------------
//
// $Log:$
//
//-----------------------------------------------------------------------------

View file

@ -39,75 +39,42 @@
#include "doomstat.h"
#include "r_state.h"
#include "z_zone.h"
#include "w_wad.h"
//
// CHANGE THE TEXTURE OF A WALL SWITCH TO ITS OPPOSITE
//
switchlist_t alphSwitchList[] =
{
// Doom shareware episode 1 switches
{"SW1BRCOM", "SW2BRCOM", 1},
{"SW1BRN1", "SW2BRN1", 1},
{"SW1BRN2", "SW2BRN2", 1},
{"SW1BRNGN", "SW2BRNGN", 1},
{"SW1BROWN", "SW2BROWN", 1},
{"SW1COMM", "SW2COMM", 1},
{"SW1COMP", "SW2COMP", 1},
{"SW1DIRT", "SW2DIRT", 1},
{"SW1EXIT", "SW2EXIT", 1},
{"SW1GRAY", "SW2GRAY", 1},
{"SW1GRAY1", "SW2GRAY1", 1},
{"SW1METAL", "SW2METAL", 1},
{"SW1PIPE", "SW2PIPE", 1},
{"SW1SLAD", "SW2SLAD", 1},
{"SW1STARG", "SW2STARG", 1},
{"SW1STON1", "SW2STON1", 1},
{"SW1STON2", "SW2STON2", 1},
{"SW1STONE", "SW2STONE", 1},
{"SW1STRTN", "SW2STRTN", 1},
// Doom registered episodes 2&3 switches
{"SW1BLUE", "SW2BLUE", 2},
{"SW1CMT", "SW2CMT", 2},
{"SW1GARG", "SW2GARG", 2},
{"SW1GSTON", "SW2GSTON", 2},
{"SW1HOT", "SW2HOT", 2},
{"SW1LION", "SW2LION", 2},
{"SW1SATYR", "SW2SATYR", 2},
{"SW1SKIN", "SW2SKIN", 2},
{"SW1VINE", "SW2VINE", 2},
{"SW1WOOD", "SW2WOOD", 2},
static int *switchlist;
static int numswitches;
// Doom II switches
{"SW1PANEL", "SW2PANEL", 3},
{"SW1ROCK", "SW2ROCK", 3},
{"SW1MET2", "SW2MET2", 3},
{"SW1WDMET", "SW2WDMET", 3},
{"SW1BRIK", "SW2BRIK", 3},
{"SW1MOD1", "SW2MOD1", 3},
{"SW1ZIM", "SW2ZIM", 3},
{"SW1STON6", "SW2STON6", 3},
{"SW1TEK", "SW2TEK", 3},
{"SW1MARB", "SW2MARB", 3},
{"SW1SKULL", "SW2SKULL", 3},
{"\0", "\0", 0}
};
int switchlist[MAXSWITCHES * 2];
int numswitches;
button_t buttonlist[MAXBUTTONS];
//
// P_InitSwitchList
// Only called at game initialization.
//
// [RH] Rewritten to use a BOOM-style SWITCHES lump and remove the
// MAXSWITCHES limit.
void P_InitSwitchList(void)
{
byte *alphSwitchList = W_CacheLumpName ("SWITCHES", PU_STATIC);
byte *list_p;
int i;
int index;
int episode;
for (i = 0, list_p = alphSwitchList; list_p[18] || list_p[19]; list_p += 20, i++)
;
if (i == 0) {
switchlist = Z_Malloc (sizeof(*switchlist), PU_STATIC, 0);
*switchlist = -1;
numswitches = 0;
} else {
switchlist = Z_Malloc (sizeof(*switchlist)*(i*2+1), PU_STATIC, 0);
if (gamemode == registered || gamemode == retail)
episode = 2;
else if ( gamemode == commercial )
@ -115,38 +82,22 @@ void P_InitSwitchList(void)
else
episode = 1;
for (index = 0,i = 0;i < MAXSWITCHES;i++)
for (i = 0, list_p = alphSwitchList; list_p[18] || list_p[19]; list_p += 20) {
if (episode >= (list_p[18] | (list_p[19] << 8)))
{
if (!alphSwitchList[i].episode)
{
numswitches = index/2;
switchlist[index] = -1;
break;
}
if (alphSwitchList[i].episode <= episode)
{
#if 0 // UNUSED - debug?
int value;
if (R_CheckTextureNumForName(alphSwitchList[i].name1) < 0)
{
I_Error("Can't find switch texture '%s'!",
alphSwitchList[i].name1);
continue;
}
value = R_TextureNumForName(alphSwitchList[i].name1);
#endif
// [RH] Skip this switch if it can't be found (since I want to see
// how well ZDoom will run with heretic.wad :-)
if (R_CheckTextureNumForName (alphSwitchList[i].name1) < 0)
// [RH] Skip this switch if it can't be found.
if (R_CheckTextureNumForName (list_p /* .name1 */) < 0)
continue;
switchlist[index++] = R_TextureNumForName(alphSwitchList[i].name1);
switchlist[index++] = R_TextureNumForName(alphSwitchList[i].name2);
switchlist[i++] = R_TextureNumForName(list_p /* .name1 */);
switchlist[i++] = R_TextureNumForName(list_p + 9 /* .name2 */);
}
}
numswitches = i/2;
switchlist[i] = -1;
}
Z_Free (alphSwitchList);
}

View file

@ -49,15 +49,15 @@ line_t* linedef;
sector_t* frontsector;
sector_t* backsector;
// killough 4/7/98: indicates doors closed wrt automap bugfix:
int doorclosed;
int MaxDrawSegs;
drawseg_t *drawsegs;
drawseg_t* ds_p;
void
R_StoreWallRange
( int start,
int stop );
void R_StoreWallRange (int start, int stop);
@ -81,11 +81,13 @@ void R_ClearDrawSegs (void)
// Clips the given range of columns
// and includes it in the new clip list.
//
typedef struct
{
int first;
int last;
//
// 1/11/98 killough: Since a type "short" is sufficient, we
// should use it, since smaller arrays fit better in cache.
//
typedef struct {
short first, last; // killough
} cliprange_t;
@ -104,13 +106,9 @@ cliprange_t *lastsolidseg;
// e.g. single sided LineDefs (middle texture)
// that entirely block the view.
//
void
R_ClipSolidWallSegment
( int first,
int last )
void R_ClipSolidWallSegment (int first, int last)
{
cliprange_t* next;
cliprange_t* start;
cliprange_t *next, *start;
// Find the first range that touches the range
// (adjacent pixels are touching).
@ -122,35 +120,19 @@ R_ClipSolidWallSegment
{
if (last < start->first-1)
{
// Post is entirely visible (above start),
// so insert a new clippost.
// Post is entirely visible (above start), so insert a new clippost.
R_StoreWallRange (first, last);
// [RH] Get more solidsegs if needed.
if (newend == lastsolidseg) {
int i = start - solidsegs;
MaxSegs += 8;
solidsegs = Realloc (solidsegs, MaxSegs * sizeof(cliprange_t));
newend = &solidsegs[MaxSegs - 8];
start = &solidsegs[i];
lastsolidseg = &solidsegs[MaxSegs];
DPrintf ("MaxSegs increased to %d\n", MaxSegs);
}
next = newend;
newend++;
while (next != start)
{
*next = *(next-1);
next--;
}
next->first = first;
next->last = last;
// 1/11/98 killough: performance tuning using fast memmove
memmove(start+1,start,(++newend-start)*sizeof(*start));
start->first = first;
start->last = last;
return;
}
// There is a fragment above *start.
R_StoreWallRange (first, start->first - 1);
// Now adjust the clip size.
start->first = first;
}
@ -168,8 +150,7 @@ R_ClipSolidWallSegment
if (last <= next->last)
{
// Bottom is contained in next.
// Adjust the clip size.
// Bottom is contained in next. Adjust the clip size.
start->last = next->last;
goto crunch;
}
@ -208,12 +189,9 @@ R_ClipSolidWallSegment
// Does handle windows,
// e.g. LineDefs with upper and lower texture.
//
void
R_ClipPassWallSegment
( int first,
int last )
void R_ClipPassWallSegment (int first, int last)
{
cliprange_t* start;
cliprange_t *start;
// Find the first range that touches the range
// (adjacent pixels are touching).
@ -264,13 +242,144 @@ void R_ClearClipSegs (void)
solidsegs = Malloc (MaxSegs * sizeof(cliprange_t));
lastsolidseg = &solidsegs[MaxSegs];
}
solidsegs[0].first = -0x7fffffff;
solidsegs[0].first = -0x7fff; // new short limit -- killough
solidsegs[0].last = -1;
solidsegs[1].first = viewwidth;
solidsegs[1].last = 0x7fffffff;
solidsegs[1].last = 0x7fff; // new short limit -- killough
newend = solidsegs+2;
}
// killough 1/18/98 -- This function is used to fix the automap bug which
// showed lines behind closed doors simply because the door had a dropoff.
//
// It assumes that Doom has already ruled out a door being closed because
// of front-back closure (e.g. front floor is taller than back ceiling).
int R_DoorClosed(void)
{
return
// if door is closed because back is shut:
backsector->ceilingheight <= backsector->floorheight
// preserve a kind of transparent door/lift special effect:
&& (backsector->ceilingheight >= frontsector->ceilingheight ||
curline->sidedef->toptexture)
&& (backsector->floorheight <= frontsector->floorheight ||
curline->sidedef->bottomtexture)
// properly render skies (consider door "open" if both ceilings are sky):
&& (backsector->ceilingpic !=skyflatnum ||
frontsector->ceilingpic!=skyflatnum);
}
//
// killough 3/7/98: Hack floor/ceiling heights for deep water etc.
//
// If player's view height is underneath fake floor, lower the
// drawn ceiling to be just under the floor height, and replace
// the drawn floor and ceiling textures, and light level, with
// the control sector's.
//
// Similar for ceiling, only reflected.
//
// killough 4/11/98, 4/13/98: fix bugs, add 'back' parameter
//
sector_t *R_FakeFlat(sector_t *sec, sector_t *tempsec,
int *floorlightlevel, int *ceilinglightlevel,
BOOL back)
{
if (floorlightlevel)
*floorlightlevel = sec->floorlightsec == -1 ?
sec->lightlevel : sectors[sec->floorlightsec].lightlevel;
if (ceilinglightlevel)
*ceilinglightlevel = sec->ceilinglightsec == -1 ? // killough 4/11/98
sec->lightlevel : sectors[sec->ceilinglightsec].lightlevel;
if (sec->heightsec != -1)
{
const sector_t *s = &sectors[sec->heightsec];
int heightsec = viewplayer->mo->subsector->sector->heightsec;
int underwater = heightsec!=-1 && viewz<=sectors[heightsec].floorheight;
// Replace sector being drawn, with a copy to be hacked
*tempsec = *sec;
// Replace floor and ceiling height with other sector's heights.
tempsec->floorheight = s->floorheight;
tempsec->ceilingheight = s->ceilingheight;
if ((underwater && (tempsec-> floorheight = sec->floorheight,
tempsec->ceilingheight = s->floorheight-1,
!back)) || viewz <= s->floorheight)
{ // head-below-floor hack
tempsec->floorpic = s->floorpic;
tempsec->floor_xoffs = s->floor_xoffs;
tempsec->floor_yoffs = s->floor_yoffs;
if (underwater)
if (s->ceilingpic == skyflatnum)
{
tempsec->floorheight = tempsec->ceilingheight+1;
tempsec->ceilingpic = tempsec->floorpic;
tempsec->ceiling_xoffs = tempsec->floor_xoffs;
tempsec->ceiling_yoffs = tempsec->floor_yoffs;
}
else
{
tempsec->ceilingpic = s->ceilingpic;
tempsec->ceiling_xoffs = s->ceiling_xoffs;
tempsec->ceiling_yoffs = s->ceiling_yoffs;
}
tempsec->lightlevel = s->lightlevel;
if (floorlightlevel)
*floorlightlevel = s->floorlightsec == -1 ? s->lightlevel :
sectors[s->floorlightsec].lightlevel; // killough 3/16/98
if (ceilinglightlevel)
*ceilinglightlevel = s->ceilinglightsec == -1 ? s->lightlevel :
sectors[s->ceilinglightsec].lightlevel; // killough 4/11/98
}
else
if (heightsec != -1 && viewz >= sectors[heightsec].ceilingheight &&
sec->ceilingheight > s->ceilingheight)
{ // Above-ceiling hack
tempsec->ceilingheight = s->ceilingheight;
tempsec->floorheight = s->ceilingheight + 1;
tempsec->floorpic = tempsec->ceilingpic = s->ceilingpic;
tempsec->floor_xoffs = tempsec->ceiling_xoffs = s->ceiling_xoffs;
tempsec->floor_yoffs = tempsec->ceiling_yoffs = s->ceiling_yoffs;
if (s->floorpic != skyflatnum)
{
tempsec->ceilingheight = sec->ceilingheight;
tempsec->floorpic = s->floorpic;
tempsec->floor_xoffs = s->floor_xoffs;
tempsec->floor_yoffs = s->floor_yoffs;
}
tempsec->lightlevel = s->lightlevel;
if (floorlightlevel)
*floorlightlevel = s->floorlightsec == -1 ? s->lightlevel :
sectors[s->floorlightsec].lightlevel; // killough 3/16/98
if (ceilinglightlevel)
*ceilinglightlevel = s->ceilinglightsec == -1 ? s->lightlevel :
sectors[s->ceilinglightsec].lightlevel; // killough 4/11/98
}
sec = tempsec; // Use other sector
}
return sec;
}
//
// R_AddLine
// Clips the given segment
@ -284,6 +393,7 @@ void R_AddLine (seg_t* line)
angle_t angle2;
angle_t span;
angle_t tspan;
static sector_t tempsec; // killough 3/8/98: ceiling/water hack
curline = line;
@ -330,11 +440,13 @@ void R_AddLine (seg_t* line)
// but not necessarily visible.
angle1 = (angle1+ANG90)>>ANGLETOFINESHIFT;
angle2 = (angle2+ANG90)>>ANGLETOFINESHIFT;
// killough 1/31/98: Here is where "slime trails" can SOMETIMES occur:
x1 = viewangletox[angle1];
x2 = viewangletox[angle2];
// Does not cross a pixel?
if (x1 == x2)
if (x1 >= x2) // killough 1/31/98 -- change == to >= for robustness
return;
backsector = line->backsector;
@ -343,11 +455,21 @@ void R_AddLine (seg_t* line)
if (!backsector)
goto clipsolid;
// killough 3/8/98, 4/4/98: hack for invisible ceilings / deep water
backsector = R_FakeFlat (backsector, &tempsec, NULL, NULL, true);
doorclosed = 0; // killough 4/16/98
// Closed door.
if (backsector->ceilingheight <= frontsector->floorheight
|| backsector->floorheight >= frontsector->ceilingheight)
goto clipsolid;
// This fixes the automap floor height bug -- killough 1/18/98:
// killough 4/7/98: optimize: save result in doorclosed for use in r_segs.c
if ((doorclosed = R_DoorClosed()))
goto clipsolid;
// Window.
if (backsector->ceilingheight != frontsector->ceilingheight
|| backsector->floorheight != frontsector->floorheight)
@ -361,7 +483,18 @@ void R_AddLine (seg_t* line)
if (backsector->ceilingpic == frontsector->ceilingpic
&& backsector->floorpic == frontsector->floorpic
&& backsector->lightlevel == frontsector->lightlevel
&& curline->sidedef->midtexture == 0)
&& curline->sidedef->midtexture == 0
// killough 3/7/98: Take flats offsets into account:
&& backsector->floor_xoffs == frontsector->floor_xoffs
&& backsector->floor_yoffs == frontsector->floor_yoffs
&& backsector->ceiling_xoffs == frontsector->ceiling_xoffs
&& backsector->ceiling_yoffs == frontsector->ceiling_yoffs
// killough 4/16/98: consider altered lighting
&& backsector->floorlightsec == frontsector->floorlightsec
&& backsector->ceilinglightsec == frontsector->ceilinglightsec
)
{
return;
}
@ -382,7 +515,7 @@ void R_AddLine (seg_t* line)
// Returns true
// if some part of the bbox might be visible.
//
int checkcoord[12][4] =
static const int checkcoord[12][4] = // killough -- static const
{
{3,0,2,1},
{3,0,2,0},
@ -398,7 +531,7 @@ int checkcoord[12][4] =
};
BOOL R_CheckBBox (fixed_t* bspcoord)
static BOOL R_CheckBBox (fixed_t *bspcoord) // killough 1/28/98: static
{
int boxx;
int boxy;
@ -518,39 +651,48 @@ void R_Subsector (int num)
{
int count;
seg_t* line;
subsector_t* sub;
subsector_t *sub;
sector_t tempsec; // killough 3/7/98: deep water hack
int floorlightlevel; // killough 3/16/98: set floor lightlevel
int ceilinglightlevel; // killough 4/11/98
#ifdef RANGECHECK
if (num>=numsubsectors)
I_Error ("R_Subsector: ss %i with numss = %i",
num,
numsubsectors);
I_Error ("R_Subsector: ss %i with numss = %i", num, numsubsectors);
#endif
sscount++;
sub = &subsectors[num];
frontsector = sub->sector;
count = sub->numlines;
line = &segs[sub->firstline];
if (frontsector->floorheight < viewz)
{
floorplane = R_FindPlane (frontsector->floorheight,
frontsector->floorpic,
frontsector->lightlevel);
}
else
floorplane = NULL;
// killough 3/8/98, 4/4/98: Deep water / fake ceiling effect
frontsector = R_FakeFlat(frontsector, &tempsec, &floorlightlevel,
&ceilinglightlevel, false); // killough 4/11/98
if (frontsector->ceilingheight > viewz
|| frontsector->ceilingpic == skyflatnum)
{
ceilingplane = R_FindPlane (frontsector->ceilingheight,
// killough 3/7/98: Add (x,y) offsets to flats, add deep water check
// killough 3/16/98: add floorlightlevel
floorplane = frontsector->floorheight < viewz || // killough 3/7/98
(frontsector->heightsec != -1 &&
sectors[frontsector->heightsec].ceilingpic == skyflatnum) ?
R_FindPlane(frontsector->floorheight,
frontsector->floorpic,
floorlightlevel, // killough 3/16/98
frontsector->floor_xoffs, // killough 3/7/98
frontsector->floor_yoffs
) : NULL;
ceilingplane = frontsector->ceilingheight > viewz ||
frontsector->ceilingpic == skyflatnum ||
(frontsector->heightsec != -1 &&
sectors[frontsector->heightsec].floorpic == skyflatnum) ?
R_FindPlane(frontsector->ceilingheight, // killough 3/8/98
frontsector->ceilingpic,
frontsector->lightlevel);
}
else
ceilingplane = NULL;
ceilinglightlevel, // killough 4/11/98
frontsector->ceiling_xoffs, // killough 3/7/98
frontsector->ceiling_yoffs
) : NULL;
R_AddSprites (frontsector);
@ -569,32 +711,26 @@ void R_Subsector (int num)
// Renders all subsectors below a given node,
// traversing subtree recursively.
// Just call with BSP root.
void R_RenderBSPNode (int bspnum)
// killough 5/2/98: reformatted, removed tail recursion
void R_RenderBSPNode(int bspnum)
{
node_t* bsp;
int side;
// Found a subsector?
if (bspnum & NF_SUBSECTOR)
while (!(bspnum & NF_SUBSECTOR)) // Found a subsector?
{
if (bspnum == -1)
R_Subsector (0);
else
R_Subsector (bspnum&(~NF_SUBSECTOR));
return;
}
bsp = &nodes[bspnum];
node_t *bsp = &nodes[bspnum];
// Decide which side the view point is on.
side = R_PointOnSide (viewx, viewy, bsp);
int side = R_PointOnSide(viewx, viewy, bsp);
// Recursively divide front space.
R_RenderBSPNode (bsp->children[side]);
R_RenderBSPNode(bsp->children[side]);
// Possibly divide back space.
if (R_CheckBBox (bsp->bbox[side^1]))
R_RenderBSPNode (bsp->children[side^1]);
if (!R_CheckBBox(bsp->bbox[side^1]))
return;
bspnum = bsp->children[side^1];
}
R_Subsector(bspnum == -1 ? 0 : bspnum & ~NF_SUBSECTOR);
}

View file

@ -44,10 +44,6 @@ extern BOOL skymap;
extern drawseg_t *drawsegs;
extern drawseg_t* ds_p;
extern lighttable_t** hscalelight;
extern lighttable_t** vscalelight;
extern lighttable_t** dscalelight;
typedef void (*drawfunc_t) (int start, int stop);
@ -55,9 +51,11 @@ typedef void (*drawfunc_t) (int start, int stop);
// BSP?
void R_ClearClipSegs (void);
void R_ClearDrawSegs (void);
void R_RenderBSPNode (int bspnum);
int R_DoorClosed(void); // killough 1/17/98
// killough 4/13/98: fake floors/ceilings for deep water / fake ceilings:
sector_t *R_FakeFlat(sector_t *, sector_t *, int *, int *, BOOL);
#endif

View file

@ -27,6 +27,7 @@
#include "i_system.h"
#include "z_zone.h"
#include "m_alloc.h"
#include "m_swap.h"
@ -84,7 +85,7 @@ typedef struct
BOOL masked;
short width;
short height;
void **columndirectory; // OBSOLETE
byte pad[4]; // OBSOLETE (was short **columndirectory)
short patchcount;
mappatch_t patches[1];
} maptexture_t;
@ -146,7 +147,7 @@ static byte* textureheightmask; // [RH] Tutti-Frutti fix
fixed_t* textureheight; // needed for texture pegging
static int* texturecompositesize;
static short** texturecolumnlump;
static unsigned short**texturecolumnofs;
static unsigned **texturecolumnofs; // killough 4/9/98: make 32-bit
static byte** texturecomposite;
// for global animation
@ -175,12 +176,11 @@ fixed_t* spritetopoffset;
// Rewritten by Lee Killough for performance and to fix Medusa bug
//
// R_DrawColumnInCache
// Clip and draw a column
// from a patch into a cached post.
//
void R_DrawColumnInCache (column_t *patch, byte *cache, int originy, int cacheheight)
void R_DrawColumnInCache (const column_t *patch, byte *cache,
int originy, int cacheheight, byte *marks)
{
while (patch->topdelta != 0xff)
{
@ -197,151 +197,192 @@ void R_DrawColumnInCache (column_t *patch, byte *cache, int originy, int cachehe
count = cacheheight - position;
if (count > 0)
{
memcpy (cache + position, (byte *)patch + 3, count);
patch = (column_t *)( (byte *)patch + patch->length + 4);
// killough 4/9/98: remember which cells in column have been drawn,
// so that column can later be converted into a series of posts, to
// fix the Medusa bug.
memset (marks + position, 0xff, count);
}
patch = (column_t *)((byte *) patch + patch->length + 4);
}
}
//
// R_GenerateComposite
// Using the texture definition,
// the composite texture is created from the patches,
// and each column is cached.
//
// Rewritten by Lee Killough for performance and to fix Medusa bug
void R_GenerateComposite (int texnum)
{
byte* block;
texture_t* texture;
texpatch_t* patch;
int i;
column_t* patchcol;
short* collump;
unsigned short* colofs;
texture = textures[texnum];
block = Z_Malloc (texturecompositesize[texnum], PU_STATIC,
&texturecomposite[texnum]);
collump = texturecolumnlump[texnum];
colofs = texturecolumnofs[texnum];
byte *block = Z_Malloc(texturecompositesize[texnum], PU_STATIC,
(void **) &texturecomposite[texnum]);
texture_t *texture = textures[texnum];
// Composite the columns together.
patch = texture->patches;
texpatch_t *patch = texture->patches;
short *collump = texturecolumnlump[texnum];
unsigned *colofs = texturecolumnofs[texnum]; // killough 4/9/98: make 32-bit
int i = texture->patchcount;
// killough 4/9/98: marks to identify transparent regions in merged textures
byte *marks = Calloc(texture->width, texture->height), *source;
for (i = texture->patchcount, patch = texture->patches; i > 0; i--, patch++)
for (; --i >=0; patch++)
{
patch_t *realpatch = W_CacheLumpNum (patch->patch, PU_CACHE);
int x1 = patch->originx;
int x2 = x1 + SHORT(realpatch->width);
int x = (x1 < 0) ? 0 : x1;
patch_t *realpatch = W_CacheLumpNum(patch->patch, PU_CACHE);
int x1 = patch->originx, x2 = x1 + SHORT(realpatch->width);
const int *cofs = realpatch->columnofs-x1;
if (x1<0)
x1 = 0;
if (x2 > texture->width)
x2 = texture->width;
for (; x1<x2 ; x1++)
if (collump[x1] == -1) // Column has multiple patches?
// killough 1/25/98, 4/9/98: Fix medusa bug.
R_DrawColumnInCache((column_t*)((byte*)realpatch+LONG(cofs[x1])),
block+colofs[x1],patch->originy,texture->height,
marks + x1 * texture->height);
}
for ( ; x < x2; x++)
// killough 4/9/98: Next, convert multipatched columns into true columns,
// to fix Medusa bug while still allowing for transparent regions.
source = malloc(texture->height); // temporary column
for (i=0; i < texture->width; i++)
if (collump[i] == -1) // process only multipatched columns
{
// Column does not have multiple patches?
if (collump[x] >= 0)
continue;
column_t *col = (column_t *)(block + colofs[i] - 3); // cached column
const byte *mark = marks + i * texture->height;
int j = 0;
patchcol = (column_t *)((byte *)realpatch
+ LONG(realpatch->columnofs[x-x1]));
R_DrawColumnInCache (patchcol,
block + colofs[x],
patch->originy,
texture->height);
}
// save column in temporary so we can shuffle it around
memcpy(source, (byte *) col + 3, texture->height);
for (;;) // reconstruct the column by scanning transparency marks
{
while (j < texture->height && !mark[j]) // skip transparent cells
j++;
if (j >= texture->height) // if at end of column
{
col->topdelta = -1; // end-of-column marker
break;
}
col->topdelta = j; // starting offset of post
for (col->length=0; j < texture->height && mark[j]; j++)
col->length++; // count opaque cells
// copy opaque cells from the temporary back into the column
memcpy((byte *) col + 3, source + col->topdelta, col->length);
col = (column_t *)((byte *) col + col->length + 4); // next post
}
}
free(source); // free temporary column
free(marks); // free transparency marks
// Now that the texture has been built in column cache,
// it is purgable from zone memory.
Z_ChangeTag (block, PU_CACHE);
Z_ChangeTag(block, PU_CACHE);
}
//
// R_GenerateLookup
//
void R_GenerateLookup (int texnum)
{
texture_t* texture;
byte* patchcount; // patchcount[texture->width]
texpatch_t* patch;
int i;
short* collump;
unsigned short* colofs;
// Rewritten by Lee Killough for performance and to fix Medusa bug
//
texture = textures[texnum];
static void R_GenerateLookup(int texnum, int *const errors)
{
const texture_t *texture = textures[texnum];
// Composited texture not created yet.
texturecomposite[texnum] = 0;
texturecompositesize[texnum] = 0;
collump = texturecolumnlump[texnum];
colofs = texturecolumnofs[texnum];
short *collump = texturecolumnlump[texnum];
unsigned *colofs = texturecolumnofs[texnum]; // killough 4/9/98: make 32-bit
// killough 4/9/98: keep count of posts in addition to patches.
// Part of fix for medusa bug for multipatched 2s normals.
struct {
unsigned short patches, posts;
} *count = Calloc(sizeof *count, texture->width);
{
int i = texture->patchcount;
const texpatch_t *patch = texture->patches;
while (--i >= 0)
{
int pat = patch->patch;
const patch_t *realpatch = W_CacheLumpNum(pat, PU_CACHE);
int x1 = patch++->originx, x2 = x1 + SHORT(realpatch->width), x = x1;
const int *cofs = realpatch->columnofs-x1;
if (x2 > texture->width)
x2 = texture->width;
if (x1 < 0)
x = 0;
for ( ; x<x2 ; x++)
{
// killough 4/9/98: keep a count of the number of posts in column,
// to fix Medusa bug while allowing for transparent multipatches.
const column_t *col = (column_t*)((byte*)realpatch+LONG(cofs[x]));
for (;col->topdelta != 0xff; count[x].posts++)
col = (column_t *)((byte *) col + col->length + 4);
count[x].patches++;
collump[x] = pat;
colofs[x] = LONG(cofs[x])+3;
}
}
}
// Now count the number of columns
// that are covered by more than one patch.
// Fill in the lump / offset, so columns
// with only a single patch are all done.
patchcount = (byte *)Z_Malloc (texture->width, PU_STATIC, 0);
memset (patchcount, 0, texture->width);
patch = texture->patches;
for (i = texture->patchcount, patch = texture->patches; i > 0; i--, patch++)
texturecomposite[texnum] = 0;
{
patch_t *realpatch = W_CacheLumpNum (patch->patch, PU_CACHE);
int x1 = patch->originx;
int x2 = x1 + SHORT(realpatch->width);
int x = (x1 < 0) ? 0 : x1;
int x = texture->width;
int height = texture->height;
int csize = 0;
if (x2 > texture->width)
x2 = texture->width;
for ( ; x < x2 ; x++)
while (--x >= 0)
{
patchcount[x]++;
collump[x] = (short)patch->patch;
colofs[x] = (short)(LONG(realpatch->columnofs[x-x1])+3);
}
}
for (i = 0; i < texture->width; i++)
if (!count[x].patches) // killough 4/9/98
{
if (!patchcount[i])
Printf("\nR_GenerateLookup: Column %d is without a patch in texture %.8s",
x, texture->name);
++*errors;
}
if (count[x].patches > 1) // killough 4/9/98
{
char namet[9];
strncpy (namet, texture->name, 8);
namet[8] = 0;
// I_Error ("R_GenerateLookup: column without a patch");
Printf ("R_GenerateLookup: column without a patch (%s)\n", namet);
return;
}
// killough 1/25/98, 4/9/98:
//
// Fix Medusa bug, by adding room for column header
// and trailer bytes for each post in merged column.
// For now, just allocate conservatively 4 bytes
// per post per patch per column, since we don't
// yet know how many posts the merged column will
// require, and it's bounded above by this limit.
if (patchcount[i] > 1)
{
// Use the cached block.
collump[i] = -1;
colofs[i] = (short)texturecompositesize[texnum];
if (texturecompositesize[texnum] > 0x10000-texture->height)
I_Error ("R_GenerateLookup: texture %i is >64k", texnum);
texturecompositesize[texnum] += texture->height;
collump[x] = -1; // mark lump as multipatched
colofs[x] = csize + 3; // three header bytes in a column
csize += 4*count[x].posts+1; // 1 stop byte plus 4 bytes per post
}
csize += height; // height bytes of texture data
}
Z_Free (patchcount);
texturecompositesize[texnum] = csize;
}
free(count); // killough 4/9/98
}
//
// R_GetColumn
//
@ -398,6 +439,8 @@ void R_InitTextures (void)
int* directory;
int errors = 0;
// Load the patch names from pnames.lmp.
{
@ -407,9 +450,20 @@ void R_InitTextures (void)
nummappatches = LONG ( *((int *)names) );
patchlookup = Z_Malloc (nummappatches*sizeof(*patchlookup), PU_STATIC, 0);
for (i = 0; i < nummappatches; i++)
patchlookup[i] = W_CheckNumForName (name_p + i * 8);
for (i = 0; i < nummappatches; i++) {
patchlookup[i] = W_CheckNumForName (name_p + i*8);
if (patchlookup[i] == -1) {
// killough 4/17/98:
// Some wads use sprites as wall patches, so repeat check and
// look for sprites this time, but only if there were no wall
// patches found. This is the same as allowing for both, except
// that wall patches always win over sprites, even when they
// appear first in a wad. This is a kludgy solution to the wad
// lump namespace problem.
patchlookup[i] = (W_CheckNumForName)(name_p + i*8, ns_sprites);
}
}
Z_Free (names);
}
@ -504,8 +558,8 @@ void R_InitTextures (void)
patch->patch = patchlookup[SHORT(mpatch->patch)];
if (patch->patch == -1)
{
I_Error ("R_InitTextures: Missing patch in texture %s",
texture->name);
Printf ("R_InitTextures: Missing patch in texture %s\n", texture->name);
errors++;
}
}
texturecolumnlump[i] = Z_Malloc (texture->width*sizeof(**texturecolumnlump), PU_STATIC,0);
@ -534,6 +588,9 @@ void R_InitTextures (void)
if (maptex2)
Z_Free (maptex2);
if (errors)
I_Error ("%d errors in R_InitTextures.", errors);
// [RH] Setup hash chains. Go from back to front so that if
// duplicates are found, the first one gets used instead
// of the last (thus mimicing the original behavior
@ -549,7 +606,10 @@ void R_InitTextures (void)
// Precalculate whatever possible.
for (i = 0; i < numtextures; i++)
R_GenerateLookup (i);
R_GenerateLookup (i, &errors);
if (errors)
I_Error ("%d errors encountered during texture generation.", errors);
// Create translation table for global animation.
texturetranslation = Z_Malloc ((numtextures+1)*sizeof(*texturetranslation), PU_STATIC, 0);
@ -662,10 +722,10 @@ void R_InitData (void)
//
int R_FlatNumForName (const char* name)
{
int i = W_CheckNumForName (name);
int i = (W_CheckNumForName) (name, ns_flats);
if (i == -1)
i = W_CheckNumForName ("-NOFLAT-");
if (i == -1) // [RH] Default flat for not found ones
i = (W_CheckNumForName) ("-NOFLAT-", ns_flats);
if (i == -1) {
char namet[9];

View file

@ -104,29 +104,39 @@ struct sector_s
short special;
short tag;
// 0 = untraversed, 1,2 = sndlines -1
int soundtraversed;
// thing that made a sound (or null)
mobj_t* soundtarget;
// mapblock bounding box for height changes
int blockbox[4];
// origin for any sounds played by the sector
degenmobj_t soundorg;
// if == validcount, already checked
int validcount;
// list of mobjs in sector
mobj_t* thinglist;
int soundtraversed; // 0 = untraversed, 1,2 = sndlines -1
mobj_t* soundtarget; // thing that made a sound (or null)
int blockbox[4]; // mapblock bounding box for height changes
degenmobj_t soundorg; // origin for any sounds played by the sector
int validcount; // if == validcount, already checked
mobj_t* thinglist; // list of mobjs in sector
// thinker_t for reversable actions
void* specialdata;
void *floordata; // jff 2/22/98 make thinkers on
void *ceilingdata; // floors, ceilings, lighting,
void *lightingdata; // independent of one another
// jff 2/26/98 lockout machinery for stairbuilding
int stairlock; // -2 on first locked -1 after thinker done 0 normally
int prevsec; // -1 or number of sector for previous step
int nextsec; // -1 or number of next step sector
// killough 3/7/98: floor and ceiling texture offsets
fixed_t floor_xoffs, floor_yoffs;
fixed_t ceiling_xoffs, ceiling_yoffs;
// killough 3/7/98: support flat heights drawn at another sector's heights
int heightsec; // other sector, or -1 if no other sector
// killough 4/11/98: support for lightlevels coming from another sector
int floorlightsec, ceilinglightsec;
// list of mobjs that are at least partially in the sector
// thinglist is a subset of touching_thinglist
struct msecnode_s *touching_thinglist; // phares 3/14/98
int linecount;
struct line_s** lines; // [linecount] size
struct line_s **lines; // [linecount] size
};
typedef struct sector_s sector_t;
@ -186,6 +196,7 @@ struct line_s
short flags;
short special;
short tag;
byte args[5]; // [RH] Hexen-style arguments
// Visual appearance: SideDefs.
// sidenum[1] will be -1 if one sided
@ -229,6 +240,32 @@ struct subsector_s
};
typedef struct subsector_s subsector_t;
// phares 3/14/98
//
// Sector list node showing all sectors an object appears in.
//
// There are two threads that flow through these nodes. The first thread
// starts at touching_thinglist in a sector_t and flows through the m_snext
// links to find all mobjs that are entirely or partially in the sector.
// The second thread starts at touching_sectorlist in an mobj_t and flows
// through the m_tnext links to find all sectors a thing touches. This is
// useful when applying friction or push effects to sectors. These effects
// can be done as thinkers that act upon all objects touching their sectors.
// As an mobj moves through the world, these nodes are created and
// destroyed, with the links changed appropriately.
//
// For the links, NULL means top or end of list.
typedef struct msecnode_s
{
sector_t *m_sector; // a sector containing this object
struct mobj_s *m_thing; // this object
struct msecnode_s *m_tprev; // prev msecnode_t for this thing
struct msecnode_s *m_tnext; // next msecnode_t for this thing
struct msecnode_s *m_sprev; // prev msecnode_t for this sector
struct msecnode_s *m_snext; // next msecnode_t for this sector
BOOL visited; // killough 4/4/98, 4/7/98: used in search algorithms
} msecnode_t;
//
// The LineSeg.
@ -403,6 +440,9 @@ struct vissprite_s
// Currently this is just a translation table and not a palette.
struct palette_s *palette;
// killough 3/27/98: height sector for underwater/fake ceiling support
int heightsec;
};
typedef struct vissprite_s vissprite_t;
@ -459,6 +499,8 @@ struct visplane_s
fixed_t height;
int picnum;
int lightlevel;
fixed_t xoffs;
fixed_t yoffs;
int minx;
int maxx;

View file

@ -876,24 +876,14 @@ void R_FillBackScreen (void)
int y;
patch_t* patch;
// DOOM border patch.
//char name1[] = "FLOOR7_2";
// DOOM II border patch.
//char name2[] = "GRNROCK";
char* name;
// [RH] Always draws something now.
if ( gamemode == commercial)
name = "GRNROCK";
else
name = "FLOOR7_2";
V_LockScreen (&screens[1]);
V_FlatFill (0,0,screens[1].width,screens[1].height,&screens[1],W_CacheLumpName (name, PU_CACHE));
{
int lump = R_FlatNumForName ((gamemode == commercial) ? "GRNROCK" : "FLOOR7_2");
V_FlatFill (0,0,screens[1].width,screens[1].height,&screens[1],
W_CacheLumpNum (lump + firstflat, PU_CACHE));
}
if (realviewwidth != screens[0].width) {
patch = W_CacheLumpName ("brdr_b",PU_CACHE);

View file

@ -77,7 +77,6 @@ fixed_t skytopfrac;
// just for profiling purposes
int framecount;
int sscount;
int linecount;
int loopcount;
@ -394,38 +393,6 @@ R_PointToAngle2
}
fixed_t
R_PointToDist
( fixed_t x,
fixed_t y )
{
int angle;
fixed_t dx;
fixed_t dy;
fixed_t temp;
fixed_t dist;
dx = abs(x - viewx);
dy = abs(y - viewy);
if (dy>dx)
{
temp = dx;
dx = dy;
dy = temp;
}
angle = (tantoangle[ FixedDiv(dy,dx)>>DBITS ]+ANG90) >> ANGLETOFINESHIFT;
// use as cosine
dist = FixedDiv (dx, finesine[angle] );
return dist;
}
//
// R_InitPointToAngle
//
@ -930,8 +897,6 @@ void R_SetupFrame (player_t* player)
viewsin = finesine[viewangle>>ANGLETOFINESHIFT];
viewcos = finecosine[viewangle>>ANGLETOFINESHIFT];
sscount = 0;
if (player->fixedcolormap)
{
fixedcolormap =

View file

@ -55,7 +55,7 @@ visplane_t *floorplane;
visplane_t *ceilingplane;
// ?
#define MAXOPENINGS (screens[0].width*64)
size_t maxopenings;
short *openings;
short *lastopening;
@ -86,6 +86,7 @@ fixed_t *yslope;
fixed_t *distscale;
fixed_t basexscale;
fixed_t baseyscale;
static fixed_t xoffs, yoffs; // killough 2/28/98: flat offsets
fixed_t *cachedheight;
fixed_t *cacheddistance;
@ -151,6 +152,8 @@ static void GetMoreVisPlanes (visplane_t **toupdate)
// baseyscale
// viewx
// viewy
// xoffs
// yoffs
//
// BASIC PRIMITIVE
//
@ -186,8 +189,10 @@ void R_MapPlane (int y, int x1, int x2)
length = FixedMul (distance,distscale[x1]);
angle = (viewangle + xtoviewangle[x1])>>ANGLETOFINESHIFT;
ds_xfrac = viewx + FixedMul(finecosine[angle], length);
ds_yfrac = -viewy - FixedMul(finesine[angle], length);
// killough 2/28/98: Add offsets
ds_xfrac = viewx + FixedMul(finecosine[angle], length) + xoffs;
ds_yfrac = -viewy - FixedMul(finesine[angle], length) + yoffs;
if (fixedcolormap)
ds_colormap = fixedcolormap;
@ -246,27 +251,29 @@ void R_ClearPlanes (void)
//
// R_FindPlane
//
visplane_t *R_FindPlane (fixed_t height, int picnum, int lightlevel)
// killough 2/28/98: Add offsets
visplane_t *R_FindPlane (fixed_t height, int picnum, int lightlevel,
fixed_t xoffs, fixed_t yoffs)
{
visplane_t* check;
visplane_t *check;
if (picnum == skyflatnum)
{
height = 0; // all skys map together
lightlevel = 0;
}
height = lightlevel = 0; // all skys map together
for (check=visplanes; check<lastvisplane; check++)
{
if (height == check->height
&& picnum == check->picnum
&& lightlevel == check->lightlevel)
&& lightlevel == check->lightlevel
&& xoffs == check->xoffs
&& yoffs == check->yoffs
)
{
break;
}
}
if (check < lastvisplane)
return check;
@ -278,6 +285,8 @@ visplane_t *R_FindPlane (fixed_t height, int picnum, int lightlevel)
check->height = height;
check->picnum = picnum;
check->lightlevel = lightlevel;
check->xoffs = xoffs; // killough 2/28/98: Save offsets
check->yoffs = yoffs;
check->minx = screens[0].width;
check->maxx = -1;
@ -341,6 +350,8 @@ visplane_t *R_CheckPlane (visplane_t *pl, int start, int stop)
lastvisplane->height = pl->height;
lastvisplane->picnum = pl->picnum;
lastvisplane->lightlevel = pl->lightlevel;
lastvisplane->xoffs = pl->xoffs; // killough 2/28/98
lastvisplane->yoffs = pl->yoffs;
pl = lastvisplane++;
@ -405,7 +416,7 @@ static void R_DrawMaskedSky (int skytexture, int skypos, fixed_t scale, fixed_t
for (x=pl->minx ; x <= pl->maxx ; x++)
{
dc_x = x;
angle = ((((viewangle + xtoviewangle[x])>>(ANGLETOSKYSHIFT-16)) + skypos)>>16)&0xff;
angle = ((((viewangle + xtoviewangle[x])>>(ANGLETOSKYSHIFT-16)) + skypos)>>16);
column = (column_t *) ((byte *)R_GetColumn(skytexture, angle) - 3);
if (column->topdelta == 0xff)
@ -467,7 +478,7 @@ static void R_DrawSky (int skytexture, int skypos, visplane_t *pl)
dc_yh = pl->bottom[x];
if (dc_yl <= dc_yh) {
angle = ((((viewangle + xtoviewangle[x])>>(ANGLETOSKYSHIFT-16)) + skypos)>>16)&0xff;
angle = ((((viewangle + xtoviewangle[x])>>(ANGLETOSKYSHIFT-16)) + skypos)>>16);
dc_x = x;
dc_source = R_GetColumn(skytexture, angle);
colfunc ();
@ -524,6 +535,8 @@ void R_DrawPlanes (void)
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;
@ -554,7 +567,6 @@ void R_DrawPlanes (void)
BOOL R_PlaneInitData (void)
{
if (openings) free (openings);
if (floorclip) free (floorclip);
if (ceilingclip) free (ceilingclip);
if (spanstart) free (spanstart);
@ -565,7 +577,6 @@ BOOL R_PlaneInitData (void)
if (cachedxstep) free (cachedxstep);
if (cachedystep) free (cachedystep);
openings = Calloc (MAXOPENINGS, sizeof(short));
floorclip = Calloc (screens[0].width, sizeof(short));
ceilingclip = Calloc (screens[0].width, sizeof(short));

View file

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

View file

@ -36,62 +36,56 @@
#include "r_local.h"
#include "r_sky.h"
#include "v_video.h"
// OPTIMIZE: closed two sided lines as single sided
// True if any of the segs textures might be visible.
BOOL segtextured;
// killough 1/6/98: replaced globals with statics where appropriate
// False if the back side is the same plane.
BOOL markfloor;
BOOL markceiling;
BOOL maskedtexture;
int toptexture;
int bottomtexture;
int midtexture;
static BOOL segtextured; // True if any of the segs textures might be visible.
static BOOL markfloor; // False if the back side is the same plane.
static BOOL markceiling;
static BOOL maskedtexture;
static int toptexture;
static int bottomtexture;
static int midtexture;
angle_t rw_normalangle;
// angle to line origin
angle_t rw_normalangle; // angle to line origin
int rw_angle1;
fixed_t rw_distance;
lighttable_t** walllights;
//
// regular wall
//
int rw_x;
int rw_stopx;
angle_t rw_centerangle;
fixed_t rw_offset;
fixed_t rw_distance;
fixed_t rw_scale;
fixed_t rw_scalestep;
fixed_t rw_midtexturemid;
fixed_t rw_toptexturemid;
fixed_t rw_bottomtexturemid;
static int rw_x;
static int rw_stopx;
static angle_t rw_centerangle;
static fixed_t rw_offset;
static fixed_t rw_scale;
static fixed_t rw_scalestep;
static fixed_t rw_midtexturemid;
static fixed_t rw_toptexturemid;
static fixed_t rw_bottomtexturemid;
int worldtop;
int worldbottom;
int worldhigh;
int worldlow;
static int worldtop;
static int worldbottom;
static int worldhigh;
static int worldlow;
fixed_t pixhigh;
fixed_t pixlow;
fixed_t pixhighstep;
fixed_t pixlowstep;
static fixed_t pixhigh;
static fixed_t pixlow;
static fixed_t pixhighstep;
static fixed_t pixlowstep;
fixed_t topfrac;
fixed_t topstep;
static fixed_t topfrac;
static fixed_t topstep;
fixed_t bottomfrac;
fixed_t bottomstep;
lighttable_t** walllights;
short* maskedtexturecol;
static fixed_t bottomfrac;
static fixed_t bottomstep;
static short *maskedtexturecol;
//
@ -99,33 +93,33 @@ short* maskedtexturecol;
//
void R_RenderMaskedSegRange (drawseg_t *ds, int x1, int x2)
{
unsigned index;
column_t* col;
int lightnum;
int texnum;
sector_t tempsec; // killough 4/13/98
// Calculate light table.
// Use different light tables
// for horizontal / vertical / diagonal. Diagonal?
// OPTIMIZE: get rid of LIGHTSEGSHIFT globally
curline = ds->curline;
frontsector = curline->frontsector;
backsector = curline->backsector;
texnum = texturetranslation[curline->sidedef->midtexture];
lightnum = (frontsector->lightlevel >> LIGHTSEGSHIFT)+extralight;
// killough 4/13/98: get correct lightlevel for 2s normal textures
lightnum = (R_FakeFlat(frontsector, &tempsec, NULL, NULL, false)
->lightlevel >> LIGHTSEGSHIFT)+extralight;
if (curline->v1->y == curline->v2->y)
lightnum--;
else if (curline->v1->x == curline->v2->x)
lightnum++;
if (lightnum < 0)
walllights = scalelight[0];
else if (lightnum >= LIGHTLEVELS)
walllights = scalelight[LIGHTLEVELS-1];
else
walllights = scalelight[lightnum];
walllights = lightnum >= LIGHTLEVELS ? scalelight[LIGHTLEVELS-1] :
lightnum < 0 ? scalelight[0] : scalelight[lightnum];
maskedtexturecol = ds->maskedtexturecol;
@ -155,22 +149,48 @@ void R_RenderMaskedSegRange (drawseg_t *ds, int x1, int x2)
// draw the columns
for (dc_x = x1 ; dc_x <= x2 ; dc_x++)
{
// calculate lighting
if (maskedtexturecol[dc_x] != MAXSHORT)
{
// calculate lighting
if (!fixedcolormap)
{
index = spryscale>>LIGHTSCALESHIFT;
unsigned index = spryscale>>LIGHTSCALESHIFT;
if (index >= MAXLIGHTSCALE )
if (index >= MAXLIGHTSCALE)
index = MAXLIGHTSCALE-1;
dc_colormap = walllights[index];
}
sprtopscreen = centeryfrac - FixedMul(dc_texturemid, spryscale);
// killough 3/2/98:
//
// This calculation used to overflow and cause crashes in Doom:
//
// sprtopscreen = centeryfrac - FixedMul(dc_texturemid, spryscale);
//
// This code fixes it, by using double-precision intermediate
// arithmetic and by skipping the drawing of 2s normals whose
// mapping to screen coordinates is totally out of range:
{
__int64 t = ((__int64) centeryfrac << FRACBITS) -
(__int64) dc_texturemid * spryscale;
// [RH] This doesn't work properly as-is with freelook
// if (t + (__int64) textureheight[texnum] * spryscale < 0 ||
// t > (__int64) screens[0].height << FRACBITS*2)
// continue; // skip if the texture is out of screen's range
sprtopscreen = (long)(t >> FRACBITS);
}
dc_iscale = 0xffffffffu / (unsigned)spryscale;
// killough 1/25/98: here's where Medusa came in, because
// it implicitly assumed that the column was all one patch.
// Originally, Doom did not construct complete columns for
// multipatched textures, so there were no header or trailer
// bytes in the column referred to below, which explains
// the Medusa effect. The fix is to construct true columns
// when forming multipatched textures (see r_data.c).
// draw the texture
col = (column_t *)(
(byte *)R_GetColumn(texnum,maskedtexturecol[dc_x]) -3);
@ -357,7 +377,23 @@ void R_RenderSegLoop (void)
}
}
// killough 5/2/98: move from r_main.c, made static, simplified
static fixed_t R_PointToDist(fixed_t x, fixed_t y)
{
fixed_t dx = abs(x - viewx);
fixed_t dy = abs(y - viewy);
if (dy > dx)
{
fixed_t t = dx;
dx = dy;
dy = t;
}
return FixedDiv(dx, finesine[(tantoangle[FixedDiv(dy,dx) >> DBITS]
+ ANG90) >> ANGLETOFINESHIFT]);
}
//
@ -365,6 +401,9 @@ void R_RenderSegLoop (void)
// A wall segment will be drawn
// between start and stop pixels (inclusive).
//
extern short *openings;
extern size_t maxopenings;
void R_StoreWallRange (int start, int stop)
{
fixed_t hyp;
@ -373,20 +412,21 @@ void R_StoreWallRange (int start, int stop)
fixed_t vtop;
int lightnum;
// don't overflow and crash
if (ds_p == &drawsegs[MaxDrawSegs]) {
// [RH] Grab some more drawsegs
MaxDrawSegs += 32;
drawsegs = Realloc (drawsegs, MaxDrawSegs * sizeof(drawseg_t));
ds_p = &drawsegs[MaxDrawSegs - 32];
DPrintf ("MaxDrawSegs increased to %d\n", MaxDrawSegs);
}
#ifdef RANGECHECK
if (start >=viewwidth || start > stop)
I_Error ("Bad R_RenderWallRange: %i to %i", start , stop);
#endif
// don't overflow and crash
if (ds_p == &drawsegs[MaxDrawSegs]) {
unsigned pos = ds_p - drawsegs;
// [RH] Grab some more drawsegs
MaxDrawSegs = MaxDrawSegs ? MaxDrawSegs*2 : 32;
drawsegs = Realloc (drawsegs, MaxDrawSegs * sizeof(drawseg_t));
ds_p = drawsegs + pos;
DPrintf ("MaxDrawSegs increased to %d\n", MaxDrawSegs);
}
sidedef = curline->sidedef;
linedef = curline->linedef;
@ -411,6 +451,36 @@ void R_StoreWallRange (int start, int stop)
ds_p->curline = curline;
rw_stopx = stop+1;
{ // killough 1/6/98, 2/1/98: remove limit on openings
size_t pos = lastopening - openings;
size_t need = (rw_stopx - start)*4 + pos;
if (need > maxopenings)
{
drawseg_t *ds;
short *oldopenings = openings;
short *oldlast = lastopening;
do
maxopenings = maxopenings ? maxopenings*2 : 16384;
while (need > maxopenings);
openings = Realloc(openings, maxopenings * sizeof(*openings));
lastopening = openings + pos;
DPrintf ("MaxOpenings increased to %u\n", maxopenings);
// [RH] We also need to adjust the openings pointers that
// were already stored in drawsegs.
for (ds = drawsegs; ds < ds_p; ds++) {
#define ADJUST(p) if (ds->p + ds->x1 >= oldopenings && ds->p + ds->x1 <= oldlast)\
ds->p = ds->p - oldopenings + openings;
ADJUST (maskedtexturecol);
ADJUST (sprtopclip);
ADJUST (sprbottomclip);
}
#undef ADJUST
}
} // killough: end of code to remove limits on openings
// calculate scale at both ends and step
ds_p->scale1 = rw_scale =
R_ScaleFromGlobalAngle (viewangle + xtoviewangle[start]);
@ -423,21 +493,6 @@ void R_StoreWallRange (int start, int stop)
}
else
{
// UNUSED: try to fix the stretched line bug
#if 0
if (rw_distance < FRACUNIT/2)
{
fixed_t trx,try;
fixed_t gxt,gyt;
trx = curline->v1->x - viewx;
try = curline->v1->y - viewy;
gxt = FixedMul(trx,viewcos);
gyt = -FixedMul(try,viewsin);
ds_p->scale1 = FixedDiv(projection, gxt-gyt);
}
#endif
ds_p->scale2 = ds_p->scale1;
}
@ -453,8 +508,10 @@ void R_StoreWallRange (int start, int stop)
{
// single sided line
midtexture = texturetranslation[sidedef->midtexture];
// a single sided line is terminal, so it must mark ends
markfloor = markceiling = true;
if (linedef->flags & ML_DONTPEGBOTTOM)
{
vtop = frontsector->floorheight +
@ -467,8 +524,18 @@ void R_StoreWallRange (int start, int stop)
// top of texture at top
rw_midtexturemid = worldtop;
}
rw_midtexturemid += sidedef->rowoffset;
{ // killough 3/27/98: reduce offset
/* [RH] Not necessary unless I do BOOM's fix for wrapping
* textures of any height
fixed_t h = textureheight[sidedef->midtexture];
if (h & (h-FRACUNIT))
rw_midtexturemid %= h;
*/
}
ds_p->silhouette = SIL_BOTH;
ds_p->sprtopclip = screenheightarray;
ds_p->sprbottomclip = negonearray;
@ -490,7 +557,6 @@ void R_StoreWallRange (int start, int stop)
{
ds_p->silhouette = SIL_BOTTOM;
ds_p->bsilheight = MAXINT;
// ds_p->sprbottomclip = negonearray;
}
if (frontsector->ceilingheight < backsector->ceilingheight)
@ -502,7 +568,6 @@ void R_StoreWallRange (int start, int stop)
{
ds_p->silhouette |= SIL_TOP;
ds_p->tsilheight = MININT;
// ds_p->sprtopclip = screenheightarray;
}
if (backsector->ceilingheight <= frontsector->floorheight)
@ -519,6 +584,30 @@ void R_StoreWallRange (int start, int stop)
ds_p->silhouette |= SIL_TOP;
}
// killough 1/17/98: this test is required if the fix
// for the automap bug (r_bsp.c) is used, or else some
// sprites will be displayed behind closed doors. That
// fix prevents lines behind closed doors with dropoffs
// from being displayed on the automap.
//
// killough 4/7/98: make doorclosed external variable
{
extern int doorclosed; // killough 1/17/98, 2/8/98, 4/7/98
if (doorclosed || backsector->ceilingheight<=frontsector->floorheight)
{
ds_p->sprbottomclip = negonearray;
ds_p->bsilheight = MAXINT;
ds_p->silhouette |= SIL_BOTTOM;
}
if (doorclosed || backsector->floorheight>=frontsector->ceilingheight)
{ // killough 1/17/98, 2/8/98
ds_p->sprtopclip = screenheightarray;
ds_p->tsilheight = MININT;
ds_p->silhouette |= SIL_TOP;
}
}
worldhigh = backsector->ceilingheight - viewz;
worldlow = backsector->floorheight - viewz;
@ -530,30 +619,38 @@ void R_StoreWallRange (int start, int stop)
}
if (worldlow != worldbottom
markfloor = worldlow != worldbottom
|| backsector->floorpic != frontsector->floorpic
|| backsector->lightlevel != frontsector->lightlevel)
{
markfloor = true;
}
else
{
// same plane on both sides
markfloor = false;
}
|| backsector->lightlevel != frontsector->lightlevel
// killough 3/7/98: Add checks for (x,y) offsets
|| backsector->floor_xoffs != frontsector->floor_xoffs
|| backsector->floor_yoffs != frontsector->floor_yoffs
if (worldhigh != worldtop
// killough 4/15/98: prevent 2s normals
// from bleeding through deep water
|| frontsector->heightsec != -1
// killough 4/17/98: draw floors if different light levels
|| backsector->floorlightsec != frontsector->floorlightsec
;
markceiling = worldhigh != worldtop
|| backsector->ceilingpic != frontsector->ceilingpic
|| backsector->lightlevel != frontsector->lightlevel)
{
markceiling = true;
}
else
{
// same plane on both sides
markceiling = false;
}
|| backsector->lightlevel != frontsector->lightlevel
// killough 3/7/98: Add checks for (x,y) offsets
|| backsector->ceiling_xoffs != frontsector->ceiling_xoffs
|| backsector->ceiling_yoffs != frontsector->ceiling_yoffs
// killough 4/15/98: prevent 2s normals
// from bleeding through fake ceilings
|| (frontsector->heightsec != -1 &&
frontsector->ceilingpic!=skyflatnum)
// killough 4/17/98: draw ceilings if different light levels
|| backsector->ceilinglightsec != frontsector->ceilinglightsec
;
if (backsector->ceilingheight <= frontsector->floorheight
|| backsector->floorheight >= frontsector->ceilingheight)
@ -597,8 +694,29 @@ void R_StoreWallRange (int start, int stop)
rw_bottomtexturemid = worldlow;
}
rw_toptexturemid += sidedef->rowoffset;
// killough 3/27/98: reduce offset
{
/* [RH] Not necessary unless I do BOOM's fix for wrapping
* textures of any height
fixed_t h = textureheight[sidedef->toptexture];
if (h & (h-FRACUNIT))
rw_toptexturemid %= h;
*/
}
rw_bottomtexturemid += sidedef->rowoffset;
// killough 3/27/98: reduce offset
{
/* [RH] Not necessary unless I do BOOM's fix for wrapping
* textures of any height
fixed_t h = textureheight[sidedef->bottomtexture];
if (h & (h-FRACUNIT))
rw_bottomtexturemid %= h;
*/
}
// allocate space for masked texture tables
if (sidedef->midtexture)
{
@ -657,20 +775,16 @@ void R_StoreWallRange (int start, int stop)
// and doesn't need to be marked.
if (frontsector->floorheight >= viewz)
// killough 3/7/98: add deep water check
if (frontsector->heightsec == -1)
{
// above view plane
if (frontsector->floorheight >= viewz) // above view plane
markfloor = false;
}
if (frontsector->ceilingheight <= viewz
&& frontsector->ceilingpic != skyflatnum)
{
// below view plane
if (frontsector->ceilingheight <= viewz &&
frontsector->ceilingpic != skyflatnum) // below view plane
markceiling = false;
}
// calculate incremental stepping values for texture edges
worldtop >>= 4;
worldbottom >>= 4;
@ -701,41 +815,46 @@ void R_StoreWallRange (int start, int stop)
// render it
if (markceiling)
if (ceilingplane) // killough 4/11/98: add NULL ptr checks
ceilingplane = R_CheckPlane (ceilingplane, rw_x, rw_stopx-1);
else
markceiling = 0;
if (markfloor)
if (floorplane) // killough 4/11/98: add NULL ptr checks
floorplane = R_CheckPlane (floorplane, rw_x, rw_stopx-1);
else
markfloor = 0;
R_RenderSegLoop ();
// save sprite clipping info
if ( ((ds_p->silhouette & SIL_TOP) || maskedtexture)
&& !ds_p->sprtopclip)
if ( ((ds_p->silhouette & SIL_TOP) || maskedtexture) && !ds_p->sprtopclip)
{
memcpy (lastopening, ceilingclip+start, 2*(rw_stopx-start));
memcpy (lastopening, ceilingclip+start, sizeof(*lastopening)*(rw_stopx-start));
ds_p->sprtopclip = lastopening - start;
lastopening += rw_stopx - start;
}
if ( ((ds_p->silhouette & SIL_BOTTOM) || maskedtexture)
&& !ds_p->sprbottomclip)
if ( ((ds_p->silhouette & SIL_BOTTOM) || maskedtexture) && !ds_p->sprbottomclip)
{
memcpy (lastopening, floorclip+start, 2*(rw_stopx-start));
memcpy (lastopening, floorclip+start, sizeof(*lastopening)*(rw_stopx-start));
ds_p->sprbottomclip = lastopening - start;
lastopening += rw_stopx - start;
}
if (maskedtexture && !(ds_p->silhouette&SIL_TOP))
if (maskedtexture && !(ds_p->silhouette & SIL_TOP))
{
ds_p->silhouette |= SIL_TOP;
ds_p->tsilheight = MININT;
}
if (maskedtexture && !(ds_p->silhouette&SIL_BOTTOM))
if (maskedtexture && !(ds_p->silhouette & SIL_BOTTOM))
{
ds_p->silhouette |= SIL_BOTTOM;
ds_p->bsilheight = MAXINT;
}
ds_p++;
}

View file

@ -56,6 +56,7 @@ fixed_t sky2pos=0, sky2speed=0;
// [RH] Stretch sky texture if not taller than 128 pixels?
cvar_t *r_stretchsky;
char SKYFLATNAME[8] = "F_SKY1";
//
// R_InitSkyMap

View file

@ -467,6 +467,7 @@ void R_ProjectSprite (mobj_t* thing)
fixed_t gxt;
fixed_t gyt;
fixed_t gzt; // killough 3/27/98
fixed_t tx;
fixed_t tz;
@ -490,6 +491,9 @@ void R_ProjectSprite (mobj_t* thing)
angle_t ang;
fixed_t iscale;
int heightsec; // killough 3/27/98
// [RH] Andy Baker's stealth monsters
if (thing->invisible == true)
return;
@ -565,14 +569,47 @@ void R_ProjectSprite (mobj_t* thing)
if (x2 < 0)
return;
gzt = thing->z + spritetopoffset[lump];
// killough 4/9/98: clip things which are out of view due to height
// [RH] This doesn't work too well with freelook
// if (thing->z > viewz + FixedDiv(centeryfrac, yscale) ||
// gzt < viewz - FixedDiv(centeryfrac-viewheight, yscale))
// return;
// killough 3/27/98: exclude things totally separated
// from the viewer, by either water or fake ceilings
// killough 4/11/98: improve sprite clipping for underwater/fake ceilings
heightsec = thing->subsector->sector->heightsec;
if (heightsec != -1) // only clip things which are in special sectors
{
int phs = viewplayer->mo->subsector->sector->heightsec;
if (phs != -1 && viewz < sectors[phs].floorheight ?
thing->z >= sectors[heightsec].floorheight :
gzt < sectors[heightsec].floorheight)
return;
if (phs != -1 && viewz > sectors[phs].ceilingheight ?
gzt < sectors[heightsec].ceilingheight &&
viewz >= sectors[heightsec].ceilingheight :
thing->z >= sectors[heightsec].ceilingheight)
return;
}
// store information in a vissprite
vis = R_NewVisSprite ();
// killough 3/27/98: save sector for special clipping later
vis->heightsec = heightsec;
vis->mobjflags = thing->flags;
vis->scale = yscale;
vis->gx = thing->x;
vis->gy = thing->y;
vis->gz = thing->z;
vis->gzt = thing->z + spritetopoffset[lump];
vis->gzt = gzt; // killough 3/27/98
vis->texturemid = vis->gzt - viewz;
vis->x1 = x1 < 0 ? 0 : x1;
vis->x2 = x2 >= viewwidth ? viewwidth-1 : x2;
@ -876,21 +913,25 @@ void R_DrawSprite (vissprite_t* spr)
int r2;
fixed_t scale;
fixed_t lowscale;
int silhouette;
for (x = spr->x1 ; x<=spr->x2 ; x++)
r_dsclipbot[x] = r_dscliptop[x] = -2;
// Scan drawsegs from end to start for obscuring segs.
// The first drawseg that has a greater scale
// is the clip seg.
for (ds=ds_p-1 ; ds >= drawsegs ; ds--)
// The first drawseg that has a greater scale is the clip seg.
// Modified by Lee Killough:
// (pointer check was originally nonportable
// and buggy, by going past LEFT end of array):
// for (ds=ds_p-1 ; ds >= drawsegs ; ds--) old buggy code
for (ds = ds_p ; ds-- > drawsegs ; ) // new -- killough
{
// determine if the drawseg obscures the sprite
if (ds->x1 > spr->x2
|| ds->x2 < spr->x1
|| (!ds->silhouette
&& !ds->maskedtexturecol) )
|| (!ds->silhouette && !ds->maskedtexturecol) )
{
// does not cover sprite
continue;
@ -923,41 +964,61 @@ void R_DrawSprite (vissprite_t* spr)
// clip this piece of the sprite
silhouette = ds->silhouette;
// killough 3/27/98: optimized and made much shorter
if (spr->gz >= ds->bsilheight)
silhouette &= ~SIL_BOTTOM;
if (spr->gzt <= ds->tsilheight)
silhouette &= ~SIL_TOP;
if (silhouette == 1)
{
// bottom sil
if (ds->silhouette&SIL_BOTTOM && spr->gz < ds->bsilheight) //bottom sil
for (x=r1 ; x<=r2 ; x++)
if (r_dsclipbot[x] == -2)
r_dsclipbot[x] = ds->sprbottomclip[x];
}
else if (silhouette == 2)
{
// top sil
if (ds->silhouette&SIL_TOP && spr->gzt > ds->tsilheight) // top sil
for (x=r1 ; x<=r2 ; x++)
if (r_dscliptop[x] == -2)
r_dscliptop[x] = ds->sprtopclip[x];
}
else if (silhouette == 3)
{
// both
for (x=r1 ; x<=r2 ; x++)
{
if (r_dsclipbot[x] == -2)
r_dsclipbot[x] = ds->sprbottomclip[x];
if (r_dscliptop[x] == -2)
r_dscliptop[x] = ds->sprtopclip[x];
}
}
// killough 3/27/98:
// Clip the sprite against deep water and/or fake ceilings.
// killough 4/9/98: optimize by adding mh
// killough 4/11/98: improve sprite clipping for underwater/fake ceilings
if (spr->heightsec != -1) // only things in specially marked sectors
{
fixed_t h,mh;
int phs = viewplayer->mo->subsector->sector->heightsec;
if ((mh = sectors[spr->heightsec].floorheight) > spr->gz &&
(h = centeryfrac - FixedMul(mh-=viewz, spr->scale)) >= 0 &&
(h >>= FRACBITS) < viewheight)
if (mh <= 0 || (phs != -1 && viewz > sectors[phs].floorheight))
{ // clip bottom
for (x=spr->x1 ; x<=spr->x2 ; x++)
if (r_dsclipbot[x] == -2 || h < r_dsclipbot[x])
r_dsclipbot[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 &&
(h = centeryfrac - FixedMul(mh-viewz, spr->scale)) >= 0 &&
(h >>= FRACBITS) < viewheight)
{
if (phs != -1 && viewz >= sectors[phs].ceilingheight)
{ // clip bottom
for (x=spr->x1 ; x<=spr->x2 ; x++)
if (r_dsclipbot[x] == -2 || h < r_dsclipbot[x])
r_dsclipbot[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;
}
}
}
// killough 3/27/98: end special clipping for deep water / fake ceilings
// all clipping has been performed, so draw the sprite
@ -1043,7 +1104,14 @@ void R_DrawMasked (void)
}
// render any remaining masked mid textures
for (ds=ds_p-1 ; ds >= drawsegs ; ds--)
// Modified by Lee Killough:
// (pointer check was originally nonportable
// and buggy, by going past LEFT end of array):
// for (ds=ds_p-1 ; ds >= drawsegs ; ds--) old buggy code
for (ds=ds_p ; ds-- > drawsegs ; ) // new -- killough
if (ds->maskedtexturecol)
R_RenderMaskedSegRange (ds, ds->x1, ds->x2);

View file

@ -1,4 +1,83 @@
July 26, 1998
- If FONTA?? is available, it is now used in deference to STCFN??? (i.e.
-file heretic)
- Renamed all the WICHAR?? in zdoom.wad to FONTB?? to match the naming
convention used by Heretic and Hexen.
July 23, 1998
- I must be an idiot! I took a fix from BOOM for freeing the lnames array too
soon and stuck it into ZDoom without really thinking about it. In BOOM (and
DOOM) lnames[] is dynamically allocated. In ZDoom, it's static since it
only needs to contain two items (the patch of the level just left and the
patch of the level being entered).
- Using the changemap command no longer says you are leaving the map you're
entering when no title patch is provided. (Unless they're one and the same.)
July 22, 1998
- Added a z parameter to P_TeleportMove() to properly handle checks in the
third dimension. Previously, I was checking for this, too, but against the
thing's original position. Now I check against the desired z location. This
prevents monsters from teleporting inside of each other.
July 19, 1998
- Improved handling of international keymaps (such as the French one) by
moving all responsibility for determining the shifted state of keys into
i_input.c. C_consol.c no longer maintains a ShiftLOT since .data3 of the
key event will contain a character that is sensitive of the current state
of modifier keys. (i.e. .data3 contains 'a' when the A key is pressed and
'A' when SHIFT-A is pressed.)
- Made some changes to D_DoAdvanceDemo() and G_CheckDemoStatus() so that
using the player setup menu during demo playback is now safe.
- Added a check to C_BackupCVars() so that it doesn't back up CVAR_LATCH
cvars are not saved. This is unnecessary since they don't actually
change until a new game anyway. The primary advantage of this is that
starting a new game during demo playback now uses the selected skill
level (again).
- Anything spawned by a boss shooter will now always telefrag even if
LEVEL_MONSTERSTELEFRAG is not set.
- Modifed PIT_RadiusAttack() (again) so that when a barrel is doing the
exploding, the original damage code is used.
- Removed the bitwise and against 0xff for angle in R_DrawSky() and
R_DrawMaskedSky(). Some skies in various PWADs are wider than this, and
R_GetColumn() masks it to the proper width for us anyway.
July 18, 1998
- Changed the unknown thing to have no gravity so that it stays at the
height it was spawned at (useful with Hexen).
- Discovered the source of a memory leak: When I added the thing_list code
from BOOM, I left out some from P_UnsetThingPosition(), so
P_SetThingPosition() was always creating a new thing_list and letting the
old one waste space. Conveyors even work now! Yay!
- Removed support for repeating the left and right arrow keys in m_menu.c
since some people had trouble with it.
- Changed D_DoServerInfoChange() so that it doesn't print messages in
single player games.
July 16, 1998
- Added entries for Heretic to SWITCHES and ANIMATED lumps (because I can).
- Did equivalent things for BOOM SWITCHES lumps.
- Removed MAXANIMS limit by scanning through the AnimDefs array to find out
how many entries it contains and then allocating that many anim_t's. Also
added support for BOOM ANIMATED lumps.
- Reduced the Revenant's height from 80 back to 56 to fix a problem with a
trap on DOOM2 MAP27. The new height caused the revenants heads to get
stuck in the ceiling, so the platforms they were on wouldn't lower. Since
there are probably other situations like this elsewhere, I went and gave
all the monsters their original heights back.
- Fixed a problem with BOOM's openings limit removal. Pointers to openings
get stored in drawsegs, and the realloc() of the openings didn't bother
to adjust those pointers. A simple fix in r_segs.c once I figured out what
the problem was.
- Incorporated BOOM's Medusa fix.
July 15, 1998
- Added Lee Killough's generalized scrollers from BOOM.
- Added Rand Phares' thing list stuff from BOOM.
- Finished support for BOOM's multiple sector thinkers and threw in the
elevator code in the process (but nothing that calls it).
July 14, 1998
- Started adding support for BOOM's multiple actions per sector.
- Uploaded the 1.14 binaries and source to notgod.com.
- Fixed bug that caused the bunny scroller to crash: Using 0 instead of
&screens[0] in the calls to F_DrawPatchCol().

View file

@ -854,12 +854,22 @@ void S_ParseSndInfo (void)
int lastlump, lump;
char *sndinfo;
char *logicalname;
char *data;
lastlump = 0;
while ((lump = W_FindLump ("SNDINFO", &lastlump)) != -1) {
sndinfo = W_CacheLumpNum (lump, PU_CACHE);
while ( (sndinfo = COM_Parse (sndinfo)) ) {
while ( (data = COM_Parse (sndinfo)) ) {
if (com_token[0] == ';') {
// Handle comments from Hexen MAPINFO lumps
while (*sndinfo && *sndinfo != ';')
sndinfo++;
while (*sndinfo && *sndinfo != '\n')
sndinfo++;
continue;
}
sndinfo = data;
if (com_token[0] == '$') {
// com_token is a command
@ -924,6 +934,16 @@ void S_ParseSndInfo (void)
ambient->volume = 255;
else if (ambient->volume < 0)
ambient->volume = 0;
} else if (!stricmp (com_token + 1, "map")) {
// Hexen-style $MAP command
level_info_t *info;
sndinfo = COM_Parse (sndinfo);
sprintf (com_token, "MAP%02d", atoi (com_token));
info = FindLevelInfo (com_token);
sndinfo = COM_Parse (sndinfo);
if (info->mapname[0])
uppercopy (info->music, com_token);
} else {
Printf ("Unknown SNDINFO command %s\n", com_token);
while (*sndinfo != '\n' && *sndinfo != '\0')

View file

@ -48,7 +48,7 @@ void ST_initNew (void)
}
*/
for (i = 0; i < 4; i++) {
if ((lump = W_CheckNumForName (ammopatches[i])) != -1)
if ((lump = (W_CheckNumForName) (ammopatches[i], ns_sprites)) != -1)
ammos[i] = W_CacheLumpNum (lump, PU_STATIC);
}

View file

@ -190,7 +190,7 @@ void W_AddFile (char *filename)
//
void W_InitMultipleFiles (char** filenames)
{
int size;
int i;
// open all the files, load headers, and count lumps
numlumps = 0;
@ -204,20 +204,25 @@ void W_InitMultipleFiles (char** filenames)
if (!numlumps)
I_Error ("W_InitFiles: no files found");
// [RH] Set namespace markers to global for everything
for (i = 0; i < numlumps; i++)
lumpinfo[i].namespc = ns_global;
// [RH] Merge sprite and flat groups.
// (We don't need to bother with patches, since
// Doom doesn't use markers to identify them.)
W_MergeLumps ("S_START", "S_END");
W_MergeLumps ("F_START", "F_END");
W_MergeLumps ("S_START", "S_END", ns_sprites);
W_MergeLumps ("F_START", "F_END", ns_flats);
W_MergeLumps ("C_START", "C_END", ns_colormaps);
// [RH] Set up hash table
W_InitHashChains ();
// set up caching
size = numlumps * sizeof(*lumpcache);
lumpcache = Malloc (size);
memset (lumpcache, 0, size);
i = numlumps * sizeof(*lumpcache);
lumpcache = Z_Malloc (i, PU_STATIC, 0);
memset (lumpcache, 0, i);
}
@ -229,7 +234,7 @@ void W_InitMultipleFiles (char** filenames)
//
void W_InitFile (char* filename)
{
char* names[2];
char *names[2];
names[0] = filename;
names[1] = NULL;
@ -253,8 +258,9 @@ int W_NumLumps (void)
// Returns -1 if name not found.
//
// [RH] Changed to use hash lookup ala BOOM instead of a linear search
// and namespace parameter
//
int W_CheckNumForName (const char *name)
int (W_CheckNumForName) (const char *name, int space)
{
char uname[8];
int i;
@ -263,7 +269,7 @@ int W_CheckNumForName (const char *name)
i = lumpinfo[W_LumpNameHash (uname) % (unsigned)numlumps].index;
while (i != -1) {
if (!strncmp (lumpinfo[i].name, uname, 8))
if (!strncmp (lumpinfo[i].name, uname, 8) && lumpinfo[i].namespc == space)
break;
i = lumpinfo[i].next;
}
@ -429,7 +435,7 @@ static BOOL IsMarker (const char *name, const char *marker)
//
// Basically from Boom, too, although I tried to write
// it independently.
void W_MergeLumps (const char *start, const char *end)
void W_MergeLumps (const char *start, const char *end, int space)
{
char ustart[8], uend[8];
lumpinfo_t *newlumpinfos;
@ -460,6 +466,7 @@ void W_MergeLumps (const char *start, const char *end)
newlumpinfos[0].handle =
newlumpinfos[0].position =
newlumpinfos[0].size = 0;
newlumpinfos[0].namespc = ns_global;
}
} else {
// Copy lumpinfo down this list
@ -473,7 +480,8 @@ void W_MergeLumps (const char *start, const char *end)
haveEndMarker = true;
insideBlock = false;
} else {
newlumpinfos[newlumps++] = lumpinfo[i];
newlumpinfos[newlumps] = lumpinfo[i];
newlumpinfos[newlumps++].namespc = space;
}
}
}
@ -487,6 +495,7 @@ void W_MergeLumps (const char *start, const char *end)
newlumpinfos[newlumps].handle =
newlumpinfos[newlumps].position =
newlumpinfos[newlumps].size = 0;
newlumpinfos[newlumps].namespc = ns_global;
newlumps++;
}

View file

@ -440,7 +440,7 @@ static int WI_DrawName (char *str, int x, int y)
char charname[9];
while (*str) {
sprintf (charname, "WICHAR%02x", toupper(*str));
sprintf (charname, "FONTB%02u", toupper(*str) - 32);
lump = W_CheckNumForName (charname);
if (lump != -1) {
p = W_CacheLumpNum (lump, PU_CACHE);
@ -452,7 +452,8 @@ static int WI_DrawName (char *str, int x, int y)
str++;
}
return p ? (5*SHORT(p->height))/4 : 0;
p = W_CacheLumpName ("FONTB39", PU_CACHE);
return (5*(SHORT(p->height)-SHORT(p->topoffset)))/4;
}
@ -1630,7 +1631,7 @@ static int WI_CalcWidth (char *str)
return 0;
while (*str) {
sprintf (charname, "WICHAR%02x", toupper(*str));
sprintf (charname, "FONTB%02u", toupper(*str) - 32);
lump = W_CheckNumForName (charname);
if (lump != -1) {
p = W_CacheLumpNum (lump, PU_CACHE);
@ -1683,11 +1684,6 @@ void WI_loadData(void)
for (i = 0; i < 2; i++) {
char *lname = (i == 0 ? wbs->lname0 : wbs->lname1);
if (lnames[i]) {
Z_Free (lnames[i]);
lnames[i] = NULL;
}
if (lname)
j = W_CheckNumForName (lname);
else
@ -1821,6 +1817,13 @@ void WI_unloadData(void)
for (i=0 ; i<10 ; i++)
Z_ChangeTag(num[i], PU_CACHE);
for (i = 0; i < 2; i++) {
if (lnames[i]) {
Z_ChangeTag (lnames[i], PU_CACHE);
lnames[i] = NULL;
}
}
if (gamemode != commercial)
{
Z_ChangeTag(yah[0], PU_CACHE);

View file

@ -348,6 +348,7 @@ void Cmd_Limits (player_t *plyr, int argc, char **argv)
extern int MaxSegs;
extern int MaxVisPlanes;
extern int MaxVisSprites;
extern int maxopenings;
Printf_Bold ("Note that the following values are\n"
"dynamic and will increase as needed.\n\n");

View file

@ -33,7 +33,7 @@ extern int gametic;
extern BOOL automapactive; // in AM_map.c
typedef enum cstate_t {
up=0, down, falling, rising
up=0, down=1, falling=2, rising=3
} constate;
@ -43,7 +43,7 @@ BOOL vidactive = false, gotconback = false;
BOOL cursoron = false;
int ShowRows, SkipRows, ConsoleTicker, ConBottom, ConScroll, RowAdjust;
int CursorTicker, ScrollState = 0;
constate ConsoleState = up;
int ConsoleState = up;
char VersionString[8];
event_t RepeatEvent; // always type ev_keydown
@ -81,15 +81,6 @@ static int HistSize;
cvar_t *NotifyTime;
static byte NotifyStrings[4][256];
static char ShiftLOT[] = {
'\"', '(', ')', '*', '+', '<', '_', '>', '?', // 9 39->
')', '!', '@', '#', '$', '%', '^', '&', '*', '(', ':', ':', '<', '+', // 14 ->61
'{', '|', '}', '^', '_', '~', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', // 14 91->
'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', // 14 ...
'W', 'X', 'Y', 'Z' // 4 ->122
};
FILE *Logfile = NULL;
@ -752,7 +743,7 @@ void C_HandleKey (event_t *ev, byte *buffer, int len)
buffer[0] = buffer[1] = buffer[len+4] = 0;
AddCommandString (&buffer[2]);
TabbedLast = false;
} else if (ev->data3 == '`' || ev->data1 == KEY_ESCAPE) {
} else if (ev->data2 == '`' || ev->data1 == KEY_ESCAPE) {
// Close console, both ` and ESC clear command line
buffer[0] = buffer[1] = buffer[len+4] = 0;
@ -766,13 +757,6 @@ void C_HandleKey (event_t *ev, byte *buffer, int len)
if (buffer[0] < len) {
char data = ev->data3;
if (KeysShifted) {
if (data >= 39 && data <= 61)
data = ShiftLOT[data-39];
else if (data >= 91 && data <= 122)
data = ShiftLOT[data-68];
}
if (buffer[1] == buffer[0]) {
buffer[buffer[0] + 2] = data;
} else {

View file

@ -102,7 +102,7 @@ void D_DoServerInfoChange (byte **stream)
if ( (breakpt = strchr (value, '\\')) )
*breakpt = 0;
if (SetServerVar (ptr, value))
if (SetServerVar (ptr, value) && netgame)
Printf ("%s changed to %s\n", ptr, value);
*(value - 1) = '\\';

View file

@ -741,7 +741,8 @@ BOOL M_OptResponder (event_t *ev)
}
if (item->type == bitflag && flagsvar &&
(ch == KEY_LEFTARROW || ch == KEY_RIGHTARROW || ch == KEY_ENTER)) {
(ch == KEY_LEFTARROW || ch == KEY_RIGHTARROW || ch == KEY_ENTER)
&& !demoplayback) {
int newflags = *item->e.flagint ^ item->a.flagmask;
char val[16];

View file

@ -169,10 +169,7 @@ void T_MoveCeiling (ceiling_t* ceiling)
// EV_DoCeiling
// Move a ceiling up/down and all around!
//
int
EV_DoCeiling
( line_t* line,
ceiling_e type )
int EV_DoCeiling (line_t *line, ceiling_e type)
{
int secnum;
int rtn;
@ -183,6 +180,7 @@ EV_DoCeiling
rtn = 0;
// Reactivate in-stasis ceilings...for certain types.
// This restarts a crusher after it has been stopped
switch(type)
{
case fastCrushAndRaise:
@ -193,17 +191,19 @@ EV_DoCeiling
break;
}
// affects all sectors with the same tag as the linedef
while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0)
{
sec = &sectors[secnum];
if (sec->specialdata)
// 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->specialdata = ceiling;
sec->ceilingdata = ceiling; //jff 2/22/98
ceiling->thinker.function.acp1 = (actionf_p1)T_MoveCeiling;
ceiling->sector = sec;
ceiling->crush = false;
@ -283,7 +283,7 @@ void P_RemoveActiveCeiling(ceiling_t* c)
{
if (activeceilings[i] == c)
{
activeceilings[i]->sector->specialdata = NULL;
activeceilings[i]->sector->ceilingdata = NULL; // [RH]
P_RemoveThinker (&activeceilings[i]->thinker);
activeceilings[i] = NULL;
break;

View file

@ -210,7 +210,7 @@ P_SpawnStrobeFlash
//
// Start strobing lights (usually from a trigger)
//
void EV_StartLightStrobing(line_t* line)
void EV_StartLightStrobing (line_t *line)
{
int secnum;
sector_t* sec;
@ -219,7 +219,7 @@ void EV_StartLightStrobing(line_t* line)
while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0)
{
sec = &sectors[secnum];
if (sec->specialdata)
if (P_SectorActive (lighting_special, sec)) //jff 2/22/98
continue;
P_SpawnStrobeFlash (sec,SLOWDARK, 0);

View file

@ -136,11 +136,7 @@ void T_PlatRaise(plat_t* plat)
// Do Platforms
// "amount" is only used for SOME platforms.
//
int
EV_DoPlat
( line_t* line,
plattype_e type,
int amount )
int EV_DoPlat (line_t *line, plattype_e type, int amount)
{
plat_t* plat;
int secnum;
@ -150,9 +146,8 @@ EV_DoPlat
secnum = -1;
rtn = 0;
// Activate all <type> plats that are in_stasis
switch(type)
switch (type)
{
case perpetualRaise:
P_ActivateInStasis(line->tag);
@ -166,7 +161,7 @@ EV_DoPlat
{
sec = &sectors[secnum];
if (sec->specialdata)
if (P_SectorActive (floor_special, sec)) //jff 2/23/98 multiple thinkers
continue;
// Find lowest & highest floors around sector
@ -176,11 +171,15 @@ EV_DoPlat
plat->type = type;
plat->sector = sec;
plat->sector->specialdata = plat;
plat->sector->floordata = plat; //jff 2/23/98 multiple thinkers
plat->thinker.function.acp1 = (actionf_p1) T_PlatRaise;
plat->crush = false;
plat->tag = line->tag;
//jff 1/26/98 Avoid raise plat bouncing a head off a ceiling and then
//going down forever -- default low to plat height when triggered
plat->low = sec->floorheight;
switch(type)
{
case raiseToNearestAndChange:
@ -309,10 +308,11 @@ void P_AddActivePlat(plat_t* plat)
void P_RemoveActivePlat(plat_t* plat)
{
int i;
for (i = 0;i < MaxPlats;i++)
if (plat == activeplats[i])
{
(activeplats[i])->sector->specialdata = NULL;
(activeplats[i])->sector->floordata = NULL; // [RH]
P_RemoveThinker(&(activeplats[i])->thinker);
activeplats[i] = NULL;

View file

@ -64,7 +64,6 @@ int EV_Teleport (line_t *line, int side, mobj_t *thing)
if (side == 1)
return 0;
tag = line->tag;
for (i = 0; i < numsectors; i++)
{
@ -94,10 +93,9 @@ int EV_Teleport (line_t *line, int side, mobj_t *thing)
oldy = thing->y;
oldz = thing->z;
if (!P_TeleportMove (thing, m->x, m->y))
if (!P_TeleportMove (thing, m->x, m->y, m->z, false))
return 0;
thing->z = thing->floorz; //fixme: not needed?
if (thing->player)
thing->player->viewz = thing->z+thing->player->viewheight;

View file

@ -27,7 +27,7 @@
#include "c_cvars.h"
// SKY, store the number for name.
#define SKYFLATNAME "F_SKY1"
extern char SKYFLATNAME[8];
// The sky map is 256*128*4 maps.
#define ANGLETOSKYSHIFT 22

View file

@ -118,8 +118,6 @@ extern angle_t rw_normalangle;
// angle to line origin
extern int rw_angle1;
// Segs count?
extern int sscount;
extern visplane_t* floorplane;
extern visplane_t* ceilingplane;

View file

@ -68,9 +68,16 @@ typedef struct lumpinfo_s
int next;
int index;
int pad; // [RH] Pad to 32 bytes
int namespc;
} lumpinfo_t;
// [RH] Namespaces from BOOM.
typedef enum {
ns_global = 0,
ns_sprites,
ns_flats,
ns_colormaps
} namespace_t;
extern void** lumpcache;
extern lumpinfo_t* lumpinfo;
@ -78,7 +85,8 @@ extern int numlumps;
void W_InitMultipleFiles (char** filenames);
int W_CheckNumForName (const char *name);
#define W_CheckNumForName(name) (W_CheckNumForName)(name, ns_global)
int (W_CheckNumForName) (const char *name, int);
int W_GetNumForName (const char *name);
int W_LumpLength (int lump);
@ -88,7 +96,7 @@ void *W_CacheLumpNum (int lump, int tag);
// [RH] W_CacheLumpName() is now a macro
#define W_CacheLumpName(name,tag) \
W_CacheLumpNum (W_GetNumForName(name), tag)
W_CacheLumpNum (W_GetNumForName(name), (tag))
void W_Profile (void);
@ -99,7 +107,7 @@ unsigned W_LumpNameHash (const char *name); // [RH] Create hash key from an 8
void W_InitHashChains (void); // [RH] Set up the lumpinfo hashing
// [RH] Combine multiple marked ranges of lumps into one.
void W_MergeLumps (const char *start, const char *end);
void W_MergeLumps (const char *start, const char *end, int);
// Copy an 8-char string and uppercase it.
void uppercopy (char *to, const char *from);

18
readme.14a.txt Normal file
View file

@ -0,0 +1,18 @@
This archive contains a unified diff that will patch the source code for
ZDoom version 1.14 to 1.14a. To use it, you need to have already downloaded
the archive zdoom114-src.zip and extracted its contains. Then extract
patch.diff from this archive into your source code directory and apply it
with the command:
patch -F 3 -i patch.diff
(You need to have kept the patch.exe included with zdoom114-src.zip.)
Note that there was another version of this archive from July. The only
difference between that one and this one is that this one fixes the
savegame loading bug. If you already installed that patch, you can do the
fix yourself by changing one string in G_DoLoadGame() in g_game.c. The
string "version %i" should be changed to "version %ia".
Randy Heit
rheit@usa.net