as re-released 2008-09-04
This commit is contained in:
commit
3e67144fa1
86 changed files with 58040 additions and 0 deletions
90
Heretic Source/AM_DATA.H
Normal file
90
Heretic Source/AM_DATA.H
Normal file
|
@ -0,0 +1,90 @@
|
|||
// AM_data.h : The vector graphics for the automap
|
||||
|
||||
#ifndef __AMDATA_H__
|
||||
#define __AMDATA_H__
|
||||
|
||||
#pragma once
|
||||
|
||||
// a line drawing of the player pointing right, starting from the middle.
|
||||
|
||||
#define R ((8*PLAYERRADIUS)/7)
|
||||
|
||||
mline_t player_arrow[] = {
|
||||
{ { -R+R/4, 0 }, { 0, 0} }, // center line.
|
||||
{ { -R+R/4, R/8 }, { R, 0} }, // blade
|
||||
{ { -R+R/4, -R/8 }, { R, 0 } },
|
||||
{ { -R+R/4, -R/4 }, { -R+R/4, R/4 } }, // crosspiece
|
||||
{ { -R+R/8, -R/4 }, { -R+R/8, R/4 } },
|
||||
{ { -R+R/8, -R/4 }, { -R+R/4, -R/4} }, //crosspiece connectors
|
||||
{ { -R+R/8, R/4 }, { -R+R/4, R/4} },
|
||||
{ { -R-R/4, R/8 }, { -R-R/4, -R/8 } }, //pommel
|
||||
{ { -R-R/4, R/8 }, { -R+R/8, R/8 } },
|
||||
{ { -R-R/4, -R/8}, { -R+R/8, -R/8 } }
|
||||
};
|
||||
|
||||
mline_t keysquare[] = {
|
||||
{ { 0, 0 }, { R/4, -R/2 } },
|
||||
{ { R/4, -R/2 }, { R/2, -R/2 } },
|
||||
{ { R/2, -R/2 }, { R/2, R/2 } },
|
||||
{ { R/2, R/2 }, { R/4, R/2 } },
|
||||
{ { R/4, R/2 }, { 0, 0 } }, // handle part type thing
|
||||
{ { 0, 0 }, { -R, 0 } }, // stem
|
||||
{ { -R, 0 }, { -R, -R/2 } }, // end lockpick part
|
||||
{ { -3*R/4, 0 }, { -3*R/4, -R/4 } }
|
||||
};
|
||||
|
||||
/*mline_t player_arrow[] = {
|
||||
{ { -R+R/8, 0 }, { R, 0 } }, // -----
|
||||
{ { R, 0 }, { R-R/2, R/4 } }, // ----->
|
||||
{ { R, 0 }, { R-R/2, -R/4 } },
|
||||
{ { -R+R/8, 0 }, { -R-R/8, R/4 } }, // >---->
|
||||
{ { -R+R/8, 0 }, { -R-R/8, -R/4 } },
|
||||
{ { -R+3*R/8, 0 }, { -R+R/8, R/4 } }, // >>--->
|
||||
{ { -R+3*R/8, 0 }, { -R+R/8, -R/4 } }
|
||||
};
|
||||
*/
|
||||
#undef R
|
||||
#define NUMPLYRLINES (sizeof(player_arrow)/sizeof(mline_t))
|
||||
#define NUMKEYSQUARELINES (sizeof(keysquare)/sizeof(mline_t))
|
||||
|
||||
#define R ((8*PLAYERRADIUS)/7)
|
||||
mline_t cheat_player_arrow[] = {
|
||||
{ { -R+R/8, 0 }, { R, 0 } }, // -----
|
||||
{ { R, 0 }, { R-R/2, R/6 } }, // ----->
|
||||
{ { R, 0 }, { R-R/2, -R/6 } },
|
||||
{ { -R+R/8, 0 }, { -R-R/8, R/6 } }, // >----->
|
||||
{ { -R+R/8, 0 }, { -R-R/8, -R/6 } },
|
||||
{ { -R+3*R/8, 0 }, { -R+R/8, R/6 } }, // >>----->
|
||||
{ { -R+3*R/8, 0 }, { -R+R/8, -R/6 } },
|
||||
{ { -R/2, 0 }, { -R/2, -R/6 } }, // >>-d--->
|
||||
{ { -R/2, -R/6 }, { -R/2+R/6, -R/6 } },
|
||||
{ { -R/2+R/6, -R/6 }, { -R/2+R/6, R/4 } },
|
||||
{ { -R/6, 0 }, { -R/6, -R/6 } }, // >>-dd-->
|
||||
{ { -R/6, -R/6 }, { 0, -R/6 } },
|
||||
{ { 0, -R/6 }, { 0, R/4 } },
|
||||
{ { R/6, R/4 }, { R/6, -R/7 } }, // >>-ddt->
|
||||
{ { R/6, -R/7 }, { R/6+R/32, -R/7-R/32 } },
|
||||
{ { R/6+R/32, -R/7-R/32 }, { R/6+R/10, -R/7 } }
|
||||
};
|
||||
#undef R
|
||||
#define NUMCHEATPLYRLINES (sizeof(cheat_player_arrow)/sizeof(mline_t))
|
||||
|
||||
#define R (FRACUNIT)
|
||||
mline_t triangle_guy[] = {
|
||||
{ { -.867*R, -.5*R }, { .867*R, -.5*R } },
|
||||
{ { .867*R, -.5*R } , { 0, R } },
|
||||
{ { 0, R }, { -.867*R, -.5*R } }
|
||||
};
|
||||
#undef R
|
||||
#define NUMTRIANGLEGUYLINES (sizeof(triangle_guy)/sizeof(mline_t))
|
||||
|
||||
#define R (FRACUNIT)
|
||||
mline_t thintriangle_guy[] = {
|
||||
{ { -.5*R, -.7*R }, { R, 0 } },
|
||||
{ { R, 0 }, { -.5*R, .7*R } },
|
||||
{ { -.5*R, .7*R }, { -.5*R, -.7*R } }
|
||||
};
|
||||
#undef R
|
||||
#define NUMTHINTRIANGLEGUYLINES (sizeof(thintriangle_guy)/sizeof(mline_t))
|
||||
|
||||
#endif
|
1352
Heretic Source/AM_MAP.C
Normal file
1352
Heretic Source/AM_MAP.C
Normal file
File diff suppressed because it is too large
Load diff
121
Heretic Source/AM_MAP.H
Normal file
121
Heretic Source/AM_MAP.H
Normal file
|
@ -0,0 +1,121 @@
|
|||
#ifndef __AMMAP_H__
|
||||
#define __AMMAP_H__
|
||||
|
||||
#pragma once
|
||||
|
||||
// For use if I do walls with outsides/insides
|
||||
#define REDS 12*8
|
||||
#define REDRANGE 1//16
|
||||
#define BLUES (256-4*16+8)
|
||||
#define BLUERANGE 1//8
|
||||
#define GREENS (33*8)
|
||||
#define GREENRANGE 1//16
|
||||
#define GRAYS (5*8)
|
||||
#define GRAYSRANGE 1//16
|
||||
#define BROWNS (14*8)
|
||||
#define BROWNRANGE 1//16
|
||||
#define YELLOWS 10*8
|
||||
#define YELLOWRANGE 1
|
||||
#define BLACK 0
|
||||
#define WHITE 4*8
|
||||
#define PARCH 13*8-1
|
||||
#define BLOODRED 150
|
||||
#define BLUEKEY 197
|
||||
#define YELLOWKEY 144
|
||||
#define GREENKEY 220
|
||||
|
||||
// Automap colors
|
||||
#define BACKGROUND PARCH
|
||||
#define YOURCOLORS WHITE
|
||||
#define YOURRANGE 0
|
||||
#define WALLCOLORS REDS
|
||||
#define WALLRANGE REDRANGE
|
||||
#define TSWALLCOLORS GRAYS
|
||||
#define TSWALLRANGE GRAYSRANGE
|
||||
#define FDWALLCOLORS BROWNS
|
||||
#define FDWALLRANGE BROWNRANGE
|
||||
#define CDWALLCOLORS YELLOWS
|
||||
#define CDWALLRANGE YELLOWRANGE
|
||||
#define THINGCOLORS GREENS
|
||||
#define THINGRANGE GREENRANGE
|
||||
#define SECRETWALLCOLORS WALLCOLORS
|
||||
#define SECRETWALLRANGE WALLRANGE
|
||||
#define GRIDCOLORS (GRAYS + GRAYSRANGE/2)
|
||||
#define GRIDRANGE 0
|
||||
#define XHAIRCOLORS GRAYS
|
||||
|
||||
// drawing stuff
|
||||
#define FB 0
|
||||
|
||||
#define KEY_TAB 9
|
||||
#define AM_PANDOWNKEY KEY_DOWNARROW
|
||||
#define AM_PANUPKEY KEY_UPARROW
|
||||
#define AM_PANRIGHTKEY KEY_RIGHTARROW
|
||||
#define AM_PANLEFTKEY KEY_LEFTARROW
|
||||
//#define AM_PANDOWNKEY SC_DOWNARROW
|
||||
//#define AM_PANUPKEY SC_UPARROW
|
||||
//#define AM_PANRIGHTKEY SC_RIGHTARROW
|
||||
//#define AM_PANLEFTKEY SC_LEFTARROW
|
||||
|
||||
#define AM_ZOOMINKEY '='
|
||||
//#define AM_ZOOMINKEY 13
|
||||
//#define AM_ZOOMOUTKEY 12
|
||||
#define AM_ZOOMOUTKEY '-'
|
||||
#define AM_STARTKEY KEY_TAB
|
||||
#define AM_ENDKEY KEY_TAB
|
||||
#define AM_GOBIGKEY '0'
|
||||
//#define AM_GOBIGKEY 11
|
||||
//#define AM_FOLLOWKEY 33
|
||||
//#define AM_GRIDKEY 34
|
||||
#define AM_FOLLOWKEY 'f'
|
||||
#define AM_GRIDKEY 'g'
|
||||
|
||||
#define AM_NUMMARKPOINTS 10
|
||||
|
||||
#define AM_MSGHEADER (('a'<<24)+('m'<<16))
|
||||
#define AM_MSGENTERED (AM_MSGHEADER | ('e'<<8))
|
||||
#define AM_MSGEXITED (AM_MSGHEADER | ('x'<<8))
|
||||
|
||||
#define INITSCALEMTOF (.2*FRACUNIT) // scale on entry
|
||||
// how much the automap moves window per tic in frame-buffer coordinates
|
||||
#define F_PANINC 4 // moves 140 pixels in 1 second
|
||||
// how much zoom-in per tic
|
||||
#define M_ZOOMIN ((int) (1.02*FRACUNIT)) // goes to 2x in 1 second
|
||||
// how much zoom-out per tic
|
||||
#define M_ZOOMOUT ((int) (FRACUNIT/1.02)) // pulls out to 0.5x in 1 second
|
||||
|
||||
// translates between frame-buffer and map distances
|
||||
#define FTOM(x) FixedMul(((x)<<16),scale_ftom)
|
||||
#define MTOF(x) (FixedMul((x),scale_mtof)>>16)
|
||||
// translates between frame-buffer and map coordinates
|
||||
#define CXMTOF(x) (f_x + MTOF((x)-m_x))
|
||||
#define CYMTOF(y) (f_y + (f_h - MTOF((y)-m_y)))
|
||||
|
||||
// the following is crap
|
||||
#define LINE_NEVERSEE ML_DONTDRAW
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int x, y;
|
||||
} fpoint_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
fpoint_t a, b;
|
||||
} fline_t;
|
||||
|
||||
typedef vertex_t mpoint_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
mpoint_t a, b;
|
||||
} mline_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
fixed_t slp, islp;
|
||||
} islope_t;
|
||||
|
||||
// extern int f_x, f_y, f_w, f_h;
|
||||
|
||||
#endif
|
BIN
Heretic Source/COLORMAP.LMP
Normal file
BIN
Heretic Source/COLORMAP.LMP
Normal file
Binary file not shown.
462
Heretic Source/CT_CHAT.C
Normal file
462
Heretic Source/CT_CHAT.C
Normal file
|
@ -0,0 +1,462 @@
|
|||
//
|
||||
// Chat mode
|
||||
//
|
||||
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include "DoomDef.h"
|
||||
#include "P_local.h"
|
||||
#include "soundst.h"
|
||||
|
||||
#define QUEUESIZE 128
|
||||
#define MESSAGESIZE 128
|
||||
#define MESSAGELEN 265
|
||||
|
||||
#define CT_PLR_GREEN 1
|
||||
#define CT_PLR_YELLOW 2
|
||||
#define CT_PLR_RED 3
|
||||
#define CT_PLR_BLUE 4
|
||||
#define CT_PLR_ALL 5
|
||||
|
||||
#define CT_KEY_GREEN 'g'
|
||||
#define CT_KEY_YELLOW 'y'
|
||||
#define CT_KEY_RED 'r'
|
||||
#define CT_KEY_BLUE 'b'
|
||||
#define CT_KEY_ALL 't'
|
||||
#define CT_ESCAPE 6
|
||||
|
||||
// Public data
|
||||
|
||||
void CT_Init(void);
|
||||
void CT_Drawer(void);
|
||||
boolean CT_Responder(event_t *ev);
|
||||
void CT_Ticker(void);
|
||||
char CT_dequeueChatChar(void);
|
||||
|
||||
boolean chatmodeon;
|
||||
|
||||
// Private data
|
||||
|
||||
void CT_queueChatChar(char ch);
|
||||
void CT_ClearChatMessage(int player);
|
||||
void CT_AddChar(int player, char c);
|
||||
void CT_BackSpace(int player);
|
||||
|
||||
int head;
|
||||
int tail;
|
||||
byte ChatQueue[QUEUESIZE];
|
||||
int chat_dest[MAXPLAYERS];
|
||||
char chat_msg[MAXPLAYERS][MESSAGESIZE];
|
||||
char plr_lastmsg[MAXPLAYERS][MESSAGESIZE+9]; // add in the length of the pre-string
|
||||
int msgptr[MAXPLAYERS];
|
||||
int msglen[MAXPLAYERS];
|
||||
|
||||
boolean cheated;
|
||||
|
||||
static int FontABaseLump;
|
||||
|
||||
char *CT_FromPlrText[MAXPLAYERS] =
|
||||
{
|
||||
"GREEN: ",
|
||||
"YELLOW: ",
|
||||
"RED: ",
|
||||
"BLUE: "
|
||||
};
|
||||
|
||||
char *chat_macros[10];
|
||||
|
||||
boolean altdown;
|
||||
boolean shiftdown;
|
||||
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// CT_Init
|
||||
//
|
||||
// Initialize chat mode data
|
||||
//===========================================================================
|
||||
|
||||
void CT_Init(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
head = 0; //initialize the queue index
|
||||
tail = 0;
|
||||
chatmodeon = false;
|
||||
memset(ChatQueue, 0, QUEUESIZE);
|
||||
for(i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
chat_dest[i] = 0;
|
||||
msgptr[i] = 0;
|
||||
memset(plr_lastmsg[i], 0, MESSAGESIZE);
|
||||
memset(chat_msg[i], 0, MESSAGESIZE);
|
||||
}
|
||||
FontABaseLump = W_GetNumForName("FONTA_S")+1;
|
||||
return;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// CT_Stop
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
void CT_Stop(void)
|
||||
{
|
||||
chatmodeon = false;
|
||||
return;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// CT_Responder
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
boolean CT_Responder(event_t *ev)
|
||||
{
|
||||
char *macro;
|
||||
|
||||
int sendto;
|
||||
|
||||
if(!netgame)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if(ev->data1 == KEY_LALT || ev->data2 == KEY_RALT)
|
||||
{
|
||||
altdown = (ev->type == ev_keydown);
|
||||
return false;
|
||||
}
|
||||
if(ev->data1 == KEY_RSHIFT)
|
||||
{
|
||||
shiftdown = (ev->type == ev_keydown);
|
||||
return false;
|
||||
}
|
||||
if(ev->type != ev_keydown)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if(!chatmodeon)
|
||||
{
|
||||
sendto = 0;
|
||||
if(ev->data1 == CT_KEY_ALL)
|
||||
{
|
||||
sendto = CT_PLR_ALL;
|
||||
}
|
||||
else if(ev->data1 == CT_KEY_GREEN)
|
||||
{
|
||||
sendto = CT_PLR_GREEN;
|
||||
}
|
||||
else if(ev->data1 == CT_KEY_YELLOW)
|
||||
{
|
||||
sendto = CT_PLR_YELLOW;
|
||||
}
|
||||
else if(ev->data1 == CT_KEY_RED)
|
||||
{
|
||||
sendto = CT_PLR_RED;
|
||||
}
|
||||
else if(ev->data1 == CT_KEY_BLUE)
|
||||
{
|
||||
sendto = CT_PLR_BLUE;
|
||||
}
|
||||
if(sendto == 0 || (sendto != CT_PLR_ALL && !playeringame[sendto-1])
|
||||
|| sendto == consoleplayer+1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
CT_queueChatChar(sendto);
|
||||
chatmodeon = true;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(altdown)
|
||||
{
|
||||
if(ev->data1 >= '0' && ev->data1 <= '9')
|
||||
{
|
||||
if(ev->data1 == '0')
|
||||
{ // macro 0 comes after macro 9
|
||||
ev->data1 = '9'+1;
|
||||
}
|
||||
macro = chat_macros[ev->data1-'1'];
|
||||
CT_queueChatChar(KEY_ENTER); //send old message
|
||||
CT_queueChatChar(chat_dest[consoleplayer]); // chose the dest.
|
||||
while(*macro)
|
||||
{
|
||||
CT_queueChatChar(toupper(*macro++));
|
||||
}
|
||||
CT_queueChatChar(KEY_ENTER); //send it off...
|
||||
CT_Stop();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if(ev->data1 == KEY_ENTER)
|
||||
{
|
||||
CT_queueChatChar(KEY_ENTER);
|
||||
CT_Stop();
|
||||
return true;
|
||||
}
|
||||
else if(ev->data1 == KEY_ESCAPE)
|
||||
{
|
||||
CT_queueChatChar(CT_ESCAPE);
|
||||
CT_Stop();
|
||||
return true;
|
||||
}
|
||||
else if(ev->data1 >= 'a' && ev->data1 <= 'z')
|
||||
{
|
||||
CT_queueChatChar(ev->data1-32);
|
||||
return true;
|
||||
}
|
||||
else if(shiftdown)
|
||||
{
|
||||
if(ev->data1 == '1')
|
||||
{
|
||||
CT_queueChatChar('!');
|
||||
return true;
|
||||
}
|
||||
else if(ev->data1 == '/')
|
||||
{
|
||||
CT_queueChatChar('?');
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(ev->data1 == ' ' || ev->data1 == ',' || ev->data1 == '.'
|
||||
|| (ev->data1 >= '0' && ev->data1 <= '9') || ev->data1 == '\''
|
||||
|| ev->data1 == KEY_BACKSPACE || ev->data1 == '-' || ev->data1 == '=')
|
||||
{
|
||||
CT_queueChatChar(ev->data1);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// CT_Ticker
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
void CT_Ticker(void)
|
||||
{
|
||||
int i;
|
||||
int j;
|
||||
char c;
|
||||
int numplayers;
|
||||
|
||||
for(i=0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if(!playeringame[i])
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if((c = players[i].cmd.chatchar) != 0)
|
||||
{
|
||||
if(c <= 5)
|
||||
{
|
||||
chat_dest[i] = c;
|
||||
continue;
|
||||
}
|
||||
else if(c == CT_ESCAPE)
|
||||
{
|
||||
CT_ClearChatMessage(i);
|
||||
}
|
||||
else if(c == KEY_ENTER)
|
||||
{
|
||||
numplayers = 0;
|
||||
for(j = 0; j < MAXPLAYERS; j++)
|
||||
{
|
||||
numplayers += playeringame[j];
|
||||
}
|
||||
CT_AddChar(i, 0); // set the end of message character
|
||||
if(numplayers > 2)
|
||||
{
|
||||
strcpy(plr_lastmsg[i], CT_FromPlrText[i]);
|
||||
strcat(plr_lastmsg[i], chat_msg[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy(plr_lastmsg[i], chat_msg[i]);
|
||||
}
|
||||
if(i != consoleplayer && (chat_dest[i] == consoleplayer+1
|
||||
|| chat_dest[i] == CT_PLR_ALL) && *chat_msg[i])
|
||||
{
|
||||
P_SetMessage(&players[consoleplayer], plr_lastmsg[i],
|
||||
true);
|
||||
S_StartSound(NULL, sfx_chat);
|
||||
}
|
||||
else if(i == consoleplayer && (*chat_msg[i]))
|
||||
{
|
||||
if(numplayers > 1)
|
||||
{
|
||||
P_SetMessage(&players[consoleplayer], "-MESSAGE SENT-",
|
||||
true);
|
||||
S_StartSound(NULL, sfx_chat);
|
||||
}
|
||||
else
|
||||
{
|
||||
P_SetMessage(&players[consoleplayer],
|
||||
"THERE ARE NO OTHER PLAYERS IN THE GAME!", true);
|
||||
S_StartSound(NULL, sfx_chat);
|
||||
}
|
||||
}
|
||||
CT_ClearChatMessage(i);
|
||||
}
|
||||
else if(c == KEY_BACKSPACE)
|
||||
{
|
||||
CT_BackSpace(i);
|
||||
}
|
||||
else
|
||||
{
|
||||
CT_AddChar(i, c);
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// CT_Drawer
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
void CT_Drawer(void)
|
||||
{
|
||||
int i;
|
||||
int x;
|
||||
patch_t *patch;
|
||||
|
||||
if(chatmodeon)
|
||||
{
|
||||
x = 25;
|
||||
for(i = 0; i < msgptr[consoleplayer]; i++)
|
||||
{
|
||||
if(chat_msg[consoleplayer][i] < 33)
|
||||
{
|
||||
x += 6;
|
||||
}
|
||||
else
|
||||
{
|
||||
patch=W_CacheLumpNum(FontABaseLump+
|
||||
chat_msg[consoleplayer][i]-33, PU_CACHE);
|
||||
V_DrawPatch(x, 10, patch);
|
||||
x += patch->width;
|
||||
}
|
||||
}
|
||||
V_DrawPatch(x, 10, W_CacheLumpName("FONTA59", PU_CACHE));
|
||||
BorderTopRefresh = true;
|
||||
UpdateState |= I_MESSAGES;
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// CT_queueChatChar
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
void CT_queueChatChar(char ch)
|
||||
{
|
||||
if((tail+1)&(QUEUESIZE-1) == head)
|
||||
{ // the queue is full
|
||||
return;
|
||||
}
|
||||
ChatQueue[tail] = ch;
|
||||
tail = (tail+1)&(QUEUESIZE-1);
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// CT_dequeueChatChar
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
char CT_dequeueChatChar(void)
|
||||
{
|
||||
byte temp;
|
||||
|
||||
if(head == tail)
|
||||
{ // queue is empty
|
||||
return 0;
|
||||
}
|
||||
temp = ChatQueue[head];
|
||||
head = (head+1)&(QUEUESIZE-1);
|
||||
return temp;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// CT_AddChar
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
void CT_AddChar(int player, char c)
|
||||
{
|
||||
patch_t *patch;
|
||||
|
||||
if(msgptr[player]+1 >= MESSAGESIZE || msglen[player] >= MESSAGELEN)
|
||||
{ // full.
|
||||
return;
|
||||
}
|
||||
chat_msg[player][msgptr[player]] = c;
|
||||
msgptr[player]++;
|
||||
if(c < 33)
|
||||
{
|
||||
msglen[player] += 6;
|
||||
}
|
||||
else
|
||||
{
|
||||
patch = W_CacheLumpNum(FontABaseLump+c-33, PU_CACHE);
|
||||
msglen[player] += patch->width;
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// CT_BackSpace
|
||||
//
|
||||
// Backs up a space, when the user hits (obviously) backspace
|
||||
//===========================================================================
|
||||
|
||||
void CT_BackSpace(int player)
|
||||
{
|
||||
patch_t *patch;
|
||||
char c;
|
||||
|
||||
if(msgptr[player] == 0)
|
||||
{ // message is already blank
|
||||
return;
|
||||
}
|
||||
msgptr[player]--;
|
||||
c = chat_msg[player][msgptr[player]];
|
||||
if(c < 33)
|
||||
{
|
||||
msglen[player] -= 6;
|
||||
}
|
||||
else
|
||||
{
|
||||
patch = W_CacheLumpNum(FontABaseLump+c-33, PU_CACHE);
|
||||
msglen[player] -= patch->width;
|
||||
}
|
||||
chat_msg[player][msgptr[player]] = 0;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// CT_ClearChatMessage
|
||||
//
|
||||
// Clears out the data for the chat message, but the player's message
|
||||
// is still saved in plrmsg.
|
||||
//===========================================================================
|
||||
|
||||
void CT_ClearChatMessage(int player)
|
||||
{
|
||||
memset(chat_msg[player], 0, MESSAGESIZE);
|
||||
msgptr[player] = 0;
|
||||
msglen[player] = 0;
|
||||
}
|
15
Heretic Source/CT_CHAT.H
Normal file
15
Heretic Source/CT_CHAT.H
Normal file
|
@ -0,0 +1,15 @@
|
|||
//
|
||||
// Chat mode stuff
|
||||
//
|
||||
|
||||
#define CT_PLR_GREEN 1
|
||||
#define CT_PLR_YELLOW 2
|
||||
#define CT_PLR_RED 3
|
||||
#define CT_PLR_BLUE 4
|
||||
#define CT_PLR_ALL 5
|
||||
|
||||
#define CT_KEY_GREEN 'g'
|
||||
#define CT_KEY_YELLOW 'y'
|
||||
#define CT_KEY_RED 'r'
|
||||
#define CT_KEY_BLUE 'b'
|
||||
#define CT_KEY_ALL 't'
|
51
Heretic Source/DEFS.INC
Normal file
51
Heretic Source/DEFS.INC
Normal file
|
@ -0,0 +1,51 @@
|
|||
SKIPPRIMITIVES = 0 ; set to 1 to skip unwound drawing
|
||||
|
||||
|
||||
SCREEN = 0a0000h
|
||||
SCREENWIDTH = 320
|
||||
SCREENHEIGHT = 200
|
||||
PLANEWIDTH = 80
|
||||
PLANESIZE = 80*200
|
||||
|
||||
PEL_WRITE_ADR = 03c8h
|
||||
PEL_DATA = 03c9h
|
||||
|
||||
SC_INDEX = 03C4h
|
||||
SC_MAPMASK = 2
|
||||
|
||||
OP_RET = 0c3h
|
||||
OP_MOVAL = 08ah
|
||||
OP_MOVDEST = 088h
|
||||
|
||||
|
||||
.DATA
|
||||
|
||||
EXTRN _dc_colormap:DWORD
|
||||
EXTRN _dc_x:DWORD
|
||||
EXTRN _dc_yl:DWORD
|
||||
EXTRN _dc_yh:DWORD
|
||||
EXTRN _dc_iscale:DWORD
|
||||
EXTRN _dc_texturemid:DWORD
|
||||
EXTRN _dc_source:DWORD
|
||||
|
||||
EXTRN _ylookup:DWORD
|
||||
EXTRN _columnofs:DWORD
|
||||
|
||||
|
||||
EXTRN _ds_y:DWORD
|
||||
EXTRN _ds_x1:DWORD
|
||||
EXTRN _ds_x2:DWORD
|
||||
EXTRN _ds_colormap:DWORD
|
||||
EXTRN _ds_xfrac:DWORD
|
||||
EXTRN _ds_yfrac:DWORD
|
||||
EXTRN _ds_xstep:DWORD
|
||||
EXTRN _ds_ystep:DWORD
|
||||
EXTRN _ds_source:DWORD
|
||||
|
||||
PUSHR MACRO
|
||||
pushad
|
||||
ENDM
|
||||
|
||||
POPR MACRO
|
||||
popad
|
||||
ENDM
|
BIN
Heretic Source/DEMO1.LMP
Normal file
BIN
Heretic Source/DEMO1.LMP
Normal file
Binary file not shown.
195
Heretic Source/DOOMDATA.H
Normal file
195
Heretic Source/DOOMDATA.H
Normal file
|
@ -0,0 +1,195 @@
|
|||
// DoomData.h
|
||||
|
||||
// all external data is defined here
|
||||
// most of the data is loaded into different structures at run time
|
||||
|
||||
#ifndef __DOOMDATA__
|
||||
#define __DOOMDATA__
|
||||
|
||||
#ifndef __BYTEBOOL__
|
||||
#define __BYTEBOOL__
|
||||
typedef enum {false, true} boolean;
|
||||
typedef unsigned char byte;
|
||||
#endif
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
|
||||
map level types
|
||||
|
||||
===============================================================================
|
||||
*/
|
||||
|
||||
// lump order in a map wad
|
||||
enum {ML_LABEL, ML_THINGS, ML_LINEDEFS, ML_SIDEDEFS, ML_VERTEXES, ML_SEGS,
|
||||
ML_SSECTORS, ML_NODES, ML_SECTORS , ML_REJECT, ML_BLOCKMAP};
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
short x,y;
|
||||
} mapvertex_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
short textureoffset;
|
||||
short rowoffset;
|
||||
char toptexture[8], bottomtexture[8], midtexture[8];
|
||||
short sector; // on viewer's side
|
||||
} mapsidedef_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
short v1, v2;
|
||||
short flags;
|
||||
short special, tag;
|
||||
short sidenum[2]; // sidenum[1] will be -1 if one sided
|
||||
} maplinedef_t;
|
||||
|
||||
#define ML_BLOCKING 1
|
||||
#define ML_BLOCKMONSTERS 2
|
||||
#define ML_TWOSIDED 4 // backside will not be present at all
|
||||
// if not two sided
|
||||
|
||||
// if a texture is pegged, the texture will have the end exposed to air held
|
||||
// constant at the top or bottom of the texture (stairs or pulled down things)
|
||||
// and will move with a height change of one of the neighbor sectors
|
||||
// Unpegged textures allways have the first row of the texture at the top
|
||||
// pixel of the line for both top and bottom textures (windows)
|
||||
#define ML_DONTPEGTOP 8
|
||||
#define ML_DONTPEGBOTTOM 16
|
||||
|
||||
#define ML_SECRET 32 // don't map as two sided: IT'S A SECRET!
|
||||
#define ML_SOUNDBLOCK 64 // don't let sound cross two of these
|
||||
#define ML_DONTDRAW 128 // don't draw on the automap
|
||||
#define ML_MAPPED 256 // set if allready drawn in automap
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
short floorheight, ceilingheight;
|
||||
char floorpic[8], ceilingpic[8];
|
||||
short lightlevel;
|
||||
short special, tag;
|
||||
} mapsector_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
short numsegs;
|
||||
short firstseg; // segs are stored sequentially
|
||||
} mapsubsector_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
short v1, v2;
|
||||
short angle;
|
||||
short linedef, side;
|
||||
short offset;
|
||||
} mapseg_t;
|
||||
|
||||
enum {BOXTOP,BOXBOTTOM,BOXLEFT,BOXRIGHT}; // bbox coordinates
|
||||
|
||||
#define NF_SUBSECTOR 0x8000
|
||||
typedef struct
|
||||
{
|
||||
short x,y,dx,dy; // partition line
|
||||
short bbox[2][4]; // bounding box for each child
|
||||
unsigned short children[2]; // if NF_SUBSECTOR its a subsector
|
||||
} mapnode_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
short x,y;
|
||||
short angle;
|
||||
short type;
|
||||
short options;
|
||||
} mapthing_t;
|
||||
|
||||
#define MTF_EASY 1
|
||||
#define MTF_NORMAL 2
|
||||
#define MTF_HARD 4
|
||||
#define MTF_AMBUSH 8
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
|
||||
texture definition
|
||||
|
||||
===============================================================================
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
short originx;
|
||||
short originy;
|
||||
short patch;
|
||||
short stepdir;
|
||||
short colormap;
|
||||
} mappatch_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char name[8];
|
||||
boolean masked;
|
||||
short width;
|
||||
short height;
|
||||
void **columndirectory; // OBSOLETE
|
||||
short patchcount;
|
||||
mappatch_t patches[1];
|
||||
} maptexture_t;
|
||||
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
|
||||
graphics
|
||||
|
||||
===============================================================================
|
||||
*/
|
||||
|
||||
// posts are runs of non masked source pixels
|
||||
typedef struct
|
||||
{
|
||||
byte topdelta; // -1 is the last post in a column
|
||||
byte length;
|
||||
// length data bytes follows
|
||||
} post_t;
|
||||
|
||||
// column_t is a list of 0 or more post_t, (byte)-1 terminated
|
||||
typedef post_t column_t;
|
||||
|
||||
// a patch holds one or more columns
|
||||
// patches are used for sprites and all masked pictures
|
||||
typedef struct
|
||||
{
|
||||
short width; // bounding box size
|
||||
short height;
|
||||
short leftoffset; // pixels to the left of origin
|
||||
short topoffset; // pixels below the origin
|
||||
int columnofs[8]; // only [width] used
|
||||
// the [0] is &columnofs[width]
|
||||
} patch_t;
|
||||
|
||||
// a pic is an unmasked block of pixels
|
||||
typedef struct
|
||||
{
|
||||
byte width,height;
|
||||
byte data;
|
||||
} pic_t;
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
|
||||
status
|
||||
|
||||
===============================================================================
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
#endif // __DOOMDATA__
|
||||
|
1182
Heretic Source/DOOMDEF.H
Normal file
1182
Heretic Source/DOOMDEF.H
Normal file
File diff suppressed because it is too large
Load diff
18
Heretic Source/DRCOORD.H
Normal file
18
Heretic Source/DRCOORD.H
Normal file
|
@ -0,0 +1,18 @@
|
|||
|
||||
#import <appkit/appkit.h>
|
||||
|
||||
@interface DRCoord:Object
|
||||
{
|
||||
id players_i;
|
||||
id console_i;
|
||||
id skill_i;
|
||||
id episode_i;
|
||||
id map_i;
|
||||
}
|
||||
|
||||
- newGame: sender;
|
||||
- scale1: sender;
|
||||
- scale2: sender;
|
||||
- scale4: sender;
|
||||
|
||||
@end
|
406
Heretic Source/DSTRINGS.BAK
Normal file
406
Heretic Source/DSTRINGS.BAK
Normal file
|
@ -0,0 +1,406 @@
|
|||
|
||||
// DStrings.h
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// M_menu.c
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
#define PRESSKEY "press a key."
|
||||
#define PRESSYN "press y or n."
|
||||
#define TXT_PAUSED "PAUSED"
|
||||
#define QUITMSG "are you sure you want to\nquit this great game?"
|
||||
#define LOADNET "you can't do load while in a net game!\n\n"PRESSKEY
|
||||
#define QLOADNET "you can't quickload during a netgame!\n\n"PRESSKEY
|
||||
#define QSAVESPOT "you haven't picked a quicksave slot yet!\n\n"PRESSKEY
|
||||
#define SAVEDEAD "you can't save if you aren't playing!\n\n"PRESSKEY
|
||||
#define QSPROMPT "quicksave over your game named\n\n'%s'?\n\n"PRESSYN
|
||||
#define QLPROMPT "do you want to quickload the game named"\
|
||||
"\n\n'%s'?\n\n"PRESSYN
|
||||
#define NEWGAME "you can't start a new game\n"\
|
||||
"while in a network game.\n\n"PRESSKEY
|
||||
#define NIGHTMARE "are you sure? this skill level\n"\
|
||||
"isn't even remotely fair.\n\n"PRESSYN
|
||||
#define SWSTRING "this is the shareware version of doom.\n\n"\
|
||||
"you need to order the entire trilogy.\n\n"PRESSKEY
|
||||
#define MSGOFF "Messages OFF"
|
||||
#define MSGON "Messages ON"
|
||||
#define NETEND "you can't end a netgame!\n\n"PRESSKEY
|
||||
#define ENDGAME "are you sure you want to end the game?\n\n"PRESSYN
|
||||
#define DOSY "(press y to quit to dos.)"
|
||||
#define DETAILHI "High detail"
|
||||
#define DETAILLO "Low detail"
|
||||
#define GAMMALVL0 "Gamma correction OFF"
|
||||
#define GAMMALVL1 "Gamma correction level 1"
|
||||
#define GAMMALVL2 "Gamma correction level 2"
|
||||
#define GAMMALVL3 "Gamma correction level 3"
|
||||
#define GAMMALVL4 "Gamma correction level 4"
|
||||
#define EMPTYSTRING "empty slot"
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// P_inter.c
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
// Keys
|
||||
|
||||
#define TXT_GOTBLUEKEY "BLUE KEY"
|
||||
#define TXT_GOTYELLOWKEY "YELLOW KEY"
|
||||
#define TXT_GOTGREENKEY "GREEN KEY"
|
||||
|
||||
// Artifacts
|
||||
|
||||
#define TXT_ARTIHEALTH "QUARTZ FLASK"
|
||||
#define TXT_ARTIFLY "WINGS OF WRATH"
|
||||
#define TXT_ARTIINVULNERABILITY "RING OF INVINCIBILITY"
|
||||
#define TXT_ARTITOMEOFPOWER "TOME OF POWER"
|
||||
#define TXT_ARTIINVISIBILITY "SHADOWSPHERE"
|
||||
#define TXT_ARTIEGG "MORPH OVUM"
|
||||
#define TXT_ARTISUPERHEALTH "MYSTIC URN"
|
||||
#define TXT_ARTITORCH "TORCH"
|
||||
#define TXT_ARTIFIREBOMB "TIME BOMB OF THE ANCIENTS"
|
||||
#define TXT_ARTITELEPORT "CHAOS DEVICE"
|
||||
|
||||
// Items
|
||||
|
||||
#define TXT_ITEMHEALTH "CRYSTAL VIAL"
|
||||
#define TXT_ITEMBAGOFHOLDING "BAG OF HOLDING"
|
||||
#define TXT_ITEMSHIELD1 "SILVER SHIELD"
|
||||
#define TXT_ITEMSHIELD2 "ENCHANTED SHIELD"
|
||||
#define TXT_ITEMSUPERMAP "MAP SCROLL"
|
||||
|
||||
// Ammo
|
||||
|
||||
#define TXT_AMMOGOLDWAND1 "WAND CRYSTAL"
|
||||
#define TXT_AMMOGOLDWAND2 "CRYSTAL GEODE"
|
||||
#define TXT_AMMOMACE1 "MACE SPHERES"
|
||||
#define TXT_AMMOMACE2 "PILE OF MACE SPHERES"
|
||||
#define TXT_AMMOCROSSBOW1 "ETHEREAL ARROWS"
|
||||
#define TXT_AMMOCROSSBOW2 "QUIVER OF ETHEREAL ARROWS"
|
||||
#define TXT_AMMOBLASTER1 "CLAW ORB"
|
||||
#define TXT_AMMOBLASTER2 "ENERGY ORB"
|
||||
#define TXT_AMMOSKULLROD1 "LESSER RUNES"
|
||||
#define TXT_AMMOSKULLROD2 "GREATER RUNES"
|
||||
#define TXT_AMMOPHOENIXROD1 "FLAME ORB"
|
||||
#define TXT_AMMOPHOENIXROD2 "INFERNO ORB"
|
||||
|
||||
// Weapons
|
||||
|
||||
#define TXT_WPNMACE "FIREMACE"
|
||||
#define TXT_WPNCROSSBOW "ETHEREAL CROSSBOW"
|
||||
#define TXT_WPNBLASTER "DRAGON CLAW"
|
||||
#define TXT_WPNSKULLROD "HELLSTAFF"
|
||||
#define TXT_WPNPHOENIXROD "PHOENIX ROD"
|
||||
#define TXT_WPNGAUNTLETS "GAUNTLETS OF THE NECROMANCER"
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// SB_bar.c
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
#define TXT_CHEATGODON "GOD MODE ON"
|
||||
#define TXT_CHEATGODOFF "GOD MODE OFF"
|
||||
#define TXT_CHEATNOCLIPON "NO CLIPPING ON"
|
||||
#define TXT_CHEATNOCLIPOFF "NO CLIPPING OFF"
|
||||
#define TXT_CHEATWEAPONS "ALL WEAPONS"
|
||||
#define TXT_CHEATFLIGHTON "FLIGHT ON"
|
||||
#define TXT_CHEATFLIGHTOFF "FLIGHT OFF"
|
||||
#define TXT_CHEATPOWERON "POWER ON"
|
||||
#define TXT_CHEATPOWEROFF "POWER OFF"
|
||||
#define TXT_CHEATHEALTH "FULL HEALTH"
|
||||
#define TXT_CHEATKEYS "ALL KEYS"
|
||||
#define TXT_CHEATSOUNDON "SOUND DEBUG ON"
|
||||
#define TXT_CHEATSOUNDOFF "SOUND DEBUG OFF"
|
||||
#define TXT_CHEATTICKERON "TICKER ON"
|
||||
#define TXT_CHEATTICKEROFF "TICKER OFF"
|
||||
#define TXT_CHEATARTIFACTS1 "CHOOSE AN ARTIFACT ( A - J )"
|
||||
#define TXT_CHEATARTIFACTS2 "HOW MANY ( 1 - 9 )"
|
||||
#define TXT_CHEATARTIFACTS3 "YOU GOT IT"
|
||||
#define TXT_CHEATARTIFACTSFAIL "BAD INPUT"
|
||||
#define TXT_CHEATWARP "LEVEL WARP"
|
||||
#define TXT_CHEATSCREENSHOT "SCREENSHOT"
|
||||
#define TXT_CHEATCHICKENON "CHICKEN ON"
|
||||
#define TXT_CHEATCHICKENOFF "CHICKEN OFF"
|
||||
#define TXT_CHEATMASSACRE "MASSACRE"
|
||||
#define TXT_CHEATIDDQD "TRYING TO CHEAT, EH? NOW YOU DIE!"
|
||||
#define TXT_CHEATIDKFA "CHEATER - YOU DON'T DESERVE WEAPONS"
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// P_doors.c
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
#define TXT_NEEDBLUEKEY "YOU NEED A BLUE KEY TO OPEN THIS DOOR"
|
||||
#define TXT_NEEDGREENKEY "YOU NEED A GREEN KEY TO OPEN THIS DOOR"
|
||||
#define TXT_NEEDYELLOWKEY "YOU NEED A YELLOW KEY TO OPEN THIS DOOR"
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// G_game.c
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
#define TXT_GAMESAVED "GAME SAVED"
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// HU_stuff.c
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
#define HUSTR_E1M1 "E1M1: Hangar"
|
||||
#define HUSTR_E1M2 "E1M2: Nuclear Plant"
|
||||
#define HUSTR_E1M3 "E1M3: Toxin Refinery"
|
||||
#define HUSTR_E1M4 "E1M4: Command Control"
|
||||
#define HUSTR_E1M5 "E1M5: Phobos Lab"
|
||||
#define HUSTR_E1M6 "E1M6: Central Processing"
|
||||
#define HUSTR_E1M7 "E1M7: Computer Station"
|
||||
#define HUSTR_E1M8 "E1M8: Phobos Anomaly"
|
||||
#define HUSTR_E1M9 "E1M9: Military Base"
|
||||
|
||||
#define HUSTR_E2M1 "E2M1: Deimos Anomaly"
|
||||
#define HUSTR_E2M2 "E2M2: Containment Area"
|
||||
#define HUSTR_E2M3 "E2M3: Refinery"
|
||||
#define HUSTR_E2M4 "E2M4: Deimos Lab"
|
||||
#define HUSTR_E2M5 "E2M5: Command Center"
|
||||
#define HUSTR_E2M6 "E2M6: Halls of the Damned"
|
||||
#define HUSTR_E2M7 "E2M7: Spawning Vats"
|
||||
#define HUSTR_E2M8 "E2M8: Tower of Babel"
|
||||
#define HUSTR_E2M9 "E2M9: Fortress of Mystery"
|
||||
|
||||
#define HUSTR_E3M1 "E3M1: Hell Keep"
|
||||
#define HUSTR_E3M2 "E3M2: Slough of Despair"
|
||||
#define HUSTR_E3M3 "E3M3: Pandemonium"
|
||||
#define HUSTR_E3M4 "E3M4: House of Pain"
|
||||
#define HUSTR_E3M5 "E3M5: Unholy Cathedral"
|
||||
#define HUSTR_E3M6 "E3M6: Mt. Erebus"
|
||||
#define HUSTR_E3M7 "E3M7: Limbo"
|
||||
#define HUSTR_E3M8 "E3M8: Dis"
|
||||
#define HUSTR_E3M9 "E3M9: Warrens"
|
||||
|
||||
#define HUSTR_CHATMACRO1 "I'm ready to kick butt!"
|
||||
#define HUSTR_CHATMACRO2 "I'm OK."
|
||||
#define HUSTR_CHATMACRO3 "I'm not looking too good!"
|
||||
#define HUSTR_CHATMACRO4 "Help!"
|
||||
#define HUSTR_CHATMACRO5 "You suck!"
|
||||
#define HUSTR_CHATMACRO6 "Next time, scumbag..."
|
||||
#define HUSTR_CHATMACRO7 "Come here!"
|
||||
#define HUSTR_CHATMACRO8 "I'll take care of it."
|
||||
#define HUSTR_CHATMACRO9 "Yes"
|
||||
#define HUSTR_CHATMACRO0 "No"
|
||||
|
||||
#define HUSTR_TALKTOSELF1 "You mumble to yourself"
|
||||
#define HUSTR_TALKTOSELF2 "Who's there?"
|
||||
#define HUSTR_TALKTOSELF3 "You scare yourself"
|
||||
#define HUSTR_TALKTOSELF4 "You start to rave"
|
||||
#define HUSTR_TALKTOSELF5 "You've lost it..."
|
||||
|
||||
#define HUSTR_MESSAGESENT "[Message Sent]"
|
||||
|
||||
// The following should NOT be changed unless it seems
|
||||
// just AWFULLY necessary
|
||||
|
||||
#define HUSTR_PLRGREEN "Green: "
|
||||
#define HUSTR_PLRINDIGO "Indigo: "
|
||||
#define HUSTR_PLRBROWN "Brown: "
|
||||
#define HUSTR_PLRRED "Red: "
|
||||
|
||||
#define HUSTR_KEYGREEN 'g'
|
||||
#define HUSTR_KEYINDIGO 'i'
|
||||
#define HUSTR_KEYBROWN 'b'
|
||||
#define HUSTR_KEYRED 'r'
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// AM_map.c
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
#define AMSTR_FOLLOWON "FOLLOW MODE ON"
|
||||
#define AMSTR_FOLLOWOFF "FOLLOW MODE OFF"
|
||||
|
||||
#define AMSTR_GRIDON "Grid ON"
|
||||
#define AMSTR_GRIDOFF "Grid OFF"
|
||||
|
||||
#define AMSTR_MARKEDSPOT "Marked Spot"
|
||||
#define AMSTR_MARKSCLEARED "All Marks Cleared"
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// ST_stuff.c
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
#define STSTR_DQDON "Degreelessness Mode On"
|
||||
#define STSTR_DQDOFF "Degreelessness Mode Off"
|
||||
|
||||
#define STSTR_KFAADDED "Very Happy Ammo Added"
|
||||
|
||||
#define STSTR_NCON "No Clipping Mode ON"
|
||||
#define STSTR_NCOFF "No Clipping Mode OFF"
|
||||
|
||||
#define STSTR_BEHOLD "inVuln, Str, Inviso, Rad, Allmap, or Lite-amp"
|
||||
#define STSTR_BEHOLDX "Power-up Toggled"
|
||||
|
||||
#define STSTR_CHOPPERS "... doesn't suck - GM"
|
||||
#define STSTR_CLEV "Changing Level..."
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// F_finale.c
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
#define E1TEXT "with the destruction of the iron\n"\
|
||||
"liches and their minions, the last\n"\
|
||||
"of the undead are cleared from this\n"\
|
||||
"plane of existence.\n\n"\
|
||||
"those creatures had to come from\n"\
|
||||
"somewhere, though, and you have the\n"\
|
||||
"sneaky suspicion that the fiery\n"\
|
||||
"portal of hell's maw opens onto\n"\
|
||||
"their home dimension.\n\n"\
|
||||
"to make sure that more undead\n"\
|
||||
"(or even worse things) don't come\n"\
|
||||
"through, you'll have to seal hell's\n"\
|
||||
"maw from the other side. of course\n"\
|
||||
"this means you may get stuck in a\n"\
|
||||
"very unfriendly world, but no one\n"\
|
||||
"ever said being a Heretic was easy!"
|
||||
|
||||
#define E2TEXT "the mighty maulotaurs have proved\n"\
|
||||
"to be no match for you, and as\n"\
|
||||
"their steaming corpses slide to the\n"\
|
||||
"ground you feel a sense of grim\n"\
|
||||
"satisfaction that they have been\n"\
|
||||
"destroyed.\n\n"\
|
||||
"the gateways which they guarded\n"\
|
||||
"have opened, revealing what you\n"\
|
||||
"hope is the way home. but as you\n"\
|
||||
"step through, mocking laughter\n"\
|
||||
"rings in your ears.\n\n"\
|
||||
"was some other force controlling\n"\
|
||||
"the maulotaurs? could there be even\n"\
|
||||
"more horrific beings through this\n"\
|
||||
"gate? the sweep of a crystal dome\n"\
|
||||
"overhead where the sky should be is\n"\
|
||||
"certainly not a good sign...."
|
||||
|
||||
#define E3TEXT "the death of d'sparil has loosed\n"\
|
||||
"the magical bonds holding his\n"\
|
||||
"creatures on this plane, their\n"\
|
||||
"dying screams overwhelming his own\n"\
|
||||
"cries of agony.\n\n"\
|
||||
"your oath of vengeance fulfilled,\n"\
|
||||
"you enter the portal to your own\n"\
|
||||
"world, mere moments before the dome\n"\
|
||||
"shatters into a million pieces.\n\n"\
|
||||
"but if d'sparil's power is broken\n"\
|
||||
"forever, why don't you feel safe?\n"\
|
||||
"was it that last shout just before\n"\
|
||||
"his death, the one that sounded\n"\
|
||||
"like a curse? or a summoning? you\n"\
|
||||
"can't really be sure, but it might\n"\
|
||||
"just have been a scream.\n\n"\
|
||||
"then again, what about the other\n"\
|
||||
"serpent riders?"
|
||||
|
||||
#define E4TEXT "you thought you would return to your\n"\
|
||||
"own world after d'sparil died, but\n"\
|
||||
"his final act banished you to his\n"\
|
||||
"own plane. here you entered the\n"\
|
||||
"shattered remnants of lands\n"\
|
||||
"conquered by d'sparil. you defeated\n"\
|
||||
"the last guardians of these lands,\n"\
|
||||
"but now you stand before the gates\n"\
|
||||
"to d'sparil's stronghold. until this\n"\
|
||||
"moment you had no doubts about your\n"\
|
||||
"ability to face anything you might\n"\
|
||||
"encounter, but beyond this portal\n"\
|
||||
"lies the very heart of the evil\n"\
|
||||
"which invaded your world. d'sparil\n"\
|
||||
"might be dead, but the pit where he\n"\
|
||||
"was spawned remains. now you must\n"\
|
||||
"enter that pit in the hopes of\n"\
|
||||
"finding a way out. and somewhere,\n"\
|
||||
"in the darkest corner of d'sparil's\n"\
|
||||
"demesne, his personal bodyguards\n"\
|
||||
"await your arrival ..."
|
||||
|
||||
#define E5TEXT "as the final maulotaur bellows his\n"\
|
||||
"death-agony, you realize that you\n"\
|
||||
"have never come so close to your own\n"\
|
||||
"destruction. not even the fight with\n"\
|
||||
"d'sparil and his disciples had been\n"\
|
||||
"this desperate. grimly you stare at\n"\
|
||||
"the gates which open before you,\n"\
|
||||
"wondering if they lead home, or if\n"\
|
||||
"they open onto some undreamed-of\n"\
|
||||
"horror. you find yourself wondering\n"\
|
||||
"if you have the strength to go on,\n"\
|
||||
"if nothing but death and pain await\n"\
|
||||
"you. but what else can you do, if\n"\
|
||||
"the will to fight is gone? can you\n"\
|
||||
"force yourself to continue in the\n"\
|
||||
"face of such despair? do you have\n"\
|
||||
"the courage? you find, in the end,\n"\
|
||||
"that it is not within you to\n"\
|
||||
"surrender without a fight. eyes\n"\
|
||||
"wide, you go to meet your fate."
|
||||
|
||||
/*
|
||||
#define E1TEXT "Once you beat the big badasses and\n"\
|
||||
"clean out the moon base you're supposed\n"\
|
||||
"to win, aren't you? Aren't you? Where's\n"\
|
||||
"your fat reward and ticket home? What\n"\
|
||||
"the hell is this? It's not supposed to\n"\
|
||||
"end this way!\n"\
|
||||
"\n" \
|
||||
"It stinks like rotten meat, but looks\n"\
|
||||
"like the lost Deimos base. Looks like\n"\
|
||||
"you're stuck on The Shores of Hell.\n"\
|
||||
"The only way out is through.\n"\
|
||||
"\n"\
|
||||
"To continue the DOOM experience, play\n"\
|
||||
"The Shores of Hell and its amazing\n"\
|
||||
"sequel, Inferno!\n"
|
||||
|
||||
#define E2TEXT "You've done it! The hideous cyber-\n"\
|
||||
"demon lord that ruled the lost Deimos\n"\
|
||||
"moon base has been slain and you\n"\
|
||||
"are triumphant! But ... where are\n"\
|
||||
"you? You clamber to the edge of the\n"\
|
||||
"moon and look down to see the awful\n"\
|
||||
"truth.\n" \
|
||||
"\n"\
|
||||
"Deimos floats above Hell itself!\n"\
|
||||
"You've never heard of anyone escaping\n"\
|
||||
"from Hell, but you'll make the bastards\n"\
|
||||
"sorry they ever heard of you! Quickly,\n"\
|
||||
"you rappel down to the surface of\n"\
|
||||
"Hell.\n"\
|
||||
"\n" \
|
||||
"Now, it's on to the final chapter of\n"\
|
||||
"DOOM! -- Inferno."
|
||||
|
||||
#define E3TEXT "The loathsome spiderdemon that\n"\
|
||||
"masterminded the invasion of the moon\n"\
|
||||
"bases and caused so much death has had\n"\
|
||||
"its ass kicked for all time.\n"\
|
||||
"\n"\
|
||||
"A hidden doorway opens and you enter.\n"\
|
||||
"You've proven too tough for Hell to\n"\
|
||||
"contain, and now Hell at last plays\n"\
|
||||
"fair -- for you emerge from the door\n"\
|
||||
"to see the green fields of Earth!\n"\
|
||||
"Home at last.\n" \
|
||||
"\n"\
|
||||
"You wonder what's been happening on\n"\
|
||||
"Earth while you were battling evil\n"\
|
||||
"unleashed. It's good that no Hell-\n"\
|
||||
"spawn could have come through that\n"\
|
||||
"door with you ..."
|
||||
*/
|
406
Heretic Source/DSTRINGS.H
Normal file
406
Heretic Source/DSTRINGS.H
Normal file
|
@ -0,0 +1,406 @@
|
|||
|
||||
// DStrings.h
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// M_menu.c
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
#define PRESSKEY "press a key."
|
||||
#define PRESSYN "press y or n."
|
||||
#define TXT_PAUSED "PAUSED"
|
||||
#define QUITMSG "are you sure you want to\nquit this great game?"
|
||||
#define LOADNET "you can't do load while in a net game!\n\n"PRESSKEY
|
||||
#define QLOADNET "you can't quickload during a netgame!\n\n"PRESSKEY
|
||||
#define QSAVESPOT "you haven't picked a quicksave slot yet!\n\n"PRESSKEY
|
||||
#define SAVEDEAD "you can't save if you aren't playing!\n\n"PRESSKEY
|
||||
#define QSPROMPT "quicksave over your game named\n\n'%s'?\n\n"PRESSYN
|
||||
#define QLPROMPT "do you want to quickload the game named"\
|
||||
"\n\n'%s'?\n\n"PRESSYN
|
||||
#define NEWGAME "you can't start a new game\n"\
|
||||
"while in a network game.\n\n"PRESSKEY
|
||||
#define NIGHTMARE "are you sure? this skill level\n"\
|
||||
"isn't even remotely fair.\n\n"PRESSYN
|
||||
#define SWSTRING "this is the shareware version of doom.\n\n"\
|
||||
"you need to order the entire trilogy.\n\n"PRESSKEY
|
||||
#define MSGOFF "Messages OFF"
|
||||
#define MSGON "Messages ON"
|
||||
#define NETEND "you can't end a netgame!\n\n"PRESSKEY
|
||||
#define ENDGAME "are you sure you want to end the game?\n\n"PRESSYN
|
||||
#define DOSY "(press y to quit to dos.)"
|
||||
#define DETAILHI "High detail"
|
||||
#define DETAILLO "Low detail"
|
||||
#define GAMMALVL0 "Gamma correction OFF"
|
||||
#define GAMMALVL1 "Gamma correction level 1"
|
||||
#define GAMMALVL2 "Gamma correction level 2"
|
||||
#define GAMMALVL3 "Gamma correction level 3"
|
||||
#define GAMMALVL4 "Gamma correction level 4"
|
||||
#define EMPTYSTRING "empty slot"
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// P_inter.c
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
// Keys
|
||||
|
||||
#define TXT_GOTBLUEKEY "BLUE KEY"
|
||||
#define TXT_GOTYELLOWKEY "YELLOW KEY"
|
||||
#define TXT_GOTGREENKEY "GREEN KEY"
|
||||
|
||||
// Artifacts
|
||||
|
||||
#define TXT_ARTIHEALTH "QUARTZ FLASK"
|
||||
#define TXT_ARTIFLY "WINGS OF WRATH"
|
||||
#define TXT_ARTIINVULNERABILITY "RING OF INVINCIBILITY"
|
||||
#define TXT_ARTITOMEOFPOWER "TOME OF POWER"
|
||||
#define TXT_ARTIINVISIBILITY "SHADOWSPHERE"
|
||||
#define TXT_ARTIEGG "MORPH OVUM"
|
||||
#define TXT_ARTISUPERHEALTH "MYSTIC URN"
|
||||
#define TXT_ARTITORCH "TORCH"
|
||||
#define TXT_ARTIFIREBOMB "TIME BOMB OF THE ANCIENTS"
|
||||
#define TXT_ARTITELEPORT "CHAOS DEVICE"
|
||||
|
||||
// Items
|
||||
|
||||
#define TXT_ITEMHEALTH "CRYSTAL VIAL"
|
||||
#define TXT_ITEMBAGOFHOLDING "BAG OF HOLDING"
|
||||
#define TXT_ITEMSHIELD1 "SILVER SHIELD"
|
||||
#define TXT_ITEMSHIELD2 "ENCHANTED SHIELD"
|
||||
#define TXT_ITEMSUPERMAP "MAP SCROLL"
|
||||
|
||||
// Ammo
|
||||
|
||||
#define TXT_AMMOGOLDWAND1 "WAND CRYSTAL"
|
||||
#define TXT_AMMOGOLDWAND2 "CRYSTAL GEODE"
|
||||
#define TXT_AMMOMACE1 "MACE SPHERES"
|
||||
#define TXT_AMMOMACE2 "PILE OF MACE SPHERES"
|
||||
#define TXT_AMMOCROSSBOW1 "ETHEREAL ARROWS"
|
||||
#define TXT_AMMOCROSSBOW2 "QUIVER OF ETHEREAL ARROWS"
|
||||
#define TXT_AMMOBLASTER1 "CLAW ORB"
|
||||
#define TXT_AMMOBLASTER2 "ENERGY ORB"
|
||||
#define TXT_AMMOSKULLROD1 "LESSER RUNES"
|
||||
#define TXT_AMMOSKULLROD2 "GREATER RUNES"
|
||||
#define TXT_AMMOPHOENIXROD1 "FLAME ORB"
|
||||
#define TXT_AMMOPHOENIXROD2 "INFERNO ORB"
|
||||
|
||||
// Weapons
|
||||
|
||||
#define TXT_WPNMACE "FIREMACE"
|
||||
#define TXT_WPNCROSSBOW "ETHEREAL CROSSBOW"
|
||||
#define TXT_WPNBLASTER "DRAGON CLAW"
|
||||
#define TXT_WPNSKULLROD "HELLSTAFF"
|
||||
#define TXT_WPNPHOENIXROD "PHOENIX ROD"
|
||||
#define TXT_WPNGAUNTLETS "GAUNTLETS OF THE NECROMANCER"
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// SB_bar.c
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
#define TXT_CHEATGODON "GOD MODE ON"
|
||||
#define TXT_CHEATGODOFF "GOD MODE OFF"
|
||||
#define TXT_CHEATNOCLIPON "NO CLIPPING ON"
|
||||
#define TXT_CHEATNOCLIPOFF "NO CLIPPING OFF"
|
||||
#define TXT_CHEATWEAPONS "ALL WEAPONS"
|
||||
#define TXT_CHEATFLIGHTON "FLIGHT ON"
|
||||
#define TXT_CHEATFLIGHTOFF "FLIGHT OFF"
|
||||
#define TXT_CHEATPOWERON "POWER ON"
|
||||
#define TXT_CHEATPOWEROFF "POWER OFF"
|
||||
#define TXT_CHEATHEALTH "FULL HEALTH"
|
||||
#define TXT_CHEATKEYS "ALL KEYS"
|
||||
#define TXT_CHEATSOUNDON "SOUND DEBUG ON"
|
||||
#define TXT_CHEATSOUNDOFF "SOUND DEBUG OFF"
|
||||
#define TXT_CHEATTICKERON "TICKER ON"
|
||||
#define TXT_CHEATTICKEROFF "TICKER OFF"
|
||||
#define TXT_CHEATARTIFACTS1 "CHOOSE AN ARTIFACT ( A - J )"
|
||||
#define TXT_CHEATARTIFACTS2 "HOW MANY ( 1 - 9 )"
|
||||
#define TXT_CHEATARTIFACTS3 "YOU GOT IT"
|
||||
#define TXT_CHEATARTIFACTSFAIL "BAD INPUT"
|
||||
#define TXT_CHEATWARP "LEVEL WARP"
|
||||
#define TXT_CHEATSCREENSHOT "SCREENSHOT"
|
||||
#define TXT_CHEATCHICKENON "CHICKEN ON"
|
||||
#define TXT_CHEATCHICKENOFF "CHICKEN OFF"
|
||||
#define TXT_CHEATMASSACRE "MASSACRE"
|
||||
#define TXT_CHEATIDDQD "TRYING TO CHEAT, EH? NOW YOU DIE!"
|
||||
#define TXT_CHEATIDKFA "CHEATER - YOU DON'T DESERVE WEAPONS"
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// P_doors.c
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
#define TXT_NEEDBLUEKEY "YOU NEED A BLUE KEY TO OPEN THIS DOOR"
|
||||
#define TXT_NEEDGREENKEY "YOU NEED A GREEN KEY TO OPEN THIS DOOR"
|
||||
#define TXT_NEEDYELLOWKEY "YOU NEED A YELLOW KEY TO OPEN THIS DOOR"
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// G_game.c
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
#define TXT_GAMESAVED "GAME SAVED"
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// HU_stuff.c
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
#define HUSTR_E1M1 "E1M1: Hangar"
|
||||
#define HUSTR_E1M2 "E1M2: Nuclear Plant"
|
||||
#define HUSTR_E1M3 "E1M3: Toxin Refinery"
|
||||
#define HUSTR_E1M4 "E1M4: Command Control"
|
||||
#define HUSTR_E1M5 "E1M5: Phobos Lab"
|
||||
#define HUSTR_E1M6 "E1M6: Central Processing"
|
||||
#define HUSTR_E1M7 "E1M7: Computer Station"
|
||||
#define HUSTR_E1M8 "E1M8: Phobos Anomaly"
|
||||
#define HUSTR_E1M9 "E1M9: Military Base"
|
||||
|
||||
#define HUSTR_E2M1 "E2M1: Deimos Anomaly"
|
||||
#define HUSTR_E2M2 "E2M2: Containment Area"
|
||||
#define HUSTR_E2M3 "E2M3: Refinery"
|
||||
#define HUSTR_E2M4 "E2M4: Deimos Lab"
|
||||
#define HUSTR_E2M5 "E2M5: Command Center"
|
||||
#define HUSTR_E2M6 "E2M6: Halls of the Damned"
|
||||
#define HUSTR_E2M7 "E2M7: Spawning Vats"
|
||||
#define HUSTR_E2M8 "E2M8: Tower of Babel"
|
||||
#define HUSTR_E2M9 "E2M9: Fortress of Mystery"
|
||||
|
||||
#define HUSTR_E3M1 "E3M1: Hell Keep"
|
||||
#define HUSTR_E3M2 "E3M2: Slough of Despair"
|
||||
#define HUSTR_E3M3 "E3M3: Pandemonium"
|
||||
#define HUSTR_E3M4 "E3M4: House of Pain"
|
||||
#define HUSTR_E3M5 "E3M5: Unholy Cathedral"
|
||||
#define HUSTR_E3M6 "E3M6: Mt. Erebus"
|
||||
#define HUSTR_E3M7 "E3M7: Limbo"
|
||||
#define HUSTR_E3M8 "E3M8: Dis"
|
||||
#define HUSTR_E3M9 "E3M9: Warrens"
|
||||
|
||||
#define HUSTR_CHATMACRO1 "I'm ready to kick butt!"
|
||||
#define HUSTR_CHATMACRO2 "I'm OK."
|
||||
#define HUSTR_CHATMACRO3 "I'm not looking too good!"
|
||||
#define HUSTR_CHATMACRO4 "Help!"
|
||||
#define HUSTR_CHATMACRO5 "You suck!"
|
||||
#define HUSTR_CHATMACRO6 "Next time, scumbag..."
|
||||
#define HUSTR_CHATMACRO7 "Come here!"
|
||||
#define HUSTR_CHATMACRO8 "I'll take care of it."
|
||||
#define HUSTR_CHATMACRO9 "Yes"
|
||||
#define HUSTR_CHATMACRO0 "No"
|
||||
|
||||
#define HUSTR_TALKTOSELF1 "You mumble to yourself"
|
||||
#define HUSTR_TALKTOSELF2 "Who's there?"
|
||||
#define HUSTR_TALKTOSELF3 "You scare yourself"
|
||||
#define HUSTR_TALKTOSELF4 "You start to rave"
|
||||
#define HUSTR_TALKTOSELF5 "You've lost it..."
|
||||
|
||||
#define HUSTR_MESSAGESENT "[Message Sent]"
|
||||
|
||||
// The following should NOT be changed unless it seems
|
||||
// just AWFULLY necessary
|
||||
|
||||
#define HUSTR_PLRGREEN "Green: "
|
||||
#define HUSTR_PLRINDIGO "Indigo: "
|
||||
#define HUSTR_PLRBROWN "Brown: "
|
||||
#define HUSTR_PLRRED "Red: "
|
||||
|
||||
#define HUSTR_KEYGREEN 'g'
|
||||
#define HUSTR_KEYINDIGO 'i'
|
||||
#define HUSTR_KEYBROWN 'b'
|
||||
#define HUSTR_KEYRED 'r'
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// AM_map.c
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
#define AMSTR_FOLLOWON "FOLLOW MODE ON"
|
||||
#define AMSTR_FOLLOWOFF "FOLLOW MODE OFF"
|
||||
|
||||
#define AMSTR_GRIDON "Grid ON"
|
||||
#define AMSTR_GRIDOFF "Grid OFF"
|
||||
|
||||
#define AMSTR_MARKEDSPOT "Marked Spot"
|
||||
#define AMSTR_MARKSCLEARED "All Marks Cleared"
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// ST_stuff.c
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
#define STSTR_DQDON "Degreelessness Mode On"
|
||||
#define STSTR_DQDOFF "Degreelessness Mode Off"
|
||||
|
||||
#define STSTR_KFAADDED "Very Happy Ammo Added"
|
||||
|
||||
#define STSTR_NCON "No Clipping Mode ON"
|
||||
#define STSTR_NCOFF "No Clipping Mode OFF"
|
||||
|
||||
#define STSTR_BEHOLD "inVuln, Str, Inviso, Rad, Allmap, or Lite-amp"
|
||||
#define STSTR_BEHOLDX "Power-up Toggled"
|
||||
|
||||
#define STSTR_CHOPPERS "... doesn't suck - GM"
|
||||
#define STSTR_CLEV "Changing Level..."
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// F_finale.c
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
#define E1TEXT "with the destruction of the iron\n"\
|
||||
"liches and their minions, the last\n"\
|
||||
"of the undead are cleared from this\n"\
|
||||
"plane of existence.\n\n"\
|
||||
"those creatures had to come from\n"\
|
||||
"somewhere, though, and you have the\n"\
|
||||
"sneaky suspicion that the fiery\n"\
|
||||
"portal of hell's maw opens onto\n"\
|
||||
"their home dimension.\n\n"\
|
||||
"to make sure that more undead\n"\
|
||||
"(or even worse things) don't come\n"\
|
||||
"through, you'll have to seal hell's\n"\
|
||||
"maw from the other side. of course\n"\
|
||||
"this means you may get stuck in a\n"\
|
||||
"very unfriendly world, but no one\n"\
|
||||
"ever said being a Heretic was easy!"
|
||||
|
||||
#define E2TEXT "the mighty maulotaurs have proved\n"\
|
||||
"to be no match for you, and as\n"\
|
||||
"their steaming corpses slide to the\n"\
|
||||
"ground you feel a sense of grim\n"\
|
||||
"satisfaction that they have been\n"\
|
||||
"destroyed.\n\n"\
|
||||
"the gateways which they guarded\n"\
|
||||
"have opened, revealing what you\n"\
|
||||
"hope is the way home. but as you\n"\
|
||||
"step through, mocking laughter\n"\
|
||||
"rings in your ears.\n\n"\
|
||||
"was some other force controlling\n"\
|
||||
"the maulotaurs? could there be even\n"\
|
||||
"more horrific beings through this\n"\
|
||||
"gate? the sweep of a crystal dome\n"\
|
||||
"overhead where the sky should be is\n"\
|
||||
"certainly not a good sign...."
|
||||
|
||||
#define E3TEXT "the death of d'sparil has loosed\n"\
|
||||
"the magical bonds holding his\n"\
|
||||
"creatures on this plane, their\n"\
|
||||
"dying screams overwhelming his own\n"\
|
||||
"cries of agony.\n\n"\
|
||||
"your oath of vengeance fulfilled,\n"\
|
||||
"you enter the portal to your own\n"\
|
||||
"world, mere moments before the dome\n"\
|
||||
"shatters into a million pieces.\n\n"\
|
||||
"but if d'sparil's power is broken\n"\
|
||||
"forever, why don't you feel safe?\n"\
|
||||
"was it that last shout just before\n"\
|
||||
"his death, the one that sounded\n"\
|
||||
"like a curse? or a summoning? you\n"\
|
||||
"can't really be sure, but it might\n"\
|
||||
"just have been a scream.\n\n"\
|
||||
"then again, what about the other\n"\
|
||||
"serpent riders?"
|
||||
|
||||
#define E4TEXT "you thought you would return to your\n"\
|
||||
"own world after d'sparil died, but\n"\
|
||||
"his final act banished you to his\n"\
|
||||
"own plane. here you entered the\n"\
|
||||
"shattered remnants of lands\n"\
|
||||
"conquered by d'sparil. you defeated\n"\
|
||||
"the last guardians of these lands,\n"\
|
||||
"but now you stand before the gates\n"\
|
||||
"to d'sparil's stronghold. until this\n"\
|
||||
"moment you had no doubts about your\n"\
|
||||
"ability to face anything you might\n"\
|
||||
"encounter, but beyond this portal\n"\
|
||||
"lies the very heart of the evil\n"\
|
||||
"which invaded your world. d'sparil\n"\
|
||||
"might be dead, but the pit where he\n"\
|
||||
"was spawned remains. now you must\n"\
|
||||
"enter that pit in the hopes of\n"\
|
||||
"finding a way out. and somewhere,\n"\
|
||||
"in the darkest corner of d'sparil's\n"\
|
||||
"demesne, his personal bodyguards\n"\
|
||||
"await your arrival ..."
|
||||
|
||||
#define E5TEXT "as the final maulotaur bellows his\n"\
|
||||
"death-agony, you realize that you\n"\
|
||||
"have never come so close to your own\n"\
|
||||
"destruction. not even the fight with\n"\
|
||||
"d'sparil and his disciples had been\n"\
|
||||
"this desperate. grimly you stare at\n"\
|
||||
"the gates which open before you,\n"\
|
||||
"wondering if they lead home, or if\n"\
|
||||
"they open onto some undreamed-of\n"\
|
||||
"horror. you find yourself wondering\n"\
|
||||
"if you have the strength to go on,\n"\
|
||||
"if nothing but death and pain await\n"\
|
||||
"you. but what else can you do, if\n"\
|
||||
"the will to fight is gone? can you\n"\
|
||||
"force yourself to continue in the\n"\
|
||||
"face of such despair? do you have\n"\
|
||||
"the courage? you find, in the end,\n"\
|
||||
"that it is not within you to\n"\
|
||||
"surrender without a fight. eyes\n"\
|
||||
"wide, you go to meet your fate."
|
||||
|
||||
/*
|
||||
#define E1TEXT "Once you beat the big badasses and\n"\
|
||||
"clean out the moon base you're supposed\n"\
|
||||
"to win, aren't you? Aren't you? Where's\n"\
|
||||
"your fat reward and ticket home? What\n"\
|
||||
"the hell is this? It's not supposed to\n"\
|
||||
"end this way!\n"\
|
||||
"\n" \
|
||||
"It stinks like rotten meat, but looks\n"\
|
||||
"like the lost Deimos base. Looks like\n"\
|
||||
"you're stuck on The Shores of Hell.\n"\
|
||||
"The only way out is through.\n"\
|
||||
"\n"\
|
||||
"To continue the DOOM experience, play\n"\
|
||||
"The Shores of Hell and its amazing\n"\
|
||||
"sequel, Inferno!\n"
|
||||
|
||||
#define E2TEXT "You've done it! The hideous cyber-\n"\
|
||||
"demon lord that ruled the lost Deimos\n"\
|
||||
"moon base has been slain and you\n"\
|
||||
"are triumphant! But ... where are\n"\
|
||||
"you? You clamber to the edge of the\n"\
|
||||
"moon and look down to see the awful\n"\
|
||||
"truth.\n" \
|
||||
"\n"\
|
||||
"Deimos floats above Hell itself!\n"\
|
||||
"You've never heard of anyone escaping\n"\
|
||||
"from Hell, but you'll make the bastards\n"\
|
||||
"sorry they ever heard of you! Quickly,\n"\
|
||||
"you rappel down to the surface of\n"\
|
||||
"Hell.\n"\
|
||||
"\n" \
|
||||
"Now, it's on to the final chapter of\n"\
|
||||
"DOOM! -- Inferno."
|
||||
|
||||
#define E3TEXT "The loathsome spiderdemon that\n"\
|
||||
"masterminded the invasion of the moon\n"\
|
||||
"bases and caused so much death has had\n"\
|
||||
"its ass kicked for all time.\n"\
|
||||
"\n"\
|
||||
"A hidden doorway opens and you enter.\n"\
|
||||
"You've proven too tough for Hell to\n"\
|
||||
"contain, and now Hell at last plays\n"\
|
||||
"fair -- for you emerge from the door\n"\
|
||||
"to see the green fields of Earth!\n"\
|
||||
"Home at last.\n" \
|
||||
"\n"\
|
||||
"You wonder what's been happening on\n"\
|
||||
"Earth while you were battling evil\n"\
|
||||
"unleashed. It's good that no Hell-\n"\
|
||||
"spawn could have come through that\n"\
|
||||
"door with you ..."
|
||||
*/
|
1040
Heretic Source/D_MAIN.C
Normal file
1040
Heretic Source/D_MAIN.C
Normal file
File diff suppressed because it is too large
Load diff
784
Heretic Source/D_NET.C
Normal file
784
Heretic Source/D_NET.C
Normal file
|
@ -0,0 +1,784 @@
|
|||
|
||||
// d_net.c
|
||||
// This version has the fixed ticdup code
|
||||
|
||||
#include "DoomDef.h"
|
||||
|
||||
#define NCMD_EXIT 0x80000000
|
||||
#define NCMD_RETRANSMIT 0x40000000
|
||||
#define NCMD_SETUP 0x20000000
|
||||
#define NCMD_KILL 0x10000000 // kill game
|
||||
#define NCMD_CHECKSUM 0x0fffffff
|
||||
|
||||
|
||||
doomcom_t *doomcom;
|
||||
doomdata_t *netbuffer; // points inside doomcom
|
||||
|
||||
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
NETWORKING
|
||||
|
||||
gametic is the tic about to (or currently being) run
|
||||
maketic is the tick that hasn't had control made for it yet
|
||||
nettics[] has the maketics for all players
|
||||
|
||||
a gametic cannot be run until nettics[] > gametic for all players
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#define RESENDCOUNT 10
|
||||
#define PL_DRONE 0x80 // bit flag in doomdata->player
|
||||
|
||||
ticcmd_t localcmds[BACKUPTICS];
|
||||
|
||||
ticcmd_t netcmds[MAXPLAYERS][BACKUPTICS];
|
||||
int nettics[MAXNETNODES];
|
||||
boolean nodeingame[MAXNETNODES]; // set false as nodes leave game
|
||||
boolean remoteresend[MAXNETNODES]; // set when local needs tics
|
||||
int resendto[MAXNETNODES]; // set when remote needs tics
|
||||
int resendcount[MAXNETNODES];
|
||||
|
||||
int nodeforplayer[MAXPLAYERS];
|
||||
|
||||
int maketic;
|
||||
int lastnettic, skiptics;
|
||||
int ticdup;
|
||||
int maxsend; // BACKUPTICS/(2*ticdup)-1
|
||||
|
||||
void D_ProcessEvents (void);
|
||||
void G_BuildTiccmd (ticcmd_t *cmd);
|
||||
void D_DoAdvanceDemo (void);
|
||||
|
||||
boolean reboundpacket;
|
||||
doomdata_t reboundstore;
|
||||
|
||||
|
||||
int NetbufferSize (void)
|
||||
{
|
||||
return (int)&(((doomdata_t *)0)->cmds[netbuffer->numtics]);
|
||||
}
|
||||
|
||||
unsigned NetbufferChecksum (void)
|
||||
{
|
||||
unsigned c;
|
||||
int i,l;
|
||||
|
||||
c = 0x1234567;
|
||||
|
||||
#if defined(NeXT) || defined(NORMALUNIX)
|
||||
return 0; // byte order problems
|
||||
#endif
|
||||
|
||||
l = (NetbufferSize () - (int)&(((doomdata_t *)0)->retransmitfrom))/4;
|
||||
for (i=0 ; i<l ; i++)
|
||||
c += ((unsigned *)&netbuffer->retransmitfrom)[i] * (i+1);
|
||||
|
||||
return c & NCMD_CHECKSUM;
|
||||
}
|
||||
|
||||
int ExpandTics (int low)
|
||||
{
|
||||
int delta;
|
||||
|
||||
delta = low - (maketic&0xff);
|
||||
|
||||
if (delta >= -64 && delta <= 64)
|
||||
return (maketic&~0xff) + low;
|
||||
if (delta > 64)
|
||||
return (maketic&~0xff) - 256 + low;
|
||||
if (delta < -64)
|
||||
return (maketic&~0xff) + 256 + low;
|
||||
|
||||
I_Error ("ExpandTics: strange value %i at maketic %i",low,maketic);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
|
||||
|
||||
/*
|
||||
==============
|
||||
=
|
||||
= HSendPacket
|
||||
=
|
||||
==============
|
||||
*/
|
||||
|
||||
void HSendPacket (int node, int flags)
|
||||
{
|
||||
netbuffer->checksum = NetbufferChecksum () | flags;
|
||||
|
||||
if (!node)
|
||||
{
|
||||
reboundstore = *netbuffer;
|
||||
reboundpacket = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (demoplayback)
|
||||
return;
|
||||
|
||||
if (!netgame)
|
||||
I_Error ("Tried to transmit to another node");
|
||||
|
||||
doomcom->command = CMD_SEND;
|
||||
doomcom->remotenode = node;
|
||||
doomcom->datalength = NetbufferSize ();
|
||||
|
||||
if (debugfile)
|
||||
{
|
||||
int i;
|
||||
int realretrans;
|
||||
if (netbuffer->checksum & NCMD_RETRANSMIT)
|
||||
realretrans = ExpandTics (netbuffer->retransmitfrom);
|
||||
else
|
||||
realretrans = -1;
|
||||
fprintf (debugfile,"send (%i + %i, R %i) [%i] "
|
||||
,ExpandTics(netbuffer->starttic),netbuffer->numtics, realretrans, doomcom->datalength);
|
||||
for (i=0 ; i<doomcom->datalength ; i++)
|
||||
fprintf (debugfile,"%i ",((byte *)netbuffer)[i]);
|
||||
fprintf (debugfile,"\n");
|
||||
}
|
||||
|
||||
I_NetCmd ();
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
=
|
||||
= HGetPacket
|
||||
=
|
||||
= Returns false if no packet is waiting
|
||||
=
|
||||
==============
|
||||
*/
|
||||
|
||||
boolean HGetPacket (void)
|
||||
{
|
||||
if (reboundpacket)
|
||||
{
|
||||
*netbuffer = reboundstore;
|
||||
doomcom->remotenode = 0;
|
||||
reboundpacket = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!netgame)
|
||||
return false;
|
||||
if (demoplayback)
|
||||
return false;
|
||||
|
||||
doomcom->command = CMD_GET;
|
||||
I_NetCmd ();
|
||||
if (doomcom->remotenode == -1)
|
||||
return false;
|
||||
|
||||
if (doomcom->datalength != NetbufferSize ())
|
||||
{
|
||||
if (debugfile)
|
||||
fprintf (debugfile,"bad packet length %i\n",doomcom->datalength);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (NetbufferChecksum () != (netbuffer->checksum&NCMD_CHECKSUM) )
|
||||
{
|
||||
if (debugfile)
|
||||
fprintf (debugfile,"bad packet checksum\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (debugfile)
|
||||
{
|
||||
int realretrans;
|
||||
int i;
|
||||
|
||||
if (netbuffer->checksum & NCMD_SETUP)
|
||||
fprintf (debugfile,"setup packet\n");
|
||||
else
|
||||
{
|
||||
if (netbuffer->checksum & NCMD_RETRANSMIT)
|
||||
realretrans = ExpandTics (netbuffer->retransmitfrom);
|
||||
else
|
||||
realretrans = -1;
|
||||
fprintf (debugfile,"get %i = (%i + %i, R %i)[%i] ",doomcom->remotenode,
|
||||
ExpandTics(netbuffer->starttic),netbuffer->numtics, realretrans, doomcom->datalength);
|
||||
for (i=0 ; i<doomcom->datalength ; i++)
|
||||
fprintf (debugfile,"%i ",((byte *)netbuffer)[i]);
|
||||
fprintf (debugfile,"\n");
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===================
|
||||
=
|
||||
= GetPackets
|
||||
=
|
||||
===================
|
||||
*/
|
||||
|
||||
char exitmsg[80];
|
||||
|
||||
void GetPackets (void)
|
||||
{
|
||||
int netconsole;
|
||||
int netnode;
|
||||
ticcmd_t *src, *dest;
|
||||
int realend;
|
||||
int realstart;
|
||||
|
||||
while (HGetPacket ())
|
||||
{
|
||||
if (netbuffer->checksum & NCMD_SETUP)
|
||||
continue; // extra setup packet
|
||||
|
||||
netconsole = netbuffer->player & ~PL_DRONE;
|
||||
netnode = doomcom->remotenode;
|
||||
//
|
||||
// to save bytes, only the low byte of tic numbers are sent
|
||||
// Figure out what the rest of the bytes are
|
||||
//
|
||||
realstart = ExpandTics (netbuffer->starttic);
|
||||
realend = (realstart+netbuffer->numtics);
|
||||
|
||||
//
|
||||
// check for exiting the game
|
||||
//
|
||||
if (netbuffer->checksum & NCMD_EXIT)
|
||||
{
|
||||
if (!nodeingame[netnode])
|
||||
continue;
|
||||
nodeingame[netnode] = false;
|
||||
playeringame[netconsole] = false;
|
||||
strcpy (exitmsg, "PLAYER 1 LEFT THE GAME");
|
||||
exitmsg[7] += netconsole;
|
||||
players[consoleplayer].message = exitmsg;
|
||||
// if (demorecording)
|
||||
// G_CheckDemoStatus ();
|
||||
continue;
|
||||
}
|
||||
|
||||
//
|
||||
// check for a remote game kill
|
||||
//
|
||||
if (netbuffer->checksum & NCMD_KILL)
|
||||
I_Error ("Killed by network driver");
|
||||
|
||||
nodeforplayer[netconsole] = netnode;
|
||||
|
||||
//
|
||||
// check for retransmit request
|
||||
//
|
||||
if ( resendcount[netnode] <= 0
|
||||
&& (netbuffer->checksum & NCMD_RETRANSMIT) )
|
||||
{
|
||||
resendto[netnode] = ExpandTics(netbuffer->retransmitfrom);
|
||||
if (debugfile)
|
||||
fprintf (debugfile,"retransmit from %i\n", resendto[netnode]);
|
||||
resendcount[netnode] = RESENDCOUNT;
|
||||
}
|
||||
else
|
||||
resendcount[netnode]--;
|
||||
|
||||
//
|
||||
// check for out of order / duplicated packet
|
||||
//
|
||||
if (realend == nettics[netnode])
|
||||
continue;
|
||||
|
||||
if (realend < nettics[netnode])
|
||||
{
|
||||
if (debugfile)
|
||||
fprintf (debugfile,"out of order packet (%i + %i)\n" ,realstart,netbuffer->numtics);
|
||||
continue;
|
||||
}
|
||||
|
||||
//
|
||||
// check for a missed packet
|
||||
//
|
||||
if (realstart > nettics[netnode])
|
||||
{
|
||||
// stop processing until the other system resends the missed tics
|
||||
if (debugfile)
|
||||
fprintf (debugfile,"missed tics from %i (%i - %i)\n", netnode, realstart, nettics[netnode]);
|
||||
remoteresend[netnode] = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
//
|
||||
// update command store from the packet
|
||||
//
|
||||
{
|
||||
int start;
|
||||
|
||||
remoteresend[netnode] = false;
|
||||
|
||||
start = nettics[netnode] - realstart;
|
||||
src = &netbuffer->cmds[start];
|
||||
|
||||
while (nettics[netnode] < realend)
|
||||
{
|
||||
dest = &netcmds[netconsole][nettics[netnode]%BACKUPTICS];
|
||||
nettics[netnode]++;
|
||||
*dest = *src;
|
||||
src++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
=
|
||||
= NetUpdate
|
||||
=
|
||||
= Builds ticcmds for console player
|
||||
= sends out a packet
|
||||
=============
|
||||
*/
|
||||
|
||||
int gametime;
|
||||
|
||||
void NetUpdate (void)
|
||||
{
|
||||
int nowtime;
|
||||
int newtics;
|
||||
int i,j;
|
||||
int realstart;
|
||||
int gameticdiv;
|
||||
|
||||
//
|
||||
// check time
|
||||
//
|
||||
nowtime = I_GetTime ()/ticdup;
|
||||
newtics = nowtime - gametime;
|
||||
gametime = nowtime;
|
||||
|
||||
if (newtics <= 0) // nothing new to update
|
||||
goto listen;
|
||||
|
||||
if (skiptics <= newtics)
|
||||
{
|
||||
newtics -= skiptics;
|
||||
skiptics = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
skiptics -= newtics;
|
||||
newtics = 0;
|
||||
}
|
||||
|
||||
|
||||
netbuffer->player = consoleplayer;
|
||||
|
||||
//
|
||||
// build new ticcmds for console player
|
||||
//
|
||||
gameticdiv = gametic/ticdup;
|
||||
for (i=0 ; i<newtics ; i++)
|
||||
{
|
||||
I_StartTic ();
|
||||
D_ProcessEvents ();
|
||||
if (maketic - gameticdiv >= BACKUPTICS/2-1)
|
||||
break; // can't hold any more
|
||||
//printf ("mk:%i ",maketic);
|
||||
G_BuildTiccmd (&localcmds[maketic%BACKUPTICS]);
|
||||
maketic++;
|
||||
}
|
||||
|
||||
|
||||
if (singletics)
|
||||
return; // singletic update is syncronous
|
||||
|
||||
//
|
||||
// send the packet to the other nodes
|
||||
//
|
||||
for (i=0 ; i<doomcom->numnodes ; i++)
|
||||
if (nodeingame[i])
|
||||
{
|
||||
netbuffer->starttic = realstart = resendto[i];
|
||||
netbuffer->numtics = maketic - realstart;
|
||||
if (netbuffer->numtics > BACKUPTICS)
|
||||
I_Error ("NetUpdate: netbuffer->numtics > BACKUPTICS");
|
||||
|
||||
resendto[i] = maketic - doomcom->extratics;
|
||||
|
||||
for (j=0 ; j< netbuffer->numtics ; j++)
|
||||
netbuffer->cmds[j] =
|
||||
localcmds[(realstart+j)%BACKUPTICS];
|
||||
|
||||
if (remoteresend[i])
|
||||
{
|
||||
netbuffer->retransmitfrom = nettics[i];
|
||||
HSendPacket (i, NCMD_RETRANSMIT);
|
||||
}
|
||||
else
|
||||
{
|
||||
netbuffer->retransmitfrom = 0;
|
||||
HSendPacket (i, 0);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// listen for other packets
|
||||
//
|
||||
listen:
|
||||
|
||||
GetPackets ();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=====================
|
||||
=
|
||||
= CheckAbort
|
||||
=
|
||||
=====================
|
||||
*/
|
||||
|
||||
void CheckAbort (void)
|
||||
{
|
||||
event_t *ev;
|
||||
int stoptic;
|
||||
|
||||
stoptic = I_GetTime () + 2;
|
||||
while (I_GetTime() < stoptic)
|
||||
I_StartTic ();
|
||||
|
||||
I_StartTic ();
|
||||
for ( ; eventtail != eventhead
|
||||
; eventtail = (++eventtail)&(MAXEVENTS-1) )
|
||||
{
|
||||
ev = &events[eventtail];
|
||||
if (ev->type == ev_keydown && ev->data1 == KEY_ESCAPE)
|
||||
I_Error ("Network game synchronization aborted.");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=====================
|
||||
=
|
||||
= D_ArbitrateNetStart
|
||||
=
|
||||
=====================
|
||||
*/
|
||||
|
||||
void D_ArbitrateNetStart (void)
|
||||
{
|
||||
int i;
|
||||
boolean gotinfo[MAXNETNODES];
|
||||
|
||||
autostart = true;
|
||||
memset (gotinfo,0,sizeof(gotinfo));
|
||||
|
||||
if (doomcom->consoleplayer)
|
||||
{ // listen for setup info from key player
|
||||
// mprintf ("listening for network start info...\n");
|
||||
while (1)
|
||||
{
|
||||
CheckAbort ();
|
||||
if (!HGetPacket ())
|
||||
continue;
|
||||
if (netbuffer->checksum & NCMD_SETUP)
|
||||
{
|
||||
if (netbuffer->player != VERSION)
|
||||
I_Error ("Different DOOM versions cannot play a net game!");
|
||||
startskill = netbuffer->retransmitfrom & 15;
|
||||
deathmatch = (netbuffer->retransmitfrom & 0xc0) >> 6;
|
||||
nomonsters = (netbuffer->retransmitfrom & 0x20) > 0;
|
||||
respawnparm = (netbuffer->retransmitfrom & 0x10) > 0;
|
||||
//startmap = netbuffer->starttic & 0x3f;
|
||||
//startepisode = netbuffer->starttic >> 6;
|
||||
startmap = netbuffer->starttic&15;
|
||||
startepisode = netbuffer->starttic>>4;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // key player, send the setup info
|
||||
// mprintf ("sending network start info...\n");
|
||||
do
|
||||
{
|
||||
CheckAbort ();
|
||||
for (i=0 ; i<doomcom->numnodes ; i++)
|
||||
{
|
||||
netbuffer->retransmitfrom = startskill;
|
||||
if (deathmatch)
|
||||
netbuffer->retransmitfrom |= (deathmatch<<6);
|
||||
if (nomonsters)
|
||||
netbuffer->retransmitfrom |= 0x20;
|
||||
if (respawnparm)
|
||||
netbuffer->retransmitfrom |= 0x10;
|
||||
//netbuffer->starttic = startepisode * 64 + startmap;
|
||||
netbuffer->starttic = (startepisode<<4)+startmap;
|
||||
netbuffer->player = VERSION;
|
||||
netbuffer->numtics = 0;
|
||||
HSendPacket (i, NCMD_SETUP);
|
||||
}
|
||||
|
||||
#if 1
|
||||
for(i = 10 ; i && HGetPacket(); --i)
|
||||
{
|
||||
if((netbuffer->player&0x7f) < MAXNETNODES)
|
||||
gotinfo[netbuffer->player&0x7f] = true;
|
||||
}
|
||||
#else
|
||||
while (HGetPacket ())
|
||||
{
|
||||
gotinfo[netbuffer->player&0x7f] = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
for (i=1 ; i<doomcom->numnodes ; i++)
|
||||
if (!gotinfo[i])
|
||||
break;
|
||||
} while (i < doomcom->numnodes);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
===================
|
||||
=
|
||||
= D_CheckNetGame
|
||||
=
|
||||
= Works out player numbers among the net participants
|
||||
===================
|
||||
*/
|
||||
|
||||
extern int viewangleoffset;
|
||||
|
||||
void D_CheckNetGame (void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0 ; i<MAXNETNODES ; i++)
|
||||
{
|
||||
nodeingame[i] = false;
|
||||
nettics[i] = 0;
|
||||
remoteresend[i] = false; // set when local needs tics
|
||||
resendto[i] = 0; // which tic to start sending
|
||||
}
|
||||
|
||||
// I_InitNetwork sets doomcom and netgame
|
||||
I_InitNetwork ();
|
||||
if (doomcom->id != DOOMCOM_ID)
|
||||
I_Error ("Doomcom buffer invalid!");
|
||||
netbuffer = &doomcom->data;
|
||||
consoleplayer = displayplayer = doomcom->consoleplayer;
|
||||
if (netgame)
|
||||
D_ArbitrateNetStart ();
|
||||
//printf ("startskill %i deathmatch: %i startmap: %i startepisode: %i\n", startskill, deathmatch, startmap, startepisode);
|
||||
|
||||
// read values out of doomcom
|
||||
ticdup = doomcom->ticdup;
|
||||
maxsend = BACKUPTICS/(2*ticdup)-1;
|
||||
if (maxsend<1)
|
||||
maxsend = 1;
|
||||
|
||||
for (i=0 ; i<doomcom->numplayers ; i++)
|
||||
playeringame[i] = true;
|
||||
for (i=0 ; i<doomcom->numnodes ; i++)
|
||||
nodeingame[i] = true;
|
||||
|
||||
//printf ("player %i of %i (%i nodes)\n", consoleplayer+1, doomcom->numplayers, doomcom->numnodes);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
=
|
||||
= D_QuitNetGame
|
||||
=
|
||||
= Called before quitting to leave a net game without hanging the
|
||||
= other players
|
||||
=
|
||||
==================
|
||||
*/
|
||||
|
||||
void D_QuitNetGame (void)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
if (debugfile)
|
||||
fclose (debugfile);
|
||||
|
||||
if (!netgame || !usergame || consoleplayer == -1 || demoplayback)
|
||||
return;
|
||||
|
||||
// send a bunch of packets for security
|
||||
netbuffer->player = consoleplayer;
|
||||
netbuffer->numtics = 0;
|
||||
for (i=0 ; i<4 ; i++)
|
||||
{
|
||||
for (j=1 ; j<doomcom->numnodes ; j++)
|
||||
if (nodeingame[j])
|
||||
HSendPacket (j, NCMD_EXIT);
|
||||
I_WaitVBL (1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
===============
|
||||
=
|
||||
= TryRunTics
|
||||
=
|
||||
===============
|
||||
*/
|
||||
|
||||
int frametics[4], frameon;
|
||||
int frameskip[4];
|
||||
int oldnettics;
|
||||
extern boolean advancedemo;
|
||||
|
||||
void TryRunTics (void)
|
||||
{
|
||||
int i;
|
||||
int lowtic;
|
||||
int entertic;
|
||||
static int oldentertics;
|
||||
int realtics, availabletics;
|
||||
int counts;
|
||||
int numplaying;
|
||||
|
||||
//
|
||||
// get real tics
|
||||
//
|
||||
entertic = I_GetTime ()/ticdup;
|
||||
realtics = entertic - oldentertics;
|
||||
oldentertics = entertic;
|
||||
|
||||
//
|
||||
// get available tics
|
||||
//
|
||||
NetUpdate ();
|
||||
|
||||
lowtic = MAXINT;
|
||||
numplaying = 0;
|
||||
for (i=0 ; i<doomcom->numnodes ; i++)
|
||||
if (nodeingame[i])
|
||||
{
|
||||
numplaying++;
|
||||
if (nettics[i] < lowtic)
|
||||
lowtic = nettics[i];
|
||||
}
|
||||
availabletics = lowtic - gametic/ticdup;
|
||||
|
||||
|
||||
//
|
||||
// decide how many tics to run
|
||||
//
|
||||
if (realtics < availabletics-1)
|
||||
counts = realtics+1;
|
||||
else if (realtics < availabletics)
|
||||
counts = realtics;
|
||||
else
|
||||
counts = availabletics;
|
||||
if (counts < 1)
|
||||
counts = 1;
|
||||
|
||||
frameon++;
|
||||
|
||||
if (debugfile)
|
||||
fprintf (debugfile,"=======real: %i avail: %i game: %i\n",realtics, availabletics,counts);
|
||||
|
||||
if (!demoplayback)
|
||||
{
|
||||
//=============================================================================
|
||||
//
|
||||
// ideally nettics[0] should be 1 - 3 tics above lowtic
|
||||
// if we are consistantly slower, speed up time
|
||||
//
|
||||
for (i=0 ; i<MAXPLAYERS ; i++)
|
||||
if (playeringame[i])
|
||||
break;
|
||||
if (consoleplayer == i)
|
||||
{ // the key player does not adapt
|
||||
}
|
||||
else
|
||||
{
|
||||
if (nettics[0] <= nettics[nodeforplayer[i]])
|
||||
{
|
||||
gametime--;
|
||||
// printf ("-");
|
||||
}
|
||||
frameskip[frameon&3] = (oldnettics > nettics[nodeforplayer[i]]);
|
||||
oldnettics = nettics[0];
|
||||
if (frameskip[0] && frameskip[1] && frameskip[2] && frameskip[3])
|
||||
{
|
||||
skiptics = 1;
|
||||
// printf ("+");
|
||||
}
|
||||
}
|
||||
//=============================================================================
|
||||
} // demoplayback
|
||||
|
||||
//
|
||||
// wait for new tics if needed
|
||||
//
|
||||
while (lowtic < gametic/ticdup + counts)
|
||||
{
|
||||
|
||||
NetUpdate ();
|
||||
lowtic = MAXINT;
|
||||
|
||||
for (i=0 ; i<doomcom->numnodes ; i++)
|
||||
if (nodeingame[i] && nettics[i] < lowtic)
|
||||
lowtic = nettics[i];
|
||||
|
||||
if (lowtic < gametic/ticdup)
|
||||
I_Error ("TryRunTics: lowtic < gametic");
|
||||
|
||||
// don't stay in here forever -- give the menu a chance to work
|
||||
if (I_GetTime ()/ticdup - entertic >= 20)
|
||||
{
|
||||
MN_Ticker ();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// run the count * ticdup dics
|
||||
//
|
||||
while (counts--)
|
||||
{
|
||||
for (i=0 ; i<ticdup ; i++)
|
||||
{
|
||||
if (gametic/ticdup > lowtic)
|
||||
I_Error ("gametic>lowtic");
|
||||
if (advancedemo)
|
||||
D_DoAdvanceDemo ();
|
||||
MN_Ticker ();
|
||||
G_Ticker ();
|
||||
gametic++;
|
||||
//
|
||||
// modify command for duplicated tics
|
||||
//
|
||||
if (i != ticdup-1)
|
||||
{
|
||||
ticcmd_t *cmd;
|
||||
int buf;
|
||||
int j;
|
||||
|
||||
buf = (gametic/ticdup)%BACKUPTICS;
|
||||
for (j=0 ; j<MAXPLAYERS ; j++)
|
||||
{
|
||||
cmd = &netcmds[j][buf];
|
||||
cmd->chatchar = 0;
|
||||
if (cmd->buttons & BT_SPECIAL)
|
||||
cmd->buttons = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
NetUpdate (); // check for new console commands
|
||||
}
|
||||
}
|
797
Heretic Source/D_NETBAK.C
Normal file
797
Heretic Source/D_NETBAK.C
Normal file
|
@ -0,0 +1,797 @@
|
|||
|
||||
// I_pcnet.m
|
||||
//
|
||||
// Modified 12-21-94 by Chris Rhinehart for use with multiple ticdups
|
||||
// actually, it wasn't modified, but rather we are currently using this
|
||||
// older version of D_NET.C, since the new one doesn't seem to work with
|
||||
// ticdup set to greater than one.
|
||||
|
||||
#include "DoomDef.h"
|
||||
#include "P_local.h"
|
||||
#include "soundst.h"
|
||||
|
||||
#define NCMD_EXIT 0x80000000
|
||||
#define NCMD_RETRANSMIT 0x40000000
|
||||
#define NCMD_SETUP 0x20000000
|
||||
#define NCMD_CHECKSUM 0x0fffffff
|
||||
|
||||
/*
|
||||
if more space needs to be crunched out of the protocol...
|
||||
|
||||
1 drone
|
||||
2 player
|
||||
8 tic
|
||||
5 numtics
|
||||
|
||||
#define NCMD_EXIT 0x80000000
|
||||
#define NCMD_RETRANSMIT 0x40000000 // a retransmit will have 0 tics
|
||||
#define NCMD_DRONE 0x20000000
|
||||
#define NCMD_PLAYER 0x18000000
|
||||
#define NCMD_PLAYERSHIFT 27
|
||||
#define NCMD_TIC 0x00ff0000
|
||||
#define NCMD_TICSHIFT 16
|
||||
#define NCMD_NUMTICS 0x0000ff00
|
||||
#define NCMD_NUMTICSSHIFT 8
|
||||
#define NCMD_CHECKSUM 0x000000ff
|
||||
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
doomcom_t *doomcom;
|
||||
doomdata_t *netbuffer; // points inside doomcom
|
||||
|
||||
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
NETWORKING
|
||||
|
||||
gametic is the tic about to (or currently being) run
|
||||
maketic is the tick that hasn't had control made for it yet
|
||||
nettics[] has the maketics for all players
|
||||
|
||||
a gametic cannot be run until nettics[] > gametic for all players
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#define RESENDCOUNT 10
|
||||
#define PL_DRONE 0x80 // bit flag in doomdata->player
|
||||
|
||||
ticcmd_t localcmds[BACKUPTICS];
|
||||
|
||||
ticcmd_t netcmds[MAXPLAYERS][BACKUPTICS];
|
||||
int nettics[MAXNETNODES];
|
||||
boolean nodeingame[MAXNETNODES]; // set false as nodes leave game
|
||||
boolean remoteresend[MAXNETNODES]; // set when local needs tics
|
||||
int resendto[MAXNETNODES]; // set when remote needs tics
|
||||
int resendcount[MAXNETNODES];
|
||||
|
||||
int nodeforplayer[MAXPLAYERS];
|
||||
|
||||
int gametime;
|
||||
int maketic;
|
||||
int lastnettic, skiptics;
|
||||
int ticdup;
|
||||
|
||||
void D_ProcessEvents (void);
|
||||
void G_BuildTiccmd (ticcmd_t *cmd);
|
||||
void D_DoAdvanceDemo (void);
|
||||
|
||||
boolean reboundpacket;
|
||||
doomdata_t reboundstore;
|
||||
|
||||
|
||||
int NetbufferSize (void)
|
||||
{
|
||||
return (int)&(((doomdata_t *)0)->cmds[netbuffer->numtics]);
|
||||
}
|
||||
|
||||
unsigned NetbufferChecksum (void)
|
||||
{
|
||||
unsigned c;
|
||||
int i,l;
|
||||
|
||||
c = 0x1234567;
|
||||
|
||||
l = (NetbufferSize () - (int)&(((doomdata_t *)0)->retransmitfrom))/4;
|
||||
for (i=0 ; i<l ; i++)
|
||||
c += ((unsigned *)&netbuffer->retransmitfrom)[i] * (i+1);
|
||||
|
||||
return c & NCMD_CHECKSUM;
|
||||
}
|
||||
|
||||
int ExpandTics (int low)
|
||||
{
|
||||
int delta;
|
||||
|
||||
delta = low - (maketic&0xff);
|
||||
|
||||
if (delta >= -64 && delta <= 64)
|
||||
return (maketic&~0xff) + low;
|
||||
if (delta > 64)
|
||||
return (maketic&~0xff) - 256 + low;
|
||||
if (delta < -64)
|
||||
return (maketic&~0xff) + 256 + low;
|
||||
|
||||
I_Error ("ExpandTics: strange value %i at maketic %i",low,maketic);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
|
||||
|
||||
/*
|
||||
==============
|
||||
=
|
||||
= HSendPacket
|
||||
=
|
||||
==============
|
||||
*/
|
||||
|
||||
void HSendPacket (int node, int flags)
|
||||
{
|
||||
netbuffer->checksum = NetbufferChecksum () | flags;
|
||||
|
||||
if (!node)
|
||||
{
|
||||
reboundstore = *netbuffer;
|
||||
reboundpacket = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!netgame)
|
||||
I_Error ("Tried to transmit to another node");
|
||||
|
||||
doomcom->command = CMD_SEND;
|
||||
doomcom->remotenode = node;
|
||||
doomcom->datalength = NetbufferSize ();
|
||||
|
||||
if (debugfile)
|
||||
{
|
||||
int i;
|
||||
int realretrans;
|
||||
if (netbuffer->checksum & NCMD_RETRANSMIT)
|
||||
realretrans = ExpandTics (netbuffer->retransmitfrom);
|
||||
else
|
||||
realretrans = -1;
|
||||
fprintf (debugfile,"send (%i + %i, R %i) [%i] "
|
||||
,ExpandTics(netbuffer->starttic),netbuffer->numtics, realretrans, doomcom->datalength);
|
||||
for (i=0 ; i<doomcom->datalength ; i++)
|
||||
fprintf (debugfile,"%i ",((byte *)netbuffer)[i]);
|
||||
fprintf (debugfile,"\n");
|
||||
}
|
||||
|
||||
I_NetCmd ();
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
=
|
||||
= HGetPacket
|
||||
=
|
||||
= Returns false if no packet is waiting
|
||||
=
|
||||
==============
|
||||
*/
|
||||
|
||||
boolean HGetPacket (void)
|
||||
{
|
||||
if (reboundpacket)
|
||||
{
|
||||
*netbuffer = reboundstore;
|
||||
doomcom->remotenode = 0;
|
||||
reboundpacket = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!netgame)
|
||||
return false;
|
||||
|
||||
doomcom->command = CMD_GET;
|
||||
I_NetCmd ();
|
||||
if (doomcom->remotenode == -1)
|
||||
return false;
|
||||
|
||||
if (doomcom->datalength != NetbufferSize ())
|
||||
{
|
||||
if (debugfile)
|
||||
fprintf (debugfile,"bad packet length %i\n",doomcom->datalength);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (NetbufferChecksum () != (netbuffer->checksum&NCMD_CHECKSUM) )
|
||||
{
|
||||
if (debugfile)
|
||||
fprintf (debugfile,"bad packet checksum\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (debugfile)
|
||||
{
|
||||
int realretrans;
|
||||
int i;
|
||||
|
||||
if (netbuffer->checksum & NCMD_SETUP)
|
||||
fprintf (debugfile,"setup packet\n");
|
||||
else
|
||||
{
|
||||
if (netbuffer->checksum & NCMD_RETRANSMIT)
|
||||
realretrans = ExpandTics (netbuffer->retransmitfrom);
|
||||
else
|
||||
realretrans = -1;
|
||||
fprintf (debugfile,"get %i = (%i + %i, R %i)[%i] ",doomcom->remotenode,
|
||||
ExpandTics(netbuffer->starttic),netbuffer->numtics, realretrans, doomcom->datalength);
|
||||
for (i=0 ; i<doomcom->datalength ; i++)
|
||||
fprintf (debugfile,"%i ",((byte *)netbuffer)[i]);
|
||||
fprintf (debugfile,"\n");
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===================
|
||||
=
|
||||
= GetPackets
|
||||
=
|
||||
===================
|
||||
*/
|
||||
|
||||
char exitmsg[80];
|
||||
|
||||
void GetPackets (void)
|
||||
{
|
||||
int netconsole;
|
||||
int netnode;
|
||||
int netdrone;
|
||||
int j;
|
||||
ticcmd_t *src, *dest;
|
||||
int dupedstart, dupedend;
|
||||
int skiptics;
|
||||
int realstart;
|
||||
|
||||
while (HGetPacket ())
|
||||
{
|
||||
if (netbuffer->checksum & NCMD_SETUP)
|
||||
continue; // extra setup packet
|
||||
|
||||
netdrone = netbuffer->player & PL_DRONE;
|
||||
netconsole = netbuffer->player & ~PL_DRONE;
|
||||
netnode = doomcom->remotenode;
|
||||
//
|
||||
// to save bytes, only the low byte of tic numbers are sent
|
||||
// Figure out what the rest of the bytes are
|
||||
//
|
||||
realstart = ExpandTics (netbuffer->starttic);
|
||||
dupedstart = realstart*doomcom->ticdup;
|
||||
dupedend = (realstart+netbuffer->numtics)*doomcom->ticdup;
|
||||
|
||||
//
|
||||
// check for exiting the game
|
||||
//
|
||||
if (netbuffer->checksum & NCMD_EXIT)
|
||||
{
|
||||
if (!nodeingame[netnode])
|
||||
continue;
|
||||
nodeingame[netnode] = false;
|
||||
if (!netdrone)
|
||||
{
|
||||
playeringame[netconsole] = false;
|
||||
strcpy (exitmsg, "PLAYER 1 HAS LEFT THE GAME");
|
||||
exitmsg[7] += netconsole;
|
||||
P_SetMessage(&players[consoleplayer], exitmsg, true);
|
||||
UpdateState |= I_MESSAGES;
|
||||
S_StartSound(NULL, sfx_chat);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
//
|
||||
// drone packets are just notifications
|
||||
//
|
||||
if (netdrone)
|
||||
{
|
||||
nettics[netnode] = dupedend;
|
||||
continue;
|
||||
}
|
||||
|
||||
nodeforplayer[netconsole] = netnode;
|
||||
|
||||
//
|
||||
// check for retransmit request
|
||||
//
|
||||
if ( resendcount[netnode] <= 0
|
||||
&& (netbuffer->checksum & NCMD_RETRANSMIT) )
|
||||
{
|
||||
resendto[netnode] = ExpandTics(netbuffer->retransmitfrom);
|
||||
if (debugfile)
|
||||
fprintf (debugfile,"retransmit from %i\n", resendto[netnode]);
|
||||
resendcount[netnode] = RESENDCOUNT;
|
||||
}
|
||||
else
|
||||
resendcount[netnode]--;
|
||||
|
||||
//
|
||||
// check for out of order / duplicated packet
|
||||
//
|
||||
if (dupedend == nettics[netnode])
|
||||
continue;
|
||||
|
||||
if (dupedend < nettics[netnode])
|
||||
{
|
||||
if (debugfile)
|
||||
fprintf (debugfile,"out of order packet (%i + %i)\n" ,realstart,netbuffer->numtics);
|
||||
continue;
|
||||
}
|
||||
|
||||
//
|
||||
// check for a missed packet
|
||||
//
|
||||
if (dupedstart > nettics[netnode])
|
||||
{
|
||||
// stop processing until the other system resends the missed tics
|
||||
if (debugfile)
|
||||
fprintf (debugfile,"missed tics from %i (%i - %i)\n", netnode, dupedstart, nettics[netnode]);
|
||||
remoteresend[netnode] = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
//
|
||||
// update command store from the packet
|
||||
//
|
||||
remoteresend[netnode] = false;
|
||||
|
||||
skiptics = nettics[netnode]/doomcom->ticdup - realstart;
|
||||
src = &netbuffer->cmds[skiptics];
|
||||
|
||||
while (nettics[netnode] < dupedend)
|
||||
{
|
||||
for (j=0 ; j<doomcom->ticdup ; j++)
|
||||
{
|
||||
dest = &netcmds[netconsole][nettics[netnode]%BACKUPTICS];
|
||||
nettics[netnode]++;
|
||||
*dest = *src;
|
||||
src->chatchar = 0;
|
||||
if (src->buttons & BT_SPECIAL)
|
||||
src->buttons = 0;
|
||||
}
|
||||
src++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
=
|
||||
= NetUpdate
|
||||
=
|
||||
= Builds ticcmds for console player
|
||||
= sends out a packet
|
||||
=============
|
||||
*/
|
||||
|
||||
void NetUpdate (void)
|
||||
{
|
||||
int nowtime;
|
||||
int newtics;
|
||||
int i,j;
|
||||
int gameticdiv;
|
||||
int realstart;
|
||||
|
||||
if (singletics)
|
||||
return; // singletic update is syncronous
|
||||
|
||||
//
|
||||
// check time
|
||||
//
|
||||
nowtime = I_GetTime ()/doomcom->ticdup;
|
||||
newtics = nowtime - gametime;
|
||||
gametime = nowtime;
|
||||
if (newtics <= 0) // nothing new to update
|
||||
goto listen;
|
||||
|
||||
if (skiptics <= newtics)
|
||||
{
|
||||
newtics -= skiptics;
|
||||
skiptics = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
skiptics -= newtics;
|
||||
newtics = 0;
|
||||
}
|
||||
|
||||
|
||||
netbuffer->player = consoleplayer;
|
||||
if (doomcom->drone)
|
||||
netbuffer->player |= PL_DRONE;
|
||||
|
||||
//
|
||||
// drone packets
|
||||
//
|
||||
if (doomcom->drone)
|
||||
{
|
||||
I_StartTic ();
|
||||
D_ProcessEvents ();
|
||||
goto sendit;
|
||||
}
|
||||
|
||||
//
|
||||
// build new ticcmds for console player
|
||||
//
|
||||
gameticdiv = (gametic+doomcom->ticdup-1)/doomcom->ticdup;
|
||||
for (i=0 ; i<newtics ; i++)
|
||||
{
|
||||
I_StartTic ();
|
||||
D_ProcessEvents ();
|
||||
if (maketic - gameticdiv >= BACKUPTICS/2 /* /doomcom->ticdup */- 1)
|
||||
{
|
||||
newtics = i;
|
||||
break; // can't hold any more
|
||||
}
|
||||
//printf ("mk:%i ",maketic);
|
||||
G_BuildTiccmd (&localcmds[maketic%BACKUPTICS]);
|
||||
maketic++;
|
||||
}
|
||||
|
||||
//
|
||||
// send the packet to the other nodes
|
||||
//
|
||||
sendit:
|
||||
for (i=0 ; i<doomcom->numnodes ; i++)
|
||||
if (nodeingame[i])
|
||||
{
|
||||
if (doomcom->drone)
|
||||
{
|
||||
netbuffer->starttic = realstart = maketic + BACKUPTICS/2;
|
||||
netbuffer->numtics = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
netbuffer->starttic = realstart = resendto[i];
|
||||
netbuffer->numtics = maketic - realstart;
|
||||
resendto[i] = maketic - doomcom->extratics;
|
||||
}
|
||||
|
||||
if (netbuffer->numtics > BACKUPTICS)
|
||||
I_Error ("NetUpdate: netbuffer->numtics > BACKUPTICS");
|
||||
|
||||
for (j=0 ; j< netbuffer->numtics ; j++)
|
||||
netbuffer->cmds[j] =
|
||||
localcmds[(realstart+j)%BACKUPTICS];
|
||||
|
||||
if (remoteresend[i])
|
||||
{
|
||||
netbuffer->retransmitfrom = nettics[i]/doomcom->ticdup;
|
||||
HSendPacket (i, NCMD_RETRANSMIT);
|
||||
}
|
||||
else
|
||||
{
|
||||
netbuffer->retransmitfrom = 0;
|
||||
HSendPacket (i, 0);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// listen for other packets
|
||||
//
|
||||
listen:
|
||||
|
||||
GetPackets ();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=====================
|
||||
=
|
||||
= CheckAbort
|
||||
=
|
||||
=====================
|
||||
*/
|
||||
|
||||
void CheckAbort (void)
|
||||
{
|
||||
event_t *ev;
|
||||
|
||||
I_WaitVBL(2);
|
||||
|
||||
I_StartTic ();
|
||||
for ( ; eventtail != eventhead
|
||||
; eventtail = (++eventtail)&(MAXEVENTS-1) )
|
||||
{
|
||||
ev = &events[eventtail];
|
||||
if (ev->type == ev_keydown && ev->data1 == KEY_ESCAPE)
|
||||
I_Error ("Network game synchronization aborted.");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=====================
|
||||
=
|
||||
= D_ArbitrateNetStart
|
||||
=
|
||||
=====================
|
||||
*/
|
||||
|
||||
void D_ArbitrateNetStart (void)
|
||||
{
|
||||
int i;
|
||||
boolean gotinfo[MAXNETNODES];
|
||||
|
||||
autostart = true;
|
||||
memset (gotinfo,0,sizeof(gotinfo));
|
||||
|
||||
if (doomcom->consoleplayer)
|
||||
{ // listen for setup info from key player
|
||||
//printf ("listening for network start info...\n");
|
||||
while (1)
|
||||
{
|
||||
CheckAbort ();
|
||||
if (!HGetPacket ())
|
||||
continue;
|
||||
if (netbuffer->checksum & NCMD_SETUP)
|
||||
{
|
||||
if (netbuffer->player != VERSION)
|
||||
I_Error ("Different HERETIC versions cannot play a net game!");
|
||||
startskill = netbuffer->retransmitfrom & 15;
|
||||
deathmatch = (netbuffer->retransmitfrom & 0x80) > 0;
|
||||
startmap = netbuffer->starttic & 15;
|
||||
startepisode = netbuffer->starttic >> 4;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // key player, send the setup info
|
||||
// printf ("sending network start info...\n");
|
||||
do
|
||||
{
|
||||
CheckAbort ();
|
||||
for (i=0 ; i<doomcom->numnodes ; i++)
|
||||
{
|
||||
netbuffer->retransmitfrom = startskill;
|
||||
if (deathmatch)
|
||||
netbuffer->retransmitfrom |= 0x80;
|
||||
netbuffer->starttic = startepisode * 16 + startmap;
|
||||
netbuffer->player = VERSION;
|
||||
netbuffer->numtics = 0;
|
||||
HSendPacket (i, NCMD_SETUP);
|
||||
}
|
||||
|
||||
while (HGetPacket ())
|
||||
{
|
||||
//printf ("got packet\n");
|
||||
gotinfo[netbuffer->player&0x7f] = true;
|
||||
}
|
||||
|
||||
for (i=1 ; i<doomcom->numnodes ; i++)
|
||||
if (!gotinfo[i])
|
||||
break;
|
||||
} while (i < doomcom->numnodes);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
===================
|
||||
=
|
||||
= D_CheckNetGame
|
||||
=
|
||||
= Works out player numbers among the net participants
|
||||
===================
|
||||
*/
|
||||
|
||||
extern int viewangleoffset;
|
||||
|
||||
void D_CheckNetGame (void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0 ; i<MAXNETNODES ; i++)
|
||||
{
|
||||
nodeingame[i] = false;
|
||||
nettics[i] = 0;
|
||||
remoteresend[i] = false; // set when local needs tics
|
||||
resendto[i] = 0; // which tic to start sending
|
||||
}
|
||||
|
||||
// I_InitNetwork sets doomcom and netgame
|
||||
I_InitNetwork ();
|
||||
if (doomcom->id != DOOMCOM_ID)
|
||||
I_Error ("Doomcom buffer invalid!");
|
||||
netbuffer = &doomcom->data;
|
||||
consoleplayer = displayplayer = doomcom->consoleplayer;
|
||||
if (netgame)
|
||||
D_ArbitrateNetStart ();
|
||||
//printf ("startskill %i deathmatch: %i startmap: %i startepisode: %i\n", startskill, deathmatch, startmap, startepisode);
|
||||
|
||||
// read values out of doomcom
|
||||
ticdup = doomcom->ticdup;
|
||||
|
||||
for (i=0 ; i<doomcom->numplayers ; i++)
|
||||
playeringame[i] = true;
|
||||
for (i=0 ; i<doomcom->numnodes ; i++)
|
||||
nodeingame[i] = true;
|
||||
|
||||
//printf ("player %i of %i (%i nodes)\n", consoleplayer+1, doomcom->numplayers, doomcom->numnodes);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
=
|
||||
= D_QuitNetGame
|
||||
=
|
||||
= Called before quitting to leave a net game without hanging the
|
||||
= other players
|
||||
=
|
||||
==================
|
||||
*/
|
||||
|
||||
void D_QuitNetGame (void)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
if (debugfile)
|
||||
fclose (debugfile);
|
||||
|
||||
if (!netgame || !usergame || consoleplayer == -1)
|
||||
return;
|
||||
|
||||
// send a bunch of packets for security
|
||||
netbuffer->player = consoleplayer;
|
||||
if (doomcom->drone)
|
||||
netbuffer->player |= PL_DRONE;
|
||||
netbuffer->numtics = 0;
|
||||
for (i=0 ; i<4 ; i++)
|
||||
{
|
||||
for (j=1 ; j<doomcom->numnodes ; j++)
|
||||
if (nodeingame[j])
|
||||
HSendPacket (j, NCMD_EXIT);
|
||||
I_WaitVBL (1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
===============
|
||||
=
|
||||
= TryRunTics
|
||||
=
|
||||
===============
|
||||
*/
|
||||
|
||||
int frametics[4], frameon;
|
||||
int frameskip[4];
|
||||
int oldnettics;
|
||||
extern boolean advancedemo;
|
||||
|
||||
void TryRunTics (void)
|
||||
{
|
||||
int i;
|
||||
int lowtic, nextlowest;
|
||||
int entertic;
|
||||
int static oldentertics;
|
||||
int realtics, availabletics;
|
||||
int counts;
|
||||
int numplaying;
|
||||
|
||||
//
|
||||
// get real tics
|
||||
//
|
||||
entertic = I_GetTime ();
|
||||
realtics = entertic - oldentertics;
|
||||
oldentertics = entertic;
|
||||
|
||||
//
|
||||
// get available tics
|
||||
//
|
||||
NetUpdate ();
|
||||
|
||||
lowtic = nextlowest = MAXINT;
|
||||
numplaying = 0;
|
||||
for (i=0 ; i<doomcom->numnodes ; i++)
|
||||
if (nodeingame[i])
|
||||
{
|
||||
numplaying++;
|
||||
if (nettics[i] < lowtic)
|
||||
{
|
||||
nextlowest = lowtic;
|
||||
lowtic = nettics[i];
|
||||
}
|
||||
else if (nettics[i] < nextlowest)
|
||||
nextlowest = nettics[i];
|
||||
}
|
||||
availabletics = lowtic - gametic;
|
||||
|
||||
|
||||
//
|
||||
// decide how many tics to run
|
||||
//
|
||||
if (realtics < availabletics-1)
|
||||
counts = realtics+1;
|
||||
else if (realtics < availabletics)
|
||||
counts = realtics;
|
||||
else
|
||||
counts = availabletics;
|
||||
if (counts < 1)
|
||||
counts = 1;
|
||||
|
||||
frameon++;
|
||||
|
||||
if (debugfile)
|
||||
fprintf (debugfile,"=======real: %i avail: %i game: %i\n",realtics, availabletics,counts);
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// ideally nettics[0] should be 1 - 3 tics above lowtic
|
||||
// if we are consistantly slower, speed up time
|
||||
// drones should never hold up the other players
|
||||
//
|
||||
for (i=0 ; i<MAXPLAYERS ; i++)
|
||||
if (playeringame[i])
|
||||
break;
|
||||
if (consoleplayer == i)
|
||||
{ // the key player does not adapt
|
||||
}
|
||||
else
|
||||
{
|
||||
if (nettics[0] <= nettics[nodeforplayer[i]])
|
||||
{
|
||||
gametime--;
|
||||
// printf ("-");
|
||||
}
|
||||
frameskip[frameon&3] = (oldnettics > nettics[nodeforplayer[i]]);
|
||||
oldnettics = nettics[0];
|
||||
if (frameskip[0] && frameskip[1] && frameskip[2] && frameskip[3])
|
||||
{
|
||||
skiptics = 1;
|
||||
// printf ("+");
|
||||
}
|
||||
}
|
||||
//=============================================================================
|
||||
|
||||
//
|
||||
// wait for new tics if needed
|
||||
//
|
||||
while (lowtic < gametic + counts)
|
||||
{
|
||||
|
||||
NetUpdate ();
|
||||
lowtic = MAXINT;
|
||||
|
||||
for (i=0 ; i<doomcom->numnodes ; i++)
|
||||
if (nodeingame[i] && nettics[i] < lowtic)
|
||||
lowtic = nettics[i];
|
||||
|
||||
if (lowtic < gametic)
|
||||
I_Error ("TryRunTics: lowtic < gametic");
|
||||
|
||||
// don't stay in here forever -- give the menu a chance to work
|
||||
if (I_GetTime () - entertic >= 20)
|
||||
{
|
||||
MN_Ticker ();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// run the tics
|
||||
//
|
||||
while (counts--)
|
||||
{
|
||||
if (advancedemo)
|
||||
D_DoAdvanceDemo ();
|
||||
MN_Ticker ();
|
||||
G_Ticker ();
|
||||
NetUpdate (); // check for new console commands
|
||||
gametic++;
|
||||
}
|
||||
}
|
452
Heretic Source/F_FINALE.C
Normal file
452
Heretic Source/F_FINALE.C
Normal file
|
@ -0,0 +1,452 @@
|
|||
// F_finale.c
|
||||
|
||||
#include "DoomDef.h"
|
||||
#include "soundst.h"
|
||||
#include <ctype.h>
|
||||
|
||||
int finalestage; // 0 = text, 1 = art screen
|
||||
int finalecount;
|
||||
|
||||
#define TEXTSPEED 3
|
||||
#define TEXTWAIT 250
|
||||
|
||||
char *e1text = E1TEXT;
|
||||
char *e2text = E2TEXT;
|
||||
char *e3text = E3TEXT;
|
||||
char *e4text = E4TEXT;
|
||||
char *e5text = E5TEXT;
|
||||
char *finaletext;
|
||||
char *finaleflat;
|
||||
|
||||
int FontABaseLump;
|
||||
|
||||
extern boolean automapactive;
|
||||
extern boolean viewactive;
|
||||
|
||||
extern void D_StartTitle(void);
|
||||
|
||||
/*
|
||||
=======================
|
||||
=
|
||||
= F_StartFinale
|
||||
=
|
||||
=======================
|
||||
*/
|
||||
|
||||
void F_StartFinale (void)
|
||||
{
|
||||
gameaction = ga_nothing;
|
||||
gamestate = GS_FINALE;
|
||||
viewactive = false;
|
||||
automapactive = false;
|
||||
players[consoleplayer].messageTics = 1;
|
||||
players[consoleplayer].message = NULL;
|
||||
|
||||
switch(gameepisode)
|
||||
{
|
||||
case 1:
|
||||
finaleflat = "FLOOR25";
|
||||
finaletext = e1text;
|
||||
break;
|
||||
case 2:
|
||||
finaleflat = "FLATHUH1";
|
||||
finaletext = e2text;
|
||||
break;
|
||||
case 3:
|
||||
finaleflat = "FLTWAWA2";
|
||||
finaletext = e3text;
|
||||
break;
|
||||
case 4:
|
||||
finaleflat = "FLOOR28";
|
||||
finaletext = e4text;
|
||||
break;
|
||||
case 5:
|
||||
finaleflat = "FLOOR08";
|
||||
finaletext = e5text;
|
||||
break;
|
||||
}
|
||||
|
||||
finalestage = 0;
|
||||
finalecount = 0;
|
||||
FontABaseLump = W_GetNumForName("FONTA_S")+1;
|
||||
|
||||
// S_ChangeMusic(mus_victor, true);
|
||||
S_StartSong(mus_cptd, true);
|
||||
}
|
||||
|
||||
|
||||
|
||||
boolean F_Responder (event_t *event)
|
||||
{
|
||||
if(event->type != ev_keydown)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if(finalestage == 1 && gameepisode == 2)
|
||||
{ // we're showing the water pic, make any key kick to demo mode
|
||||
finalestage++;
|
||||
memset((byte *)0xa0000, 0, SCREENWIDTH*SCREENHEIGHT);
|
||||
memset(screen, 0, SCREENWIDTH*SCREENHEIGHT);
|
||||
I_SetPalette(W_CacheLumpName("PLAYPAL", PU_CACHE));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=======================
|
||||
=
|
||||
= F_Ticker
|
||||
=
|
||||
=======================
|
||||
*/
|
||||
|
||||
void F_Ticker (void)
|
||||
{
|
||||
finalecount++;
|
||||
if (!finalestage && finalecount>strlen (finaletext)*TEXTSPEED + TEXTWAIT)
|
||||
{
|
||||
finalecount = 0;
|
||||
if(!finalestage)
|
||||
{
|
||||
finalestage = 1;
|
||||
}
|
||||
|
||||
// wipegamestate = -1; // force a wipe
|
||||
/*
|
||||
if (gameepisode == 3)
|
||||
S_StartMusic (mus_bunny);
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=======================
|
||||
=
|
||||
= F_TextWrite
|
||||
=
|
||||
=======================
|
||||
*/
|
||||
|
||||
//#include "HU_stuff.h"
|
||||
//extern patch_t *hu_font[HU_FONTSIZE];
|
||||
|
||||
void F_TextWrite (void)
|
||||
{
|
||||
byte *src, *dest;
|
||||
int x,y;
|
||||
int count;
|
||||
char *ch;
|
||||
int c;
|
||||
int cx, cy;
|
||||
patch_t *w;
|
||||
|
||||
//
|
||||
// erase the entire screen to a tiled background
|
||||
//
|
||||
src = W_CacheLumpName(finaleflat, PU_CACHE);
|
||||
dest = screen;
|
||||
for (y=0 ; y<SCREENHEIGHT ; y++)
|
||||
{
|
||||
for (x=0 ; x<SCREENWIDTH/64 ; x++)
|
||||
{
|
||||
memcpy (dest, src+((y&63)<<6), 64);
|
||||
dest += 64;
|
||||
}
|
||||
if (SCREENWIDTH&63)
|
||||
{
|
||||
memcpy (dest, src+((y&63)<<6), SCREENWIDTH&63);
|
||||
dest += (SCREENWIDTH&63);
|
||||
}
|
||||
}
|
||||
|
||||
// V_MarkRect (0, 0, SCREENWIDTH, SCREENHEIGHT);
|
||||
|
||||
//
|
||||
// draw some of the text onto the screen
|
||||
//
|
||||
cx = 20;
|
||||
cy = 5;
|
||||
ch = finaletext;
|
||||
|
||||
count = (finalecount - 10)/TEXTSPEED;
|
||||
if (count < 0)
|
||||
count = 0;
|
||||
for ( ; count ; count-- )
|
||||
{
|
||||
c = *ch++;
|
||||
if (!c)
|
||||
break;
|
||||
if (c == '\n')
|
||||
{
|
||||
cx = 20;
|
||||
cy += 9;
|
||||
continue;
|
||||
}
|
||||
|
||||
c = toupper(c);
|
||||
if (c < 33)
|
||||
{
|
||||
cx += 5;
|
||||
continue;
|
||||
}
|
||||
|
||||
w = W_CacheLumpNum(FontABaseLump+c-33, PU_CACHE);
|
||||
if (cx+w->width > SCREENWIDTH)
|
||||
break;
|
||||
V_DrawPatch(cx, cy, w);
|
||||
cx += w->width;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
/*
|
||||
=======================
|
||||
=
|
||||
= F_Cast
|
||||
=
|
||||
=======================
|
||||
*/
|
||||
|
||||
void F_Cast (void)
|
||||
{
|
||||
byte *src, *dest;
|
||||
int x,y,w;
|
||||
int count;
|
||||
char *ch;
|
||||
int c;
|
||||
int cx, cy;
|
||||
|
||||
//
|
||||
// erase the entire screen to a tiled background
|
||||
//
|
||||
src = W_CacheLumpName ( "FWATER1" , PU_CACHE);
|
||||
dest = screen;
|
||||
|
||||
for (y=0 ; y<SCREENHEIGHT ; y++)
|
||||
{
|
||||
for (x=0 ; x<SCREENWIDTH/64 ; x++)
|
||||
{
|
||||
memcpy (dest, src+((y&63)<<6), 64);
|
||||
dest += 64;
|
||||
}
|
||||
if (SCREENWIDTH&63)
|
||||
{
|
||||
memcpy (dest, src+((y&63)<<6), SCREENWIDTH&63);
|
||||
dest += (SCREENWIDTH&63);
|
||||
}
|
||||
}
|
||||
|
||||
V_MarkRect (0, 0, SCREENWIDTH, SCREENHEIGHT);
|
||||
|
||||
V_DrawPatch (105,21,0, W_CacheLumpName ( "
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void F_DrawPatchCol (int x, patch_t *patch, int col)
|
||||
{
|
||||
column_t *column;
|
||||
byte *source, *dest, *desttop;
|
||||
int count;
|
||||
|
||||
column = (column_t *)((byte *)patch + LONG(patch->columnofs[col]));
|
||||
desttop = screen+x;
|
||||
|
||||
// step through the posts in a column
|
||||
|
||||
while (column->topdelta != 0xff )
|
||||
{
|
||||
source = (byte *)column + 3;
|
||||
dest = desttop + column->topdelta*SCREENWIDTH;
|
||||
count = column->length;
|
||||
|
||||
while (count--)
|
||||
{
|
||||
*dest = *source++;
|
||||
dest += SCREENWIDTH;
|
||||
}
|
||||
column = (column_t *)( (byte *)column + column->length+ 4 );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
=
|
||||
= F_DemonScroll
|
||||
=
|
||||
==================
|
||||
*/
|
||||
|
||||
void F_DemonScroll(void)
|
||||
{
|
||||
byte *p1, *p2;
|
||||
static int yval = 0;
|
||||
static int nextscroll = 0;
|
||||
|
||||
if(finalecount < nextscroll)
|
||||
{
|
||||
return;
|
||||
}
|
||||
p1 = W_CacheLumpName("FINAL1", PU_LEVEL);
|
||||
p2 = W_CacheLumpName("FINAL2", PU_LEVEL);
|
||||
if(finalecount < 70)
|
||||
{
|
||||
memcpy(screen, p1, SCREENHEIGHT*SCREENWIDTH);
|
||||
nextscroll = finalecount;
|
||||
return;
|
||||
}
|
||||
if(yval < 64000)
|
||||
{
|
||||
memcpy(screen, p2+SCREENHEIGHT*SCREENWIDTH-yval, yval);
|
||||
memcpy(screen+yval, p1, SCREENHEIGHT*SCREENWIDTH-yval);
|
||||
yval += SCREENWIDTH;
|
||||
nextscroll = finalecount+3;
|
||||
}
|
||||
else
|
||||
{ //else, we'll just sit here and wait, for now
|
||||
memcpy(screen, p2, SCREENWIDTH*SCREENHEIGHT);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
=
|
||||
= F_DrawUnderwater
|
||||
=
|
||||
==================
|
||||
*/
|
||||
|
||||
void F_DrawUnderwater(void)
|
||||
{
|
||||
static boolean underwawa;
|
||||
extern boolean MenuActive;
|
||||
extern boolean askforquit;
|
||||
|
||||
switch(finalestage)
|
||||
{
|
||||
case 1:
|
||||
if(!underwawa)
|
||||
{
|
||||
underwawa = true;
|
||||
memset((byte *)0xa0000, 0, SCREENWIDTH*SCREENHEIGHT);
|
||||
I_SetPalette(W_CacheLumpName("E2PAL", PU_CACHE));
|
||||
memcpy(screen, W_CacheLumpName("E2END", PU_CACHE),
|
||||
SCREENWIDTH*SCREENHEIGHT);
|
||||
}
|
||||
paused = false;
|
||||
MenuActive = false;
|
||||
askforquit = false;
|
||||
|
||||
break;
|
||||
case 2:
|
||||
memcpy(screen, W_CacheLumpName("TITLE", PU_CACHE),
|
||||
SCREENWIDTH*SCREENHEIGHT);
|
||||
//D_StartTitle(); // go to intro/demo mode.
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
/*
|
||||
==================
|
||||
=
|
||||
= F_BunnyScroll
|
||||
=
|
||||
==================
|
||||
*/
|
||||
|
||||
void F_BunnyScroll (void)
|
||||
{
|
||||
int scrolled, x;
|
||||
patch_t *p1, *p2;
|
||||
char name[10];
|
||||
int stage;
|
||||
static int laststage;
|
||||
|
||||
p1 = W_CacheLumpName ("PFUB2", PU_LEVEL);
|
||||
p2 = W_CacheLumpName ("PFUB1", PU_LEVEL);
|
||||
|
||||
V_MarkRect (0, 0, SCREENWIDTH, SCREENHEIGHT);
|
||||
|
||||
scrolled = 320 - (finalecount-230)/2;
|
||||
if (scrolled > 320)
|
||||
scrolled = 320;
|
||||
if (scrolled < 0)
|
||||
scrolled = 0;
|
||||
|
||||
for ( x=0 ; x<SCREENWIDTH ; x++)
|
||||
{
|
||||
if (x+scrolled < 320)
|
||||
F_DrawPatchCol (x, p1, x+scrolled);
|
||||
else
|
||||
F_DrawPatchCol (x, p2, x+scrolled - 320);
|
||||
}
|
||||
|
||||
if (finalecount < 1130)
|
||||
return;
|
||||
if (finalecount < 1180)
|
||||
{
|
||||
V_DrawPatch ((SCREENWIDTH-13*8)/2, (SCREENHEIGHT-8*8)/2,0, W_CacheLumpName ("END0",PU_CACHE));
|
||||
laststage = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
stage = (finalecount-1180) / 5;
|
||||
if (stage > 6)
|
||||
stage = 6;
|
||||
if (stage > laststage)
|
||||
{
|
||||
S_StartSound (NULL, sfx_pistol);
|
||||
laststage = stage;
|
||||
}
|
||||
|
||||
sprintf (name,"END%i",stage);
|
||||
V_DrawPatch ((SCREENWIDTH-13*8)/2, (SCREENHEIGHT-8*8)/2, W_CacheLumpName (name,PU_CACHE));
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
=======================
|
||||
=
|
||||
= F_Drawer
|
||||
=
|
||||
=======================
|
||||
*/
|
||||
|
||||
void F_Drawer(void)
|
||||
{
|
||||
UpdateState |= I_FULLSCRN;
|
||||
if (!finalestage)
|
||||
F_TextWrite ();
|
||||
else
|
||||
{
|
||||
switch (gameepisode)
|
||||
{
|
||||
case 1:
|
||||
if(shareware)
|
||||
{
|
||||
V_DrawRawScreen(W_CacheLumpName("ORDER", PU_CACHE));
|
||||
}
|
||||
else
|
||||
{
|
||||
V_DrawRawScreen(W_CacheLumpName("CREDIT", PU_CACHE));
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
F_DrawUnderwater();
|
||||
break;
|
||||
case 3:
|
||||
F_DemonScroll();
|
||||
break;
|
||||
case 4: // Just show credits screen for extended episodes
|
||||
case 5:
|
||||
V_DrawRawScreen(W_CacheLumpName("CREDIT", PU_CACHE));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
1952
Heretic Source/G_GAME.C
Normal file
1952
Heretic Source/G_GAME.C
Normal file
File diff suppressed because it is too large
Load diff
1819
Heretic Source/G_OLD.C
Normal file
1819
Heretic Source/G_OLD.C
Normal file
File diff suppressed because it is too large
Load diff
124
Heretic Source/H.BAT
Normal file
124
Heretic Source/H.BAT
Normal file
|
@ -0,0 +1,124 @@
|
|||
@echo off
|
||||
|
||||
if "%1x"=="x" goto badargs
|
||||
if "%2x"=="x" goto badargs
|
||||
|
||||
set hticargs=-noartiskip -warp %1 %2
|
||||
set hticwads=-file
|
||||
set hticnplay=
|
||||
|
||||
:parseloop
|
||||
if "%3x"=="x" goto doneparse
|
||||
if "%3"=="m" goto nomonsters
|
||||
if "%3"=="M" goto nomonsters
|
||||
if "%3"=="s1" goto skill1
|
||||
if "%3"=="S1" goto skill1
|
||||
if "%3"=="s2" goto skill2
|
||||
if "%3"=="S2" goto skill2
|
||||
if "%3"=="s3" goto skill3
|
||||
if "%3"=="S3" goto skill3
|
||||
if "%3"=="s4" goto skill4
|
||||
if "%3"=="S4" goto skill4
|
||||
if "%3"=="s5" goto skill5
|
||||
if "%3"=="S5" goto skill5
|
||||
if "%3"=="n1" goto nplay1
|
||||
if "%3"=="N1" goto nplay1
|
||||
if "%3"=="n2" goto nplay2
|
||||
if "%3"=="N2" goto nplay2
|
||||
if "%3"=="n3" goto nplay3
|
||||
if "%3"=="N3" goto nplay3
|
||||
if "%3"=="n4" goto nplay4
|
||||
if "%3"=="N4" goto nplay4
|
||||
if "%3"=="p" goto altport
|
||||
if "%3"=="P" goto altport
|
||||
goto addwad
|
||||
|
||||
:nomonsters
|
||||
set hticargs=%hticargs% -nomonsters
|
||||
shift
|
||||
goto parseloop
|
||||
|
||||
:skill1
|
||||
set hticargs=%hticargs% -skill 1
|
||||
shift
|
||||
goto parseloop
|
||||
|
||||
:skill2
|
||||
set hticargs=%hticargs% -skill 2
|
||||
shift
|
||||
goto parseloop
|
||||
|
||||
:skill3
|
||||
set hticargs=%hticargs% -skill 3
|
||||
shift
|
||||
goto parseloop
|
||||
|
||||
:skill4
|
||||
set hticargs=%hticargs% -skill 4
|
||||
shift
|
||||
goto parseloop
|
||||
|
||||
:skill5
|
||||
set hticargs=%hticargs% -skill 5
|
||||
shift
|
||||
goto parseloop
|
||||
|
||||
:nplay1
|
||||
set hticnplay=1
|
||||
shift
|
||||
goto parseloop
|
||||
|
||||
:nplay2
|
||||
set hticnplay=2
|
||||
shift
|
||||
goto parseloop
|
||||
|
||||
:nplay3
|
||||
set hticnplay=3
|
||||
shift
|
||||
goto parseloop
|
||||
|
||||
:nplay4
|
||||
set hticnplay=4
|
||||
shift
|
||||
goto parseloop
|
||||
|
||||
:altport
|
||||
set hticargs=%hticargs% -port 3
|
||||
shift
|
||||
goto parseloop
|
||||
|
||||
:addwad
|
||||
set hticwads=%hticwads% %3.wad
|
||||
shift
|
||||
goto parseloop
|
||||
|
||||
:badargs
|
||||
echo Usage: H episode map [s?] [m] [n?] [p] [wadfile [wadfile ...] ]
|
||||
echo.
|
||||
echo [s?] = skill (1-5)
|
||||
echo [m] = no monsters
|
||||
echo [n?] = net play (1-4)
|
||||
echo [p] = use alternate port setting
|
||||
echo [wadfile] = add external wadfile (.WAD is implicit)
|
||||
echo.
|
||||
goto end
|
||||
|
||||
:doneparse
|
||||
if"%hticwads%"=="-file" goto startgame
|
||||
set hticargs=%hticargs% %hticwads%
|
||||
:startgame
|
||||
if"%hticnplay%x"=="x" goto normalplay
|
||||
echo -nodes %hticnplay% -deathmatch %hticargs%
|
||||
ipxsetup -nodes %hticnplay% -deathmatch %hticargs%
|
||||
goto end
|
||||
|
||||
:normalplay
|
||||
echo %hticargs%
|
||||
heretic %hticargs%
|
||||
goto end
|
||||
|
||||
:end
|
||||
set hticargs=
|
||||
set hticwads=
|
||||
set hticnplay=
|
BIN
Heretic Source/HDEMO1.LMP
Normal file
BIN
Heretic Source/HDEMO1.LMP
Normal file
Binary file not shown.
BIN
Heretic Source/HDEMO2.LMP
Normal file
BIN
Heretic Source/HDEMO2.LMP
Normal file
Binary file not shown.
BIN
Heretic Source/HDEMO3.LMP
Normal file
BIN
Heretic Source/HDEMO3.LMP
Normal file
Binary file not shown.
93
Heretic Source/HERETIC.LNT
Normal file
93
Heretic Source/HERETIC.LNT
Normal file
|
@ -0,0 +1,93 @@
|
|||
|
||||
/* Lint file for Heretic project */
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// OPTIONS
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
// Use integer model for enumerations
|
||||
//
|
||||
+fie
|
||||
|
||||
// Allow ignoring return values
|
||||
//
|
||||
-e534
|
||||
|
||||
// Allow repeated include files
|
||||
//
|
||||
-e537
|
||||
|
||||
// Allow shifting signed quantities
|
||||
//
|
||||
-e701
|
||||
-e702
|
||||
|
||||
// Allow more than 127 enumeration constants (ANSI limit)
|
||||
//
|
||||
-"esym(793,enumeration constants)"
|
||||
|
||||
// Don't complain about global macros that are not referenced
|
||||
//
|
||||
-e755
|
||||
|
||||
// Don't complain about global enumeration constants that are not
|
||||
// referenced
|
||||
//
|
||||
-e769
|
||||
|
||||
// Don't complain about external symbols that could be made static
|
||||
//
|
||||
-e765
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// FILES
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
i_ibm.c
|
||||
i_cyber.c
|
||||
i_sound.c
|
||||
am_map.c
|
||||
ct_chat.c
|
||||
d_main.c
|
||||
d_net.c
|
||||
g_game.c
|
||||
f_finale.c
|
||||
info.c
|
||||
in_lude.c
|
||||
mn_menu.c
|
||||
m_misc.c
|
||||
p_ceilng.c
|
||||
p_doors.c
|
||||
p_enemy.c
|
||||
p_floor.c
|
||||
p_inter.c
|
||||
p_lights.c
|
||||
p_map.c
|
||||
p_maputl.c
|
||||
p_mobj.c
|
||||
p_plats.c
|
||||
p_pspr.c
|
||||
p_setup.c
|
||||
p_sight.c
|
||||
p_spec.c
|
||||
p_switch.c
|
||||
p_telept.c
|
||||
p_tick.c
|
||||
p_user.c
|
||||
r_bsp.c
|
||||
r_data.c
|
||||
r_draw.c
|
||||
r_main.c
|
||||
r_plane.c
|
||||
r_segs.c
|
||||
r_things.c
|
||||
sb_bar.c
|
||||
sounds.c
|
||||
tables.c
|
||||
v_video.c
|
||||
w_wad.c
|
||||
z_zone.c
|
5677
Heretic Source/INFO.C
Normal file
5677
Heretic Source/INFO.C
Normal file
File diff suppressed because it is too large
Load diff
1550
Heretic Source/INFO.H
Normal file
1550
Heretic Source/INFO.H
Normal file
File diff suppressed because it is too large
Load diff
1007
Heretic Source/IN_LUDE.C
Normal file
1007
Heretic Source/IN_LUDE.C
Normal file
File diff suppressed because it is too large
Load diff
997
Heretic Source/IN_LUDE.OLD
Normal file
997
Heretic Source/IN_LUDE.OLD
Normal file
|
@ -0,0 +1,997 @@
|
|||
/*
|
||||
========================
|
||||
=
|
||||
= IN_lude.c
|
||||
=
|
||||
========================
|
||||
*/
|
||||
|
||||
#include "DoomDef.h"
|
||||
#include "soundst.h"
|
||||
|
||||
typedef enum
|
||||
{
|
||||
SINGLE,
|
||||
COOPERATIVE,
|
||||
DEATHMATCH
|
||||
} gametype_t;
|
||||
|
||||
// Public functions
|
||||
|
||||
void IN_Start(void);
|
||||
void IN_Ticker(void);
|
||||
void IN_Drawer(void);
|
||||
|
||||
boolean intermission;
|
||||
|
||||
// Private functions
|
||||
|
||||
void IN_WaitStop(void);
|
||||
void IN_Stop(void);
|
||||
void IN_LoadPics(void);
|
||||
void IN_UnloadPics(void);
|
||||
void IN_CheckForSkip(void);
|
||||
void IN_InitStats(void);
|
||||
void IN_InitDeathmatchStats(void);
|
||||
void IN_InitNetgameStats(void);
|
||||
void IN_DrawOldLevel(void);
|
||||
void IN_DrawYAH(void);
|
||||
void IN_DrawStatBack(void);
|
||||
void IN_DrawSingleStats(void);
|
||||
void IN_DrawCoopStats(void);
|
||||
void IN_DrawDMStats(void);
|
||||
void IN_DrawNumber(int val, int x, int y, int digits);
|
||||
void IN_DrawTime(int x, int y, int h, int m, int s);
|
||||
void IN_DrTextB(char *text, int x, int y);
|
||||
|
||||
static boolean skipintermission;
|
||||
static int interstate = 0;
|
||||
static int intertime = -1;
|
||||
static int oldintertime = 0;
|
||||
static gametype_t gametype;
|
||||
|
||||
static int cnt;
|
||||
|
||||
static int time;
|
||||
static int hours;
|
||||
static int minutes;
|
||||
static int seconds;
|
||||
|
||||
static int slaughterboy; // in DM, the player with the most kills
|
||||
|
||||
static int killPercent[MAXPLAYERS];
|
||||
static int bonusPercent[MAXPLAYERS];
|
||||
static int secretPercent[MAXPLAYERS];
|
||||
|
||||
static patch_t *patchINTERPIC;
|
||||
static patch_t *patchBEENTHERE;
|
||||
static patch_t *patchGOINGTHERE;
|
||||
static patch_t *FontBNumbers[10];
|
||||
static patch_t *FontBNegative;
|
||||
static patch_t *FontBSlash;
|
||||
static patch_t *FontBPercent;
|
||||
|
||||
static int FontBLump;
|
||||
static int FontBLumpBase;
|
||||
static int patchFaceOkayBase;
|
||||
static int patchFaceDeadBase;
|
||||
|
||||
static signed int totalFrags[MAXPLAYERS];
|
||||
static fixed_t dSlideX[MAXPLAYERS];
|
||||
static fixed_t dSlideY[MAXPLAYERS];
|
||||
|
||||
static char *KillersText[] = { "K", "I", "L", "L", "E", "R", "S" };
|
||||
|
||||
extern char *LevelNames[];
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int x;
|
||||
int y;
|
||||
} yahpt_t;
|
||||
|
||||
static yahpt_t YAHspot[3][9] =
|
||||
{
|
||||
{
|
||||
{ 172, 78 },
|
||||
{ 86, 90 },
|
||||
{ 73, 66 },
|
||||
{ 159, 95 },
|
||||
{ 148, 126 },
|
||||
{ 132, 54 },
|
||||
{ 131, 74 },
|
||||
{ 208, 138 },
|
||||
{ 52, 101 }
|
||||
},
|
||||
{
|
||||
{ 218, 57 },
|
||||
{ 137, 81 },
|
||||
{ 155, 124 },
|
||||
{ 171, 68 },
|
||||
{ 250, 86 },
|
||||
{ 136, 98 },
|
||||
{ 203, 90 },
|
||||
{ 220, 140 },
|
||||
{ 279, 106 }
|
||||
},
|
||||
{
|
||||
{ 86, 99 },
|
||||
{ 124, 103 },
|
||||
{ 154, 79 },
|
||||
{ 202, 83 },
|
||||
{ 178, 59 },
|
||||
{ 142, 58 },
|
||||
{ 219, 66 },
|
||||
{ 247, 57 },
|
||||
{ 107, 80 }
|
||||
}
|
||||
};
|
||||
|
||||
//========================================================================
|
||||
//
|
||||
// IN_Start
|
||||
//
|
||||
//========================================================================
|
||||
|
||||
extern void AM_Stop (void);
|
||||
|
||||
void IN_Start(void)
|
||||
{
|
||||
I_SetPalette(W_CacheLumpName("PLAYPAL", PU_CACHE));
|
||||
IN_LoadPics();
|
||||
IN_InitStats();
|
||||
intermission = true;
|
||||
interstate = -1;
|
||||
skipintermission = false;
|
||||
intertime = 0;
|
||||
oldintertime = 0;
|
||||
AM_Stop();
|
||||
S_StartSong(mus_intr, true);
|
||||
}
|
||||
|
||||
//========================================================================
|
||||
//
|
||||
// IN_WaitStop
|
||||
//
|
||||
//========================================================================
|
||||
|
||||
void IN_WaitStop(void)
|
||||
{
|
||||
if(!--cnt)
|
||||
{
|
||||
IN_Stop();
|
||||
G_WorldDone();
|
||||
}
|
||||
}
|
||||
|
||||
//========================================================================
|
||||
//
|
||||
// IN_Stop
|
||||
//
|
||||
//========================================================================
|
||||
|
||||
void IN_Stop(void)
|
||||
{
|
||||
intermission = false;
|
||||
IN_UnloadPics();
|
||||
SB_state = -1;
|
||||
BorderNeedRefresh = true;
|
||||
}
|
||||
|
||||
//========================================================================
|
||||
//
|
||||
// IN_InitStats
|
||||
//
|
||||
// Initializes the stats for single player mode
|
||||
//========================================================================
|
||||
|
||||
void IN_InitStats(void)
|
||||
{
|
||||
int i;
|
||||
int j;
|
||||
signed int slaughterfrags;
|
||||
int posnum;
|
||||
int slaughtercount;
|
||||
int playercount;
|
||||
|
||||
|
||||
if(!netgame)
|
||||
{
|
||||
gametype = SINGLE;
|
||||
time = leveltime/35;
|
||||
hours = time/3600;
|
||||
time -= hours*3600;
|
||||
minutes = time/60;
|
||||
time -= minutes*60;
|
||||
seconds = time;
|
||||
}
|
||||
else if(netgame && !deathmatch)
|
||||
{
|
||||
gametype = COOPERATIVE;
|
||||
memset(killPercent, 0, MAXPLAYERS*sizeof(int));
|
||||
memset(bonusPercent, 0, MAXPLAYERS*sizeof(int));
|
||||
memset(secretPercent, 0, MAXPLAYERS*sizeof(int));
|
||||
for(i=0; i<MAXPLAYERS; i++)
|
||||
{
|
||||
if(playeringame[i])
|
||||
{
|
||||
if(totalkills)
|
||||
{
|
||||
killPercent[i] = players[i].killcount*100/totalkills;
|
||||
}
|
||||
if(totalitems)
|
||||
{
|
||||
bonusPercent[i] = players[i].itemcount*100/totalitems;
|
||||
}
|
||||
if(totalsecret)
|
||||
{
|
||||
secretPercent[i] = players[i].secretcount*100/totalsecret;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
gametype = DEATHMATCH;
|
||||
slaughterboy = 0;
|
||||
slaughterfrags = -9999;
|
||||
posnum = 0;
|
||||
playercount = 0;
|
||||
slaughtercount = 0;
|
||||
for(i=0; i<MAXPLAYERS; i++)
|
||||
{
|
||||
totalFrags[i] = 0;
|
||||
if(playeringame[i])
|
||||
{
|
||||
playercount++;
|
||||
for(j=0; j<MAXPLAYERS; j++)
|
||||
{
|
||||
if(playeringame[j])
|
||||
{
|
||||
totalFrags[i] += players[i].frags[j];
|
||||
}
|
||||
}
|
||||
dSlideX[i] = (43*posnum*FRACUNIT)/20;
|
||||
dSlideY[i] = (36*posnum*FRACUNIT)/20;
|
||||
posnum++;
|
||||
}
|
||||
if(totalFrags[i] > slaughterfrags)
|
||||
{
|
||||
slaughterboy = 1<<i;
|
||||
slaughterfrags = totalFrags[i];
|
||||
slaughtercount = 1;
|
||||
}
|
||||
else if(totalFrags[i] == slaughterfrags)
|
||||
{
|
||||
slaughterboy |= 1<<i;
|
||||
slaughtercount++;
|
||||
}
|
||||
}
|
||||
if(playercount == slaughtercount)
|
||||
{ // don't do the slaughter stuff if everyone is equal
|
||||
slaughterboy = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//========================================================================
|
||||
//
|
||||
// IN_LoadPics
|
||||
//
|
||||
//========================================================================
|
||||
|
||||
void IN_LoadPics(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
switch(gameepisode)
|
||||
{
|
||||
case 1:
|
||||
patchINTERPIC = W_CacheLumpName("MAPE1", PU_STATIC);
|
||||
break;
|
||||
case 2:
|
||||
patchINTERPIC = W_CacheLumpName("MAPE2", PU_STATIC);
|
||||
break;
|
||||
case 3:
|
||||
patchINTERPIC = W_CacheLumpName("MAPE3", PU_STATIC);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
patchBEENTHERE = W_CacheLumpName("IN_X", PU_STATIC);
|
||||
patchGOINGTHERE = W_CacheLumpName("IN_YAH", PU_STATIC);
|
||||
FontBLumpBase = W_GetNumForName("FONTB16");
|
||||
for(i=0; i<10; i++)
|
||||
{
|
||||
FontBNumbers[i] = W_CacheLumpNum(FontBLumpBase+i, PU_STATIC);
|
||||
}
|
||||
FontBLump = W_GetNumForName("FONTB_S")+1;
|
||||
FontBNegative = W_CacheLumpName("FONTB13", PU_STATIC);
|
||||
|
||||
FontBSlash = W_CacheLumpName("FONTB15", PU_STATIC);
|
||||
FontBPercent = W_CacheLumpName("FONTB05", PU_STATIC);
|
||||
patchFaceOkayBase = W_GetNumForName("FACEA0");
|
||||
patchFaceDeadBase = W_GetNumForName("FACEB0");
|
||||
}
|
||||
|
||||
//========================================================================
|
||||
//
|
||||
// IN_UnloadPics
|
||||
//
|
||||
//========================================================================
|
||||
|
||||
void IN_UnloadPics(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
if(patchINTERPIC)
|
||||
{
|
||||
Z_ChangeTag(patchINTERPIC, PU_CACHE);
|
||||
}
|
||||
Z_ChangeTag(patchBEENTHERE, PU_CACHE);
|
||||
Z_ChangeTag(patchGOINGTHERE, PU_CACHE);
|
||||
for(i=0; i<10; i++)
|
||||
{
|
||||
Z_ChangeTag(FontBNumbers[i], PU_CACHE);
|
||||
}
|
||||
Z_ChangeTag(FontBNegative, PU_CACHE);
|
||||
Z_ChangeTag(FontBSlash, PU_CACHE);
|
||||
Z_ChangeTag(FontBPercent, PU_CACHE);
|
||||
}
|
||||
|
||||
//========================================================================
|
||||
//
|
||||
// IN_Ticker
|
||||
//
|
||||
//========================================================================
|
||||
|
||||
void IN_Ticker(void)
|
||||
{
|
||||
if(!intermission)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if(interstate == 3)
|
||||
{
|
||||
IN_WaitStop();
|
||||
return;
|
||||
}
|
||||
IN_CheckForSkip();
|
||||
intertime++;
|
||||
if(oldintertime < intertime)
|
||||
{
|
||||
interstate++;
|
||||
switch(interstate)
|
||||
{
|
||||
case 0:
|
||||
oldintertime = intertime+300;
|
||||
break;
|
||||
case 1:
|
||||
oldintertime = intertime+200;
|
||||
break;
|
||||
case 2:
|
||||
oldintertime = MAXINT;
|
||||
break;
|
||||
case 3:
|
||||
cnt = 10;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(skipintermission)
|
||||
{
|
||||
if(interstate == 0 && intertime < 150)
|
||||
{
|
||||
intertime = 150;
|
||||
skipintermission = false;
|
||||
return;
|
||||
}
|
||||
else if(interstate < 2 && gameepisode < 4)
|
||||
{
|
||||
interstate = 2;
|
||||
skipintermission = false;
|
||||
return;
|
||||
}
|
||||
interstate = 3;
|
||||
cnt = 10;
|
||||
skipintermission = false;
|
||||
S_StartSound(NULL, sfx_dorcls);
|
||||
}
|
||||
}
|
||||
|
||||
//========================================================================
|
||||
//
|
||||
// IN_CheckForSkip
|
||||
//
|
||||
// Check to see if any player hit a key
|
||||
//========================================================================
|
||||
|
||||
void IN_CheckForSkip(void)
|
||||
{
|
||||
int i;
|
||||
player_t *player;
|
||||
|
||||
for (i=0, player = players ; i<MAXPLAYERS ; i++, player++)
|
||||
{
|
||||
if (playeringame[i])
|
||||
{
|
||||
if (player->cmd.buttons&BT_ATTACK)
|
||||
{
|
||||
if (!player->attackdown)
|
||||
{
|
||||
skipintermission = 1;
|
||||
}
|
||||
player->attackdown = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
player->attackdown = false;
|
||||
}
|
||||
if (player->cmd.buttons&BT_USE)
|
||||
{
|
||||
if (!player->usedown)
|
||||
{
|
||||
skipintermission = 1;
|
||||
}
|
||||
player->usedown = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
player->usedown = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//========================================================================
|
||||
//
|
||||
// IN_Drawer
|
||||
//
|
||||
//========================================================================
|
||||
|
||||
void IN_Drawer(void)
|
||||
{
|
||||
static int oldinterstate;
|
||||
|
||||
if(!intermission)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if(interstate == 3)
|
||||
{
|
||||
return;
|
||||
}
|
||||
UpdateState |= I_FULLSCRN;
|
||||
if(oldinterstate != 2 && interstate == 2)
|
||||
{
|
||||
S_StartSound(NULL, sfx_pstop);
|
||||
}
|
||||
oldinterstate = interstate;
|
||||
switch(interstate)
|
||||
{
|
||||
case 0: // draw stats
|
||||
IN_DrawStatBack();
|
||||
switch(gametype)
|
||||
{
|
||||
case SINGLE:
|
||||
IN_DrawSingleStats();
|
||||
break;
|
||||
case COOPERATIVE:
|
||||
IN_DrawCoopStats();
|
||||
break;
|
||||
case DEATHMATCH:
|
||||
IN_DrawDMStats();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 1: // leaving old level
|
||||
if(gameepisode < 4)
|
||||
{
|
||||
V_DrawPatch(0, 0, patchINTERPIC);
|
||||
IN_DrawOldLevel();
|
||||
}
|
||||
break;
|
||||
case 2: // going to the next level
|
||||
if(gameepisode < 4)
|
||||
{
|
||||
V_DrawPatch(0, 0, patchINTERPIC);
|
||||
IN_DrawYAH();
|
||||
}
|
||||
break;
|
||||
case 3: // waiting before going to the next level
|
||||
if(gameepisode < 4)
|
||||
{
|
||||
V_DrawPatch(0, 0, patchINTERPIC);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
I_Error("IN_lude: Intermission state out of range.\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//========================================================================
|
||||
//
|
||||
// IN_DrawStatBack
|
||||
//
|
||||
//========================================================================
|
||||
|
||||
void IN_DrawStatBack(void)
|
||||
{
|
||||
int x;
|
||||
int y;
|
||||
|
||||
byte *src;
|
||||
byte *dest;
|
||||
|
||||
src = W_CacheLumpName ("FLOOR16", PU_CACHE);
|
||||
dest = screen;
|
||||
|
||||
for (y=0 ; y<SCREENHEIGHT ; y++)
|
||||
{
|
||||
for (x=0 ; x<SCREENWIDTH/64 ; x++)
|
||||
{
|
||||
memcpy (dest, src+((y&63)<<6), 64);
|
||||
dest += 64;
|
||||
}
|
||||
if (SCREENWIDTH&63)
|
||||
{
|
||||
memcpy (dest, src+((y&63)<<6), SCREENWIDTH&63);
|
||||
dest += (SCREENWIDTH&63);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//========================================================================
|
||||
//
|
||||
// IN_DrawOldLevel
|
||||
//
|
||||
//========================================================================
|
||||
|
||||
void IN_DrawOldLevel(void)
|
||||
{
|
||||
int i;
|
||||
int x;
|
||||
|
||||
x = 160-MN_TextBWidth(LevelNames[(gameepisode-1)*9+prevmap-1]+7)/2;
|
||||
IN_DrTextB(LevelNames[(gameepisode-1)*9+prevmap-1]+7, x, 3);
|
||||
x = 160-MN_TextAWidth("FINISHED")/2;
|
||||
MN_DrTextA("FINISHED", x, 25);
|
||||
|
||||
if(prevmap == 9)
|
||||
{
|
||||
for(i=0; i<gamemap-1; i++)
|
||||
{
|
||||
V_DrawPatch(YAHspot[gameepisode-1][i].x, YAHspot[gameepisode-1][i].y,
|
||||
patchBEENTHERE);
|
||||
}
|
||||
if(!(intertime&16))
|
||||
{
|
||||
V_DrawPatch(YAHspot[gameepisode-1][8].x, YAHspot[gameepisode-1][8].y,
|
||||
patchBEENTHERE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for(i=0; i<prevmap-1; i++)
|
||||
{
|
||||
V_DrawPatch(YAHspot[gameepisode-1][i].x, YAHspot[gameepisode-1][i].y,
|
||||
patchBEENTHERE);
|
||||
}
|
||||
if(players[consoleplayer].didsecret)
|
||||
{
|
||||
V_DrawPatch(YAHspot[gameepisode-1][8].x, YAHspot[gameepisode-1][8].y,
|
||||
patchBEENTHERE);
|
||||
}
|
||||
if(!(intertime&16))
|
||||
{
|
||||
V_DrawPatch(YAHspot[gameepisode-1][prevmap-1].x, YAHspot[gameepisode-1][prevmap-1].y,
|
||||
patchBEENTHERE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//========================================================================
|
||||
//
|
||||
// IN_DrawYAH
|
||||
//
|
||||
//========================================================================
|
||||
|
||||
void IN_DrawYAH(void)
|
||||
{
|
||||
int i;
|
||||
int x;
|
||||
|
||||
x = 160-MN_TextAWidth("NOW ENTERING:")/2;
|
||||
MN_DrTextA("NOW ENTERING:", x, 10);
|
||||
x = 160-MN_TextBWidth(LevelNames[(gameepisode-1)*9+gamemap-1]+7)/2;
|
||||
IN_DrTextB(LevelNames[(gameepisode-1)*9+gamemap-1]+7, x, 20);
|
||||
|
||||
if(prevmap == 9)
|
||||
{
|
||||
prevmap = gamemap-1;
|
||||
}
|
||||
for(i=0; i<prevmap; i++)
|
||||
{
|
||||
V_DrawPatch(YAHspot[gameepisode-1][i].x, YAHspot[gameepisode-1][i].y,
|
||||
patchBEENTHERE);
|
||||
}
|
||||
if(players[consoleplayer].didsecret)
|
||||
{
|
||||
V_DrawPatch(YAHspot[gameepisode-1][8].x, YAHspot[gameepisode-1][8].y,
|
||||
patchBEENTHERE);
|
||||
}
|
||||
if(!(intertime&16) || interstate == 3)
|
||||
{ // draw the destination 'X'
|
||||
V_DrawPatch(YAHspot[gameepisode-1][gamemap-1].x,
|
||||
YAHspot[gameepisode-1][gamemap-1].y, patchGOINGTHERE);
|
||||
}
|
||||
}
|
||||
|
||||
//========================================================================
|
||||
//
|
||||
// IN_DrawSingleStats
|
||||
//
|
||||
//========================================================================
|
||||
|
||||
void IN_DrawSingleStats(void)
|
||||
{
|
||||
int x;
|
||||
static int sounds;
|
||||
|
||||
IN_DrTextB("KILLS", 50, 65);
|
||||
IN_DrTextB("ITEMS", 50, 90);
|
||||
IN_DrTextB("SECRETS", 50, 115);
|
||||
|
||||
x = 160-MN_TextBWidth(LevelNames[(gameepisode-1)*9+prevmap-1]+7)/2;
|
||||
IN_DrTextB(LevelNames[(gameepisode-1)*9+prevmap-1]+7, x, 3);
|
||||
x = 160-MN_TextAWidth("FINISHED")/2;
|
||||
MN_DrTextA("FINISHED", x, 25);
|
||||
|
||||
if(intertime < 30)
|
||||
{
|
||||
sounds = 0;
|
||||
return;
|
||||
}
|
||||
if(sounds < 1 && intertime >= 30)
|
||||
{
|
||||
S_StartSound(NULL, sfx_dorcls);
|
||||
sounds++;
|
||||
}
|
||||
IN_DrawNumber(players[consoleplayer].killcount, 200, 65, 3);
|
||||
V_DrawShadowedPatch(237, 65, FontBSlash);
|
||||
IN_DrawNumber(totalkills, 248, 65, 3);
|
||||
if(intertime < 60)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if(sounds < 2 && intertime >= 60)
|
||||
{
|
||||
S_StartSound(NULL, sfx_dorcls);
|
||||
sounds++;
|
||||
}
|
||||
IN_DrawNumber(players[consoleplayer].itemcount, 200, 90, 3);
|
||||
V_DrawShadowedPatch(237, 90, FontBSlash);
|
||||
IN_DrawNumber(totalitems, 248, 90, 3);
|
||||
if(intertime < 90)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if(sounds < 3 && intertime >= 90)
|
||||
{
|
||||
S_StartSound(NULL, sfx_dorcls);
|
||||
sounds++;
|
||||
}
|
||||
IN_DrawNumber(players[consoleplayer].secretcount, 200, 115, 3);
|
||||
V_DrawShadowedPatch(237, 115, FontBSlash);
|
||||
IN_DrawNumber(totalsecret, 248, 115, 3);
|
||||
if(intertime < 150)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if(sounds < 4 && intertime >= 150)
|
||||
{
|
||||
S_StartSound(NULL, sfx_dorcls);
|
||||
sounds++;
|
||||
}
|
||||
|
||||
if(!ExtendedWAD || gameepisode < 4)
|
||||
{
|
||||
IN_DrTextB("TIME", 85, 160);
|
||||
IN_DrawTime(155, 160, hours, minutes, seconds);
|
||||
}
|
||||
else
|
||||
{
|
||||
x = 160-MN_TextAWidth("NOW ENTERING:")/2;
|
||||
MN_DrTextA("NOW ENTERING:", x, 160);
|
||||
x = 160-MN_TextBWidth(LevelNames[(gameepisode-1)*9+gamemap-1]+7)/2;
|
||||
IN_DrTextB(LevelNames[(gameepisode-1)*9+gamemap-1]+7, x, 170);
|
||||
skipintermission = false;
|
||||
}
|
||||
}
|
||||
|
||||
//========================================================================
|
||||
//
|
||||
// IN_DrawCoopStats
|
||||
//
|
||||
//========================================================================
|
||||
|
||||
void IN_DrawCoopStats(void)
|
||||
{
|
||||
int i;
|
||||
int x;
|
||||
int ypos;
|
||||
|
||||
static int sounds;
|
||||
|
||||
IN_DrTextB("KILLS", 95, 35);
|
||||
IN_DrTextB("BONUS", 155, 35);
|
||||
IN_DrTextB("SECRET", 232, 35);
|
||||
x = 160-MN_TextBWidth(LevelNames[(gameepisode-1)*9+prevmap-1]+7)/2;
|
||||
IN_DrTextB(LevelNames[(gameepisode-1)*9+prevmap-1]+7, x, 3);
|
||||
x = 160-MN_TextAWidth("FINISHED")/2;
|
||||
MN_DrTextA("FINISHED", x, 25);
|
||||
|
||||
ypos = 50;
|
||||
for(i=0; i<MAXPLAYERS; i++)
|
||||
{
|
||||
if(playeringame[i])
|
||||
{
|
||||
V_DrawShadowedPatch(25, ypos, W_CacheLumpNum(patchFaceOkayBase+i, PU_CACHE));
|
||||
if(intertime < 40)
|
||||
{
|
||||
sounds = 0;
|
||||
ypos += 37;
|
||||
continue;
|
||||
}
|
||||
else if(intertime >= 40 && sounds < 1)
|
||||
{
|
||||
S_StartSound(NULL, sfx_dorcls);
|
||||
sounds++;
|
||||
}
|
||||
IN_DrawNumber(killPercent[i], 85, ypos+10, 3);
|
||||
V_DrawShadowedPatch(121, ypos+10, FontBPercent);
|
||||
IN_DrawNumber(bonusPercent[i], 160, ypos+10, 3);
|
||||
V_DrawShadowedPatch(196, ypos+10, FontBPercent);
|
||||
IN_DrawNumber(secretPercent[i], 237, ypos+10, 3);
|
||||
V_DrawShadowedPatch(273, ypos+10, FontBPercent);
|
||||
ypos += 37;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//========================================================================
|
||||
//
|
||||
// IN_DrawDMStats
|
||||
//
|
||||
//========================================================================
|
||||
|
||||
void IN_DrawDMStats(void)
|
||||
{
|
||||
int i;
|
||||
int j;
|
||||
int ypos;
|
||||
int xpos;
|
||||
int kpos;
|
||||
|
||||
static int sounds;
|
||||
|
||||
xpos = 90;
|
||||
ypos = 55;
|
||||
|
||||
IN_DrTextB("TOTAL", 265, 30);
|
||||
MN_DrTextA("VICTIMS", 140, 8);
|
||||
for(i=0; i<7; i++)
|
||||
{
|
||||
MN_DrTextA(KillersText[i], 10, 80+9*i);
|
||||
}
|
||||
if(intertime < 20)
|
||||
{
|
||||
for(i=0; i<MAXPLAYERS; i++)
|
||||
{
|
||||
if(playeringame[i])
|
||||
{
|
||||
V_DrawShadowedPatch(40, ((ypos<<FRACBITS)+dSlideY[i]*intertime)
|
||||
>>FRACBITS, W_CacheLumpNum(patchFaceOkayBase+i, PU_CACHE));
|
||||
V_DrawShadowedPatch(((xpos<<FRACBITS)+dSlideX[i]*intertime)
|
||||
>>FRACBITS, 18, W_CacheLumpNum(patchFaceDeadBase+i, PU_CACHE));
|
||||
}
|
||||
}
|
||||
sounds = 0;
|
||||
return;
|
||||
}
|
||||
if(intertime >= 20 && sounds < 1)
|
||||
{
|
||||
S_StartSound(NULL, sfx_dorcls);
|
||||
sounds++;
|
||||
}
|
||||
if(intertime >= 100 && slaughterboy && sounds < 2)
|
||||
{
|
||||
S_StartSound(NULL, sfx_wpnup);
|
||||
sounds++;
|
||||
}
|
||||
for(i=0; i<MAXPLAYERS; i++)
|
||||
{
|
||||
if(playeringame[i])
|
||||
{
|
||||
if(intertime < 100 || i == consoleplayer)
|
||||
{
|
||||
V_DrawShadowedPatch(40, ypos, W_CacheLumpNum(patchFaceOkayBase+i, PU_CACHE));
|
||||
V_DrawShadowedPatch(xpos, 18, W_CacheLumpNum(patchFaceDeadBase+i, PU_CACHE));
|
||||
}
|
||||
else
|
||||
{
|
||||
V_DrawFuzzPatch(40, ypos, W_CacheLumpNum(patchFaceOkayBase+i, PU_CACHE));
|
||||
V_DrawFuzzPatch(xpos, 18, W_CacheLumpNum(patchFaceDeadBase+i, PU_CACHE));
|
||||
}
|
||||
kpos = 86;
|
||||
for(j=0; j<MAXPLAYERS; j++)
|
||||
{
|
||||
if(playeringame[j])
|
||||
{
|
||||
IN_DrawNumber(players[i].frags[j], kpos, ypos+10, 3);
|
||||
kpos += 43;
|
||||
}
|
||||
}
|
||||
if(slaughterboy&(1<<i))
|
||||
{
|
||||
if(!(intertime&16))
|
||||
{
|
||||
IN_DrawNumber(totalFrags[i], 263, ypos+10, 3);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
IN_DrawNumber(totalFrags[i], 263, ypos+10, 3);
|
||||
}
|
||||
ypos += 36;
|
||||
xpos += 43;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//========================================================================
|
||||
//
|
||||
// IN_DrawTime
|
||||
//
|
||||
//========================================================================
|
||||
|
||||
void IN_DrawTime(int x, int y, int h, int m, int s)
|
||||
{
|
||||
if(h)
|
||||
{
|
||||
IN_DrawNumber(h, x, y, 2);
|
||||
IN_DrTextB(":", x+26, y);
|
||||
}
|
||||
x += 34;
|
||||
if(m || h)
|
||||
{
|
||||
IN_DrawNumber(m, x, y, 2);
|
||||
}
|
||||
x += 34;
|
||||
if(s)
|
||||
{
|
||||
IN_DrTextB(":", x-8, y);
|
||||
IN_DrawNumber(s, x, y, 2);
|
||||
}
|
||||
}
|
||||
|
||||
//========================================================================
|
||||
//
|
||||
// IN_DrawNumber
|
||||
//
|
||||
//========================================================================
|
||||
|
||||
void IN_DrawNumber(int val, int x, int y, int digits)
|
||||
{
|
||||
patch_t *patch;
|
||||
int xpos;
|
||||
int oldval;
|
||||
int realdigits;
|
||||
boolean neg;
|
||||
|
||||
oldval = val;
|
||||
xpos = x;
|
||||
neg = false;
|
||||
realdigits = 1;
|
||||
|
||||
if(val < 0)
|
||||
{ //...this should reflect negative frags
|
||||
val = -val;
|
||||
neg = true;
|
||||
if(val > 99)
|
||||
{
|
||||
val = 99;
|
||||
}
|
||||
}
|
||||
if(val > 9)
|
||||
{
|
||||
realdigits++;
|
||||
if(digits < realdigits)
|
||||
{
|
||||
realdigits = digits;
|
||||
val = 9;
|
||||
}
|
||||
}
|
||||
if(val > 99)
|
||||
{
|
||||
realdigits++;
|
||||
if(digits < realdigits)
|
||||
{
|
||||
realdigits = digits;
|
||||
val = 99;
|
||||
}
|
||||
}
|
||||
if(val > 999)
|
||||
{
|
||||
realdigits++;
|
||||
if(digits < realdigits)
|
||||
{
|
||||
realdigits = digits;
|
||||
val = 999;
|
||||
}
|
||||
}
|
||||
if(digits == 4)
|
||||
{
|
||||
patch = FontBNumbers[val/1000];
|
||||
V_DrawShadowedPatch(xpos+6-patch->width/2-12, y, patch);
|
||||
}
|
||||
if(digits > 2)
|
||||
{
|
||||
if(realdigits > 2)
|
||||
{
|
||||
patch = FontBNumbers[val/100];
|
||||
V_DrawShadowedPatch(xpos+6-patch->width/2, y, patch);
|
||||
}
|
||||
xpos += 12;
|
||||
}
|
||||
val = val%100;
|
||||
if(digits > 1)
|
||||
{
|
||||
if(val > 9)
|
||||
{
|
||||
patch = FontBNumbers[val/10];
|
||||
V_DrawShadowedPatch(xpos+6-patch->width/2, y, patch);
|
||||
}
|
||||
else if(digits == 2 || oldval > 99)
|
||||
{
|
||||
V_DrawShadowedPatch(xpos, y, FontBNumbers[0]);
|
||||
}
|
||||
xpos += 12;
|
||||
}
|
||||
val = val%10;
|
||||
patch = FontBNumbers[val];
|
||||
V_DrawShadowedPatch(xpos+6-patch->width/2, y, patch);
|
||||
if(neg)
|
||||
{
|
||||
patch = FontBNegative;
|
||||
V_DrawShadowedPatch(xpos+6-patch->width/2-12*(realdigits), y, patch);
|
||||
}
|
||||
}
|
||||
|
||||
//========================================================================
|
||||
//
|
||||
// IN_DrTextB
|
||||
//
|
||||
//========================================================================
|
||||
|
||||
void IN_DrTextB(char *text, int x, int y)
|
||||
{
|
||||
char c;
|
||||
patch_t *p;
|
||||
|
||||
while((c = *text++) != 0)
|
||||
{
|
||||
if(c < 33)
|
||||
{
|
||||
x += 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
p = W_CacheLumpNum(FontBLump+c-33, PU_CACHE);
|
||||
V_DrawShadowedPatch(x, y, p);
|
||||
x += p->width-1;
|
||||
}
|
||||
}
|
||||
}
|
259
Heretic Source/I_CYBER.C
Normal file
259
Heretic Source/I_CYBER.C
Normal file
|
@ -0,0 +1,259 @@
|
|||
// I_cyber.c
|
||||
|
||||
#include <dos.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
/*
|
||||
====================================================
|
||||
|
||||
Doom control structure
|
||||
|
||||
The keybaord and joystick will add to the values set by the cyberman,
|
||||
to a maximum of 0x19000 for forwardmove and sidemove. Angleturn is
|
||||
not bounded at all.
|
||||
|
||||
parm normal fast
|
||||
----- ------ ----
|
||||
forwardmove 0xc800 0x19000
|
||||
sidemove 0xc000 0x14000
|
||||
angleturn 0x2800000 0x5000000
|
||||
|
||||
The keyboard and joystick have a 1/3 second slow turn of 0x1400000 under
|
||||
normal speed to help aiming.
|
||||
|
||||
|
||||
|
||||
====================================================
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char forwardmove; // *2048 for move
|
||||
char sidemove; // *2048 for move
|
||||
short angleturn; // <<16 for angle delta
|
||||
short consistancy; // checks for net game
|
||||
unsigned char chatchar;
|
||||
unsigned char buttons;
|
||||
} ticcmd_t;
|
||||
|
||||
#define BT_ATTACK 1
|
||||
#define BT_USE 2
|
||||
#define BT_CHANGE 4 // if true, the next 3 bits hold weapon num
|
||||
#define BT_WEAPONMASK (8+16+32)
|
||||
#define BT_WEAPONSHIFT 3
|
||||
|
||||
|
||||
|
||||
//==================================================
|
||||
//
|
||||
// CyberMan detection and usage info
|
||||
//
|
||||
//==================================================
|
||||
#define DPMI_INT 0x31
|
||||
#define MOUSE_INT 0x33
|
||||
|
||||
#define DOSMEMSIZE 64 // enough for any SWIFT structure
|
||||
|
||||
typedef struct {
|
||||
short x;
|
||||
short y;
|
||||
short z;
|
||||
short pitch;
|
||||
short roll;
|
||||
short yaw;
|
||||
short buttons;
|
||||
} SWIFT_3DStatus;
|
||||
|
||||
// DPMI real mode interrupt structure
|
||||
static struct rminfo {
|
||||
long EDI;
|
||||
long ESI;
|
||||
long EBP;
|
||||
long reserved_by_system;
|
||||
long EBX;
|
||||
long EDX;
|
||||
long ECX;
|
||||
long EAX;
|
||||
short flags;
|
||||
short ES,DS,FS,GS,IP,CS,SP,SS;
|
||||
} RMI;
|
||||
|
||||
typedef struct {
|
||||
unsigned char deviceType;
|
||||
unsigned char majorVersion;
|
||||
unsigned char minorVersion;
|
||||
unsigned char absRelFlags;
|
||||
unsigned char centeringFlags;
|
||||
unsigned char reserved[5];
|
||||
} StaticDeviceData;
|
||||
|
||||
// values for deviceType:
|
||||
#define DEVTYPE_CYBERMAN 1
|
||||
|
||||
short selector;
|
||||
unsigned short segment; // segment of DOS memory block
|
||||
SWIFT_3DStatus *cyberstat;
|
||||
int isCyberPresent; // is CyberMan present?
|
||||
|
||||
|
||||
static union REGS regs;
|
||||
static struct SREGS sregs;
|
||||
|
||||
|
||||
extern int mousepresent;
|
||||
|
||||
//===========================================================
|
||||
//
|
||||
// I_StartupCyberMan
|
||||
//
|
||||
// If a cyberman is present, init it and set isCyberPresent to 1
|
||||
//===========================================================
|
||||
void I_StartupCyberMan(void)
|
||||
{
|
||||
StaticDeviceData *pbuf;
|
||||
int success = 0;
|
||||
|
||||
isCyberPresent = 0;
|
||||
|
||||
cyberstat = (SWIFT_3DStatus *)I_AllocLow (DOSMEMSIZE);
|
||||
segment = (int)cyberstat>>4;
|
||||
|
||||
pbuf = (StaticDeviceData *)cyberstat;
|
||||
memset(pbuf, 0, sizeof (StaticDeviceData));
|
||||
|
||||
// Use DPMI call 300h to issue mouse interrupt
|
||||
memset(&RMI, 0, sizeof(RMI));
|
||||
RMI.EAX = 0x53C1; // SWIFT: Get Static Device Data
|
||||
RMI.ES = segment;
|
||||
RMI.EDX = 0;
|
||||
memset(&sregs, 0, sizeof (sregs));
|
||||
regs.w.ax = 0x0300; // DPMI: simulate interrupt
|
||||
regs.w.bx = MOUSE_INT;
|
||||
regs.w.cx = 0;
|
||||
regs.x.edi = FP_OFF(&RMI);
|
||||
sregs.es = FP_SEG(&RMI);
|
||||
int386x( DPMI_INT, ®s, ®s, &sregs );
|
||||
|
||||
if ((short)RMI.EAX != 1)
|
||||
{
|
||||
// SWIFT functions not present
|
||||
tprintf("CyberMan: Wrong mouse driver - no SWIFT support (AX=%04x).\n",
|
||||
(unsigned)(short)RMI.EAX);
|
||||
}
|
||||
else
|
||||
if (pbuf->deviceType != DEVTYPE_CYBERMAN)
|
||||
{
|
||||
// no SWIFT device, or not CyberMan
|
||||
if (pbuf->deviceType == 0)
|
||||
{
|
||||
tprintf("CyberMan: no SWIFT device connected.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
tprintf("CyberMan: SWIFT device is not a CyberMan! (type=%d)\n",
|
||||
pbuf->deviceType);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
tprintf("CyberMan: CyberMan %d.%02d connected.\n",
|
||||
pbuf->majorVersion, pbuf->minorVersion);
|
||||
isCyberPresent = 1;
|
||||
mousepresent = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
===============
|
||||
=
|
||||
= I_ReadCyberCmds
|
||||
=
|
||||
===============
|
||||
*/
|
||||
|
||||
|
||||
int oldpos;
|
||||
|
||||
void I_ReadCyberCmd (ticcmd_t *cmd)
|
||||
{
|
||||
int delta;
|
||||
|
||||
// Use DPMI call 300h to issue mouse interrupt
|
||||
memset(&RMI, 0, sizeof(RMI));
|
||||
RMI.EAX = 0x5301; // SWIFT: Get Position and Buttons
|
||||
RMI.ES = segment;
|
||||
RMI.EDX = 0;
|
||||
memset(&sregs, 0, sizeof (sregs));
|
||||
regs.w.ax = 0x0300; // DPMI: simulate interrupt
|
||||
regs.w.bx = MOUSE_INT;
|
||||
regs.w.cx = 0;
|
||||
regs.x.edi = FP_OFF(&RMI);
|
||||
sregs.es = FP_SEG(&RMI);
|
||||
int386x( DPMI_INT, ®s, ®s, &sregs );
|
||||
|
||||
if (cyberstat->y < -7900)
|
||||
cmd->forwardmove = 0xc800/2048;
|
||||
else if (cyberstat->y > 7900)
|
||||
cmd->forwardmove = -0xc800/2048;
|
||||
|
||||
if (cyberstat->buttons & 4)
|
||||
cmd->buttons |= BT_ATTACK;
|
||||
if (cyberstat->buttons & 2)
|
||||
cmd->buttons |= BT_USE;
|
||||
|
||||
delta = cyberstat->x - oldpos;
|
||||
oldpos = cyberstat->x;
|
||||
|
||||
if (cyberstat->buttons & 1)
|
||||
{ // strafe
|
||||
if (cyberstat->x < -7900)
|
||||
cmd->sidemove = -0xc800/2048;
|
||||
else if (cyberstat->x > 7900)
|
||||
cmd->sidemove = 0xc800/2048;
|
||||
else
|
||||
cmd->sidemove = delta*40/2048;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (cyberstat->x < -7900)
|
||||
cmd->angleturn = 0x280;
|
||||
else if (cyberstat->x > 7900)
|
||||
cmd->angleturn = -0x280;
|
||||
else
|
||||
cmd->angleturn = -delta*0xa/16;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void I_Tactile (int on, int off, int total)
|
||||
{
|
||||
if (!isCyberPresent)
|
||||
return;
|
||||
|
||||
on /= 5;
|
||||
off /= 5;
|
||||
total /= 40;
|
||||
if (on > 255)
|
||||
on = 255;
|
||||
if (off > 255)
|
||||
off = 255;
|
||||
if (total > 255)
|
||||
total = 255;
|
||||
|
||||
memset(&RMI, 0, sizeof(RMI));
|
||||
RMI.EAX = 0x5330; // SWIFT: Get Position and Buttons
|
||||
RMI.EBX = on*256+off;
|
||||
RMI.ECX = total;
|
||||
memset(&sregs, 0, sizeof (sregs));
|
||||
regs.w.ax = 0x0300; // DPMI: simulate interrupt
|
||||
regs.w.bx = MOUSE_INT;
|
||||
regs.w.cx = 0;
|
||||
regs.x.edi = FP_OFF(&RMI);
|
||||
sregs.es = FP_SEG(&RMI);
|
||||
int386x( DPMI_INT, ®s, ®s, &sregs );
|
||||
}
|
77
Heretic Source/I_HEADER.H
Normal file
77
Heretic Source/I_HEADER.H
Normal file
|
@ -0,0 +1,77 @@
|
|||
#ifndef __I_HEADER_H__
|
||||
#define __I_HEADER_H__
|
||||
|
||||
#include "DoomDef.h"
|
||||
|
||||
//--------
|
||||
//SOUND IO
|
||||
//--------
|
||||
#define FREQ_LOW 0x40
|
||||
#define FREQ_NORM 0x80
|
||||
#define FREQ_HIGH 0xff
|
||||
|
||||
void I_SetMasterVolume(int volume);
|
||||
|
||||
void I_TurnOffSfx(void);
|
||||
void I_TurnOnSfx(void);
|
||||
void I_TurnOffMusic(void);
|
||||
void I_TurnOnMusic(void);
|
||||
|
||||
// MUSIC I/O
|
||||
//
|
||||
|
||||
int I_RegisterSong(void *songdata);
|
||||
// called by anything that wants to register a song lump with the sound lib
|
||||
// calls Paul's function of the similar name to register music only.
|
||||
// note that the song data is the same for any sound card and is paul's
|
||||
// MUS format. Returns a handle which will be passed to all other music
|
||||
// functions.
|
||||
|
||||
void I_UnregisterSong(int handle);
|
||||
// called by anything which is finished with a song and no longer needs
|
||||
// the sound library to be aware of it. All songs should be stopped
|
||||
// before calling this, but it will double check and stop it if necessary.
|
||||
|
||||
void I_LoopSong(int handle);
|
||||
// called by anything that wishes to start music.
|
||||
// plays a song, and when the song is done, starts playing it again in
|
||||
// an endless loop. the start is faded in over three seconds.
|
||||
|
||||
void I_FadeOutSong(int handle, int fotime);
|
||||
// called by anything that wishes to stop music.
|
||||
// fades out the song over <fotime> milliseconds.
|
||||
|
||||
void I_StopSong(int handle);
|
||||
// called by anything that wishes to stop music.
|
||||
// stops a song abruptly.
|
||||
|
||||
// SFX I/O
|
||||
//
|
||||
|
||||
void *I_GetSoundEffect (char *soundname);
|
||||
// called by routines which wish to play a sound effect at some later
|
||||
// time. Pass it the lump name of a sound effect WITHOUT the sfx
|
||||
// prefix. This means the maximum name length is 7 letters/digits.
|
||||
// The prefixes for different sound cards are 'S','M','A', and 'P'.
|
||||
// They refer to the card type. The routine will cache in the
|
||||
// appropriate sound effect when it is played.
|
||||
|
||||
void I_UngetSoundEffect (void *soundset);
|
||||
// called by routines which wish to no longer use the sounds at all
|
||||
// frees up the associated structure. It stops any currently playing
|
||||
// sound effects.
|
||||
|
||||
void I_StartSound (channel_t *c, int vol, int sep, int pitch, int priority);
|
||||
// Starts a sound in a particular sound channel
|
||||
|
||||
void I_UpdateSoundParams(channel_t *c, int vol, int sep, int pitch);
|
||||
// Updates the volume, separation, and pitch of a sound channel
|
||||
|
||||
void I_StopSound(channel_t *c);
|
||||
// Stops a sound channel
|
||||
|
||||
int I_SoundIsPlaying(channel_t *c);
|
||||
// called by S_*()'s to see if a channel is still playing. Returns 0
|
||||
// if no longer playing, 1 if playing.
|
||||
|
||||
#endif
|
2204
Heretic Source/I_IBM.C
Normal file
2204
Heretic Source/I_IBM.C
Normal file
File diff suppressed because it is too large
Load diff
135
Heretic Source/I_IBM_A.ASM
Normal file
135
Heretic Source/I_IBM_A.ASM
Normal file
|
@ -0,0 +1,135 @@
|
|||
.386
|
||||
.MODEL small
|
||||
|
||||
.DATA
|
||||
|
||||
|
||||
|
||||
.CODE
|
||||
|
||||
IF 0
|
||||
#define PEL_WRITE_ADR 0x3c8
|
||||
#define PEL_READ_ADR 0x3c7
|
||||
#define PEL_DATA 0x3c9
|
||||
ENDIF
|
||||
|
||||
;================
|
||||
;
|
||||
; I_DivException
|
||||
;
|
||||
;================
|
||||
|
||||
PROC I_DivException_
|
||||
PUBLIC I_DivException_
|
||||
mov edx,03c9h
|
||||
mov al,63
|
||||
out dx,al
|
||||
|
||||
mov ebx,0ffffffh
|
||||
mov eax,[ebx]
|
||||
retf
|
||||
ENDP
|
||||
|
||||
;================
|
||||
;
|
||||
; I_SetDivException
|
||||
;
|
||||
;================
|
||||
|
||||
PROC I_SetDivException_
|
||||
PUBLIC I_SetDivException_
|
||||
pusha
|
||||
|
||||
mov eax,0212h
|
||||
mov ebx,0
|
||||
mov ecx,cs
|
||||
mov edx,OFFSET I_DivException_
|
||||
int 31h
|
||||
jnc good
|
||||
|
||||
popa
|
||||
mov eax,0
|
||||
ret
|
||||
|
||||
good:
|
||||
popa
|
||||
mov eax,1
|
||||
ret
|
||||
|
||||
ENDP
|
||||
|
||||
|
||||
;================
|
||||
;
|
||||
; I_ReadJoystick
|
||||
;
|
||||
; Read the absolute joystick values
|
||||
; returns false if not connected
|
||||
;================
|
||||
|
||||
.data
|
||||
|
||||
_joystickx dd 0
|
||||
_joysticky dd 0
|
||||
PUBLIC _joystickx, _joysticky
|
||||
|
||||
.code
|
||||
|
||||
PROC I_ReadJoystick_
|
||||
PUBLIC I_ReadJoystick_
|
||||
pusha
|
||||
pushf ; state of interrupt flag
|
||||
cli
|
||||
|
||||
mov dx,0201h
|
||||
in al,dx
|
||||
out dx,al ; Clear the resistors
|
||||
|
||||
mov ah,1 ; Get masks into registers
|
||||
mov ch,2
|
||||
|
||||
xor esi,esi ; Clear count registers
|
||||
xor edi,edi
|
||||
xor ebx,ebx ; Clear high byte of bx for later
|
||||
|
||||
mov ebp,10000 ; joystick is disconnected if value is this big
|
||||
|
||||
jloop:
|
||||
in al,dx ; Get bits indicating whether all are finished
|
||||
|
||||
dec ebp ; Check bounding register
|
||||
jz bad ; We have a silly value - abort
|
||||
|
||||
mov bl,al ; Duplicate the bits
|
||||
and bl,ah ; Mask off useless bits (in [xb])
|
||||
add esi,ebx ; Possibly increment count register
|
||||
mov cl,bl ; Save for testing later
|
||||
|
||||
mov bl,al
|
||||
and bl,ch ; [yb]
|
||||
add edi,ebx
|
||||
|
||||
add cl,bl
|
||||
jnz jloop ; If both bits were 0, drop out
|
||||
|
||||
done:
|
||||
mov [_joystickx],esi
|
||||
shr edi,1 ; because 2s were added
|
||||
mov [_joysticky],edi
|
||||
|
||||
popf ; restore interrupt flag
|
||||
popa
|
||||
mov eax,1 ; read was ok
|
||||
ret
|
||||
|
||||
bad:
|
||||
popf ; restore interrupt flag
|
||||
popa
|
||||
xor eax, eax ; read was bad
|
||||
ret
|
||||
|
||||
ENDP
|
||||
|
||||
|
||||
END
|
||||
|
391
Heretic Source/I_SOUND.C
Normal file
391
Heretic Source/I_SOUND.C
Normal file
|
@ -0,0 +1,391 @@
|
|||
|
||||
// I_SOUND.C
|
||||
|
||||
#include <stdio.h>
|
||||
#include "doomdef.h"
|
||||
#include "dmx.h"
|
||||
#include "sounds.h"
|
||||
#include "i_sound.h"
|
||||
|
||||
/*
|
||||
===============
|
||||
=
|
||||
= I_StartupTimer
|
||||
=
|
||||
===============
|
||||
*/
|
||||
|
||||
int tsm_ID = -1;
|
||||
|
||||
void I_StartupTimer (void)
|
||||
{
|
||||
#ifndef NOTIMER
|
||||
extern int I_TimerISR(void);
|
||||
|
||||
tprintf("I_StartupTimer()\n",0);
|
||||
// installs master timer. Must be done before StartupTimer()!
|
||||
TSM_Install(SND_TICRATE);
|
||||
tsm_ID = TSM_NewService (I_TimerISR, 35, 255, 0); // max priority
|
||||
if (tsm_ID == -1)
|
||||
{
|
||||
I_Error("Can't register 35 Hz timer w/ DMX library");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void I_ShutdownTimer (void)
|
||||
{
|
||||
TSM_DelService(tsm_ID);
|
||||
TSM_Remove();
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* SOUND HEADER & DATA
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
// sound information
|
||||
#if 0
|
||||
const char *dnames[] = {"None",
|
||||
"PC_Speaker",
|
||||
"Adlib",
|
||||
"Sound_Blaster",
|
||||
"ProAudio_Spectrum16",
|
||||
"Gravis_Ultrasound",
|
||||
"MPU",
|
||||
"AWE32"
|
||||
};
|
||||
#endif
|
||||
|
||||
const char snd_prefixen[] = { 'P', 'P', 'A', 'S', 'S', 'S', 'M',
|
||||
'M', 'M', 'S' };
|
||||
|
||||
int snd_Channels;
|
||||
int snd_DesiredMusicDevice, snd_DesiredSfxDevice;
|
||||
int snd_MusicDevice, // current music card # (index to dmxCodes)
|
||||
snd_SfxDevice, // current sfx card # (index to dmxCodes)
|
||||
snd_MaxVolume, // maximum volume for sound
|
||||
snd_MusicVolume; // maximum volume for music
|
||||
int dmxCodes[NUM_SCARDS]; // the dmx code for a given card
|
||||
|
||||
int snd_SBport, snd_SBirq, snd_SBdma; // sound blaster variables
|
||||
int snd_Mport; // midi variables
|
||||
|
||||
extern boolean snd_MusicAvail, // whether music is available
|
||||
snd_SfxAvail; // whether sfx are available
|
||||
|
||||
void I_PauseSong(int handle)
|
||||
{
|
||||
MUS_PauseSong(handle);
|
||||
}
|
||||
|
||||
void I_ResumeSong(int handle)
|
||||
{
|
||||
MUS_ResumeSong(handle);
|
||||
}
|
||||
|
||||
void I_SetMusicVolume(int volume)
|
||||
{
|
||||
MUS_SetMasterVolume(volume*8);
|
||||
// snd_MusicVolume = volume;
|
||||
}
|
||||
|
||||
void I_SetSfxVolume(int volume)
|
||||
{
|
||||
snd_MaxVolume = volume; // THROW AWAY?
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* SONG API
|
||||
*
|
||||
*/
|
||||
|
||||
int I_RegisterSong(void *data)
|
||||
{
|
||||
int rc = MUS_RegisterSong(data);
|
||||
#ifdef SNDDEBUG
|
||||
if (rc<0) printf("MUS_Reg() returned %d\n", rc);
|
||||
#endif
|
||||
return rc;
|
||||
}
|
||||
|
||||
void I_UnRegisterSong(int handle)
|
||||
{
|
||||
int rc = MUS_UnregisterSong(handle);
|
||||
#ifdef SNDDEBUG
|
||||
if (rc < 0) printf("MUS_Unreg() returned %d\n", rc);
|
||||
#endif
|
||||
}
|
||||
|
||||
int I_QrySongPlaying(int handle)
|
||||
{
|
||||
int rc = MUS_QrySongPlaying(handle);
|
||||
#ifdef SNDDEBUG
|
||||
if (rc < 0) printf("MUS_QrySP() returned %d\n", rc);
|
||||
#endif
|
||||
return rc;
|
||||
}
|
||||
|
||||
// Stops a song. MUST be called before I_UnregisterSong().
|
||||
|
||||
void I_StopSong(int handle)
|
||||
{
|
||||
int rc;
|
||||
rc = MUS_StopSong(handle);
|
||||
#ifdef SNDDEBUG
|
||||
if (rc < 0) printf("MUS_StopSong() returned %d\n", rc);
|
||||
#endif
|
||||
// Fucking kluge pause
|
||||
{
|
||||
int s;
|
||||
extern volatile int ticcount;
|
||||
for (s=ticcount ; ticcount - s < 10 ; );
|
||||
}
|
||||
}
|
||||
|
||||
void I_PlaySong(int handle, boolean looping)
|
||||
{
|
||||
int rc;
|
||||
rc = MUS_ChainSong(handle, looping ? handle : -1);
|
||||
#ifdef SNDDEBUG
|
||||
if (rc < 0) printf("MUS_ChainSong() returned %d\n", rc);
|
||||
#endif
|
||||
rc = MUS_PlaySong(handle, snd_MusicVolume);
|
||||
#ifdef SNDDEBUG
|
||||
if (rc < 0) printf("MUS_PlaySong() returned %d\n", rc);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* SOUND FX API
|
||||
*
|
||||
*/
|
||||
|
||||
// Gets lump nums of the named sound. Returns pointer which will be
|
||||
// passed to I_StartSound() when you want to start an SFX. Must be
|
||||
// sure to pass this to UngetSoundEffect() so that they can be
|
||||
// freed!
|
||||
|
||||
|
||||
int I_GetSfxLumpNum(sfxinfo_t *sound)
|
||||
{
|
||||
char namebuf[9];
|
||||
|
||||
if(sound->name == 0)
|
||||
return 0;
|
||||
if (sound->link) sound = sound->link;
|
||||
// sprintf(namebuf, "d%c%s", snd_prefixen[snd_SfxDevice], sound->name);
|
||||
return W_GetNumForName(sound->name);
|
||||
|
||||
}
|
||||
|
||||
int I_StartSound (int id, void *data, int vol, int sep, int pitch, int priority)
|
||||
{
|
||||
/*
|
||||
// hacks out certain PC sounds
|
||||
if (snd_SfxDevice == PC
|
||||
&& (data == S_sfx[sfx_posact].data
|
||||
|| data == S_sfx[sfx_bgact].data
|
||||
|| data == S_sfx[sfx_dmact].data
|
||||
|| data == S_sfx[sfx_dmpain].data
|
||||
|| data == S_sfx[sfx_popain].data
|
||||
|| data == S_sfx[sfx_sawidl].data)) return -1;
|
||||
|
||||
else
|
||||
*/
|
||||
return SFX_PlayPatch(data, pitch, sep, vol, 0, 0);
|
||||
|
||||
}
|
||||
|
||||
void I_StopSound(int handle)
|
||||
{
|
||||
// extern volatile long gDmaCount;
|
||||
// long waittocount;
|
||||
SFX_StopPatch(handle);
|
||||
// waittocount = gDmaCount + 2;
|
||||
// while (gDmaCount < waittocount) ;
|
||||
}
|
||||
|
||||
int I_SoundIsPlaying(int handle)
|
||||
{
|
||||
return SFX_Playing(handle);
|
||||
}
|
||||
|
||||
void I_UpdateSoundParams(int handle, int vol, int sep, int pitch)
|
||||
{
|
||||
SFX_SetOrigin(handle, pitch, sep, vol);
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* SOUND STARTUP STUFF
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
//
|
||||
// Why PC's Suck, Reason #8712
|
||||
//
|
||||
|
||||
void I_sndArbitrateCards(void)
|
||||
{
|
||||
char tmp[160];
|
||||
boolean gus, adlib, pc, sb, midi;
|
||||
int i, rc, mputype, p, opltype, wait, dmxlump;
|
||||
|
||||
// snd_MaxVolume = 127;
|
||||
//Damn you, Dave Taylor!
|
||||
|
||||
snd_MusicDevice = snd_DesiredMusicDevice;
|
||||
snd_SfxDevice = snd_DesiredSfxDevice;
|
||||
|
||||
// check command-line parameters- overrides config file
|
||||
//
|
||||
if (M_CheckParm("-nosound")) snd_MusicDevice = snd_SfxDevice = snd_none;
|
||||
if (M_CheckParm("-nosfx")) snd_SfxDevice = snd_none;
|
||||
if (M_CheckParm("-nomusic")) snd_MusicDevice = snd_none;
|
||||
|
||||
if (snd_MusicDevice > snd_MPU && snd_MusicDevice <= snd_MPU3)
|
||||
snd_MusicDevice = snd_MPU;
|
||||
if (snd_MusicDevice == snd_SB)
|
||||
snd_MusicDevice = snd_Adlib;
|
||||
if (snd_MusicDevice == snd_PAS)
|
||||
snd_MusicDevice = snd_Adlib;
|
||||
|
||||
// figure out what i've got to initialize
|
||||
//
|
||||
gus = snd_MusicDevice == snd_GUS || snd_SfxDevice == snd_GUS;
|
||||
sb = snd_SfxDevice == snd_SB || snd_MusicDevice == snd_SB;
|
||||
adlib = snd_MusicDevice == snd_Adlib ;
|
||||
pc = snd_SfxDevice == snd_PC;
|
||||
midi = snd_MusicDevice == snd_MPU;
|
||||
|
||||
// initialize whatever i've got
|
||||
//
|
||||
if (gus)
|
||||
{
|
||||
if (GF1_Detect()) tprintf("Dude. The GUS ain't responding.\n",1);
|
||||
else
|
||||
{
|
||||
dmxlump = W_GetNumForName("dmxgus");
|
||||
GF1_SetMap(W_CacheLumpNum(dmxlump, PU_CACHE), lumpinfo[dmxlump].size);
|
||||
}
|
||||
|
||||
}
|
||||
if (sb)
|
||||
{
|
||||
if(debugmode)
|
||||
{
|
||||
sprintf(tmp,"cfg p=0x%x, i=%d, d=%d\n",
|
||||
snd_SBport, snd_SBirq, snd_SBdma);
|
||||
tprintf(tmp,0);
|
||||
}
|
||||
if (SB_Detect(&snd_SBport, &snd_SBirq, &snd_SBdma, 0))
|
||||
{
|
||||
sprintf(tmp,"SB isn't responding at p=0x%x, i=%d, d=%d\n",
|
||||
snd_SBport, snd_SBirq, snd_SBdma);
|
||||
tprintf(tmp,0);
|
||||
}
|
||||
else SB_SetCard(snd_SBport, snd_SBirq, snd_SBdma);
|
||||
|
||||
if(debugmode)
|
||||
{
|
||||
sprintf(tmp,"SB_Detect returned p=0x%x,i=%d,d=%d\n",
|
||||
snd_SBport, snd_SBirq, snd_SBdma);
|
||||
tprintf(tmp,0);
|
||||
}
|
||||
}
|
||||
|
||||
if (adlib)
|
||||
{
|
||||
if (AL_Detect(&wait,0))
|
||||
tprintf("Dude. The Adlib isn't responding.\n",1);
|
||||
else
|
||||
AL_SetCard(wait, W_CacheLumpName("genmidi", PU_STATIC));
|
||||
}
|
||||
|
||||
if (midi)
|
||||
{
|
||||
if (debugmode)
|
||||
{
|
||||
sprintf(tmp,"cfg p=0x%x\n", snd_Mport);
|
||||
tprintf(tmp,0);
|
||||
}
|
||||
|
||||
if (MPU_Detect(&snd_Mport, &i))
|
||||
{
|
||||
sprintf(tmp,"The MPU-401 isn't reponding @ p=0x%x.\n", snd_Mport);
|
||||
tprintf(tmp,0);
|
||||
}
|
||||
else MPU_SetCard(snd_Mport);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// inits all sound stuff
|
||||
|
||||
void I_StartupSound (void)
|
||||
{
|
||||
char tmp[80];
|
||||
int rc, i;
|
||||
|
||||
if (debugmode)
|
||||
tprintf("I_StartupSound: Hope you hear a pop.\n",1);
|
||||
|
||||
// initialize dmxCodes[]
|
||||
dmxCodes[0] = 0;
|
||||
dmxCodes[snd_PC] = AHW_PC_SPEAKER;
|
||||
dmxCodes[snd_Adlib] = AHW_ADLIB;
|
||||
dmxCodes[snd_SB] = AHW_SOUND_BLASTER;
|
||||
dmxCodes[snd_PAS] = AHW_MEDIA_VISION;
|
||||
dmxCodes[snd_GUS] = AHW_ULTRA_SOUND;
|
||||
dmxCodes[snd_MPU] = AHW_MPU_401;
|
||||
dmxCodes[snd_AWE] = AHW_AWE32;
|
||||
|
||||
// inits sound library timer stuff
|
||||
I_StartupTimer();
|
||||
|
||||
// pick the sound cards i'm going to use
|
||||
//
|
||||
I_sndArbitrateCards();
|
||||
|
||||
if (debugmode)
|
||||
{
|
||||
sprintf(tmp," Music device #%d & dmxCode=%d", snd_MusicDevice,
|
||||
dmxCodes[snd_MusicDevice]);
|
||||
tprintf(tmp,0);
|
||||
sprintf(tmp," Sfx device #%d & dmxCode=%d\n", snd_SfxDevice,
|
||||
dmxCodes[snd_SfxDevice]);
|
||||
tprintf(tmp,0);
|
||||
}
|
||||
|
||||
// inits DMX sound library
|
||||
tprintf(" calling DMX_Init",0);
|
||||
rc = DMX_Init(SND_TICRATE, SND_MAXSONGS, dmxCodes[snd_MusicDevice],
|
||||
dmxCodes[snd_SfxDevice]);
|
||||
|
||||
if (debugmode)
|
||||
{
|
||||
sprintf(tmp," DMX_Init() returned %d", rc);
|
||||
tprintf(tmp,0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// shuts down all sound stuff
|
||||
|
||||
void I_ShutdownSound (void)
|
||||
{
|
||||
DMX_DeInit();
|
||||
I_ShutdownTimer();
|
||||
}
|
||||
|
||||
void I_SetChannels(int channels)
|
||||
{
|
||||
WAV_PlayMode(channels, SND_SAMPLERATE);
|
||||
}
|
23
Heretic Source/I_SOUND.H
Normal file
23
Heretic Source/I_SOUND.H
Normal file
|
@ -0,0 +1,23 @@
|
|||
#ifndef __SOUND__
|
||||
#define __SOUND__
|
||||
|
||||
#define SND_TICRATE 140 // tic rate for updating sound
|
||||
#define SND_MAXSONGS 40 // max number of songs in game
|
||||
#define SND_SAMPLERATE 11025 // sample rate of sound effects
|
||||
|
||||
typedef enum
|
||||
{
|
||||
snd_none,
|
||||
snd_PC,
|
||||
snd_Adlib,
|
||||
snd_SB,
|
||||
snd_PAS,
|
||||
snd_GUS,
|
||||
snd_MPU,
|
||||
snd_MPU2,
|
||||
snd_MPU3,
|
||||
snd_AWE,
|
||||
NUM_SCARDS
|
||||
} cardenum_t;
|
||||
|
||||
#endif
|
258
Heretic Source/LINEAR.ASM
Normal file
258
Heretic Source/LINEAR.ASM
Normal file
|
@ -0,0 +1,258 @@
|
|||
.386
|
||||
.MODEL small
|
||||
INCLUDE defs.inc
|
||||
|
||||
|
||||
;============================================================================
|
||||
;
|
||||
; unwound vertical scaling code
|
||||
;
|
||||
; eax light table pointer, 0 lowbyte overwritten
|
||||
; ebx all 0, low byte overwritten
|
||||
; ecx fractional step value
|
||||
; edx fractional scale value
|
||||
; esi start of source pixels
|
||||
; edi bottom pixel in screenbuffer to blit into
|
||||
;
|
||||
; ebx should be set to 0 0 0 dh to feed the pipeline
|
||||
;
|
||||
; The graphics wrap vertically at 128 pixels
|
||||
;============================================================================
|
||||
|
||||
.DATA
|
||||
|
||||
EXTRN _centery:DWORD
|
||||
|
||||
SCALEDEFINE MACRO number
|
||||
dd vscale&number
|
||||
ENDM
|
||||
|
||||
ALIGN 4
|
||||
scalecalls LABEL
|
||||
LINE = 0
|
||||
REPT SCREENHEIGHT+1
|
||||
SCALEDEFINE %LINE
|
||||
LINE = LINE+1
|
||||
ENDM
|
||||
|
||||
|
||||
;=================================
|
||||
|
||||
|
||||
.CODE
|
||||
|
||||
;================
|
||||
;
|
||||
; R_DrawColumn
|
||||
;
|
||||
;================
|
||||
|
||||
PROC R_DrawColumn_
|
||||
PUBLIC R_DrawColumn_
|
||||
PUSHR
|
||||
|
||||
mov ebp,[_dc_yh]
|
||||
mov ebx,ebp
|
||||
mov edi,[_ylookup+ebx*4]
|
||||
mov ebx,[_dc_x]
|
||||
add edi,[_columnofs + ebx*4]
|
||||
|
||||
mov eax,[_dc_yl]
|
||||
sub ebp,eax ; ebp = pixel count
|
||||
or ebp,ebp
|
||||
js done
|
||||
|
||||
mov ecx,[_dc_iscale]
|
||||
|
||||
sub eax,[_centery]
|
||||
imul ecx
|
||||
mov edx,[_dc_texturemid]
|
||||
add edx,eax
|
||||
shl edx,9 ; 7 significant bits, 25 frac
|
||||
|
||||
shl ecx,9 ; 7 significant bits, 25 frac
|
||||
mov esi,[_dc_source]
|
||||
|
||||
mov eax,[_dc_colormap]
|
||||
|
||||
xor ebx,ebx
|
||||
shld ebx,edx,7 ; get address of first location
|
||||
call [scalecalls+4+ebp*4]
|
||||
|
||||
done:
|
||||
POPR
|
||||
ret
|
||||
|
||||
;============ HIGH DETAIL ============
|
||||
|
||||
SCALELABEL MACRO number
|
||||
vscale&number:
|
||||
ENDM
|
||||
|
||||
LINE = SCREENHEIGHT
|
||||
REPT SCREENHEIGHT-1
|
||||
SCALELABEL %LINE
|
||||
mov al,[esi+ebx] ; get source pixel
|
||||
add edx,ecx ; calculate next location
|
||||
mov al,[eax] ; translate the color
|
||||
; xor ebx,ebx
|
||||
; shld ebx,edx,7 ; get address of next location
|
||||
mov ebx,edx
|
||||
shr ebx,25
|
||||
mov [edi-(LINE-1)*SCREENWIDTH],al ; draw a pixel to the buffer
|
||||
LINE = LINE-1
|
||||
ENDM
|
||||
vscale1:
|
||||
mov al,[esi+ebx]
|
||||
mov al,[eax]
|
||||
mov [edi],al
|
||||
vscale0:
|
||||
ret
|
||||
|
||||
ENDP
|
||||
|
||||
|
||||
|
||||
;============================================================================
|
||||
;
|
||||
; unwound horizontal texture mapping code
|
||||
;
|
||||
; eax lighttable
|
||||
; ebx scratch register
|
||||
; ecx position 6.10 bits x, 6.10 bits y
|
||||
; edx step 6.10 bits x, 6.10 bits y
|
||||
; esi start of block
|
||||
; edi dest
|
||||
; ebp fff to mask bx
|
||||
;
|
||||
; ebp should by preset from ebx / ecx before calling
|
||||
;============================================================================
|
||||
|
||||
OP_SHLD = 0fh
|
||||
|
||||
|
||||
.DATA
|
||||
|
||||
|
||||
MAPDEFINE MACRO number
|
||||
dd hmap&number
|
||||
ENDM
|
||||
|
||||
ALIGN 4
|
||||
mapcalls LABEL
|
||||
LINE = 0
|
||||
REPT SCREENWIDTH+1
|
||||
MAPDEFINE %LINE
|
||||
LINE = LINE+1
|
||||
ENDM
|
||||
|
||||
|
||||
callpoint dd 0
|
||||
returnpoint dd 0
|
||||
|
||||
|
||||
.CODE
|
||||
|
||||
;================
|
||||
;
|
||||
; R_DrawSpan
|
||||
;
|
||||
; Horizontal texture mapping
|
||||
;
|
||||
;================
|
||||
|
||||
|
||||
PROC R_DrawSpan_
|
||||
PUBLIC R_DrawSpan_
|
||||
PUSHR
|
||||
|
||||
IFE SKIPPRIMITIVES
|
||||
|
||||
mov eax,[_ds_x1]
|
||||
mov ebx,[_ds_x2]
|
||||
mov eax,[mapcalls+eax*4]
|
||||
mov [callpoint],eax ; spot to jump into unwound
|
||||
mov eax,[mapcalls+4+ebx*4]
|
||||
mov [returnpoint],eax ; spot to patch a ret at
|
||||
mov BYTE PTR [eax], OP_RET
|
||||
|
||||
;
|
||||
; build composite position
|
||||
;
|
||||
mov ecx,[_ds_xfrac]
|
||||
shl ecx,10
|
||||
and ecx,0ffff0000h
|
||||
mov eax,[_ds_yfrac]
|
||||
shr eax,6
|
||||
and eax,0ffffh
|
||||
or ecx,eax
|
||||
|
||||
;
|
||||
; build composite step
|
||||
;
|
||||
mov edx,[_ds_xstep]
|
||||
shl edx,10
|
||||
and edx,0ffff0000h
|
||||
mov eax,[_ds_ystep]
|
||||
shr eax,6
|
||||
and eax,0ffffh
|
||||
or edx,eax
|
||||
|
||||
mov esi,[_ds_source]
|
||||
|
||||
mov edi,[_ds_y]
|
||||
mov edi,[_ylookup+edi*4]
|
||||
add edi,[_columnofs]
|
||||
|
||||
mov eax,[_ds_colormap]
|
||||
|
||||
;
|
||||
; feed the pipeline and jump in
|
||||
;
|
||||
mov ebp,0fffh ; used to mask off slop high bits from position
|
||||
shld ebx,ecx,22 ; shift y units in
|
||||
shld ebx,ecx,6 ; shift x units in
|
||||
and ebx,ebp ; mask off slop bits
|
||||
call [callpoint]
|
||||
|
||||
mov ebx,[returnpoint]
|
||||
mov BYTE PTR [ebx],OP_MOVAL ; remove the ret patched in
|
||||
|
||||
ENDIF
|
||||
POPR
|
||||
ret
|
||||
|
||||
|
||||
;============= HIGH DETAIL ============
|
||||
|
||||
.CODE
|
||||
|
||||
MAPLABEL MACRO number
|
||||
hmap&number:
|
||||
ENDM
|
||||
|
||||
LINE = 0
|
||||
PCOL = 0
|
||||
REPT SCREENWIDTH/4
|
||||
PLANE = 0
|
||||
REPT 4
|
||||
MAPLABEL %LINE
|
||||
LINE = LINE + 1
|
||||
|
||||
mov al,[esi+ebx] ; get source pixel
|
||||
shld ebx,ecx,22 ; shift y units in
|
||||
shld ebx,ecx,6 ; shift x units in
|
||||
mov al,[eax] ; translate color
|
||||
and ebx,ebp ; mask off slop bits
|
||||
add ecx,edx ; position += step
|
||||
mov [edi+PLANE+PCOL*4],al ; write pixel
|
||||
PLANE = PLANE + 1
|
||||
ENDM
|
||||
PCOL = PCOL + 1
|
||||
ENDM
|
||||
hmap320:
|
||||
ret
|
||||
|
||||
ENDP
|
||||
|
||||
END
|
2
Heretic Source/MAKE.BAT
Normal file
2
Heretic Source/MAKE.BAT
Normal file
|
@ -0,0 +1,2 @@
|
|||
@echo off
|
||||
wmake %1 %2 %3 %4 %5 %6 %7 %8 %9
|
95
Heretic Source/MAKEFILE
Normal file
95
Heretic Source/MAKEFILE
Normal file
|
@ -0,0 +1,95 @@
|
|||
|
||||
# TIC.EXE and HERETIC.EXE makefile
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
#
|
||||
# 4r use 80486 timings and register argument passing
|
||||
# c compile only
|
||||
# d1 include line number debugging information
|
||||
# d2 include full sybolic debugging information
|
||||
# ei force enums to be of type int
|
||||
# j change char default from unsigned to signed
|
||||
# oa relax aliasing checking
|
||||
# od do not optimize
|
||||
# oe[=#] expand functions inline, # = quads (default 20)
|
||||
# oi use the inline library functions
|
||||
# om generate inline 80x87 code for math functions
|
||||
# ot optimize for time
|
||||
# ox maximum optimization
|
||||
# s remove stack overflow checks
|
||||
# zp1 align structures on bytes
|
||||
# zq use quiet mode
|
||||
# /i=dir add include directories
|
||||
#
|
||||
# --------------------------------------------------------------------------
|
||||
|
||||
CCOPTS = /d2 /omaxet /zp1 /4r /ei /j /zq /i=dmx
|
||||
|
||||
LOCOBJS = &
|
||||
i_cyber.obj &
|
||||
i_ibm_a.obj &
|
||||
i_sound.obj &
|
||||
linear.obj
|
||||
|
||||
GLOBOBJS = &
|
||||
am_map.obj &
|
||||
ct_chat.obj &
|
||||
d_main.obj &
|
||||
d_net.obj &
|
||||
g_game.obj &
|
||||
f_finale.obj &
|
||||
info.obj &
|
||||
in_lude.obj &
|
||||
mn_menu.obj &
|
||||
m_misc.obj &
|
||||
p_ceilng.obj &
|
||||
p_doors.obj &
|
||||
p_enemy.obj &
|
||||
p_floor.obj &
|
||||
p_inter.obj &
|
||||
p_lights.obj &
|
||||
p_map.obj &
|
||||
p_maputl.obj &
|
||||
p_mobj.obj &
|
||||
p_plats.obj &
|
||||
p_pspr.obj &
|
||||
p_setup.obj &
|
||||
p_sight.obj &
|
||||
p_spec.obj &
|
||||
p_switch.obj &
|
||||
p_telept.obj &
|
||||
p_tick.obj &
|
||||
p_user.obj &
|
||||
r_bsp.obj &
|
||||
r_data.obj &
|
||||
r_draw.obj &
|
||||
r_main.obj &
|
||||
r_plane.obj &
|
||||
r_segs.obj &
|
||||
r_things.obj &
|
||||
sb_bar.obj &
|
||||
sounds.obj &
|
||||
tables.obj &
|
||||
v_video.obj &
|
||||
w_wad.obj &
|
||||
z_zone.obj
|
||||
|
||||
tic.exe : $(LOCOBJS) $(GLOBOBJS) i_ibm.obj
|
||||
wlink @tic.lnk
|
||||
copy tic.exe striptic.exe
|
||||
wstrip striptic.exe
|
||||
4gwbind 4gwpro.exe striptic.exe heretic.exe -V
|
||||
prsucc
|
||||
|
||||
i_ibm.obj:
|
||||
wcc386 /zp1 /4r /zq /ei /j i_ibm.c
|
||||
|
||||
.c.obj :
|
||||
wcc386 $(CCOPTS) $[*
|
||||
|
||||
.asm.obj :
|
||||
tasm /mx $[*
|
||||
|
||||
clean : .SYMBOLIC
|
||||
del *.obj
|
||||
del tic.exe
|
1588
Heretic Source/MN_MENU.C
Normal file
1588
Heretic Source/MN_MENU.C
Normal file
File diff suppressed because it is too large
Load diff
798
Heretic Source/M_MISC.C
Normal file
798
Heretic Source/M_MISC.C
Normal file
|
@ -0,0 +1,798 @@
|
|||
|
||||
// M_misc.c
|
||||
|
||||
#ifdef __NeXT__
|
||||
#include <libc.h>
|
||||
#else
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <direct.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
#include "DoomDef.h"
|
||||
#include "soundst.h"
|
||||
|
||||
int myargc;
|
||||
char **myargv;
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// FUNC M_ValidEpisodeMap
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
boolean M_ValidEpisodeMap(int episode, int map)
|
||||
{
|
||||
if(episode < 1 || map < 1 || map > 9)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if(shareware)
|
||||
{ // Shareware version checks
|
||||
if(episode != 1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if(ExtendedWAD)
|
||||
{ // Extended version checks
|
||||
if(episode == 6)
|
||||
{
|
||||
if(map > 3)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if(episode > 5)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // Registered version checks
|
||||
if(episode == 4)
|
||||
{
|
||||
if(map != 1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if(episode > 3)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
=
|
||||
= M_CheckParm
|
||||
=
|
||||
= Checks for the given parameter in the program's command line arguments
|
||||
=
|
||||
= Returns the argument number (1 to argc-1) or 0 if not present
|
||||
=
|
||||
=================
|
||||
*/
|
||||
|
||||
int M_CheckParm (char *check)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 1;i<myargc;i++)
|
||||
{
|
||||
if ( !strcasecmp(check, myargv[i]) )
|
||||
return i;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
===============
|
||||
=
|
||||
= M_Random
|
||||
=
|
||||
= Returns a 0-255 number
|
||||
=
|
||||
===============
|
||||
*/
|
||||
|
||||
unsigned char rndtable[256] = {
|
||||
0, 8, 109, 220, 222, 241, 149, 107, 75, 248, 254, 140, 16, 66,
|
||||
74, 21, 211, 47, 80, 242, 154, 27, 205, 128, 161, 89, 77, 36,
|
||||
95, 110, 85, 48, 212, 140, 211, 249, 22, 79, 200, 50, 28, 188,
|
||||
52, 140, 202, 120, 68, 145, 62, 70, 184, 190, 91, 197, 152, 224,
|
||||
149, 104, 25, 178, 252, 182, 202, 182, 141, 197, 4, 81, 181, 242,
|
||||
145, 42, 39, 227, 156, 198, 225, 193, 219, 93, 122, 175, 249, 0,
|
||||
175, 143, 70, 239, 46, 246, 163, 53, 163, 109, 168, 135, 2, 235,
|
||||
25, 92, 20, 145, 138, 77, 69, 166, 78, 176, 173, 212, 166, 113,
|
||||
94, 161, 41, 50, 239, 49, 111, 164, 70, 60, 2, 37, 171, 75,
|
||||
136, 156, 11, 56, 42, 146, 138, 229, 73, 146, 77, 61, 98, 196,
|
||||
135, 106, 63, 197, 195, 86, 96, 203, 113, 101, 170, 247, 181, 113,
|
||||
80, 250, 108, 7, 255, 237, 129, 226, 79, 107, 112, 166, 103, 241,
|
||||
24, 223, 239, 120, 198, 58, 60, 82, 128, 3, 184, 66, 143, 224,
|
||||
145, 224, 81, 206, 163, 45, 63, 90, 168, 114, 59, 33, 159, 95,
|
||||
28, 139, 123, 98, 125, 196, 15, 70, 194, 253, 54, 14, 109, 226,
|
||||
71, 17, 161, 93, 186, 87, 244, 138, 20, 52, 123, 251, 26, 36,
|
||||
17, 46, 52, 231, 232, 76, 31, 221, 84, 37, 216, 165, 212, 106,
|
||||
197, 242, 98, 43, 39, 175, 254, 145, 190, 84, 118, 222, 187, 136,
|
||||
120, 163, 236, 249
|
||||
};
|
||||
int rndindex = 0;
|
||||
int prndindex = 0;
|
||||
|
||||
int P_Random (void)
|
||||
{
|
||||
prndindex = (prndindex+1)&0xff;
|
||||
return rndtable[prndindex];
|
||||
}
|
||||
|
||||
int M_Random (void)
|
||||
{
|
||||
rndindex = (rndindex+1)&0xff;
|
||||
return rndtable[rndindex];
|
||||
}
|
||||
|
||||
void M_ClearRandom (void)
|
||||
{
|
||||
rndindex = prndindex = 0;
|
||||
}
|
||||
|
||||
|
||||
void M_ClearBox (fixed_t *box)
|
||||
{
|
||||
box[BOXTOP] = box[BOXRIGHT] = MININT;
|
||||
box[BOXBOTTOM] = box[BOXLEFT] = MAXINT;
|
||||
}
|
||||
|
||||
void M_AddToBox (fixed_t *box, fixed_t x, fixed_t y)
|
||||
{
|
||||
if (x<box[BOXLEFT])
|
||||
box[BOXLEFT] = x;
|
||||
else if (x>box[BOXRIGHT])
|
||||
box[BOXRIGHT] = x;
|
||||
if (y<box[BOXBOTTOM])
|
||||
box[BOXBOTTOM] = y;
|
||||
else if (y>box[BOXTOP])
|
||||
box[BOXTOP] = y;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
==================
|
||||
=
|
||||
= M_WriteFile
|
||||
=
|
||||
==================
|
||||
*/
|
||||
|
||||
#ifndef O_BINARY
|
||||
#define O_BINARY 0
|
||||
#endif
|
||||
|
||||
boolean M_WriteFile (char const *name, void *source, int length)
|
||||
{
|
||||
int handle, count;
|
||||
|
||||
handle = open (name, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666);
|
||||
if (handle == -1)
|
||||
return false;
|
||||
count = write (handle, source, length);
|
||||
close (handle);
|
||||
|
||||
if (count < length)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
==================
|
||||
=
|
||||
= M_ReadFile
|
||||
=
|
||||
==================
|
||||
*/
|
||||
|
||||
int M_ReadFile (char const *name, byte **buffer)
|
||||
{
|
||||
int handle, count, length;
|
||||
struct stat fileinfo;
|
||||
byte *buf;
|
||||
|
||||
handle = open (name, O_RDONLY | O_BINARY, 0666);
|
||||
if (handle == -1)
|
||||
I_Error ("Couldn't read file %s", name);
|
||||
if (fstat (handle,&fileinfo) == -1)
|
||||
I_Error ("Couldn't read file %s", name);
|
||||
length = fileinfo.st_size;
|
||||
buf = Z_Malloc (length, PU_STATIC, NULL);
|
||||
count = read (handle, buf, length);
|
||||
close (handle);
|
||||
|
||||
if (count < length)
|
||||
I_Error ("Couldn't read file %s", name);
|
||||
|
||||
*buffer = buf;
|
||||
return length;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// PROC M_FindResponseFile
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
#define MAXARGVS 100
|
||||
|
||||
void M_FindResponseFile(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i = 1; i < myargc; i++)
|
||||
{
|
||||
if(myargv[i][0] == '@')
|
||||
{
|
||||
FILE *handle;
|
||||
int size;
|
||||
int k;
|
||||
int index;
|
||||
int indexinfile;
|
||||
char *infile;
|
||||
char *file;
|
||||
char *moreargs[20];
|
||||
char *firstargv;
|
||||
|
||||
// READ THE RESPONSE FILE INTO MEMORY
|
||||
handle = fopen(&myargv[i][1], "rb");
|
||||
if(!handle)
|
||||
{
|
||||
printf("\nNo such response file!");
|
||||
exit(1);
|
||||
}
|
||||
printf("Found response file %s!\n",&myargv[i][1]);
|
||||
fseek (handle,0,SEEK_END);
|
||||
size = ftell(handle);
|
||||
fseek (handle,0,SEEK_SET);
|
||||
file = malloc (size);
|
||||
fread (file,size,1,handle);
|
||||
fclose (handle);
|
||||
|
||||
// KEEP ALL CMDLINE ARGS FOLLOWING @RESPONSEFILE ARG
|
||||
for (index = 0,k = i+1; k < myargc; k++)
|
||||
moreargs[index++] = myargv[k];
|
||||
|
||||
firstargv = myargv[0];
|
||||
myargv = malloc(sizeof(char *)*MAXARGVS);
|
||||
memset(myargv,0,sizeof(char *)*MAXARGVS);
|
||||
myargv[0] = firstargv;
|
||||
|
||||
infile = file;
|
||||
indexinfile = k = 0;
|
||||
indexinfile++; // SKIP PAST ARGV[0] (KEEP IT)
|
||||
do
|
||||
{
|
||||
myargv[indexinfile++] = infile+k;
|
||||
while(k < size &&
|
||||
|
||||
((*(infile+k)>= ' '+1) && (*(infile+k)<='z')))
|
||||
k++;
|
||||
*(infile+k) = 0;
|
||||
while(k < size &&
|
||||
((*(infile+k)<= ' ') || (*(infile+k)>'z')))
|
||||
k++;
|
||||
} while(k < size);
|
||||
|
||||
for (k = 0;k < index;k++)
|
||||
myargv[indexinfile++] = moreargs[k];
|
||||
myargc = indexinfile;
|
||||
// DISPLAY ARGS
|
||||
if(M_CheckParm("-debug"))
|
||||
{
|
||||
printf("%d command-line args:\n", myargc);
|
||||
for(k = 1; k < myargc; k++)
|
||||
{
|
||||
printf("%s\n", myargv[k]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// PROC M_ForceUppercase
|
||||
//
|
||||
// Change string to uppercase.
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void M_ForceUppercase(char *text)
|
||||
{
|
||||
char c;
|
||||
|
||||
while((c = *text) != 0)
|
||||
{
|
||||
if(c >= 'a' && c <= 'z')
|
||||
{
|
||||
*text++ = c-('a'-'A');
|
||||
}
|
||||
else
|
||||
{
|
||||
text++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
DEFAULTS
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
int usemouse;
|
||||
int usejoystick;
|
||||
|
||||
extern int key_right, key_left, key_up, key_down;
|
||||
extern int key_strafeleft, key_straferight;
|
||||
extern int key_fire, key_use, key_strafe, key_speed;
|
||||
extern int key_flyup, key_flydown, key_flycenter;
|
||||
extern int key_lookup, key_lookdown, key_lookcenter;
|
||||
extern int key_invleft, key_invright, key_useartifact;
|
||||
|
||||
extern int mousebfire;
|
||||
extern int mousebstrafe;
|
||||
extern int mousebforward;
|
||||
|
||||
extern int joybfire;
|
||||
extern int joybstrafe;
|
||||
extern int joybuse;
|
||||
extern int joybspeed;
|
||||
|
||||
extern int viewwidth, viewheight;
|
||||
|
||||
int mouseSensitivity;
|
||||
|
||||
extern int screenblocks;
|
||||
|
||||
extern char *chat_macros[10];
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char *name;
|
||||
int *location;
|
||||
int defaultvalue;
|
||||
int scantranslate; // PC scan code hack
|
||||
int untranslated; // lousy hack
|
||||
} default_t;
|
||||
|
||||
#ifndef __NeXT__
|
||||
extern int snd_Channels;
|
||||
extern int snd_DesiredMusicDevice, snd_DesiredSfxDevice;
|
||||
extern int snd_MusicDevice, // current music card # (index to dmxCodes)
|
||||
snd_SfxDevice; // current sfx card # (index to dmxCodes)
|
||||
|
||||
extern int snd_SBport, snd_SBirq, snd_SBdma; // sound blaster variables
|
||||
extern int snd_Mport; // midi variables
|
||||
#endif
|
||||
|
||||
default_t defaults[] =
|
||||
{
|
||||
{ "mouse_sensitivity", &mouseSensitivity, 5 },
|
||||
|
||||
#ifndef __NeXT__
|
||||
{ "sfx_volume", &snd_MaxVolume, 10},
|
||||
{ "music_volume", &snd_MusicVolume, 10},
|
||||
#endif
|
||||
|
||||
#ifdef __WATCOMC__
|
||||
#define SC_UPARROW 0x48
|
||||
#define SC_DOWNARROW 0x50
|
||||
#define SC_LEFTARROW 0x4b
|
||||
#define SC_RIGHTARROW 0x4d
|
||||
#define SC_RCTRL 0x1d
|
||||
#define SC_RALT 0x38
|
||||
#define SC_RSHIFT 0x36
|
||||
#define SC_SPACE 0x39
|
||||
#define SC_COMMA 0x33
|
||||
#define SC_PERIOD 0x34
|
||||
#define SC_PAGEUP 0x49
|
||||
#define SC_INSERT 0x52
|
||||
#define SC_HOME 0x47
|
||||
#define SC_PAGEDOWN 0x51
|
||||
#define SC_DELETE 0x53
|
||||
#define SC_END 0x4f
|
||||
#define SC_ENTER 0x1c
|
||||
|
||||
{ "key_right", &key_right, SC_RIGHTARROW, 1 },
|
||||
{ "key_left", &key_left, SC_LEFTARROW, 1 },
|
||||
{ "key_up", &key_up, SC_UPARROW, 1 },
|
||||
{ "key_down", &key_down, SC_DOWNARROW, 1 },
|
||||
{ "key_strafeleft", &key_strafeleft, SC_COMMA, 1 },
|
||||
{ "key_straferight", &key_straferight, SC_PERIOD, 1 },
|
||||
{ "key_flyup", &key_flyup, SC_PAGEUP, 1 },
|
||||
{ "key_flydown", &key_flydown, SC_INSERT, 1 },
|
||||
{ "key_flycenter", &key_flycenter, SC_HOME, 1 },
|
||||
{ "key_lookup", &key_lookup, SC_PAGEDOWN, 1 },
|
||||
{ "key_lookdown", &key_lookdown, SC_DELETE, 1 },
|
||||
{ "key_lookcenter", &key_lookcenter, SC_END, 1 },
|
||||
{ "key_invleft", &key_invleft, 0x1a, 1 },
|
||||
{ "key_invright", &key_invright, 0x1b, 1 },
|
||||
{ "key_useartifact", &key_useartifact, SC_ENTER, 1 },
|
||||
|
||||
{ "key_fire", &key_fire, SC_RCTRL, 1 },
|
||||
{ "key_use", &key_use, SC_SPACE, 1 },
|
||||
{ "key_strafe", &key_strafe, SC_RALT, 1 },
|
||||
{ "key_speed", &key_speed, SC_RSHIFT, 1 },
|
||||
#endif
|
||||
|
||||
#ifdef __NeXT__
|
||||
{ "key_right", &key_right, KEY_RIGHTARROW },
|
||||
{ "key_left", &key_left, KEY_LEFTARROW },
|
||||
{ "key_up", &key_up, KEY_UPARROW },
|
||||
{ "key_down", &key_down, KEY_DOWNARROW },
|
||||
{ "key_strafeleft", &key_strafeleft, ',' },
|
||||
{ "key_straferight", &key_straferight, '.' },
|
||||
{ "key_flyup", &key_flyup, 'u' },
|
||||
{ "key_flydown", &key_flydown, 'j' },
|
||||
{ "key_flycenter", &key_flycenter, 'k' },
|
||||
{ "key_lookup", &key_lookup, 'm' },
|
||||
{ "key_lookdown", &key_lookdown, 'b' },
|
||||
{ "key_lookcenter", &key_lookcenter, 'n' },
|
||||
{ "key_invleft", &key_invleft, '[' },
|
||||
{ "key_invright", &key_invright, ']' },
|
||||
{ "key_useartifact", &key_useartifact, 13 },
|
||||
|
||||
{ "key_fire", &key_fire, ' ', 1 },
|
||||
{ "key_use", &key_use, 'x', 1 },
|
||||
{ "key_strafe", &key_strafe, 'c', 1 },
|
||||
{ "key_speed", &key_speed, 'z', 1 },
|
||||
#endif
|
||||
|
||||
{ "use_mouse", &usemouse, 1 },
|
||||
{ "mouseb_fire", &mousebfire, 0 },
|
||||
{ "mouseb_strafe", &mousebstrafe, 1 },
|
||||
{ "mouseb_forward", &mousebforward, 2 },
|
||||
|
||||
{ "use_joystick", &usejoystick, 0 },
|
||||
{ "joyb_fire", &joybfire, 0 },
|
||||
{ "joyb_strafe", &joybstrafe, 1 },
|
||||
{ "joyb_use", &joybuse, 3 },
|
||||
{ "joyb_speed", &joybspeed, 2 },
|
||||
|
||||
{ "screenblocks", &screenblocks, 10 },
|
||||
|
||||
#ifndef __NeXT__
|
||||
{ "snd_channels", &snd_Channels, 3 },
|
||||
{ "snd_musicdevice", &snd_DesiredMusicDevice, 0 },
|
||||
{ "snd_sfxdevice", &snd_DesiredSfxDevice, 0 },
|
||||
{ "snd_sbport", &snd_SBport, 544 },
|
||||
{ "snd_sbirq", &snd_SBirq, -1 },
|
||||
{ "snd_sbdma", &snd_SBdma, -1 },
|
||||
{ "snd_mport", &snd_Mport, -1 },
|
||||
#endif
|
||||
|
||||
{ "usegamma", &usegamma, 0 },
|
||||
|
||||
{ "chatmacro0", (int *) &chat_macros[0], (int) HUSTR_CHATMACRO0 },
|
||||
{ "chatmacro1", (int *) &chat_macros[1], (int) HUSTR_CHATMACRO1 },
|
||||
{ "chatmacro2", (int *) &chat_macros[2], (int) HUSTR_CHATMACRO2 },
|
||||
{ "chatmacro3", (int *) &chat_macros[3], (int) HUSTR_CHATMACRO3 },
|
||||
{ "chatmacro4", (int *) &chat_macros[4], (int) HUSTR_CHATMACRO4 },
|
||||
{ "chatmacro5", (int *) &chat_macros[5], (int) HUSTR_CHATMACRO5 },
|
||||
{ "chatmacro6", (int *) &chat_macros[6], (int) HUSTR_CHATMACRO6 },
|
||||
{ "chatmacro7", (int *) &chat_macros[7], (int) HUSTR_CHATMACRO7 },
|
||||
{ "chatmacro8", (int *) &chat_macros[8], (int) HUSTR_CHATMACRO8 },
|
||||
{ "chatmacro9", (int *) &chat_macros[9], (int) HUSTR_CHATMACRO9 }
|
||||
};
|
||||
|
||||
int numdefaults;
|
||||
char *defaultfile;
|
||||
|
||||
/*
|
||||
==============
|
||||
=
|
||||
= M_SaveDefaults
|
||||
=
|
||||
==============
|
||||
*/
|
||||
|
||||
void M_SaveDefaults (void)
|
||||
{
|
||||
int i,v;
|
||||
FILE *f;
|
||||
|
||||
f = fopen (defaultfile, "w");
|
||||
if (!f)
|
||||
return; // can't write the file, but don't complain
|
||||
|
||||
for (i=0 ; i<numdefaults ; i++)
|
||||
{
|
||||
#ifdef __WATCOMC__
|
||||
if (defaults[i].scantranslate)
|
||||
defaults[i].location = &defaults[i].untranslated;
|
||||
#endif
|
||||
if (defaults[i].defaultvalue > -0xfff
|
||||
&& defaults[i].defaultvalue < 0xfff)
|
||||
{
|
||||
v = *defaults[i].location;
|
||||
fprintf (f,"%s\t\t%i\n",defaults[i].name,v);
|
||||
} else {
|
||||
fprintf (f,"%s\t\t\"%s\"\n",defaults[i].name,
|
||||
* (char **) (defaults[i].location));
|
||||
}
|
||||
}
|
||||
|
||||
fclose (f);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
==============
|
||||
=
|
||||
= M_LoadDefaults
|
||||
=
|
||||
==============
|
||||
*/
|
||||
|
||||
extern byte scantokey[128];
|
||||
extern char *basedefault;
|
||||
|
||||
void M_LoadDefaults (void)
|
||||
{
|
||||
int i, len;
|
||||
FILE *f;
|
||||
char def[80];
|
||||
char strparm[100];
|
||||
char *newstring;
|
||||
int parm;
|
||||
boolean isstring;
|
||||
|
||||
//
|
||||
// set everything to base values
|
||||
//
|
||||
numdefaults = sizeof(defaults)/sizeof(defaults[0]);
|
||||
for (i=0 ; i<numdefaults ; i++)
|
||||
*defaults[i].location = defaults[i].defaultvalue;
|
||||
|
||||
//
|
||||
// check for a custom default file
|
||||
//
|
||||
i = M_CheckParm("-config");
|
||||
if(i && i<myargc-1)
|
||||
{
|
||||
defaultfile = myargv[i+1];
|
||||
printf("default file: %s\n", defaultfile);
|
||||
}
|
||||
else if(cdrom)
|
||||
{
|
||||
defaultfile = "c:\\heretic.cd\\heretic.cfg";
|
||||
}
|
||||
else
|
||||
{
|
||||
defaultfile = basedefault;
|
||||
}
|
||||
|
||||
//
|
||||
// read the file in, overriding any set defaults
|
||||
//
|
||||
f = fopen (defaultfile, "r");
|
||||
if (f)
|
||||
{
|
||||
while (!feof(f))
|
||||
{
|
||||
isstring = false;
|
||||
if (fscanf (f, "%79s %[^\n]\n", def, strparm) == 2)
|
||||
{
|
||||
if (strparm[0] == '"')
|
||||
{
|
||||
// get a string default
|
||||
isstring = true;
|
||||
len = strlen(strparm);
|
||||
newstring = (char *) malloc(len);
|
||||
strparm[len-1] = 0;
|
||||
strcpy(newstring, strparm+1);
|
||||
}
|
||||
else if (strparm[0] == '0' && strparm[1] == 'x')
|
||||
sscanf(strparm+2, "%x", &parm);
|
||||
else
|
||||
sscanf(strparm, "%i", &parm);
|
||||
for (i=0 ; i<numdefaults ; i++)
|
||||
if (!strcmp(def, defaults[i].name))
|
||||
{
|
||||
if (!isstring)
|
||||
*defaults[i].location = parm;
|
||||
else
|
||||
*defaults[i].location =
|
||||
(int) newstring;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fclose (f);
|
||||
}
|
||||
|
||||
|
||||
#ifdef __WATCOMC__
|
||||
for(i = 0; i < numdefaults; i++)
|
||||
{
|
||||
if(defaults[i].scantranslate)
|
||||
{
|
||||
parm = *defaults[i].location;
|
||||
defaults[i].untranslated = parm;
|
||||
*defaults[i].location = scantokey[parm];
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
SCREEN SHOTS
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char manufacturer;
|
||||
char version;
|
||||
char encoding;
|
||||
char bits_per_pixel;
|
||||
unsigned short xmin,ymin,xmax,ymax;
|
||||
unsigned short hres,vres;
|
||||
unsigned char palette[48];
|
||||
char reserved;
|
||||
char color_planes;
|
||||
unsigned short bytes_per_line;
|
||||
unsigned short palette_type;
|
||||
char filler[58];
|
||||
unsigned char data; // unbounded
|
||||
} pcx_t;
|
||||
|
||||
/*
|
||||
==============
|
||||
=
|
||||
= WritePCXfile
|
||||
=
|
||||
==============
|
||||
*/
|
||||
|
||||
void WritePCXfile (char *filename, byte *data, int width, int height, byte *palette)
|
||||
{
|
||||
int i, length;
|
||||
pcx_t *pcx;
|
||||
byte *pack;
|
||||
|
||||
pcx = Z_Malloc (width*height*2+1000, PU_STATIC, NULL);
|
||||
|
||||
pcx->manufacturer = 0x0a; // PCX id
|
||||
pcx->version = 5; // 256 color
|
||||
pcx->encoding = 1; // uncompressed
|
||||
pcx->bits_per_pixel = 8; // 256 color
|
||||
pcx->xmin = 0;
|
||||
pcx->ymin = 0;
|
||||
pcx->xmax = SHORT(width-1);
|
||||
pcx->ymax = SHORT(height-1);
|
||||
pcx->hres = SHORT(width);
|
||||
pcx->vres = SHORT(height);
|
||||
memset (pcx->palette,0,sizeof(pcx->palette));
|
||||
pcx->color_planes = 1; // chunky image
|
||||
pcx->bytes_per_line = SHORT(width);
|
||||
pcx->palette_type = SHORT(2); // not a grey scale
|
||||
memset (pcx->filler,0,sizeof(pcx->filler));
|
||||
|
||||
//
|
||||
// pack the image
|
||||
//
|
||||
pack = &pcx->data;
|
||||
|
||||
for (i=0 ; i<width*height ; i++)
|
||||
if ( (*data & 0xc0) != 0xc0)
|
||||
*pack++ = *data++;
|
||||
else
|
||||
{
|
||||
*pack++ = 0xc1;
|
||||
*pack++ = *data++;
|
||||
}
|
||||
|
||||
//
|
||||
// write the palette
|
||||
//
|
||||
*pack++ = 0x0c; // palette ID byte
|
||||
for (i=0 ; i<768 ; i++)
|
||||
*pack++ = *palette++;
|
||||
|
||||
//
|
||||
// write output file
|
||||
//
|
||||
length = pack - (byte *)pcx;
|
||||
M_WriteFile (filename, pcx, length);
|
||||
|
||||
Z_Free (pcx);
|
||||
}
|
||||
|
||||
|
||||
//==============================================================================
|
||||
|
||||
/*
|
||||
==================
|
||||
=
|
||||
= M_ScreenShot
|
||||
=
|
||||
==================
|
||||
*/
|
||||
|
||||
void M_ScreenShot (void)
|
||||
{
|
||||
int i;
|
||||
byte *linear;
|
||||
char lbmname[12];
|
||||
byte *pal;
|
||||
|
||||
#ifdef _WATCOMC_
|
||||
extern byte *pcscreen;
|
||||
#endif
|
||||
//
|
||||
// munge planar buffer to linear
|
||||
//
|
||||
#ifdef _WATCOMC_
|
||||
linear = pcscreen;
|
||||
#else
|
||||
linear = screen;
|
||||
#endif
|
||||
//
|
||||
// find a file name to save it to
|
||||
//
|
||||
strcpy(lbmname,"HRTIC00.pcx");
|
||||
|
||||
for (i=0 ; i<=99 ; i++)
|
||||
{
|
||||
lbmname[5] = i/10 + '0';
|
||||
lbmname[6] = i%10 + '0';
|
||||
if (access(lbmname,0) == -1)
|
||||
break; // file doesn't exist
|
||||
}
|
||||
if (i==100)
|
||||
I_Error ("M_ScreenShot: Couldn't create a PCX");
|
||||
|
||||
//
|
||||
// save the pcx file
|
||||
//
|
||||
#ifdef __WATCOMC__
|
||||
pal = (byte *)Z_Malloc(768, PU_STATIC, NULL);
|
||||
outp(0x3c7, 0);
|
||||
for(i = 0; i < 768; i++)
|
||||
{
|
||||
*(pal+i) = inp(0x3c9)<<2;
|
||||
}
|
||||
#else
|
||||
pal = (byte *)W_CacheLumpName("PLAYPAL", PU_CACHE);
|
||||
#endif
|
||||
|
||||
WritePCXfile (lbmname, linear, SCREENWIDTH, SCREENHEIGHT
|
||||
, pal);
|
||||
|
||||
players[consoleplayer].message = "SCREEN SHOT";
|
||||
#ifdef __WATCOMC__
|
||||
Z_Free(pal);
|
||||
#endif
|
||||
}
|
783
Heretic Source/NETOLD.C
Normal file
783
Heretic Source/NETOLD.C
Normal file
|
@ -0,0 +1,783 @@
|
|||
// I_pcnet.m
|
||||
|
||||
#include "DoomDef.h"
|
||||
#include "P_local.h"
|
||||
#include "soundst.h"
|
||||
|
||||
#define NCMD_EXIT 0x80000000
|
||||
#define NCMD_RETRANSMIT 0x40000000
|
||||
#define NCMD_SETUP 0x20000000
|
||||
#define NCMD_KILL 0x10000000 // kill game
|
||||
#define NCMD_CHECKSUM 0x0fffffff
|
||||
|
||||
|
||||
doomcom_t *doomcom;
|
||||
doomdata_t *netbuffer; // points inside doomcom
|
||||
|
||||
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
NETWORKING
|
||||
|
||||
gametic is the tic about to (or currently being) run
|
||||
maketic is the tick that hasn't had control made for it yet
|
||||
nettics[] has the maketics for all players
|
||||
|
||||
a gametic cannot be run until nettics[] > gametic for all players
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#define RESENDCOUNT 10
|
||||
#define PL_DRONE 0x80 // bit flag in doomdata->player
|
||||
|
||||
ticcmd_t localcmds[BACKUPTICS];
|
||||
|
||||
ticcmd_t netcmds[MAXPLAYERS][BACKUPTICS];
|
||||
int nettics[MAXNETNODES];
|
||||
boolean nodeingame[MAXNETNODES]; // set false as nodes leave game
|
||||
boolean remoteresend[MAXNETNODES]; // set when local needs tics
|
||||
int resendto[MAXNETNODES]; // set when remote needs tics
|
||||
int resendcount[MAXNETNODES];
|
||||
|
||||
int nodeforplayer[MAXPLAYERS];
|
||||
|
||||
int maketic;
|
||||
int lastnettic, skiptics;
|
||||
int ticdup;
|
||||
int maxsend; // BACKUPTICS/(2*ticdup)-1
|
||||
|
||||
void D_ProcessEvents (void);
|
||||
void G_BuildTiccmd (ticcmd_t *cmd);
|
||||
void D_DoAdvanceDemo (void);
|
||||
|
||||
boolean reboundpacket;
|
||||
doomdata_t reboundstore;
|
||||
|
||||
|
||||
int NetbufferSize (void)
|
||||
{
|
||||
return (int)&(((doomdata_t *)0)->cmds[netbuffer->numtics]);
|
||||
}
|
||||
|
||||
unsigned NetbufferChecksum (void)
|
||||
{
|
||||
unsigned c;
|
||||
int i,l;
|
||||
|
||||
c = 0x1234567;
|
||||
|
||||
#ifdef NeXT
|
||||
return 0; // byte order problems
|
||||
#endif
|
||||
|
||||
l = (NetbufferSize () - (int)&(((doomdata_t *)0)->retransmitfrom))/4;
|
||||
for (i=0 ; i<l ; i++)
|
||||
c += ((unsigned *)&netbuffer->retransmitfrom)[i] * (i+1);
|
||||
|
||||
return c & NCMD_CHECKSUM;
|
||||
}
|
||||
|
||||
int ExpandTics (int low)
|
||||
{
|
||||
int delta;
|
||||
|
||||
delta = low - (maketic&0xff);
|
||||
|
||||
if (delta >= -64 && delta <= 64)
|
||||
return (maketic&~0xff) + low;
|
||||
if (delta > 64)
|
||||
return (maketic&~0xff) - 256 + low;
|
||||
if (delta < -64)
|
||||
return (maketic&~0xff) + 256 + low;
|
||||
|
||||
I_Error ("ExpandTics: strange value %i at maketic %i",low,maketic);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
|
||||
|
||||
/*
|
||||
==============
|
||||
=
|
||||
= HSendPacket
|
||||
=
|
||||
==============
|
||||
*/
|
||||
|
||||
void HSendPacket (int node, int flags)
|
||||
{
|
||||
netbuffer->checksum = NetbufferChecksum () | flags;
|
||||
|
||||
if (!node)
|
||||
{
|
||||
reboundstore = *netbuffer;
|
||||
reboundpacket = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (demoplayback)
|
||||
return;
|
||||
|
||||
if (!netgame)
|
||||
I_Error ("Tried to transmit to another node");
|
||||
|
||||
doomcom->command = CMD_SEND;
|
||||
doomcom->remotenode = node;
|
||||
doomcom->datalength = NetbufferSize ();
|
||||
|
||||
if (debugfile)
|
||||
{
|
||||
int i;
|
||||
int realretrans;
|
||||
if (netbuffer->checksum & NCMD_RETRANSMIT)
|
||||
realretrans = ExpandTics (netbuffer->retransmitfrom);
|
||||
else
|
||||
realretrans = -1;
|
||||
fprintf (debugfile,"send (%i + %i, R %i) [%i] "
|
||||
,ExpandTics(netbuffer->starttic),netbuffer->numtics, realretrans, doomcom->datalength);
|
||||
for (i=0 ; i<doomcom->datalength ; i++)
|
||||
fprintf (debugfile,"%i ",((byte *)netbuffer)[i]);
|
||||
fprintf (debugfile,"\n");
|
||||
}
|
||||
|
||||
I_NetCmd ();
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
=
|
||||
= HGetPacket
|
||||
=
|
||||
= Returns false if no packet is waiting
|
||||
=
|
||||
==============
|
||||
*/
|
||||
|
||||
boolean HGetPacket (void)
|
||||
{
|
||||
if (reboundpacket)
|
||||
{
|
||||
*netbuffer = reboundstore;
|
||||
doomcom->remotenode = 0;
|
||||
reboundpacket = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!netgame)
|
||||
return false;
|
||||
if (demoplayback)
|
||||
return false;
|
||||
|
||||
doomcom->command = CMD_GET;
|
||||
I_NetCmd ();
|
||||
if (doomcom->remotenode == -1)
|
||||
return false;
|
||||
|
||||
if (doomcom->datalength != NetbufferSize ())
|
||||
{
|
||||
if (debugfile)
|
||||
fprintf (debugfile,"bad packet length %i\n",doomcom->datalength);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (NetbufferChecksum () != (netbuffer->checksum&NCMD_CHECKSUM) )
|
||||
{
|
||||
if (debugfile)
|
||||
fprintf (debugfile,"bad packet checksum\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (debugfile)
|
||||
{
|
||||
int realretrans;
|
||||
int i;
|
||||
|
||||
if (netbuffer->checksum & NCMD_SETUP)
|
||||
fprintf (debugfile,"setup packet\n");
|
||||
else
|
||||
{
|
||||
if (netbuffer->checksum & NCMD_RETRANSMIT)
|
||||
realretrans = ExpandTics (netbuffer->retransmitfrom);
|
||||
else
|
||||
realretrans = -1;
|
||||
fprintf (debugfile,"get %i = (%i + %i, R %i)[%i] ",doomcom->remotenode,
|
||||
ExpandTics(netbuffer->starttic),netbuffer->numtics, realretrans, doomcom->datalength);
|
||||
for (i=0 ; i<doomcom->datalength ; i++)
|
||||
fprintf (debugfile,"%i ",((byte *)netbuffer)[i]);
|
||||
fprintf (debugfile,"\n");
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===================
|
||||
=
|
||||
= GetPackets
|
||||
=
|
||||
===================
|
||||
*/
|
||||
|
||||
char exitmsg[80];
|
||||
|
||||
void GetPackets (void)
|
||||
{
|
||||
int netconsole;
|
||||
int netnode;
|
||||
ticcmd_t *src, *dest;
|
||||
int realend;
|
||||
int realstart;
|
||||
|
||||
while (HGetPacket ())
|
||||
{
|
||||
if (netbuffer->checksum & NCMD_SETUP)
|
||||
continue; // extra setup packet
|
||||
|
||||
netconsole = netbuffer->player & ~PL_DRONE;
|
||||
netnode = doomcom->remotenode;
|
||||
//
|
||||
// to save bytes, only the low byte of tic numbers are sent
|
||||
// Figure out what the rest of the bytes are
|
||||
//
|
||||
realstart = ExpandTics (netbuffer->starttic);
|
||||
realend = (realstart+netbuffer->numtics);
|
||||
|
||||
//
|
||||
// check for exiting the game
|
||||
//
|
||||
if (netbuffer->checksum & NCMD_EXIT)
|
||||
{
|
||||
if (!nodeingame[netnode])
|
||||
continue;
|
||||
nodeingame[netnode] = false;
|
||||
playeringame[netconsole] = false;
|
||||
strcpy(exitmsg, "PLAYER 1 LEFT THE GAME");
|
||||
S_StartSound(NULL, sfx_chat);
|
||||
exitmsg[7] += netconsole;
|
||||
//players[consoleplayer].message = exitmsg;
|
||||
P_SetMessage(&players[consoleplayer], exitmsg, true);
|
||||
/* if (demorecording)
|
||||
G_CheckDemoStatus ();
|
||||
*/ // DEBUG
|
||||
continue;
|
||||
}
|
||||
|
||||
//
|
||||
// check for a remote game kill
|
||||
//
|
||||
if (netbuffer->checksum & NCMD_KILL)
|
||||
I_Error ("Killed by network driver");
|
||||
|
||||
nodeforplayer[netconsole] = netnode;
|
||||
|
||||
//
|
||||
// check for retransmit request
|
||||
//
|
||||
if ( resendcount[netnode] <= 0
|
||||
&& (netbuffer->checksum & NCMD_RETRANSMIT) )
|
||||
{
|
||||
resendto[netnode] = ExpandTics(netbuffer->retransmitfrom);
|
||||
if (debugfile)
|
||||
fprintf (debugfile,"retransmit from %i\n", resendto[netnode]);
|
||||
resendcount[netnode] = RESENDCOUNT;
|
||||
}
|
||||
else
|
||||
resendcount[netnode]--;
|
||||
|
||||
//
|
||||
// check for out of order / duplicated packet
|
||||
//
|
||||
if (realend == nettics[netnode])
|
||||
continue;
|
||||
|
||||
if (realend < nettics[netnode])
|
||||
{
|
||||
if (debugfile)
|
||||
fprintf (debugfile,"out of order packet (%i + %i)\n" ,realstart,netbuffer->numtics);
|
||||
continue;
|
||||
}
|
||||
|
||||
//
|
||||
// check for a missed packet
|
||||
//
|
||||
if (realstart > nettics[netnode])
|
||||
{
|
||||
// stop processing until the other system resends the missed tics
|
||||
if (debugfile)
|
||||
fprintf (debugfile,"missed tics from %i (%i - %i)\n", netnode, realstart, nettics[netnode]);
|
||||
remoteresend[netnode] = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
//
|
||||
// update command store from the packet
|
||||
//
|
||||
{
|
||||
int start;
|
||||
|
||||
remoteresend[netnode] = false;
|
||||
|
||||
start = nettics[netnode] - realstart;
|
||||
src = &netbuffer->cmds[start];
|
||||
|
||||
while (nettics[netnode] < realend)
|
||||
{
|
||||
dest = &netcmds[netconsole][nettics[netnode]%BACKUPTICS];
|
||||
nettics[netnode]++;
|
||||
*dest = *src;
|
||||
src++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
=
|
||||
= NetUpdate
|
||||
=
|
||||
= Builds ticcmds for console player
|
||||
= sends out a packet
|
||||
=============
|
||||
*/
|
||||
|
||||
int gametime;
|
||||
|
||||
void NetUpdate (void)
|
||||
{
|
||||
int nowtime;
|
||||
int newtics;
|
||||
int i,j;
|
||||
int realstart;
|
||||
int gameticdiv;
|
||||
|
||||
//
|
||||
// check time
|
||||
//
|
||||
nowtime = I_GetTime ()/ticdup;
|
||||
newtics = nowtime - gametime;
|
||||
gametime = nowtime;
|
||||
|
||||
if (newtics <= 0) // nothing new to update
|
||||
goto listen;
|
||||
|
||||
if (skiptics <= newtics)
|
||||
{
|
||||
newtics -= skiptics;
|
||||
skiptics = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
skiptics -= newtics;
|
||||
newtics = 0;
|
||||
}
|
||||
|
||||
|
||||
netbuffer->player = consoleplayer;
|
||||
|
||||
//
|
||||
// build new ticcmds for console player
|
||||
//
|
||||
gameticdiv = gametic/ticdup;
|
||||
for (i=0 ; i<newtics ; i++)
|
||||
{
|
||||
I_StartTic ();
|
||||
D_ProcessEvents ();
|
||||
if (maketic - gameticdiv >= BACKUPTICS/2-1)
|
||||
break; // can't hold any more
|
||||
//printf ("mk:%i ",maketic);
|
||||
G_BuildTiccmd (&localcmds[maketic%BACKUPTICS]);
|
||||
maketic++;
|
||||
}
|
||||
|
||||
|
||||
if (singletics)
|
||||
return; // singletic update is syncronous
|
||||
|
||||
//
|
||||
// send the packet to the other nodes
|
||||
//
|
||||
for (i=0 ; i<doomcom->numnodes ; i++)
|
||||
if (nodeingame[i])
|
||||
{
|
||||
netbuffer->starttic = realstart = resendto[i];
|
||||
netbuffer->numtics = maketic - realstart;
|
||||
if (netbuffer->numtics > BACKUPTICS)
|
||||
I_Error ("NetUpdate: netbuffer->numtics > BACKUPTICS");
|
||||
|
||||
resendto[i] = maketic - doomcom->extratics;
|
||||
|
||||
|
||||
for (j=0 ; j< netbuffer->numtics ; j++)
|
||||
netbuffer->cmds[j] =
|
||||
localcmds[(realstart+j)%BACKUPTICS];
|
||||
|
||||
if (remoteresend[i])
|
||||
{
|
||||
netbuffer->retransmitfrom = nettics[i];
|
||||
HSendPacket (i, NCMD_RETRANSMIT);
|
||||
}
|
||||
else
|
||||
{
|
||||
netbuffer->retransmitfrom = 0;
|
||||
HSendPacket (i, 0);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// listen for other packets
|
||||
//
|
||||
listen:
|
||||
|
||||
GetPackets ();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=====================
|
||||
=
|
||||
= CheckAbort
|
||||
=
|
||||
=====================
|
||||
*/
|
||||
|
||||
void CheckAbort (void)
|
||||
{
|
||||
event_t *ev;
|
||||
int stoptic;
|
||||
|
||||
stoptic = I_GetTime () + 2;
|
||||
while (I_GetTime() < stoptic)
|
||||
I_StartTic ();
|
||||
|
||||
I_StartTic ();
|
||||
for ( ; eventtail != eventhead
|
||||
; eventtail = (++eventtail)&(MAXEVENTS-1) )
|
||||
{
|
||||
ev = &events[eventtail];
|
||||
if (ev->type == ev_keydown && ev->data1 == KEY_ESCAPE)
|
||||
I_Error ("Network game synchronization aborted.");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=====================
|
||||
=
|
||||
= D_ArbitrateNetStart
|
||||
=
|
||||
=====================
|
||||
*/
|
||||
|
||||
void D_ArbitrateNetStart (void)
|
||||
{
|
||||
int i;
|
||||
boolean gotinfo[MAXNETNODES];
|
||||
|
||||
autostart = true;
|
||||
memset (gotinfo,0,sizeof(gotinfo));
|
||||
|
||||
if (doomcom->consoleplayer)
|
||||
{ // listen for setup info from key player
|
||||
while (1)
|
||||
{
|
||||
CheckAbort ();
|
||||
if (!HGetPacket ())
|
||||
continue;
|
||||
if (netbuffer->checksum & NCMD_SETUP)
|
||||
{
|
||||
if (netbuffer->player != VERSION)
|
||||
I_Error ("Different DOOM versions cannot play a net game!");
|
||||
startskill = netbuffer->retransmitfrom & 15;
|
||||
deathmatch = (netbuffer->retransmitfrom & 0xc0) >> 6;
|
||||
nomonsters = (netbuffer->retransmitfrom & 0x20) > 0;
|
||||
respawnparm = (netbuffer->retransmitfrom & 0x10) > 0;
|
||||
startmap = netbuffer->starttic & 0x3f;
|
||||
startepisode = netbuffer->starttic >> 6;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // key player, send the setup info
|
||||
do
|
||||
{
|
||||
CheckAbort ();
|
||||
for (i=0 ; i<doomcom->numnodes ; i++)
|
||||
{
|
||||
netbuffer->retransmitfrom = startskill;
|
||||
if (deathmatch)
|
||||
netbuffer->retransmitfrom |= (deathmatch<<6);
|
||||
if (nomonsters)
|
||||
netbuffer->retransmitfrom |= 0x20;
|
||||
if (respawnparm)
|
||||
netbuffer->retransmitfrom |= 0x10;
|
||||
netbuffer->starttic = startepisode * 64 + startmap;
|
||||
netbuffer->player = VERSION;
|
||||
netbuffer->numtics = 0;
|
||||
HSendPacket (i, NCMD_SETUP);
|
||||
}
|
||||
|
||||
#if 1
|
||||
for(i = 10 ; i && HGetPacket(); --i)
|
||||
{
|
||||
if((netbuffer->player&0x7f) < MAXNETNODES)
|
||||
gotinfo[netbuffer->player&0x7f] = true;
|
||||
}
|
||||
#else
|
||||
while (HGetPacket ())
|
||||
{
|
||||
gotinfo[netbuffer->player&0x7f] = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
for (i=1 ; i<doomcom->numnodes ; i++)
|
||||
if (!gotinfo[i])
|
||||
break;
|
||||
} while (i < doomcom->numnodes);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
===================
|
||||
=
|
||||
= D_CheckNetGame
|
||||
=
|
||||
= Works out player numbers among the net participants
|
||||
===================
|
||||
*/
|
||||
|
||||
extern int viewangleoffset;
|
||||
|
||||
void D_CheckNetGame (void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0 ; i<MAXNETNODES ; i++)
|
||||
{
|
||||
nodeingame[i] = false;
|
||||
nettics[i] = 0;
|
||||
remoteresend[i] = false; // set when local needs tics
|
||||
resendto[i] = 0; // which tic to start sending
|
||||
}
|
||||
|
||||
// I_InitNetwork sets doomcom and netgame
|
||||
I_InitNetwork ();
|
||||
if (doomcom->id != DOOMCOM_ID)
|
||||
I_Error ("Doomcom buffer invalid!");
|
||||
netbuffer = &doomcom->data;
|
||||
consoleplayer = displayplayer = doomcom->consoleplayer;
|
||||
if (netgame)
|
||||
D_ArbitrateNetStart ();
|
||||
//printf ("startskill %i deathmatch: %i startmap: %i startepisode: %i\n", startskill, deathmatch, startmap, startepisode);
|
||||
|
||||
// read values out of doomcom
|
||||
ticdup = doomcom->ticdup;
|
||||
maxsend = BACKUPTICS/2-1;
|
||||
if (maxsend<1)
|
||||
maxsend = 1;
|
||||
|
||||
for (i=0 ; i<doomcom->numplayers ; i++)
|
||||
playeringame[i] = true;
|
||||
for (i=0 ; i<doomcom->numnodes ; i++)
|
||||
nodeingame[i] = true;
|
||||
|
||||
//printf ("player %i of %i (%i nodes)\n", consoleplayer+1, doomcom->numplayers, doomcom->numnodes);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
=
|
||||
= D_QuitNetGame
|
||||
=
|
||||
= Called before quitting to leave a net game without hanging the
|
||||
= other players
|
||||
=
|
||||
==================
|
||||
*/
|
||||
|
||||
void D_QuitNetGame (void)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
if (debugfile)
|
||||
fclose (debugfile);
|
||||
|
||||
if (!netgame || !usergame || consoleplayer == -1 || demoplayback)
|
||||
return;
|
||||
|
||||
// send a bunch of packets for security
|
||||
netbuffer->player = consoleplayer;
|
||||
netbuffer->numtics = 0;
|
||||
for (i=0 ; i<4 ; i++)
|
||||
{
|
||||
for (j=1 ; j<doomcom->numnodes ; j++)
|
||||
if (nodeingame[j])
|
||||
HSendPacket (j, NCMD_EXIT);
|
||||
I_WaitVBL (1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
===============
|
||||
=
|
||||
= TryRunTics
|
||||
=
|
||||
===============
|
||||
*/
|
||||
|
||||
int frametics[4], frameon;
|
||||
int frameskip[4];
|
||||
int oldnettics;
|
||||
extern boolean advancedemo;
|
||||
|
||||
void TryRunTics (void)
|
||||
{
|
||||
int i;
|
||||
int lowtic;
|
||||
int entertic;
|
||||
static int oldentertics;
|
||||
int realtics, availabletics;
|
||||
int counts;
|
||||
int numplaying;
|
||||
|
||||
//
|
||||
// get real tics
|
||||
//
|
||||
entertic = I_GetTime ()/ticdup;
|
||||
realtics = entertic - oldentertics;
|
||||
oldentertics = entertic;
|
||||
|
||||
//
|
||||
// get available tics
|
||||
//
|
||||
NetUpdate ();
|
||||
|
||||
lowtic = MAXINT;
|
||||
numplaying = 0;
|
||||
for (i=0 ; i<doomcom->numnodes ; i++)
|
||||
if (nodeingame[i])
|
||||
{
|
||||
numplaying++;
|
||||
if (nettics[i] < lowtic)
|
||||
lowtic = nettics[i];
|
||||
}
|
||||
availabletics = lowtic - gametic/ticdup;
|
||||
|
||||
|
||||
//
|
||||
// decide how many tics to run
|
||||
//
|
||||
if (realtics < availabletics-1)
|
||||
counts = realtics+1;
|
||||
else if (realtics < availabletics)
|
||||
counts = realtics;
|
||||
else
|
||||
counts = availabletics;
|
||||
if (counts < 1)
|
||||
counts = 1;
|
||||
|
||||
frameon++;
|
||||
|
||||
if (debugfile)
|
||||
fprintf (debugfile,"=======real: %i avail: %i game: %i\n",realtics, availabletics,counts);
|
||||
|
||||
if (!demoplayback)
|
||||
{
|
||||
//=============================================================================
|
||||
//
|
||||
// ideally nettics[0] should be 1 - 3 tics above lowtic
|
||||
// if we are consistantly slower, speed up time
|
||||
//
|
||||
for (i=0 ; i<MAXPLAYERS ; i++)
|
||||
if (playeringame[i])
|
||||
break;
|
||||
if (consoleplayer == i)
|
||||
{ // the key player does not adapt
|
||||
}
|
||||
else
|
||||
{
|
||||
if (nettics[0] <= nettics[nodeforplayer[i]])
|
||||
{
|
||||
gametime--;
|
||||
// printf ("-");
|
||||
}
|
||||
frameskip[frameon&3] = (oldnettics > nettics[nodeforplayer[i]]);
|
||||
oldnettics = nettics[0];
|
||||
if (frameskip[0] && frameskip[1] && frameskip[2] && frameskip[3])
|
||||
{
|
||||
skiptics = 1;
|
||||
// printf ("+");
|
||||
}
|
||||
}
|
||||
//=============================================================================
|
||||
} // demoplayback
|
||||
|
||||
//
|
||||
// wait for new tics if needed
|
||||
//
|
||||
while (lowtic < gametic/ticdup + counts)
|
||||
{
|
||||
|
||||
NetUpdate ();
|
||||
lowtic = MAXINT;
|
||||
|
||||
for (i=0 ; i<doomcom->numnodes ; i++)
|
||||
if (nodeingame[i] && nettics[i] < lowtic)
|
||||
lowtic = nettics[i];
|
||||
|
||||
if (lowtic < gametic/ticdup)
|
||||
I_Error ("TryRunTics: lowtic < gametic");
|
||||
|
||||
// don't stay in here forever -- give the menu a chance to work
|
||||
if (I_GetTime ()/ticdup - entertic >= 20)
|
||||
{
|
||||
MN_Ticker ();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// run the count * ticdup dics
|
||||
//
|
||||
while (counts--)
|
||||
{
|
||||
for (i=0 ; i<ticdup ; i++)
|
||||
{
|
||||
if (gametic/ticdup > lowtic)
|
||||
I_Error ("gametic>lowtic");
|
||||
if (advancedemo)
|
||||
D_DoAdvanceDemo ();
|
||||
MN_Ticker ();
|
||||
G_Ticker ();
|
||||
gametic++;
|
||||
//
|
||||
// modify command for duplicated tics
|
||||
//
|
||||
if (i != ticdup-1)
|
||||
{
|
||||
ticcmd_t *cmd;
|
||||
int buf;
|
||||
int j;
|
||||
|
||||
buf = (gametic/ticdup)%BACKUPTICS;
|
||||
for (j=0 ; j<MAXPLAYERS ; j++)
|
||||
{
|
||||
cmd = &netcmds[j][buf];
|
||||
cmd->chatchar = 0;
|
||||
if (cmd->buttons & BT_SPECIAL)
|
||||
cmd->buttons = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
NetUpdate (); // check for new console commands
|
||||
}
|
||||
}
|
790
Heretic Source/OLDD_NET.C
Normal file
790
Heretic Source/OLDD_NET.C
Normal file
|
@ -0,0 +1,790 @@
|
|||
// I_pcnet.m
|
||||
|
||||
#include "DoomDef.h"
|
||||
|
||||
#define NCMD_EXIT 0x80000000
|
||||
#define NCMD_RETRANSMIT 0x40000000
|
||||
#define NCMD_SETUP 0x20000000
|
||||
#define NCMD_CHECKSUM 0x0fffffff
|
||||
|
||||
/*
|
||||
if more space needs to be crunched out of the protocol...
|
||||
|
||||
1 drone
|
||||
2 player
|
||||
8 tic
|
||||
5 numtics
|
||||
|
||||
#define NCMD_EXIT 0x80000000
|
||||
#define NCMD_RETRANSMIT 0x40000000 // a retransmit will have 0 tics
|
||||
#define NCMD_DRONE 0x20000000
|
||||
#define NCMD_PLAYER 0x18000000
|
||||
#define NCMD_PLAYERSHIFT 27
|
||||
#define NCMD_TIC 0x00ff0000
|
||||
#define NCMD_TICSHIFT 16
|
||||
#define NCMD_NUMTICS 0x0000ff00
|
||||
#define NCMD_NUMTICSSHIFT 8
|
||||
#define NCMD_CHECKSUM 0x000000ff
|
||||
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
doomcom_t *doomcom;
|
||||
doomdata_t *netbuffer; // points inside doomcom
|
||||
|
||||
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
NETWORKING
|
||||
|
||||
gametic is the tic about to (or currently being) run
|
||||
maketic is the tick that hasn't had control made for it yet
|
||||
nettics[] has the maketics for all players
|
||||
|
||||
a gametic cannot be run until nettics[] > gametic for all players
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#define RESENDCOUNT 10
|
||||
#define PL_DRONE 0x80 // bit flag in doomdata->player
|
||||
|
||||
ticcmd_t localcmds[BACKUPTICS];
|
||||
|
||||
ticcmd_t netcmds[MAXPLAYERS][BACKUPTICS];
|
||||
int nettics[MAXNETNODES];
|
||||
boolean nodeingame[MAXNETNODES]; // set false as nodes leave game
|
||||
boolean remoteresend[MAXNETNODES]; // set when local needs tics
|
||||
int resendto[MAXNETNODES]; // set when remote needs tics
|
||||
int resendcount[MAXNETNODES];
|
||||
|
||||
int nodeforplayer[MAXPLAYERS];
|
||||
|
||||
int gametime;
|
||||
int maketic;
|
||||
int lastnettic, skiptics;
|
||||
int ticdup;
|
||||
|
||||
void D_ProcessEvents (void);
|
||||
void G_BuildTiccmd (ticcmd_t *cmd);
|
||||
void D_DoAdvanceDemo (void);
|
||||
|
||||
boolean reboundpacket;
|
||||
doomdata_t reboundstore;
|
||||
|
||||
|
||||
int NetbufferSize (void)
|
||||
{
|
||||
return (int)&(((doomdata_t *)0)->cmds[netbuffer->numtics]);
|
||||
}
|
||||
|
||||
unsigned NetbufferChecksum (void)
|
||||
{
|
||||
unsigned c;
|
||||
int i,l;
|
||||
|
||||
c = 0x1234567;
|
||||
|
||||
#ifdef NeXT
|
||||
return 0; // byte order problems
|
||||
#endif
|
||||
|
||||
l = (NetbufferSize () - (int)&(((doomdata_t *)0)->retransmitfrom))/4;
|
||||
for (i=0 ; i<l ; i++)
|
||||
c += ((unsigned *)&netbuffer->retransmitfrom)[i] * (i+1);
|
||||
|
||||
return c & NCMD_CHECKSUM;
|
||||
}
|
||||
|
||||
int ExpandTics (int low)
|
||||
{
|
||||
int delta;
|
||||
|
||||
delta = low - (maketic&0xff);
|
||||
|
||||
if (delta >= -64 && delta <= 64)
|
||||
return (maketic&~0xff) + low;
|
||||
if (delta > 64)
|
||||
return (maketic&~0xff) - 256 + low;
|
||||
if (delta < -64)
|
||||
return (maketic&~0xff) + 256 + low;
|
||||
|
||||
I_Error ("ExpandTics: strange value %i at maketic %i",low,maketic);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
|
||||
|
||||
/*
|
||||
==============
|
||||
=
|
||||
= HSendPacket
|
||||
=
|
||||
==============
|
||||
*/
|
||||
|
||||
void HSendPacket (int node, int flags)
|
||||
{
|
||||
netbuffer->checksum = NetbufferChecksum () | flags;
|
||||
|
||||
if (!node)
|
||||
{
|
||||
reboundstore = *netbuffer;
|
||||
reboundpacket = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!netgame)
|
||||
I_Error ("Tried to transmit to another node");
|
||||
|
||||
doomcom->command = CMD_SEND;
|
||||
doomcom->remotenode = node;
|
||||
doomcom->datalength = NetbufferSize ();
|
||||
|
||||
if (debugfile)
|
||||
{
|
||||
int i;
|
||||
int realretrans;
|
||||
if (netbuffer->checksum & NCMD_RETRANSMIT)
|
||||
realretrans = ExpandTics (netbuffer->retransmitfrom);
|
||||
else
|
||||
realretrans = -1;
|
||||
fprintf (debugfile,"send (%i + %i, R %i) [%i] "
|
||||
,ExpandTics(netbuffer->starttic),netbuffer->numtics, realretrans, doomcom->datalength);
|
||||
for (i=0 ; i<doomcom->datalength ; i++)
|
||||
fprintf (debugfile,"%i ",((byte *)netbuffer)[i]);
|
||||
fprintf (debugfile,"\n");
|
||||
}
|
||||
|
||||
I_NetCmd ();
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
=
|
||||
= HGetPacket
|
||||
=
|
||||
= Returns false if no packet is waiting
|
||||
=
|
||||
==============
|
||||
*/
|
||||
|
||||
boolean HGetPacket (void)
|
||||
{
|
||||
if (reboundpacket)
|
||||
{
|
||||
*netbuffer = reboundstore;
|
||||
doomcom->remotenode = 0;
|
||||
reboundpacket = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!netgame)
|
||||
return false;
|
||||
|
||||
doomcom->command = CMD_GET;
|
||||
I_NetCmd ();
|
||||
if (doomcom->remotenode == -1)
|
||||
return false;
|
||||
|
||||
if (doomcom->datalength != NetbufferSize ())
|
||||
{
|
||||
if (debugfile)
|
||||
fprintf (debugfile,"bad packet length %i\n",doomcom->datalength);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (NetbufferChecksum () != (netbuffer->checksum&NCMD_CHECKSUM) )
|
||||
{
|
||||
if (debugfile)
|
||||
fprintf (debugfile,"bad packet checksum\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (debugfile)
|
||||
{
|
||||
int realretrans;
|
||||
int i;
|
||||
|
||||
if (netbuffer->checksum & NCMD_SETUP)
|
||||
fprintf (debugfile,"setup packet\n");
|
||||
else
|
||||
{
|
||||
if (netbuffer->checksum & NCMD_RETRANSMIT)
|
||||
realretrans = ExpandTics (netbuffer->retransmitfrom);
|
||||
else
|
||||
realretrans = -1;
|
||||
fprintf (debugfile,"get %i = (%i + %i, R %i)[%i] ",doomcom->remotenode,
|
||||
ExpandTics(netbuffer->starttic),netbuffer->numtics, realretrans, doomcom->datalength);
|
||||
for (i=0 ; i<doomcom->datalength ; i++)
|
||||
fprintf (debugfile,"%i ",((byte *)netbuffer)[i]);
|
||||
fprintf (debugfile,"\n");
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===================
|
||||
=
|
||||
= GetPackets
|
||||
=
|
||||
===================
|
||||
*/
|
||||
|
||||
char exitmsg[80];
|
||||
|
||||
void GetPackets (void)
|
||||
{
|
||||
int netconsole;
|
||||
int netnode;
|
||||
int netdrone;
|
||||
int j;
|
||||
ticcmd_t *src, *dest;
|
||||
int dupedstart, dupedend;
|
||||
int skiptics;
|
||||
int realstart;
|
||||
|
||||
while (HGetPacket ())
|
||||
{
|
||||
if (netbuffer->checksum & NCMD_SETUP)
|
||||
continue; // extra setup packet
|
||||
|
||||
netdrone = netbuffer->player & PL_DRONE;
|
||||
netconsole = netbuffer->player & ~PL_DRONE;
|
||||
netnode = doomcom->remotenode;
|
||||
//
|
||||
// to save bytes, only the low byte of tic numbers are sent
|
||||
// Figure out what the rest of the bytes are
|
||||
//
|
||||
realstart = ExpandTics (netbuffer->starttic);
|
||||
dupedstart = realstart*doomcom->ticdup;
|
||||
dupedend = (realstart+netbuffer->numtics)*doomcom->ticdup;
|
||||
|
||||
//
|
||||
// check for exiting the game
|
||||
//
|
||||
if (netbuffer->checksum & NCMD_EXIT)
|
||||
{
|
||||
if (!nodeingame[netnode])
|
||||
continue;
|
||||
nodeingame[netnode] = false;
|
||||
if (!netdrone)
|
||||
{
|
||||
playeringame[netconsole] = false;
|
||||
strcpy (exitmsg, "Player 1 left the game");
|
||||
exitmsg[7] += netconsole;
|
||||
players[consoleplayer].message = exitmsg;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
//
|
||||
// drone packets are just notifications
|
||||
//
|
||||
if (netdrone)
|
||||
{
|
||||
nettics[netnode] = dupedend;
|
||||
continue;
|
||||
}
|
||||
|
||||
nodeforplayer[netconsole] = netnode;
|
||||
|
||||
//
|
||||
// check for retransmit request
|
||||
//
|
||||
if ( resendcount[netnode] <= 0
|
||||
&& (netbuffer->checksum & NCMD_RETRANSMIT) )
|
||||
{
|
||||
resendto[netnode] = ExpandTics(netbuffer->retransmitfrom);
|
||||
if (debugfile)
|
||||
fprintf (debugfile,"retransmit from %i\n", resendto[netnode]);
|
||||
resendcount[netnode] = RESENDCOUNT;
|
||||
}
|
||||
else
|
||||
resendcount[netnode]--;
|
||||
|
||||
//
|
||||
// check for out of order / duplicated packet
|
||||
//
|
||||
if (dupedend == nettics[netnode])
|
||||
continue;
|
||||
|
||||
if (dupedend < nettics[netnode])
|
||||
{
|
||||
if (debugfile)
|
||||
fprintf (debugfile,"out of order packet (%i + %i)\n" ,realstart,netbuffer->numtics);
|
||||
continue;
|
||||
}
|
||||
|
||||
//
|
||||
// check for a missed packet
|
||||
//
|
||||
if (dupedstart > nettics[netnode])
|
||||
{
|
||||
// stop processing until the other system resends the missed tics
|
||||
if (debugfile)
|
||||
fprintf (debugfile,"missed tics from %i (%i - %i)\n", netnode, dupedstart, nettics[netnode]);
|
||||
remoteresend[netnode] = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
//
|
||||
// update command store from the packet
|
||||
//
|
||||
remoteresend[netnode] = false;
|
||||
|
||||
skiptics = nettics[netnode]/doomcom->ticdup - realstart;
|
||||
src = &netbuffer->cmds[skiptics];
|
||||
|
||||
while (nettics[netnode] < dupedend)
|
||||
{
|
||||
for (j=0 ; j<doomcom->ticdup ; j++)
|
||||
{
|
||||
dest = &netcmds[netconsole][nettics[netnode]%BACKUPTICS];
|
||||
nettics[netnode]++;
|
||||
*dest = *src;
|
||||
src->chatchar = 0;
|
||||
if (src->buttons & BT_SPECIAL)
|
||||
src->buttons = 0;
|
||||
}
|
||||
src++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
=
|
||||
= NetUpdate
|
||||
=
|
||||
= Builds ticcmds for console player
|
||||
= sends out a packet
|
||||
=============
|
||||
*/
|
||||
|
||||
void NetUpdate (void)
|
||||
{
|
||||
int nowtime;
|
||||
int newtics;
|
||||
int i,j;
|
||||
int gameticdiv;
|
||||
int realstart;
|
||||
|
||||
if (singletics)
|
||||
return; // singletic update is syncronous
|
||||
|
||||
//
|
||||
// check time
|
||||
//
|
||||
nowtime = I_GetTime ()/doomcom->ticdup;
|
||||
newtics = nowtime - gametime;
|
||||
gametime = nowtime;
|
||||
if (newtics <= 0) // nothing new to update
|
||||
goto listen;
|
||||
|
||||
if (skiptics <= newtics)
|
||||
{
|
||||
newtics -= skiptics;
|
||||
skiptics = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
skiptics -= newtics;
|
||||
newtics = 0;
|
||||
}
|
||||
|
||||
|
||||
netbuffer->player = consoleplayer;
|
||||
if (doomcom->drone)
|
||||
netbuffer->player |= PL_DRONE;
|
||||
|
||||
//
|
||||
// drone packets
|
||||
//
|
||||
if (doomcom->drone)
|
||||
{
|
||||
I_StartTic ();
|
||||
D_ProcessEvents ();
|
||||
goto sendit;
|
||||
}
|
||||
|
||||
//
|
||||
// build new ticcmds for console player
|
||||
//
|
||||
gameticdiv = (gametic+doomcom->ticdup-1)/doomcom->ticdup;
|
||||
for (i=0 ; i<newtics ; i++)
|
||||
{
|
||||
I_StartTic ();
|
||||
D_ProcessEvents ();
|
||||
if (maketic - gameticdiv >= BACKUPTICS/2 /* /doomcom->ticdup */- 1)
|
||||
{
|
||||
newtics = i;
|
||||
break; // can't hold any more
|
||||
}
|
||||
//printf ("mk:%i ",maketic);
|
||||
G_BuildTiccmd (&localcmds[maketic%BACKUPTICS]);
|
||||
maketic++;
|
||||
}
|
||||
|
||||
//
|
||||
// send the packet to the other nodes
|
||||
//
|
||||
sendit:
|
||||
for (i=0 ; i<doomcom->numnodes ; i++)
|
||||
if (nodeingame[i])
|
||||
{
|
||||
if (doomcom->drone)
|
||||
{
|
||||
netbuffer->starttic = realstart = maketic + BACKUPTICS/2;
|
||||
netbuffer->numtics = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
netbuffer->starttic = realstart = resendto[i];
|
||||
netbuffer->numtics = maketic - realstart;
|
||||
resendto[i] = maketic - doomcom->extratics;
|
||||
}
|
||||
|
||||
if (netbuffer->numtics > BACKUPTICS)
|
||||
I_Error ("NetUpdate: netbuffer->numtics > BACKUPTICS");
|
||||
|
||||
for (j=0 ; j< netbuffer->numtics ; j++)
|
||||
netbuffer->cmds[j] =
|
||||
localcmds[(realstart+j)%BACKUPTICS];
|
||||
|
||||
if (remoteresend[i])
|
||||
{
|
||||
netbuffer->retransmitfrom = nettics[i]/doomcom->ticdup;
|
||||
HSendPacket (i, NCMD_RETRANSMIT);
|
||||
}
|
||||
else
|
||||
{
|
||||
netbuffer->retransmitfrom = 0;
|
||||
HSendPacket (i, 0);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// listen for other packets
|
||||
//
|
||||
listen:
|
||||
|
||||
GetPackets ();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=====================
|
||||
=
|
||||
= CheckAbort
|
||||
=
|
||||
=====================
|
||||
*/
|
||||
|
||||
void CheckAbort (void)
|
||||
{
|
||||
event_t *ev;
|
||||
|
||||
I_WaitVBL(2);
|
||||
|
||||
I_StartTic ();
|
||||
for ( ; eventtail != eventhead
|
||||
; eventtail = (++eventtail)&(MAXEVENTS-1) )
|
||||
{
|
||||
ev = &events[eventtail];
|
||||
if (ev->type == ev_keydown && ev->data1 == KEY_ESCAPE)
|
||||
I_Error ("Network game synchronization aborted.");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=====================
|
||||
=
|
||||
= D_ArbitrateNetStart
|
||||
=
|
||||
=====================
|
||||
*/
|
||||
|
||||
void D_ArbitrateNetStart (void)
|
||||
{
|
||||
int i;
|
||||
boolean gotinfo[MAXNETNODES];
|
||||
|
||||
autostart = true;
|
||||
memset (gotinfo,0,sizeof(gotinfo));
|
||||
|
||||
if (doomcom->consoleplayer)
|
||||
{ // listen for setup info from key player
|
||||
printf ("listening for network start info...\n");
|
||||
while (1)
|
||||
{
|
||||
CheckAbort ();
|
||||
if (!HGetPacket ())
|
||||
continue;
|
||||
if (netbuffer->checksum & NCMD_SETUP)
|
||||
{
|
||||
if (netbuffer->player != VERSION)
|
||||
I_Error ("Different DOOM versions cannot play a net game!");
|
||||
startskill = netbuffer->retransmitfrom & 15;
|
||||
deathmatch = (netbuffer->retransmitfrom & 0x80) > 0;
|
||||
nomonsters = (netbuffer->retransmitfrom & 0x40) > 0;
|
||||
respawnparm = (netbuffer->retransmitfrom & 0x20) > 0;
|
||||
startmap = netbuffer->starttic & 15;
|
||||
startepisode = netbuffer->starttic >> 4;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // key player, send the setup info
|
||||
printf ("sending network start info...\n");
|
||||
do
|
||||
{
|
||||
CheckAbort ();
|
||||
for (i=0 ; i<doomcom->numnodes ; i++)
|
||||
{
|
||||
netbuffer->retransmitfrom = startskill;
|
||||
if (deathmatch)
|
||||
netbuffer->retransmitfrom |= 0x80;
|
||||
if (nomonsters)
|
||||
netbuffer->retransmitfrom |= 0x40;
|
||||
if (respawnparm)
|
||||
netbuffer->retransmitfrom |= 0x20;
|
||||
netbuffer->starttic = startepisode * 16 + startmap;
|
||||
netbuffer->player = VERSION;
|
||||
netbuffer->numtics = 0;
|
||||
HSendPacket (i, NCMD_SETUP);
|
||||
}
|
||||
|
||||
while (HGetPacket ())
|
||||
{
|
||||
gotinfo[netbuffer->player&0x7f] = true;
|
||||
}
|
||||
|
||||
for (i=1 ; i<doomcom->numnodes ; i++)
|
||||
if (!gotinfo[i])
|
||||
break;
|
||||
} while (i < doomcom->numnodes);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
===================
|
||||
=
|
||||
= D_CheckNetGame
|
||||
=
|
||||
= Works out player numbers among the net participants
|
||||
===================
|
||||
*/
|
||||
|
||||
extern int viewangleoffset;
|
||||
|
||||
void D_CheckNetGame (void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0 ; i<MAXNETNODES ; i++)
|
||||
{
|
||||
nodeingame[i] = false;
|
||||
nettics[i] = 0;
|
||||
remoteresend[i] = false; // set when local needs tics
|
||||
resendto[i] = 0; // which tic to start sending
|
||||
}
|
||||
|
||||
// I_InitNetwork sets doomcom and netgame
|
||||
I_InitNetwork ();
|
||||
if (doomcom->id != DOOMCOM_ID)
|
||||
I_Error ("Doomcom buffer invalid!");
|
||||
netbuffer = &doomcom->data;
|
||||
consoleplayer = displayplayer = doomcom->consoleplayer;
|
||||
if (netgame)
|
||||
D_ArbitrateNetStart ();
|
||||
printf ("startskill %i deathmatch: %i startmap: %i startepisode: %i\n", startskill, deathmatch, startmap, startepisode);
|
||||
|
||||
// read values out of doomcom
|
||||
ticdup = doomcom->ticdup;
|
||||
|
||||
for (i=0 ; i<doomcom->numplayers ; i++)
|
||||
playeringame[i] = true;
|
||||
for (i=0 ; i<doomcom->numnodes ; i++)
|
||||
nodeingame[i] = true;
|
||||
|
||||
printf ("player %i of %i (%i nodes)\n", consoleplayer+1, doomcom->numplayers, doomcom->numnodes);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
=
|
||||
= D_QuitNetGame
|
||||
=
|
||||
= Called before quitting to leave a net game without hanging the
|
||||
= other players
|
||||
=
|
||||
==================
|
||||
*/
|
||||
|
||||
void D_QuitNetGame (void)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
if (debugfile)
|
||||
fclose (debugfile);
|
||||
|
||||
if (!netgame || !usergame || consoleplayer == -1)
|
||||
return;
|
||||
|
||||
// send a bunch of packets for security
|
||||
netbuffer->player = consoleplayer;
|
||||
if (doomcom->drone)
|
||||
netbuffer->player |= PL_DRONE;
|
||||
netbuffer->numtics = 0;
|
||||
for (i=0 ; i<4 ; i++)
|
||||
{
|
||||
for (j=1 ; j<doomcom->numnodes ; j++)
|
||||
if (nodeingame[j])
|
||||
HSendPacket (j, NCMD_EXIT);
|
||||
I_WaitVBL (1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
===============
|
||||
=
|
||||
= TryRunTics
|
||||
=
|
||||
===============
|
||||
*/
|
||||
|
||||
int frametics[4], frameon;
|
||||
int frameskip[4];
|
||||
int oldnettics;
|
||||
extern boolean advancedemo;
|
||||
|
||||
void TryRunTics (void)
|
||||
{
|
||||
int i;
|
||||
int lowtic, nextlowest;
|
||||
int entertic;
|
||||
int static oldentertics;
|
||||
int realtics, availabletics;
|
||||
int counts;
|
||||
int numplaying;
|
||||
|
||||
//
|
||||
// get real tics
|
||||
//
|
||||
entertic = I_GetTime ();
|
||||
realtics = entertic - oldentertics;
|
||||
oldentertics = entertic;
|
||||
|
||||
//
|
||||
// get available tics
|
||||
//
|
||||
NetUpdate ();
|
||||
|
||||
lowtic = nextlowest = MAXINT;
|
||||
numplaying = 0;
|
||||
for (i=0 ; i<doomcom->numnodes ; i++)
|
||||
if (nodeingame[i])
|
||||
{
|
||||
numplaying++;
|
||||
if (nettics[i] < lowtic)
|
||||
{
|
||||
nextlowest = lowtic;
|
||||
lowtic = nettics[i];
|
||||
}
|
||||
else if (nettics[i] < nextlowest)
|
||||
nextlowest = nettics[i];
|
||||
}
|
||||
availabletics = lowtic - gametic;
|
||||
|
||||
|
||||
//
|
||||
// decide how many tics to run
|
||||
//
|
||||
if (realtics < availabletics-1)
|
||||
counts = realtics+1;
|
||||
else if (realtics < availabletics)
|
||||
counts = realtics;
|
||||
else
|
||||
counts = availabletics;
|
||||
if (counts < 1)
|
||||
counts = 1;
|
||||
|
||||
frameon++;
|
||||
|
||||
if (debugfile)
|
||||
fprintf (debugfile,"=======real: %i avail: %i game: %i\n",realtics, availabletics,counts);
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// ideally nettics[0] should be 1 - 3 tics above lowtic
|
||||
// if we are consistantly slower, speed up time
|
||||
// drones should never hold up the other players
|
||||
//
|
||||
for (i=0 ; i<MAXPLAYERS ; i++)
|
||||
if (playeringame[i])
|
||||
break;
|
||||
if (consoleplayer == i)
|
||||
{ // the key player does not adapt
|
||||
}
|
||||
else
|
||||
{
|
||||
if (nettics[0] <= nettics[nodeforplayer[i]])
|
||||
{
|
||||
gametime--;
|
||||
// printf ("-");
|
||||
}
|
||||
frameskip[frameon&3] = (oldnettics > nettics[nodeforplayer[i]]);
|
||||
oldnettics = nettics[0];
|
||||
if (frameskip[0] && frameskip[1] && frameskip[2] && frameskip[3])
|
||||
{
|
||||
skiptics = 1;
|
||||
// printf ("+");
|
||||
}
|
||||
}
|
||||
//=============================================================================
|
||||
|
||||
//
|
||||
// wait for new tics if needed
|
||||
//
|
||||
while (lowtic < gametic + counts)
|
||||
{
|
||||
|
||||
NetUpdate ();
|
||||
lowtic = MAXINT;
|
||||
|
||||
for (i=0 ; i<doomcom->numnodes ; i++)
|
||||
if (nodeingame[i] && nettics[i] < lowtic)
|
||||
lowtic = nettics[i];
|
||||
|
||||
if (lowtic < gametic)
|
||||
I_Error ("TryRunTics: lowtic < gametic");
|
||||
|
||||
// don't stay in here forever -- give the menu a chance to work
|
||||
if (I_GetTime () - entertic >= 20)
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// run the tics
|
||||
//
|
||||
while (counts--)
|
||||
{
|
||||
G_Ticker ();
|
||||
NetUpdate (); // check for new console commands
|
||||
gametic++;
|
||||
}
|
||||
}
|
236
Heretic Source/P_CEILNG.C
Normal file
236
Heretic Source/P_CEILNG.C
Normal file
|
@ -0,0 +1,236 @@
|
|||
|
||||
#include "DoomDef.h"
|
||||
#include "P_local.h"
|
||||
#include "soundst.h"
|
||||
|
||||
//==================================================================
|
||||
//==================================================================
|
||||
//
|
||||
// CEILINGS
|
||||
//
|
||||
//==================================================================
|
||||
//==================================================================
|
||||
|
||||
ceiling_t *activeceilings[MAXCEILINGS];
|
||||
|
||||
//==================================================================
|
||||
//
|
||||
// T_MoveCeiling
|
||||
//
|
||||
//==================================================================
|
||||
void T_MoveCeiling (ceiling_t *ceiling)
|
||||
{
|
||||
result_e res;
|
||||
|
||||
switch(ceiling->direction)
|
||||
{
|
||||
case 0: // IN STASIS
|
||||
break;
|
||||
case 1: // UP
|
||||
res = T_MovePlane(ceiling->sector,ceiling->speed,
|
||||
ceiling->topheight,false,1,ceiling->direction);
|
||||
if(!(leveltime&7))
|
||||
S_StartSound((mobj_t *)&ceiling->sector->soundorg, sfx_dormov);
|
||||
if (res == pastdest)
|
||||
switch(ceiling->type)
|
||||
{
|
||||
case raiseToHighest:
|
||||
P_RemoveActiveCeiling(ceiling);
|
||||
break;
|
||||
case fastCrushAndRaise:
|
||||
case crushAndRaise:
|
||||
ceiling->direction = -1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case -1: // DOWN
|
||||
res = T_MovePlane(ceiling->sector,ceiling->speed,
|
||||
ceiling->bottomheight,ceiling->crush,1,ceiling->direction);
|
||||
if (!(leveltime&7))
|
||||
S_StartSound((mobj_t *)&ceiling->sector->soundorg,sfx_dormov);
|
||||
if (res == pastdest)
|
||||
switch(ceiling->type)
|
||||
{
|
||||
case crushAndRaise:
|
||||
ceiling->speed = CEILSPEED;
|
||||
case fastCrushAndRaise:
|
||||
ceiling->direction = 1;
|
||||
break;
|
||||
case lowerAndCrush:
|
||||
case lowerToFloor:
|
||||
P_RemoveActiveCeiling(ceiling);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
else
|
||||
if (res == crushed)
|
||||
switch(ceiling->type)
|
||||
{
|
||||
case crushAndRaise:
|
||||
case lowerAndCrush:
|
||||
ceiling->speed = CEILSPEED / 8;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//==================================================================
|
||||
//
|
||||
// EV_DoCeiling
|
||||
// Move a ceiling up/down and all around!
|
||||
//
|
||||
//==================================================================
|
||||
int EV_DoCeiling (line_t *line, ceiling_e type)
|
||||
{
|
||||
int secnum,rtn;
|
||||
sector_t *sec;
|
||||
ceiling_t *ceiling;
|
||||
|
||||
secnum = -1;
|
||||
rtn = 0;
|
||||
|
||||
//
|
||||
// Reactivate in-stasis ceilings...for certain types.
|
||||
//
|
||||
switch(type)
|
||||
{
|
||||
case fastCrushAndRaise:
|
||||
case crushAndRaise:
|
||||
P_ActivateInStasisCeiling(line);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0)
|
||||
{
|
||||
sec = §ors[secnum];
|
||||
if (sec->specialdata)
|
||||
continue;
|
||||
|
||||
//
|
||||
// new door thinker
|
||||
//
|
||||
rtn = 1;
|
||||
ceiling = Z_Malloc (sizeof(*ceiling), PU_LEVSPEC, 0);
|
||||
P_AddThinker (&ceiling->thinker);
|
||||
sec->specialdata = ceiling;
|
||||
ceiling->thinker.function = T_MoveCeiling;
|
||||
ceiling->sector = sec;
|
||||
ceiling->crush = false;
|
||||
switch(type)
|
||||
{
|
||||
case fastCrushAndRaise:
|
||||
ceiling->crush = true;
|
||||
ceiling->topheight = sec->ceilingheight;
|
||||
ceiling->bottomheight = sec->floorheight + (8*FRACUNIT);
|
||||
ceiling->direction = -1;
|
||||
ceiling->speed = CEILSPEED * 2;
|
||||
break;
|
||||
case crushAndRaise:
|
||||
ceiling->crush = true;
|
||||
ceiling->topheight = sec->ceilingheight;
|
||||
case lowerAndCrush:
|
||||
case lowerToFloor:
|
||||
ceiling->bottomheight = sec->floorheight;
|
||||
if (type != lowerToFloor)
|
||||
ceiling->bottomheight += 8*FRACUNIT;
|
||||
ceiling->direction = -1;
|
||||
ceiling->speed = CEILSPEED;
|
||||
break;
|
||||
case raiseToHighest:
|
||||
ceiling->topheight = P_FindHighestCeilingSurrounding(sec);
|
||||
ceiling->direction = 1;
|
||||
ceiling->speed = CEILSPEED;
|
||||
break;
|
||||
}
|
||||
|
||||
ceiling->tag = sec->tag;
|
||||
ceiling->type = type;
|
||||
P_AddActiveCeiling(ceiling);
|
||||
}
|
||||
return rtn;
|
||||
}
|
||||
|
||||
//==================================================================
|
||||
//
|
||||
// Add an active ceiling
|
||||
//
|
||||
//==================================================================
|
||||
void P_AddActiveCeiling(ceiling_t *c)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < MAXCEILINGS;i++)
|
||||
if (activeceilings[i] == NULL)
|
||||
{
|
||||
activeceilings[i] = c;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//==================================================================
|
||||
//
|
||||
// Remove a ceiling's thinker
|
||||
//
|
||||
//==================================================================
|
||||
void P_RemoveActiveCeiling(ceiling_t *c)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0;i < MAXCEILINGS;i++)
|
||||
if (activeceilings[i] == c)
|
||||
{
|
||||
activeceilings[i]->sector->specialdata = NULL;
|
||||
P_RemoveThinker (&activeceilings[i]->thinker);
|
||||
activeceilings[i] = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//==================================================================
|
||||
//
|
||||
// Restart a ceiling that's in-stasis
|
||||
//
|
||||
//==================================================================
|
||||
void P_ActivateInStasisCeiling(line_t *line)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0;i < MAXCEILINGS;i++)
|
||||
if (activeceilings[i] && (activeceilings[i]->tag == line->tag) &&
|
||||
(activeceilings[i]->direction == 0))
|
||||
{
|
||||
activeceilings[i]->direction = activeceilings[i]->olddirection;
|
||||
activeceilings[i]->thinker.function = T_MoveCeiling;
|
||||
}
|
||||
}
|
||||
|
||||
//==================================================================
|
||||
//
|
||||
// EV_CeilingCrushStop
|
||||
// Stop a ceiling from crushing!
|
||||
//
|
||||
//==================================================================
|
||||
int EV_CeilingCrushStop(line_t *line)
|
||||
{
|
||||
int i;
|
||||
int rtn;
|
||||
|
||||
rtn = 0;
|
||||
for (i = 0;i < MAXCEILINGS;i++)
|
||||
if (activeceilings[i] && (activeceilings[i]->tag == line->tag) &&
|
||||
(activeceilings[i]->direction != 0))
|
||||
{
|
||||
activeceilings[i]->olddirection = activeceilings[i]->direction;
|
||||
activeceilings[i]->thinker.function = NULL;
|
||||
activeceilings[i]->direction = 0; // in-stasis
|
||||
rtn = 1;
|
||||
}
|
||||
|
||||
return rtn;
|
||||
}
|
368
Heretic Source/P_DOORS.C
Normal file
368
Heretic Source/P_DOORS.C
Normal file
|
@ -0,0 +1,368 @@
|
|||
|
||||
// P_doors.c
|
||||
|
||||
#include "DoomDef.h"
|
||||
#include "P_local.h"
|
||||
#include "soundst.h"
|
||||
|
||||
//==================================================================
|
||||
//==================================================================
|
||||
//
|
||||
// VERTICAL DOORS
|
||||
//
|
||||
//==================================================================
|
||||
//==================================================================
|
||||
|
||||
//==================================================================
|
||||
//
|
||||
// T_VerticalDoor
|
||||
//
|
||||
//==================================================================
|
||||
void T_VerticalDoor(vldoor_t *door)
|
||||
{
|
||||
result_e res;
|
||||
|
||||
switch(door->direction)
|
||||
{
|
||||
case 0: // WAITING
|
||||
if(!--door->topcountdown)
|
||||
switch(door->type)
|
||||
{
|
||||
case normal:
|
||||
door->direction = -1; // time to go back down
|
||||
S_StartSound((mobj_t *)
|
||||
&door->sector->soundorg, sfx_doropn);
|
||||
break;
|
||||
case close30ThenOpen:
|
||||
door->direction = 1;
|
||||
S_StartSound((mobj_t *)
|
||||
&door->sector->soundorg, sfx_doropn);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 2: // INITIAL WAIT
|
||||
if(!--door->topcountdown)
|
||||
{
|
||||
switch(door->type)
|
||||
{
|
||||
case raiseIn5Mins:
|
||||
door->direction = 1;
|
||||
door->type = normal;
|
||||
S_StartSound((mobj_t *)
|
||||
&door->sector->soundorg, sfx_doropn);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case -1: // DOWN
|
||||
res = T_MovePlane(door->sector, door->speed,
|
||||
door->sector->floorheight, false, 1, door->direction);
|
||||
if(res == pastdest)
|
||||
{
|
||||
switch(door->type)
|
||||
{
|
||||
case normal:
|
||||
case close:
|
||||
door->sector->specialdata = NULL;
|
||||
P_RemoveThinker(&door->thinker); // unlink and free
|
||||
S_StartSound((mobj_t *)
|
||||
&door->sector->soundorg, sfx_dorcls);
|
||||
break;
|
||||
case close30ThenOpen:
|
||||
door->direction = 0;
|
||||
door->topcountdown = 35*30;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if(res == crushed)
|
||||
{
|
||||
switch(door->type)
|
||||
{
|
||||
case close: // DON'T GO BACK UP!
|
||||
break;
|
||||
default:
|
||||
door->direction = 1;
|
||||
S_StartSound((mobj_t *)
|
||||
&door->sector->soundorg,sfx_doropn);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 1: // UP
|
||||
res = T_MovePlane(door->sector, door->speed,
|
||||
door->topheight, false, 1, door->direction);
|
||||
if(res == pastdest)
|
||||
{
|
||||
switch(door->type)
|
||||
{
|
||||
case normal:
|
||||
door->direction = 0; // wait at top
|
||||
door->topcountdown = door->topwait;
|
||||
break;
|
||||
case close30ThenOpen:
|
||||
case open:
|
||||
door->sector->specialdata = NULL;
|
||||
P_RemoveThinker (&door->thinker); // unlink and free
|
||||
S_StopSound((mobj_t *)&door->sector->soundorg);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// EV_DoDoor
|
||||
//
|
||||
// Move a door up/down
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
int EV_DoDoor(line_t *line, vldoor_e type, fixed_t speed)
|
||||
{
|
||||
int secnum;
|
||||
int retcode;
|
||||
sector_t *sec;
|
||||
vldoor_t *door;
|
||||
|
||||
secnum = -1;
|
||||
retcode = 0;
|
||||
while((secnum = P_FindSectorFromLineTag(line, secnum)) >= 0)
|
||||
{
|
||||
sec = §ors[secnum];
|
||||
if(sec->specialdata)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
// Add new door thinker
|
||||
retcode = 1;
|
||||
door = Z_Malloc(sizeof(*door), PU_LEVSPEC, 0);
|
||||
P_AddThinker(&door->thinker);
|
||||
sec->specialdata = door;
|
||||
door->thinker.function = T_VerticalDoor;
|
||||
door->sector = sec;
|
||||
switch(type)
|
||||
{
|
||||
case close:
|
||||
door->topheight = P_FindLowestCeilingSurrounding(sec);
|
||||
door->topheight -= 4*FRACUNIT;
|
||||
door->direction = -1;
|
||||
S_StartSound((mobj_t *)&door->sector->soundorg, sfx_doropn);
|
||||
break;
|
||||
case close30ThenOpen:
|
||||
door->topheight = sec->ceilingheight;
|
||||
door->direction = -1;
|
||||
S_StartSound((mobj_t *)&door->sector->soundorg, sfx_doropn);
|
||||
break;
|
||||
case normal:
|
||||
case open:
|
||||
door->direction = 1;
|
||||
door->topheight = P_FindLowestCeilingSurrounding(sec);
|
||||
door->topheight -= 4*FRACUNIT;
|
||||
if(door->topheight != sec->ceilingheight)
|
||||
{
|
||||
S_StartSound((mobj_t *)&door->sector->soundorg,
|
||||
sfx_doropn);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
door->type = type;
|
||||
door->speed = speed;
|
||||
door->topwait = VDOORWAIT;
|
||||
}
|
||||
return(retcode);
|
||||
}
|
||||
|
||||
//==================================================================
|
||||
//
|
||||
// EV_VerticalDoor : open a door manually, no tag value
|
||||
//
|
||||
//==================================================================
|
||||
void EV_VerticalDoor(line_t *line, mobj_t *thing)
|
||||
{
|
||||
player_t *player;
|
||||
int secnum;
|
||||
sector_t *sec;
|
||||
vldoor_t *door;
|
||||
int side;
|
||||
|
||||
side = 0; // only front sides can be used
|
||||
//
|
||||
// Check for locks
|
||||
//
|
||||
player = thing->player;
|
||||
switch(line->special)
|
||||
{
|
||||
case 26: // Blue Lock
|
||||
case 32:
|
||||
if(!player)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if(!player->keys[key_blue])
|
||||
{
|
||||
P_SetMessage(player, TXT_NEEDBLUEKEY, false);
|
||||
S_StartSound(NULL, sfx_plroof);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 27: // Yellow Lock
|
||||
case 34:
|
||||
if(!player)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if(!player->keys[key_yellow])
|
||||
{
|
||||
P_SetMessage(player, TXT_NEEDYELLOWKEY, false);
|
||||
S_StartSound(NULL, sfx_plroof);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 28: // Green Lock
|
||||
case 33:
|
||||
if(!player)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if(!player->keys[key_green])
|
||||
{
|
||||
P_SetMessage(player, TXT_NEEDGREENKEY, false);
|
||||
S_StartSound(NULL, sfx_plroof);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// if the sector has an active thinker, use it
|
||||
sec = sides[line->sidenum[side^1]].sector;
|
||||
secnum = sec-sectors;
|
||||
if(sec->specialdata)
|
||||
{
|
||||
door = sec->specialdata;
|
||||
switch(line->special)
|
||||
{
|
||||
case 1: // ONLY FOR "RAISE" DOORS, NOT "OPEN"s
|
||||
case 26:
|
||||
case 27:
|
||||
case 28:
|
||||
if(door->direction == -1)
|
||||
{
|
||||
door->direction = 1; // go back up
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!thing->player)
|
||||
{ // Monsters don't close doors
|
||||
return;
|
||||
}
|
||||
door->direction = -1; // start going down immediately
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// for proper sound
|
||||
switch(line->special)
|
||||
{
|
||||
case 1: // NORMAL DOOR SOUND
|
||||
case 31:
|
||||
S_StartSound((mobj_t *)&sec->soundorg, sfx_doropn);
|
||||
//S_StartSound((mobj_t *)&sec->soundorg, sfx_dormov);
|
||||
break;
|
||||
default: // LOCKED DOOR SOUND
|
||||
S_StartSound((mobj_t *)&sec->soundorg, sfx_doropn);
|
||||
//S_StartSound((mobj_t *)&sec->soundorg, sfx_dormov);
|
||||
break;
|
||||
}
|
||||
|
||||
//
|
||||
// new door thinker
|
||||
//
|
||||
door = Z_Malloc (sizeof(*door), PU_LEVSPEC, 0);
|
||||
P_AddThinker(&door->thinker);
|
||||
sec->specialdata = door;
|
||||
door->thinker.function = T_VerticalDoor;
|
||||
door->sector = sec;
|
||||
door->direction = 1;
|
||||
switch(line->special)
|
||||
{
|
||||
case 1:
|
||||
case 26:
|
||||
case 27:
|
||||
case 28:
|
||||
door->type = normal;
|
||||
break;
|
||||
case 31:
|
||||
case 32:
|
||||
case 33:
|
||||
case 34:
|
||||
door->type = open;
|
||||
line->special = 0;
|
||||
break;
|
||||
}
|
||||
door->speed = VDOORSPEED;
|
||||
door->topwait = VDOORWAIT;
|
||||
|
||||
//
|
||||
// find the top and bottom of the movement range
|
||||
//
|
||||
door->topheight = P_FindLowestCeilingSurrounding(sec);
|
||||
door->topheight -= 4*FRACUNIT;
|
||||
}
|
||||
|
||||
//==================================================================
|
||||
//
|
||||
// Spawn a door that closes after 30 seconds
|
||||
//
|
||||
//==================================================================
|
||||
void P_SpawnDoorCloseIn30(sector_t *sec)
|
||||
{
|
||||
vldoor_t *door;
|
||||
|
||||
door = Z_Malloc(sizeof(*door), PU_LEVSPEC, 0);
|
||||
P_AddThinker(&door->thinker);
|
||||
sec->specialdata = door;
|
||||
sec->special = 0;
|
||||
door->thinker.function = T_VerticalDoor;
|
||||
door->sector = sec;
|
||||
door->direction = 0;
|
||||
door->type = normal;
|
||||
door->speed = VDOORSPEED;
|
||||
door->topcountdown = 30*35;
|
||||
}
|
||||
|
||||
//==================================================================
|
||||
//
|
||||
// Spawn a door that opens after 5 minutes
|
||||
//
|
||||
//==================================================================
|
||||
void P_SpawnDoorRaiseIn5Mins(sector_t *sec, int secnum)
|
||||
{
|
||||
vldoor_t *door;
|
||||
|
||||
door = Z_Malloc(sizeof(*door), PU_LEVSPEC, 0);
|
||||
P_AddThinker(&door->thinker);
|
||||
sec->specialdata = door;
|
||||
sec->special = 0;
|
||||
door->thinker.function = T_VerticalDoor;
|
||||
door->sector = sec;
|
||||
door->direction = 2;
|
||||
door->type = raiseIn5Mins;
|
||||
door->speed = VDOORSPEED;
|
||||
door->topheight = P_FindLowestCeilingSurrounding(sec);
|
||||
door->topheight -= 4*FRACUNIT;
|
||||
door->topwait = VDOORWAIT;
|
||||
door->topcountdown = 5*60*35;
|
||||
}
|
2636
Heretic Source/P_ENEMY.C
Normal file
2636
Heretic Source/P_ENEMY.C
Normal file
File diff suppressed because it is too large
Load diff
445
Heretic Source/P_FLOOR.C
Normal file
445
Heretic Source/P_FLOOR.C
Normal file
|
@ -0,0 +1,445 @@
|
|||
#include "DoomDef.h"
|
||||
#include "P_local.h"
|
||||
#include "soundst.h"
|
||||
|
||||
//==================================================================
|
||||
//==================================================================
|
||||
//
|
||||
// FLOORS
|
||||
//
|
||||
//==================================================================
|
||||
//==================================================================
|
||||
|
||||
|
||||
|
||||
//==================================================================
|
||||
//
|
||||
// Move a plane (floor or ceiling) and check for crushing
|
||||
//
|
||||
//==================================================================
|
||||
result_e T_MovePlane(sector_t *sector,fixed_t speed,
|
||||
fixed_t dest,boolean crush,int floorOrCeiling,int direction)
|
||||
{
|
||||
boolean flag;
|
||||
fixed_t lastpos;
|
||||
|
||||
switch(floorOrCeiling)
|
||||
{
|
||||
case 0: // FLOOR
|
||||
switch(direction)
|
||||
{
|
||||
case -1: // DOWN
|
||||
if (sector->floorheight - speed < dest)
|
||||
{
|
||||
lastpos = sector->floorheight;
|
||||
sector->floorheight = dest;
|
||||
flag = P_ChangeSector(sector,crush);
|
||||
if (flag == true)
|
||||
{
|
||||
sector->floorheight =lastpos;
|
||||
P_ChangeSector(sector,crush);
|
||||
//return crushed;
|
||||
}
|
||||
return pastdest;
|
||||
}
|
||||
else
|
||||
{
|
||||
lastpos = sector->floorheight;
|
||||
sector->floorheight -= speed;
|
||||
flag = P_ChangeSector(sector,crush);
|
||||
if (flag == true)
|
||||
{
|
||||
sector->floorheight = lastpos;
|
||||
P_ChangeSector(sector,crush);
|
||||
return crushed;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 1: // UP
|
||||
if (sector->floorheight + speed > dest)
|
||||
{
|
||||
lastpos = sector->floorheight;
|
||||
sector->floorheight = dest;
|
||||
flag = P_ChangeSector(sector,crush);
|
||||
if (flag == true)
|
||||
{
|
||||
sector->floorheight = lastpos;
|
||||
P_ChangeSector(sector,crush);
|
||||
//return crushed;
|
||||
}
|
||||
return pastdest;
|
||||
}
|
||||
else // COULD GET CRUSHED
|
||||
{
|
||||
lastpos = sector->floorheight;
|
||||
sector->floorheight += speed;
|
||||
flag = P_ChangeSector(sector,crush);
|
||||
if (flag == true)
|
||||
{
|
||||
if (crush == true)
|
||||
return crushed;
|
||||
sector->floorheight = lastpos;
|
||||
P_ChangeSector(sector,crush);
|
||||
return crushed;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 1: // CEILING
|
||||
switch(direction)
|
||||
{
|
||||
case -1: // DOWN
|
||||
if (sector->ceilingheight - speed < dest)
|
||||
{
|
||||
lastpos = sector->ceilingheight;
|
||||
sector->ceilingheight = dest;
|
||||
flag = P_ChangeSector(sector,crush);
|
||||
if (flag == true)
|
||||
{
|
||||
sector->ceilingheight = lastpos;
|
||||
P_ChangeSector(sector,crush);
|
||||
//return crushed;
|
||||
}
|
||||
return pastdest;
|
||||
}
|
||||
else // COULD GET CRUSHED
|
||||
{
|
||||
lastpos = sector->ceilingheight;
|
||||
sector->ceilingheight -= speed;
|
||||
flag = P_ChangeSector(sector,crush);
|
||||
if (flag == true)
|
||||
{
|
||||
if (crush == true)
|
||||
return crushed;
|
||||
sector->ceilingheight = lastpos;
|
||||
P_ChangeSector(sector,crush);
|
||||
return crushed;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 1: // UP
|
||||
if (sector->ceilingheight + speed > dest)
|
||||
{
|
||||
lastpos = sector->ceilingheight;
|
||||
sector->ceilingheight = dest;
|
||||
flag = P_ChangeSector(sector,crush);
|
||||
if (flag == true)
|
||||
{
|
||||
sector->ceilingheight = lastpos;
|
||||
P_ChangeSector(sector,crush);
|
||||
//return crushed;
|
||||
}
|
||||
return pastdest;
|
||||
}
|
||||
else
|
||||
{
|
||||
lastpos = sector->ceilingheight;
|
||||
sector->ceilingheight += speed;
|
||||
flag = P_ChangeSector(sector,crush);
|
||||
#if 0
|
||||
if (flag == true)
|
||||
{
|
||||
sector->ceilingheight = lastpos;
|
||||
P_ChangeSector(sector,crush);
|
||||
return crushed;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
//==================================================================
|
||||
//
|
||||
// MOVE A FLOOR TO IT'S DESTINATION (UP OR DOWN)
|
||||
//
|
||||
//==================================================================
|
||||
void T_MoveFloor(floormove_t *floor)
|
||||
{
|
||||
result_e res;
|
||||
|
||||
res = T_MovePlane(floor->sector,floor->speed,
|
||||
floor->floordestheight,floor->crush,0,floor->direction);
|
||||
if(!(leveltime&7))
|
||||
{
|
||||
S_StartSound((mobj_t *)&floor->sector->soundorg, sfx_dormov);
|
||||
}
|
||||
|
||||
if (res == pastdest)
|
||||
{
|
||||
floor->sector->specialdata = NULL;
|
||||
if(floor->type == raiseBuildStep)
|
||||
{
|
||||
S_StartSound((mobj_t *)&floor->sector->soundorg, sfx_pstop);
|
||||
}
|
||||
if (floor->direction == 1)
|
||||
switch(floor->type)
|
||||
{
|
||||
case donutRaise:
|
||||
floor->sector->special = floor->newspecial;
|
||||
floor->sector->floorpic = floor->texture;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
else if (floor->direction == -1)
|
||||
switch(floor->type)
|
||||
{
|
||||
case lowerAndChange:
|
||||
floor->sector->special = floor->newspecial;
|
||||
floor->sector->floorpic = floor->texture;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
P_RemoveThinker(&floor->thinker);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//==================================================================
|
||||
//
|
||||
// HANDLE FLOOR TYPES
|
||||
//
|
||||
//==================================================================
|
||||
int EV_DoFloor(line_t *line,floor_e floortype)
|
||||
{
|
||||
int secnum;
|
||||
int rtn;
|
||||
int i;
|
||||
sector_t *sec;
|
||||
floormove_t *floor;
|
||||
|
||||
secnum = -1;
|
||||
rtn = 0;
|
||||
while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0)
|
||||
{
|
||||
sec = §ors[secnum];
|
||||
|
||||
// ALREADY MOVING? IF SO, KEEP GOING...
|
||||
if (sec->specialdata)
|
||||
continue;
|
||||
|
||||
//
|
||||
// new floor thinker
|
||||
//
|
||||
rtn = 1;
|
||||
floor = Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0);
|
||||
P_AddThinker (&floor->thinker);
|
||||
sec->specialdata = floor;
|
||||
floor->thinker.function = T_MoveFloor;
|
||||
floor->type = floortype;
|
||||
floor->crush = false;
|
||||
switch(floortype)
|
||||
{
|
||||
case lowerFloor:
|
||||
floor->direction = -1;
|
||||
floor->sector = sec;
|
||||
floor->speed = FLOORSPEED;
|
||||
floor->floordestheight =
|
||||
P_FindHighestFloorSurrounding(sec);
|
||||
break;
|
||||
case lowerFloorToLowest:
|
||||
floor->direction = -1;
|
||||
floor->sector = sec;
|
||||
floor->speed = FLOORSPEED;
|
||||
floor->floordestheight =
|
||||
P_FindLowestFloorSurrounding(sec);
|
||||
break;
|
||||
case turboLower:
|
||||
floor->direction = -1;
|
||||
floor->sector = sec;
|
||||
floor->speed = FLOORSPEED * 4;
|
||||
floor->floordestheight = (8*FRACUNIT) +
|
||||
P_FindHighestFloorSurrounding(sec);
|
||||
break;
|
||||
case raiseFloorCrush:
|
||||
floor->crush = true;
|
||||
case raiseFloor:
|
||||
floor->direction = 1;
|
||||
floor->sector = sec;
|
||||
floor->speed = FLOORSPEED;
|
||||
floor->floordestheight =
|
||||
P_FindLowestCeilingSurrounding(sec);
|
||||
if (floor->floordestheight > sec->ceilingheight)
|
||||
floor->floordestheight = sec->ceilingheight;
|
||||
floor->floordestheight -= (8*FRACUNIT)*
|
||||
(floortype == raiseFloorCrush);
|
||||
break;
|
||||
case raiseFloorToNearest:
|
||||
floor->direction = 1;
|
||||
floor->sector = sec;
|
||||
floor->speed = FLOORSPEED;
|
||||
floor->floordestheight =
|
||||
P_FindNextHighestFloor(sec,sec->floorheight);
|
||||
break;
|
||||
case raiseFloor24:
|
||||
floor->direction = 1;
|
||||
floor->sector = sec;
|
||||
floor->speed = FLOORSPEED;
|
||||
floor->floordestheight = floor->sector->floorheight +
|
||||
24 * FRACUNIT;
|
||||
break;
|
||||
case raiseFloor24AndChange:
|
||||
floor->direction = 1;
|
||||
floor->sector = sec;
|
||||
floor->speed = FLOORSPEED;
|
||||
floor->floordestheight = floor->sector->floorheight +
|
||||
24 * FRACUNIT;
|
||||
sec->floorpic = line->frontsector->floorpic;
|
||||
sec->special = line->frontsector->special;
|
||||
break;
|
||||
case raiseToTexture:
|
||||
{
|
||||
int minsize = MAXINT;
|
||||
side_t *side;
|
||||
|
||||
floor->direction = 1;
|
||||
floor->sector = sec;
|
||||
floor->speed = FLOORSPEED;
|
||||
for (i = 0; i < sec->linecount; i++)
|
||||
if (twoSided (secnum, i) )
|
||||
{
|
||||
side = getSide(secnum,i,0);
|
||||
if (side->bottomtexture >= 0)
|
||||
if (textureheight[side->bottomtexture] <
|
||||
minsize)
|
||||
minsize =
|
||||
textureheight[side->bottomtexture];
|
||||
side = getSide(secnum,i,1);
|
||||
if (side->bottomtexture >= 0)
|
||||
if (textureheight[side->bottomtexture] <
|
||||
minsize)
|
||||
minsize =
|
||||
textureheight[side->bottomtexture];
|
||||
}
|
||||
floor->floordestheight = floor->sector->floorheight +
|
||||
minsize;
|
||||
}
|
||||
break;
|
||||
case lowerAndChange:
|
||||
floor->direction = -1;
|
||||
floor->sector = sec;
|
||||
floor->speed = FLOORSPEED;
|
||||
floor->floordestheight =
|
||||
P_FindLowestFloorSurrounding(sec);
|
||||
floor->texture = sec->floorpic;
|
||||
for (i = 0; i < sec->linecount; i++)
|
||||
if ( twoSided(secnum, i) )
|
||||
{
|
||||
if (getSide(secnum,i,0)->sector-sectors == secnum)
|
||||
{
|
||||
sec = getSector(secnum,i,1);
|
||||
floor->texture = sec->floorpic;
|
||||
floor->newspecial = sec->special;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
sec = getSector(secnum,i,0);
|
||||
floor->texture = sec->floorpic;
|
||||
floor->newspecial = sec->special;
|
||||
break;
|
||||
}
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return rtn;
|
||||
}
|
||||
|
||||
//==================================================================
|
||||
//
|
||||
// BUILD A STAIRCASE!
|
||||
//
|
||||
//==================================================================
|
||||
int EV_BuildStairs(line_t *line, fixed_t stepDelta)
|
||||
{
|
||||
int secnum;
|
||||
int height;
|
||||
int i;
|
||||
int newsecnum;
|
||||
int texture;
|
||||
int ok;
|
||||
int rtn;
|
||||
sector_t *sec, *tsec;
|
||||
floormove_t *floor;
|
||||
|
||||
secnum = -1;
|
||||
rtn = 0;
|
||||
while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0)
|
||||
{
|
||||
sec = §ors[secnum];
|
||||
|
||||
// ALREADY MOVING? IF SO, KEEP GOING...
|
||||
if (sec->specialdata)
|
||||
continue;
|
||||
|
||||
//
|
||||
// new floor thinker
|
||||
//
|
||||
rtn = 1;
|
||||
height = sec->floorheight+stepDelta;
|
||||
floor = Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0);
|
||||
P_AddThinker (&floor->thinker);
|
||||
sec->specialdata = floor;
|
||||
floor->thinker.function = T_MoveFloor;
|
||||
floor->type = raiseBuildStep;
|
||||
floor->direction = 1;
|
||||
floor->sector = sec;
|
||||
floor->speed = FLOORSPEED;
|
||||
floor->floordestheight = height;
|
||||
|
||||
texture = sec->floorpic;
|
||||
|
||||
//
|
||||
// Find next sector to raise
|
||||
// 1. Find 2-sided line with same sector side[0]
|
||||
// 2. Other side is the next sector to raise
|
||||
//
|
||||
do
|
||||
{
|
||||
ok = 0;
|
||||
for (i = 0;i < sec->linecount;i++)
|
||||
{
|
||||
if ( !((sec->lines[i])->flags & ML_TWOSIDED) )
|
||||
continue;
|
||||
|
||||
tsec = (sec->lines[i])->frontsector;
|
||||
newsecnum = tsec-sectors;
|
||||
if (secnum != newsecnum)
|
||||
continue;
|
||||
tsec = (sec->lines[i])->backsector;
|
||||
newsecnum = tsec - sectors;
|
||||
if (tsec->floorpic != texture)
|
||||
continue;
|
||||
|
||||
height += stepDelta;
|
||||
if (tsec->specialdata)
|
||||
continue;
|
||||
|
||||
sec = tsec;
|
||||
secnum = newsecnum;
|
||||
floor = Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0);
|
||||
P_AddThinker (&floor->thinker);
|
||||
sec->specialdata = floor;
|
||||
floor->thinker.function = T_MoveFloor;
|
||||
floor->type = raiseBuildStep;
|
||||
floor->direction = 1;
|
||||
floor->sector = sec;
|
||||
floor->speed = FLOORSPEED;
|
||||
floor->floordestheight = height;
|
||||
ok = 1;
|
||||
break;
|
||||
}
|
||||
} while(ok);
|
||||
}
|
||||
return(rtn);
|
||||
}
|
1473
Heretic Source/P_INTER.C
Normal file
1473
Heretic Source/P_INTER.C
Normal file
File diff suppressed because it is too large
Load diff
258
Heretic Source/P_LIGHTS.C
Normal file
258
Heretic Source/P_LIGHTS.C
Normal file
|
@ -0,0 +1,258 @@
|
|||
#include "DoomDef.h"
|
||||
#include "P_local.h"
|
||||
|
||||
//==================================================================
|
||||
//==================================================================
|
||||
//
|
||||
// BROKEN LIGHT FLASHING
|
||||
//
|
||||
//==================================================================
|
||||
//==================================================================
|
||||
|
||||
//==================================================================
|
||||
//
|
||||
// T_LightFlash
|
||||
//
|
||||
// After the map has been loaded, scan each sector for specials
|
||||
// that spawn thinkers
|
||||
//
|
||||
//==================================================================
|
||||
void T_LightFlash (lightflash_t *flash)
|
||||
{
|
||||
if (--flash->count)
|
||||
return;
|
||||
|
||||
if (flash->sector->lightlevel == flash->maxlight)
|
||||
{
|
||||
flash-> sector->lightlevel = flash->minlight;
|
||||
flash->count = (P_Random()&flash->mintime)+1;
|
||||
}
|
||||
else
|
||||
{
|
||||
flash-> sector->lightlevel = flash->maxlight;
|
||||
flash->count = (P_Random()&flash->maxtime)+1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
//==================================================================
|
||||
//
|
||||
// P_SpawnLightFlash
|
||||
//
|
||||
// After the map has been loaded, scan each sector for specials that spawn thinkers
|
||||
//
|
||||
//==================================================================
|
||||
void P_SpawnLightFlash (sector_t *sector)
|
||||
{
|
||||
lightflash_t *flash;
|
||||
|
||||
sector->special = 0; // nothing special about it during gameplay
|
||||
|
||||
flash = Z_Malloc ( sizeof(*flash), PU_LEVSPEC, 0);
|
||||
P_AddThinker (&flash->thinker);
|
||||
flash->thinker.function = T_LightFlash;
|
||||
flash->sector = sector;
|
||||
flash->maxlight = sector->lightlevel;
|
||||
|
||||
flash->minlight = P_FindMinSurroundingLight(sector,sector->lightlevel);
|
||||
flash->maxtime = 64;
|
||||
flash->mintime = 7;
|
||||
flash->count = (P_Random()&flash->maxtime)+1;
|
||||
}
|
||||
|
||||
//==================================================================
|
||||
//
|
||||
// STROBE LIGHT FLASHING
|
||||
//
|
||||
//==================================================================
|
||||
|
||||
//==================================================================
|
||||
//
|
||||
// T_StrobeFlash
|
||||
//
|
||||
// After the map has been loaded, scan each sector for specials that spawn thinkers
|
||||
//
|
||||
//==================================================================
|
||||
void T_StrobeFlash (strobe_t *flash)
|
||||
{
|
||||
if (--flash->count)
|
||||
return;
|
||||
|
||||
if (flash->sector->lightlevel == flash->minlight)
|
||||
{
|
||||
flash-> sector->lightlevel = flash->maxlight;
|
||||
flash->count = flash->brighttime;
|
||||
}
|
||||
else
|
||||
{
|
||||
flash-> sector->lightlevel = flash->minlight;
|
||||
flash->count =flash->darktime;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//==================================================================
|
||||
//
|
||||
// P_SpawnLightFlash
|
||||
//
|
||||
// After the map has been loaded, scan each sector for specials that spawn thinkers
|
||||
//
|
||||
//==================================================================
|
||||
void P_SpawnStrobeFlash (sector_t *sector,int fastOrSlow, int inSync)
|
||||
{
|
||||
strobe_t *flash;
|
||||
|
||||
flash = Z_Malloc ( sizeof(*flash), PU_LEVSPEC, 0);
|
||||
P_AddThinker (&flash->thinker);
|
||||
flash->sector = sector;
|
||||
flash->darktime = fastOrSlow;
|
||||
flash->brighttime = STROBEBRIGHT;
|
||||
flash->thinker.function = T_StrobeFlash;
|
||||
flash->maxlight = sector->lightlevel;
|
||||
flash->minlight = P_FindMinSurroundingLight(sector, sector->lightlevel);
|
||||
|
||||
if (flash->minlight == flash->maxlight)
|
||||
flash->minlight = 0;
|
||||
sector->special = 0; // nothing special about it during gameplay
|
||||
|
||||
if (!inSync)
|
||||
flash->count = (P_Random()&7)+1;
|
||||
else
|
||||
flash->count = 1;
|
||||
}
|
||||
|
||||
//==================================================================
|
||||
//
|
||||
// Start strobing lights (usually from a trigger)
|
||||
//
|
||||
//==================================================================
|
||||
void EV_StartLightStrobing(line_t *line)
|
||||
{
|
||||
int secnum;
|
||||
sector_t *sec;
|
||||
|
||||
secnum = -1;
|
||||
while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0)
|
||||
{
|
||||
sec = §ors[secnum];
|
||||
if (sec->specialdata)
|
||||
continue;
|
||||
|
||||
P_SpawnStrobeFlash (sec,SLOWDARK, 0);
|
||||
}
|
||||
}
|
||||
|
||||
//==================================================================
|
||||
//
|
||||
// TURN LINE'S TAG LIGHTS OFF
|
||||
//
|
||||
//==================================================================
|
||||
void EV_TurnTagLightsOff(line_t *line)
|
||||
{
|
||||
int i;
|
||||
int j;
|
||||
int min;
|
||||
sector_t *sector;
|
||||
sector_t *tsec;
|
||||
line_t *templine;
|
||||
|
||||
sector = sectors;
|
||||
for (j = 0;j < numsectors; j++, sector++)
|
||||
if (sector->tag == line->tag)
|
||||
{
|
||||
min = sector->lightlevel;
|
||||
for (i = 0;i < sector->linecount; i++)
|
||||
{
|
||||
templine = sector->lines[i];
|
||||
tsec = getNextSector(templine,sector);
|
||||
if (!tsec)
|
||||
continue;
|
||||
if (tsec->lightlevel < min)
|
||||
min = tsec->lightlevel;
|
||||
}
|
||||
sector->lightlevel = min;
|
||||
}
|
||||
}
|
||||
|
||||
//==================================================================
|
||||
//
|
||||
// TURN LINE'S TAG LIGHTS ON
|
||||
//
|
||||
//==================================================================
|
||||
void EV_LightTurnOn(line_t *line, int bright)
|
||||
{
|
||||
int i;
|
||||
int j;
|
||||
sector_t *sector;
|
||||
sector_t *temp;
|
||||
line_t *templine;
|
||||
|
||||
sector = sectors;
|
||||
|
||||
for (i=0;i<numsectors;i++, sector++)
|
||||
if (sector->tag == line->tag)
|
||||
{
|
||||
//
|
||||
// bright = 0 means to search for highest
|
||||
// light level surrounding sector
|
||||
//
|
||||
if (!bright)
|
||||
{
|
||||
for (j = 0;j < sector->linecount; j++)
|
||||
{
|
||||
templine = sector->lines[j];
|
||||
temp = getNextSector(templine,sector);
|
||||
if (!temp)
|
||||
continue;
|
||||
if (temp->lightlevel > bright)
|
||||
bright = temp->lightlevel;
|
||||
}
|
||||
}
|
||||
sector-> lightlevel = bright;
|
||||
}
|
||||
}
|
||||
|
||||
//==================================================================
|
||||
//
|
||||
// Spawn glowing light
|
||||
//
|
||||
//==================================================================
|
||||
void T_Glow(glow_t *g)
|
||||
{
|
||||
switch(g->direction)
|
||||
{
|
||||
case -1: // DOWN
|
||||
g->sector->lightlevel -= GLOWSPEED;
|
||||
if (g->sector->lightlevel <= g->minlight)
|
||||
{
|
||||
g->sector->lightlevel += GLOWSPEED;
|
||||
g->direction = 1;
|
||||
}
|
||||
break;
|
||||
case 1: // UP
|
||||
g->sector->lightlevel += GLOWSPEED;
|
||||
if (g->sector->lightlevel >= g->maxlight)
|
||||
{
|
||||
g->sector->lightlevel -= GLOWSPEED;
|
||||
g->direction = -1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void P_SpawnGlowingLight(sector_t *sector)
|
||||
{
|
||||
glow_t *g;
|
||||
|
||||
g = Z_Malloc( sizeof(*g), PU_LEVSPEC, 0);
|
||||
P_AddThinker(&g->thinker);
|
||||
g->sector = sector;
|
||||
g->minlight = P_FindMinSurroundingLight(sector,sector->lightlevel);
|
||||
g->maxlight = sector->lightlevel;
|
||||
g->thinker.function = T_Glow;
|
||||
g->direction = -1;
|
||||
|
||||
sector->special = 0;
|
||||
}
|
||||
|
262
Heretic Source/P_LOCAL.H
Normal file
262
Heretic Source/P_LOCAL.H
Normal file
|
@ -0,0 +1,262 @@
|
|||
|
||||
// P_local.h
|
||||
|
||||
#ifndef __P_LOCAL__
|
||||
#define __P_LOCAL__
|
||||
|
||||
#ifndef __R_LOCAL__
|
||||
#include "R_local.h"
|
||||
#endif
|
||||
|
||||
#define STARTREDPALS 1
|
||||
#define STARTBONUSPALS 9
|
||||
#define NUMREDPALS 8
|
||||
#define NUMBONUSPALS 4
|
||||
|
||||
#define FOOTCLIPSIZE 10*FRACUNIT
|
||||
|
||||
#define TOCENTER -8
|
||||
#define FLOATSPEED (FRACUNIT*4)
|
||||
|
||||
#define MAXHEALTH 100
|
||||
#define MAXCHICKENHEALTH 30
|
||||
#define VIEWHEIGHT (41*FRACUNIT)
|
||||
|
||||
// mapblocks are used to check movement against lines and things
|
||||
#define MAPBLOCKUNITS 128
|
||||
#define MAPBLOCKSIZE (MAPBLOCKUNITS*FRACUNIT)
|
||||
#define MAPBLOCKSHIFT (FRACBITS+7)
|
||||
#define MAPBMASK (MAPBLOCKSIZE-1)
|
||||
#define MAPBTOFRAC (MAPBLOCKSHIFT-FRACBITS)
|
||||
|
||||
// player radius for movement checking
|
||||
#define PLAYERRADIUS 16*FRACUNIT
|
||||
|
||||
// MAXRADIUS is for precalculated sector block boxes
|
||||
// the spider demon is larger, but we don't have any moving sectors
|
||||
// nearby
|
||||
#define MAXRADIUS 32*FRACUNIT
|
||||
|
||||
#define GRAVITY FRACUNIT
|
||||
#define MAXMOVE (30*FRACUNIT)
|
||||
|
||||
#define USERANGE (64*FRACUNIT)
|
||||
#define MELEERANGE (64*FRACUNIT)
|
||||
#define MISSILERANGE (32*64*FRACUNIT)
|
||||
|
||||
typedef enum
|
||||
{
|
||||
DI_EAST,
|
||||
DI_NORTHEAST,
|
||||
DI_NORTH,
|
||||
DI_NORTHWEST,
|
||||
DI_WEST,
|
||||
DI_SOUTHWEST,
|
||||
DI_SOUTH,
|
||||
DI_SOUTHEAST,
|
||||
DI_NODIR,
|
||||
NUMDIRS
|
||||
} dirtype_t;
|
||||
|
||||
#define BASETHRESHOLD 100 // follow a player exlusively for 3 seconds
|
||||
|
||||
// ***** P_TICK *****
|
||||
|
||||
extern thinker_t thinkercap; // both the head and tail of the thinker list
|
||||
extern int TimerGame; // tic countdown for deathmatch
|
||||
|
||||
void P_InitThinkers(void);
|
||||
void P_AddThinker(thinker_t *thinker);
|
||||
void P_RemoveThinker(thinker_t *thinker);
|
||||
|
||||
// ***** P_PSPR *****
|
||||
|
||||
#define USE_GWND_AMMO_1 1
|
||||
#define USE_GWND_AMMO_2 1
|
||||
#define USE_CBOW_AMMO_1 1
|
||||
#define USE_CBOW_AMMO_2 1
|
||||
#define USE_BLSR_AMMO_1 1
|
||||
#define USE_BLSR_AMMO_2 5
|
||||
#define USE_SKRD_AMMO_1 1
|
||||
#define USE_SKRD_AMMO_2 5
|
||||
#define USE_PHRD_AMMO_1 1
|
||||
#define USE_PHRD_AMMO_2 1
|
||||
#define USE_MACE_AMMO_1 1
|
||||
#define USE_MACE_AMMO_2 5
|
||||
|
||||
void P_OpenWeapons(void);
|
||||
void P_CloseWeapons(void);
|
||||
void P_AddMaceSpot(mapthing_t *mthing);
|
||||
void P_RepositionMace(mobj_t *mo);
|
||||
void P_SetPsprite(player_t *player, int position, statenum_t stnum);
|
||||
void P_SetupPsprites(player_t *curplayer);
|
||||
void P_MovePsprites(player_t *curplayer);
|
||||
void P_DropWeapon(player_t *player);
|
||||
void P_ActivateBeak(player_t *player);
|
||||
void P_PostChickenWeapon(player_t *player, weapontype_t weapon);
|
||||
void P_UpdateBeak(player_t *player, pspdef_t *psp);
|
||||
|
||||
// ***** P_USER *****
|
||||
|
||||
void P_PlayerThink(player_t *player);
|
||||
void P_Thrust(player_t *player, angle_t angle, fixed_t move);
|
||||
void P_PlayerRemoveArtifact(player_t *player, int slot);
|
||||
void P_PlayerUseArtifact(player_t *player, artitype_t arti);
|
||||
boolean P_UseArtifact(player_t *player, artitype_t arti);
|
||||
int P_GetPlayerNum(player_t *player);
|
||||
|
||||
// ***** P_MOBJ *****
|
||||
|
||||
#define FLOOR_SOLID 0
|
||||
#define FLOOR_WATER 1
|
||||
#define FLOOR_LAVA 2
|
||||
#define FLOOR_SLUDGE 3
|
||||
|
||||
#define ONFLOORZ MININT
|
||||
#define ONCEILINGZ MAXINT
|
||||
#define FLOATRANDZ (MAXINT-1)
|
||||
|
||||
extern mobjtype_t PuffType;
|
||||
extern mobj_t *MissileMobj;
|
||||
|
||||
mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type);
|
||||
void P_RemoveMobj(mobj_t *th);
|
||||
boolean P_SetMobjState(mobj_t *mobj, statenum_t state);
|
||||
boolean P_SetMobjStateNF(mobj_t *mobj, statenum_t state);
|
||||
void P_ThrustMobj(mobj_t *mo, angle_t angle, fixed_t move);
|
||||
int P_FaceMobj(mobj_t *source, mobj_t *target, angle_t *delta);
|
||||
boolean P_SeekerMissile(mobj_t *actor, angle_t thresh, angle_t turnMax);
|
||||
void P_MobjThinker(mobj_t *mobj);
|
||||
void P_BlasterMobjThinker(mobj_t *mobj);
|
||||
void P_SpawnPuff(fixed_t x, fixed_t y, fixed_t z);
|
||||
void P_SpawnBlood(fixed_t x, fixed_t y, fixed_t z, int damage);
|
||||
void P_BloodSplatter(fixed_t x, fixed_t y, fixed_t z, mobj_t *originator);
|
||||
void P_RipperBlood(mobj_t *mo);
|
||||
int P_GetThingFloorType(mobj_t *thing);
|
||||
int P_HitFloor(mobj_t *thing);
|
||||
boolean P_CheckMissileSpawn(mobj_t *missile);
|
||||
mobj_t *P_SpawnMissile(mobj_t *source, mobj_t *dest, mobjtype_t type);
|
||||
mobj_t *P_SpawnMissileAngle(mobj_t *source, mobjtype_t type,
|
||||
angle_t angle, fixed_t momz);
|
||||
mobj_t *P_SpawnPlayerMissile(mobj_t *source, mobjtype_t type);
|
||||
mobj_t *P_SPMAngle(mobj_t *source, mobjtype_t type, angle_t angle);
|
||||
|
||||
// ***** P_ENEMY *****
|
||||
|
||||
void P_NoiseAlert (mobj_t *target, mobj_t *emmiter);
|
||||
void P_InitMonsters(void);
|
||||
void P_AddBossSpot(fixed_t x, fixed_t y, angle_t angle);
|
||||
void P_Massacre(void);
|
||||
void P_DSparilTeleport(mobj_t *actor);
|
||||
|
||||
// ***** P_MAPUTL *****
|
||||
|
||||
typedef struct
|
||||
{
|
||||
fixed_t x, y, dx, dy;
|
||||
} divline_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
fixed_t frac; // along trace line
|
||||
boolean isaline;
|
||||
union {
|
||||
mobj_t *thing;
|
||||
line_t *line;
|
||||
} d;
|
||||
} intercept_t;
|
||||
|
||||
#define MAXINTERCEPTS 128
|
||||
extern intercept_t intercepts[MAXINTERCEPTS], *intercept_p;
|
||||
typedef boolean (*traverser_t) (intercept_t *in);
|
||||
|
||||
|
||||
fixed_t P_AproxDistance (fixed_t dx, fixed_t dy);
|
||||
int P_PointOnLineSide (fixed_t x, fixed_t y, line_t *line);
|
||||
int P_PointOnDivlineSide (fixed_t x, fixed_t y, divline_t *line);
|
||||
void P_MakeDivline (line_t *li, divline_t *dl);
|
||||
fixed_t P_InterceptVector (divline_t *v2, divline_t *v1);
|
||||
int P_BoxOnLineSide (fixed_t *tmbox, line_t *ld);
|
||||
|
||||
extern fixed_t opentop, openbottom, openrange;
|
||||
extern fixed_t lowfloor;
|
||||
void P_LineOpening (line_t *linedef);
|
||||
|
||||
boolean P_BlockLinesIterator (int x, int y, boolean(*func)(line_t*) );
|
||||
boolean P_BlockThingsIterator (int x, int y, boolean(*func)(mobj_t*) );
|
||||
|
||||
#define PT_ADDLINES 1
|
||||
#define PT_ADDTHINGS 2
|
||||
#define PT_EARLYOUT 4
|
||||
|
||||
extern divline_t trace;
|
||||
boolean P_PathTraverse (fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2,
|
||||
int flags, boolean (*trav) (intercept_t *));
|
||||
|
||||
void P_UnsetThingPosition (mobj_t *thing);
|
||||
void P_SetThingPosition (mobj_t *thing);
|
||||
|
||||
// ***** P_MAP *****
|
||||
|
||||
extern boolean floatok; // if true, move would be ok if
|
||||
extern fixed_t tmfloorz, tmceilingz; // within tmfloorz - tmceilingz
|
||||
|
||||
extern line_t *ceilingline;
|
||||
boolean P_TestMobjLocation(mobj_t *mobj);
|
||||
boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y);
|
||||
mobj_t *P_CheckOnmobj(mobj_t *thing);
|
||||
void P_FakeZMovement(mobj_t *mo);
|
||||
boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y);
|
||||
boolean P_TeleportMove(mobj_t *thing, fixed_t x, fixed_t y);
|
||||
void P_SlideMove(mobj_t *mo);
|
||||
boolean P_CheckSight(mobj_t *t1, mobj_t *t2);
|
||||
void P_UseLines(player_t *player);
|
||||
|
||||
boolean P_ChangeSector (sector_t *sector, boolean crunch);
|
||||
|
||||
extern mobj_t *linetarget; // who got hit (or NULL)
|
||||
fixed_t P_AimLineAttack (mobj_t *t1, angle_t angle, fixed_t distance);
|
||||
|
||||
void P_LineAttack (mobj_t *t1, angle_t angle, fixed_t distance, fixed_t slope, int damage);
|
||||
|
||||
void P_RadiusAttack (mobj_t *spot, mobj_t *source, int damage);
|
||||
|
||||
// ***** P_SETUP *****
|
||||
|
||||
extern byte *rejectmatrix; // for fast sight rejection
|
||||
extern short *blockmaplump; // offsets in blockmap are from here
|
||||
extern short *blockmap;
|
||||
extern int bmapwidth, bmapheight; // in mapblocks
|
||||
extern fixed_t bmaporgx, bmaporgy; // origin of block map
|
||||
extern mobj_t **blocklinks; // for thing chains
|
||||
|
||||
// ***** P_INTER *****
|
||||
|
||||
extern int maxammo[NUMAMMO];
|
||||
extern int clipammo[NUMAMMO];
|
||||
|
||||
void P_SetMessage(player_t *player, char *message, boolean ultmsg);
|
||||
void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher);
|
||||
void P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source,
|
||||
int damage);
|
||||
boolean P_GiveAmmo(player_t *player, ammotype_t ammo, int count);
|
||||
boolean P_GiveArtifact(player_t *player, artitype_t arti, mobj_t *mo);
|
||||
boolean P_GiveBody(player_t *player, int num);
|
||||
boolean P_GivePower(player_t *player, powertype_t power);
|
||||
boolean P_ChickenMorphPlayer(player_t *player);
|
||||
|
||||
// ***** AM_MAP *****
|
||||
|
||||
boolean AM_Responder(event_t *ev);
|
||||
void AM_Ticker(void);
|
||||
void AM_Drawer(void);
|
||||
|
||||
// ***** SB_BAR *****
|
||||
|
||||
extern int SB_state;
|
||||
extern int ArtifactFlash;
|
||||
void SB_PaletteFlash(void);
|
||||
|
||||
#include "P_spec.h"
|
||||
|
||||
#endif // __P_LOCAL__
|
1638
Heretic Source/P_MAP.C
Normal file
1638
Heretic Source/P_MAP.C
Normal file
File diff suppressed because it is too large
Load diff
760
Heretic Source/P_MAPUTL.C
Normal file
760
Heretic Source/P_MAPUTL.C
Normal file
|
@ -0,0 +1,760 @@
|
|||
|
||||
// P_maputl.c
|
||||
|
||||
#include "DoomDef.h"
|
||||
#include "P_local.h"
|
||||
|
||||
|
||||
/*
|
||||
===================
|
||||
=
|
||||
= P_AproxDistance
|
||||
=
|
||||
= Gives an estimation of distance (not exact)
|
||||
=
|
||||
===================
|
||||
*/
|
||||
|
||||
fixed_t P_AproxDistance (fixed_t dx, fixed_t dy)
|
||||
{
|
||||
dx = abs(dx);
|
||||
dy = abs(dy);
|
||||
if (dx < dy)
|
||||
return dx+dy-(dx>>1);
|
||||
return dx+dy-(dy>>1);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
==================
|
||||
=
|
||||
= P_PointOnLineSide
|
||||
=
|
||||
= Returns 0 or 1
|
||||
==================
|
||||
*/
|
||||
|
||||
int P_PointOnLineSide (fixed_t x, fixed_t y, line_t *line)
|
||||
{
|
||||
fixed_t dx,dy;
|
||||
fixed_t left, right;
|
||||
|
||||
if (!line->dx)
|
||||
{
|
||||
if (x <= line->v1->x)
|
||||
return line->dy > 0;
|
||||
return line->dy < 0;
|
||||
}
|
||||
if (!line->dy)
|
||||
{
|
||||
if (y <= line->v1->y)
|
||||
return line->dx < 0;
|
||||
return line->dx > 0;
|
||||
}
|
||||
|
||||
dx = (x - line->v1->x);
|
||||
dy = (y - line->v1->y);
|
||||
|
||||
left = FixedMul ( line->dy>>FRACBITS , dx );
|
||||
right = FixedMul ( dy , line->dx>>FRACBITS );
|
||||
|
||||
if (right < left)
|
||||
return 0; // front side
|
||||
return 1; // back side
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=================
|
||||
=
|
||||
= P_BoxOnLineSide
|
||||
=
|
||||
= Considers the line to be infinite
|
||||
= Returns side 0 or 1, -1 if box crosses the line
|
||||
=================
|
||||
*/
|
||||
|
||||
int P_BoxOnLineSide (fixed_t *tmbox, line_t *ld)
|
||||
{
|
||||
int p1, p2;
|
||||
|
||||
switch (ld->slopetype)
|
||||
{
|
||||
case ST_HORIZONTAL:
|
||||
p1 = tmbox[BOXTOP] > ld->v1->y;
|
||||
p2 = tmbox[BOXBOTTOM] > ld->v1->y;
|
||||
if (ld->dx < 0)
|
||||
{
|
||||
p1 ^= 1;
|
||||
p2 ^= 1;
|
||||
}
|
||||
break;
|
||||
case ST_VERTICAL:
|
||||
p1 = tmbox[BOXRIGHT] < ld->v1->x;
|
||||
p2 = tmbox[BOXLEFT] < ld->v1->x;
|
||||
if (ld->dy < 0)
|
||||
{
|
||||
p1 ^= 1;
|
||||
p2 ^= 1;
|
||||
}
|
||||
break;
|
||||
case ST_POSITIVE:
|
||||
p1 = P_PointOnLineSide (tmbox[BOXLEFT], tmbox[BOXTOP], ld);
|
||||
p2 = P_PointOnLineSide (tmbox[BOXRIGHT], tmbox[BOXBOTTOM], ld);
|
||||
break;
|
||||
case ST_NEGATIVE:
|
||||
p1 = P_PointOnLineSide (tmbox[BOXRIGHT], tmbox[BOXTOP], ld);
|
||||
p2 = P_PointOnLineSide (tmbox[BOXLEFT], tmbox[BOXBOTTOM], ld);
|
||||
break;
|
||||
}
|
||||
|
||||
if (p1 == p2)
|
||||
return p1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
=
|
||||
= P_PointOnDivlineSide
|
||||
=
|
||||
= Returns 0 or 1
|
||||
==================
|
||||
*/
|
||||
|
||||
int P_PointOnDivlineSide (fixed_t x, fixed_t y, divline_t *line)
|
||||
{
|
||||
fixed_t dx,dy;
|
||||
fixed_t left, right;
|
||||
|
||||
if (!line->dx)
|
||||
{
|
||||
if (x <= line->x)
|
||||
return line->dy > 0;
|
||||
return line->dy < 0;
|
||||
}
|
||||
if (!line->dy)
|
||||
{
|
||||
if (y <= line->y)
|
||||
return line->dx < 0;
|
||||
return line->dx > 0;
|
||||
}
|
||||
|
||||
dx = (x - line->x);
|
||||
dy = (y - line->y);
|
||||
|
||||
// try to quickly decide by looking at sign bits
|
||||
if ( (line->dy ^ line->dx ^ dx ^ dy)&0x80000000 )
|
||||
{
|
||||
if ( (line->dy ^ dx) & 0x80000000 )
|
||||
return 1; // (left is negative)
|
||||
return 0;
|
||||
}
|
||||
|
||||
left = FixedMul ( line->dy>>8, dx>>8 );
|
||||
right = FixedMul ( dy>>8 , line->dx>>8 );
|
||||
|
||||
if (right < left)
|
||||
return 0; // front side
|
||||
return 1; // back side
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
==============
|
||||
=
|
||||
= P_MakeDivline
|
||||
=
|
||||
==============
|
||||
*/
|
||||
|
||||
void P_MakeDivline (line_t *li, divline_t *dl)
|
||||
{
|
||||
dl->x = li->v1->x;
|
||||
dl->y = li->v1->y;
|
||||
dl->dx = li->dx;
|
||||
dl->dy = li->dy;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===============
|
||||
=
|
||||
= P_InterceptVector
|
||||
=
|
||||
= Returns the fractional intercept point along the first divline
|
||||
=
|
||||
= This is only called by the addthings and addlines traversers
|
||||
===============
|
||||
*/
|
||||
|
||||
fixed_t P_InterceptVector (divline_t *v2, divline_t *v1)
|
||||
{
|
||||
#if 1
|
||||
fixed_t frac, num, den;
|
||||
|
||||
den = FixedMul (v1->dy>>8,v2->dx) - FixedMul(v1->dx>>8,v2->dy);
|
||||
if (den == 0)
|
||||
return 0;
|
||||
// I_Error ("P_InterceptVector: parallel");
|
||||
num = FixedMul ( (v1->x - v2->x)>>8 ,v1->dy) +
|
||||
FixedMul ( (v2->y - v1->y)>>8 , v1->dx);
|
||||
frac = FixedDiv (num , den);
|
||||
|
||||
return frac;
|
||||
#else
|
||||
float frac, num, den, v1x,v1y,v1dx,v1dy,v2x,v2y,v2dx,v2dy;
|
||||
|
||||
v1x = (float)v1->x/FRACUNIT;
|
||||
v1y = (float)v1->y/FRACUNIT;
|
||||
v1dx = (float)v1->dx/FRACUNIT;
|
||||
v1dy = (float)v1->dy/FRACUNIT;
|
||||
v2x = (float)v2->x/FRACUNIT;
|
||||
v2y = (float)v2->y/FRACUNIT;
|
||||
v2dx = (float)v2->dx/FRACUNIT;
|
||||
v2dy = (float)v2->dy/FRACUNIT;
|
||||
|
||||
den = v1dy*v2dx - v1dx*v2dy;
|
||||
if (den == 0)
|
||||
return 0; // parallel
|
||||
num = (v1x - v2x)*v1dy + (v2y - v1y)*v1dx;
|
||||
frac = num / den;
|
||||
|
||||
return frac*FRACUNIT;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
=
|
||||
= P_LineOpening
|
||||
=
|
||||
= Sets opentop and openbottom to the window through a two sided line
|
||||
= OPTIMIZE: keep this precalculated
|
||||
==================
|
||||
*/
|
||||
|
||||
fixed_t opentop, openbottom, openrange;
|
||||
fixed_t lowfloor;
|
||||
|
||||
void P_LineOpening (line_t *linedef)
|
||||
{
|
||||
sector_t *front, *back;
|
||||
|
||||
if (linedef->sidenum[1] == -1)
|
||||
{ // single sided line
|
||||
openrange = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
front = linedef->frontsector;
|
||||
back = linedef->backsector;
|
||||
|
||||
if (front->ceilingheight < back->ceilingheight)
|
||||
opentop = front->ceilingheight;
|
||||
else
|
||||
opentop = back->ceilingheight;
|
||||
if (front->floorheight > back->floorheight)
|
||||
{
|
||||
openbottom = front->floorheight;
|
||||
lowfloor = back->floorheight;
|
||||
}
|
||||
else
|
||||
{
|
||||
openbottom = back->floorheight;
|
||||
lowfloor = front->floorheight;
|
||||
}
|
||||
|
||||
openrange = opentop - openbottom;
|
||||
}
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
|
||||
THING POSITION SETTING
|
||||
|
||||
===============================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
===================
|
||||
=
|
||||
= P_UnsetThingPosition
|
||||
=
|
||||
= Unlinks a thing from block map and sectors
|
||||
=
|
||||
===================
|
||||
*/
|
||||
|
||||
void P_UnsetThingPosition (mobj_t *thing)
|
||||
{
|
||||
int blockx, blocky;
|
||||
|
||||
if ( ! (thing->flags & MF_NOSECTOR) )
|
||||
{ // inert things don't need to be in blockmap
|
||||
// unlink from subsector
|
||||
if (thing->snext)
|
||||
thing->snext->sprev = thing->sprev;
|
||||
if (thing->sprev)
|
||||
thing->sprev->snext = thing->snext;
|
||||
else
|
||||
thing->subsector->sector->thinglist = thing->snext;
|
||||
}
|
||||
|
||||
if ( ! (thing->flags & MF_NOBLOCKMAP) )
|
||||
{ // inert things don't need to be in blockmap
|
||||
// unlink from block map
|
||||
if (thing->bnext)
|
||||
thing->bnext->bprev = thing->bprev;
|
||||
if (thing->bprev)
|
||||
thing->bprev->bnext = thing->bnext;
|
||||
else
|
||||
{
|
||||
blockx = (thing->x - bmaporgx)>>MAPBLOCKSHIFT;
|
||||
blocky = (thing->y - bmaporgy)>>MAPBLOCKSHIFT;
|
||||
if (blockx>=0 && blockx < bmapwidth
|
||||
&& blocky>=0 && blocky <bmapheight)
|
||||
blocklinks[blocky*bmapwidth+blockx] = thing->bnext;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===================
|
||||
=
|
||||
= P_SetThingPosition
|
||||
=
|
||||
= Links a thing into both a block and a subsector based on it's x y
|
||||
= Sets thing->subsector properly
|
||||
=
|
||||
===================
|
||||
*/
|
||||
|
||||
void P_SetThingPosition (mobj_t *thing)
|
||||
{
|
||||
subsector_t *ss;
|
||||
sector_t *sec;
|
||||
int blockx, blocky;
|
||||
mobj_t **link;
|
||||
|
||||
//
|
||||
// link into subsector
|
||||
//
|
||||
ss = R_PointInSubsector (thing->x,thing->y);
|
||||
thing->subsector = ss;
|
||||
if ( ! (thing->flags & MF_NOSECTOR) )
|
||||
{ // invisible things don't go into the sector links
|
||||
sec = ss->sector;
|
||||
|
||||
thing->sprev = NULL;
|
||||
thing->snext = sec->thinglist;
|
||||
if (sec->thinglist)
|
||||
sec->thinglist->sprev = thing;
|
||||
sec->thinglist = thing;
|
||||
}
|
||||
|
||||
//
|
||||
// link into blockmap
|
||||
//
|
||||
if ( ! (thing->flags & MF_NOBLOCKMAP) )
|
||||
{ // inert things don't need to be in blockmap
|
||||
blockx = (thing->x - bmaporgx)>>MAPBLOCKSHIFT;
|
||||
blocky = (thing->y - bmaporgy)>>MAPBLOCKSHIFT;
|
||||
if (blockx>=0 && blockx < bmapwidth && blocky>=0 && blocky <bmapheight)
|
||||
{
|
||||
link = &blocklinks[blocky*bmapwidth+blockx];
|
||||
thing->bprev = NULL;
|
||||
thing->bnext = *link;
|
||||
if (*link)
|
||||
(*link)->bprev = thing;
|
||||
*link = thing;
|
||||
}
|
||||
else
|
||||
{ // thing is off the map
|
||||
thing->bnext = thing->bprev = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
|
||||
BLOCK MAP ITERATORS
|
||||
|
||||
For each line/thing in the given mapblock, call the passed function.
|
||||
If the function returns false, exit with false without checking anything else.
|
||||
|
||||
===============================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
==================
|
||||
=
|
||||
= P_BlockLinesIterator
|
||||
=
|
||||
= The validcount flags are used to avoid checking lines
|
||||
= that are marked in multiple mapblocks, so increment validcount before
|
||||
= the first call to P_BlockLinesIterator, then make one or more calls to it
|
||||
===================
|
||||
*/
|
||||
|
||||
boolean P_BlockLinesIterator (int x, int y, boolean(*func)(line_t*) )
|
||||
{
|
||||
int offset;
|
||||
short *list;
|
||||
line_t *ld;
|
||||
|
||||
if (x<0 || y<0 || x>=bmapwidth || y>=bmapheight)
|
||||
return true;
|
||||
offset = y*bmapwidth+x;
|
||||
|
||||
offset = *(blockmap+offset);
|
||||
|
||||
for ( list = blockmaplump+offset ; *list != -1 ; list++)
|
||||
{
|
||||
ld = &lines[*list];
|
||||
if (ld->validcount == validcount)
|
||||
continue; // line has already been checked
|
||||
ld->validcount = validcount;
|
||||
|
||||
if ( !func(ld) )
|
||||
return false;
|
||||
}
|
||||
|
||||
return true; // everything was checked
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
==================
|
||||
=
|
||||
= P_BlockThingsIterator
|
||||
=
|
||||
==================
|
||||
*/
|
||||
|
||||
boolean P_BlockThingsIterator (int x, int y, boolean(*func)(mobj_t*) )
|
||||
{
|
||||
mobj_t *mobj;
|
||||
|
||||
if (x<0 || y<0 || x>=bmapwidth || y>=bmapheight)
|
||||
return true;
|
||||
|
||||
for (mobj = blocklinks[y*bmapwidth+x] ; mobj ; mobj = mobj->bnext)
|
||||
if (!func( mobj ) )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
|
||||
INTERCEPT ROUTINES
|
||||
|
||||
===============================================================================
|
||||
*/
|
||||
|
||||
intercept_t intercepts[MAXINTERCEPTS], *intercept_p;
|
||||
|
||||
divline_t trace;
|
||||
boolean earlyout;
|
||||
int ptflags;
|
||||
|
||||
/*
|
||||
==================
|
||||
=
|
||||
= PIT_AddLineIntercepts
|
||||
=
|
||||
= Looks for lines in the given block that intercept the given trace
|
||||
= to add to the intercepts list
|
||||
= A line is crossed if its endpoints are on opposite sides of the trace
|
||||
= Returns true if earlyout and a solid line hit
|
||||
==================
|
||||
*/
|
||||
|
||||
boolean PIT_AddLineIntercepts (line_t *ld)
|
||||
{
|
||||
int s1, s2;
|
||||
fixed_t frac;
|
||||
divline_t dl;
|
||||
|
||||
// avoid precision problems with two routines
|
||||
if ( trace.dx > FRACUNIT*16 || trace.dy > FRACUNIT*16
|
||||
|| trace.dx < -FRACUNIT*16 || trace.dy < -FRACUNIT*16)
|
||||
{
|
||||
s1 = P_PointOnDivlineSide (ld->v1->x, ld->v1->y, &trace);
|
||||
s2 = P_PointOnDivlineSide (ld->v2->x, ld->v2->y, &trace);
|
||||
}
|
||||
else
|
||||
{
|
||||
s1 = P_PointOnLineSide (trace.x, trace.y, ld);
|
||||
s2 = P_PointOnLineSide (trace.x+trace.dx, trace.y+trace.dy, ld);
|
||||
}
|
||||
if (s1 == s2)
|
||||
return true; // line isn't crossed
|
||||
|
||||
//
|
||||
// hit the line
|
||||
//
|
||||
P_MakeDivline (ld, &dl);
|
||||
frac = P_InterceptVector (&trace, &dl);
|
||||
if (frac < 0)
|
||||
return true; // behind source
|
||||
|
||||
// try to early out the check
|
||||
if (earlyout && frac < FRACUNIT && !ld->backsector)
|
||||
return false; // stop checking
|
||||
|
||||
intercept_p->frac = frac;
|
||||
intercept_p->isaline = true;
|
||||
intercept_p->d.line = ld;
|
||||
intercept_p++;
|
||||
|
||||
return true; // continue
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
==================
|
||||
=
|
||||
= PIT_AddThingIntercepts
|
||||
=
|
||||
==================
|
||||
*/
|
||||
|
||||
boolean PIT_AddThingIntercepts (mobj_t *thing)
|
||||
{
|
||||
fixed_t x1,y1, x2,y2;
|
||||
int s1, s2;
|
||||
boolean tracepositive;
|
||||
divline_t dl;
|
||||
fixed_t frac;
|
||||
|
||||
tracepositive = (trace.dx ^ trace.dy)>0;
|
||||
|
||||
// check a corner to corner crossection for hit
|
||||
|
||||
if (tracepositive)
|
||||
{
|
||||
x1 = thing->x - thing->radius;
|
||||
y1 = thing->y + thing->radius;
|
||||
|
||||
x2 = thing->x + thing->radius;
|
||||
y2 = thing->y - thing->radius;
|
||||
}
|
||||
else
|
||||
{
|
||||
x1 = thing->x - thing->radius;
|
||||
y1 = thing->y - thing->radius;
|
||||
|
||||
x2 = thing->x + thing->radius;
|
||||
y2 = thing->y + thing->radius;
|
||||
}
|
||||
s1 = P_PointOnDivlineSide (x1, y1, &trace);
|
||||
s2 = P_PointOnDivlineSide (x2, y2, &trace);
|
||||
if (s1 == s2)
|
||||
return true; // line isn't crossed
|
||||
|
||||
dl.x = x1;
|
||||
dl.y = y1;
|
||||
dl.dx = x2-x1;
|
||||
dl.dy = y2-y1;
|
||||
frac = P_InterceptVector (&trace, &dl);
|
||||
if (frac < 0)
|
||||
return true; // behind source
|
||||
intercept_p->frac = frac;
|
||||
intercept_p->isaline = false;
|
||||
intercept_p->d.thing = thing;
|
||||
intercept_p++;
|
||||
|
||||
return true; // keep going
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
====================
|
||||
=
|
||||
= P_TraverseIntercepts
|
||||
=
|
||||
= Returns true if the traverser function returns true for all lines
|
||||
====================
|
||||
*/
|
||||
|
||||
boolean P_TraverseIntercepts ( traverser_t func, fixed_t maxfrac )
|
||||
{
|
||||
int count;
|
||||
fixed_t dist;
|
||||
intercept_t *scan, *in;
|
||||
|
||||
count = intercept_p - intercepts;
|
||||
in = 0; // shut up compiler warning
|
||||
|
||||
while (count--)
|
||||
{
|
||||
dist = MAXINT;
|
||||
for (scan = intercepts ; scan<intercept_p ; scan++)
|
||||
if (scan->frac < dist)
|
||||
{
|
||||
dist = scan->frac;
|
||||
in = scan;
|
||||
}
|
||||
|
||||
if (dist > maxfrac)
|
||||
return true; // checked everything in range
|
||||
#if 0
|
||||
{ // don't check these yet, ther may be others inserted
|
||||
in = scan = intercepts;
|
||||
for ( scan = intercepts ; scan<intercept_p ; scan++)
|
||||
if (scan->frac > maxfrac)
|
||||
*in++ = *scan;
|
||||
intercept_p = in;
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
if ( !func (in) )
|
||||
return false; // don't bother going farther
|
||||
in->frac = MAXINT;
|
||||
}
|
||||
|
||||
return true; // everything was traversed
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
==================
|
||||
=
|
||||
= P_PathTraverse
|
||||
=
|
||||
= Traces a line from x1,y1 to x2,y2, calling the traverser function for each
|
||||
= Returns true if the traverser function returns true for all lines
|
||||
==================
|
||||
*/
|
||||
|
||||
boolean P_PathTraverse (fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2,
|
||||
int flags, boolean (*trav) (intercept_t *))
|
||||
{
|
||||
fixed_t xt1,yt1,xt2,yt2;
|
||||
fixed_t xstep,ystep;
|
||||
fixed_t partial;
|
||||
fixed_t xintercept, yintercept;
|
||||
int mapx, mapy, mapxstep, mapystep;
|
||||
int count;
|
||||
|
||||
earlyout = flags & PT_EARLYOUT;
|
||||
|
||||
validcount++;
|
||||
intercept_p = intercepts;
|
||||
|
||||
if ( ((x1-bmaporgx)&(MAPBLOCKSIZE-1)) == 0)
|
||||
x1 += FRACUNIT; // don't side exactly on a line
|
||||
if ( ((y1-bmaporgy)&(MAPBLOCKSIZE-1)) == 0)
|
||||
y1 += FRACUNIT; // don't side exactly on a line
|
||||
trace.x = x1;
|
||||
trace.y = y1;
|
||||
trace.dx = x2 - x1;
|
||||
trace.dy = y2 - y1;
|
||||
|
||||
x1 -= bmaporgx;
|
||||
y1 -= bmaporgy;
|
||||
xt1 = x1>>MAPBLOCKSHIFT;
|
||||
yt1 = y1>>MAPBLOCKSHIFT;
|
||||
|
||||
x2 -= bmaporgx;
|
||||
y2 -= bmaporgy;
|
||||
xt2 = x2>>MAPBLOCKSHIFT;
|
||||
yt2 = y2>>MAPBLOCKSHIFT;
|
||||
|
||||
if (xt2 > xt1)
|
||||
{
|
||||
mapxstep = 1;
|
||||
partial = FRACUNIT - ((x1>>MAPBTOFRAC)&(FRACUNIT-1));
|
||||
ystep = FixedDiv (y2-y1,abs(x2-x1));
|
||||
}
|
||||
else if (xt2 < xt1)
|
||||
{
|
||||
mapxstep = -1;
|
||||
partial = (x1>>MAPBTOFRAC)&(FRACUNIT-1);
|
||||
ystep = FixedDiv (y2-y1,abs(x2-x1));
|
||||
}
|
||||
else
|
||||
{
|
||||
mapxstep = 0;
|
||||
partial = FRACUNIT;
|
||||
ystep = 256*FRACUNIT;
|
||||
}
|
||||
yintercept = (y1>>MAPBTOFRAC) + FixedMul (partial, ystep);
|
||||
|
||||
|
||||
if (yt2 > yt1)
|
||||
{
|
||||
mapystep = 1;
|
||||
partial = FRACUNIT - ((y1>>MAPBTOFRAC)&(FRACUNIT-1));
|
||||
xstep = FixedDiv (x2-x1,abs(y2-y1));
|
||||
}
|
||||
else if (yt2 < yt1)
|
||||
{
|
||||
mapystep = -1;
|
||||
partial = (y1>>MAPBTOFRAC)&(FRACUNIT-1);
|
||||
xstep = FixedDiv (x2-x1,abs(y2-y1));
|
||||
}
|
||||
else
|
||||
{
|
||||
mapystep = 0;
|
||||
partial = FRACUNIT;
|
||||
xstep = 256*FRACUNIT;
|
||||
}
|
||||
xintercept = (x1>>MAPBTOFRAC) + FixedMul (partial, xstep);
|
||||
|
||||
|
||||
//
|
||||
// step through map blocks
|
||||
// Count is present to prevent a round off error from skipping the break
|
||||
mapx = xt1;
|
||||
mapy = yt1;
|
||||
|
||||
for (count = 0 ; count < 64 ; count++)
|
||||
{
|
||||
if (flags & PT_ADDLINES)
|
||||
{
|
||||
if (!P_BlockLinesIterator (mapx, mapy,PIT_AddLineIntercepts))
|
||||
return false; // early out
|
||||
}
|
||||
if (flags & PT_ADDTHINGS)
|
||||
{
|
||||
if (!P_BlockThingsIterator (mapx, mapy,PIT_AddThingIntercepts))
|
||||
return false; // early out
|
||||
}
|
||||
|
||||
if (mapx == xt2 && mapy == yt2)
|
||||
break;
|
||||
|
||||
if ( (yintercept >> FRACBITS) == mapy)
|
||||
{
|
||||
yintercept += ystep;
|
||||
mapx += mapxstep;
|
||||
}
|
||||
else if ( (xintercept >> FRACBITS) == mapx)
|
||||
{
|
||||
xintercept += xstep;
|
||||
mapy += mapystep;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// go through the sorted list
|
||||
//
|
||||
return P_TraverseIntercepts ( trav, FRACUNIT );
|
||||
}
|
||||
|
||||
|
||||
|
1599
Heretic Source/P_MOBJ.C
Normal file
1599
Heretic Source/P_MOBJ.C
Normal file
File diff suppressed because it is too large
Load diff
240
Heretic Source/P_PLATS.C
Normal file
240
Heretic Source/P_PLATS.C
Normal file
|
@ -0,0 +1,240 @@
|
|||
|
||||
// P_plats.c
|
||||
|
||||
#include "DoomDef.h"
|
||||
#include "P_local.h"
|
||||
#include "soundst.h"
|
||||
|
||||
plat_t *activeplats[MAXPLATS];
|
||||
|
||||
//==================================================================
|
||||
//
|
||||
// Move a plat up and down
|
||||
//
|
||||
//==================================================================
|
||||
void T_PlatRaise(plat_t *plat)
|
||||
{
|
||||
result_e res;
|
||||
|
||||
switch(plat->status)
|
||||
{
|
||||
case up:
|
||||
res = T_MovePlane(plat->sector,plat->speed,
|
||||
plat->high,plat->crush,0,1);
|
||||
if(!(leveltime&31))
|
||||
{
|
||||
S_StartSound((mobj_t *)&plat->sector->soundorg,
|
||||
sfx_stnmov);
|
||||
}
|
||||
if(plat->type == raiseAndChange
|
||||
|| plat->type == raiseToNearestAndChange)
|
||||
{
|
||||
if(!(leveltime&7))
|
||||
{
|
||||
S_StartSound((mobj_t *)&plat->sector->soundorg,
|
||||
sfx_stnmov);
|
||||
}
|
||||
}
|
||||
if (res == crushed && (!plat->crush))
|
||||
{
|
||||
plat->count = plat->wait;
|
||||
plat->status = down;
|
||||
S_StartSound((mobj_t *)&plat->sector->soundorg, sfx_pstart);
|
||||
}
|
||||
else
|
||||
if (res == pastdest)
|
||||
{
|
||||
plat->count = plat->wait;
|
||||
plat->status = waiting;
|
||||
S_StartSound((mobj_t *)&plat->sector->soundorg, sfx_pstop);
|
||||
switch(plat->type)
|
||||
{
|
||||
case downWaitUpStay:
|
||||
P_RemoveActivePlat(plat);
|
||||
break;
|
||||
case raiseAndChange:
|
||||
P_RemoveActivePlat(plat);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case down:
|
||||
res = T_MovePlane(plat->sector,plat->speed,plat->low,false,0,-1);
|
||||
if (res == pastdest)
|
||||
{
|
||||
plat->count = plat->wait;
|
||||
plat->status = waiting;
|
||||
S_StartSound((mobj_t *)&plat->sector->soundorg, sfx_pstop);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!(leveltime&31))
|
||||
{
|
||||
S_StartSound((mobj_t *)&plat->sector->soundorg,
|
||||
sfx_stnmov);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case waiting:
|
||||
if (!--plat->count)
|
||||
{
|
||||
if (plat->sector->floorheight == plat->low)
|
||||
plat->status = up;
|
||||
else
|
||||
plat->status = down;
|
||||
S_StartSound((mobj_t *)&plat->sector->soundorg, sfx_pstart);
|
||||
}
|
||||
case in_stasis:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//==================================================================
|
||||
//
|
||||
// Do Platforms
|
||||
// "amount" is only used for SOME platforms.
|
||||
//
|
||||
//==================================================================
|
||||
int EV_DoPlat(line_t *line,plattype_e type,int amount)
|
||||
{
|
||||
plat_t *plat;
|
||||
int secnum;
|
||||
int rtn;
|
||||
sector_t *sec;
|
||||
|
||||
secnum = -1;
|
||||
rtn = 0;
|
||||
|
||||
//
|
||||
// Activate all <type> plats that are in_stasis
|
||||
//
|
||||
switch(type)
|
||||
{
|
||||
case perpetualRaise:
|
||||
P_ActivateInStasis(line->tag);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0)
|
||||
{
|
||||
sec = §ors[secnum];
|
||||
if (sec->specialdata)
|
||||
continue;
|
||||
|
||||
//
|
||||
// Find lowest & highest floors around sector
|
||||
//
|
||||
rtn = 1;
|
||||
plat = Z_Malloc( sizeof(*plat), PU_LEVSPEC, 0);
|
||||
P_AddThinker(&plat->thinker);
|
||||
|
||||
plat->type = type;
|
||||
plat->sector = sec;
|
||||
plat->sector->specialdata = plat;
|
||||
plat->thinker.function = T_PlatRaise;
|
||||
plat->crush = false;
|
||||
plat->tag = line->tag;
|
||||
switch(type)
|
||||
{
|
||||
case raiseToNearestAndChange:
|
||||
plat->speed = PLATSPEED/2;
|
||||
sec->floorpic = sides[line->sidenum[0]].sector->floorpic;
|
||||
plat->high = P_FindNextHighestFloor(sec,sec->floorheight);
|
||||
plat->wait = 0;
|
||||
plat->status = up;
|
||||
sec->special = 0; // NO MORE DAMAGE, IF APPLICABLE
|
||||
S_StartSound((mobj_t *)&sec->soundorg, sfx_stnmov);
|
||||
break;
|
||||
case raiseAndChange:
|
||||
plat->speed = PLATSPEED/2;
|
||||
sec->floorpic = sides[line->sidenum[0]].sector->floorpic;
|
||||
plat->high = sec->floorheight + amount*FRACUNIT;
|
||||
plat->wait = 0;
|
||||
plat->status = up;
|
||||
S_StartSound((mobj_t *)&sec->soundorg, sfx_stnmov);
|
||||
break;
|
||||
case downWaitUpStay:
|
||||
plat->speed = PLATSPEED * 4;
|
||||
plat->low = P_FindLowestFloorSurrounding(sec);
|
||||
if (plat->low > sec->floorheight)
|
||||
plat->low = sec->floorheight;
|
||||
plat->high = sec->floorheight;
|
||||
plat->wait = 35*PLATWAIT;
|
||||
plat->status = down;
|
||||
S_StartSound((mobj_t *)&sec->soundorg, sfx_pstart);
|
||||
break;
|
||||
case perpetualRaise:
|
||||
plat->speed = PLATSPEED;
|
||||
plat->low = P_FindLowestFloorSurrounding(sec);
|
||||
if (plat->low > sec->floorheight)
|
||||
plat->low = sec->floorheight;
|
||||
plat->high = P_FindHighestFloorSurrounding(sec);
|
||||
if (plat->high < sec->floorheight)
|
||||
plat->high = sec->floorheight;
|
||||
plat->wait = 35*PLATWAIT;
|
||||
plat->status = P_Random()&1;
|
||||
S_StartSound((mobj_t *)&sec->soundorg, sfx_pstart);
|
||||
break;
|
||||
}
|
||||
P_AddActivePlat(plat);
|
||||
}
|
||||
return rtn;
|
||||
}
|
||||
|
||||
void P_ActivateInStasis(int tag)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0;i < MAXPLATS;i++)
|
||||
if (activeplats[i] &&
|
||||
(activeplats[i])->tag == tag &&
|
||||
(activeplats[i])->status == in_stasis)
|
||||
{
|
||||
(activeplats[i])->status = (activeplats[i])->oldstatus;
|
||||
(activeplats[i])->thinker.function = T_PlatRaise;
|
||||
}
|
||||
}
|
||||
|
||||
void EV_StopPlat(line_t *line)
|
||||
{
|
||||
int j;
|
||||
|
||||
for (j = 0;j < MAXPLATS;j++)
|
||||
if (activeplats[j] && ((activeplats[j])->status != in_stasis) &&
|
||||
((activeplats[j])->tag == line->tag))
|
||||
{
|
||||
(activeplats[j])->oldstatus = (activeplats[j])->status;
|
||||
(activeplats[j])->status = in_stasis;
|
||||
(activeplats[j])->thinker.function = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void P_AddActivePlat(plat_t *plat)
|
||||
{
|
||||
int i;
|
||||
for (i = 0;i < MAXPLATS;i++)
|
||||
if (activeplats[i] == NULL)
|
||||
{
|
||||
activeplats[i] = plat;
|
||||
return;
|
||||
}
|
||||
I_Error ("P_AddActivePlat: no more plats!");
|
||||
}
|
||||
|
||||
void P_RemoveActivePlat(plat_t *plat)
|
||||
{
|
||||
int i;
|
||||
for (i = 0;i < MAXPLATS;i++)
|
||||
if (plat == activeplats[i])
|
||||
{
|
||||
(activeplats[i])->sector->specialdata = NULL;
|
||||
P_RemoveThinker(&(activeplats[i])->thinker);
|
||||
activeplats[i] = NULL;
|
||||
return;
|
||||
}
|
||||
I_Error ("P_RemoveActivePlat: can't find plat!");
|
||||
}
|
1869
Heretic Source/P_PSPR.C
Normal file
1869
Heretic Source/P_PSPR.C
Normal file
File diff suppressed because it is too large
Load diff
624
Heretic Source/P_SETUP.C
Normal file
624
Heretic Source/P_SETUP.C
Normal file
|
@ -0,0 +1,624 @@
|
|||
|
||||
// P_main.c
|
||||
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include "DoomDef.h"
|
||||
#include "P_local.h"
|
||||
#include "soundst.h"
|
||||
|
||||
void P_SpawnMapThing (mapthing_t *mthing);
|
||||
|
||||
int numvertexes;
|
||||
vertex_t *vertexes;
|
||||
|
||||
int numsegs;
|
||||
seg_t *segs;
|
||||
|
||||
int numsectors;
|
||||
sector_t *sectors;
|
||||
|
||||
int numsubsectors;
|
||||
subsector_t *subsectors;
|
||||
|
||||
int numnodes;
|
||||
node_t *nodes;
|
||||
|
||||
int numlines;
|
||||
line_t *lines;
|
||||
|
||||
int numsides;
|
||||
side_t *sides;
|
||||
|
||||
short *blockmaplump; // offsets in blockmap are from here
|
||||
short *blockmap;
|
||||
int bmapwidth, bmapheight; // in mapblocks
|
||||
fixed_t bmaporgx, bmaporgy; // origin of block map
|
||||
mobj_t **blocklinks; // for thing chains
|
||||
|
||||
byte *rejectmatrix; // for fast sight rejection
|
||||
|
||||
mapthing_t deathmatchstarts[10], *deathmatch_p;
|
||||
mapthing_t playerstarts[MAXPLAYERS];
|
||||
|
||||
/*
|
||||
=================
|
||||
=
|
||||
= P_LoadVertexes
|
||||
=
|
||||
=================
|
||||
*/
|
||||
|
||||
void P_LoadVertexes (int lump)
|
||||
{
|
||||
byte *data;
|
||||
int i;
|
||||
mapvertex_t *ml;
|
||||
vertex_t *li;
|
||||
|
||||
numvertexes = W_LumpLength (lump) / sizeof(mapvertex_t);
|
||||
vertexes = Z_Malloc (numvertexes*sizeof(vertex_t),PU_LEVEL,0);
|
||||
data = W_CacheLumpNum (lump,PU_STATIC);
|
||||
|
||||
ml = (mapvertex_t *)data;
|
||||
li = vertexes;
|
||||
for (i=0 ; i<numvertexes ; i++, li++, ml++)
|
||||
{
|
||||
li->x = SHORT(ml->x)<<FRACBITS;
|
||||
li->y = SHORT(ml->y)<<FRACBITS;
|
||||
}
|
||||
|
||||
Z_Free (data);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=================
|
||||
=
|
||||
= P_LoadSegs
|
||||
=
|
||||
=================
|
||||
*/
|
||||
|
||||
void P_LoadSegs (int lump)
|
||||
{
|
||||
byte *data;
|
||||
int i;
|
||||
mapseg_t *ml;
|
||||
seg_t *li;
|
||||
line_t *ldef;
|
||||
int linedef, side;
|
||||
|
||||
numsegs = W_LumpLength (lump) / sizeof(mapseg_t);
|
||||
segs = Z_Malloc (numsegs*sizeof(seg_t),PU_LEVEL,0);
|
||||
memset (segs, 0, numsegs*sizeof(seg_t));
|
||||
data = W_CacheLumpNum (lump,PU_STATIC);
|
||||
|
||||
ml = (mapseg_t *)data;
|
||||
li = segs;
|
||||
for (i=0 ; i<numsegs ; i++, li++, ml++)
|
||||
{
|
||||
li->v1 = &vertexes[SHORT(ml->v1)];
|
||||
li->v2 = &vertexes[SHORT(ml->v2)];
|
||||
|
||||
li->angle = (SHORT(ml->angle))<<16;
|
||||
li->offset = (SHORT(ml->offset))<<16;
|
||||
linedef = SHORT(ml->linedef);
|
||||
ldef = &lines[linedef];
|
||||
li->linedef = ldef;
|
||||
side = SHORT(ml->side);
|
||||
li->sidedef = &sides[ldef->sidenum[side]];
|
||||
li->frontsector = sides[ldef->sidenum[side]].sector;
|
||||
if (ldef-> flags & ML_TWOSIDED)
|
||||
li->backsector = sides[ldef->sidenum[side^1]].sector;
|
||||
else
|
||||
li->backsector = 0;
|
||||
}
|
||||
|
||||
Z_Free (data);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=================
|
||||
=
|
||||
= P_LoadSubsectors
|
||||
=
|
||||
=================
|
||||
*/
|
||||
|
||||
void P_LoadSubsectors (int lump)
|
||||
{
|
||||
byte *data;
|
||||
int i;
|
||||
mapsubsector_t *ms;
|
||||
subsector_t *ss;
|
||||
|
||||
numsubsectors = W_LumpLength (lump) / sizeof(mapsubsector_t);
|
||||
subsectors = Z_Malloc (numsubsectors*sizeof(subsector_t),PU_LEVEL,0);
|
||||
data = W_CacheLumpNum (lump,PU_STATIC);
|
||||
|
||||
ms = (mapsubsector_t *)data;
|
||||
memset (subsectors,0, numsubsectors*sizeof(subsector_t));
|
||||
ss = subsectors;
|
||||
for (i=0 ; i<numsubsectors ; i++, ss++, ms++)
|
||||
{
|
||||
ss->numlines = SHORT(ms->numsegs);
|
||||
ss->firstline = SHORT(ms->firstseg);
|
||||
}
|
||||
|
||||
Z_Free (data);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=================
|
||||
=
|
||||
= P_LoadSectors
|
||||
=
|
||||
=================
|
||||
*/
|
||||
|
||||
void P_LoadSectors (int lump)
|
||||
{
|
||||
byte *data;
|
||||
int i;
|
||||
mapsector_t *ms;
|
||||
sector_t *ss;
|
||||
|
||||
numsectors = W_LumpLength (lump) / sizeof(mapsector_t);
|
||||
sectors = Z_Malloc (numsectors*sizeof(sector_t),PU_LEVEL,0);
|
||||
memset (sectors, 0, numsectors*sizeof(sector_t));
|
||||
data = W_CacheLumpNum (lump,PU_STATIC);
|
||||
|
||||
ms = (mapsector_t *)data;
|
||||
ss = sectors;
|
||||
for (i=0 ; i<numsectors ; i++, ss++, ms++)
|
||||
{
|
||||
ss->floorheight = SHORT(ms->floorheight)<<FRACBITS;
|
||||
ss->ceilingheight = SHORT(ms->ceilingheight)<<FRACBITS;
|
||||
ss->floorpic = R_FlatNumForName(ms->floorpic);
|
||||
ss->ceilingpic = R_FlatNumForName(ms->ceilingpic);
|
||||
ss->lightlevel = SHORT(ms->lightlevel);
|
||||
ss->special = SHORT(ms->special);
|
||||
ss->tag = SHORT(ms->tag);
|
||||
ss->thinglist = NULL;
|
||||
}
|
||||
|
||||
Z_Free (data);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=================
|
||||
=
|
||||
= P_LoadNodes
|
||||
=
|
||||
=================
|
||||
*/
|
||||
|
||||
void P_LoadNodes (int lump)
|
||||
{
|
||||
byte *data;
|
||||
int i,j,k;
|
||||
mapnode_t *mn;
|
||||
node_t *no;
|
||||
|
||||
numnodes = W_LumpLength (lump) / sizeof(mapnode_t);
|
||||
nodes = Z_Malloc (numnodes*sizeof(node_t),PU_LEVEL,0);
|
||||
data = W_CacheLumpNum (lump,PU_STATIC);
|
||||
|
||||
mn = (mapnode_t *)data;
|
||||
no = nodes;
|
||||
for (i=0 ; i<numnodes ; i++, no++, mn++)
|
||||
{
|
||||
no->x = SHORT(mn->x)<<FRACBITS;
|
||||
no->y = SHORT(mn->y)<<FRACBITS;
|
||||
no->dx = SHORT(mn->dx)<<FRACBITS;
|
||||
no->dy = SHORT(mn->dy)<<FRACBITS;
|
||||
for (j=0 ; j<2 ; j++)
|
||||
{
|
||||
no->children[j] = SHORT(mn->children[j]);
|
||||
for (k=0 ; k<4 ; k++)
|
||||
no->bbox[j][k] = SHORT(mn->bbox[j][k])<<FRACBITS;
|
||||
}
|
||||
}
|
||||
|
||||
Z_Free (data);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
=================
|
||||
=
|
||||
= P_LoadThings
|
||||
=
|
||||
=================
|
||||
*/
|
||||
|
||||
void P_LoadThings (int lump)
|
||||
{
|
||||
byte *data;
|
||||
int i;
|
||||
mapthing_t *mt;
|
||||
int numthings;
|
||||
|
||||
data = W_CacheLumpNum (lump,PU_STATIC);
|
||||
numthings = W_LumpLength (lump) / sizeof(mapthing_t);
|
||||
|
||||
mt = (mapthing_t *)data;
|
||||
for (i=0 ; i<numthings ; i++, mt++)
|
||||
{
|
||||
mt->x = SHORT(mt->x);
|
||||
mt->y = SHORT(mt->y);
|
||||
mt->angle = SHORT(mt->angle);
|
||||
mt->type = SHORT(mt->type);
|
||||
mt->options = SHORT(mt->options);
|
||||
P_SpawnMapThing (mt);
|
||||
}
|
||||
|
||||
Z_Free (data);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
=================
|
||||
=
|
||||
= P_LoadLineDefs
|
||||
=
|
||||
= Also counts secret lines for intermissions
|
||||
=================
|
||||
*/
|
||||
|
||||
void P_LoadLineDefs (int lump)
|
||||
{
|
||||
byte *data;
|
||||
int i;
|
||||
maplinedef_t *mld;
|
||||
line_t *ld;
|
||||
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);
|
||||
|
||||
mld = (maplinedef_t *)data;
|
||||
ld = lines;
|
||||
for (i=0 ; i<numlines ; i++, mld++, ld++)
|
||||
{
|
||||
ld->flags = SHORT(mld->flags);
|
||||
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;
|
||||
if (!ld->dx)
|
||||
ld->slopetype = ST_VERTICAL;
|
||||
else if (!ld->dy)
|
||||
ld->slopetype = ST_HORIZONTAL;
|
||||
else
|
||||
{
|
||||
if (FixedDiv (ld->dy , ld->dx) > 0)
|
||||
ld->slopetype = ST_POSITIVE;
|
||||
else
|
||||
ld->slopetype = ST_NEGATIVE;
|
||||
}
|
||||
|
||||
if (v1->x < v2->x)
|
||||
{
|
||||
ld->bbox[BOXLEFT] = v1->x;
|
||||
ld->bbox[BOXRIGHT] = v2->x;
|
||||
}
|
||||
else
|
||||
{
|
||||
ld->bbox[BOXLEFT] = v2->x;
|
||||
ld->bbox[BOXRIGHT] = v1->x;
|
||||
}
|
||||
if (v1->y < v2->y)
|
||||
{
|
||||
ld->bbox[BOXBOTTOM] = v1->y;
|
||||
ld->bbox[BOXTOP] = v2->y;
|
||||
}
|
||||
else
|
||||
{
|
||||
ld->bbox[BOXBOTTOM] = v2->y;
|
||||
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
|
||||
ld->frontsector = 0;
|
||||
if (ld->sidenum[1] != -1)
|
||||
ld->backsector = sides[ld->sidenum[1]].sector;
|
||||
else
|
||||
ld->backsector = 0;
|
||||
}
|
||||
|
||||
Z_Free (data);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=================
|
||||
=
|
||||
= P_LoadSideDefs
|
||||
=
|
||||
=================
|
||||
*/
|
||||
|
||||
void P_LoadSideDefs (int lump)
|
||||
{
|
||||
byte *data;
|
||||
int i;
|
||||
mapsidedef_t *msd;
|
||||
side_t *sd;
|
||||
|
||||
numsides = W_LumpLength (lump) / sizeof(mapsidedef_t);
|
||||
sides = Z_Malloc (numsides*sizeof(side_t),PU_LEVEL,0);
|
||||
memset (sides, 0, numsides*sizeof(side_t));
|
||||
data = W_CacheLumpNum (lump,PU_STATIC);
|
||||
|
||||
msd = (mapsidedef_t *)data;
|
||||
sd = sides;
|
||||
for (i=0 ; i<numsides ; i++, msd++, sd++)
|
||||
{
|
||||
sd->textureoffset = SHORT(msd->textureoffset)<<FRACBITS;
|
||||
sd->rowoffset = SHORT(msd->rowoffset)<<FRACBITS;
|
||||
sd->toptexture = R_TextureNumForName(msd->toptexture);
|
||||
sd->bottomtexture = R_TextureNumForName(msd->bottomtexture);
|
||||
sd->midtexture = R_TextureNumForName(msd->midtexture);
|
||||
sd->sector = §ors[SHORT(msd->sector)];
|
||||
}
|
||||
|
||||
Z_Free (data);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
=================
|
||||
=
|
||||
= P_LoadBlockMap
|
||||
=
|
||||
=================
|
||||
*/
|
||||
|
||||
void P_LoadBlockMap (int lump)
|
||||
{
|
||||
int i, count;
|
||||
|
||||
blockmaplump = W_CacheLumpNum (lump,PU_LEVEL);
|
||||
blockmap = blockmaplump+4;
|
||||
count = W_LumpLength (lump)/2;
|
||||
for (i=0 ; i<count ; i++)
|
||||
blockmaplump[i] = SHORT(blockmaplump[i]);
|
||||
|
||||
bmaporgx = blockmaplump[0]<<FRACBITS;
|
||||
bmaporgy = blockmaplump[1]<<FRACBITS;
|
||||
bmapwidth = blockmaplump[2];
|
||||
bmapheight = blockmaplump[3];
|
||||
|
||||
// clear out mobj chains
|
||||
count = sizeof(*blocklinks)* bmapwidth*bmapheight;
|
||||
blocklinks = Z_Malloc (count,PU_LEVEL, 0);
|
||||
memset (blocklinks, 0, count);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
=================
|
||||
=
|
||||
= P_GroupLines
|
||||
=
|
||||
= Builds sector line lists and subsector sector numbers
|
||||
= Finds block bounding boxes for sectors
|
||||
=================
|
||||
*/
|
||||
|
||||
void P_GroupLines (void)
|
||||
{
|
||||
line_t **linebuffer;
|
||||
int i, j, total;
|
||||
line_t *li;
|
||||
sector_t *sector;
|
||||
subsector_t *ss;
|
||||
seg_t *seg;
|
||||
fixed_t bbox[4];
|
||||
int block;
|
||||
|
||||
// look up sector number for each subsector
|
||||
ss = subsectors;
|
||||
for (i=0 ; i<numsubsectors ; i++, ss++)
|
||||
{
|
||||
seg = &segs[ss->firstline];
|
||||
ss->sector = seg->sidedef->sector;
|
||||
}
|
||||
|
||||
// count number of lines in each sector
|
||||
li = lines;
|
||||
total = 0;
|
||||
for (i=0 ; i<numlines ; i++, li++)
|
||||
{
|
||||
total++;
|
||||
li->frontsector->linecount++;
|
||||
if (li->backsector && li->backsector != li->frontsector)
|
||||
{
|
||||
li->backsector->linecount++;
|
||||
total++;
|
||||
}
|
||||
}
|
||||
|
||||
// build line tables for each sector
|
||||
linebuffer = Z_Malloc (total*4, PU_LEVEL, 0);
|
||||
sector = sectors;
|
||||
for (i=0 ; i<numsectors ; i++, sector++)
|
||||
{
|
||||
M_ClearBox (bbox);
|
||||
sector->lines = linebuffer;
|
||||
li = lines;
|
||||
for (j=0 ; j<numlines ; j++, li++)
|
||||
{
|
||||
if (li->frontsector == sector || li->backsector == sector)
|
||||
{
|
||||
*linebuffer++ = li;
|
||||
M_AddToBox (bbox, li->v1->x, li->v1->y);
|
||||
M_AddToBox (bbox, li->v2->x, li->v2->y);
|
||||
}
|
||||
}
|
||||
if (linebuffer - sector->lines != sector->linecount)
|
||||
I_Error ("P_GroupLines: miscounted");
|
||||
|
||||
// set the degenmobj_t to the middle of the bounding box
|
||||
sector->soundorg.x = (bbox[BOXRIGHT]+bbox[BOXLEFT])/2;
|
||||
sector->soundorg.y = (bbox[BOXTOP]+bbox[BOXBOTTOM])/2;
|
||||
|
||||
// adjust bounding box to map blocks
|
||||
block = (bbox[BOXTOP]-bmaporgy+MAXRADIUS)>>MAPBLOCKSHIFT;
|
||||
block = block >= bmapheight ? bmapheight-1 : block;
|
||||
sector->blockbox[BOXTOP]=block;
|
||||
|
||||
block = (bbox[BOXBOTTOM]-bmaporgy-MAXRADIUS)>>MAPBLOCKSHIFT;
|
||||
block = block < 0 ? 0 : block;
|
||||
sector->blockbox[BOXBOTTOM]=block;
|
||||
|
||||
block = (bbox[BOXRIGHT]-bmaporgx+MAXRADIUS)>>MAPBLOCKSHIFT;
|
||||
block = block >= bmapwidth ? bmapwidth-1 : block;
|
||||
sector->blockbox[BOXRIGHT]=block;
|
||||
|
||||
block = (bbox[BOXLEFT]-bmaporgx-MAXRADIUS)>>MAPBLOCKSHIFT;
|
||||
block = block < 0 ? 0 : block;
|
||||
sector->blockbox[BOXLEFT]=block;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
||||
|
||||
/*
|
||||
=================
|
||||
=
|
||||
= P_SetupLevel
|
||||
=
|
||||
=================
|
||||
*/
|
||||
|
||||
void P_SetupLevel (int episode, int map, int playermask, skill_t skill)
|
||||
{
|
||||
int i;
|
||||
int parm;
|
||||
char lumpname[9];
|
||||
int lumpnum;
|
||||
mobj_t *mobj;
|
||||
|
||||
totalkills = totalitems = totalsecret = 0;
|
||||
for (i=0 ; i<MAXPLAYERS ; i++)
|
||||
{
|
||||
players[i].killcount = players[i].secretcount
|
||||
= players[i].itemcount = 0;
|
||||
}
|
||||
players[consoleplayer].viewz = 1; // will be set by player think
|
||||
|
||||
S_Start (); // make sure all sounds are stopped before Z_FreeTags
|
||||
|
||||
Z_FreeTags (PU_LEVEL, PU_PURGELEVEL-1);
|
||||
|
||||
P_InitThinkers ();
|
||||
|
||||
//
|
||||
// look for a regular (development) map first
|
||||
//
|
||||
lumpname[0] = 'E';
|
||||
lumpname[1] = '0' + episode;
|
||||
lumpname[2] = 'M';
|
||||
lumpname[3] = '0' + map;
|
||||
lumpname[4] = 0;
|
||||
leveltime = 0;
|
||||
|
||||
lumpnum = W_GetNumForName (lumpname);
|
||||
|
||||
// note: most of this ordering is important
|
||||
P_LoadBlockMap (lumpnum+ML_BLOCKMAP);
|
||||
P_LoadVertexes (lumpnum+ML_VERTEXES);
|
||||
P_LoadSectors (lumpnum+ML_SECTORS);
|
||||
P_LoadSideDefs (lumpnum+ML_SIDEDEFS);
|
||||
|
||||
P_LoadLineDefs (lumpnum+ML_LINEDEFS);
|
||||
P_LoadSubsectors (lumpnum+ML_SSECTORS);
|
||||
P_LoadNodes (lumpnum+ML_NODES);
|
||||
P_LoadSegs (lumpnum+ML_SEGS);
|
||||
|
||||
rejectmatrix = W_CacheLumpNum (lumpnum+ML_REJECT,PU_LEVEL);
|
||||
P_GroupLines ();
|
||||
|
||||
bodyqueslot = 0;
|
||||
deathmatch_p = deathmatchstarts;
|
||||
P_InitAmbientSound();
|
||||
P_InitMonsters();
|
||||
P_OpenWeapons();
|
||||
P_LoadThings(lumpnum+ML_THINGS);
|
||||
P_CloseWeapons();
|
||||
|
||||
//
|
||||
// if deathmatch, randomly spawn the active players
|
||||
//
|
||||
TimerGame = 0;
|
||||
if(deathmatch)
|
||||
{
|
||||
for (i=0 ; i<MAXPLAYERS ; i++)
|
||||
{
|
||||
if (playeringame[i])
|
||||
{ // must give a player spot before deathmatchspawn
|
||||
mobj = P_SpawnMobj (playerstarts[i].x<<16,
|
||||
playerstarts[i].y<<16,0, MT_PLAYER);
|
||||
players[i].mo = mobj;
|
||||
G_DeathMatchSpawnPlayer (i);
|
||||
P_RemoveMobj (mobj);
|
||||
}
|
||||
}
|
||||
parm = M_CheckParm("-timer");
|
||||
if(parm && parm < myargc-1)
|
||||
{
|
||||
TimerGame = atoi(myargv[parm+1])*35*60;
|
||||
}
|
||||
}
|
||||
|
||||
// set up world state
|
||||
P_SpawnSpecials ();
|
||||
|
||||
// build subsector connect matrix
|
||||
// P_ConnectSubsectors ();
|
||||
|
||||
// preload graphics
|
||||
if (precache)
|
||||
R_PrecacheLevel ();
|
||||
|
||||
//printf ("free memory: 0x%x\n", Z_FreeMemory());
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=================
|
||||
=
|
||||
= P_Init
|
||||
=
|
||||
=================
|
||||
*/
|
||||
|
||||
void P_Init (void)
|
||||
{
|
||||
P_InitSwitchList();
|
||||
P_InitPicAnims();
|
||||
P_InitTerrainTypes();
|
||||
P_InitLava();
|
||||
R_InitSprites(sprnames);
|
||||
}
|
340
Heretic Source/P_SIGHT.C
Normal file
340
Heretic Source/P_SIGHT.C
Normal file
|
@ -0,0 +1,340 @@
|
|||
// P_sight.c
|
||||
|
||||
#include "DoomDef.h"
|
||||
#include "P_local.h"
|
||||
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
P_CheckSight
|
||||
|
||||
This uses specialized forms of the maputils routines for optimized performance
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
fixed_t sightzstart; // eye z of looker
|
||||
fixed_t topslope, bottomslope; // slopes to top and bottom of target
|
||||
|
||||
int sightcounts[3];
|
||||
|
||||
/*
|
||||
==============
|
||||
=
|
||||
= PTR_SightTraverse
|
||||
=
|
||||
==============
|
||||
*/
|
||||
|
||||
boolean PTR_SightTraverse (intercept_t *in)
|
||||
{
|
||||
line_t *li;
|
||||
fixed_t slope;
|
||||
|
||||
li = in->d.line;
|
||||
|
||||
//
|
||||
// crosses a two sided line
|
||||
//
|
||||
P_LineOpening (li);
|
||||
|
||||
if (openbottom >= opentop) // quick test for totally closed doors
|
||||
return false; // stop
|
||||
|
||||
if (li->frontsector->floorheight != li->backsector->floorheight)
|
||||
{
|
||||
slope = FixedDiv (openbottom - sightzstart , in->frac);
|
||||
if (slope > bottomslope)
|
||||
bottomslope = slope;
|
||||
}
|
||||
|
||||
if (li->frontsector->ceilingheight != li->backsector->ceilingheight)
|
||||
{
|
||||
slope = FixedDiv (opentop - sightzstart , in->frac);
|
||||
if (slope < topslope)
|
||||
topslope = slope;
|
||||
}
|
||||
|
||||
if (topslope <= bottomslope)
|
||||
return false; // stop
|
||||
|
||||
return true; // keep going
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
==================
|
||||
=
|
||||
= P_SightBlockLinesIterator
|
||||
=
|
||||
===================
|
||||
*/
|
||||
|
||||
boolean P_SightBlockLinesIterator (int x, int y )
|
||||
{
|
||||
int offset;
|
||||
short *list;
|
||||
line_t *ld;
|
||||
int s1, s2;
|
||||
divline_t dl;
|
||||
|
||||
offset = y*bmapwidth+x;
|
||||
|
||||
offset = *(blockmap+offset);
|
||||
|
||||
for ( list = blockmaplump+offset ; *list != -1 ; list++)
|
||||
{
|
||||
ld = &lines[*list];
|
||||
if (ld->validcount == validcount)
|
||||
continue; // line has already been checked
|
||||
ld->validcount = validcount;
|
||||
|
||||
s1 = P_PointOnDivlineSide (ld->v1->x, ld->v1->y, &trace);
|
||||
s2 = P_PointOnDivlineSide (ld->v2->x, ld->v2->y, &trace);
|
||||
if (s1 == s2)
|
||||
continue; // line isn't crossed
|
||||
P_MakeDivline (ld, &dl);
|
||||
s1 = P_PointOnDivlineSide (trace.x, trace.y, &dl);
|
||||
s2 = P_PointOnDivlineSide (trace.x+trace.dx, trace.y+trace.dy, &dl);
|
||||
if (s1 == s2)
|
||||
continue; // line isn't crossed
|
||||
|
||||
// try to early out the check
|
||||
if (!ld->backsector)
|
||||
return false; // stop checking
|
||||
|
||||
// store the line for later intersection testing
|
||||
intercept_p->d.line = ld;
|
||||
intercept_p++;
|
||||
|
||||
}
|
||||
|
||||
return true; // everything was checked
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
=
|
||||
= P_SightTraverseIntercepts
|
||||
=
|
||||
= Returns true if the traverser function returns true for all lines
|
||||
====================
|
||||
*/
|
||||
|
||||
boolean P_SightTraverseIntercepts ( void )
|
||||
{
|
||||
int count;
|
||||
fixed_t dist;
|
||||
intercept_t *scan, *in;
|
||||
divline_t dl;
|
||||
|
||||
count = intercept_p - intercepts;
|
||||
//
|
||||
// calculate intercept distance
|
||||
//
|
||||
for (scan = intercepts ; scan<intercept_p ; scan++)
|
||||
{
|
||||
P_MakeDivline (scan->d.line, &dl);
|
||||
scan->frac = P_InterceptVector (&trace, &dl);
|
||||
}
|
||||
|
||||
//
|
||||
// go through in order
|
||||
//
|
||||
in = 0; // shut up compiler warning
|
||||
|
||||
while (count--)
|
||||
{
|
||||
dist = MAXINT;
|
||||
for (scan = intercepts ; scan<intercept_p ; scan++)
|
||||
if (scan->frac < dist)
|
||||
{
|
||||
dist = scan->frac;
|
||||
in = scan;
|
||||
}
|
||||
|
||||
if ( !PTR_SightTraverse (in) )
|
||||
return false; // don't bother going farther
|
||||
in->frac = MAXINT;
|
||||
}
|
||||
|
||||
return true; // everything was traversed
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
==================
|
||||
=
|
||||
= P_SightPathTraverse
|
||||
=
|
||||
= Traces a line from x1,y1 to x2,y2, calling the traverser function for each
|
||||
= Returns true if the traverser function returns true for all lines
|
||||
==================
|
||||
*/
|
||||
|
||||
boolean P_SightPathTraverse (fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2)
|
||||
{
|
||||
fixed_t xt1,yt1,xt2,yt2;
|
||||
fixed_t xstep,ystep;
|
||||
fixed_t partial;
|
||||
fixed_t xintercept, yintercept;
|
||||
int mapx, mapy, mapxstep, mapystep;
|
||||
int count;
|
||||
|
||||
validcount++;
|
||||
intercept_p = intercepts;
|
||||
|
||||
if ( ((x1-bmaporgx)&(MAPBLOCKSIZE-1)) == 0)
|
||||
x1 += FRACUNIT; // don't side exactly on a line
|
||||
if ( ((y1-bmaporgy)&(MAPBLOCKSIZE-1)) == 0)
|
||||
y1 += FRACUNIT; // don't side exactly on a line
|
||||
trace.x = x1;
|
||||
trace.y = y1;
|
||||
trace.dx = x2 - x1;
|
||||
trace.dy = y2 - y1;
|
||||
|
||||
x1 -= bmaporgx;
|
||||
y1 -= bmaporgy;
|
||||
xt1 = x1>>MAPBLOCKSHIFT;
|
||||
yt1 = y1>>MAPBLOCKSHIFT;
|
||||
|
||||
x2 -= bmaporgx;
|
||||
y2 -= bmaporgy;
|
||||
xt2 = x2>>MAPBLOCKSHIFT;
|
||||
yt2 = y2>>MAPBLOCKSHIFT;
|
||||
|
||||
// points should never be out of bounds, but check once instead of
|
||||
// each block
|
||||
if (xt1<0 || yt1<0 || xt1>=bmapwidth || yt1>=bmapheight
|
||||
|| xt2<0 || yt2<0 || xt2>=bmapwidth || yt2>=bmapheight)
|
||||
return false;
|
||||
|
||||
if (xt2 > xt1)
|
||||
{
|
||||
mapxstep = 1;
|
||||
partial = FRACUNIT - ((x1>>MAPBTOFRAC)&(FRACUNIT-1));
|
||||
ystep = FixedDiv (y2-y1,abs(x2-x1));
|
||||
}
|
||||
else if (xt2 < xt1)
|
||||
{
|
||||
mapxstep = -1;
|
||||
partial = (x1>>MAPBTOFRAC)&(FRACUNIT-1);
|
||||
ystep = FixedDiv (y2-y1,abs(x2-x1));
|
||||
}
|
||||
else
|
||||
{
|
||||
mapxstep = 0;
|
||||
partial = FRACUNIT;
|
||||
ystep = 256*FRACUNIT;
|
||||
}
|
||||
yintercept = (y1>>MAPBTOFRAC) + FixedMul (partial, ystep);
|
||||
|
||||
|
||||
if (yt2 > yt1)
|
||||
{
|
||||
mapystep = 1;
|
||||
partial = FRACUNIT - ((y1>>MAPBTOFRAC)&(FRACUNIT-1));
|
||||
xstep = FixedDiv (x2-x1,abs(y2-y1));
|
||||
}
|
||||
else if (yt2 < yt1)
|
||||
{
|
||||
mapystep = -1;
|
||||
partial = (y1>>MAPBTOFRAC)&(FRACUNIT-1);
|
||||
xstep = FixedDiv (x2-x1,abs(y2-y1));
|
||||
}
|
||||
else
|
||||
{
|
||||
mapystep = 0;
|
||||
partial = FRACUNIT;
|
||||
xstep = 256*FRACUNIT;
|
||||
}
|
||||
xintercept = (x1>>MAPBTOFRAC) + FixedMul (partial, xstep);
|
||||
|
||||
|
||||
//
|
||||
// step through map blocks
|
||||
// Count is present to prevent a round off error from skipping the break
|
||||
mapx = xt1;
|
||||
mapy = yt1;
|
||||
|
||||
|
||||
for (count = 0 ; count < 64 ; count++)
|
||||
{
|
||||
if (!P_SightBlockLinesIterator (mapx, mapy))
|
||||
{
|
||||
sightcounts[1]++;
|
||||
return false; // early out
|
||||
}
|
||||
|
||||
if (mapx == xt2 && mapy == yt2)
|
||||
break;
|
||||
|
||||
if ( (yintercept >> FRACBITS) == mapy)
|
||||
{
|
||||
yintercept += ystep;
|
||||
mapx += mapxstep;
|
||||
}
|
||||
else if ( (xintercept >> FRACBITS) == mapx)
|
||||
{
|
||||
xintercept += xstep;
|
||||
mapy += mapystep;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// couldn't early out, so go through the sorted list
|
||||
//
|
||||
sightcounts[2]++;
|
||||
|
||||
return P_SightTraverseIntercepts ( );
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
=====================
|
||||
=
|
||||
= P_CheckSight
|
||||
=
|
||||
= Returns true if a straight line between t1 and t2 is unobstructed
|
||||
= look from eyes of t1 to any part of t2
|
||||
=
|
||||
=====================
|
||||
*/
|
||||
|
||||
boolean P_CheckSight (mobj_t *t1, mobj_t *t2)
|
||||
{
|
||||
int s1, s2;
|
||||
int pnum, bytenum, bitnum;
|
||||
|
||||
//
|
||||
// check for trivial rejection
|
||||
//
|
||||
s1 = (t1->subsector->sector - sectors);
|
||||
s2 = (t2->subsector->sector - sectors);
|
||||
pnum = s1*numsectors + s2;
|
||||
bytenum = pnum>>3;
|
||||
bitnum = 1 << (pnum&7);
|
||||
|
||||
if (rejectmatrix[bytenum]&bitnum)
|
||||
{
|
||||
sightcounts[0]++;
|
||||
return false; // can't possibly be connected
|
||||
}
|
||||
|
||||
//
|
||||
// check precisely
|
||||
//
|
||||
sightzstart = t1->z + t1->height - (t1->height>>2);
|
||||
topslope = (t2->z+t2->height) - sightzstart;
|
||||
bottomslope = (t2->z) - sightzstart;
|
||||
|
||||
return P_SightPathTraverse ( t1->x, t1->y, t2->x, t2->y );
|
||||
}
|
||||
|
||||
|
||||
|
1253
Heretic Source/P_SPEC.C
Normal file
1253
Heretic Source/P_SPEC.C
Normal file
File diff suppressed because it is too large
Load diff
374
Heretic Source/P_SPEC.H
Normal file
374
Heretic Source/P_SPEC.H
Normal file
|
@ -0,0 +1,374 @@
|
|||
|
||||
// P_spec.h
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
|
||||
P_SPEC
|
||||
|
||||
===============================================================================
|
||||
*/
|
||||
|
||||
//
|
||||
// Animating textures and planes
|
||||
//
|
||||
typedef struct
|
||||
{
|
||||
boolean istexture;
|
||||
int picnum;
|
||||
int basepic;
|
||||
int numpics;
|
||||
int speed;
|
||||
} anim_t;
|
||||
|
||||
//
|
||||
// source animation definition
|
||||
//
|
||||
typedef struct
|
||||
{
|
||||
boolean istexture; // if false, it's a flat
|
||||
char endname[9];
|
||||
char startname[9];
|
||||
int speed;
|
||||
} animdef_t;
|
||||
|
||||
#define MAXANIMS 32
|
||||
|
||||
extern anim_t anims[MAXANIMS], *lastanim;
|
||||
extern int *TerrainTypes;
|
||||
|
||||
//
|
||||
// Animating line specials
|
||||
//
|
||||
#define MAXLINEANIMS 64
|
||||
extern short numlinespecials;
|
||||
extern line_t *linespeciallist[MAXLINEANIMS];
|
||||
|
||||
// Define values for map objects
|
||||
#define MO_TELEPORTMAN 14
|
||||
|
||||
// at game start
|
||||
void P_InitPicAnims(void);
|
||||
void P_InitTerrainTypes(void);
|
||||
void P_InitLava(void);
|
||||
|
||||
// at map load
|
||||
void P_SpawnSpecials(void);
|
||||
void P_InitAmbientSound(void);
|
||||
void P_AddAmbientSfx(int sequence);
|
||||
|
||||
// every tic
|
||||
void P_UpdateSpecials(void);
|
||||
void P_AmbientSound(void);
|
||||
|
||||
// when needed
|
||||
boolean P_UseSpecialLine ( mobj_t *thing, line_t *line);
|
||||
void P_ShootSpecialLine ( mobj_t *thing, line_t *line);
|
||||
void P_CrossSpecialLine (int linenum, int side, mobj_t *thing);
|
||||
|
||||
void P_PlayerInSpecialSector (player_t *player);
|
||||
|
||||
int twoSided(int sector,int line);
|
||||
sector_t *getSector(int currentSector,int line,int side);
|
||||
side_t *getSide(int currentSector,int line, int side);
|
||||
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_FindLowestCeilingSurrounding(sector_t *sec);
|
||||
fixed_t P_FindHighestCeilingSurrounding(sector_t *sec);
|
||||
int P_FindSectorFromLineTag(line_t *line,int start);
|
||||
int P_FindMinSurroundingLight(sector_t *sector,int max);
|
||||
sector_t *getNextSector(line_t *line,sector_t *sec);
|
||||
|
||||
//
|
||||
// SPECIAL
|
||||
//
|
||||
int EV_DoDonut(line_t *line);
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
|
||||
P_LIGHTS
|
||||
|
||||
===============================================================================
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
thinker_t thinker;
|
||||
sector_t *sector;
|
||||
int count;
|
||||
int maxlight;
|
||||
int minlight;
|
||||
int maxtime;
|
||||
int mintime;
|
||||
} lightflash_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
thinker_t thinker;
|
||||
sector_t *sector;
|
||||
int count;
|
||||
int minlight;
|
||||
int maxlight;
|
||||
int darktime;
|
||||
int brighttime;
|
||||
} strobe_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
thinker_t thinker;
|
||||
sector_t *sector;
|
||||
int minlight;
|
||||
int maxlight;
|
||||
int direction;
|
||||
} glow_t;
|
||||
|
||||
#define GLOWSPEED 8
|
||||
#define STROBEBRIGHT 5
|
||||
#define FASTDARK 15
|
||||
#define SLOWDARK 35
|
||||
|
||||
void T_LightFlash (lightflash_t *flash);
|
||||
void P_SpawnLightFlash (sector_t *sector);
|
||||
void T_StrobeFlash (strobe_t *flash);
|
||||
void P_SpawnStrobeFlash (sector_t *sector, int fastOrSlow, int inSync);
|
||||
void EV_StartLightStrobing(line_t *line);
|
||||
void EV_TurnTagLightsOff(line_t *line);
|
||||
void EV_LightTurnOn(line_t *line, int bright);
|
||||
void T_Glow(glow_t *g);
|
||||
void P_SpawnGlowingLight(sector_t *sector);
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
|
||||
P_SWITCH
|
||||
|
||||
===============================================================================
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
char name1[9];
|
||||
char name2[9];
|
||||
short episode;
|
||||
} switchlist_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
top,
|
||||
middle,
|
||||
bottom
|
||||
} bwhere_e;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
line_t *line;
|
||||
bwhere_e where;
|
||||
int btexture;
|
||||
int btimer;
|
||||
mobj_t *soundorg;
|
||||
} button_t;
|
||||
|
||||
#define MAXSWITCHES 50 // max # of wall switches in a level
|
||||
#define MAXBUTTONS 16 // 4 players, 4 buttons each at once, max.
|
||||
#define BUTTONTIME 35 // 1 second
|
||||
|
||||
extern button_t buttonlist[MAXBUTTONS];
|
||||
|
||||
void P_ChangeSwitchTexture(line_t *line,int useAgain);
|
||||
void P_InitSwitchList(void);
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
|
||||
P_PLATS
|
||||
|
||||
===============================================================================
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
up,
|
||||
down,
|
||||
waiting,
|
||||
in_stasis
|
||||
} plat_e;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
perpetualRaise,
|
||||
downWaitUpStay,
|
||||
raiseAndChange,
|
||||
raiseToNearestAndChange
|
||||
} plattype_e;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
thinker_t thinker;
|
||||
sector_t *sector;
|
||||
fixed_t speed;
|
||||
fixed_t low;
|
||||
fixed_t high;
|
||||
int wait;
|
||||
int count;
|
||||
plat_e status;
|
||||
plat_e oldstatus;
|
||||
boolean crush;
|
||||
int tag;
|
||||
plattype_e type;
|
||||
} plat_t;
|
||||
|
||||
#define PLATWAIT 3
|
||||
#define PLATSPEED FRACUNIT
|
||||
#define MAXPLATS 30
|
||||
|
||||
extern plat_t *activeplats[MAXPLATS];
|
||||
|
||||
void T_PlatRaise(plat_t *plat);
|
||||
int EV_DoPlat(line_t *line,plattype_e type,int amount);
|
||||
void P_AddActivePlat(plat_t *plat);
|
||||
void P_RemoveActivePlat(plat_t *plat);
|
||||
void EV_StopPlat(line_t *line);
|
||||
void P_ActivateInStasis(int tag);
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
|
||||
P_DOORS
|
||||
|
||||
===============================================================================
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
normal,
|
||||
close30ThenOpen,
|
||||
close,
|
||||
open,
|
||||
raiseIn5Mins
|
||||
} vldoor_e;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
thinker_t thinker;
|
||||
vldoor_e type;
|
||||
sector_t *sector;
|
||||
fixed_t topheight;
|
||||
fixed_t speed;
|
||||
int direction; // 1 = up, 0 = waiting at top, -1 = down
|
||||
int topwait; // tics to wait at the top
|
||||
// (keep in case a door going down is reset)
|
||||
int topcountdown; // when it reaches 0, start going down
|
||||
} vldoor_t;
|
||||
|
||||
#define VDOORSPEED FRACUNIT*2
|
||||
#define VDOORWAIT 150
|
||||
|
||||
void EV_VerticalDoor (line_t *line, mobj_t *thing);
|
||||
int EV_DoDoor (line_t *line, vldoor_e type, fixed_t speed);
|
||||
void T_VerticalDoor (vldoor_t *door);
|
||||
void P_SpawnDoorCloseIn30 (sector_t *sec);
|
||||
void P_SpawnDoorRaiseIn5Mins (sector_t *sec, int secnum);
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
|
||||
P_CEILNG
|
||||
|
||||
===============================================================================
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
lowerToFloor,
|
||||
raiseToHighest,
|
||||
lowerAndCrush,
|
||||
crushAndRaise,
|
||||
fastCrushAndRaise
|
||||
} ceiling_e;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
thinker_t thinker;
|
||||
ceiling_e type;
|
||||
sector_t *sector;
|
||||
fixed_t bottomheight, topheight;
|
||||
fixed_t speed;
|
||||
boolean crush;
|
||||
int direction; // 1 = up, 0 = waiting, -1 = down
|
||||
int tag; // ID
|
||||
int olddirection;
|
||||
} ceiling_t;
|
||||
|
||||
#define CEILSPEED FRACUNIT
|
||||
#define CEILWAIT 150
|
||||
#define MAXCEILINGS 30
|
||||
|
||||
extern ceiling_t *activeceilings[MAXCEILINGS];
|
||||
|
||||
int EV_DoCeiling (line_t *line, ceiling_e type);
|
||||
void T_MoveCeiling (ceiling_t *ceiling);
|
||||
void P_AddActiveCeiling(ceiling_t *c);
|
||||
void P_RemoveActiveCeiling(ceiling_t *c);
|
||||
int EV_CeilingCrushStop(line_t *line);
|
||||
void P_ActivateInStasisCeiling(line_t *line);
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
|
||||
P_FLOOR
|
||||
|
||||
===============================================================================
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
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,
|
||||
donutRaise,
|
||||
raiseBuildStep // One step of a staircase
|
||||
} floor_e;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
thinker_t thinker;
|
||||
floor_e type;
|
||||
boolean crush;
|
||||
sector_t *sector;
|
||||
int direction;
|
||||
int newspecial;
|
||||
short texture;
|
||||
fixed_t floordestheight;
|
||||
fixed_t speed;
|
||||
} floormove_t;
|
||||
|
||||
#define FLOORSPEED FRACUNIT
|
||||
|
||||
typedef enum
|
||||
{
|
||||
ok,
|
||||
crushed,
|
||||
pastdest
|
||||
} result_e;
|
||||
|
||||
result_e T_MovePlane(sector_t *sector,fixed_t speed,
|
||||
fixed_t dest,boolean crush,int floorOrCeiling,int direction);
|
||||
|
||||
int EV_BuildStairs(line_t *line, fixed_t stepDelta);
|
||||
int EV_DoFloor(line_t *line,floor_e floortype);
|
||||
void T_MoveFloor(floormove_t *floor);
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
|
||||
P_TELEPT
|
||||
|
||||
===============================================================================
|
||||
*/
|
||||
|
||||
boolean P_Teleport(mobj_t *thing, fixed_t x, fixed_t y, angle_t angle);
|
||||
boolean EV_Teleport(line_t *line, int side, mobj_t *thing);
|
390
Heretic Source/P_SWITCH.C
Normal file
390
Heretic Source/P_SWITCH.C
Normal file
|
@ -0,0 +1,390 @@
|
|||
|
||||
#include "DoomDef.h"
|
||||
#include "P_local.h"
|
||||
#include "soundst.h"
|
||||
|
||||
//==================================================================
|
||||
//
|
||||
// CHANGE THE TEXTURE OF A WALL SWITCH TO ITS OPPOSITE
|
||||
//
|
||||
//==================================================================
|
||||
switchlist_t alphSwitchList[] =
|
||||
{
|
||||
{"SW1OFF", "SW1ON", 1},
|
||||
{"SW2OFF", "SW2ON", 1},
|
||||
|
||||
/*
|
||||
{"SW1CTY", "SW2CTY", 1},
|
||||
{"SW1ORGRY", "SW2ORGRY", 1},
|
||||
{"SW1GRSTN", "SW2GRSTN", 1},
|
||||
{"SW1SNDP", "SW2SNDP", 1},
|
||||
{"SW1SPINE", "SW2SPINE", 1},
|
||||
{"SW1SQPEB", "SW2SQPEB", 1},
|
||||
{"SW1TRST1", "SW2TRST1", 1},
|
||||
{"SW1CSTL", "SW2CSTL", 1},
|
||||
{"SW1MOSS", "SW2MOSS", 1},
|
||||
{"SW1SNDSQ", "SW2SNDSQ", 1},
|
||||
{"SW1RED", "SW2RED", 1},
|
||||
{"SW1WOOD", "SW2WOOD", 1},
|
||||
{"SW1BROWN", "SW2BROWN", 1},
|
||||
|
||||
{"SW1TRST2", "SW2TRST2", 2},
|
||||
{"SW1MSC", "SW2MSC", 2},
|
||||
{"SW1MSC2", "SW2MSC2", 2},
|
||||
{"SW1GRDMD", "SW2GRDMD", 2},
|
||||
*/
|
||||
|
||||
#if 0
|
||||
{"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},
|
||||
|
||||
{"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},
|
||||
#endif
|
||||
{"\0", "\0", 0}
|
||||
};
|
||||
|
||||
int switchlist[MAXSWITCHES * 2];
|
||||
int numswitches;
|
||||
button_t buttonlist[MAXBUTTONS];
|
||||
|
||||
/*
|
||||
===============
|
||||
=
|
||||
= P_InitSwitchList
|
||||
=
|
||||
= Only called at game initialization
|
||||
=
|
||||
===============
|
||||
*/
|
||||
|
||||
void P_InitSwitchList(void)
|
||||
{
|
||||
int i;
|
||||
int index;
|
||||
int episode;
|
||||
|
||||
episode = 1;
|
||||
if (!shareware)
|
||||
episode = 2;
|
||||
|
||||
for (index = 0,i = 0;i < MAXSWITCHES;i++)
|
||||
{
|
||||
if (!alphSwitchList[i].episode)
|
||||
{
|
||||
numswitches = index/2;
|
||||
switchlist[index] = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (alphSwitchList[i].episode <= episode)
|
||||
{
|
||||
switchlist[index++] = R_TextureNumForName(alphSwitchList[i].name1);
|
||||
switchlist[index++] = R_TextureNumForName(alphSwitchList[i].name2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//==================================================================
|
||||
//
|
||||
// Start a button counting down till it turns off.
|
||||
//
|
||||
//==================================================================
|
||||
void P_StartButton(line_t *line,bwhere_e w,int texture,int time)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0;i < MAXBUTTONS;i++)
|
||||
if (!buttonlist[i].btimer)
|
||||
{
|
||||
buttonlist[i].line = line;
|
||||
buttonlist[i].where = w;
|
||||
buttonlist[i].btexture = texture;
|
||||
buttonlist[i].btimer = time;
|
||||
buttonlist[i].soundorg = (mobj_t *)&line->frontsector->soundorg;
|
||||
return;
|
||||
}
|
||||
|
||||
I_Error("P_StartButton: no button slots left!");
|
||||
}
|
||||
|
||||
//==================================================================
|
||||
//
|
||||
// Function that changes wall texture.
|
||||
// Tell it if switch is ok to use again (1=yes, it's a button).
|
||||
//
|
||||
//==================================================================
|
||||
void P_ChangeSwitchTexture(line_t *line,int useAgain)
|
||||
{
|
||||
int texTop;
|
||||
int texMid;
|
||||
int texBot;
|
||||
int i;
|
||||
int sound;
|
||||
|
||||
if (!useAgain)
|
||||
line->special = 0;
|
||||
|
||||
texTop = sides[line->sidenum[0]].toptexture;
|
||||
texMid = sides[line->sidenum[0]].midtexture;
|
||||
texBot = sides[line->sidenum[0]].bottomtexture;
|
||||
|
||||
sound = sfx_switch;
|
||||
//if (line->special == 11) // EXIT SWITCH?
|
||||
// sound = sfx_swtchx;
|
||||
|
||||
for (i = 0;i < numswitches*2;i++)
|
||||
if (switchlist[i] == texTop)
|
||||
{
|
||||
S_StartSound(buttonlist->soundorg,sound);
|
||||
sides[line->sidenum[0]].toptexture = switchlist[i^1];
|
||||
if (useAgain)
|
||||
P_StartButton(line,top,switchlist[i],BUTTONTIME);
|
||||
return;
|
||||
}
|
||||
else
|
||||
if (switchlist[i] == texMid)
|
||||
{
|
||||
S_StartSound(buttonlist->soundorg,sound);
|
||||
sides[line->sidenum[0]].midtexture = switchlist[i^1];
|
||||
if (useAgain)
|
||||
P_StartButton(line, middle,switchlist[i],BUTTONTIME);
|
||||
return;
|
||||
}
|
||||
else
|
||||
if (switchlist[i] == texBot)
|
||||
{
|
||||
S_StartSound(buttonlist->soundorg,sound);
|
||||
sides[line->sidenum[0]].bottomtexture = switchlist[i^1];
|
||||
if (useAgain)
|
||||
P_StartButton(line, bottom,switchlist[i],BUTTONTIME);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
==============================================================================
|
||||
=
|
||||
= P_UseSpecialLine
|
||||
=
|
||||
= Called when a thing uses a special line
|
||||
= Only the front sides of lines are usable
|
||||
===============================================================================
|
||||
*/
|
||||
|
||||
boolean P_UseSpecialLine ( mobj_t *thing, line_t *line)
|
||||
{
|
||||
//
|
||||
// Switches that other things can activate
|
||||
//
|
||||
if (!thing->player)
|
||||
{
|
||||
if (line->flags & ML_SECRET)
|
||||
return false; // never open secret doors
|
||||
switch(line->special)
|
||||
{
|
||||
case 1: // MANUAL DOOR RAISE
|
||||
case 32: // MANUAL BLUE
|
||||
case 33: // MANUAL RED
|
||||
case 34: // MANUAL YELLOW
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// do something
|
||||
//
|
||||
switch (line->special)
|
||||
{
|
||||
//===============================================
|
||||
// MANUALS
|
||||
//===============================================
|
||||
case 1: // Vertical Door
|
||||
case 26: // Blue Door/Locked
|
||||
case 27: // Yellow Door /Locked
|
||||
case 28: // Red Door /Locked
|
||||
|
||||
case 31: // Manual door open
|
||||
case 32: // Blue locked door open
|
||||
case 33: // Red locked door open
|
||||
case 34: // Yellow locked door open
|
||||
EV_VerticalDoor (line, thing);
|
||||
break;
|
||||
//===============================================
|
||||
// SWITCHES
|
||||
//===============================================
|
||||
case 7: // Switch_Build_Stairs (8 pixel steps)
|
||||
if(EV_BuildStairs(line, 8*FRACUNIT))
|
||||
{
|
||||
P_ChangeSwitchTexture(line, 0);
|
||||
}
|
||||
break;
|
||||
case 107: // Switch_Build_Stairs_16 (16 pixel steps)
|
||||
if(EV_BuildStairs(line, 16*FRACUNIT))
|
||||
{
|
||||
P_ChangeSwitchTexture(line, 0);
|
||||
}
|
||||
break;
|
||||
case 9: // Change Donut
|
||||
if (EV_DoDonut(line))
|
||||
P_ChangeSwitchTexture(line,0);
|
||||
break;
|
||||
case 11: // Exit level
|
||||
G_ExitLevel ();
|
||||
P_ChangeSwitchTexture(line,0);
|
||||
break;
|
||||
case 14: // Raise Floor 32 and change texture
|
||||
if (EV_DoPlat(line,raiseAndChange,32))
|
||||
P_ChangeSwitchTexture(line,0);
|
||||
break;
|
||||
case 15: // Raise Floor 24 and change texture
|
||||
if (EV_DoPlat(line,raiseAndChange,24))
|
||||
P_ChangeSwitchTexture(line,0);
|
||||
break;
|
||||
case 18: // Raise Floor to next highest floor
|
||||
if (EV_DoFloor(line, raiseFloorToNearest))
|
||||
P_ChangeSwitchTexture(line,0);
|
||||
break;
|
||||
case 20: // Raise Plat next highest floor and change texture
|
||||
if (EV_DoPlat(line,raiseToNearestAndChange,0))
|
||||
P_ChangeSwitchTexture(line,0);
|
||||
break;
|
||||
case 21: // PlatDownWaitUpStay
|
||||
if (EV_DoPlat(line,downWaitUpStay,0))
|
||||
P_ChangeSwitchTexture(line,0);
|
||||
break;
|
||||
case 23: // Lower Floor to Lowest
|
||||
if (EV_DoFloor(line,lowerFloorToLowest))
|
||||
P_ChangeSwitchTexture(line,0);
|
||||
break;
|
||||
case 29: // Raise Door
|
||||
if (EV_DoDoor(line,normal,VDOORSPEED))
|
||||
P_ChangeSwitchTexture(line,0);
|
||||
break;
|
||||
case 41: // Lower Ceiling to Floor
|
||||
if (EV_DoCeiling(line,lowerToFloor))
|
||||
P_ChangeSwitchTexture(line,0);
|
||||
break;
|
||||
case 71: // Turbo Lower Floor
|
||||
if (EV_DoFloor(line,turboLower))
|
||||
P_ChangeSwitchTexture(line,0);
|
||||
break;
|
||||
case 49: // Lower Ceiling And Crush
|
||||
if (EV_DoCeiling(line,lowerAndCrush))
|
||||
P_ChangeSwitchTexture(line,0);
|
||||
break;
|
||||
case 50: // Close Door
|
||||
if (EV_DoDoor(line,close,VDOORSPEED))
|
||||
P_ChangeSwitchTexture(line,0);
|
||||
break;
|
||||
case 51: // Secret EXIT
|
||||
G_SecretExitLevel ();
|
||||
P_ChangeSwitchTexture(line,0);
|
||||
break;
|
||||
case 55: // Raise Floor Crush
|
||||
if (EV_DoFloor(line,raiseFloorCrush))
|
||||
P_ChangeSwitchTexture(line,0);
|
||||
break;
|
||||
case 101: // Raise Floor
|
||||
if (EV_DoFloor(line,raiseFloor))
|
||||
P_ChangeSwitchTexture(line,0);
|
||||
break;
|
||||
case 102: // Lower Floor to Surrounding floor height
|
||||
if (EV_DoFloor(line,lowerFloor))
|
||||
P_ChangeSwitchTexture(line,0);
|
||||
break;
|
||||
case 103: // Open Door
|
||||
if (EV_DoDoor(line,open,VDOORSPEED))
|
||||
P_ChangeSwitchTexture(line,0);
|
||||
break;
|
||||
//===============================================
|
||||
// BUTTONS
|
||||
//===============================================
|
||||
case 42: // Close Door
|
||||
if (EV_DoDoor(line,close,VDOORSPEED))
|
||||
P_ChangeSwitchTexture(line,1);
|
||||
break;
|
||||
case 43: // Lower Ceiling to Floor
|
||||
if (EV_DoCeiling(line,lowerToFloor))
|
||||
P_ChangeSwitchTexture(line,1);
|
||||
break;
|
||||
case 45: // Lower Floor to Surrounding floor height
|
||||
if (EV_DoFloor(line,lowerFloor))
|
||||
P_ChangeSwitchTexture(line,1);
|
||||
break;
|
||||
case 60: // Lower Floor to Lowest
|
||||
if (EV_DoFloor(line,lowerFloorToLowest))
|
||||
P_ChangeSwitchTexture(line,1);
|
||||
break;
|
||||
case 61: // Open Door
|
||||
if (EV_DoDoor(line,open,VDOORSPEED))
|
||||
P_ChangeSwitchTexture(line,1);
|
||||
break;
|
||||
case 62: // PlatDownWaitUpStay
|
||||
if (EV_DoPlat(line,downWaitUpStay,1))
|
||||
P_ChangeSwitchTexture(line,1);
|
||||
break;
|
||||
case 63: // Raise Door
|
||||
if (EV_DoDoor(line,normal,VDOORSPEED))
|
||||
P_ChangeSwitchTexture(line,1);
|
||||
break;
|
||||
case 64: // Raise Floor to ceiling
|
||||
if (EV_DoFloor(line,raiseFloor))
|
||||
P_ChangeSwitchTexture(line,1);
|
||||
break;
|
||||
case 66: // Raise Floor 24 and change texture
|
||||
if (EV_DoPlat(line,raiseAndChange,24))
|
||||
P_ChangeSwitchTexture(line,1);
|
||||
break;
|
||||
case 67: // Raise Floor 32 and change texture
|
||||
if (EV_DoPlat(line,raiseAndChange,32))
|
||||
P_ChangeSwitchTexture(line,1);
|
||||
break;
|
||||
case 65: // Raise Floor Crush
|
||||
if (EV_DoFloor(line,raiseFloorCrush))
|
||||
P_ChangeSwitchTexture(line,1);
|
||||
break;
|
||||
case 68: // Raise Plat to next highest floor and change texture
|
||||
if (EV_DoPlat(line,raiseToNearestAndChange,0))
|
||||
P_ChangeSwitchTexture(line,1);
|
||||
break;
|
||||
case 69: // Raise Floor to next highest floor
|
||||
if (EV_DoFloor(line, raiseFloorToNearest))
|
||||
P_ChangeSwitchTexture(line,1);
|
||||
break;
|
||||
case 70: // Turbo Lower Floor
|
||||
if (EV_DoFloor(line,turboLower))
|
||||
P_ChangeSwitchTexture(line,1);
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
148
Heretic Source/P_TELEPT.C
Normal file
148
Heretic Source/P_TELEPT.C
Normal file
|
@ -0,0 +1,148 @@
|
|||
|
||||
// P_telept.c
|
||||
|
||||
#include "DoomDef.h"
|
||||
#include "P_local.h"
|
||||
#include "soundst.h"
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// FUNC P_Teleport
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
boolean P_Teleport(mobj_t *thing, fixed_t x, fixed_t y, angle_t angle)
|
||||
{
|
||||
fixed_t oldx;
|
||||
fixed_t oldy;
|
||||
fixed_t oldz;
|
||||
fixed_t aboveFloor;
|
||||
fixed_t fogDelta;
|
||||
player_t *player;
|
||||
unsigned an;
|
||||
mobj_t *fog;
|
||||
|
||||
oldx = thing->x;
|
||||
oldy = thing->y;
|
||||
oldz = thing->z;
|
||||
aboveFloor = thing->z-thing->floorz;
|
||||
if(!P_TeleportMove(thing, x, y))
|
||||
{
|
||||
return(false);
|
||||
}
|
||||
if(thing->player)
|
||||
{
|
||||
player = thing->player;
|
||||
if(player->powers[pw_flight] && aboveFloor)
|
||||
{
|
||||
thing->z = thing->floorz+aboveFloor;
|
||||
if(thing->z+thing->height > thing->ceilingz)
|
||||
{
|
||||
thing->z = thing->ceilingz-thing->height;
|
||||
}
|
||||
player->viewz = thing->z+player->viewheight;
|
||||
}
|
||||
else
|
||||
{
|
||||
thing->z = thing->floorz;
|
||||
player->viewz = thing->z+player->viewheight;
|
||||
player->lookdir = 0;
|
||||
}
|
||||
}
|
||||
else if(thing->flags&MF_MISSILE)
|
||||
{
|
||||
thing->z = thing->floorz+aboveFloor;
|
||||
if(thing->z+thing->height > thing->ceilingz)
|
||||
{
|
||||
thing->z = thing->ceilingz-thing->height;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
thing->z = thing->floorz;
|
||||
}
|
||||
// Spawn teleport fog at source and destination
|
||||
fogDelta = thing->flags&MF_MISSILE ? 0 : TELEFOGHEIGHT;
|
||||
fog = P_SpawnMobj(oldx, oldy, oldz+fogDelta, MT_TFOG);
|
||||
S_StartSound(fog, sfx_telept);
|
||||
an = angle>>ANGLETOFINESHIFT;
|
||||
fog = P_SpawnMobj(x+20*finecosine[an],
|
||||
y+20*finesine[an], thing->z+fogDelta, MT_TFOG);
|
||||
S_StartSound(fog, sfx_telept);
|
||||
if(thing->player && !thing->player->powers[pw_weaponlevel2])
|
||||
{ // Freeze player for about .5 sec
|
||||
thing->reactiontime = 18;
|
||||
}
|
||||
thing->angle = angle;
|
||||
if(thing->flags2&MF2_FOOTCLIP && P_GetThingFloorType(thing) != FLOOR_SOLID)
|
||||
{
|
||||
thing->flags2 |= MF2_FEETARECLIPPED;
|
||||
}
|
||||
else if(thing->flags2&MF2_FEETARECLIPPED)
|
||||
{
|
||||
thing->flags2 &= ~MF2_FEETARECLIPPED;
|
||||
}
|
||||
if(thing->flags&MF_MISSILE)
|
||||
{
|
||||
angle >>= ANGLETOFINESHIFT;
|
||||
thing->momx = FixedMul(thing->info->speed, finecosine[angle]);
|
||||
thing->momy = FixedMul(thing->info->speed, finesine[angle]);
|
||||
}
|
||||
else
|
||||
{
|
||||
thing->momx = thing->momy = thing->momz = 0;
|
||||
}
|
||||
return(true);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// FUNC EV_Teleport
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
boolean EV_Teleport(line_t *line, int side, mobj_t *thing)
|
||||
{
|
||||
int i;
|
||||
int tag;
|
||||
mobj_t *m;
|
||||
thinker_t *thinker;
|
||||
sector_t *sector;
|
||||
|
||||
if(thing->flags2&MF2_NOTELEPORT)
|
||||
{
|
||||
return(false);
|
||||
}
|
||||
if(side == 1)
|
||||
{ // Don't teleport when crossing back side
|
||||
return(false);
|
||||
}
|
||||
tag = line->tag;
|
||||
for(i = 0; i < numsectors; i++)
|
||||
{
|
||||
if(sectors[i].tag == tag)
|
||||
{
|
||||
thinker = thinkercap.next;
|
||||
for(thinker = thinkercap.next; thinker != &thinkercap;
|
||||
thinker = thinker->next)
|
||||
{
|
||||
if(thinker->function != P_MobjThinker)
|
||||
{ // Not a mobj
|
||||
continue;
|
||||
}
|
||||
m = (mobj_t *)thinker;
|
||||
if(m->type != MT_TELEPORTMAN )
|
||||
{ // Not a teleportman
|
||||
continue;
|
||||
}
|
||||
sector = m->subsector->sector;
|
||||
if(sector-sectors != i)
|
||||
{ // Wrong sector
|
||||
continue;
|
||||
}
|
||||
return(P_Teleport(thing, m->x, m->y, m->angle));
|
||||
}
|
||||
}
|
||||
}
|
||||
return(false);
|
||||
}
|
643
Heretic Source/P_TICK.C
Normal file
643
Heretic Source/P_TICK.C
Normal file
|
@ -0,0 +1,643 @@
|
|||
|
||||
// P_tick.c
|
||||
|
||||
#include "DoomDef.h"
|
||||
#include "P_local.h"
|
||||
|
||||
int leveltime;
|
||||
int TimerGame;
|
||||
|
||||
/*
|
||||
====================
|
||||
=
|
||||
= P_ArchivePlayers
|
||||
=
|
||||
====================
|
||||
*/
|
||||
|
||||
void P_ArchivePlayers(void)
|
||||
{
|
||||
int i;
|
||||
int j;
|
||||
player_t dest;
|
||||
|
||||
for(i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if(!playeringame[i])
|
||||
{
|
||||
continue;
|
||||
}
|
||||
memcpy(&dest, &players[i], sizeof(player_t));
|
||||
for(j = 0; j < NUMPSPRITES; j++)
|
||||
{
|
||||
if(dest.psprites[j].state)
|
||||
{
|
||||
dest.psprites[j].state =
|
||||
(state_t *)(dest.psprites[j].state-states);
|
||||
}
|
||||
}
|
||||
SV_Write(&dest, sizeof(player_t));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
=
|
||||
= P_UnArchivePlayers
|
||||
=
|
||||
====================
|
||||
*/
|
||||
|
||||
void P_UnArchivePlayers (void)
|
||||
{
|
||||
int i,j;
|
||||
|
||||
for (i=0 ; i<MAXPLAYERS ; i++)
|
||||
{
|
||||
if (!playeringame[i])
|
||||
continue;
|
||||
memcpy (&players[i],save_p, sizeof(player_t));
|
||||
save_p += sizeof(player_t);
|
||||
players[i].mo = NULL; // will be set when unarc thinker
|
||||
players[i].message = NULL;
|
||||
players[i].attacker = NULL;
|
||||
for (j=0 ; j<NUMPSPRITES ; j++)
|
||||
if (players[i]. psprites[j].state)
|
||||
players[i]. psprites[j].state
|
||||
= &states[ (int)players[i].psprites[j].state ];
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
||||
|
||||
/*
|
||||
====================
|
||||
=
|
||||
= P_ArchiveWorld
|
||||
=
|
||||
====================
|
||||
*/
|
||||
|
||||
void P_ArchiveWorld(void)
|
||||
{
|
||||
int i, j;
|
||||
sector_t *sec;
|
||||
line_t *li;
|
||||
side_t *si;
|
||||
|
||||
// Sectors
|
||||
for(i = 0, sec = sectors; i < numsectors; i++, sec++)
|
||||
{
|
||||
SV_WriteWord(sec->floorheight>>FRACBITS);
|
||||
SV_WriteWord(sec->ceilingheight>>FRACBITS);
|
||||
SV_WriteWord(sec->floorpic);
|
||||
SV_WriteWord(sec->ceilingpic);
|
||||
SV_WriteWord(sec->lightlevel);
|
||||
SV_WriteWord(sec->special); // needed?
|
||||
SV_WriteWord(sec->tag); // needed?
|
||||
}
|
||||
|
||||
// Lines
|
||||
for(i = 0, li = lines; i < numlines; i++, li++)
|
||||
{
|
||||
SV_WriteWord(li->flags);
|
||||
SV_WriteWord(li->special);
|
||||
SV_WriteWord(li->tag);
|
||||
for(j = 0; j < 2; j++)
|
||||
{
|
||||
if(li->sidenum[j] == -1)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
si = &sides[li->sidenum[j]];
|
||||
SV_WriteWord(si->textureoffset>>FRACBITS);
|
||||
SV_WriteWord(si->rowoffset>>FRACBITS);
|
||||
SV_WriteWord(si->toptexture);
|
||||
SV_WriteWord(si->bottomtexture);
|
||||
SV_WriteWord(si->midtexture);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
=
|
||||
= P_UnArchiveWorld
|
||||
=
|
||||
====================
|
||||
*/
|
||||
|
||||
void P_UnArchiveWorld (void)
|
||||
{
|
||||
int i,j;
|
||||
sector_t *sec;
|
||||
line_t *li;
|
||||
side_t *si;
|
||||
short *get;
|
||||
|
||||
get = (short *)save_p;
|
||||
|
||||
//
|
||||
// do sectors
|
||||
//
|
||||
for (i=0, sec = sectors ; i<numsectors ; i++,sec++)
|
||||
{
|
||||
sec->floorheight = *get++ << FRACBITS;
|
||||
sec->ceilingheight = *get++ << FRACBITS;
|
||||
sec->floorpic = *get++;
|
||||
sec->ceilingpic = *get++;
|
||||
sec->lightlevel = *get++;
|
||||
sec->special = *get++; // needed?
|
||||
sec->tag = *get++; // needed?
|
||||
sec->specialdata = 0;
|
||||
sec->soundtarget = 0;
|
||||
}
|
||||
|
||||
//
|
||||
// do lines
|
||||
//
|
||||
for (i=0, li = lines ; i<numlines ; i++,li++)
|
||||
{
|
||||
li->flags = *get++;
|
||||
li->special = *get++;
|
||||
li->tag = *get++;
|
||||
for (j=0 ; j<2 ; j++)
|
||||
{
|
||||
if (li->sidenum[j] == -1)
|
||||
continue;
|
||||
si = &sides[li->sidenum[j]];
|
||||
si->textureoffset = *get++ << FRACBITS;
|
||||
si->rowoffset = *get++ << FRACBITS;
|
||||
si->toptexture = *get++;
|
||||
si->bottomtexture = *get++;
|
||||
si->midtexture = *get++;
|
||||
}
|
||||
}
|
||||
|
||||
save_p = (byte *)get;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
||||
typedef enum
|
||||
{
|
||||
tc_end,
|
||||
tc_mobj
|
||||
} thinkerclass_t;
|
||||
|
||||
/*
|
||||
====================
|
||||
=
|
||||
= P_ArchiveThinkers
|
||||
=
|
||||
====================
|
||||
*/
|
||||
|
||||
void P_ArchiveThinkers(void)
|
||||
{
|
||||
thinker_t *th;
|
||||
mobj_t mobj;
|
||||
|
||||
for(th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
{
|
||||
if(th->function == P_MobjThinker)
|
||||
{
|
||||
SV_WriteByte(tc_mobj);
|
||||
memcpy(&mobj, th, sizeof(mobj_t));
|
||||
mobj.state = (state_t *)(mobj.state-states);
|
||||
if(mobj.player)
|
||||
{
|
||||
mobj.player = (player_t *)((mobj.player-players)+1);
|
||||
}
|
||||
SV_Write(&mobj, sizeof(mobj_t));
|
||||
continue;
|
||||
}
|
||||
//I_Error("P_ArchiveThinkers: Unknown thinker function");
|
||||
}
|
||||
|
||||
// Add a terminating marker
|
||||
SV_WriteByte(tc_end);
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
=
|
||||
= P_UnArchiveThinkers
|
||||
=
|
||||
====================
|
||||
*/
|
||||
|
||||
void P_UnArchiveThinkers (void)
|
||||
{
|
||||
byte tclass;
|
||||
thinker_t *currentthinker, *next;
|
||||
mobj_t *mobj;
|
||||
|
||||
//
|
||||
// remove all the current thinkers
|
||||
//
|
||||
currentthinker = thinkercap.next;
|
||||
while (currentthinker != &thinkercap)
|
||||
{
|
||||
next = currentthinker->next;
|
||||
if (currentthinker->function == P_MobjThinker)
|
||||
P_RemoveMobj ((mobj_t *)currentthinker);
|
||||
else
|
||||
Z_Free (currentthinker);
|
||||
currentthinker = next;
|
||||
}
|
||||
P_InitThinkers ();
|
||||
|
||||
// read in saved thinkers
|
||||
while (1)
|
||||
{
|
||||
tclass = *save_p++;
|
||||
switch (tclass)
|
||||
{
|
||||
case tc_end:
|
||||
return; // end of list
|
||||
|
||||
case tc_mobj:
|
||||
mobj = Z_Malloc (sizeof(*mobj), PU_LEVEL, NULL);
|
||||
memcpy (mobj, save_p, sizeof(*mobj));
|
||||
save_p += sizeof(*mobj);
|
||||
mobj->state = &states[(int)mobj->state];
|
||||
mobj->target = NULL;
|
||||
if (mobj->player)
|
||||
{
|
||||
mobj->player = &players[(int)mobj->player-1];
|
||||
mobj->player->mo = mobj;
|
||||
}
|
||||
P_SetThingPosition (mobj);
|
||||
mobj->info = &mobjinfo[mobj->type];
|
||||
mobj->floorz = mobj->subsector->sector->floorheight;
|
||||
mobj->ceilingz = mobj->subsector->sector->ceilingheight;
|
||||
mobj->thinker.function = P_MobjThinker;
|
||||
P_AddThinker (&mobj->thinker);
|
||||
break;
|
||||
|
||||
default:
|
||||
I_Error ("Unknown tclass %i in savegame",tclass);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
||||
|
||||
/*
|
||||
====================
|
||||
=
|
||||
= P_ArchiveSpecials
|
||||
=
|
||||
====================
|
||||
*/
|
||||
enum
|
||||
{
|
||||
tc_ceiling,
|
||||
tc_door,
|
||||
tc_floor,
|
||||
tc_plat,
|
||||
tc_flash,
|
||||
tc_strobe,
|
||||
tc_glow,
|
||||
tc_endspecials
|
||||
} specials_e;
|
||||
|
||||
void P_ArchiveSpecials(void)
|
||||
{
|
||||
/*
|
||||
T_MoveCeiling, (ceiling_t: sector_t * swizzle), - active list
|
||||
T_VerticalDoor, (vldoor_t: sector_t * swizzle),
|
||||
T_MoveFloor, (floormove_t: sector_t * swizzle),
|
||||
T_LightFlash, (lightflash_t: sector_t * swizzle),
|
||||
T_StrobeFlash, (strobe_t: sector_t *),
|
||||
T_Glow, (glow_t: sector_t *),
|
||||
T_PlatRaise, (plat_t: sector_t *), - active list
|
||||
*/
|
||||
|
||||
thinker_t *th;
|
||||
ceiling_t ceiling;
|
||||
vldoor_t door;
|
||||
floormove_t floor;
|
||||
plat_t plat;
|
||||
lightflash_t flash;
|
||||
strobe_t strobe;
|
||||
glow_t glow;
|
||||
|
||||
for(th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
{
|
||||
if(th->function == T_MoveCeiling)
|
||||
{
|
||||
SV_WriteByte(tc_ceiling);
|
||||
memcpy(&ceiling, th, sizeof(ceiling_t));
|
||||
ceiling.sector = (sector_t *)(ceiling.sector-sectors);
|
||||
SV_Write(&ceiling, sizeof(ceiling_t));
|
||||
continue;
|
||||
}
|
||||
if(th->function == T_VerticalDoor)
|
||||
{
|
||||
SV_WriteByte(tc_door);
|
||||
memcpy(&door, th, sizeof(vldoor_t));
|
||||
door.sector = (sector_t *)(door.sector-sectors);
|
||||
SV_Write(&door, sizeof(vldoor_t));
|
||||
continue;
|
||||
}
|
||||
if(th->function == T_MoveFloor)
|
||||
{
|
||||
SV_WriteByte(tc_floor);
|
||||
memcpy(&floor, th, sizeof(floormove_t));
|
||||
floor.sector = (sector_t *)(floor.sector-sectors);
|
||||
SV_Write(&floor, sizeof(floormove_t));
|
||||
continue;
|
||||
}
|
||||
if(th->function == T_PlatRaise)
|
||||
{
|
||||
SV_WriteByte(tc_plat);
|
||||
memcpy(&plat, th, sizeof(plat_t));
|
||||
plat.sector = (sector_t *)(plat.sector-sectors);
|
||||
SV_Write(&plat, sizeof(plat_t));
|
||||
continue;
|
||||
}
|
||||
if(th->function == T_LightFlash)
|
||||
{
|
||||
SV_WriteByte(tc_flash);
|
||||
memcpy(&flash, th, sizeof(lightflash_t));
|
||||
flash.sector = (sector_t *)(flash.sector-sectors);
|
||||
SV_Write(&flash, sizeof(lightflash_t));
|
||||
continue;
|
||||
}
|
||||
if(th->function == T_StrobeFlash)
|
||||
{
|
||||
SV_WriteByte(tc_strobe);
|
||||
memcpy(&strobe, th, sizeof(strobe_t));
|
||||
strobe.sector = (sector_t *)(strobe.sector-sectors);
|
||||
SV_Write(&strobe, sizeof(strobe_t));
|
||||
continue;
|
||||
}
|
||||
if(th->function == T_Glow)
|
||||
{
|
||||
SV_WriteByte(tc_glow);
|
||||
memcpy(&glow, th, sizeof(glow_t));
|
||||
glow.sector = (sector_t *)(glow.sector-sectors);
|
||||
SV_Write(&glow, sizeof(glow_t));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// Add a terminating marker
|
||||
SV_WriteByte(tc_endspecials);
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
=
|
||||
= P_UnArchiveSpecials
|
||||
=
|
||||
====================
|
||||
*/
|
||||
|
||||
void P_UnArchiveSpecials (void)
|
||||
{
|
||||
byte tclass;
|
||||
ceiling_t *ceiling;
|
||||
vldoor_t *door;
|
||||
floormove_t *floor;
|
||||
plat_t *plat;
|
||||
lightflash_t *flash;
|
||||
strobe_t *strobe;
|
||||
glow_t *glow;
|
||||
|
||||
|
||||
// read in saved thinkers
|
||||
while (1)
|
||||
{
|
||||
tclass = *save_p++;
|
||||
switch (tclass)
|
||||
{
|
||||
case tc_endspecials:
|
||||
return; // end of list
|
||||
|
||||
case tc_ceiling:
|
||||
ceiling = Z_Malloc (sizeof(*ceiling), PU_LEVEL, NULL);
|
||||
memcpy (ceiling, save_p, sizeof(*ceiling));
|
||||
save_p += sizeof(*ceiling);
|
||||
ceiling->sector = §ors[(int)ceiling->sector];
|
||||
ceiling->sector->specialdata = T_MoveCeiling;
|
||||
if (ceiling->thinker.function)
|
||||
ceiling->thinker.function = T_MoveCeiling;
|
||||
P_AddThinker (&ceiling->thinker);
|
||||
P_AddActiveCeiling(ceiling);
|
||||
break;
|
||||
|
||||
case tc_door:
|
||||
door = Z_Malloc (sizeof(*door), PU_LEVEL, NULL);
|
||||
memcpy (door, save_p, sizeof(*door));
|
||||
save_p += sizeof(*door);
|
||||
door->sector = §ors[(int)door->sector];
|
||||
door->sector->specialdata = door;
|
||||
door->thinker.function = T_VerticalDoor;
|
||||
P_AddThinker (&door->thinker);
|
||||
break;
|
||||
|
||||
case tc_floor:
|
||||
floor = Z_Malloc (sizeof(*floor), PU_LEVEL, NULL);
|
||||
memcpy (floor, save_p, sizeof(*floor));
|
||||
save_p += sizeof(*floor);
|
||||
floor->sector = §ors[(int)floor->sector];
|
||||
floor->sector->specialdata = T_MoveFloor;
|
||||
floor->thinker.function = T_MoveFloor;
|
||||
P_AddThinker (&floor->thinker);
|
||||
break;
|
||||
|
||||
case tc_plat:
|
||||
plat = Z_Malloc (sizeof(*plat), PU_LEVEL, NULL);
|
||||
memcpy (plat, save_p, sizeof(*plat));
|
||||
save_p += sizeof(*plat);
|
||||
plat->sector = §ors[(int)plat->sector];
|
||||
plat->sector->specialdata = T_PlatRaise;
|
||||
if (plat->thinker.function)
|
||||
plat->thinker.function = T_PlatRaise;
|
||||
P_AddThinker (&plat->thinker);
|
||||
P_AddActivePlat(plat);
|
||||
break;
|
||||
|
||||
case tc_flash:
|
||||
flash = Z_Malloc (sizeof(*flash), PU_LEVEL, NULL);
|
||||
memcpy (flash, save_p, sizeof(*flash));
|
||||
save_p += sizeof(*flash);
|
||||
flash->sector = §ors[(int)flash->sector];
|
||||
flash->thinker.function = T_LightFlash;
|
||||
P_AddThinker (&flash->thinker);
|
||||
break;
|
||||
|
||||
case tc_strobe:
|
||||
strobe = Z_Malloc (sizeof(*strobe), PU_LEVEL, NULL);
|
||||
memcpy (strobe, save_p, sizeof(*strobe));
|
||||
save_p += sizeof(*strobe);
|
||||
strobe->sector = §ors[(int)strobe->sector];
|
||||
strobe->thinker.function = T_StrobeFlash;
|
||||
P_AddThinker (&strobe->thinker);
|
||||
break;
|
||||
|
||||
case tc_glow:
|
||||
glow = Z_Malloc (sizeof(*glow), PU_LEVEL, NULL);
|
||||
memcpy (glow, save_p, sizeof(*glow));
|
||||
save_p += sizeof(*glow);
|
||||
glow->sector = §ors[(int)glow->sector];
|
||||
glow->thinker.function = T_Glow;
|
||||
P_AddThinker (&glow->thinker);
|
||||
break;
|
||||
|
||||
default:
|
||||
I_Error ("P_UnarchiveSpecials:Unknown tclass %i "
|
||||
"in savegame",tclass);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
|
||||
THINKERS
|
||||
|
||||
All thinkers should be allocated by Z_Malloc so they can be operated on uniformly. The actual
|
||||
structures will vary in size, but the first element must be thinker_t.
|
||||
|
||||
===============================================================================
|
||||
*/
|
||||
|
||||
thinker_t thinkercap; // both the head and tail of the thinker list
|
||||
|
||||
/*
|
||||
===============
|
||||
=
|
||||
= P_InitThinkers
|
||||
=
|
||||
===============
|
||||
*/
|
||||
|
||||
void P_InitThinkers (void)
|
||||
{
|
||||
thinkercap.prev = thinkercap.next = &thinkercap;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===============
|
||||
=
|
||||
= P_AddThinker
|
||||
=
|
||||
= Adds a new thinker at the end of the list
|
||||
=
|
||||
===============
|
||||
*/
|
||||
|
||||
void P_AddThinker (thinker_t *thinker)
|
||||
{
|
||||
thinkercap.prev->next = thinker;
|
||||
thinker->next = &thinkercap;
|
||||
thinker->prev = thinkercap.prev;
|
||||
thinkercap.prev = thinker;
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
=
|
||||
= P_RemoveThinker
|
||||
=
|
||||
= Deallocation is lazy -- it will not actually be freed until its
|
||||
= thinking turn comes up
|
||||
=
|
||||
===============
|
||||
*/
|
||||
|
||||
void P_RemoveThinker (thinker_t *thinker)
|
||||
{
|
||||
thinker->function = (think_t)-1;
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
=
|
||||
= P_AllocateThinker
|
||||
=
|
||||
= Allocates memory and adds a new thinker at the end of the list
|
||||
=
|
||||
===============
|
||||
*/
|
||||
|
||||
void P_AllocateThinker (thinker_t *thinker)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===============
|
||||
=
|
||||
= P_RunThinkers
|
||||
=
|
||||
===============
|
||||
*/
|
||||
|
||||
void P_RunThinkers (void)
|
||||
{
|
||||
thinker_t *currentthinker;
|
||||
|
||||
currentthinker = thinkercap.next;
|
||||
while (currentthinker != &thinkercap)
|
||||
{
|
||||
if (currentthinker->function == (think_t)-1)
|
||||
{ // time to remove it
|
||||
currentthinker->next->prev = currentthinker->prev;
|
||||
currentthinker->prev->next = currentthinker->next;
|
||||
Z_Free (currentthinker);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (currentthinker->function)
|
||||
currentthinker->function (currentthinker);
|
||||
}
|
||||
currentthinker = currentthinker->next;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// PROC P_Ticker
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void P_Ticker(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
if(paused)
|
||||
{
|
||||
return;
|
||||
}
|
||||
for(i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if(playeringame[i])
|
||||
{
|
||||
P_PlayerThink(&players[i]);
|
||||
}
|
||||
}
|
||||
if(TimerGame)
|
||||
{
|
||||
if(!--TimerGame)
|
||||
{
|
||||
G_ExitLevel();
|
||||
}
|
||||
}
|
||||
P_RunThinkers();
|
||||
P_UpdateSpecials();
|
||||
P_AmbientSound();
|
||||
leveltime++;
|
||||
}
|
1007
Heretic Source/P_USER.C
Normal file
1007
Heretic Source/P_USER.C
Normal file
File diff suppressed because it is too large
Load diff
474
Heretic Source/R_BSP.C
Normal file
474
Heretic Source/R_BSP.C
Normal file
|
@ -0,0 +1,474 @@
|
|||
// R_bsp.c
|
||||
|
||||
#include "DoomDef.h"
|
||||
#include "R_local.h"
|
||||
|
||||
seg_t *curline;
|
||||
side_t *sidedef;
|
||||
line_t *linedef;
|
||||
sector_t *frontsector, *backsector;
|
||||
|
||||
drawseg_t drawsegs[MAXDRAWSEGS], *ds_p;
|
||||
|
||||
void R_StoreWallRange (int start, int stop);
|
||||
|
||||
/*
|
||||
====================
|
||||
=
|
||||
= R_ClearDrawSegs
|
||||
=
|
||||
====================
|
||||
*/
|
||||
|
||||
void R_ClearDrawSegs (void)
|
||||
{
|
||||
ds_p = drawsegs;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
=
|
||||
= ClipWallSegment
|
||||
=
|
||||
= Clips the given range of columns and includes it in the new clip list
|
||||
===============================================================================
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int first, last;
|
||||
} cliprange_t;
|
||||
|
||||
#define MAXSEGS 32
|
||||
|
||||
cliprange_t solidsegs[MAXSEGS], *newend; // newend is one past the last valid seg
|
||||
|
||||
|
||||
void R_ClipSolidWallSegment (int first, int last)
|
||||
{
|
||||
cliprange_t *next, *start;
|
||||
|
||||
// find the first range that touches the range (adjacent pixels are touching)
|
||||
start = solidsegs;
|
||||
while (start->last < first-1)
|
||||
start++;
|
||||
|
||||
if (first < start->first)
|
||||
{
|
||||
if (last < start->first-1)
|
||||
{ // post is entirely visible (above start), so insert a new clippost
|
||||
R_StoreWallRange (first, last);
|
||||
next = newend;
|
||||
newend++;
|
||||
while (next != start)
|
||||
{
|
||||
*next = *(next-1);
|
||||
next--;
|
||||
}
|
||||
next->first = first;
|
||||
next->last = last;
|
||||
return;
|
||||
}
|
||||
|
||||
// there is a fragment above *start
|
||||
R_StoreWallRange (first, start->first - 1);
|
||||
start->first = first; // adjust the clip size
|
||||
}
|
||||
|
||||
if (last <= start->last)
|
||||
return; // bottom contained in start
|
||||
|
||||
next = start;
|
||||
while (last >= (next+1)->first-1)
|
||||
{
|
||||
// there is a fragment between two posts
|
||||
R_StoreWallRange (next->last + 1, (next+1)->first - 1);
|
||||
next++;
|
||||
if (last <= next->last)
|
||||
{ // bottom is contained in next
|
||||
start->last = next->last; // adjust the clip size
|
||||
goto crunch;
|
||||
}
|
||||
}
|
||||
|
||||
// there is a fragment after *next
|
||||
R_StoreWallRange (next->last + 1, last);
|
||||
start->last = last; // adjust the clip size
|
||||
|
||||
|
||||
// remove start+1 to next from the clip list,
|
||||
// because start now covers their area
|
||||
crunch:
|
||||
if (next == start)
|
||||
return; // post just extended past the bottom of one post
|
||||
|
||||
while (next++ != newend) // remove a post
|
||||
*++start = *next;
|
||||
newend = start+1;
|
||||
}
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
=
|
||||
= R_ClipPassWallSegment
|
||||
=
|
||||
= Clips the given range of columns, but does not includes it in the clip list
|
||||
===============================================================================
|
||||
*/
|
||||
|
||||
void R_ClipPassWallSegment (int first, int last)
|
||||
{
|
||||
cliprange_t *start;
|
||||
|
||||
// find the first range that touches the range (adjacent pixels are touching)
|
||||
start = solidsegs;
|
||||
while (start->last < first-1)
|
||||
start++;
|
||||
|
||||
if (first < start->first)
|
||||
{
|
||||
if (last < start->first-1)
|
||||
{ // post is entirely visible (above start)
|
||||
R_StoreWallRange (first, last);
|
||||
return;
|
||||
}
|
||||
|
||||
// there is a fragment above *start
|
||||
R_StoreWallRange (first, start->first - 1);
|
||||
}
|
||||
|
||||
if (last <= start->last)
|
||||
return; // bottom contained in start
|
||||
|
||||
while (last >= (start+1)->first-1)
|
||||
{
|
||||
// there is a fragment between two posts
|
||||
R_StoreWallRange (start->last + 1, (start+1)->first - 1);
|
||||
start++;
|
||||
if (last <= start->last)
|
||||
return;
|
||||
}
|
||||
|
||||
// there is a fragment after *next
|
||||
R_StoreWallRange (start->last + 1, last);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
====================
|
||||
=
|
||||
= R_ClearClipSegs
|
||||
=
|
||||
====================
|
||||
*/
|
||||
|
||||
void R_ClearClipSegs (void)
|
||||
{
|
||||
solidsegs[0].first = -0x7fffffff;
|
||||
solidsegs[0].last = -1;
|
||||
solidsegs[1].first = viewwidth;
|
||||
solidsegs[1].last = 0x7fffffff;
|
||||
newend = solidsegs+2;
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================
|
||||
|
||||
/*
|
||||
======================
|
||||
=
|
||||
= R_AddLine
|
||||
=
|
||||
= Clips the given segment and adds any visible pieces to the line list
|
||||
=
|
||||
======================
|
||||
*/
|
||||
|
||||
void R_AddLine (seg_t *line)
|
||||
{
|
||||
int x1, x2;
|
||||
angle_t angle1, angle2, span, tspan;
|
||||
|
||||
#ifdef __NeXT__
|
||||
RD_DrawLineCheck (line);
|
||||
#endif
|
||||
curline = line;
|
||||
|
||||
// OPTIMIZE: quickly reject orthogonal back sides
|
||||
|
||||
angle1 = R_PointToAngle (line->v1->x, line->v1->y);
|
||||
angle2 = R_PointToAngle (line->v2->x, line->v2->y);
|
||||
|
||||
//
|
||||
// clip to view edges
|
||||
// OPTIMIZE: make constant out of 2*clipangle (FIELDOFVIEW)
|
||||
span = angle1 - angle2;
|
||||
if (span >= ANG180)
|
||||
return; // back side
|
||||
|
||||
rw_angle1 = angle1; // global angle needed by segcalc
|
||||
angle1 -= viewangle;
|
||||
angle2 -= viewangle;
|
||||
|
||||
tspan = angle1 + clipangle;
|
||||
if (tspan > 2*clipangle)
|
||||
{
|
||||
tspan -= 2*clipangle;
|
||||
if (tspan >= span)
|
||||
return; // totally off the left edge
|
||||
angle1 = clipangle;
|
||||
}
|
||||
tspan = clipangle - angle2;
|
||||
if (tspan > 2*clipangle)
|
||||
{
|
||||
tspan -= 2*clipangle;
|
||||
if (tspan >= span)
|
||||
return; // totally off the left edge
|
||||
angle2 = -clipangle;
|
||||
}
|
||||
|
||||
//
|
||||
// the seg is in the view range, but not necessarily visible
|
||||
//
|
||||
angle1 = (angle1+ANG90)>>ANGLETOFINESHIFT;
|
||||
angle2 = (angle2+ANG90)>>ANGLETOFINESHIFT;
|
||||
x1 = viewangletox[angle1];
|
||||
x2 = viewangletox[angle2];
|
||||
if (x1 == x2)
|
||||
return; // does not cross a pixel
|
||||
|
||||
backsector = line->backsector;
|
||||
|
||||
if (!backsector)
|
||||
goto clipsolid; // single sided line
|
||||
|
||||
if (backsector->ceilingheight <= frontsector->floorheight
|
||||
|| backsector->floorheight >= frontsector->ceilingheight)
|
||||
goto clipsolid; // closed door
|
||||
|
||||
if (backsector->ceilingheight != frontsector->ceilingheight
|
||||
|| backsector->floorheight != frontsector->floorheight)
|
||||
goto clippass; // window
|
||||
|
||||
// reject empty lines used for triggers and special events
|
||||
if (backsector->ceilingpic == frontsector->ceilingpic
|
||||
&& backsector->floorpic == frontsector->floorpic
|
||||
&& backsector->lightlevel == frontsector->lightlevel
|
||||
&& curline->sidedef->midtexture == 0)
|
||||
return;
|
||||
|
||||
clippass:
|
||||
R_ClipPassWallSegment (x1, x2-1);
|
||||
return;
|
||||
|
||||
clipsolid:
|
||||
R_ClipSolidWallSegment (x1, x2-1);
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
=
|
||||
= R_CheckBBox
|
||||
=
|
||||
= Returns true if some part of the bbox might be visible
|
||||
=
|
||||
===============================================================================
|
||||
*/
|
||||
|
||||
int checkcoord[12][4] = {
|
||||
{3,0, 2,1},
|
||||
{3,0, 2,0},
|
||||
{3,1, 2,0},
|
||||
{0},
|
||||
{2,0, 2,1},
|
||||
{0,0,0,0},
|
||||
{3,1, 3,0},
|
||||
{0},
|
||||
{2,0, 3,1},
|
||||
{2,1, 3,1},
|
||||
{2,1, 3,0} };
|
||||
|
||||
|
||||
boolean R_CheckBBox (fixed_t *bspcoord)
|
||||
{
|
||||
int boxx, boxy, boxpos;
|
||||
fixed_t x1, y1, x2, y2;
|
||||
angle_t angle1, angle2, span, tspan;
|
||||
cliprange_t *start;
|
||||
int sx1, sx2;
|
||||
|
||||
#ifdef __NeXT__
|
||||
RD_DrawBBox (bspcoord);
|
||||
#endif
|
||||
|
||||
// find the corners of the box that define the edges from current viewpoint
|
||||
if (viewx <= bspcoord[BOXLEFT])
|
||||
boxx = 0;
|
||||
else if (viewx < bspcoord[BOXRIGHT])
|
||||
boxx = 1;
|
||||
else
|
||||
boxx = 2;
|
||||
|
||||
if (viewy >= bspcoord[BOXTOP])
|
||||
boxy = 0;
|
||||
else if (viewy > bspcoord[BOXBOTTOM])
|
||||
boxy = 1;
|
||||
else
|
||||
boxy = 2;
|
||||
|
||||
boxpos = (boxy<<2)+boxx;
|
||||
if (boxpos == 5)
|
||||
return true;
|
||||
|
||||
x1 = bspcoord[checkcoord[boxpos][0]];
|
||||
y1 = bspcoord[checkcoord[boxpos][1]];
|
||||
x2 = bspcoord[checkcoord[boxpos][2]];
|
||||
y2 = bspcoord[checkcoord[boxpos][3]];
|
||||
|
||||
|
||||
#ifdef __NeXT__
|
||||
// RD_DisplayLine (x1, y1, x2, y2, 0.1);
|
||||
#endif
|
||||
|
||||
//
|
||||
// check clip list for an open space
|
||||
//
|
||||
angle1 = R_PointToAngle (x1, y1) - viewangle;
|
||||
angle2 = R_PointToAngle (x2, y2) - viewangle;
|
||||
|
||||
span = angle1 - angle2;
|
||||
if (span >= ANG180)
|
||||
return true; // sitting on a line
|
||||
tspan = angle1 + clipangle;
|
||||
if (tspan > 2*clipangle)
|
||||
{
|
||||
tspan -= 2*clipangle;
|
||||
if (tspan >= span)
|
||||
return false; // totally off the left edge
|
||||
angle1 = clipangle;
|
||||
}
|
||||
tspan = clipangle - angle2;
|
||||
if (tspan > 2*clipangle)
|
||||
{
|
||||
tspan -= 2*clipangle;
|
||||
if (tspan >= span)
|
||||
return false; // totally off the left edge
|
||||
angle2 = -clipangle;
|
||||
}
|
||||
|
||||
|
||||
// find the first clippost that touches the source post (adjacent pixels are touching)
|
||||
angle1 = (angle1+ANG90)>>ANGLETOFINESHIFT;
|
||||
angle2 = (angle2+ANG90)>>ANGLETOFINESHIFT;
|
||||
sx1 = viewangletox[angle1];
|
||||
sx2 = viewangletox[angle2];
|
||||
if (sx1 == sx2)
|
||||
return false; // does not cross a pixel
|
||||
sx2--;
|
||||
|
||||
start = solidsegs;
|
||||
while (start->last < sx2)
|
||||
start++;
|
||||
if (sx1 >= start->first && sx2 <= start->last)
|
||||
return false; // the clippost contains the new span
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
=
|
||||
= R_Subsector
|
||||
=
|
||||
= Draw one or more segments
|
||||
================
|
||||
*/
|
||||
|
||||
void R_Subsector (int num)
|
||||
{
|
||||
int count;
|
||||
seg_t *line;
|
||||
subsector_t *sub;
|
||||
|
||||
#ifdef RANGECHECK
|
||||
if (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,
|
||||
frontsector->special);
|
||||
else
|
||||
floorplane = NULL;
|
||||
if (frontsector->ceilingheight > viewz
|
||||
|| frontsector->ceilingpic == skyflatnum)
|
||||
ceilingplane = R_FindPlane (frontsector->ceilingheight,
|
||||
frontsector->ceilingpic, frontsector->lightlevel, 0);
|
||||
else
|
||||
ceilingplane = NULL;
|
||||
|
||||
R_AddSprites (frontsector);
|
||||
|
||||
while (count--)
|
||||
{
|
||||
R_AddLine (line);
|
||||
line++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
=
|
||||
= RenderBSPNode
|
||||
=
|
||||
===============================================================================
|
||||
*/
|
||||
|
||||
void R_RenderBSPNode (int bspnum)
|
||||
{
|
||||
node_t *bsp;
|
||||
int side;
|
||||
|
||||
if (bspnum & NF_SUBSECTOR)
|
||||
{
|
||||
if (bspnum == -1)
|
||||
R_Subsector (0);
|
||||
else
|
||||
R_Subsector (bspnum&(~NF_SUBSECTOR));
|
||||
return;
|
||||
}
|
||||
|
||||
bsp = &nodes[bspnum];
|
||||
|
||||
#ifdef __NeXT__
|
||||
RD_DrawNodeLine (bsp);
|
||||
#endif
|
||||
|
||||
//
|
||||
// decide which side the view point is on
|
||||
//
|
||||
side = R_PointOnSide (viewx, viewy, bsp);
|
||||
|
||||
R_RenderBSPNode (bsp->children[side]); // recursively divide front space
|
||||
|
||||
if (R_CheckBBox (bsp->bbox[side^1])) // possibly divide back space
|
||||
R_RenderBSPNode (bsp->children[side^1]);
|
||||
}
|
||||
|
||||
|
701
Heretic Source/R_DATA.C
Normal file
701
Heretic Source/R_DATA.C
Normal file
|
@ -0,0 +1,701 @@
|
|||
|
||||
// R_data.c
|
||||
|
||||
#include "DoomDef.h"
|
||||
#include "R_local.h"
|
||||
#include "P_local.h"
|
||||
|
||||
extern void CheckAbortStartup(void);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int originx; // block origin (allways UL), which has allready
|
||||
int originy; // accounted for the patch's internal origin
|
||||
int patch;
|
||||
} texpatch_t;
|
||||
|
||||
// a maptexturedef_t describes a rectangular texture, which is composed of one
|
||||
// or more mappatch_t structures that arrange graphic patches
|
||||
typedef struct
|
||||
{
|
||||
char name[8]; // for switch changing, etc
|
||||
short width;
|
||||
short height;
|
||||
short patchcount;
|
||||
texpatch_t patches[1]; // [patchcount] drawn back to front
|
||||
// into the cached texture
|
||||
} texture_t;
|
||||
|
||||
|
||||
|
||||
int firstflat, lastflat, numflats;
|
||||
int firstpatch, lastpatch, numpatches;
|
||||
int firstspritelump, lastspritelump, numspritelumps;
|
||||
|
||||
int numtextures;
|
||||
texture_t **textures;
|
||||
int *texturewidthmask;
|
||||
fixed_t *textureheight; // needed for texture pegging
|
||||
int *texturecompositesize;
|
||||
short **texturecolumnlump;
|
||||
unsigned short **texturecolumnofs;
|
||||
byte **texturecomposite;
|
||||
|
||||
int *flattranslation; // for global animation
|
||||
int *texturetranslation; // for global animation
|
||||
|
||||
fixed_t *spritewidth; // needed for pre rendering
|
||||
fixed_t *spriteoffset;
|
||||
fixed_t *spritetopoffset;
|
||||
|
||||
lighttable_t *colormaps;
|
||||
|
||||
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
MAPTEXTURE_T CACHING
|
||||
|
||||
when a texture is first needed, it counts the number of composite columns
|
||||
required in the texture and allocates space for a column directory and any
|
||||
new columns. The directory will simply point inside other patches if there
|
||||
is only one patch in a given column, but any columns with multiple patches
|
||||
will have new column_ts generated.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
===================
|
||||
=
|
||||
= R_DrawColumnInCache
|
||||
=
|
||||
= Clip and draw a column from a patch into a cached post
|
||||
=
|
||||
===================
|
||||
*/
|
||||
|
||||
void R_DrawColumnInCache (column_t *patch, byte *cache, int originy, int cacheheight)
|
||||
{
|
||||
int count, position;
|
||||
byte *source, *dest;
|
||||
|
||||
dest = (byte *)cache + 3;
|
||||
|
||||
while (patch->topdelta != 0xff)
|
||||
{
|
||||
source = (byte *)patch + 3;
|
||||
count = patch->length;
|
||||
position = originy + patch->topdelta;
|
||||
if (position < 0)
|
||||
{
|
||||
count += position;
|
||||
position = 0;
|
||||
}
|
||||
if (position + count > cacheheight)
|
||||
count = cacheheight - position;
|
||||
if (count > 0)
|
||||
memcpy (cache + position, source, count);
|
||||
|
||||
patch = (column_t *)( (byte *)patch + patch->length
+ 4);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===================
|
||||
=
|
||||
= R_GenerateComposite
|
||||
=
|
||||
===================
|
||||
*/
|
||||
|
||||
void R_GenerateComposite (int texnum)
|
||||
{
|
||||
byte *block;
|
||||
texture_t *texture;
|
||||
texpatch_t *patch;
|
||||
patch_t *realpatch;
|
||||
int x, x1, x2;
|
||||
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];
|
||||
|
||||
//
|
||||
// composite the columns together
|
||||
//
|
||||
patch = texture->patches;
|
||||
|
||||
for (i=0 , patch = texture->patches; i<texture->patchcount ; i++, patch++)
|
||||
{
|
||||
realpatch = W_CacheLumpNum (patch->patch, PU_CACHE);
|
||||
x1 = patch->originx;
|
||||
x2 = x1 + SHORT(realpatch->width);
|
||||
|
||||
if (x1<0)
|
||||
x = 0;
|
||||
else
|
||||
x = x1;
|
||||
if (x2 > texture->width)
|
||||
x2 = texture->width;
|
||||
|
||||
for ( ; x<x2 ; x++)
|
||||
{
|
||||
if (collump[x] >= 0)
|
||||
continue; // column does not have multiple patches
|
||||
patchcol = (column_t *)((byte *)realpatch +
|
||||
LONG(realpatch->columnofs[x-x1]));
|
||||
R_DrawColumnInCache (patchcol, block + colofs[x], patch->originy,
|
||||
texture->height);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// now that the texture has been built, it is purgable
|
||||
Z_ChangeTag (block, PU_CACHE);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===================
|
||||
=
|
||||
= R_GenerateLookup
|
||||
=
|
||||
===================
|
||||
*/
|
||||
|
||||
void R_GenerateLookup (int texnum)
|
||||
{
|
||||
texture_t *texture;
|
||||
byte *patchcount; // [texture->width]
|
||||
texpatch_t *patch;
|
||||
patch_t *realpatch;
|
||||
int x, x1, x2;
|
||||
int i;
|
||||
short *collump;
|
||||
unsigned short *colofs;
|
||||
|
||||
texture = textures[texnum];
|
||||
|
||||
texturecomposite[texnum] = 0; // composited not created yet
|
||||
texturecompositesize[texnum] = 0;
|
||||
collump = texturecolumnlump[texnum];
|
||||
colofs = texturecolumnofs[texnum];
|
||||
|
||||
//
|
||||
// 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 *)alloca (texture->width);
|
||||
memset (patchcount, 0, texture->width);
|
||||
patch = texture->patches;
|
||||
|
||||
for (i=0 , patch = texture->patches; i<texture->patchcount ; i++, patch++)
|
||||
{
|
||||
realpatch = W_CacheLumpNum (patch->patch, PU_CACHE);
|
||||
x1 = patch->originx;
|
||||
x2 = x1 + SHORT(realpatch->width);
|
||||
if (x1 < 0)
|
||||
x = 0;
|
||||
else
|
||||
x = x1;
|
||||
if (x2 > texture->width)
|
||||
x2 = texture->width;
|
||||
for ( ; x<x2 ; x++)
|
||||
{
|
||||
patchcount[x]++;
|
||||
collump[x] = patch->patch;
|
||||
colofs[x] = LONG(realpatch->columnofs[x-x1])+3;
|
||||
}
|
||||
}
|
||||
|
||||
for (x=0 ; x<texture->width ; x++)
|
||||
{
|
||||
if (!patchcount[x])
|
||||
{
|
||||
printf ("R_GenerateLookup: column without a patch (%s)\n", texture->name);
|
||||
return;
|
||||
}
|
||||
// I_Error ("R_GenerateLookup: column without a patch");
|
||||
if (patchcount[x] > 1)
|
||||
{
|
||||
collump[x] = -1; // use the cached block
|
||||
colofs[x] = texturecompositesize[texnum];
|
||||
if (texturecompositesize[texnum] > 0x10000-texture->height)
|
||||
I_Error ("R_GenerateLookup: texture %i is >64k",texnum);
|
||||
texturecompositesize[texnum] += texture->height;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
=
|
||||
= R_GetColumn
|
||||
=
|
||||
================
|
||||
*/
|
||||
|
||||
byte *R_GetColumn (int tex, int col)
|
||||
{
|
||||
int lump, ofs;
|
||||
|
||||
col &= texturewidthmask[tex];
|
||||
lump = texturecolumnlump[tex][col];
|
||||
ofs = texturecolumnofs[tex][col];
|
||||
if (lump > 0)
|
||||
return (byte *)W_CacheLumpNum(lump,PU_CACHE)+ofs;
|
||||
if (!texturecomposite[tex])
|
||||
R_GenerateComposite (tex);
|
||||
return texturecomposite[tex] + ofs;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
==================
|
||||
=
|
||||
= R_InitTextures
|
||||
=
|
||||
= Initializes the texture list with the textures from the world map
|
||||
=
|
||||
==================
|
||||
*/
|
||||
|
||||
void R_InitTextures (void)
|
||||
{
|
||||
maptexture_t *mtexture;
|
||||
texture_t *texture;
|
||||
mappatch_t *mpatch;
|
||||
texpatch_t *patch;
|
||||
int i,j;
|
||||
int *maptex, *maptex2, *maptex1;
|
||||
char name[9], *names, *name_p;
|
||||
int *patchlookup;
|
||||
int totalwidth;
|
||||
int nummappatches;
|
||||
int offset, maxoff, maxoff2;
|
||||
int numtextures1, numtextures2;
|
||||
int *directory;
|
||||
|
||||
//
|
||||
// load the patch names from pnames.lmp
|
||||
//
|
||||
name[8] = 0;
|
||||
names = W_CacheLumpName ("PNAMES", PU_STATIC);
|
||||
nummappatches = LONG ( *((int *)names) );
|
||||
name_p = names+4;
|
||||
patchlookup = alloca (nummappatches*sizeof(*patchlookup));
|
||||
for (i=0 ; i<nummappatches ; i++)
|
||||
{
|
||||
strncpy (name,name_p+i*8, 8);
|
||||
patchlookup[i] = W_CheckNumForName (name);
|
||||
}
|
||||
Z_Free (names);
|
||||
|
||||
//
|
||||
// load the map texture definitions from textures.lmp
|
||||
//
|
||||
maptex = maptex1 = W_CacheLumpName ("TEXTURE1", PU_STATIC);
|
||||
numtextures1 = LONG(*maptex);
|
||||
maxoff = W_LumpLength (W_GetNumForName ("TEXTURE1"));
|
||||
directory = maptex+1;
|
||||
|
||||
if (W_CheckNumForName ("TEXTURE2") != -1)
|
||||
{
|
||||
maptex2 = W_CacheLumpName ("TEXTURE2", PU_STATIC);
|
||||
numtextures2 = LONG(*maptex2);
|
||||
maxoff2 = W_LumpLength (W_GetNumForName ("TEXTURE2"));
|
||||
}
|
||||
else
|
||||
{
|
||||
maptex2 = NULL;
|
||||
numtextures2 = 0;
|
||||
maxoff2 = 0;
|
||||
}
|
||||
numtextures = numtextures1 + numtextures2;
|
||||
|
||||
//
|
||||
// Init the startup thermometer at this point...
|
||||
//
|
||||
{
|
||||
int spramount;
|
||||
spramount = W_GetNumForName("S_END") - W_GetNumForName("S_START") + 1;
|
||||
InitThermo(spramount + numtextures + 6);
|
||||
}
|
||||
|
||||
textures = Z_Malloc (numtextures*4, PU_STATIC, 0);
|
||||
texturecolumnlump = Z_Malloc (numtextures*4, PU_STATIC, 0);
|
||||
texturecolumnofs = Z_Malloc (numtextures*4, PU_STATIC, 0);
|
||||
texturecomposite = Z_Malloc (numtextures*4, PU_STATIC, 0);
|
||||
texturecompositesize = Z_Malloc (numtextures*4, PU_STATIC, 0);
|
||||
texturewidthmask = Z_Malloc (numtextures*4, PU_STATIC, 0);
|
||||
textureheight = Z_Malloc (numtextures*4, PU_STATIC, 0);
|
||||
|
||||
totalwidth = 0;
|
||||
|
||||
for (i=0 ; i<numtextures ; i++, directory++)
|
||||
{
|
||||
#ifdef __NEXT__
|
||||
if(!(i&63))
|
||||
printf (".");
|
||||
#else
|
||||
IncThermo();
|
||||
#endif
|
||||
if (i == numtextures1)
|
||||
{ // start looking in second texture file
|
||||
maptex = maptex2;
|
||||
maxoff = maxoff2;
|
||||
directory = maptex+1;
|
||||
}
|
||||
|
||||
offset = LONG(*directory);
|
||||
if (offset > maxoff)
|
||||
I_Error ("R_InitTextures: bad texture directory");
|
||||
mtexture = (maptexture_t *) ( (byte *)maptex + offset);
|
||||
texture = textures[i] = Z_Malloc (sizeof(texture_t)
|
||||
+ sizeof(texpatch_t)*(SHORT(mtexture->patchcount)-1), PU_STATIC,
|
||||
0);
|
||||
texture->width = SHORT(mtexture->width);
|
||||
texture->height = SHORT(mtexture->height);
|
||||
texture->patchcount = SHORT(mtexture->patchcount);
|
||||
memcpy (texture->name, mtexture->name, sizeof(texture->name));
|
||||
mpatch = &mtexture->patches[0];
|
||||
patch = &texture->patches[0];
|
||||
for (j=0 ; j<texture->patchcount ; j++, mpatch++, patch++)
|
||||
{
|
||||
patch->originx = SHORT(mpatch->originx);
|
||||
patch->originy = SHORT(mpatch->originy);
|
||||
patch->patch = patchlookup[SHORT(mpatch->patch)];
|
||||
if (patch->patch == -1)
|
||||
I_Error (
|
||||
"R_InitTextures: Missing patch in texture %s",texture->name);
|
||||
}
|
||||
texturecolumnlump[i] = Z_Malloc (texture->width*2, PU_STATIC,0);
|
||||
texturecolumnofs[i] = Z_Malloc (texture->width*2, PU_STATIC,0);
|
||||
j = 1;
|
||||
while (j*2 <= texture->width)
|
||||
j<<=1;
|
||||
texturewidthmask[i] = j-1;
|
||||
textureheight[i] = texture->height<<FRACBITS;
|
||||
|
||||
totalwidth += texture->width;
|
||||
}
|
||||
|
||||
Z_Free (maptex1);
|
||||
if (maptex2)
|
||||
Z_Free (maptex2);
|
||||
|
||||
//
|
||||
// precalculate whatever possible
|
||||
//
|
||||
for(i = 0; i < numtextures; i++)
|
||||
{
|
||||
R_GenerateLookup(i);
|
||||
CheckAbortStartup();
|
||||
}
|
||||
|
||||
//
|
||||
// translation table for global animation
|
||||
//
|
||||
texturetranslation = Z_Malloc ((numtextures+1)*4, PU_STATIC, 0);
|
||||
for (i=0 ; i<numtextures ; i++)
|
||||
texturetranslation[i] = i;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
=
|
||||
= R_InitFlats
|
||||
=
|
||||
=================
|
||||
*/
|
||||
|
||||
void R_InitFlats (void)
|
||||
{
|
||||
int i;
|
||||
|
||||
firstflat = W_GetNumForName ("F_START") + 1;
|
||||
lastflat = W_GetNumForName ("F_END") - 1;
|
||||
numflats = lastflat - firstflat + 1;
|
||||
|
||||
// translation table for global animation
|
||||
flattranslation = Z_Malloc ((numflats+1)*4, PU_STATIC, 0);
|
||||
for (i=0 ; i<numflats ; i++)
|
||||
flattranslation[i] = i;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
=
|
||||
= R_InitSpriteLumps
|
||||
=
|
||||
= Finds the width and hoffset of all sprites in the wad, so the sprite doesn't
|
||||
= need to be cached just for the header during rendering
|
||||
=================
|
||||
*/
|
||||
|
||||
void R_InitSpriteLumps (void)
|
||||
{
|
||||
int i;
|
||||
patch_t *patch;
|
||||
|
||||
firstspritelump = W_GetNumForName ("S_START") + 1;
|
||||
lastspritelump = W_GetNumForName ("S_END") - 1;
|
||||
numspritelumps = lastspritelump - firstspritelump + 1;
|
||||
spritewidth = Z_Malloc (numspritelumps*4, PU_STATIC, 0);
|
||||
spriteoffset = Z_Malloc (numspritelumps*4, PU_STATIC, 0);
|
||||
spritetopoffset = Z_Malloc (numspritelumps*4, PU_STATIC, 0);
|
||||
|
||||
for (i=0 ; i< numspritelumps ; i++)
|
||||
{
|
||||
#ifdef __NEXT__
|
||||
if (!(i&63))
|
||||
printf (".");
|
||||
#else
|
||||
IncThermo();
|
||||
#endif
|
||||
patch = W_CacheLumpNum (firstspritelump+i, PU_CACHE);
|
||||
spritewidth[i] = SHORT(patch->width)<<FRACBITS;
|
||||
spriteoffset[i] = SHORT(patch->leftoffset)<<FRACBITS;
|
||||
spritetopoffset[i] = SHORT(patch->topoffset)<<FRACBITS;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
=
|
||||
= R_InitColormaps
|
||||
=
|
||||
=================
|
||||
*/
|
||||
|
||||
void R_InitColormaps (void)
|
||||
{
|
||||
int lump, length;
|
||||
//
|
||||
// load in the light tables
|
||||
// 256 byte align tables
|
||||
//
|
||||
lump = W_GetNumForName("COLORMAP");
|
||||
length = W_LumpLength (lump) + 255;
|
||||
colormaps = Z_Malloc (length, PU_STATIC, 0);
|
||||
colormaps = (byte *)( ((int)colormaps + 255)&~0xff);
|
||||
W_ReadLump (lump,colormaps);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
=
|
||||
= R_InitData
|
||||
=
|
||||
= Locates all the lumps that will be used by all views
|
||||
= Must be called after W_Init
|
||||
=================
|
||||
*/
|
||||
|
||||
void R_InitData (void)
|
||||
{
|
||||
tprintf("\nR_InitTextures ",0);
|
||||
R_InitTextures ();
|
||||
//printf (".");
|
||||
tprintf("R_InitFlats\n",0);
|
||||
R_InitFlats ();
|
||||
IncThermo();
|
||||
//printf (".");
|
||||
tprintf("R_InitSpriteLumps ",0);
|
||||
R_InitSpriteLumps ();
|
||||
IncThermo();
|
||||
//printf (".");
|
||||
R_InitColormaps ();
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================
|
||||
|
||||
/*
|
||||
================
|
||||
=
|
||||
= R_FlatNumForName
|
||||
=
|
||||
================
|
||||
*/
|
||||
|
||||
int R_FlatNumForName (char *name)
|
||||
{
|
||||
int i;
|
||||
char namet[9];
|
||||
|
||||
i = W_CheckNumForName (name);
|
||||
if (i == -1)
|
||||
{
|
||||
namet[8] = 0;
|
||||
memcpy (namet, name,8);
|
||||
I_Error ("R_FlatNumForName: %s not found",namet);
|
||||
}
|
||||
return i - firstflat;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
=
|
||||
= R_CheckTextureNumForName
|
||||
=
|
||||
================
|
||||
*/
|
||||
|
||||
int R_CheckTextureNumForName (char *name)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (name[0] == '-') // no texture marker
|
||||
return 0;
|
||||
|
||||
for (i=0 ; i<numtextures ; i++)
|
||||
if (!strncasecmp (textures[i]->name, name, 8) )
|
||||
return i;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
=
|
||||
= R_TextureNumForName
|
||||
=
|
||||
================
|
||||
*/
|
||||
|
||||
int R_TextureNumForName (char *name)
|
||||
{
|
||||
int i;
|
||||
//char namet[9];
|
||||
|
||||
i = R_CheckTextureNumForName (name);
|
||||
if (i==-1)
|
||||
I_Error ("R_TextureNumForName: %s not found",name);
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=================
|
||||
=
|
||||
= R_PrecacheLevel
|
||||
=
|
||||
= Preloads all relevent graphics for the level
|
||||
=================
|
||||
*/
|
||||
|
||||
int flatmemory, texturememory, spritememory;
|
||||
|
||||
void R_PrecacheLevel (void)
|
||||
{
|
||||
char *flatpresent;
|
||||
char *texturepresent;
|
||||
char *spritepresent;
|
||||
int i,j,k, lump;
|
||||
texture_t *texture;
|
||||
thinker_t *th;
|
||||
spriteframe_t *sf;
|
||||
|
||||
if (demoplayback)
|
||||
return;
|
||||
|
||||
//
|
||||
// precache flats
|
||||
//
|
||||
flatpresent = alloca(numflats);
|
||||
memset (flatpresent,0,numflats);
|
||||
for (i=0 ; i<numsectors ; i++)
|
||||
{
|
||||
flatpresent[sectors[i].floorpic] = 1;
|
||||
flatpresent[sectors[i].ceilingpic] = 1;
|
||||
}
|
||||
|
||||
flatmemory = 0;
|
||||
for (i=0 ; i<numflats ; i++)
|
||||
if (flatpresent[i])
|
||||
{
|
||||
lump = firstflat + i;
|
||||
flatmemory += lumpinfo[lump].size;
|
||||
W_CacheLumpNum(lump, PU_CACHE);
|
||||
}
|
||||
|
||||
//
|
||||
// precache textures
|
||||
//
|
||||
texturepresent = alloca(numtextures);
|
||||
memset (texturepresent,0, numtextures);
|
||||
|
||||
for (i=0 ; i<numsides ; i++)
|
||||
{
|
||||
texturepresent[sides[i].toptexture] = 1;
|
||||
texturepresent[sides[i].midtexture] = 1;
|
||||
texturepresent[sides[i].bottomtexture] = 1;
|
||||
}
|
||||
|
||||
texturepresent[skytexture] = 1;
|
||||
|
||||
texturememory = 0;
|
||||
for (i=0 ; i<numtextures ; i++)
|
||||
{
|
||||
if (!texturepresent[i])
|
||||
continue;
|
||||
texture = textures[i];
|
||||
for (j=0 ; j<texture->patchcount ; j++)
|
||||
{
|
||||
lump = texture->patches[j].patch;
|
||||
texturememory += lumpinfo[lump].size;
|
||||
W_CacheLumpNum(lump , PU_CACHE);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// precache sprites
|
||||
//
|
||||
spritepresent = alloca(numsprites);
|
||||
memset (spritepresent,0, numsprites);
|
||||
|
||||
for (th = thinkercap.next ; th != &thinkercap ; th=th->next)
|
||||
{
|
||||
if (th->function == P_MobjThinker)
|
||||
spritepresent[((mobj_t *)th)->sprite] = 1;
|
||||
}
|
||||
|
||||
spritememory = 0;
|
||||
for (i=0 ; i<numsprites ; i++)
|
||||
{
|
||||
if (!spritepresent[i])
|
||||
continue;
|
||||
for (j=0 ; j<sprites[i].numframes ; j++)
|
||||
{
|
||||
sf = &sprites[i].spriteframes[j];
|
||||
for (k=0 ; k<8 ; k++)
|
||||
{
|
||||
lump = firstspritelump + sf->lump[k];
|
||||
spritememory += lumpinfo[lump].size;
|
||||
W_CacheLumpNum(lump , PU_CACHE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
498
Heretic Source/R_DRAW.C
Normal file
498
Heretic Source/R_DRAW.C
Normal file
|
@ -0,0 +1,498 @@
|
|||
// R_draw.c
|
||||
|
||||
#include "DoomDef.h"
|
||||
#include "R_local.h"
|
||||
|
||||
/*
|
||||
|
||||
All drawing to the view buffer is accomplished in this file. The other refresh
|
||||
files only know about ccordinates, not the architecture of the frame buffer.
|
||||
|
||||
*/
|
||||
|
||||
byte *viewimage;
|
||||
int viewwidth, scaledviewwidth, viewheight, viewwindowx, viewwindowy;
|
||||
byte *ylookup[MAXHEIGHT];
|
||||
int columnofs[MAXWIDTH];
|
||||
byte translations[3][256]; // color tables for different players
|
||||
byte *tinttable; // used for translucent sprites
|
||||
|
||||
/*
|
||||
==================
|
||||
=
|
||||
= R_DrawColumn
|
||||
=
|
||||
= Source is the top of the column to scale
|
||||
=
|
||||
==================
|
||||
*/
|
||||
|
||||
lighttable_t *dc_colormap;
|
||||
int dc_x;
|
||||
int dc_yl;
|
||||
int dc_yh;
|
||||
fixed_t dc_iscale;
|
||||
fixed_t dc_texturemid;
|
||||
byte *dc_source; // first pixel in a column (possibly virtual)
|
||||
|
||||
int dccount; // just for profiling
|
||||
|
||||
#ifndef __WATCOMC__
|
||||
#ifndef __i386
|
||||
#ifndef __m68k
|
||||
void R_DrawColumn (void)
|
||||
{
|
||||
int count;
|
||||
byte *dest;
|
||||
fixed_t frac, fracstep;
|
||||
|
||||
count = dc_yh - dc_yl;
|
||||
if (count < 0)
|
||||
return;
|
||||
|
||||
#ifdef RANGECHECK
|
||||
if ((unsigned)dc_x >= SCREENWIDTH || dc_yl < 0 || dc_yh >= SCREENHEIGHT)
|
||||
I_Error ("R_DrawColumn: %i to %i at %i", dc_yl, dc_yh, dc_x);
|
||||
#endif
|
||||
|
||||
dest = ylookup[dc_yl] + columnofs[dc_x];
|
||||
|
||||
fracstep = dc_iscale;
|
||||
frac = dc_texturemid + (dc_yl-centery)*fracstep;
|
||||
|
||||
do
|
||||
{
|
||||
*dest = dc_colormap[dc_source[(frac>>FRACBITS)&127]];
|
||||
dest += SCREENWIDTH;
|
||||
frac += fracstep;
|
||||
} while (count--);
|
||||
}
|
||||
#endif // __m68k
|
||||
#endif // __i386
|
||||
#endif
|
||||
|
||||
void R_DrawColumnLow (void)
|
||||
{
|
||||
int count;
|
||||
byte *dest;
|
||||
fixed_t frac, fracstep;
|
||||
|
||||
count = dc_yh - dc_yl;
|
||||
if (count < 0)
|
||||
return;
|
||||
|
||||
#ifdef RANGECHECK
|
||||
if ((unsigned)dc_x >= SCREENWIDTH || dc_yl < 0 || dc_yh >= SCREENHEIGHT)
|
||||
I_Error ("R_DrawColumn: %i to %i at %i", dc_yl, dc_yh, dc_x);
|
||||
// dccount++;
|
||||
#endif
|
||||
|
||||
dest = ylookup[dc_yl] + columnofs[dc_x];
|
||||
|
||||
fracstep = dc_iscale;
|
||||
frac = dc_texturemid + (dc_yl-centery)*fracstep;
|
||||
|
||||
do
|
||||
{
|
||||
*dest = dc_colormap[dc_source[(frac>>FRACBITS)&127]];
|
||||
dest += SCREENWIDTH;
|
||||
frac += fracstep;
|
||||
} while (count--);
|
||||
}
|
||||
|
||||
|
||||
#define FUZZTABLE 50
|
||||
|
||||
#define FUZZOFF (SCREENWIDTH)
|
||||
int fuzzoffset[FUZZTABLE] = {
|
||||
FUZZOFF,-FUZZOFF,FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,-FUZZOFF,-FUZZOFF,-FUZZOFF,FUZZOFF,-FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,-FUZZOFF,-FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,FUZZOFF
|
||||
};
|
||||
int fuzzpos = 0;
|
||||
|
||||
void R_DrawFuzzColumn (void)
|
||||
{
|
||||
int count;
|
||||
byte *dest;
|
||||
fixed_t frac, fracstep;
|
||||
|
||||
if (!dc_yl)
|
||||
dc_yl = 1;
|
||||
if (dc_yh == viewheight-1)
|
||||
dc_yh = viewheight - 2;
|
||||
|
||||
count = dc_yh - dc_yl;
|
||||
if (count < 0)
|
||||
return;
|
||||
|
||||
#ifdef RANGECHECK
|
||||
if ((unsigned)dc_x >= SCREENWIDTH || dc_yl < 0 || dc_yh >= SCREENHEIGHT)
|
||||
I_Error ("R_DrawFuzzColumn: %i to %i at %i", dc_yl, dc_yh, dc_x);
|
||||
#endif
|
||||
|
||||
dest = ylookup[dc_yl] + columnofs[dc_x];
|
||||
|
||||
fracstep = dc_iscale;
|
||||
frac = dc_texturemid + (dc_yl-centery)*fracstep;
|
||||
|
||||
// OLD FUZZY INVISO SPRITE STUFF
|
||||
/* do
|
||||
{
|
||||
*dest = colormaps[6*256+dest[fuzzoffset[fuzzpos]]];
|
||||
if (++fuzzpos == FUZZTABLE)
|
||||
fuzzpos = 0;
|
||||
dest += SCREENWIDTH;
|
||||
frac += fracstep;
|
||||
} while (count--);
|
||||
*/
|
||||
|
||||
do
|
||||
{
|
||||
*dest = tinttable[((*dest)<<8)+dc_colormap[dc_source[(frac>>FRACBITS)&127]]];
|
||||
|
||||
//*dest = dest[SCREENWIDTH*10+5];
|
||||
|
||||
// *dest = //tinttable[((*dest)<<8)+colormaps[dc_source[(frac>>FRACBITS)&127]]];
|
||||
|
||||
// *dest = dc_colormap[dc_source[(frac>>FRACBITS)&127]];
|
||||
dest += SCREENWIDTH;
|
||||
frac += fracstep;
|
||||
} while(count--);
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
=
|
||||
= R_DrawTranslatedColumn
|
||||
=
|
||||
========================
|
||||
*/
|
||||
|
||||
byte *dc_translation;
|
||||
byte *translationtables;
|
||||
|
||||
void R_DrawTranslatedColumn (void)
|
||||
{
|
||||
int count;
|
||||
byte *dest;
|
||||
fixed_t frac, fracstep;
|
||||
|
||||
count = dc_yh - dc_yl;
|
||||
if (count < 0)
|
||||
return;
|
||||
|
||||
#ifdef RANGECHECK
|
||||
if ((unsigned)dc_x >= SCREENWIDTH || dc_yl < 0 || dc_yh >= SCREENHEIGHT)
|
||||
I_Error ("R_DrawColumn: %i to %i at %i", dc_yl, dc_yh, dc_x);
|
||||
#endif
|
||||
|
||||
dest = ylookup[dc_yl] + columnofs[dc_x];
|
||||
|
||||
fracstep = dc_iscale;
|
||||
frac = dc_texturemid + (dc_yl-centery)*fracstep;
|
||||
|
||||
do
|
||||
{
|
||||
*dest = dc_colormap[dc_translation[dc_source[frac>>FRACBITS]]];
|
||||
dest += SCREENWIDTH;
|
||||
frac += fracstep;
|
||||
} while (count--);
|
||||
}
|
||||
|
||||
void R_DrawTranslatedFuzzColumn (void)
|
||||
{
|
||||
int count;
|
||||
byte *dest;
|
||||
fixed_t frac, fracstep;
|
||||
|
||||
count = dc_yh - dc_yl;
|
||||
if (count < 0)
|
||||
return;
|
||||
|
||||
#ifdef RANGECHECK
|
||||
if ((unsigned)dc_x >= SCREENWIDTH || dc_yl < 0 || dc_yh >= SCREENHEIGHT)
|
||||
I_Error ("R_DrawColumn: %i to %i at %i", dc_yl, dc_yh, dc_x);
|
||||
#endif
|
||||
|
||||
dest = ylookup[dc_yl] + columnofs[dc_x];
|
||||
|
||||
fracstep = dc_iscale;
|
||||
frac = dc_texturemid + (dc_yl-centery)*fracstep;
|
||||
|
||||
do
|
||||
{
|
||||
*dest = tinttable[((*dest)<<8)
|
||||
+dc_colormap[dc_translation[dc_source[frac>>FRACBITS]]]];
|
||||
dest += SCREENWIDTH;
|
||||
frac += fracstep;
|
||||
} while (count--);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// PROC R_InitTranslationTables
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
void R_InitTranslationTables (void)
|
||||
{
|
||||
int i;
|
||||
|
||||
// Load tint table
|
||||
tinttable = W_CacheLumpName("TINTTAB", PU_STATIC);
|
||||
|
||||
// Allocate translation tables
|
||||
translationtables = Z_Malloc(256*3+255, PU_STATIC, 0);
|
||||
translationtables = (byte *)(( (int)translationtables + 255 )& ~255);
|
||||
|
||||
// Fill out the translation tables
|
||||
for(i = 0; i < 256; i++)
|
||||
{
|
||||
if(i >= 225 && i <= 240)
|
||||
{
|
||||
translationtables[i] = 114+(i-225); // yellow
|
||||
translationtables[i+256] = 145+(i-225); // red
|
||||
translationtables[i+512] = 190+(i-225); // blue
|
||||
}
|
||||
else
|
||||
{
|
||||
translationtables[i] = translationtables[i+256]
|
||||
= translationtables[i+512] = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
=
|
||||
= R_DrawSpan
|
||||
=
|
||||
================
|
||||
*/
|
||||
|
||||
int ds_y;
|
||||
int ds_x1;
|
||||
int ds_x2;
|
||||
lighttable_t *ds_colormap;
|
||||
fixed_t ds_xfrac;
|
||||
fixed_t ds_yfrac;
|
||||
fixed_t ds_xstep;
|
||||
fixed_t ds_ystep;
|
||||
byte *ds_source; // start of a 64*64 tile image
|
||||
|
||||
int dscount; // just for profiling
|
||||
|
||||
#ifndef __WATCOMC__
|
||||
#ifndef __i386
|
||||
#ifndef __m68k
|
||||
void R_DrawSpan (void)
|
||||
{
|
||||
fixed_t xfrac, yfrac;
|
||||
byte *dest;
|
||||
int count, spot;
|
||||
|
||||
#ifdef RANGECHECK
|
||||
if (ds_x2 < ds_x1 || ds_x1<0 || ds_x2>=SCREENWIDTH
|
||||
|| (unsigned)ds_y>SCREENHEIGHT)
|
||||
I_Error ("R_DrawSpan: %i to %i at %i",ds_x1,ds_x2,ds_y);
|
||||
// dscount++;
|
||||
#endif
|
||||
|
||||
xfrac = ds_xfrac;
|
||||
yfrac = ds_yfrac;
|
||||
|
||||
dest = ylookup[ds_y] + columnofs[ds_x1];
|
||||
count = ds_x2 - ds_x1;
|
||||
do
|
||||
{
|
||||
spot = ((yfrac>>(16-6))&(63*64)) + ((xfrac>>16)&63);
|
||||
*dest++ = ds_colormap[ds_source[spot]];
|
||||
xfrac += ds_xstep;
|
||||
yfrac += ds_ystep;
|
||||
} while (count--);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
void R_DrawSpanLow (void)
|
||||
{
|
||||
fixed_t xfrac, yfrac;
|
||||
byte *dest;
|
||||
int count, spot;
|
||||
|
||||
#ifdef RANGECHECK
|
||||
if (ds_x2 < ds_x1 || ds_x1<0 || ds_x2>=SCREENWIDTH
|
||||
|| (unsigned)ds_y>SCREENHEIGHT)
|
||||
I_Error ("R_DrawSpan: %i to %i at %i",ds_x1,ds_x2,ds_y);
|
||||
// dscount++;
|
||||
#endif
|
||||
|
||||
xfrac = ds_xfrac;
|
||||
yfrac = ds_yfrac;
|
||||
|
||||
dest = ylookup[ds_y] + columnofs[ds_x1];
|
||||
count = ds_x2 - ds_x1;
|
||||
do
|
||||
{
|
||||
spot = ((yfrac>>(16-6))&(63*64)) + ((xfrac>>16)&63);
|
||||
*dest++ = ds_colormap[ds_source[spot]];
|
||||
xfrac += ds_xstep;
|
||||
yfrac += ds_ystep;
|
||||
} while (count--);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
=
|
||||
= R_InitBuffer
|
||||
=
|
||||
=================
|
||||
*/
|
||||
|
||||
void R_InitBuffer (int width, int height)
|
||||
{
|
||||
int i;
|
||||
|
||||
viewwindowx = (SCREENWIDTH-width) >> 1;
|
||||
for (i=0 ; i<width ; i++)
|
||||
columnofs[i] = viewwindowx + i;
|
||||
if (width == SCREENWIDTH)
|
||||
viewwindowy = 0;
|
||||
else
|
||||
viewwindowy = (SCREENHEIGHT-SBARHEIGHT-height) >> 1;
|
||||
for (i=0 ; i<height ; i++)
|
||||
ylookup[i] = screen + (i+viewwindowy)*SCREENWIDTH;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
==================
|
||||
=
|
||||
= R_DrawViewBorder
|
||||
=
|
||||
= Draws the border around the view for different size windows
|
||||
==================
|
||||
*/
|
||||
|
||||
boolean BorderNeedRefresh;
|
||||
|
||||
void R_DrawViewBorder (void)
|
||||
{
|
||||
byte *src, *dest;
|
||||
int x,y;
|
||||
|
||||
if (scaledviewwidth == SCREENWIDTH)
|
||||
return;
|
||||
|
||||
if(shareware)
|
||||
{
|
||||
src = W_CacheLumpName ("FLOOR04", PU_CACHE);
|
||||
}
|
||||
else
|
||||
{
|
||||
src = W_CacheLumpName ("FLAT513", PU_CACHE);
|
||||
}
|
||||
dest = screen;
|
||||
|
||||
for (y=0 ; y<SCREENHEIGHT-SBARHEIGHT ; y++)
|
||||
{
|
||||
for (x=0 ; x<SCREENWIDTH/64 ; x++)
|
||||
{
|
||||
memcpy (dest, src+((y&63)<<6), 64);
|
||||
dest += 64;
|
||||
}
|
||||
if (SCREENWIDTH&63)
|
||||
{
|
||||
memcpy (dest, src+((y&63)<<6), SCREENWIDTH&63);
|
||||
dest += (SCREENWIDTH&63);
|
||||
}
|
||||
}
|
||||
for(x=viewwindowx; x < viewwindowx+viewwidth; x += 16)
|
||||
{
|
||||
V_DrawPatch(x, viewwindowy-4, W_CacheLumpName("bordt", PU_CACHE));
|
||||
V_DrawPatch(x, viewwindowy+viewheight, W_CacheLumpName("bordb",
|
||||
PU_CACHE));
|
||||
}
|
||||
for(y=viewwindowy; y < viewwindowy+viewheight; y += 16)
|
||||
{
|
||||
V_DrawPatch(viewwindowx-4, y, W_CacheLumpName("bordl", PU_CACHE));
|
||||
V_DrawPatch(viewwindowx+viewwidth, y, W_CacheLumpName("bordr",
|
||||
PU_CACHE));
|
||||
}
|
||||
V_DrawPatch(viewwindowx-4, viewwindowy-4, W_CacheLumpName("bordtl",
|
||||
PU_CACHE));
|
||||
V_DrawPatch(viewwindowx+viewwidth, viewwindowy-4,
|
||||
W_CacheLumpName("bordtr", PU_CACHE));
|
||||
V_DrawPatch(viewwindowx+viewwidth, viewwindowy+viewheight,
|
||||
W_CacheLumpName("bordbr", PU_CACHE));
|
||||
V_DrawPatch(viewwindowx-4, viewwindowy+viewheight,
|
||||
W_CacheLumpName("bordbl", PU_CACHE));
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
=
|
||||
= R_DrawTopBorder
|
||||
=
|
||||
= Draws the top border around the view for different size windows
|
||||
==================
|
||||
*/
|
||||
|
||||
boolean BorderTopRefresh;
|
||||
|
||||
void R_DrawTopBorder (void)
|
||||
{
|
||||
byte *src, *dest;
|
||||
int x,y;
|
||||
|
||||
if (scaledviewwidth == SCREENWIDTH)
|
||||
return;
|
||||
|
||||
if(shareware)
|
||||
{
|
||||
src = W_CacheLumpName ("FLOOR04", PU_CACHE);
|
||||
}
|
||||
else
|
||||
{
|
||||
src = W_CacheLumpName ("FLAT513", PU_CACHE);
|
||||
}
|
||||
dest = screen;
|
||||
|
||||
for (y=0 ; y<30 ; y++)
|
||||
{
|
||||
for (x=0 ; x<SCREENWIDTH/64 ; x++)
|
||||
{
|
||||
memcpy (dest, src+((y&63)<<6), 64);
|
||||
dest += 64;
|
||||
}
|
||||
if (SCREENWIDTH&63)
|
||||
{
|
||||
memcpy (dest, src+((y&63)<<6), SCREENWIDTH&63);
|
||||
dest += (SCREENWIDTH&63);
|
||||
}
|
||||
}
|
||||
if(viewwindowy < 25)
|
||||
{
|
||||
for(x=viewwindowx; x < viewwindowx+viewwidth; x += 16)
|
||||
{
|
||||
V_DrawPatch(x, viewwindowy-4, W_CacheLumpName("bordt", PU_CACHE));
|
||||
}
|
||||
V_DrawPatch(viewwindowx-4, viewwindowy, W_CacheLumpName("bordl",
|
||||
PU_CACHE));
|
||||
V_DrawPatch(viewwindowx+viewwidth, viewwindowy,
|
||||
W_CacheLumpName("bordr", PU_CACHE));
|
||||
V_DrawPatch(viewwindowx-4, viewwindowy+16, W_CacheLumpName("bordl",
|
||||
PU_CACHE));
|
||||
V_DrawPatch(viewwindowx+viewwidth, viewwindowy+16,
|
||||
W_CacheLumpName("bordr", PU_CACHE));
|
||||
|
||||
V_DrawPatch(viewwindowx-4, viewwindowy-4, W_CacheLumpName("bordtl",
|
||||
PU_CACHE));
|
||||
V_DrawPatch(viewwindowx+viewwidth, viewwindowy-4,
|
||||
W_CacheLumpName("bordtr", PU_CACHE));
|
||||
}
|
||||
}
|
||||
|
||||
|
468
Heretic Source/R_LOCAL.H
Normal file
468
Heretic Source/R_LOCAL.H
Normal file
|
@ -0,0 +1,468 @@
|
|||
// R_local.h
|
||||
|
||||
#ifndef __R_LOCAL__
|
||||
#define __R_LOCAL__
|
||||
|
||||
#define ANGLETOSKYSHIFT 22 // sky map is 256*128*4 maps
|
||||
|
||||
#define BASEYCENTER 100
|
||||
|
||||
#define MAXWIDTH 1120
|
||||
#define MAXHEIGHT 832
|
||||
|
||||
#define PI 3.141592657
|
||||
|
||||
#define CENTERY (SCREENHEIGHT/2)
|
||||
|
||||
#define MINZ (FRACUNIT*4)
|
||||
|
||||
#define FIELDOFVIEW 2048 // fineangles in the SCREENWIDTH wide window
|
||||
|
||||
//
|
||||
// lighting constants
|
||||
//
|
||||
#define LIGHTLEVELS 16
|
||||
#define LIGHTSEGSHIFT 4
|
||||
#define MAXLIGHTSCALE 48
|
||||
#define LIGHTSCALESHIFT 12
|
||||
#define MAXLIGHTZ 128
|
||||
#define LIGHTZSHIFT 20
|
||||
#define NUMCOLORMAPS 32 // number of diminishing
|
||||
#define INVERSECOLORMAP 32
|
||||
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
INTERNAL MAP TYPES
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
//================ used by play and refresh
|
||||
|
||||
typedef struct
|
||||
{
|
||||
fixed_t x,y;
|
||||
} vertex_t;
|
||||
|
||||
struct line_s;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
fixed_t floorheight, ceilingheight;
|
||||
short floorpic, ceilingpic;
|
||||
short lightlevel;
|
||||
short special, tag;
|
||||
|
||||
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; // for any sounds played by the sector
|
||||
|
||||
int validcount; // if == validcount, already checked
|
||||
mobj_t *thinglist; // list of mobjs in sector
|
||||
void *specialdata; // thinker_t for reversable actions
|
||||
int linecount;
|
||||
struct line_s **lines; // [linecount] size
|
||||
} sector_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
fixed_t textureoffset; // add this to the calculated texture col
|
||||
fixed_t rowoffset; // add this to the calculated texture top
|
||||
short toptexture, bottomtexture, midtexture;
|
||||
sector_t *sector;
|
||||
} side_t;
|
||||
|
||||
typedef enum {ST_HORIZONTAL, ST_VERTICAL, ST_POSITIVE, ST_NEGATIVE} slopetype_t;
|
||||
|
||||
typedef struct line_s
|
||||
{
|
||||
vertex_t *v1, *v2;
|
||||
fixed_t dx,dy; // v2 - v1 for side checking
|
||||
short flags;
|
||||
short special, tag;
|
||||
short sidenum[2]; // sidenum[1] will be -1 if one sided
|
||||
fixed_t bbox[4];
|
||||
slopetype_t slopetype; // to aid move clipping
|
||||
sector_t *frontsector, *backsector;
|
||||
int validcount; // if == validcount, already checked
|
||||
void *specialdata; // thinker_t for reversable actions
|
||||
} line_t;
|
||||
|
||||
|
||||
typedef struct subsector_s
|
||||
{
|
||||
sector_t *sector;
|
||||
short numlines;
|
||||
short firstline;
|
||||
} subsector_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
vertex_t *v1, *v2;
|
||||
fixed_t offset;
|
||||
angle_t angle;
|
||||
side_t *sidedef;
|
||||
line_t *linedef;
|
||||
sector_t *frontsector;
|
||||
sector_t *backsector; // NULL for one sided lines
|
||||
} seg_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
fixed_t x,y,dx,dy; // partition line
|
||||
fixed_t bbox[2][4]; // bounding box for each child
|
||||
unsigned short children[2]; // if NF_SUBSECTOR its a subsector
|
||||
} node_t;
|
||||
|
||||
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
OTHER TYPES
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
typedef byte lighttable_t; // this could be wider for >8 bit display
|
||||
|
||||
#define MAXVISPLANES 128
|
||||
#define MAXOPENINGS SCREENWIDTH*64
|
||||
|
||||
typedef struct
|
||||
{
|
||||
fixed_t height;
|
||||
int picnum;
|
||||
int lightlevel;
|
||||
int special;
|
||||
int minx, maxx;
|
||||
byte pad1; // leave pads for [minx-1]/[maxx+1]
|
||||
byte top[SCREENWIDTH];
|
||||
byte pad2;
|
||||
byte pad3;
|
||||
byte bottom[SCREENWIDTH];
|
||||
byte pad4;
|
||||
} visplane_t;
|
||||
|
||||
typedef struct drawseg_s
|
||||
{
|
||||
seg_t *curline;
|
||||
int x1, x2;
|
||||
fixed_t scale1, scale2, scalestep;
|
||||
int silhouette; // 0=none, 1=bottom, 2=top, 3=both
|
||||
fixed_t bsilheight; // don't clip sprites above this
|
||||
fixed_t tsilheight; // don't clip sprites below this
|
||||
// pointers to lists for sprite clipping
|
||||
short *sprtopclip; // adjusted so [x1] is first value
|
||||
short *sprbottomclip; // adjusted so [x1] is first value
|
||||
short *maskedtexturecol; // adjusted so [x1] is first value
|
||||
} drawseg_t;
|
||||
|
||||
#define SIL_NONE 0
|
||||
#define SIL_BOTTOM 1
|
||||
#define SIL_TOP 2
|
||||
#define SIL_BOTH 3
|
||||
|
||||
#define MAXDRAWSEGS 256
|
||||
|
||||
// A vissprite_t is a thing that will be drawn during a refresh
|
||||
typedef struct vissprite_s
|
||||
{
|
||||
struct vissprite_s *prev, *next;
|
||||
int x1, x2;
|
||||
fixed_t gx, gy; // for line side calculation
|
||||
fixed_t gz, gzt; // global bottom / top for silhouette clipping
|
||||
fixed_t startfrac; // horizontal position of x1
|
||||
fixed_t scale;
|
||||
fixed_t xiscale; // negative if flipped
|
||||
fixed_t texturemid;
|
||||
int patch;
|
||||
lighttable_t *colormap;
|
||||
int mobjflags; // for color translation and shadow draw
|
||||
boolean psprite; // true if psprite
|
||||
fixed_t footclip; // foot clipping
|
||||
} vissprite_t;
|
||||
|
||||
|
||||
extern visplane_t *floorplane, *ceilingplane;
|
||||
|
||||
// Sprites are patches with a special naming convention so they can be
|
||||
// recognized by R_InitSprites. The sprite and frame specified by a
|
||||
// thing_t is range checked at run time.
|
||||
// a sprite is a patch_t that is assumed to represent a three dimensional
|
||||
// object and may have multiple rotations pre drawn. Horizontal flipping
|
||||
// is used to save space. Some sprites will only have one picture used
|
||||
// for all views.
|
||||
|
||||
typedef struct
|
||||
{
|
||||
boolean rotate; // if false use 0 for any position
|
||||
short lump[8]; // lump to use for view angles 0-7
|
||||
byte flip[8]; // flip (1 = flip) to use for view angles 0-7
|
||||
} spriteframe_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int numframes;
|
||||
spriteframe_t *spriteframes;
|
||||
} spritedef_t;
|
||||
|
||||
extern spritedef_t *sprites;
|
||||
extern int numsprites;
|
||||
|
||||
//=============================================================================
|
||||
|
||||
extern int numvertexes;
|
||||
extern vertex_t *vertexes;
|
||||
|
||||
extern int numsegs;
|
||||
extern seg_t *segs;
|
||||
|
||||
extern int numsectors;
|
||||
extern sector_t *sectors;
|
||||
|
||||
extern int numsubsectors;
|
||||
extern subsector_t *subsectors;
|
||||
|
||||
extern int numnodes;
|
||||
extern node_t *nodes;
|
||||
|
||||
extern int numlines;
|
||||
extern line_t *lines;
|
||||
|
||||
extern int numsides;
|
||||
extern side_t *sides;
|
||||
|
||||
|
||||
|
||||
extern fixed_t viewx, viewy, viewz;
|
||||
extern angle_t viewangle;
|
||||
extern player_t *viewplayer;
|
||||
|
||||
|
||||
extern angle_t clipangle;
|
||||
|
||||
extern int viewangletox[FINEANGLES/2];
|
||||
extern angle_t xtoviewangle[SCREENWIDTH+1];
|
||||
extern fixed_t finetangent[FINEANGLES/2];
|
||||
|
||||
extern fixed_t rw_distance;
|
||||
extern angle_t rw_normalangle;
|
||||
|
||||
//
|
||||
// R_main.c
|
||||
//
|
||||
extern int viewwidth, viewheight, viewwindowx, viewwindowy;
|
||||
extern int centerx, centery;
|
||||
extern int flyheight;
|
||||
extern fixed_t centerxfrac;
|
||||
extern fixed_t centeryfrac;
|
||||
extern fixed_t projection;
|
||||
|
||||
extern int validcount;
|
||||
|
||||
extern int sscount, linecount, loopcount;
|
||||
extern lighttable_t *scalelight[LIGHTLEVELS][MAXLIGHTSCALE];
|
||||
extern lighttable_t *scalelightfixed[MAXLIGHTSCALE];
|
||||
extern lighttable_t *zlight[LIGHTLEVELS][MAXLIGHTZ];
|
||||
|
||||
extern int extralight;
|
||||
extern lighttable_t *fixedcolormap;
|
||||
|
||||
extern fixed_t viewcos, viewsin;
|
||||
|
||||
extern int detailshift; // 0 = high, 1 = low
|
||||
|
||||
extern void (*colfunc) (void);
|
||||
extern void (*basecolfunc) (void);
|
||||
extern void (*fuzzcolfunc) (void);
|
||||
extern void (*spanfunc) (void);
|
||||
|
||||
int R_PointOnSide (fixed_t x, fixed_t y, node_t *node);
|
||||
int R_PointOnSegSide (fixed_t x, fixed_t y, seg_t *line);
|
||||
angle_t R_PointToAngle (fixed_t x, fixed_t y);
|
||||
angle_t R_PointToAngle2 (fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2);
|
||||
fixed_t R_PointToDist (fixed_t x, fixed_t y);
|
||||
fixed_t R_ScaleFromGlobalAngle (angle_t visangle);
|
||||
subsector_t *R_PointInSubsector (fixed_t x, fixed_t y);
|
||||
void R_AddPointToBox (int x, int y, fixed_t *box);
|
||||
|
||||
|
||||
//
|
||||
// R_bsp.c
|
||||
//
|
||||
extern seg_t *curline;
|
||||
extern side_t *sidedef;
|
||||
extern line_t *linedef;
|
||||
extern sector_t *frontsector, *backsector;
|
||||
|
||||
extern int rw_x;
|
||||
extern int rw_stopx;
|
||||
|
||||
extern boolean segtextured;
|
||||
extern boolean markfloor; // false if the back side is the same plane
|
||||
extern boolean markceiling;
|
||||
extern boolean skymap;
|
||||
|
||||
extern drawseg_t drawsegs[MAXDRAWSEGS], *ds_p;
|
||||
|
||||
extern lighttable_t **hscalelight, **vscalelight, **dscalelight;
|
||||
|
||||
typedef void (*drawfunc_t) (int start, int stop);
|
||||
void R_ClearClipSegs (void);
|
||||
|
||||
void R_ClearDrawSegs (void);
|
||||
void R_InitSkyMap (void);
|
||||
void R_RenderBSPNode (int bspnum);
|
||||
|
||||
//
|
||||
// R_segs.c
|
||||
//
|
||||
extern int rw_angle1; // angle to line origin
|
||||
|
||||
void R_RenderMaskedSegRange (drawseg_t *ds, int x1, int x2);
|
||||
|
||||
|
||||
//
|
||||
// R_plane.c
|
||||
//
|
||||
typedef void (*planefunction_t) (int top, int bottom);
|
||||
extern planefunction_t floorfunc, ceilingfunc;
|
||||
|
||||
extern int skyflatnum;
|
||||
|
||||
extern short openings[MAXOPENINGS], *lastopening;
|
||||
|
||||
extern short floorclip[SCREENWIDTH];
|
||||
extern short ceilingclip[SCREENWIDTH];
|
||||
|
||||
extern fixed_t yslope[SCREENHEIGHT];
|
||||
extern fixed_t distscale[SCREENWIDTH];
|
||||
|
||||
void R_InitPlanes (void);
|
||||
void R_ClearPlanes (void);
|
||||
void R_MapPlane (int y, int x1, int x2);
|
||||
void R_MakeSpans (int x, int t1, int b1, int t2, int b2);
|
||||
void R_DrawPlanes (void);
|
||||
|
||||
visplane_t *R_FindPlane (fixed_t height, int picnum, int lightlevel,
|
||||
int special);
|
||||
visplane_t *R_CheckPlane (visplane_t *pl, int start, int stop);
|
||||
|
||||
|
||||
//
|
||||
// R_debug.m
|
||||
//
|
||||
extern int drawbsp;
|
||||
|
||||
void RD_OpenMapWindow (void);
|
||||
void RD_ClearMapWindow (void);
|
||||
void RD_DisplayLine (int x1, int y1, int x2, int y2, float gray);
|
||||
void RD_DrawNodeLine (node_t *node);
|
||||
void RD_DrawLineCheck (seg_t *line);
|
||||
void RD_DrawLine (seg_t *line);
|
||||
void RD_DrawBBox (fixed_t *bbox);
|
||||
|
||||
|
||||
//
|
||||
// R_data.c
|
||||
//
|
||||
extern fixed_t *textureheight; // needed for texture pegging
|
||||
extern fixed_t *spritewidth; // needed for pre rendering (fracs)
|
||||
extern fixed_t *spriteoffset;
|
||||
extern fixed_t *spritetopoffset;
|
||||
extern lighttable_t *colormaps;
|
||||
extern int viewwidth, scaledviewwidth, viewheight;
|
||||
extern int firstflat;
|
||||
extern int numflats;
|
||||
|
||||
extern int *flattranslation; // for global animation
|
||||
extern int *texturetranslation; // for global animation
|
||||
|
||||
extern int firstspritelump, lastspritelump, numspritelumps;
|
||||
|
||||
byte *R_GetColumn (int tex, int col);
|
||||
void R_InitData (void);
|
||||
void R_PrecacheLevel (void);
|
||||
|
||||
|
||||
//
|
||||
// R_things.c
|
||||
//
|
||||
#define MAXVISSPRITES 128
|
||||
|
||||
extern vissprite_t vissprites[MAXVISSPRITES], *vissprite_p;
|
||||
extern vissprite_t vsprsortedhead;
|
||||
|
||||
// constant arrays used for psprite clipping and initializing clipping
|
||||
extern short negonearray[SCREENWIDTH];
|
||||
extern short screenheightarray[SCREENWIDTH];
|
||||
|
||||
// vars for R_DrawMaskedColumn
|
||||
extern short *mfloorclip;
|
||||
extern short *mceilingclip;
|
||||
extern fixed_t spryscale;
|
||||
extern fixed_t sprtopscreen;
|
||||
extern fixed_t sprbotscreen;
|
||||
|
||||
extern fixed_t pspritescale, pspriteiscale;
|
||||
|
||||
|
||||
void R_DrawMaskedColumn (column_t *column, signed int baseclip);
|
||||
|
||||
|
||||
void R_SortVisSprites (void);
|
||||
|
||||
void R_AddSprites (sector_t *sec);
|
||||
void R_AddPSprites (void);
|
||||
void R_DrawSprites (void);
|
||||
void R_InitSprites (char **namelist);
|
||||
void R_ClearSprites (void);
|
||||
void R_DrawMasked (void);
|
||||
void R_ClipVisSprite (vissprite_t *vis, int xl, int xh);
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// R_draw.c
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
extern lighttable_t *dc_colormap;
|
||||
extern int dc_x;
|
||||
extern int dc_yl;
|
||||
extern int dc_yh;
|
||||
extern fixed_t dc_iscale;
|
||||
extern fixed_t dc_texturemid;
|
||||
extern byte *dc_source; // first pixel in a column
|
||||
|
||||
void R_DrawColumn (void);
|
||||
void R_DrawColumnLow (void);
|
||||
void R_DrawFuzzColumn (void);
|
||||
void R_DrawFuzzColumnLow (void);
|
||||
void R_DrawTranslatedColumn (void);
|
||||
void R_DrawTranslatedFuzzColumn (void);
|
||||
void R_DrawTranslatedColumnLow (void);
|
||||
|
||||
extern int ds_y;
|
||||
extern int ds_x1;
|
||||
extern int ds_x2;
|
||||
extern lighttable_t *ds_colormap;
|
||||
extern fixed_t ds_xfrac;
|
||||
extern fixed_t ds_yfrac;
|
||||
extern fixed_t ds_xstep;
|
||||
extern fixed_t ds_ystep;
|
||||
extern byte *ds_source; // start of a 64*64 tile image
|
||||
|
||||
extern byte *translationtables;
|
||||
extern byte *dc_translation;
|
||||
|
||||
void R_DrawSpan (void);
|
||||
void R_DrawSpanLow (void);
|
||||
|
||||
void R_InitBuffer (int width, int height);
|
||||
void R_InitTranslationTables (void);
|
||||
|
||||
#endif // __R_LOCAL__
|
||||
|
847
Heretic Source/R_MAIN.C
Normal file
847
Heretic Source/R_MAIN.C
Normal file
|
@ -0,0 +1,847 @@
|
|||
// R_main.c
|
||||
|
||||
#include <math.h>
|
||||
#include "DoomDef.h"
|
||||
#include "R_local.h"
|
||||
/*
|
||||
|
||||
*/
|
||||
|
||||
int viewangleoffset;
|
||||
|
||||
#ifdef __WATCOMC__
|
||||
int newViewAngleOff;
|
||||
#endif
|
||||
|
||||
int validcount = 1; // increment every time a check is made
|
||||
|
||||
lighttable_t *fixedcolormap;
|
||||
extern lighttable_t **walllights;
|
||||
|
||||
int centerx, centery;
|
||||
fixed_t centerxfrac, centeryfrac;
|
||||
fixed_t projection;
|
||||
|
||||
int framecount; // just for profiling purposes
|
||||
|
||||
int sscount, linecount, loopcount;
|
||||
|
||||
fixed_t viewx, viewy, viewz;
|
||||
angle_t viewangle;
|
||||
fixed_t viewcos, viewsin;
|
||||
player_t *viewplayer;
|
||||
|
||||
int detailshift; // 0 = high, 1 = low
|
||||
|
||||
//
|
||||
// precalculated math tables
|
||||
//
|
||||
angle_t clipangle;
|
||||
|
||||
// The viewangletox[viewangle + FINEANGLES/4] lookup maps the visible view
|
||||
// angles to screen X coordinates, flattening the arc to a flat projection
|
||||
// plane. There will be many angles mapped to the same X.
|
||||
int viewangletox[FINEANGLES/2];
|
||||
|
||||
// The xtoviewangleangle[] table maps a screen pixel to the lowest viewangle
|
||||
// that maps back to x ranges from clipangle to -clipangle
|
||||
angle_t xtoviewangle[SCREENWIDTH+1];
|
||||
|
||||
// the finetangentgent[angle+FINEANGLES/4] table holds the fixed_t tangent
|
||||
// values for view angles, ranging from MININT to 0 to MAXINT.
|
||||
// fixed_t finetangent[FINEANGLES/2];
|
||||
|
||||
// fixed_t finesine[5*FINEANGLES/4];
|
||||
fixed_t *finecosine = &finesine[FINEANGLES/4];
|
||||
|
||||
|
||||
lighttable_t *scalelight[LIGHTLEVELS][MAXLIGHTSCALE];
|
||||
lighttable_t *scalelightfixed[MAXLIGHTSCALE];
|
||||
lighttable_t *zlight[LIGHTLEVELS][MAXLIGHTZ];
|
||||
|
||||
int extralight; // bumped light from gun blasts
|
||||
|
||||
void (*colfunc) (void);
|
||||
void (*basecolfunc) (void);
|
||||
void (*fuzzcolfunc) (void);
|
||||
void (*transcolfunc) (void);
|
||||
void (*spanfunc) (void);
|
||||
|
||||
/*
|
||||
===================
|
||||
=
|
||||
= R_AddPointToBox
|
||||
=
|
||||
===================
|
||||
*/
|
||||
|
||||
void R_AddPointToBox (int x, int y, fixed_t *box)
|
||||
{
|
||||
if (x< box[BOXLEFT])
|
||||
box[BOXLEFT] = x;
|
||||
if (x> box[BOXRIGHT])
|
||||
box[BOXRIGHT] = x;
|
||||
if (y< box[BOXBOTTOM])
|
||||
box[BOXBOTTOM] = y;
|
||||
if (y> box[BOXTOP])
|
||||
box[BOXTOP] = y;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
=
|
||||
= R_PointOnSide
|
||||
=
|
||||
= Returns side 0 (front) or 1 (back)
|
||||
===============================================================================
|
||||
*/
|
||||
|
||||
int R_PointOnSide (fixed_t x, fixed_t y, node_t *node)
|
||||
{
|
||||
fixed_t dx,dy;
|
||||
fixed_t left, right;
|
||||
|
||||
if (!node->dx)
|
||||
{
|
||||
if (x <= node->x)
|
||||
return node->dy > 0;
|
||||
return node->dy < 0;
|
||||
}
|
||||
if (!node->dy)
|
||||
{
|
||||
if (y <= node->y)
|
||||
return node->dx < 0;
|
||||
return node->dx > 0;
|
||||
}
|
||||
|
||||
dx = (x - node->x);
|
||||
dy = (y - node->y);
|
||||
|
||||
// try to quickly decide by looking at sign bits
|
||||
if ( (node->dy ^ node->dx ^ dx ^ dy)&0x80000000 )
|
||||
{
|
||||
if ( (node->dy ^ dx) & 0x80000000 )
|
||||
return 1; // (left is negative)
|
||||
return 0;
|
||||
}
|
||||
|
||||
left = FixedMul ( node->dy>>FRACBITS , dx );
|
||||
right = FixedMul ( dy , node->dx>>FRACBITS );
|
||||
|
||||
if (right < left)
|
||||
return 0; // front side
|
||||
return 1; // back side
|
||||
}
|
||||
|
||||
|
||||
int R_PointOnSegSide (fixed_t x, fixed_t y, seg_t *line)
|
||||
{
|
||||
fixed_t lx, ly;
|
||||
fixed_t ldx, ldy;
|
||||
fixed_t dx,dy;
|
||||
fixed_t left, right;
|
||||
|
||||
lx = line->v1->x;
|
||||
ly = line->v1->y;
|
||||
|
||||
ldx = line->v2->x - lx;
|
||||
ldy = line->v2->y - ly;
|
||||
|
||||
if (!ldx)
|
||||
{
|
||||
if (x <= lx)
|
||||
return ldy > 0;
|
||||
return ldy < 0;
|
||||
}
|
||||
if (!ldy)
|
||||
{
|
||||
if (y <= ly)
|
||||
return ldx < 0;
|
||||
return ldx > 0;
|
||||
}
|
||||
|
||||
dx = (x - lx);
|
||||
dy = (y - ly);
|
||||
|
||||
// try to quickly decide by looking at sign bits
|
||||
if ( (ldy ^ ldx ^ dx ^ dy)&0x80000000 )
|
||||
{
|
||||
if ( (ldy ^ dx) & 0x80000000 )
|
||||
return 1; // (left is negative)
|
||||
return 0;
|
||||
}
|
||||
|
||||
left = FixedMul ( ldy>>FRACBITS , dx );
|
||||
right = FixedMul ( dy , ldx>>FRACBITS );
|
||||
|
||||
if (right < left)
|
||||
return 0; // front side
|
||||
return 1; // back side
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
=
|
||||
= R_PointToAngle
|
||||
=
|
||||
===============================================================================
|
||||
*/
|
||||
|
||||
// to get a global angle from cartesian coordinates, the coordinates are
|
||||
// flipped until they are in the first octant of the coordinate system, then
|
||||
// the y (<=x) is scaled and divided by x to get a tangent (slope) value
|
||||
// which is looked up in the tantoangle[] table. The +1 size is to handle
|
||||
// the case when x==y without additional checking.
|
||||
#define SLOPERANGE 2048
|
||||
#define SLOPEBITS 11
|
||||
#define DBITS (FRACBITS-SLOPEBITS)
|
||||
|
||||
|
||||
extern int tantoangle[SLOPERANGE+1]; // get from tables.c
|
||||
|
||||
// int tantoangle[SLOPERANGE+1];
|
||||
|
||||
int SlopeDiv (unsigned num, unsigned den)
|
||||
{
|
||||
unsigned ans;
|
||||
if (den < 512)
|
||||
return SLOPERANGE;
|
||||
ans = (num<<3)/(den>>8);
|
||||
return ans <= SLOPERANGE ? ans : SLOPERANGE;
|
||||
}
|
||||
|
||||
angle_t R_PointToAngle (fixed_t x, fixed_t y)
|
||||
{
|
||||
x -= viewx;
|
||||
y -= viewy;
|
||||
if ( (!x) && (!y) )
|
||||
return 0;
|
||||
if (x>= 0)
|
||||
{ // x >=0
|
||||
if (y>= 0)
|
||||
{ // y>= 0
|
||||
if (x>y)
|
||||
return tantoangle[ SlopeDiv(y,x)]; // octant 0
|
||||
else
|
||||
return ANG90-1-tantoangle[ SlopeDiv(x,y)]; // octant 1
|
||||
}
|
||||
else
|
||||
{ // y<0
|
||||
y = -y;
|
||||
if (x>y)
|
||||
return -tantoangle[SlopeDiv(y,x)]; // octant 8
|
||||
else
|
||||
return ANG270+tantoangle[ SlopeDiv(x,y)]; // octant 7
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // x<0
|
||||
x = -x;
|
||||
if (y>= 0)
|
||||
{ // y>= 0
|
||||
if (x>y)
|
||||
return ANG180-1-tantoangle[ SlopeDiv(y,x)]; // octant 3
|
||||
else
|
||||
return ANG90+ tantoangle[ SlopeDiv(x,y)]; // octant 2
|
||||
}
|
||||
else
|
||||
{ // y<0
|
||||
y = -y;
|
||||
if (x>y)
|
||||
return ANG180+tantoangle[ SlopeDiv(y,x)]; // octant 4
|
||||
else
|
||||
return ANG270-1-tantoangle[ SlopeDiv(x,y)]; // octant 5
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
angle_t R_PointToAngle2 (fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2)
|
||||
{
|
||||
viewx = x1;
|
||||
viewy = y1;
|
||||
return R_PointToAngle (x2, y2);
|
||||
}
|
||||
|
||||
|
||||
fixed_t R_PointToDist (fixed_t x, fixed_t y)
|
||||
{
|
||||
int angle;
|
||||
fixed_t dx, dy, 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;
|
||||
|
||||
dist = FixedDiv (dx, finesine[angle] ); // use as cosine
|
||||
|
||||
return dist;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
=================
|
||||
=
|
||||
= R_InitPointToAngle
|
||||
=
|
||||
=================
|
||||
*/
|
||||
|
||||
void R_InitPointToAngle (void)
|
||||
{
|
||||
// now getting from tables.c
|
||||
#if 0
|
||||
int i;
|
||||
long t;
|
||||
float f;
|
||||
//
|
||||
// slope (tangent) to angle lookup
|
||||
//
|
||||
for (i=0 ; i<=SLOPERANGE ; i++)
|
||||
{
|
||||
f = atan( (float)i/SLOPERANGE )/(3.141592657*2);
|
||||
t = 0xffffffff*f;
|
||||
tantoangle[i] = t;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
||||
/*
|
||||
================
|
||||
=
|
||||
= R_ScaleFromGlobalAngle
|
||||
=
|
||||
= Returns the texture mapping scale for the current line at the given angle
|
||||
= rw_distance must be calculated first
|
||||
================
|
||||
*/
|
||||
|
||||
fixed_t R_ScaleFromGlobalAngle (angle_t visangle)
|
||||
{
|
||||
fixed_t scale;
|
||||
int anglea, angleb;
|
||||
int sinea, sineb;
|
||||
fixed_t num,den;
|
||||
|
||||
#if 0
|
||||
{
|
||||
fixed_t dist,z;
|
||||
fixed_t sinv, cosv;
|
||||
|
||||
sinv = finesine[(visangle-rw_normalangle)>>ANGLETOFINESHIFT];
|
||||
dist = FixedDiv (rw_distance, sinv);
|
||||
cosv = finecosine[(viewangle-visangle)>>ANGLETOFINESHIFT];
|
||||
z = abs(FixedMul (dist, cosv));
|
||||
scale = FixedDiv(projection, z);
|
||||
return scale;
|
||||
}
|
||||
#endif
|
||||
|
||||
anglea = ANG90 + (visangle-viewangle);
|
||||
angleb = ANG90 + (visangle-rw_normalangle);
|
||||
// bothe sines are allways positive
|
||||
sinea = finesine[anglea>>ANGLETOFINESHIFT];
|
||||
sineb = finesine[angleb>>ANGLETOFINESHIFT];
|
||||
num = FixedMul(projection,sineb)<<detailshift;
|
||||
den = FixedMul(rw_distance,sinea);
|
||||
if (den > num>>16)
|
||||
{
|
||||
scale = FixedDiv (num, den);
|
||||
if (scale > 64*FRACUNIT)
|
||||
scale = 64*FRACUNIT;
|
||||
else if (scale < 256)
|
||||
scale = 256;
|
||||
}
|
||||
else
|
||||
scale = 64*FRACUNIT;
|
||||
|
||||
return scale;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
=================
|
||||
=
|
||||
= R_InitTables
|
||||
=
|
||||
=================
|
||||
*/
|
||||
|
||||
void R_InitTables (void)
|
||||
{
|
||||
// now getting from tables.c
|
||||
#if 0
|
||||
int i;
|
||||
float a, fv;
|
||||
int t;
|
||||
|
||||
//
|
||||
// viewangle tangent table
|
||||
//
|
||||
for (i=0 ; i<FINEANGLES/2 ; i++)
|
||||
{
|
||||
a = (i-FINEANGLES/4+0.5)*PI*2/FINEANGLES;
|
||||
fv = FRACUNIT*tan (a);
|
||||
t = fv;
|
||||
finetangent[i] = t;
|
||||
}
|
||||
|
||||
//
|
||||
// finesine table
|
||||
//
|
||||
for (i=0 ; i<5*FINEANGLES/4 ; i++)
|
||||
{
|
||||
// OPTIMIZE: mirror...
|
||||
a = (i+0.5)*PI*2/FINEANGLES;
|
||||
t = FRACUNIT*sin (a);
|
||||
finesine[i] = t;
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=================
|
||||
=
|
||||
= R_InitTextureMapping
|
||||
=
|
||||
=================
|
||||
*/
|
||||
|
||||
void R_InitTextureMapping (void)
|
||||
{
|
||||
int i;
|
||||
int x;
|
||||
int t;
|
||||
fixed_t focallength;
|
||||
|
||||
|
||||
//
|
||||
// use tangent table to generate viewangletox
|
||||
// viewangletox will give the next greatest x after the view angle
|
||||
//
|
||||
// calc focallength so FIELDOFVIEW angles covers SCREENWIDTH
|
||||
focallength = FixedDiv (centerxfrac
|
||||
, finetangent[FINEANGLES/4+FIELDOFVIEW/2] );
|
||||
|
||||
for (i=0 ; i<FINEANGLES/2 ; i++)
|
||||
{
|
||||
if (finetangent[i] > FRACUNIT*2)
|
||||
t = -1;
|
||||
else if (finetangent[i] < -FRACUNIT*2)
|
||||
t = viewwidth+1;
|
||||
else
|
||||
{
|
||||
t = FixedMul (finetangent[i], focallength);
|
||||
t = (centerxfrac - t+FRACUNIT-1)>>FRACBITS;
|
||||
if (t < -1)
|
||||
t = -1;
|
||||
else if (t>viewwidth+1)
|
||||
t = viewwidth+1;
|
||||
}
|
||||
viewangletox[i] = t;
|
||||
}
|
||||
|
||||
//
|
||||
// scan viewangletox[] to generate xtoviewangleangle[]
|
||||
//
|
||||
// xtoviewangle will give the smallest view angle that maps to x
|
||||
for (x=0;x<=viewwidth;x++)
|
||||
{
|
||||
i = 0;
|
||||
while (viewangletox[i]>x)
|
||||
i++;
|
||||
xtoviewangle[x] = (i<<ANGLETOFINESHIFT)-ANG90;
|
||||
}
|
||||
|
||||
//
|
||||
// take out the fencepost cases from viewangletox
|
||||
//
|
||||
for (i=0 ; i<FINEANGLES/2 ; i++)
|
||||
{
|
||||
t = FixedMul (finetangent[i], focallength);
|
||||
t = centerx - t;
|
||||
if (viewangletox[i] == -1)
|
||||
viewangletox[i] = 0;
|
||||
else if (viewangletox[i] == viewwidth+1)
|
||||
viewangletox[i] = viewwidth;
|
||||
}
|
||||
|
||||
clipangle = xtoviewangle[0];
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
||||
/*
|
||||
====================
|
||||
=
|
||||
= R_InitLightTables
|
||||
=
|
||||
= Only inits the zlight table, because the scalelight table changes
|
||||
= with view size
|
||||
=
|
||||
====================
|
||||
*/
|
||||
|
||||
#define DISTMAP 2
|
||||
|
||||
void R_InitLightTables (void)
|
||||
{
|
||||
int i,j, level, startmap;
|
||||
int scale;
|
||||
|
||||
//
|
||||
// Calculate the light levels to use for each level / distance combination
|
||||
//
|
||||
for (i=0 ; i< LIGHTLEVELS ; i++)
|
||||
{
|
||||
startmap = ((LIGHTLEVELS-1-i)*2)*NUMCOLORMAPS/LIGHTLEVELS;
|
||||
for (j=0 ; j<MAXLIGHTZ ; j++)
|
||||
{
|
||||
scale = FixedDiv ((SCREENWIDTH/2*FRACUNIT), (j+1)<<LIGHTZSHIFT);
|
||||
scale >>= LIGHTSCALESHIFT;
|
||||
level = startmap - scale/DISTMAP;
|
||||
if (level < 0)
|
||||
level = 0;
|
||||
if (level >= NUMCOLORMAPS)
|
||||
level = NUMCOLORMAPS-1;
|
||||
zlight[i][j] = colormaps + level*256;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
==============
|
||||
=
|
||||
= R_SetViewSize
|
||||
=
|
||||
= Don't really change anything here, because i might be in the middle of
|
||||
= a refresh. The change will take effect next refresh.
|
||||
=
|
||||
==============
|
||||
*/
|
||||
|
||||
boolean setsizeneeded;
|
||||
int setblocks, setdetail;
|
||||
|
||||
void R_SetViewSize (int blocks, int detail)
|
||||
{
|
||||
setsizeneeded = true;
|
||||
setblocks = blocks;
|
||||
setdetail = detail;
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
=
|
||||
= R_ExecuteSetViewSize
|
||||
=
|
||||
==============
|
||||
*/
|
||||
|
||||
void R_ExecuteSetViewSize (void)
|
||||
{
|
||||
fixed_t cosadj, dy;
|
||||
int i,j, level, startmap;
|
||||
|
||||
setsizeneeded = false;
|
||||
|
||||
if (setblocks == 11)
|
||||
{
|
||||
scaledviewwidth = SCREENWIDTH;
|
||||
viewheight = SCREENHEIGHT;
|
||||
}
|
||||
else
|
||||
{
|
||||
scaledviewwidth = setblocks*32;
|
||||
viewheight = (setblocks*158/10);
|
||||
}
|
||||
|
||||
detailshift = setdetail;
|
||||
viewwidth = scaledviewwidth>>detailshift;
|
||||
|
||||
centery = viewheight/2;
|
||||
centerx = viewwidth/2;
|
||||
centerxfrac = centerx<<FRACBITS;
|
||||
centeryfrac = centery<<FRACBITS;
|
||||
projection = centerxfrac;
|
||||
|
||||
if (!detailshift)
|
||||
{
|
||||
colfunc = basecolfunc = R_DrawColumn;
|
||||
fuzzcolfunc = R_DrawFuzzColumn;
|
||||
transcolfunc = R_DrawTranslatedColumn;
|
||||
spanfunc = R_DrawSpan;
|
||||
}
|
||||
else
|
||||
{
|
||||
colfunc = basecolfunc = R_DrawColumnLow;
|
||||
fuzzcolfunc = R_DrawFuzzColumn;
|
||||
transcolfunc = R_DrawTranslatedColumn;
|
||||
spanfunc = R_DrawSpanLow;
|
||||
}
|
||||
|
||||
R_InitBuffer (scaledviewwidth, viewheight);
|
||||
|
||||
R_InitTextureMapping ();
|
||||
|
||||
//
|
||||
// psprite scales
|
||||
//
|
||||
pspritescale = FRACUNIT*viewwidth/SCREENWIDTH;
|
||||
pspriteiscale = FRACUNIT*SCREENWIDTH/viewwidth;
|
||||
|
||||
//
|
||||
// thing clipping
|
||||
//
|
||||
for (i=0 ; i<viewwidth ; i++)
|
||||
screenheightarray[i] = viewheight;
|
||||
|
||||
//
|
||||
// planes
|
||||
//
|
||||
for (i=0 ; i<viewheight ; i++)
|
||||
{
|
||||
dy = ((i-viewheight/2)<<FRACBITS)+FRACUNIT/2;
|
||||
dy = abs(dy);
|
||||
yslope[i] = FixedDiv ( (viewwidth<<detailshift)/2*FRACUNIT, dy);
|
||||
}
|
||||
|
||||
for (i=0 ; i<viewwidth ; i++)
|
||||
{
|
||||
cosadj = abs(finecosine[xtoviewangle[i]>>ANGLETOFINESHIFT]);
|
||||
distscale[i] = FixedDiv (FRACUNIT,cosadj);
|
||||
}
|
||||
|
||||
//
|
||||
// Calculate the light levels to use for each level / scale combination
|
||||
//
|
||||
for (i=0 ; i< LIGHTLEVELS ; i++)
|
||||
{
|
||||
startmap = ((LIGHTLEVELS-1-i)*2)*NUMCOLORMAPS/LIGHTLEVELS;
|
||||
for (j=0 ; j<MAXLIGHTSCALE ; j++)
|
||||
{
|
||||
level = startmap - j*SCREENWIDTH/(viewwidth<<detailshift)/DISTMAP;
|
||||
if (level < 0)
|
||||
level = 0;
|
||||
if (level >= NUMCOLORMAPS)
|
||||
level = NUMCOLORMAPS-1;
|
||||
scalelight[i][j] = colormaps + level*256;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// draw the border
|
||||
//
|
||||
R_DrawViewBorder (); // erase old menu stuff
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
==============
|
||||
=
|
||||
= R_Init
|
||||
=
|
||||
==============
|
||||
*/
|
||||
|
||||
int detailLevel;
|
||||
int screenblocks;
|
||||
|
||||
void R_Init (void)
|
||||
{
|
||||
tprintf("R_InitData ",1);
|
||||
R_InitData ();
|
||||
//printf (".");
|
||||
tprintf("R_InitPointToAngle\n",0);
|
||||
R_InitPointToAngle ();
|
||||
//printf (".");
|
||||
tprintf("R_InitTables ",0);
|
||||
R_InitTables ();
|
||||
// viewwidth / viewheight / detailLevel are set by the defaults
|
||||
//printf (".");
|
||||
R_SetViewSize (screenblocks, detailLevel);
|
||||
tprintf("R_InitPlanes\n",0);
|
||||
R_InitPlanes ();
|
||||
//printf (".");
|
||||
tprintf("R_InitLightTables ",0);
|
||||
R_InitLightTables ();
|
||||
//printf (".");
|
||||
tprintf("R_InitSkyMap\n",0);
|
||||
R_InitSkyMap ();
|
||||
//printf (".");
|
||||
R_InitTranslationTables();
|
||||
framecount = 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
==============
|
||||
=
|
||||
= R_PointInSubsector
|
||||
=
|
||||
==============
|
||||
*/
|
||||
|
||||
subsector_t *R_PointInSubsector (fixed_t x, fixed_t y)
|
||||
{
|
||||
node_t *node;
|
||||
int side, nodenum;
|
||||
|
||||
if (!numnodes) // single subsector is a special case
|
||||
return subsectors;
|
||||
|
||||
nodenum = numnodes-1;
|
||||
|
||||
while (! (nodenum & NF_SUBSECTOR) )
|
||||
{
|
||||
node = &nodes[nodenum];
|
||||
side = R_PointOnSide (x, y, node);
|
||||
nodenum = node->children[side];
|
||||
}
|
||||
|
||||
return &subsectors[nodenum & ~NF_SUBSECTOR];
|
||||
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// PROC R_SetupFrame
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void R_SetupFrame(player_t *player)
|
||||
{
|
||||
int i;
|
||||
int tableAngle;
|
||||
int tempCentery;
|
||||
|
||||
//drawbsp = 1;
|
||||
viewplayer = player;
|
||||
#ifdef __WATCOMC__
|
||||
viewangleoffset = newViewAngleOff<<ANGLETOFINESHIFT;
|
||||
#endif
|
||||
viewangle = player->mo->angle+viewangleoffset;
|
||||
tableAngle = viewangle>>ANGLETOFINESHIFT;
|
||||
if(player->chickenTics && player->chickenPeck)
|
||||
{ // Set chicken attack view position
|
||||
viewx = player->mo->x+player->chickenPeck*finecosine[tableAngle];
|
||||
viewy = player->mo->y+player->chickenPeck*finesine[tableAngle];
|
||||
}
|
||||
else
|
||||
{ // Normal view position
|
||||
viewx = player->mo->x;
|
||||
viewy = player->mo->y;
|
||||
}
|
||||
extralight = player->extralight;
|
||||
viewz = player->viewz;
|
||||
|
||||
tempCentery = viewheight/2+(player->lookdir)*screenblocks/10;
|
||||
if(centery != tempCentery)
|
||||
{
|
||||
centery = tempCentery;
|
||||
centeryfrac = centery<<FRACBITS;
|
||||
for(i = 0; i < viewheight; i++)
|
||||
{
|
||||
yslope[i] = FixedDiv ((viewwidth<<detailshift)/2*FRACUNIT,
|
||||
abs(((i-centery)<<FRACBITS)+FRACUNIT/2));
|
||||
}
|
||||
}
|
||||
viewsin = finesine[tableAngle];
|
||||
viewcos = finecosine[tableAngle];
|
||||
sscount = 0;
|
||||
if(player->fixedcolormap)
|
||||
{
|
||||
fixedcolormap = colormaps+player->fixedcolormap
|
||||
*256*sizeof(lighttable_t);
|
||||
walllights = scalelightfixed;
|
||||
for(i = 0; i < MAXLIGHTSCALE; i++)
|
||||
{
|
||||
scalelightfixed[i] = fixedcolormap;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fixedcolormap = 0;
|
||||
}
|
||||
framecount++;
|
||||
validcount++;
|
||||
if(BorderNeedRefresh)
|
||||
{
|
||||
if(setblocks < 10)
|
||||
{
|
||||
R_DrawViewBorder();
|
||||
}
|
||||
BorderNeedRefresh = false;
|
||||
BorderTopRefresh = false;
|
||||
UpdateState |= I_FULLSCRN;
|
||||
}
|
||||
if(BorderTopRefresh)
|
||||
{
|
||||
if(setblocks < 10)
|
||||
{
|
||||
R_DrawTopBorder();
|
||||
}
|
||||
BorderTopRefresh = false;
|
||||
UpdateState |= I_MESSAGES;
|
||||
}
|
||||
|
||||
#ifdef __NeXT__
|
||||
RD_ClearMapWindow ();
|
||||
#endif
|
||||
#ifdef __WATCOMC__
|
||||
destview = destscreen+(viewwindowx>>2)+viewwindowy*80;
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
{
|
||||
static int frame;
|
||||
memset (screen, frame, SCREENWIDTH*SCREENHEIGHT);
|
||||
frame++;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
=
|
||||
= R_RenderView
|
||||
=
|
||||
==============
|
||||
*/
|
||||
|
||||
void R_RenderPlayerView (player_t *player)
|
||||
{
|
||||
R_SetupFrame (player);
|
||||
R_ClearClipSegs ();
|
||||
R_ClearDrawSegs ();
|
||||
R_ClearPlanes ();
|
||||
R_ClearSprites ();
|
||||
NetUpdate (); // check for new console commands
|
||||
R_RenderBSPNode (numnodes-1); // the head node is the last node output
|
||||
NetUpdate (); // check for new console commands
|
||||
R_DrawPlanes ();
|
||||
NetUpdate (); // check for new console commands
|
||||
R_DrawMasked ();
|
||||
NetUpdate (); // check for new console commands
|
||||
}
|
472
Heretic Source/R_PLANE.C
Normal file
472
Heretic Source/R_PLANE.C
Normal file
|
@ -0,0 +1,472 @@
|
|||
// R_planes.c
|
||||
|
||||
#include "DoomDef.h"
|
||||
#include "R_local.h"
|
||||
|
||||
planefunction_t floorfunc, ceilingfunc;
|
||||
|
||||
//
|
||||
// sky mapping
|
||||
//
|
||||
int skyflatnum;
|
||||
int skytexture;
|
||||
int skytexturemid;
|
||||
fixed_t skyiscale;
|
||||
|
||||
//
|
||||
// opening
|
||||
//
|
||||
|
||||
visplane_t visplanes[MAXVISPLANES], *lastvisplane;
|
||||
visplane_t *floorplane, *ceilingplane;
|
||||
|
||||
short openings[MAXOPENINGS], *lastopening;
|
||||
|
||||
//
|
||||
// clip values are the solid pixel bounding the range
|
||||
// floorclip starts out SCREENHEIGHT
|
||||
// ceilingclip starts out -1
|
||||
//
|
||||
short floorclip[SCREENWIDTH];
|
||||
short ceilingclip[SCREENWIDTH];
|
||||
|
||||
//
|
||||
// spanstart holds the start of a plane span
|
||||
// initialized to 0 at start
|
||||
//
|
||||
int spanstart[SCREENHEIGHT];
|
||||
int spanstop[SCREENHEIGHT];
|
||||
|
||||
//
|
||||
// texture mapping
|
||||
//
|
||||
lighttable_t **planezlight;
|
||||
fixed_t planeheight;
|
||||
|
||||
fixed_t yslope[SCREENHEIGHT];
|
||||
fixed_t distscale[SCREENWIDTH];
|
||||
fixed_t basexscale, baseyscale;
|
||||
|
||||
fixed_t cachedheight[SCREENHEIGHT];
|
||||
fixed_t cacheddistance[SCREENHEIGHT];
|
||||
fixed_t cachedxstep[SCREENHEIGHT];
|
||||
fixed_t cachedystep[SCREENHEIGHT];
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
=
|
||||
= R_InitSkyMap
|
||||
=
|
||||
= Called whenever the view size changes
|
||||
=
|
||||
================
|
||||
*/
|
||||
|
||||
void R_InitSkyMap (void)
|
||||
{
|
||||
skyflatnum = R_FlatNumForName ("F_SKY1");
|
||||
skytexturemid = 200*FRACUNIT;
|
||||
skyiscale = FRACUNIT;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
====================
|
||||
=
|
||||
= R_InitPlanes
|
||||
=
|
||||
= Only at game startup
|
||||
====================
|
||||
*/
|
||||
|
||||
void R_InitPlanes (void)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
=
|
||||
= R_MapPlane
|
||||
=
|
||||
global vars:
|
||||
|
||||
planeheight
|
||||
ds_source
|
||||
basexscale
|
||||
baseyscale
|
||||
viewx
|
||||
viewy
|
||||
|
||||
BASIC PRIMITIVE
|
||||
================
|
||||
*/
|
||||
|
||||
void R_MapPlane (int y, int x1, int x2)
|
||||
{
|
||||
angle_t angle;
|
||||
fixed_t distance, length;
|
||||
unsigned index;
|
||||
|
||||
#ifdef RANGECHECK
|
||||
if (x2 < x1 || x1<0 || x2>=viewwidth || (unsigned)y>viewheight)
|
||||
I_Error ("R_MapPlane: %i, %i at %i",x1,x2,y);
|
||||
#endif
|
||||
|
||||
if (planeheight != cachedheight[y])
|
||||
{
|
||||
cachedheight[y] = planeheight;
|
||||
distance = cacheddistance[y] = FixedMul (planeheight, yslope[y]);
|
||||
|
||||
ds_xstep = cachedxstep[y] = FixedMul (distance,basexscale);
|
||||
ds_ystep = cachedystep[y] = FixedMul (distance,baseyscale);
|
||||
}
|
||||
else
|
||||
{
|
||||
distance = cacheddistance[y];
|
||||
ds_xstep = cachedxstep[y];
|
||||
ds_ystep = cachedystep[y];
|
||||
}
|
||||
|
||||
length = FixedMul (distance,distscale[x1]);
|
||||
angle = (viewangle + xtoviewangle[x1])>>ANGLETOFINESHIFT;
|
||||
ds_xfrac = viewx + FixedMul(finecosine[angle], length);
|
||||
ds_yfrac = -viewy - FixedMul(finesine[angle], length);
|
||||
|
||||
if (fixedcolormap)
|
||||
ds_colormap = fixedcolormap;
|
||||
else
|
||||
{
|
||||
index = distance >> LIGHTZSHIFT;
|
||||
if (index >= MAXLIGHTZ )
|
||||
index = MAXLIGHTZ-1;
|
||||
ds_colormap = planezlight[index];
|
||||
}
|
||||
|
||||
ds_y = y;
|
||||
ds_x1 = x1;
|
||||
ds_x2 = x2;
|
||||
|
||||
spanfunc (); // high or low detail
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
||||
/*
|
||||
====================
|
||||
=
|
||||
= R_ClearPlanes
|
||||
=
|
||||
= At begining of frame
|
||||
====================
|
||||
*/
|
||||
|
||||
void R_ClearPlanes (void)
|
||||
{
|
||||
int i;
|
||||
angle_t angle;
|
||||
|
||||
//
|
||||
// opening / clipping determination
|
||||
//
|
||||
for (i=0 ; i<viewwidth ; i++)
|
||||
{
|
||||
floorclip[i] = viewheight;
|
||||
ceilingclip[i] = -1;
|
||||
}
|
||||
|
||||
lastvisplane = visplanes;
|
||||
lastopening = openings;
|
||||
|
||||
//
|
||||
// texture calculation
|
||||
//
|
||||
memset (cachedheight, 0, sizeof(cachedheight));
|
||||
angle = (viewangle-ANG90)>>ANGLETOFINESHIFT; // left to right mapping
|
||||
|
||||
// scale will be unit scale at SCREENWIDTH/2 distance
|
||||
basexscale = FixedDiv (finecosine[angle],centerxfrac);
|
||||
baseyscale = -FixedDiv (finesine[angle],centerxfrac);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
===============
|
||||
=
|
||||
= R_FindPlane
|
||||
=
|
||||
===============
|
||||
*/
|
||||
|
||||
visplane_t *R_FindPlane(fixed_t height, int picnum,
|
||||
int lightlevel, int special)
|
||||
{
|
||||
visplane_t *check;
|
||||
|
||||
if(picnum == skyflatnum)
|
||||
{
|
||||
// all skies map together
|
||||
height = 0;
|
||||
lightlevel = 0;
|
||||
}
|
||||
|
||||
for(check = visplanes; check < lastvisplane; check++)
|
||||
{
|
||||
if(height == check->height
|
||||
&& picnum == check->picnum
|
||||
&& lightlevel == check->lightlevel
|
||||
&& special == check->special)
|
||||
break;
|
||||
}
|
||||
|
||||
if(check < lastvisplane)
|
||||
{
|
||||
return(check);
|
||||
}
|
||||
|
||||
if(lastvisplane-visplanes == MAXVISPLANES)
|
||||
{
|
||||
I_Error("R_FindPlane: no more visplanes");
|
||||
}
|
||||
|
||||
lastvisplane++;
|
||||
check->height = height;
|
||||
check->picnum = picnum;
|
||||
check->lightlevel = lightlevel;
|
||||
check->special = special;
|
||||
check->minx = SCREENWIDTH;
|
||||
check->maxx = -1;
|
||||
memset(check->top,0xff,sizeof(check->top));
|
||||
return(check);
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
=
|
||||
= R_CheckPlane
|
||||
=
|
||||
===============
|
||||
*/
|
||||
|
||||
visplane_t *R_CheckPlane (visplane_t *pl, int start, int stop)
|
||||
{
|
||||
int intrl, intrh;
|
||||
int unionl, unionh;
|
||||
int x;
|
||||
|
||||
if (start < pl->minx)
|
||||
{
|
||||
intrl = pl->minx;
|
||||
unionl = start;
|
||||
}
|
||||
else
|
||||
{
|
||||
unionl = pl->minx;
|
||||
intrl = start;
|
||||
}
|
||||
|
||||
if (stop > pl->maxx)
|
||||
{
|
||||
intrh = pl->maxx;
|
||||
unionh = stop;
|
||||
}
|
||||
else
|
||||
{
|
||||
unionh = pl->maxx;
|
||||
intrh = stop;
|
||||
}
|
||||
|
||||
for (x=intrl ; x<= intrh ; x++)
|
||||
if (pl->top[x] != 0xff)
|
||||
break;
|
||||
|
||||
if (x > intrh)
|
||||
{
|
||||
pl->minx = unionl;
|
||||
pl->maxx = unionh;
|
||||
return pl; // use the same one
|
||||
}
|
||||
|
||||
// make a new visplane
|
||||
|
||||
lastvisplane->height = pl->height;
|
||||
lastvisplane->picnum = pl->picnum;
|
||||
lastvisplane->lightlevel = pl->lightlevel;
|
||||
lastvisplane->special = pl->special;
|
||||
pl = lastvisplane++;
|
||||
pl->minx = start;
|
||||
pl->maxx = stop;
|
||||
memset (pl->top,0xff,sizeof(pl->top));
|
||||
|
||||
return pl;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//=============================================================================
|
||||
|
||||
/*
|
||||
================
|
||||
=
|
||||
= R_MakeSpans
|
||||
=
|
||||
================
|
||||
*/
|
||||
|
||||
void R_MakeSpans (int x, int t1, int b1, int t2, int b2)
|
||||
{
|
||||
while (t1 < t2 && t1<=b1)
|
||||
{
|
||||
R_MapPlane (t1,spanstart[t1],x-1);
|
||||
t1++;
|
||||
}
|
||||
while (b1 > b2 && b1>=t1)
|
||||
{
|
||||
R_MapPlane (b1,spanstart[b1],x-1);
|
||||
b1--;
|
||||
}
|
||||
|
||||
while (t2 < t1 && t2<=b2)
|
||||
{
|
||||
spanstart[t2] = x;
|
||||
t2++;
|
||||
}
|
||||
while (b2 > b1 && b2>=t2)
|
||||
{
|
||||
spanstart[b2] = x;
|
||||
b2--;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
=
|
||||
= R_DrawPlanes
|
||||
=
|
||||
= At the end of each frame
|
||||
================
|
||||
*/
|
||||
|
||||
void R_DrawPlanes (void)
|
||||
{
|
||||
visplane_t *pl;
|
||||
int light;
|
||||
int x, stop;
|
||||
int angle;
|
||||
byte *tempSource;
|
||||
|
||||
byte *dest;
|
||||
int count;
|
||||
fixed_t frac, fracstep;
|
||||
|
||||
extern byte *ylookup[MAXHEIGHT];
|
||||
extern int columnofs[MAXWIDTH];
|
||||
|
||||
#ifdef RANGECHECK
|
||||
if (ds_p - drawsegs > MAXDRAWSEGS)
|
||||
I_Error ("R_DrawPlanes: drawsegs overflow (%i)", ds_p - drawsegs);
|
||||
if (lastvisplane - visplanes > MAXVISPLANES)
|
||||
I_Error ("R_DrawPlanes: visplane overflow (%i)", lastvisplane - visplanes);
|
||||
if (lastopening - openings > MAXOPENINGS)
|
||||
I_Error ("R_DrawPlanes: opening overflow (%i)", lastopening - openings);
|
||||
#endif
|
||||
|
||||
for (pl = visplanes ; pl < lastvisplane ; pl++)
|
||||
{
|
||||
if (pl->minx > pl->maxx)
|
||||
continue;
|
||||
//
|
||||
// sky flat
|
||||
//
|
||||
if (pl->picnum == skyflatnum)
|
||||
{
|
||||
dc_iscale = skyiscale;
|
||||
dc_colormap = colormaps;// sky is allways drawn full bright
|
||||
dc_texturemid = skytexturemid;
|
||||
for (x=pl->minx ; x <= pl->maxx ; x++)
|
||||
{
|
||||
dc_yl = pl->top[x];
|
||||
dc_yh = pl->bottom[x];
|
||||
if (dc_yl <= dc_yh)
|
||||
{
|
||||
angle = (viewangle + xtoviewangle[x])>>ANGLETOSKYSHIFT;
|
||||
dc_x = x;
|
||||
dc_source = R_GetColumn(skytexture, angle);
|
||||
|
||||
count = dc_yh - dc_yl;
|
||||
if (count < 0)
|
||||
return;
|
||||
|
||||
#ifdef RANGECHECK
|
||||
if ((unsigned)dc_x >= SCREENWIDTH || dc_yl < 0 || dc_yh >= SCREENHEIGHT)
|
||||
I_Error ("R_DrawColumn: %i to %i at %i", dc_yl, dc_yh, dc_x);
|
||||
#endif
|
||||
|
||||
dest = ylookup[dc_yl] + columnofs[dc_x];
|
||||
|
||||
fracstep = 1;
|
||||
frac = (dc_texturemid>>FRACBITS) + (dc_yl-centery);
|
||||
do
|
||||
{
|
||||
*dest = dc_source[frac];
|
||||
dest += SCREENWIDTH;
|
||||
frac += fracstep;
|
||||
} while (count--);
|
||||
|
||||
// colfunc ();
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
//
|
||||
// regular flat
|
||||
//
|
||||
tempSource = W_CacheLumpNum(firstflat +
|
||||
flattranslation[pl->picnum], PU_STATIC);
|
||||
|
||||
switch(pl->special)
|
||||
{
|
||||
case 25: case 26: case 27: case 28: case 29: // Scroll_North
|
||||
ds_source = tempSource;
|
||||
break;
|
||||
case 20: case 21: case 22: case 23: case 24: // Scroll_East
|
||||
ds_source = tempSource+((63-((leveltime>>1)&63))<<
|
||||
(pl->special-20)&63);
|
||||
//ds_source = tempSource+((leveltime>>1)&63);
|
||||
break;
|
||||
case 30: case 31: case 32: case 33: case 34: // Scroll_South
|
||||
ds_source = tempSource;
|
||||
break;
|
||||
case 35: case 36: case 37: case 38: case 39: // Scroll_West
|
||||
ds_source = tempSource;
|
||||
break;
|
||||
case 4: // Scroll_EastLavaDamage
|
||||
ds_source = tempSource+(((63-((leveltime>>1)&63))<<3)&63);
|
||||
break;
|
||||
default:
|
||||
ds_source = tempSource;
|
||||
}
|
||||
planeheight = abs(pl->height-viewz);
|
||||
light = (pl->lightlevel >> LIGHTSEGSHIFT)+extralight;
|
||||
if (light >= LIGHTLEVELS)
|
||||
light = LIGHTLEVELS-1;
|
||||
if (light < 0)
|
||||
light = 0;
|
||||
planezlight = zlight[light];
|
||||
|
||||
pl->top[pl->maxx+1] = 0xff;
|
||||
pl->top[pl->minx-1] = 0xff;
|
||||
|
||||
stop = pl->maxx + 1;
|
||||
for (x=pl->minx ; x<= stop ; x++)
|
||||
R_MakeSpans (x,pl->top[x-1],pl->bottom[x-1]
|
||||
,pl->top[x],pl->bottom[x]);
|
||||
|
||||
Z_ChangeTag (tempSource, PU_CACHE);
|
||||
}
|
||||
}
|
645
Heretic Source/R_SEGS.C
Normal file
645
Heretic Source/R_SEGS.C
Normal file
|
@ -0,0 +1,645 @@
|
|||
|
||||
//**************************************************************************
|
||||
//**
|
||||
//** R_SEGS.C
|
||||
//**
|
||||
//** This version has the tall-sector-crossing-precision-bug fixed.
|
||||
//**
|
||||
//**************************************************************************
|
||||
|
||||
#include "DoomDef.h"
|
||||
#include "R_local.h"
|
||||
|
||||
// OPTIMIZE: closed two sided lines as single sided
|
||||
|
||||
boolean segtextured; // true if any of the segs textures might be vis
|
||||
boolean markfloor; // false if the back side is the same plane
|
||||
boolean markceiling;
|
||||
boolean maskedtexture;
|
||||
int toptexture, bottomtexture, midtexture;
|
||||
|
||||
|
||||
angle_t rw_normalangle;
|
||||
int rw_angle1; // angle to line origin
|
||||
|
||||
//
|
||||
// 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;
|
||||
|
||||
int worldtop, worldbottom, worldhigh, worldlow;
|
||||
|
||||
fixed_t pixhigh, pixlow;
|
||||
fixed_t pixhighstep, pixlowstep;
|
||||
fixed_t topfrac, topstep;
|
||||
fixed_t bottomfrac, bottomstep;
|
||||
|
||||
|
||||
lighttable_t **walllights;
|
||||
|
||||
short *maskedtexturecol;
|
||||
|
||||
/*
|
||||
================
|
||||
=
|
||||
= R_RenderMaskedSegRange
|
||||
=
|
||||
================
|
||||
*/
|
||||
|
||||
void R_RenderMaskedSegRange (drawseg_t *ds, int x1, int x2)
|
||||
{
|
||||
unsigned index;
|
||||
column_t *col;
|
||||
int lightnum;
|
||||
int texnum;
|
||||
|
||||
//
|
||||
// calculate light table
|
||||
// use different light tables for horizontal / vertical / 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;
|
||||
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];
|
||||
|
||||
maskedtexturecol = ds->maskedtexturecol;
|
||||
|
||||
rw_scalestep = ds->scalestep;
|
||||
spryscale = ds->scale1 + (x1 - ds->x1)*rw_scalestep;
|
||||
mfloorclip = ds->sprbottomclip;
|
||||
mceilingclip = ds->sprtopclip;
|
||||
|
||||
//
|
||||
// find positioning
|
||||
//
|
||||
if (curline->linedef->flags & ML_DONTPEGBOTTOM)
|
||||
{
|
||||
dc_texturemid = frontsector->floorheight > backsector->floorheight
|
||||
? frontsector->floorheight : backsector->floorheight;
|
||||
dc_texturemid = dc_texturemid + textureheight[texnum] - viewz;
|
||||
}
|
||||
else
|
||||
{
|
||||
dc_texturemid =frontsector->ceilingheight<backsector->ceilingheight
|
||||
? frontsector->ceilingheight : backsector->ceilingheight;
|
||||
dc_texturemid = dc_texturemid - viewz;
|
||||
}
|
||||
dc_texturemid += curline->sidedef->rowoffset;
|
||||
|
||||
if (fixedcolormap)
|
||||
dc_colormap = fixedcolormap;
|
||||
//
|
||||
// draw the columns
|
||||
//
|
||||
for (dc_x = x1 ; dc_x <= x2 ; dc_x++)
|
||||
{
|
||||
// calculate lighting
|
||||
if (maskedtexturecol[dc_x] != MAXSHORT)
|
||||
{
|
||||
if (!fixedcolormap)
|
||||
{
|
||||
index = spryscale>>LIGHTSCALESHIFT;
|
||||
if (index >= MAXLIGHTSCALE )
|
||||
index = MAXLIGHTSCALE-1;
|
||||
dc_colormap = walllights[index];
|
||||
}
|
||||
|
||||
sprtopscreen = centeryfrac - FixedMul(dc_texturemid, spryscale);
|
||||
dc_iscale = 0xffffffffu / (unsigned)spryscale;
|
||||
|
||||
//
|
||||
// draw the texture
|
||||
//
|
||||
col = (column_t *)(
|
||||
(byte *)R_GetColumn(texnum,maskedtexturecol[dc_x]) -3);
|
||||
|
||||
R_DrawMaskedColumn (col, -1);
|
||||
maskedtexturecol[dc_x] = MAXSHORT;
|
||||
}
|
||||
spryscale += rw_scalestep;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
=
|
||||
= R_RenderSegLoop
|
||||
=
|
||||
= Draws zero, one, or two textures (and possibly a masked texture) for walls
|
||||
= Can draw or mark the starting pixel of floor and ceiling textures
|
||||
=
|
||||
= CALLED: CORE LOOPING ROUTINE
|
||||
================
|
||||
*/
|
||||
|
||||
#define HEIGHTBITS 12
|
||||
#define HEIGHTUNIT (1<<HEIGHTBITS)
|
||||
|
||||
void R_RenderSegLoop (void)
|
||||
{
|
||||
angle_t angle;
|
||||
unsigned index;
|
||||
int yl, yh, mid;
|
||||
fixed_t texturecolumn;
|
||||
int top, bottom;
|
||||
|
||||
// texturecolumn = 0; // shut up compiler warning
|
||||
|
||||
for ( ; rw_x < rw_stopx ; rw_x++)
|
||||
{
|
||||
//
|
||||
// mark floor / ceiling areas
|
||||
//
|
||||
yl = (topfrac+HEIGHTUNIT-1)>>HEIGHTBITS;
|
||||
if (yl < ceilingclip[rw_x]+1)
|
||||
yl = ceilingclip[rw_x]+1; // no space above wall
|
||||
if (markceiling)
|
||||
{
|
||||
top = ceilingclip[rw_x]+1;
|
||||
bottom = yl-1;
|
||||
if (bottom >= floorclip[rw_x])
|
||||
bottom = floorclip[rw_x]-1;
|
||||
if (top <= bottom)
|
||||
{
|
||||
ceilingplane->top[rw_x] = top;
|
||||
ceilingplane->bottom[rw_x] = bottom;
|
||||
}
|
||||
}
|
||||
|
||||
yh = bottomfrac>>HEIGHTBITS;
|
||||
if (yh >= floorclip[rw_x])
|
||||
yh = floorclip[rw_x]-1;
|
||||
if (markfloor)
|
||||
{
|
||||
top = yh+1;
|
||||
bottom = floorclip[rw_x]-1;
|
||||
if (top <= ceilingclip[rw_x])
|
||||
top = ceilingclip[rw_x]+1;
|
||||
if (top <= bottom)
|
||||
{
|
||||
floorplane->top[rw_x] = top;
|
||||
floorplane->bottom[rw_x] = bottom;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// texturecolumn and lighting are independent of wall tiers
|
||||
//
|
||||
if (segtextured)
|
||||
{
|
||||
// calculate texture offset
|
||||
angle = (rw_centerangle + xtoviewangle[rw_x])>>ANGLETOFINESHIFT;
|
||||
texturecolumn = rw_offset-FixedMul(finetangent[angle],rw_distance);
|
||||
texturecolumn >>= FRACBITS;
|
||||
// calculate lighting
|
||||
index = rw_scale>>LIGHTSCALESHIFT;
|
||||
if (index >= MAXLIGHTSCALE )
|
||||
index = MAXLIGHTSCALE-1;
|
||||
dc_colormap = walllights[index];
|
||||
dc_x = rw_x;
|
||||
dc_iscale = 0xffffffffu / (unsigned)rw_scale;
|
||||
}
|
||||
|
||||
//
|
||||
// draw the wall tiers
|
||||
//
|
||||
if (midtexture)
|
||||
{ // single sided line
|
||||
dc_yl = yl;
|
||||
dc_yh = yh;
|
||||
dc_texturemid = rw_midtexturemid;
|
||||
dc_source = R_GetColumn(midtexture,texturecolumn);
|
||||
colfunc ();
|
||||
ceilingclip[rw_x] = viewheight;
|
||||
floorclip[rw_x] = -1;
|
||||
}
|
||||
else
|
||||
{ // two sided line
|
||||
if (toptexture)
|
||||
{ // top wall
|
||||
mid = pixhigh>>HEIGHTBITS;
|
||||
pixhigh += pixhighstep;
|
||||
if (mid >= floorclip[rw_x])
|
||||
mid = floorclip[rw_x]-1;
|
||||
if (mid >= yl)
|
||||
{
|
||||
dc_yl = yl;
|
||||
dc_yh = mid;
|
||||
dc_texturemid = rw_toptexturemid;
|
||||
dc_source = R_GetColumn(toptexture,texturecolumn);
|
||||
colfunc ();
|
||||
ceilingclip[rw_x] = mid;
|
||||
}
|
||||
else
|
||||
ceilingclip[rw_x] = yl-1;
|
||||
}
|
||||
else
|
||||
{ // no top wall
|
||||
if (markceiling)
|
||||
ceilingclip[rw_x] = yl-1;
|
||||
}
|
||||
|
||||
if (bottomtexture)
|
||||
{ // bottom wall
|
||||
mid = (pixlow+HEIGHTUNIT-1)>>HEIGHTBITS;
|
||||
pixlow += pixlowstep;
|
||||
if (mid <= ceilingclip[rw_x])
|
||||
mid = ceilingclip[rw_x]+1; // no space above wall
|
||||
if (mid <= yh)
|
||||
{
|
||||
dc_yl = mid;
|
||||
dc_yh = yh;
|
||||
dc_texturemid = rw_bottomtexturemid;
|
||||
dc_source = R_GetColumn(bottomtexture,
|
||||
texturecolumn);
|
||||
colfunc ();
|
||||
floorclip[rw_x] = mid;
|
||||
}
|
||||
else
|
||||
floorclip[rw_x] = yh+1;
|
||||
}
|
||||
else
|
||||
{ // no bottom wall
|
||||
if (markfloor)
|
||||
floorclip[rw_x] = yh+1;
|
||||
}
|
||||
|
||||
if (maskedtexture)
|
||||
{ // save texturecol for backdrawing of masked mid texture
|
||||
maskedtexturecol[rw_x] = texturecolumn;
|
||||
}
|
||||
}
|
||||
|
||||
rw_scale += rw_scalestep;
|
||||
topfrac += topstep;
|
||||
bottomfrac += bottomstep;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
=====================
|
||||
=
|
||||
= R_StoreWallRange
|
||||
=
|
||||
= A wall segment will be drawn between start and stop pixels (inclusive)
|
||||
=
|
||||
======================
|
||||
*/
|
||||
|
||||
void R_StoreWallRange (int start, int stop)
|
||||
{
|
||||
fixed_t hyp;
|
||||
fixed_t sineval;
|
||||
angle_t distangle, offsetangle;
|
||||
fixed_t vtop;
|
||||
int lightnum;
|
||||
|
||||
if (ds_p == &drawsegs[MAXDRAWSEGS])
|
||||
return; // don't overflow and crash
|
||||
|
||||
#ifdef RANGECHECK
|
||||
if (start >=viewwidth || start > stop)
|
||||
I_Error ("Bad R_RenderWallRange: %i to %i", start , stop);
|
||||
#endif
|
||||
#ifdef __NeXT__
|
||||
RD_DrawLine (curline);
|
||||
#endif
|
||||
|
||||
sidedef = curline->sidedef;
|
||||
linedef = curline->linedef;
|
||||
|
||||
// mark the segment as visible for auto map
|
||||
linedef->flags |= ML_MAPPED;
|
||||
|
||||
//
|
||||
// calculate rw_distance for scale calculation
|
||||
//
|
||||
rw_normalangle = curline->angle + ANG90;
|
||||
offsetangle = abs(rw_normalangle-rw_angle1);
|
||||
if (offsetangle > ANG90)
|
||||
offsetangle = ANG90;
|
||||
distangle = ANG90 - offsetangle;
|
||||
hyp = R_PointToDist (curline->v1->x, curline->v1->y);
|
||||
sineval = finesine[distangle>>ANGLETOFINESHIFT];
|
||||
rw_distance = FixedMul (hyp, sineval);
|
||||
|
||||
|
||||
ds_p->x1 = rw_x = start;
|
||||
ds_p->x2 = stop;
|
||||
ds_p->curline = curline;
|
||||
rw_stopx = stop+1;
|
||||
|
||||
//
|
||||
// calculate scale at both ends and step
|
||||
//
|
||||
ds_p->scale1 = rw_scale =
|
||||
R_ScaleFromGlobalAngle (viewangle + xtoviewangle[start]);
|
||||
if (stop > start )
|
||||
{
|
||||
ds_p->scale2 = R_ScaleFromGlobalAngle (viewangle + xtoviewangle[stop]);
|
||||
ds_p->scalestep = rw_scalestep =
|
||||
(ds_p->scale2 - rw_scale) / (stop-start);
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// 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;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// calculate texture boundaries and decide if floor / ceiling marks
|
||||
// are needed
|
||||
//
|
||||
worldtop = frontsector->ceilingheight - viewz;
|
||||
worldbottom = frontsector->floorheight - viewz;
|
||||
|
||||
midtexture = toptexture = bottomtexture = maskedtexture = 0;
|
||||
ds_p->maskedtexturecol = NULL;
|
||||
|
||||
if (!backsector)
|
||||
{
|
||||
//
|
||||
// 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 +
|
||||
textureheight[sidedef->midtexture];
|
||||
rw_midtexturemid = vtop - viewz; // bottom of texture at bottom
|
||||
}
|
||||
else
|
||||
rw_midtexturemid = worldtop; // top of texture at top
|
||||
rw_midtexturemid += sidedef->rowoffset;
|
||||
ds_p->silhouette = SIL_BOTH;
|
||||
ds_p->sprtopclip = screenheightarray;
|
||||
ds_p->sprbottomclip = negonearray;
|
||||
ds_p->bsilheight = MAXINT;
|
||||
ds_p->tsilheight = MININT;
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// two sided line
|
||||
//
|
||||
ds_p->sprtopclip = ds_p->sprbottomclip = NULL;
|
||||
ds_p->silhouette = 0;
|
||||
if (frontsector->floorheight > backsector->floorheight)
|
||||
{
|
||||
ds_p->silhouette = SIL_BOTTOM;
|
||||
ds_p->bsilheight = frontsector->floorheight;
|
||||
}
|
||||
else if (backsector->floorheight > viewz)
|
||||
{
|
||||
ds_p->silhouette = SIL_BOTTOM;
|
||||
ds_p->bsilheight = MAXINT;
|
||||
// ds_p->sprbottomclip = negonearray;
|
||||
}
|
||||
if (frontsector->ceilingheight < backsector->ceilingheight)
|
||||
{
|
||||
ds_p->silhouette |= SIL_TOP;
|
||||
ds_p->tsilheight = frontsector->ceilingheight;
|
||||
}
|
||||
else if (backsector->ceilingheight < viewz)
|
||||
{
|
||||
ds_p->silhouette |= SIL_TOP;
|
||||
ds_p->tsilheight = MININT;
|
||||
// ds_p->sprtopclip = screenheightarray;
|
||||
}
|
||||
|
||||
if (backsector->ceilingheight <= frontsector->floorheight)
|
||||
{
|
||||
ds_p->sprbottomclip = negonearray;
|
||||
ds_p->bsilheight = MAXINT;
|
||||
ds_p->silhouette |= SIL_BOTTOM;
|
||||
}
|
||||
if (backsector->floorheight >= frontsector->ceilingheight)
|
||||
{
|
||||
ds_p->sprtopclip = screenheightarray;
|
||||
ds_p->tsilheight = MININT;
|
||||
ds_p->silhouette |= SIL_TOP;
|
||||
}
|
||||
worldhigh = backsector->ceilingheight - viewz;
|
||||
worldlow = backsector->floorheight - viewz;
|
||||
|
||||
// hack to allow height changes in outdoor areas
|
||||
if (frontsector->ceilingpic == skyflatnum
|
||||
&& backsector->ceilingpic == skyflatnum)
|
||||
worldtop = worldhigh;
|
||||
|
||||
if (worldlow != worldbottom
|
||||
|| backsector->floorpic != frontsector->floorpic
|
||||
|| backsector->lightlevel != frontsector->lightlevel)
|
||||
markfloor = true;
|
||||
else
|
||||
markfloor = false; // same plane on both sides
|
||||
|
||||
if (worldhigh != worldtop
|
||||
|| backsector->ceilingpic != frontsector->ceilingpic
|
||||
|| backsector->lightlevel != frontsector->lightlevel)
|
||||
markceiling = true;
|
||||
else
|
||||
markceiling = false; // same plane on both sides
|
||||
|
||||
if (backsector->ceilingheight <= frontsector->floorheight
|
||||
|| backsector->floorheight >= frontsector->ceilingheight)
|
||||
markceiling = markfloor = true; // closed door
|
||||
|
||||
if (worldhigh < worldtop)
|
||||
{ // top texture
|
||||
toptexture = texturetranslation[sidedef->toptexture];
|
||||
if (linedef->flags & ML_DONTPEGTOP)
|
||||
rw_toptexturemid = worldtop; // top of texture at top
|
||||
else
|
||||
{
|
||||
vtop = backsector->ceilingheight +
|
||||
textureheight[sidedef->toptexture];
|
||||
rw_toptexturemid = vtop - viewz; // bottom of texture
|
||||
}
|
||||
}
|
||||
if (worldlow > worldbottom)
|
||||
{ // bottom texture
|
||||
bottomtexture = texturetranslation[sidedef->bottomtexture];
|
||||
if (linedef->flags & ML_DONTPEGBOTTOM )
|
||||
{ // bottom of texture at bottom
|
||||
rw_bottomtexturemid = worldtop;// top of texture at top
|
||||
}
|
||||
else // top of texture at top
|
||||
rw_bottomtexturemid = worldlow;
|
||||
}
|
||||
rw_toptexturemid += sidedef->rowoffset;
|
||||
rw_bottomtexturemid += sidedef->rowoffset;
|
||||
|
||||
//
|
||||
// allocate space for masked texture tables
|
||||
//
|
||||
if (sidedef->midtexture)
|
||||
{ // masked midtexture
|
||||
maskedtexture = true;
|
||||
ds_p->maskedtexturecol = maskedtexturecol = lastopening - rw_x;
|
||||
lastopening += rw_stopx - rw_x;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// calculate rw_offset (only needed for textured lines)
|
||||
//
|
||||
segtextured = midtexture | toptexture | bottomtexture | maskedtexture;
|
||||
|
||||
if (segtextured)
|
||||
{
|
||||
offsetangle = rw_normalangle-rw_angle1;
|
||||
if (offsetangle > ANG180)
|
||||
offsetangle = -offsetangle;
|
||||
if (offsetangle > ANG90)
|
||||
offsetangle = ANG90;
|
||||
sineval = finesine[offsetangle >>ANGLETOFINESHIFT];
|
||||
rw_offset = FixedMul (hyp, sineval);
|
||||
if (rw_normalangle-rw_angle1 < ANG180)
|
||||
rw_offset = -rw_offset;
|
||||
rw_offset += sidedef->textureoffset + curline->offset;
|
||||
rw_centerangle = ANG90 + viewangle - rw_normalangle;
|
||||
|
||||
//
|
||||
// calculate light table
|
||||
// use different light tables for horizontal / vertical / diagonal
|
||||
// OPTIMIZE: get rid of LIGHTSEGSHIFT globally
|
||||
if (!fixedcolormap)
|
||||
{
|
||||
lightnum = (frontsector->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];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// if a floor / ceiling plane is on the wrong side of the view plane
|
||||
// it is definately invisible and doesn't need to be marked
|
||||
//
|
||||
if (frontsector->floorheight >= viewz)
|
||||
markfloor = false; // above view plane
|
||||
if (frontsector->ceilingheight <= viewz
|
||||
&& frontsector->ceilingpic != skyflatnum)
|
||||
markceiling = false; // below view plane
|
||||
|
||||
//
|
||||
// calculate incremental stepping values for texture edges
|
||||
//
|
||||
worldtop >>= 4;
|
||||
worldbottom >>= 4;
|
||||
|
||||
topstep = -FixedMul (rw_scalestep, worldtop);
|
||||
topfrac = (centeryfrac>>4) - FixedMul (worldtop, rw_scale);
|
||||
|
||||
bottomstep = -FixedMul (rw_scalestep,worldbottom);
|
||||
bottomfrac = (centeryfrac>>4) - FixedMul (worldbottom, rw_scale);
|
||||
|
||||
if (backsector)
|
||||
{
|
||||
worldhigh >>= 4;
|
||||
worldlow >>= 4;
|
||||
|
||||
if (worldhigh < worldtop)
|
||||
{
|
||||
pixhigh = (centeryfrac>>4) - FixedMul (worldhigh, rw_scale);
|
||||
pixhighstep = -FixedMul (rw_scalestep,worldhigh);
|
||||
}
|
||||
if (worldlow > worldbottom)
|
||||
{
|
||||
pixlow = (centeryfrac>>4) - FixedMul (worldlow, rw_scale);
|
||||
pixlowstep = -FixedMul (rw_scalestep,worldlow);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// render it
|
||||
//
|
||||
if (markceiling)
|
||||
ceilingplane = R_CheckPlane (ceilingplane, rw_x, rw_stopx-1);
|
||||
if (markfloor)
|
||||
floorplane = R_CheckPlane (floorplane, rw_x, rw_stopx-1);
|
||||
|
||||
R_RenderSegLoop ();
|
||||
|
||||
//
|
||||
// save sprite clipping info
|
||||
//
|
||||
if ( ((ds_p->silhouette & SIL_TOP) || maskedtexture) && !ds_p->sprtopclip)
|
||||
{
|
||||
memcpy (lastopening, ceilingclip+start, 2*(rw_stopx-start));
|
||||
ds_p->sprtopclip = lastopening - start;
|
||||
lastopening += rw_stopx - start;
|
||||
}
|
||||
if ( ((ds_p->silhouette & SIL_BOTTOM) || maskedtexture) && !ds_p->sprbottomclip)
|
||||
{
|
||||
memcpy (lastopening, floorclip+start, 2*(rw_stopx-start));
|
||||
ds_p->sprbottomclip = lastopening - start;
|
||||
lastopening += rw_stopx - start;
|
||||
}
|
||||
if (maskedtexture && !(ds_p->silhouette&SIL_TOP))
|
||||
{
|
||||
ds_p->silhouette |= SIL_TOP;
|
||||
ds_p->tsilheight = MININT;
|
||||
}
|
||||
if (maskedtexture && !(ds_p->silhouette&SIL_BOTTOM))
|
||||
{
|
||||
ds_p->silhouette |= SIL_BOTTOM;
|
||||
ds_p->bsilheight = MAXINT;
|
||||
}
|
||||
ds_p++;
|
||||
}
|
||||
|
992
Heretic Source/R_THINGS.C
Normal file
992
Heretic Source/R_THINGS.C
Normal file
|
@ -0,0 +1,992 @@
|
|||
// R_things.c
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "DoomDef.h"
|
||||
#include "R_local.h"
|
||||
|
||||
void R_DrawColumn (void);
|
||||
void R_DrawFuzzColumn (void);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int x1, x2;
|
||||
|
||||
int column;
|
||||
int topclip;
|
||||
int bottomclip;
|
||||
} maskdraw_t;
|
||||
|
||||
/*
|
||||
|
||||
Sprite rotation 0 is facing the viewer, rotation 1 is one angle turn CLOCKWISE around the axis.
|
||||
This is not the same as the angle, which increases counter clockwise
|
||||
(protractor). There was a lot of stuff grabbed wrong, so I changed it...
|
||||
|
||||
*/
|
||||
|
||||
|
||||
fixed_t pspritescale, pspriteiscale;
|
||||
|
||||
lighttable_t **spritelights;
|
||||
|
||||
// constant arrays used for psprite clipping and initializing clipping
|
||||
short negonearray[SCREENWIDTH];
|
||||
short screenheightarray[SCREENWIDTH];
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
|
||||
INITIALIZATION FUNCTIONS
|
||||
|
||||
===============================================================================
|
||||
*/
|
||||
|
||||
// variables used to look up and range check thing_t sprites patches
|
||||
spritedef_t *sprites;
|
||||
int numsprites;
|
||||
|
||||
spriteframe_t sprtemp[26];
|
||||
int maxframe;
|
||||
char *spritename;
|
||||
|
||||
|
||||
|
||||
/*
|
||||
=================
|
||||
=
|
||||
= R_InstallSpriteLump
|
||||
=
|
||||
= Local function for R_InitSprites
|
||||
=================
|
||||
*/
|
||||
|
||||
void R_InstallSpriteLump (int lump, unsigned frame, unsigned rotation, boolean flipped)
|
||||
{
|
||||
int r;
|
||||
|
||||
if (frame >= 26 || rotation > 8)
|
||||
I_Error ("R_InstallSpriteLump: Bad frame characters in lump %i", lump);
|
||||
|
||||
if ((int)frame > maxframe)
|
||||
maxframe = frame;
|
||||
|
||||
if (rotation == 0)
|
||||
{
|
||||
// the lump should be used for all rotations
|
||||
if (sprtemp[frame].rotate == false)
|
||||
I_Error ("R_InitSprites: Sprite %s frame %c has multip rot=0 lump"
|
||||
, spritename, 'A'+frame);
|
||||
if (sprtemp[frame].rotate == true)
|
||||
I_Error ("R_InitSprites: Sprite %s frame %c has rotations and a rot=0 lump"
|
||||
, spritename, 'A'+frame);
|
||||
|
||||
sprtemp[frame].rotate = false;
|
||||
for (r=0 ; r<8 ; r++)
|
||||
{
|
||||
sprtemp[frame].lump[r] = lump - firstspritelump;
|
||||
sprtemp[frame].flip[r] = (byte)flipped;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// the lump is only used for one rotation
|
||||
if (sprtemp[frame].rotate == false)
|
||||
I_Error ("R_InitSprites: Sprite %s frame %c has rotations and a rot=0 lump"
|
||||
, spritename, 'A'+frame);
|
||||
|
||||
sprtemp[frame].rotate = true;
|
||||
|
||||
rotation--; // make 0 based
|
||||
if (sprtemp[frame].lump[rotation] != -1)
|
||||
I_Error ("R_InitSprites: Sprite %s : %c : %c has two lumps mapped to it"
|
||||
,spritename, 'A'+frame, '1'+rotation);
|
||||
|
||||
sprtemp[frame].lump[rotation] = lump - firstspritelump;
|
||||
sprtemp[frame].flip[rotation] = (byte)flipped;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
=
|
||||
= R_InitSpriteDefs
|
||||
=
|
||||
= Pass a null terminated list of sprite names (4 chars exactly) to be used
|
||||
= Builds the sprite rotation matrixes to account for horizontally flipped
|
||||
= sprites. Will report an error if the lumps are inconsistant
|
||||
=
Only called at startup
|
||||
=
|
||||
= Sprite lump names are 4 characters for the actor, a letter for the frame,
|
||||
= and a number for the rotation, A sprite that is flippable will have an
|
||||
= additional letter/number appended. The rotation character can be 0 to
|
||||
= signify no rotations
|
||||
=================
|
||||
*/
|
||||
|
||||
void R_InitSpriteDefs (char **namelist)
|
||||
{
|
||||
char **check;
|
||||
int i, l, intname, frame, rotation;
|
||||
int start, end;
|
||||
|
||||
// count the number of sprite names
|
||||
check = namelist;
|
||||
while (*check != NULL)
|
||||
check++;
|
||||
numsprites = check-namelist;
|
||||
|
||||
if (!numsprites)
|
||||
return;
|
||||
|
||||
sprites = Z_Malloc(numsprites *sizeof(*sprites), PU_STATIC, NULL);
|
||||
|
||||
start = firstspritelump-1;
|
||||
end = lastspritelump+1;
|
||||
|
||||
// scan all the lump names for each of the names, noting the highest
|
||||
// frame letter
|
||||
// Just compare 4 characters as ints
|
||||
for (i=0 ; i<numsprites ; i++)
|
||||
{
|
||||
spritename = namelist[i];
|
||||
memset (sprtemp,-1, sizeof(sprtemp));
|
||||
|
||||
maxframe = -1;
|
||||
intname = *(int *)namelist[i];
|
||||
|
||||
//
|
||||
// scan the lumps, filling in the frames for whatever is found
|
||||
//
|
||||
for (l=start+1 ; l<end ; l++)
|
||||
if (*(int *)lumpinfo[l].name == intname)
|
||||
{
|
||||
frame = lumpinfo[l].name[4] - 'A';
|
||||
rotation = lumpinfo[l].name[5] - '0';
|
||||
R_InstallSpriteLump (l, frame, rotation, false);
|
||||
if (lumpinfo[l].name[6])
|
||||
{
|
||||
frame = lumpinfo[l].name[6] - 'A';
|
||||
rotation = lumpinfo[l].name[7] - '0';
|
||||
R_InstallSpriteLump (l, frame, rotation, true);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// check the frames that were found for completeness
|
||||
//
|
||||
if (maxframe == -1)
|
||||
{
|
||||
//continue;
|
||||
sprites[i].numframes = 0;
|
||||
if (shareware)
|
||||
continue;
|
||||
I_Error ("R_InitSprites: No lumps found for sprite %s"
|
||||
,namelist[i]);
|
||||
}
|
||||
|
||||
maxframe++;
|
||||
for (frame = 0 ; frame < maxframe ; frame++)
|
||||
{
|
||||
switch ((int)sprtemp[frame].rotate)
|
||||
{
|
||||
case -1: // no rotations were found for that frame at all
|
||||
I_Error ("R_InitSprites: No patches found for %s frame %c"
|
||||
, namelist[i], frame+'A');
|
||||
case 0: // only the first rotation is needed
|
||||
break;
|
||||
|
||||
case 1: // must have all 8 frames
|
||||
for (rotation=0 ; rotation<8 ; rotation++)
|
||||
if (sprtemp[frame].lump[rotation] == -1)
|
||||
I_Error ("R_InitSprites: Sprite %s frame %c is missing rotations"
|
||||
, namelist[i], frame+'A');
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// allocate space for the frames present and copy sprtemp to it
|
||||
//
|
||||
sprites[i].numframes = maxframe;
|
||||
sprites[i].spriteframes =
|
||||
Z_Malloc (maxframe * sizeof(spriteframe_t), PU_STATIC, NULL);
|
||||
memcpy (sprites[i].spriteframes, sprtemp, maxframe*sizeof(spriteframe_t));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
|
||||
GAME FUNCTIONS
|
||||
|
||||
===============================================================================
|
||||
*/
|
||||
|
||||
vissprite_t vissprites[MAXVISSPRITES], *vissprite_p;
|
||||
int newvissprite;
|
||||
|
||||
|
||||
/*
|
||||
===================
|
||||
=
|
||||
= R_InitSprites
|
||||
=
|
||||
= Called at program start
|
||||
===================
|
||||
*/
|
||||
|
||||
void R_InitSprites (char **namelist)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0 ; i<SCREENWIDTH ; i++)
|
||||
{
|
||||
negonearray[i] = -1;
|
||||
}
|
||||
|
||||
R_InitSpriteDefs (namelist);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===================
|
||||
=
|
||||
= R_ClearSprites
|
||||
=
|
||||
= Called at frame start
|
||||
===================
|
||||
*/
|
||||
|
||||
void R_ClearSprites (void)
|
||||
{
|
||||
vissprite_p = vissprites;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===================
|
||||
=
|
||||
= R_NewVisSprite
|
||||
=
|
||||
===================
|
||||
*/
|
||||
|
||||
vissprite_t overflowsprite;
|
||||
|
||||
vissprite_t *R_NewVisSprite (void)
|
||||
{
|
||||
if (vissprite_p == &vissprites[MAXVISSPRITES])
|
||||
return &overflowsprite;
|
||||
vissprite_p++;
|
||||
return vissprite_p-1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
=
|
||||
= R_DrawMaskedColumn
|
||||
=
|
||||
= Used for sprites and masked mid textures
|
||||
================
|
||||
*/
|
||||
|
||||
short *mfloorclip;
|
||||
short *mceilingclip;
|
||||
fixed_t spryscale;
|
||||
fixed_t sprtopscreen;
|
||||
fixed_t sprbotscreen;
|
||||
|
||||
void R_DrawMaskedColumn (column_t *column, signed int baseclip)
|
||||
{
|
||||
int topscreen, bottomscreen;
|
||||
fixed_t basetexturemid;
|
||||
|
||||
basetexturemid = dc_texturemid;
|
||||
|
||||
for ( ; column->topdelta != 0xff ; )
|
||||
{
|
||||
// calculate unclipped screen coordinates for post
|
||||
topscreen = sprtopscreen + spryscale*column->topdelta;
|
||||
bottomscreen = topscreen + spryscale*column->length;
|
||||
dc_yl = (topscreen+FRACUNIT-1)>>FRACBITS;
|
||||
dc_yh = (bottomscreen-1)>>FRACBITS;
|
||||
|
||||
if (dc_yh >= mfloorclip[dc_x])
|
||||
dc_yh = mfloorclip[dc_x]-1;
|
||||
if (dc_yl <= mceilingclip[dc_x])
|
||||
dc_yl = mceilingclip[dc_x]+1;
|
||||
|
||||
if(dc_yh >= baseclip && baseclip != -1)
|
||||
dc_yh = baseclip;
|
||||
|
||||
if (dc_yl <= dc_yh)
|
||||
{
|
||||
dc_source = (byte *)column + 3;
|
||||
dc_texturemid = basetexturemid - (column->topdelta<<FRACBITS);
|
||||
// dc_source = (byte *)column + 3 - column->topdelta;
|
||||
colfunc (); // either R_DrawColumn or R_DrawFuzzColumn
|
||||
}
|
||||
column = (column_t *)( (byte *)column + column->length + 4);
|
||||
}
|
||||
|
||||
dc_texturemid = basetexturemid;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
=
|
||||
= R_DrawVisSprite
|
||||
=
|
||||
= mfloorclip and mceilingclip should also be set
|
||||
================
|
||||
*/
|
||||
|
||||
void R_DrawVisSprite (vissprite_t *vis, int x1, int x2)
|
||||
{
|
||||
column_t *column;
|
||||
int texturecolumn;
|
||||
fixed_t frac;
|
||||
patch_t *patch;
|
||||
fixed_t baseclip;
|
||||
|
||||
|
||||
patch = W_CacheLumpNum(vis->patch+firstspritelump, PU_CACHE);
|
||||
|
||||
dc_colormap = vis->colormap;
|
||||
|
||||
// if(!dc_colormap)
|
||||
// colfunc = fuzzcolfunc; // NULL colormap = shadow draw
|
||||
|
||||
if(vis->mobjflags&MF_SHADOW)
|
||||
{
|
||||
if(vis->mobjflags&MF_TRANSLATION)
|
||||
{
|
||||
colfunc = R_DrawTranslatedFuzzColumn;
|
||||
dc_translation = translationtables - 256 +
|
||||
((vis->mobjflags & MF_TRANSLATION) >> (MF_TRANSSHIFT-8));
|
||||
}
|
||||
else
|
||||
{ // Draw using shadow column function
|
||||
colfunc = fuzzcolfunc;
|
||||
}
|
||||
}
|
||||
else if(vis->mobjflags&MF_TRANSLATION)
|
||||
{
|
||||
// Draw using translated column function
|
||||
colfunc = R_DrawTranslatedColumn;
|
||||
dc_translation = translationtables - 256 +
|
||||
( (vis->mobjflags & MF_TRANSLATION) >> (MF_TRANSSHIFT-8) );
|
||||
}
|
||||
|
||||
dc_iscale = abs(vis->xiscale)>>detailshift;
|
||||
dc_texturemid = vis->texturemid;
|
||||
frac = vis->startfrac;
|
||||
spryscale = vis->scale;
|
||||
|
||||
sprtopscreen = centeryfrac - FixedMul(dc_texturemid,spryscale);
|
||||
|
||||
// check to see if weapon is a vissprite
|
||||
if(vis->psprite)
|
||||
{
|
||||
dc_texturemid += FixedMul(((centery-viewheight/2)<<FRACBITS),
|
||||
vis->xiscale);
|
||||
sprtopscreen += (viewheight/2-centery)<<FRACBITS;
|
||||
}
|
||||
|
||||
if(vis->footclip && !vis->psprite)
|
||||
{
|
||||
sprbotscreen = sprtopscreen+FixedMul(patch->height<<FRACBITS,
|
||||
spryscale);
|
||||
baseclip = (sprbotscreen-FixedMul(vis->footclip<<FRACBITS,
|
||||
spryscale))>>FRACBITS;
|
||||
}
|
||||
else
|
||||
{
|
||||
baseclip = -1;
|
||||
}
|
||||
|
||||
for (dc_x=vis->x1 ; dc_x<=vis->x2 ; dc_x++, frac += vis->xiscale)
|
||||
{
|
||||
texturecolumn = frac>>FRACBITS;
|
||||
#ifdef RANGECHECK
|
||||
if (texturecolumn < 0 || texturecolumn >= SHORT(patch->width))
|
||||
I_Error ("R_DrawSpriteRange: bad texturecolumn");
|
||||
#endif
|
||||
column = (column_t *) ((byte *)patch +
|
||||
LONG(patch->columnofs[texturecolumn]));
|
||||
R_DrawMaskedColumn (column, baseclip);
|
||||
}
|
||||
|
||||
colfunc = basecolfunc;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
===================
|
||||
=
|
||||
= R_ProjectSprite
|
||||
=
|
||||
= Generates a vissprite for a thing if it might be visible
|
||||
=
|
||||
===================
|
||||
*/
|
||||
|
||||
void R_ProjectSprite (mobj_t *thing)
|
||||
{
|
||||
fixed_t trx,try;
|
||||
fixed_t gxt,gyt;
|
||||
fixed_t tx,tz;
|
||||
fixed_t xscale;
|
||||
int x1, x2;
|
||||
spritedef_t *sprdef;
|
||||
spriteframe_t *sprframe;
|
||||
int lump;
|
||||
unsigned rot;
|
||||
boolean flip;
|
||||
int index;
|
||||
vissprite_t *vis;
|
||||
angle_t ang;
|
||||
fixed_t iscale;
|
||||
|
||||
if(thing->flags2&MF2_DONTDRAW)
|
||||
{ // Never make a vissprite when MF2_DONTDRAW is flagged.
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// transform the origin point
|
||||
//
|
||||
trx = thing->x - viewx;
|
||||
try = thing->y - viewy;
|
||||
|
||||
gxt = FixedMul(trx,viewcos);
|
||||
gyt = -FixedMul(try,viewsin);
|
||||
tz = gxt-gyt;
|
||||
|
||||
if (tz < MINZ)
|
||||
return; // thing is behind view plane
|
||||
xscale = FixedDiv(projection, tz);
|
||||
|
||||
gxt = -FixedMul(trx,viewsin);
|
||||
gyt = FixedMul(try,viewcos);
|
||||
tx = -(gyt+gxt);
|
||||
|
||||
if (abs(tx)>(tz<<2))
|
||||
return; // too far off the side
|
||||
|
||||
//
|
||||
// decide which patch to use for sprite reletive to player
|
||||
//
|
||||
#ifdef RANGECHECK
|
||||
if ((unsigned)thing->sprite >= numsprites)
|
||||
I_Error ("R_ProjectSprite: invalid sprite number %i ",thing->sprite);
|
||||
#endif
|
||||
sprdef = &sprites[thing->sprite];
|
||||
#ifdef RANGECHECK
|
||||
if ( (thing->frame&FF_FRAMEMASK) >= sprdef->numframes )
|
||||
I_Error ("R_ProjectSprite: invalid sprite frame %i : %i "
|
||||
,thing->sprite, thing->frame);
|
||||
#endif
|
||||
sprframe = &sprdef->spriteframes[ thing->frame & FF_FRAMEMASK];
|
||||
|
||||
if (sprframe->rotate)
|
||||
{ // choose a different rotation based on player view
|
||||
ang = R_PointToAngle (thing->x, thing->y);
|
||||
rot = (ang-thing->angle+(unsigned)(ANG45/2)*9)>>29;
|
||||
lump = sprframe->lump[rot];
|
||||
flip = (boolean)sprframe->flip[rot];
|
||||
}
|
||||
else
|
||||
{ // use single rotation for all views
|
||||
lump = sprframe->lump[0];
|
||||
flip = (boolean)sprframe->flip[0];
|
||||
}
|
||||
|
||||
//
|
||||
// calculate edges of the shape
|
||||
//
|
||||
tx -= spriteoffset[lump];
|
||||
x1 = (centerxfrac + FixedMul (tx,xscale) ) >>FRACBITS;
|
||||
if (x1 > viewwidth)
|
||||
return; // off the right side
|
||||
tx += spritewidth[lump];
|
||||
x2 = ((centerxfrac + FixedMul (tx,xscale) ) >>FRACBITS) - 1;
|
||||
if (x2 < 0)
|
||||
return; // off the left side
|
||||
|
||||
|
||||
//
|
||||
// store information in a vissprite
|
||||
//
|
||||
vis = R_NewVisSprite ();
|
||||
vis->mobjflags = thing->flags;
|
||||
vis->psprite = false;
|
||||
vis->scale = xscale<<detailshift;
|
||||
vis->gx = thing->x;
|
||||
vis->gy = thing->y;
|
||||
vis->gz = thing->z;
|
||||
vis->gzt = thing->z + spritetopoffset[lump];
|
||||
|
||||
// foot clipping
|
||||
if(thing->flags2&MF2_FEETARECLIPPED
|
||||
&& thing->z <= thing->subsector->sector->floorheight)
|
||||
{
|
||||
vis->footclip = 10;
|
||||
}
|
||||
else vis->footclip = 0;
|
||||
vis->texturemid = vis->gzt - viewz - (vis->footclip<<FRACBITS);
|
||||
|
||||
vis->x1 = x1 < 0 ? 0 : x1;
|
||||
vis->x2 = x2 >= viewwidth ? viewwidth-1 : x2;
|
||||
iscale = FixedDiv (FRACUNIT, xscale);
|
||||
if (flip)
|
||||
{
|
||||
vis->startfrac = spritewidth[lump]-1;
|
||||
vis->xiscale = -iscale;
|
||||
}
|
||||
else
|
||||
{
|
||||
vis->startfrac = 0;
|
||||
vis->xiscale = iscale;
|
||||
}
|
||||
if (vis->x1 > x1)
|
||||
vis->startfrac += vis->xiscale*(vis->x1-x1);
|
||||
vis->patch = lump;
|
||||
//
|
||||
// get light level
|
||||
//
|
||||
|
||||
// if (thing->flags & MF_SHADOW)
|
||||
// vis->colormap = NULL; // shadow draw
|
||||
// else ...
|
||||
|
||||
if (fixedcolormap)
|
||||
vis->colormap = fixedcolormap; // fixed map
|
||||
else if (thing->frame & FF_FULLBRIGHT)
|
||||
vis->colormap = colormaps; // full bright
|
||||
else
|
||||
{ // diminished light
|
||||
index = xscale>>(LIGHTSCALESHIFT-detailshift);
|
||||
if (index >= MAXLIGHTSCALE)
|
||||
index = MAXLIGHTSCALE-1;
|
||||
vis->colormap = spritelights[index];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
========================
|
||||
=
|
||||
= R_AddSprites
|
||||
=
|
||||
========================
|
||||
*/
|
||||
|
||||
void R_AddSprites (sector_t *sec)
|
||||
{
|
||||
mobj_t *thing;
|
||||
int lightnum;
|
||||
|
||||
if (sec->validcount == validcount)
|
||||
return; // already added
|
||||
|
||||
sec->validcount = validcount;
|
||||
|
||||
lightnum = (sec->lightlevel >> LIGHTSEGSHIFT)+extralight;
|
||||
if (lightnum < 0)
|
||||
spritelights = scalelight[0];
|
||||
else if (lightnum >= LIGHTLEVELS)
|
||||
spritelights = scalelight[LIGHTLEVELS-1];
|
||||
else
|
||||
spritelights = scalelight[lightnum];
|
||||
|
||||
|
||||
for (thing = sec->thinglist ; thing ; thing = thing->snext)
|
||||
R_ProjectSprite (thing);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
========================
|
||||
=
|
||||
= R_DrawPSprite
|
||||
=
|
||||
========================
|
||||
*/
|
||||
|
||||
int PSpriteSY[NUMWEAPONS] =
|
||||
{
|
||||
0, // staff
|
||||
5*FRACUNIT, // goldwand
|
||||
15*FRACUNIT, // crossbow
|
||||
15*FRACUNIT, // blaster
|
||||
15*FRACUNIT, // skullrod
|
||||
15*FRACUNIT, // phoenix rod
|
||||
15*FRACUNIT, // mace
|
||||
15*FRACUNIT, // gauntlets
|
||||
15*FRACUNIT // beak
|
||||
};
|
||||
|
||||
void R_DrawPSprite (pspdef_t *psp)
|
||||
{
|
||||
fixed_t tx;
|
||||
int x1, x2;
|
||||
spritedef_t *sprdef;
|
||||
spriteframe_t *sprframe;
|
||||
int lump;
|
||||
boolean flip;
|
||||
vissprite_t *vis, avis;
|
||||
|
||||
int tempangle;
|
||||
|
||||
//
|
||||
// decide which patch to use
|
||||
//
|
||||
#ifdef RANGECHECK
|
||||
if ( (unsigned)psp->state->sprite >= numsprites)
|
||||
I_Error ("R_ProjectSprite: invalid sprite number %i "
|
||||
, psp->state->sprite);
|
||||
#endif
|
||||
sprdef = &sprites[psp->state->sprite];
|
||||
#ifdef RANGECHECK
|
||||
if ( (psp->state->frame & FF_FRAMEMASK) >= sprdef->numframes)
|
||||
I_Error ("R_ProjectSprite: invalid sprite frame %i : %i "
|
||||
, psp->state->sprite, psp->state->frame);
|
||||
#endif
|
||||
sprframe = &sprdef->spriteframes[ psp->state->frame & FF_FRAMEMASK ];
|
||||
|
||||
lump = sprframe->lump[0];
|
||||
flip = (boolean)sprframe->flip[0];
|
||||
|
||||
//
|
||||
// calculate edges of the shape
|
||||
//
|
||||
tx = psp->sx-160*FRACUNIT;
|
||||
|
||||
tx -= spriteoffset[lump];
|
||||
if(viewangleoffset)
|
||||
{
|
||||
tempangle = ((centerxfrac/1024)*(viewangleoffset>>ANGLETOFINESHIFT));
|
||||
}
|
||||
else
|
||||
{
|
||||
tempangle = 0;
|
||||
}
|
||||
x1 = (centerxfrac + FixedMul (tx,pspritescale)+tempangle ) >>FRACBITS;
|
||||
if (x1 > viewwidth)
|
||||
return; // off the right side
|
||||
tx += spritewidth[lump];
|
||||
x2 = ((centerxfrac + FixedMul (tx, pspritescale)+tempangle ) >>FRACBITS) - 1;
|
||||
if (x2 < 0)
|
||||
return; // off the left side
|
||||
|
||||
//
|
||||
// store information in a vissprite
|
||||
//
|
||||
vis = &avis;
|
||||
vis->mobjflags = 0;
|
||||
vis->psprite = true;
|
||||
vis->texturemid = (BASEYCENTER<<FRACBITS)+FRACUNIT/2-(psp->sy-spritetopoffset[lump]);
|
||||
if(viewheight == SCREENHEIGHT)
|
||||
{
|
||||
vis->texturemid -= PSpriteSY[players[consoleplayer].readyweapon];
|
||||
}
|
||||
vis->x1 = x1 < 0 ? 0 : x1;
|
||||
vis->x2 = x2 >= viewwidth ? viewwidth-1 : x2;
|
||||
vis->scale = pspritescale<<detailshift;
|
||||
if (flip)
|
||||
{
|
||||
vis->xiscale = -pspriteiscale;
|
||||
vis->startfrac = spritewidth[lump]-1;
|
||||
}
|
||||
else
|
||||
{
|
||||
vis->xiscale = pspriteiscale;
|
||||
vis->startfrac = 0;
|
||||
}
|
||||
if (vis->x1 > x1)
|
||||
vis->startfrac += vis->xiscale*(vis->x1-x1);
|
||||
vis->patch = lump;
|
||||
|
||||
if(viewplayer->powers[pw_invisibility] > 4*32 ||
|
||||
viewplayer->powers[pw_invisibility] & 8)
|
||||
{
|
||||
// Invisibility
|
||||
vis->colormap = spritelights[MAXLIGHTSCALE-1];
|
||||
vis->mobjflags |= MF_SHADOW;
|
||||
}
|
||||
else if(fixedcolormap)
|
||||
{
|
||||
// Fixed color
|
||||
vis->colormap = fixedcolormap;
|
||||
}
|
||||
else if(psp->state->frame & FF_FULLBRIGHT)
|
||||
{
|
||||
// Full bright
|
||||
vis->colormap = colormaps;
|
||||
}
|
||||
else
|
||||
{
|
||||
// local light
|
||||
vis->colormap = spritelights[MAXLIGHTSCALE-1];
|
||||
}
|
||||
R_DrawVisSprite(vis, vis->x1, vis->x2);
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
=
|
||||
= R_DrawPlayerSprites
|
||||
=
|
||||
========================
|
||||
*/
|
||||
|
||||
void R_DrawPlayerSprites (void)
|
||||
{
|
||||
int i, lightnum;
|
||||
pspdef_t *psp;
|
||||
|
||||
//
|
||||
// get light level
|
||||
//
|
||||
lightnum = (viewplayer->mo->subsector->sector->lightlevel >> LIGHTSEGSHIFT)
|
||||
+extralight;
|
||||
if (lightnum < 0)
|
||||
spritelights = scalelight[0];
|
||||
else if (lightnum >= LIGHTLEVELS)
|
||||
spritelights = scalelight[LIGHTLEVELS-1];
|
||||
else
|
||||
spritelights = scalelight[lightnum];
|
||||
//
|
||||
// clip to screen bounds
|
||||
//
|
||||
mfloorclip = screenheightarray;
|
||||
mceilingclip = negonearray;
|
||||
|
||||
//
|
||||
// add all active psprites
|
||||
//
|
||||
for (i=0, psp=viewplayer->psprites ; i<NUMPSPRITES ; i++,psp++)
|
||||
if (psp->state)
|
||||
R_DrawPSprite (psp);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
========================
|
||||
=
|
||||
= R_SortVisSprites
|
||||
=
|
||||
========================
|
||||
*/
|
||||
|
||||
vissprite_t vsprsortedhead;
|
||||
|
||||
void R_SortVisSprites (void)
|
||||
{
|
||||
int i, count;
|
||||
vissprite_t *ds, *best;
|
||||
vissprite_t unsorted;
|
||||
fixed_t bestscale;
|
||||
|
||||
count = vissprite_p - vissprites;
|
||||
|
||||
unsorted.next = unsorted.prev = &unsorted;
|
||||
if (!count)
|
||||
return;
|
||||
|
||||
for (ds=vissprites ; ds<vissprite_p ; ds++)
|
||||
{
|
||||
ds->next = ds+1;
|
||||
ds->prev = ds-1;
|
||||
}
|
||||
vissprites[0].prev = &unsorted;
|
||||
unsorted.next = &vissprites[0];
|
||||
(vissprite_p-1)->next = &unsorted;
|
||||
unsorted.prev = vissprite_p-1;
|
||||
|
||||
//
|
||||
// pull the vissprites out by scale
|
||||
//
|
||||
best = 0; // shut up the compiler warning
|
||||
vsprsortedhead.next = vsprsortedhead.prev = &vsprsortedhead;
|
||||
for (i=0 ; i<count ; i++)
|
||||
{
|
||||
bestscale = MAXINT;
|
||||
for (ds=unsorted.next ; ds!= &unsorted ; ds=ds->next)
|
||||
{
|
||||
if (ds->scale < bestscale)
|
||||
{
|
||||
bestscale = ds->scale;
|
||||
best = ds;
|
||||
}
|
||||
}
|
||||
best->next->prev = best->prev;
|
||||
best->prev->next = best->next;
|
||||
best->next = &vsprsortedhead;
|
||||
best->prev = vsprsortedhead.prev;
|
||||
vsprsortedhead.prev->next = best;
|
||||
vsprsortedhead.prev = best;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
========================
|
||||
=
|
||||
= R_DrawSprite
|
||||
=
|
||||
========================
|
||||
*/
|
||||
|
||||
void R_DrawSprite (vissprite_t *spr)
|
||||
{
|
||||
drawseg_t *ds;
|
||||
short clipbot[SCREENWIDTH], cliptop[SCREENWIDTH];
|
||||
int x, r1, r2;
|
||||
fixed_t scale, lowscale;
|
||||
int silhouette;
|
||||
|
||||
for (x = spr->x1 ; x<=spr->x2 ; x++)
|
||||
clipbot[x] = cliptop[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--)
|
||||
{
|
||||
//
|
||||
// determine if the drawseg obscures the sprite
|
||||
//
|
||||
if (ds->x1 > spr->x2 || ds->x2 < spr->x1 ||
|
||||
(!ds->silhouette && !ds->maskedtexturecol) )
|
||||
continue; // doesn't cover sprite
|
||||
|
||||
r1 = ds->x1 < spr->x1 ? spr->x1 : ds->x1;
|
||||
r2 = ds->x2 > spr->x2 ? spr->x2 : ds->x2;
|
||||
if (ds->scale1 > ds->scale2)
|
||||
{
|
||||
lowscale = ds->scale2;
|
||||
scale = ds->scale1;
|
||||
}
|
||||
else
|
||||
{
|
||||
lowscale = ds->scale1;
|
||||
scale = ds->scale2;
|
||||
}
|
||||
|
||||
if (scale < spr->scale || ( lowscale < spr->scale
|
||||
&& !R_PointOnSegSide (spr->gx, spr->gy, ds->curline) ) )
|
||||
{
|
||||
if (ds->maskedtexturecol) // masked mid texture
|
||||
R_RenderMaskedSegRange (ds, r1, r2);
|
||||
continue; // seg is behind sprite
|
||||
}
|
||||
|
||||
//
|
||||
// clip this piece of the sprite
|
||||
//
|
||||
silhouette = ds->silhouette;
|
||||
if (spr->gz >= ds->bsilheight)
|
||||
silhouette &= ~SIL_BOTTOM;
|
||||
if (spr->gzt <= ds->tsilheight)
|
||||
silhouette &= ~SIL_TOP;
|
||||
|
||||
if (silhouette == 1)
|
||||
{ // bottom sil
|
||||
for (x=r1 ; x<=r2 ; x++)
|
||||
if (clipbot[x] == -2)
|
||||
clipbot[x] = ds->sprbottomclip[x];
|
||||
}
|
||||
else if (silhouette == 2)
|
||||
{ // top sil
|
||||
for (x=r1 ; x<=r2 ; x++)
|
||||
if (cliptop[x] == -2)
|
||||
cliptop[x] = ds->sprtopclip[x];
|
||||
}
|
||||
else if (silhouette == 3)
|
||||
{ // both
|
||||
for (x=r1 ; x<=r2 ; x++)
|
||||
{
|
||||
if (clipbot[x] == -2)
|
||||
clipbot[x] = ds->sprbottomclip[x];
|
||||
if (cliptop[x] == -2)
|
||||
cliptop[x] = ds->sprtopclip[x];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
// all clipping has been performed, so draw the sprite
|
||||
//
|
||||
|
||||
// check for unclipped columns
|
||||
for (x = spr->x1 ; x<=spr->x2 ; x++)
|
||||
{
|
||||
if (clipbot[x] == -2)
|
||||
clipbot[x] = viewheight;
|
||||
if (cliptop[x] == -2)
|
||||
cliptop[x] = -1;
|
||||
}
|
||||
|
||||
mfloorclip = clipbot;
|
||||
mceilingclip = cliptop;
|
||||
R_DrawVisSprite (spr, spr->x1, spr->x2);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
========================
|
||||
=
|
||||
= R_DrawMasked
|
||||
=
|
||||
========================
|
||||
*/
|
||||
|
||||
void R_DrawMasked (void)
|
||||
{
|
||||
vissprite_t *spr;
|
||||
drawseg_t *ds;
|
||||
|
||||
R_SortVisSprites ();
|
||||
|
||||
if (vissprite_p > vissprites)
|
||||
{
|
||||
// draw all vissprites back to front
|
||||
|
||||
for (spr = vsprsortedhead.next ; spr != &vsprsortedhead
|
||||
; spr=spr->next)
|
||||
R_DrawSprite (spr);
|
||||
}
|
||||
|
||||
//
|
||||
// render any remaining masked mid textures
|
||||
//
|
||||
for (ds=ds_p-1 ; ds >= drawsegs ; ds--)
|
||||
if (ds->maskedtexturecol)
|
||||
R_RenderMaskedSegRange (ds, ds->x1, ds->x2);
|
||||
|
||||
//
|
||||
// draw the psprites on top of everything
|
||||
//
|
||||
// Added for the sideviewing with an external device
|
||||
if (viewangleoffset <= 1024<<ANGLETOFINESHIFT || viewangleoffset >=
|
||||
-1024<<ANGLETOFINESHIFT)
|
||||
{ // don't draw on side views
|
||||
R_DrawPlayerSprites ();
|
||||
}
|
||||
|
||||
// if (!viewangleoffset) // don't draw on side views
|
||||
// R_DrawPlayerSprites ();
|
||||
}
|
||||
|
||||
|
1456
Heretic Source/SB_BAR.C
Normal file
1456
Heretic Source/SB_BAR.C
Normal file
File diff suppressed because it is too large
Load diff
220
Heretic Source/SOUNDS.C
Normal file
220
Heretic Source/SOUNDS.C
Normal file
|
@ -0,0 +1,220 @@
|
|||
|
||||
|
||||
// sounds.c
|
||||
|
||||
#include "DoomDef.h"
|
||||
#include "sounds.h"
|
||||
|
||||
// Music info
|
||||
|
||||
musicinfo_t S_music[] =
|
||||
{
|
||||
{ "MUS_E1M1", 0 }, // 1-1
|
||||
{ "MUS_E1M2", 0 },
|
||||
{ "MUS_E1M3", 0 },
|
||||
{ "MUS_E1M4", 0 },
|
||||
{ "MUS_E1M5", 0 },
|
||||
{ "MUS_E1M6", 0 },
|
||||
{ "MUS_E1M7", 0 },
|
||||
{ "MUS_E1M8", 0 },
|
||||
{ "MUS_E1M9", 0 },
|
||||
|
||||
{ "MUS_E2M1", 0 }, // 2-1
|
||||
{ "MUS_E2M2", 0 },
|
||||
{ "MUS_E2M3", 0 },
|
||||
{ "MUS_E2M4", 0 },
|
||||
{ "MUS_E1M4", 0 },
|
||||
{ "MUS_E2M6", 0 },
|
||||
{ "MUS_E2M7", 0 },
|
||||
{ "MUS_E2M8", 0 },
|
||||
{ "MUS_E2M9", 0 },
|
||||
|
||||
{ "MUS_E1M1", 0 }, // 3-1
|
||||
{ "MUS_E3M2", 0 },
|
||||
{ "MUS_E3M3", 0 },
|
||||
{ "MUS_E1M6", 0 },
|
||||
{ "MUS_E1M3", 0 },
|
||||
{ "MUS_E1M2", 0 },
|
||||
{ "MUS_E1M5", 0 },
|
||||
{ "MUS_E1M9", 0 },
|
||||
{ "MUS_E2M6", 0 },
|
||||
|
||||
{ "MUS_E1M6", 0 }, // 4-1
|
||||
{ "MUS_E1M2", 0 },
|
||||
{ "MUS_E1M3", 0 },
|
||||
{ "MUS_E1M4", 0 },
|
||||
{ "MUS_E1M5", 0 },
|
||||
{ "MUS_E1M1", 0 },
|
||||
{ "MUS_E1M7", 0 },
|
||||
{ "MUS_E1M8", 0 },
|
||||
{ "MUS_E1M9", 0 },
|
||||
|
||||
{ "MUS_E2M1", 0 }, // 5-1
|
||||
{ "MUS_E2M2", 0 },
|
||||
{ "MUS_E2M3", 0 },
|
||||
{ "MUS_E2M4", 0 },
|
||||
{ "MUS_E1M4", 0 },
|
||||
{ "MUS_E2M6", 0 },
|
||||
{ "MUS_E2M7", 0 },
|
||||
{ "MUS_E2M8", 0 },
|
||||
{ "MUS_E2M9", 0 },
|
||||
|
||||
{ "MUS_E3M2", 0 }, // 6-1
|
||||
{ "MUS_E3M3", 0 }, // 6-2
|
||||
{ "MUS_E1M6", 0 }, // 6-3
|
||||
|
||||
{ "MUS_TITL", 0 },
|
||||
{ "MUS_INTR", 0 },
|
||||
{ "MUS_CPTD", 0 }
|
||||
};
|
||||
|
||||
// Sound info
|
||||
|
||||
sfxinfo_t S_sfx[] =
|
||||
{
|
||||
{ {0,0,0,0,0,0,0,0}, NULL, 0, -1, NULL, 0, 0 },
|
||||
{ "gldhit", NULL, 32, -1, NULL, 0, 2 },
|
||||
{ "gntful", NULL, 32, -1, NULL, 0, -1 },
|
||||
{ "gnthit", NULL, 32, -1, NULL, 0, -1 },
|
||||
{ "gntpow", NULL, 32, -1, NULL, 0, -1 },
|
||||
{ "gntact", NULL, 32, -1, NULL, 0, -1 },
|
||||
{ "gntuse", NULL, 32, -1, NULL, 0, -1 },
|
||||
{ "phosht", NULL, 32, -1, NULL, 0, 2 },
|
||||
{ "phohit", NULL, 32, -1, NULL, 0, -1 },
|
||||
{ "-phopow", &S_sfx[sfx_hedat1], 32, -1, NULL, 0, 1 },
|
||||
{ "lobsht", NULL, 20, -1, NULL, 0, 2 },
|
||||
{ "lobhit", NULL, 20, -1, NULL, 0, 2 },
|
||||
{ "lobpow", NULL, 20, -1, NULL, 0, 2 },
|
||||
{ "hrnsht", NULL, 32, -1, NULL, 0, 2 },
|
||||
{ "hrnhit", NULL, 32, -1, NULL, 0, 2 },
|
||||
{ "hrnpow", NULL, 32, -1, NULL, 0, 2 },
|
||||
{ "ramphit", NULL, 32, -1, NULL, 0, 2 },
|
||||
{ "ramrain", NULL, 10, -1, NULL, 0, 2 },
|
||||
{ "bowsht", NULL, 32, -1, NULL, 0, 2 },
|
||||
{ "stfhit", NULL, 32, -1, NULL, 0, 2 },
|
||||
{ "stfpow", NULL, 32, -1, NULL, 0, 2 },
|
||||
{ "stfcrk", NULL, 32, -1, NULL, 0, 2 },
|
||||
{ "impsit", NULL, 32, -1, NULL, 0, 2 },
|
||||
{ "impat1", NULL, 32, -1, NULL, 0, 2 },
|
||||
{ "impat2", NULL, 32, -1, NULL, 0, 2 },
|
||||
{ "impdth", NULL, 80, -1, NULL, 0, 2 },
|
||||
{ "-impact", &S_sfx[sfx_impsit], 20, -1, NULL, 0, 2 },
|
||||
{ "imppai", NULL, 32, -1, NULL, 0, 2 },
|
||||
{ "mumsit", NULL, 32, -1, NULL, 0, 2 },
|
||||
{ "mumat1", NULL, 32, -1, NULL, 0, 2 },
|
||||
{ "mumat2", NULL, 32, -1, NULL, 0, 2 },
|
||||
{ "mumdth", NULL, 80, -1, NULL, 0, 2 },
|
||||
{ "-mumact", &S_sfx[sfx_mumsit], 20, -1, NULL, 0, 2 },
|
||||
{ "mumpai", NULL, 32, -1, NULL, 0, 2 },
|
||||
{ "mumhed", NULL, 32, -1, NULL, 0, 2 },
|
||||
{ "bstsit", NULL, 32, -1, NULL, 0, 2 },
|
||||
{ "bstatk", NULL, 32, -1, NULL, 0, 2 },
|
||||
{ "bstdth", NULL, 80, -1, NULL, 0, 2 },
|
||||
{ "bstact", NULL, 20, -1, NULL, 0, 2 },
|
||||
{ "bstpai", NULL, 32, -1, NULL, 0, 2 },
|
||||
{ "clksit", NULL, 32, -1, NULL, 0, 2 },
|
||||
{ "clkatk", NULL, 32, -1, NULL, 0, 2 },
|
||||
{ "clkdth", NULL, 80, -1, NULL, 0, 2 },
|
||||
{ "clkact", NULL, 20, -1, NULL, 0, 2 },
|
||||
{ "clkpai", NULL, 32, -1, NULL, 0, 2 },
|
||||
{ "snksit", NULL, 32, -1, NULL, 0, 2 },
|
||||
{ "snkatk", NULL, 32, -1, NULL, 0, 2 },
|
||||
{ "snkdth", NULL, 80, -1, NULL, 0, 2 },
|
||||
{ "snkact", NULL, 20, -1, NULL, 0, 2 },
|
||||
{ "snkpai", NULL, 32, -1, NULL, 0, 2 },
|
||||
{ "kgtsit", NULL, 32, -1, NULL, 0, 2 },
|
||||
{ "kgtatk", NULL, 32, -1, NULL, 0, 2 },
|
||||
{ "kgtat2", NULL, 32, -1, NULL, 0, 2 },
|
||||
{ "kgtdth", NULL, 80, -1, NULL, 0, 2 },
|
||||
{ "-kgtact", &S_sfx[sfx_kgtsit], 20, -1, NULL, 0, 2 },
|
||||
{ "kgtpai", NULL, 32, -1, NULL, 0, 2 },
|
||||
{ "wizsit", NULL, 32, -1, NULL, 0, 2 },
|
||||
{ "wizatk", NULL, 32, -1, NULL, 0, 2 },
|
||||
{ "wizdth", NULL, 80, -1, NULL, 0, 2 },
|
||||
{ "wizact", NULL, 20, -1, NULL, 0, 2 },
|
||||
{ "wizpai", NULL, 32, -1, NULL, 0, 2 },
|
||||
{ "minsit", NULL, 32, -1, NULL, 0, 2 },
|
||||
{ "minat1", NULL, 32, -1, NULL, 0, 2 },
|
||||
{ "minat2", NULL, 32, -1, NULL, 0, 2 },
|
||||
{ "minat3", NULL, 32, -1, NULL, 0, 2 },
|
||||
{ "mindth", NULL, 80, -1, NULL, 0, 2 },
|
||||
{ "minact", NULL, 20, -1, NULL, 0, 2 },
|
||||
{ "minpai", NULL, 32, -1, NULL, 0, 2 },
|
||||
{ "hedsit", NULL, 32, -1, NULL, 0, 2 },
|
||||
{ "hedat1", NULL, 32, -1, NULL, 0, 2 },
|
||||
{ "hedat2", NULL, 32, -1, NULL, 0, 2 },
|
||||
{ "hedat3", NULL, 32, -1, NULL, 0, 2 },
|
||||
{ "heddth", NULL, 80, -1, NULL, 0, 2 },
|
||||
{ "hedact", NULL, 20, -1, NULL, 0, 2 },
|
||||
{ "hedpai", NULL, 32, -1, NULL, 0, 2 },
|
||||
{ "sorzap", NULL, 32, -1, NULL, 0, 2 },
|
||||
{ "sorrise", NULL, 32, -1, NULL, 0, 2 },
|
||||
{ "sorsit", NULL, 200, -1, NULL, 0, 2 },
|
||||
{ "soratk", NULL, 32, -1, NULL, 0, 2 },
|
||||
{ "soract", NULL, 200, -1, NULL, 0, 2 },
|
||||
{ "sorpai", NULL, 200, -1, NULL, 0, 2 },
|
||||
{ "sordsph", NULL, 200, -1, NULL, 0, 2 },
|
||||
{ "sordexp", NULL, 200, -1, NULL, 0, 2 },
|
||||
{ "sordbon", NULL, 200, -1, NULL, 0, 2 },
|
||||
{ "-sbtsit", &S_sfx[sfx_bstsit], 32, -1, NULL, 0, 2 },
|
||||
{ "-sbtatk", &S_sfx[sfx_bstatk], 32, -1, NULL, 0, 2 },
|
||||
{ "sbtdth", NULL, 80, -1, NULL, 0, 2 },
|
||||
{ "sbtact", NULL, 20, -1, NULL, 0, 2 },
|
||||
{ "sbtpai", NULL, 32, -1, NULL, 0, 2 },
|
||||
{ "plroof", NULL, 32, -1, NULL, 0, 2 },
|
||||
{ "plrpai", NULL, 32, -1, NULL, 0, 2 },
|
||||
{ "plrdth", NULL, 80, -1, NULL, 0, 2 },
|
||||
{ "gibdth", NULL, 100, -1, NULL, 0, 2 },
|
||||
{ "plrwdth", NULL, 80, -1, NULL, 0, 2 },
|
||||
{ "plrcdth", NULL, 100, -1, NULL, 0, 2 },
|
||||
{ "itemup", NULL, 32, -1, NULL, 0, 2 },
|
||||
{ "wpnup", NULL, 32, -1, NULL, 0, 2 },
|
||||
{ "telept", NULL, 50, -1, NULL, 0, 2 },
|
||||
{ "doropn", NULL, 40, -1, NULL, 0, 2 },
|
||||
{ "dorcls", NULL, 40, -1, NULL, 0, 2 },
|
||||
{ "dormov", NULL, 40, -1, NULL, 0, 2 },
|
||||
{ "artiup", NULL, 32, -1, NULL, 0, 2 },
|
||||
{ "switch", NULL, 40, -1, NULL, 0, 2 },
|
||||
{ "pstart", NULL, 40, -1, NULL, 0, 2 },
|
||||
{ "pstop", NULL, 40, -1, NULL, 0, 2 },
|
||||
{ "stnmov", NULL, 40, -1, NULL, 0, 2 },
|
||||
{ "chicpai", NULL, 32, -1, NULL, 0, 2 },
|
||||
{ "chicatk", NULL, 32, -1, NULL, 0, 2 },
|
||||
{ "chicdth", NULL, 40, -1, NULL, 0, 2 },
|
||||
{ "chicact", NULL, 32, -1, NULL, 0, 2 },
|
||||
{ "chicpk1", NULL, 32, -1, NULL, 0, 2 },
|
||||
{ "chicpk2", NULL, 32, -1, NULL, 0, 2 },
|
||||
{ "chicpk3", NULL, 32, -1, NULL, 0, 2 },
|
||||
{ "keyup", NULL, 50, -1, NULL, 0, 2 },
|
||||
{ "ripslop", NULL, 16, -1, NULL, 0, 2 },
|
||||
{ "newpod", NULL, 16, -1, NULL, 0, -1 },
|
||||
{ "podexp", NULL, 40, -1, NULL, 0, -1 },
|
||||
{ "bounce", NULL, 16, -1, NULL, 0, 2 },
|
||||
{ "-volsht", &S_sfx[sfx_bstatk], 16, -1, NULL, 0, 2 },
|
||||
{ "-volhit", &S_sfx[sfx_lobhit], 16, -1, NULL, 0, 2 },
|
||||
{ "burn", NULL, 10, -1, NULL, 0, 2 },
|
||||
{ "splash", NULL, 10, -1, NULL, 0, 1 },
|
||||
{ "gloop", NULL, 10, -1, NULL, 0, 2 },
|
||||
{ "respawn", NULL, 10, -1, NULL, 0, 1 },
|
||||
{ "blssht", NULL, 32, -1, NULL, 0, 2 },
|
||||
{ "blshit", NULL, 32, -1, NULL, 0, 2 },
|
||||
{ "chat", NULL, 100, -1, NULL, 0, 1 },
|
||||
{ "artiuse", NULL, 32, -1, NULL, 0, 1 },
|
||||
{ "gfrag", NULL, 100, -1, NULL, 0, 1 },
|
||||
{ "waterfl", NULL, 16, -1, NULL, 0, 2 },
|
||||
|
||||
// Monophonic sounds
|
||||
|
||||
{ "wind", NULL, 16, -1, NULL, 0, 1 },
|
||||
{ "amb1", NULL, 1, -1, NULL, 0, 1 },
|
||||
{ "amb2", NULL, 1, -1, NULL, 0, 1 },
|
||||
{ "amb3", NULL, 1, -1, NULL, 0, 1 },
|
||||
{ "amb4", NULL, 1, -1, NULL, 0, 1 },
|
||||
{ "amb5", NULL, 1, -1, NULL, 0, 1 },
|
||||
{ "amb6", NULL, 1, -1, NULL, 0, 1 },
|
||||
{ "amb7", NULL, 1, -1, NULL, 0, 1 },
|
||||
{ "amb8", NULL, 1, -1, NULL, 0, 1 },
|
||||
{ "amb9", NULL, 1, -1, NULL, 0, 1 },
|
||||
{ "amb10", NULL, 1, -1, NULL, 0, 1 },
|
||||
{ "amb11", NULL, 1, -1, NULL, 0, 0 }
|
||||
};
|
269
Heretic Source/SOUNDS.H
Normal file
269
Heretic Source/SOUNDS.H
Normal file
|
@ -0,0 +1,269 @@
|
|||
|
||||
// sounds.h
|
||||
|
||||
#ifndef __SOUNDSH__
|
||||
#define __SOUNDSH__
|
||||
|
||||
#define MAX_SND_DIST 1600
|
||||
#define MAX_CHANNELS 16
|
||||
|
||||
// Music identifiers
|
||||
|
||||
typedef enum
|
||||
{
|
||||
mus_e1m1,
|
||||
mus_e1m2,
|
||||
mus_e1m3,
|
||||
mus_e1m4,
|
||||
mus_e1m5,
|
||||
mus_e1m6,
|
||||
mus_e1m7,
|
||||
mus_e1m8,
|
||||
mus_e1m9,
|
||||
|
||||
mus_e2m1,
|
||||
mus_e2m2,
|
||||
mus_e2m3,
|
||||
mus_e2m4,
|
||||
mus_e2m5,
|
||||
mus_e2m6,
|
||||
mus_e2m7,
|
||||
mus_e2m8,
|
||||
mus_e2m9,
|
||||
|
||||
mus_e3m1,
|
||||
mus_e3m2,
|
||||
mus_e3m3,
|
||||
mus_e3m4,
|
||||
mus_e3m5,
|
||||
mus_e3m6,
|
||||
mus_e3m7,
|
||||
mus_e3m8,
|
||||
mus_e3m9,
|
||||
|
||||
mus_e4m1,
|
||||
mus_e4m2,
|
||||
mus_e4m3,
|
||||
mus_e4m4,
|
||||
mus_e4m5,
|
||||
mus_e4m6,
|
||||
mus_e4m7,
|
||||
mus_e4m8,
|
||||
mus_e4m9,
|
||||
|
||||
mus_e5m1,
|
||||
mus_e5m2,
|
||||
mus_e5m3,
|
||||
mus_e5m4,
|
||||
mus_e5m5,
|
||||
mus_e5m6,
|
||||
mus_e5m7,
|
||||
mus_e5m8,
|
||||
mus_e5m9,
|
||||
|
||||
mus_e6m1,
|
||||
mus_e6m2,
|
||||
mus_e6m3,
|
||||
|
||||
mus_titl,
|
||||
mus_intr,
|
||||
mus_cptd,
|
||||
NUMMUSIC
|
||||
} musicenum_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char name[8];
|
||||
int p1;
|
||||
} musicinfo_t;
|
||||
|
||||
typedef struct sfxinfo_s
|
||||
{
|
||||
char name[8];
|
||||
struct sfxinfo_s *link; // Make alias for another sound
|
||||
unsigned short priority; // Higher priority takes precendence
|
||||
int usefulness; // Determines when a sound should be cached out
|
||||
void *snd_ptr;
|
||||
int lumpnum;
|
||||
int numchannels; // total number of channels a sound type may occupy
|
||||
} sfxinfo_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
mobj_t *mo;
|
||||
long sound_id;
|
||||
long handle;
|
||||
long pitch;
|
||||
int priority;
|
||||
} channel_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
long id;
|
||||
unsigned short priority;
|
||||
char *name;
|
||||
mobj_t *mo;
|
||||
int distance;
|
||||
} ChanInfo_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int channelCount;
|
||||
int musicVolume;
|
||||
int soundVolume;
|
||||
ChanInfo_t chan[8];
|
||||
} SoundInfo_t;
|
||||
|
||||
// Sound identifiers
|
||||
|
||||
typedef enum
|
||||
{
|
||||
sfx_None,
|
||||
sfx_gldhit,
|
||||
sfx_gntful,
|
||||
sfx_gnthit,
|
||||
sfx_gntpow,
|
||||
sfx_gntact,
|
||||
sfx_gntuse,
|
||||
sfx_phosht,
|
||||
sfx_phohit,
|
||||
sfx_phopow,
|
||||
sfx_lobsht,
|
||||
sfx_lobhit,
|
||||
sfx_lobpow,
|
||||
sfx_hrnsht,
|
||||
sfx_hrnhit,
|
||||
sfx_hrnpow,
|
||||
sfx_ramphit,
|
||||
sfx_ramrain,
|
||||
sfx_bowsht,
|
||||
sfx_stfhit,
|
||||
sfx_stfpow,
|
||||
sfx_stfcrk,
|
||||
sfx_impsit,
|
||||
sfx_impat1,
|
||||
sfx_impat2,
|
||||
sfx_impdth,
|
||||
sfx_impact,
|
||||
sfx_imppai,
|
||||
sfx_mumsit,
|
||||
sfx_mumat1,
|
||||
sfx_mumat2,
|
||||
sfx_mumdth,
|
||||
sfx_mumact,
|
||||
sfx_mumpai,
|
||||
sfx_mumhed,
|
||||
sfx_bstsit,
|
||||
sfx_bstatk,
|
||||
sfx_bstdth,
|
||||
sfx_bstact,
|
||||
sfx_bstpai,
|
||||
sfx_clksit,
|
||||
sfx_clkatk,
|
||||
sfx_clkdth,
|
||||
sfx_clkact,
|
||||
sfx_clkpai,
|
||||
sfx_snksit,
|
||||
sfx_snkatk,
|
||||
sfx_snkdth,
|
||||
sfx_snkact,
|
||||
sfx_snkpai,
|
||||
sfx_kgtsit,
|
||||
sfx_kgtatk,
|
||||
sfx_kgtat2,
|
||||
sfx_kgtdth,
|
||||
sfx_kgtact,
|
||||
sfx_kgtpai,
|
||||
sfx_wizsit,
|
||||
sfx_wizatk,
|
||||
sfx_wizdth,
|
||||
sfx_wizact,
|
||||
sfx_wizpai,
|
||||
sfx_minsit,
|
||||
sfx_minat1,
|
||||
sfx_minat2,
|
||||
sfx_minat3,
|
||||
sfx_mindth,
|
||||
sfx_minact,
|
||||
sfx_minpai,
|
||||
sfx_hedsit,
|
||||
sfx_hedat1,
|
||||
sfx_hedat2,
|
||||
sfx_hedat3,
|
||||
sfx_heddth,
|
||||
sfx_hedact,
|
||||
sfx_hedpai,
|
||||
sfx_sorzap,
|
||||
sfx_sorrise,
|
||||
sfx_sorsit,
|
||||
sfx_soratk,
|
||||
sfx_soract,
|
||||
sfx_sorpai,
|
||||
sfx_sordsph,
|
||||
sfx_sordexp,
|
||||
sfx_sordbon,
|
||||
sfx_sbtsit,
|
||||
sfx_sbtatk,
|
||||
sfx_sbtdth,
|
||||
sfx_sbtact,
|
||||
sfx_sbtpai,
|
||||
sfx_plroof,
|
||||
sfx_plrpai,
|
||||
sfx_plrdth, // Normal
|
||||
sfx_gibdth, // Extreme
|
||||
sfx_plrwdth, // Wimpy
|
||||
sfx_plrcdth, // Crazy
|
||||
sfx_itemup,
|
||||
sfx_wpnup,
|
||||
sfx_telept,
|
||||
sfx_doropn,
|
||||
sfx_dorcls,
|
||||
sfx_dormov,
|
||||
sfx_artiup,
|
||||
sfx_switch,
|
||||
sfx_pstart,
|
||||
sfx_pstop,
|
||||
sfx_stnmov,
|
||||
sfx_chicpai,
|
||||
sfx_chicatk,
|
||||
sfx_chicdth,
|
||||
sfx_chicact,
|
||||
sfx_chicpk1,
|
||||
sfx_chicpk2,
|
||||
sfx_chicpk3,
|
||||
sfx_keyup,
|
||||
sfx_ripslop,
|
||||
sfx_newpod,
|
||||
sfx_podexp,
|
||||
sfx_bounce,
|
||||
sfx_volsht,
|
||||
sfx_volhit,
|
||||
sfx_burn,
|
||||
sfx_splash,
|
||||
sfx_gloop,
|
||||
sfx_respawn,
|
||||
sfx_blssht,
|
||||
sfx_blshit,
|
||||
sfx_chat,
|
||||
sfx_artiuse,
|
||||
sfx_gfrag,
|
||||
sfx_waterfl,
|
||||
|
||||
// Monophonic sounds
|
||||
|
||||
sfx_wind,
|
||||
sfx_amb1,
|
||||
sfx_amb2,
|
||||
sfx_amb3,
|
||||
sfx_amb4,
|
||||
sfx_amb5,
|
||||
sfx_amb6,
|
||||
sfx_amb7,
|
||||
sfx_amb8,
|
||||
sfx_amb9,
|
||||
sfx_amb10,
|
||||
sfx_amb11,
|
||||
NUMSFX
|
||||
} sfxenum_t;
|
||||
|
||||
#endif
|
23
Heretic Source/SOUNDST.H
Normal file
23
Heretic Source/SOUNDST.H
Normal file
|
@ -0,0 +1,23 @@
|
|||
|
||||
// soundst.h
|
||||
|
||||
#ifndef __SOUNDSTH__
|
||||
#define __SOUNDSTH__
|
||||
|
||||
extern int snd_MaxVolume;
|
||||
extern int snd_MusicVolume;
|
||||
|
||||
void S_Start(void);
|
||||
void S_StartSound(mobj_t *origin, int sound_id);
|
||||
void S_StartSoundAtVolume(mobj_t *origin, int sound_id, int volume);
|
||||
void S_StopSound(mobj_t *origin);
|
||||
void S_PauseSound(void);
|
||||
void S_ResumeSound(void);
|
||||
void S_UpdateSounds(mobj_t *listener);
|
||||
void S_StartSong(int song, boolean loop);
|
||||
void S_Init(void);
|
||||
void S_GetChannelInfo(SoundInfo_t *s);
|
||||
void S_SetMaxVolume(boolean fullprocess);
|
||||
void S_SetMusicVolume(void);
|
||||
|
||||
#endif
|
2062
Heretic Source/TABLES.C
Normal file
2062
Heretic Source/TABLES.C
Normal file
File diff suppressed because it is too large
Load diff
62
Heretic Source/TIC.LNK
Normal file
62
Heretic Source/TIC.LNK
Normal file
|
@ -0,0 +1,62 @@
|
|||
|
||||
# TIC.EXE Linker directive file
|
||||
|
||||
option quiet
|
||||
option map
|
||||
option stack=65536
|
||||
option stub=wstub
|
||||
debug all
|
||||
libpath %WATCOM%\lib386
|
||||
libpath %WATCOM%\lib386\dos
|
||||
lib noemu387.lib
|
||||
lib dmx
|
||||
format os2 le
|
||||
name tic
|
||||
|
||||
file i_cyber.obj
|
||||
file i_ibm.obj
|
||||
file i_ibm_a.obj
|
||||
file i_sound.obj
|
||||
file linear.obj
|
||||
|
||||
file am_map.obj
|
||||
file ct_chat.obj
|
||||
file d_main.obj
|
||||
file d_net.obj
|
||||
file g_game.obj
|
||||
file f_finale.obj
|
||||
file info.obj
|
||||
file in_lude.obj
|
||||
file mn_menu.obj
|
||||
file m_misc.obj
|
||||
file p_ceilng.obj
|
||||
file p_doors.obj
|
||||
file p_enemy.obj
|
||||
file p_floor.obj
|
||||
file p_inter.obj
|
||||
file p_lights.obj
|
||||
file p_map.obj
|
||||
file p_maputl.obj
|
||||
file p_mobj.obj
|
||||
file p_plats.obj
|
||||
file p_pspr.obj
|
||||
file p_setup.obj
|
||||
file p_sight.obj
|
||||
file p_spec.obj
|
||||
file p_switch.obj
|
||||
file p_telept.obj
|
||||
file p_tick.obj
|
||||
file p_user.obj
|
||||
file r_bsp.obj
|
||||
file r_data.obj
|
||||
file r_draw.obj
|
||||
file r_main.obj
|
||||
file r_plane.obj
|
||||
file r_segs.obj
|
||||
file r_things.obj
|
||||
file sb_bar.obj
|
||||
file sounds.obj
|
||||
file tables.obj
|
||||
file v_video.obj
|
||||
file w_wad.obj
|
||||
file z_zone.obj
|
2231
Heretic Source/TIC.MAP
Normal file
2231
Heretic Source/TIC.MAP
Normal file
File diff suppressed because it is too large
Load diff
BIN
Heretic Source/TINTTAB.LMP
Normal file
BIN
Heretic Source/TINTTAB.LMP
Normal file
Binary file not shown.
24
Heretic Source/VGAVIEW.H
Normal file
24
Heretic Source/VGAVIEW.H
Normal file
|
@ -0,0 +1,24 @@
|
|||
|
||||
#import <appkit/appkit.h>
|
||||
|
||||
#import "DoomDef.h"
|
||||
|
||||
// a few globals
|
||||
extern byte *bytebuffer;
|
||||
|
||||
|
||||
@interface VGAView:View
|
||||
{
|
||||
id game;
|
||||
int nextpalette[256]; // color lookup table
|
||||
int *nextimage; // palette expanded and scaled
|
||||
unsigned scale;
|
||||
NXWindowDepth depth;
|
||||
}
|
||||
|
||||
- updateView;
|
||||
- (unsigned)scale;
|
||||
- setPalette:(byte *)pal;
|
||||
- setScale:(int)newscale;
|
||||
|
||||
@end
|
200
Heretic Source/V_VIDEO.C
Normal file
200
Heretic Source/V_VIDEO.C
Normal file
|
@ -0,0 +1,200 @@
|
|||
|
||||
// V_video.c
|
||||
|
||||
#include "DoomDef.h"
|
||||
|
||||
#define SC_INDEX 0x3c4
|
||||
|
||||
byte *screen;
|
||||
int dirtybox[4];
|
||||
int usegamma;
|
||||
|
||||
byte gammatable[5][256] =
|
||||
{
|
||||
{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,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255},
|
||||
|
||||
{2,4,5,7,8,10,11,12,14,15,16,18,19,20,21,23,24,25,26,27,29,30,31,32,33,34,36,37,38,39,40,41,42,44,45,46,47,48,49,50,51,52,54,55,56,57,58,59,60,61,62,63,64,65,66,67,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,163,164,165,166,167,168,169,170,171,172,173,174,175,175,176,177,178,179,180,181,182,183,184,185,186,186,187,188,189,190,191,192,193,194,195,196,196,197,198,199,200,201,202,203,204,205,205,206,207,208,209,210,211,212,213,214,214,215,216,217,218,219,220,221,222,222,223,224,225,226,227,228,229,230,230,231,232,233,234,235,236,237,237,238,239,240,241,242,243,244,245,245,246,247,248,249,250,251,252,252,253,254,255},
|
||||
|
||||
{4,7,9,11,13,15,17,19,21,22,24,26,27,29,30,32,33,35,36,38,39,40,42,43,45,46,47,48,50,51,52,54,55,56,57,59,60,61,62,63,65,66,67,68,69,70,72,73,74,75,76,77,78,79,80,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,133,134,135,136,137,138,139,140,141,142,143,144,144,145,146,147,148,149,150,151,152,153,153,154,155,156,157,158,159,160,160,161,162,163,164,165,166,166,167,168,169,170,171,172,172,173,174,175,176,177,178,178,179,180,181,182,183,183,184,185,186,187,188,188,189,190,191,192,193,193,194,195,196,197,197,198,199,200,201,201,202,203,204,205,206,206,207,208,209,210,210,211,212,213,213,214,215,216,217,217,218,219,220,221,221,222,223,224,224,225,226,227,228,228,229,230,231,231,232,233,234,235,235,236,237,238,238,239,240,241,241,242,243,244,244,245,246,247,247,248,249,250,251,251,252,253,254,254,255},
|
||||
|
||||
{8,12,16,19,22,24,27,29,31,34,36,38,40,41,43,45,47,49,50,52,53,55,57,58,60,61,63,64,65,67,68,70,71,72,74,75,76,77,79,80,81,82,84,85,86,87,88,90,91,92,93,94,95,96,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,135,136,137,138,139,140,141,142,143,143,144,145,146,147,148,149,150,150,151,152,153,154,155,155,156,157,158,159,160,160,161,162,163,164,165,165,166,167,168,169,169,170,171,172,173,173,174,175,176,176,177,178,179,180,180,181,182,183,183,184,185,186,186,187,188,189,189,190,191,192,192,193,194,195,195,196,197,197,198,199,200,200,201,202,202,203,204,205,205,206,207,207,208,209,210,210,211,212,212,213,214,214,215,216,216,217,218,219,219,220,221,221,222,223,223,224,225,225,226,227,227,228,229,229,230,231,231,232,233,233,234,235,235,236,237,237,238,238,239,240,240,241,242,242,243,244,244,245,246,246,247,247,248,249,249,250,251,251,252,253,253,254,254,255},
|
||||
|
||||
{16,23,28,32,36,39,42,45,48,50,53,55,57,60,62,64,66,68,69,71,73,75,76,78,80,81,83,84,86,87,89,90,92,93,94,96,97,98,100,101,102,103,105,106,107,108,109,110,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,128,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,143,144,145,146,147,148,149,150,150,151,152,153,154,155,155,156,157,158,159,159,160,161,162,163,163,164,165,166,166,167,168,169,169,170,171,172,172,173,174,175,175,176,177,177,178,179,180,180,181,182,182,183,184,184,185,186,187,187,188,189,189,190,191,191,192,193,193,194,195,195,196,196,197,198,198,199,200,200,201,202,202,203,203,204,205,205,206,207,207,208,208,209,210,210,211,211,212,213,213,214,214,215,216,216,217,217,218,219,219,220,220,221,221,222,223,223,224,224,225,225,226,227,227,228,228,229,229,230,230,231,232,232,233,233,234,234,235,235,236,236,237,237,238,239,239,240,240,241,241,242,242,243,243,244,244,245,245,246,246,247,247,248,248,249,249,250,250,251,251,252,252,253,254,254,255,255}
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// PROC V_DrawPatch
|
||||
//
|
||||
// Draws a column based masked pic to the screen.
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void V_DrawPatch(int x, int y, patch_t *patch)
|
||||
{
|
||||
int count;
|
||||
int col;
|
||||
column_t *column;
|
||||
byte *desttop;
|
||||
byte *dest;
|
||||
byte *source;
|
||||
int w;
|
||||
|
||||
y -= SHORT(patch->topoffset);
|
||||
x -= SHORT(patch->leftoffset);
|
||||
if(x < 0 || x+SHORT(patch->width) > SCREENWIDTH || y < 0
|
||||
|| y+SHORT(patch->height) > SCREENHEIGHT)
|
||||
{
|
||||
I_Error("Bad V_DrawPatch");
|
||||
}
|
||||
col = 0;
|
||||
desttop = screen+y*SCREENWIDTH+x;
|
||||
w = SHORT(patch->width);
|
||||
for(; col < w; x++, col++, desttop++)
|
||||
{
|
||||
column = (column_t *)((byte *)patch+LONG(patch->columnofs[col]));
|
||||
// Step through the posts in a column
|
||||
while(column->topdelta != 0xff)
|
||||
{
|
||||
source = (byte *)column+3;
|
||||
dest = desttop+column->topdelta*SCREENWIDTH;
|
||||
count = column->length;
|
||||
while(count--)
|
||||
{
|
||||
*dest = *source++;
|
||||
dest += SCREENWIDTH;
|
||||
}
|
||||
column = (column_t *)((byte *)column+column->length+4);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
=
|
||||
= V_DrawFuzzPatch
|
||||
=
|
||||
= Masks a column based translucent masked pic to the screen.
|
||||
=
|
||||
==================
|
||||
*/
|
||||
extern byte *tinttable;
|
||||
|
||||
void V_DrawFuzzPatch (int x, int y, patch_t *patch)
|
||||
{
|
||||
int count,col;
|
||||
column_t *column;
|
||||
byte *desttop, *dest, *source;
|
||||
int w;
|
||||
|
||||
y -= SHORT(patch->topoffset);
|
||||
x -= SHORT(patch->leftoffset);
|
||||
|
||||
if (x<0||x+SHORT(patch->width) >SCREENWIDTH || y<0 || y+SHORT(patch->height)>SCREENHEIGHT
)
|
||||
I_Error ("Bad V_DrawPatch");
|
||||
|
||||
col = 0;
|
||||
desttop = screen+y*SCREENWIDTH+x;
|
||||
|
||||
w = SHORT(patch->width);
|
||||
for ( ; col<w ; x++, col++, desttop++)
|
||||
{
|
||||
column = (column_t *)((byte *)patch + LONG(patch->columnofs[col]));
|
||||
|
||||
// step through the posts in a column
|
||||
|
||||
while (column->topdelta != 0xff )
|
||||
{
|
||||
source = (byte *)column + 3;
|
||||
dest = desttop + column->topdelta*SCREENWIDTH;
|
||||
count = column->length;
|
||||
|
||||
while (count--)
|
||||
{
|
||||
*dest = tinttable[((*dest)<<8) + *source++];
|
||||
dest += SCREENWIDTH;
|
||||
}
|
||||
column = (column_t *)( (byte *)column + column->length
|
||||
+ 4 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
=
|
||||
= V_DrawShadowedPatch
|
||||
=
|
||||
= Masks a column based masked pic to the screen.
|
||||
=
|
||||
==================
|
||||
*/
|
||||
|
||||
void V_DrawShadowedPatch(int x, int y, patch_t *patch)
|
||||
{
|
||||
int count,col;
|
||||
column_t *column;
|
||||
byte *desttop, *dest, *source;
|
||||
byte *desttop2, *dest2;
|
||||
int w;
|
||||
|
||||
y -= SHORT(patch->topoffset);
|
||||
x -= SHORT(patch->leftoffset);
|
||||
|
||||
if (x<0||x+SHORT(patch->width) >SCREENWIDTH || y<0 || y+SHORT(patch->height)>SCREENHEIGHT
)
|
||||
I_Error ("Bad V_DrawPatch");
|
||||
|
||||
col = 0;
|
||||
desttop = screen+y*SCREENWIDTH+x;
|
||||
desttop2 = screen+(y+2)*SCREENWIDTH+x+2;
|
||||
|
||||
w = SHORT(patch->width);
|
||||
for ( ; col<w ; x++, col++, desttop++, desttop2++)
|
||||
{
|
||||
column = (column_t *)((byte *)patch + LONG(patch->columnofs[col]));
|
||||
|
||||
// step through the posts in a column
|
||||
|
||||
while (column->topdelta != 0xff )
|
||||
{
|
||||
source = (byte *)column + 3;
|
||||
dest = desttop + column->topdelta*SCREENWIDTH;
|
||||
dest2 = desttop2 + column->topdelta*SCREENWIDTH;
|
||||
count = column->length;
|
||||
|
||||
while (count--)
|
||||
{
|
||||
*dest2 = tinttable[((*dest2)<<8)];
|
||||
dest2 += SCREENWIDTH;
|
||||
*dest = *source++;
|
||||
dest += SCREENWIDTH;
|
||||
|
||||
}
|
||||
column = (column_t *)( (byte *)column + column->length
|
||||
+ 4 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// PROC V_DrawRawScreen
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void V_DrawRawScreen(byte *raw)
|
||||
{
|
||||
memcpy(screen, raw, SCREENWIDTH*SCREENHEIGHT);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// PROC V_Init
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void V_Init(void)
|
||||
{
|
||||
// I_AllocLow will put screen in low dos memory on PCs.
|
||||
screen = I_AllocLow(SCREENWIDTH*SCREENHEIGHT);
|
||||
}
|
319
Heretic Source/WADLINK.TXT
Normal file
319
Heretic Source/WADLINK.TXT
Normal file
|
@ -0,0 +1,319 @@
|
|||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// WADLINK.TXT
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
; WAD NAME
|
||||
|
||||
#ifdef EXTENDED
|
||||
; Extended version
|
||||
$WADNAME extended/heretic
|
||||
#elif defined(REGISTERED)
|
||||
; Registered version
|
||||
$WADNAME heretic
|
||||
#else
|
||||
; Shareware version
|
||||
$WADNAME heretic1
|
||||
#endif
|
||||
|
||||
#ifdef EXTENDED
|
||||
\data\extended.txt
|
||||
#endif
|
||||
|
||||
; PALETTES AND COLOR MAPS
|
||||
|
||||
\art\palette\playpal.lmp
|
||||
\art\palette\colormap.lmp
|
||||
\art\palette\tinttab.lmp
|
||||
|
||||
; DEMOS AND DOS SCREENS
|
||||
|
||||
\data\txtscr_s\loading.bin
|
||||
|
||||
#ifdef EXTENDED
|
||||
; Extended version
|
||||
$shootwad \art\screens\scrn_e.wad
|
||||
\data\txtscr_e\endtext.bin
|
||||
\data\demos_r\demo1.lmp
|
||||
\data\demos_r\demo2.lmp
|
||||
\data\demos_r\demo3.lmp
|
||||
#elif defined(REGISTERED)
|
||||
; Registered version
|
||||
$shootwad \art\screens\scrn_r.wad
|
||||
\data\txtscr_r\endtext.bin
|
||||
\data\demos_r\demo1.lmp
|
||||
\data\demos_r\demo2.lmp
|
||||
\data\demos_r\demo3.lmp
|
||||
#else
|
||||
; Shareware version
|
||||
$shootwad \art\screens\scrn_s.wad
|
||||
\data\txtscr_s\endtext.bin
|
||||
\data\demos_s\demo1.lmp
|
||||
\data\demos_s\demo2.lmp
|
||||
\data\demos_s\demo3.lmp
|
||||
#endif
|
||||
|
||||
; LEVEL MAPS
|
||||
|
||||
$shootwad \data\e1m1
|
||||
$shootwad \data\e1m2
|
||||
$shootwad \data\e1m3
|
||||
$shootwad \data\e1m4
|
||||
$shootwad \data\e1m5
|
||||
$shootwad \data\e1m6
|
||||
$shootwad \data\e1m7
|
||||
$shootwad \data\e1m8
|
||||
$shootwad \data\e1m9
|
||||
#ifdef REGISTERED
|
||||
$shootwad \data\e2m1
|
||||
$shootwad \data\e2m2
|
||||
$shootwad \data\e2m3
|
||||
$shootwad \data\e2m4
|
||||
$shootwad \data\e2m5
|
||||
$shootwad \data\e2m6
|
||||
$shootwad \data\e2m7
|
||||
$shootwad \data\e2m8
|
||||
$shootwad \data\e2m9
|
||||
$shootwad \data\e3m1
|
||||
$shootwad \data\e3m2
|
||||
$shootwad \data\e3m3
|
||||
$shootwad \data\e3m4
|
||||
$shootwad \data\e3m5
|
||||
$shootwad \data\e3m6
|
||||
$shootwad \data\e3m7
|
||||
$shootwad \data\e3m8
|
||||
$shootwad \data\e3m9
|
||||
#ifdef EXTENDED
|
||||
$shootwad \data\e4m1
|
||||
$shootwad \data\e4m2
|
||||
$shootwad \data\e4m3
|
||||
$shootwad \data\e4m4
|
||||
$shootwad \data\e4m5
|
||||
$shootwad \data\e4m6
|
||||
$shootwad \data\e4m7
|
||||
$shootwad \data\e4m8
|
||||
$shootwad \data\e4m9
|
||||
$shootwad \data\e5m1
|
||||
$shootwad \data\e5m2
|
||||
$shootwad \data\e5m3
|
||||
$shootwad \data\e5m4
|
||||
$shootwad \data\e5m5
|
||||
$shootwad \data\e5m6
|
||||
$shootwad \data\e5m7
|
||||
$shootwad \data\e5m8
|
||||
$shootwad \data\e5m9
|
||||
$shootwad \data\e6m1
|
||||
$shootwad \data\e6m2
|
||||
$shootwad \data\e6m3
|
||||
#else
|
||||
$shootwad \data\e4m1map
|
||||
#endif
|
||||
#endif
|
||||
|
||||
; TEXTURE INFO AND PATCH NAMES
|
||||
|
||||
\data\texture1.lmp
|
||||
#ifdef REGISTERED
|
||||
\data\texture2.lmp
|
||||
#endif
|
||||
\data\pnames.lmp
|
||||
|
||||
; AUTOMAP
|
||||
|
||||
$shootwad \art\automap\automap
|
||||
|
||||
; SOUND
|
||||
|
||||
\data\genmidi.op2
|
||||
; \data\dmxgus.ini ;included in wavwad.wads...
|
||||
\sound\samples\sndcurve.lmp
|
||||
|
||||
#ifdef REGISTERED
|
||||
$shootwad \sound\samples\wavwad
|
||||
#else
|
||||
$shootwad \sound\samples\wavwad1
|
||||
#endif
|
||||
|
||||
; SCREENS
|
||||
|
||||
;$shootwad \gfx\screens\help
|
||||
;$shootwad \gfx\screens\credits
|
||||
#ifdef REGISTERED
|
||||
;$shootwad \gfx\screens\victory2
|
||||
;$shootwad \gfx\screens\title
|
||||
;$shootwad \gfx\screens\pfub
|
||||
;$shootwad \gfx\screens\end
|
||||
#else
|
||||
;$shootwad \gfx\screens\stitle
|
||||
#endif
|
||||
|
||||
; INTERMISSION
|
||||
|
||||
#ifdef REGISTERED
|
||||
$shootwad \art\intermsn\intermsn.wad
|
||||
#else
|
||||
$shootwad \art\intermsn\interm1.wad
|
||||
#endif
|
||||
|
||||
; STATUS BAR
|
||||
|
||||
#ifdef REGISTERED
|
||||
$shootwad \art\statbar\statbar
|
||||
#else
|
||||
$shootwad \art\statbar\statbar1
|
||||
#endif
|
||||
|
||||
; MENU
|
||||
|
||||
$shootwad \art\menu\menu
|
||||
|
||||
; FONTS
|
||||
|
||||
$label fonta_s
|
||||
$shootwad \art\fonts\fonta
|
||||
$label fonta_e
|
||||
$label fontb_s
|
||||
$shootwad \art\fonts\fontb
|
||||
$label fontb_e
|
||||
|
||||
; START SPRITES
|
||||
|
||||
$label s_start
|
||||
|
||||
; EPISODE 1 WINDOW WEAPONS
|
||||
|
||||
$shootwad \art\weapons\staff\staff.wad
|
||||
$shootwad \art\weapons\goldwand\goldwand.wad
|
||||
$shootwad \art\weapons\crossbow\crossbow.wad
|
||||
$shootwad \art\weapons\blaster\blaster
|
||||
$shootwad \art\weapons\gauntlet\gauntlet.wad
|
||||
$shootwad \art\weapons\beak\beak.wad
|
||||
|
||||
#ifdef REGISTERED
|
||||
|
||||
; EPISODE 2 AND 3 WINDOW WEAPONS
|
||||
|
||||
; Fire mace
|
||||
$shootwad \art\weapons\mace\mace.wad
|
||||
; Hellstaff
|
||||
$shootwad \art\weapons\hornrod\hornrod.wad
|
||||
; Phoenix rod
|
||||
$shootwad \art\weapons\phoenix\phoenix.wad
|
||||
|
||||
#endif
|
||||
|
||||
; PLAYER
|
||||
|
||||
$shootwad \art\player\player
|
||||
$shootwad \art\player\player2
|
||||
|
||||
; EPISODE 1 MONSTERS
|
||||
|
||||
; Chicken
|
||||
$shootwad \art\monsters\chicken\chicken
|
||||
; Imp (Gargoyle)
|
||||
$shootwad \art\monsters\imp\imp
|
||||
; Mummy (Golem)
|
||||
$shootwad \art\monsters\mummy\mummy
|
||||
; Knight (Undead warrior)
|
||||
$shootwad \art\monsters\knight\knight
|
||||
; Wizard (Disciple of D'Sparil)
|
||||
$shootwad \art\monsters\wizard\wizard
|
||||
; Head (Ironlich)
|
||||
$shootwad \art\monsters\head\head
|
||||
|
||||
#ifdef REGISTERED
|
||||
|
||||
; EPISODE 2 AND 3 MONSTERS
|
||||
|
||||
; Clink (Sabreclaw)
|
||||
$shootwad \art\monsters\clink\clink
|
||||
; Beast (Weredragon)
|
||||
$shootwad \art\monsters\beast\beast
|
||||
; Snake (Ophidian)
|
||||
$shootwad \art\monsters\snake\snake
|
||||
; Minotaur (Maulotaur)
|
||||
$shootwad \art\monsters\minotaur\walk
|
||||
$shootwad \art\monsters\minotaur\pain
|
||||
$shootwad \art\monsters\minotaur\death
|
||||
$shootwad \art\monsters\minotaur\attack
|
||||
$shootwad \art\monsters\minotaur\fx
|
||||
; Sorcerer (D'Sparil)
|
||||
$shootwad \art\monsters\sorcerer\d1
|
||||
$shootwad \art\monsters\sorcerer\d2
|
||||
$shootwad \art\monsters\sorcerer\s1
|
||||
$shootwad \art\monsters\sorcerer\s2
|
||||
|
||||
#endif
|
||||
|
||||
; STATIC SPRITES
|
||||
|
||||
$shootwad \art\sprites\e1spr
|
||||
#ifdef REGISTERED
|
||||
$shootwad \art\weapons\images\images
|
||||
$shootwad \art\artifcts\artifcts
|
||||
$shootwad \art\items\items
|
||||
$shootwad \art\ammo\ammo
|
||||
#else
|
||||
$shootwad \art\weapons\images\images1
|
||||
$shootwad \art\artifcts\arti1
|
||||
$shootwad \art\items\items1
|
||||
$shootwad \art\ammo\ammo1
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef REGISTERED
|
||||
$shootwad \art\sprites\e23spr
|
||||
#endif
|
||||
|
||||
; END SPRITES
|
||||
|
||||
$label s_end
|
||||
|
||||
; START PATCHES
|
||||
|
||||
$label p_start
|
||||
|
||||
; EPSIDOE 1 PATCHES
|
||||
|
||||
$label p1_start
|
||||
$shootwad \art\walls\e1\e1walls
|
||||
$shootwad \art\backdrop\e1sky
|
||||
$label p1_end
|
||||
|
||||
; EPISODE 2 AND 3 PATCHES
|
||||
|
||||
#ifdef REGISTERED
|
||||
$label p2_start
|
||||
$shootwad \art\walls\e23\e23walls
|
||||
$shootwad \art\backdrop\e23sky
|
||||
$label p2_end
|
||||
#endif
|
||||
|
||||
; END PATCHES
|
||||
|
||||
$label p_end
|
||||
|
||||
; START FLATS
|
||||
|
||||
$label f_start
|
||||
|
||||
; EPISODE 1 FLATS
|
||||
|
||||
$label f1_start
|
||||
$shootwad \art\flats\e1\e1flats
|
||||
$label f1_end
|
||||
|
||||
; EPISODE 2 AND 3 FLATS
|
||||
|
||||
#ifdef REGISTERED
|
||||
$label f2_start
|
||||
$shootwad \art\flats\e23\e23flats
|
||||
$label f2_end
|
||||
#endif
|
||||
|
||||
; END FLATS
|
||||
|
||||
$label f_end
|
285
Heretic Source/WADLINK.WL
Normal file
285
Heretic Source/WADLINK.WL
Normal file
|
@ -0,0 +1,285 @@
|
|||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
; WAD NAME
|
||||
|
||||
|
||||
; Extended version
|
||||
$WADNAME extended/heretic
|
||||
|
||||
|
||||
|
||||
\data\extended.txt
|
||||
|
||||
|
||||
; PALETTES AND COLOR MAPS
|
||||
|
||||
\art\palette\playpal.lmp
|
||||
\art\palette\colormap.lmp
|
||||
\art\palette\tinttab.lmp
|
||||
|
||||
; DEMOS AND DOS SCREENS
|
||||
|
||||
\data\txtscr_s\loading.bin
|
||||
|
||||
|
||||
; Extended version
|
||||
$shootwad \art\screens\scrn_e.wad
|
||||
\data\txtscr_e\endtext.bin
|
||||
\data\demos_r\demo1.lmp
|
||||
\data\demos_r\demo2.lmp
|
||||
\data\demos_r\demo3.lmp
|
||||
|
||||
|
||||
; LEVEL MAPS
|
||||
|
||||
$shootwad \data\e1m1
|
||||
$shootwad \data\e1m2
|
||||
$shootwad \data\e1m3
|
||||
$shootwad \data\e1m4
|
||||
$shootwad \data\e1m5
|
||||
$shootwad \data\e1m6
|
||||
$shootwad \data\e1m7
|
||||
$shootwad \data\e1m8
|
||||
$shootwad \data\e1m9
|
||||
|
||||
$shootwad \data\e2m1
|
||||
$shootwad \data\e2m2
|
||||
$shootwad \data\e2m3
|
||||
$shootwad \data\e2m4
|
||||
$shootwad \data\e2m5
|
||||
$shootwad \data\e2m6
|
||||
$shootwad \data\e2m7
|
||||
$shootwad \data\e2m8
|
||||
$shootwad \data\e2m9
|
||||
$shootwad \data\e3m1
|
||||
$shootwad \data\e3m2
|
||||
$shootwad \data\e3m3
|
||||
$shootwad \data\e3m4
|
||||
$shootwad \data\e3m5
|
||||
$shootwad \data\e3m6
|
||||
$shootwad \data\e3m7
|
||||
$shootwad \data\e3m8
|
||||
$shootwad \data\e3m9
|
||||
|
||||
$shootwad \data\e4m1
|
||||
$shootwad \data\e4m2
|
||||
$shootwad \data\e4m3
|
||||
$shootwad \data\e4m4
|
||||
$shootwad \data\e4m5
|
||||
$shootwad \data\e4m6
|
||||
$shootwad \data\e4m7
|
||||
$shootwad \data\e4m8
|
||||
$shootwad \data\e4m9
|
||||
$shootwad \data\e5m1
|
||||
$shootwad \data\e5m2
|
||||
$shootwad \data\e5m3
|
||||
$shootwad \data\e5m4
|
||||
$shootwad \data\e5m5
|
||||
$shootwad \data\e5m6
|
||||
$shootwad \data\e5m7
|
||||
$shootwad \data\e5m8
|
||||
$shootwad \data\e5m9
|
||||
$shootwad \data\e6m1
|
||||
$shootwad \data\e6m2
|
||||
$shootwad \data\e6m3
|
||||
|
||||
|
||||
|
||||
; TEXTURE INFO AND PATCH NAMES
|
||||
|
||||
\data\texture1.lmp
|
||||
|
||||
\data\texture2.lmp
|
||||
|
||||
\data\pnames.lmp
|
||||
|
||||
; AUTOMAP
|
||||
|
||||
$shootwad \art\automap\automap
|
||||
|
||||
; SOUND
|
||||
|
||||
\data\genmidi.op2
|
||||
; \data\dmxgus.ini ;included in wavwad.wads...
|
||||
\sound\samples\sndcurve.lmp
|
||||
|
||||
|
||||
$shootwad \sound\samples\wavwad
|
||||
|
||||
|
||||
; SCREENS
|
||||
|
||||
;$shootwad \gfx\screens\help
|
||||
;$shootwad \gfx\screens\credits
|
||||
|
||||
;$shootwad \gfx\screens\victory2
|
||||
;$shootwad \gfx\screens\title
|
||||
;$shootwad \gfx\screens\pfub
|
||||
;$shootwad \gfx\screens\end
|
||||
|
||||
|
||||
; INTERMISSION
|
||||
|
||||
|
||||
$shootwad \art\intermsn\intermsn.wad
|
||||
|
||||
|
||||
; STATUS BAR
|
||||
|
||||
|
||||
$shootwad \art\statbar\statbar
|
||||
|
||||
|
||||
; MENU
|
||||
|
||||
$shootwad \art\menu\menu
|
||||
|
||||
; FONTS
|
||||
|
||||
$label fonta_s
|
||||
$shootwad \art\fonts\fonta
|
||||
$label fonta_e
|
||||
$label fontb_s
|
||||
$shootwad \art\fonts\fontb
|
||||
$label fontb_e
|
||||
|
||||
; START SPRITES
|
||||
|
||||
$label s_start
|
||||
|
||||
; EPISODE 1 WINDOW WEAPONS
|
||||
|
||||
$shootwad \art\weapons\staff\staff.wad
|
||||
$shootwad \art\weapons\goldwand\goldwand.wad
|
||||
$shootwad \art\weapons\crossbow\crossbow.wad
|
||||
$shootwad \art\weapons\blaster\blaster
|
||||
$shootwad \art\weapons\gauntlet\gauntlet.wad
|
||||
$shootwad \art\weapons\beak\beak.wad
|
||||
|
||||
|
||||
|
||||
; EPISODE 2 AND 3 WINDOW WEAPONS
|
||||
|
||||
; Fire mace
|
||||
$shootwad \art\weapons\mace\mace.wad
|
||||
; Hellstaff
|
||||
$shootwad \art\weapons\hornrod\hornrod.wad
|
||||
; Phoenix rod
|
||||
$shootwad \art\weapons\phoenix\phoenix.wad
|
||||
|
||||
|
||||
|
||||
; PLAYER
|
||||
|
||||
$shootwad \art\player\player
|
||||
$shootwad \art\player\player2
|
||||
|
||||
; EPISODE 1 MONSTERS
|
||||
|
||||
; Chicken
|
||||
$shootwad \art\monsters\chicken\chicken
|
||||
; Imp (Gargoyle)
|
||||
$shootwad \art\monsters\imp\imp
|
||||
; Mummy (Golem)
|
||||
$shootwad \art\monsters\mummy\mummy
|
||||
; Knight (Undead warrior)
|
||||
$shootwad \art\monsters\knight\knight
|
||||
; Wizard (Disciple of D'Sparil)
|
||||
$shootwad \art\monsters\wizard\wizard
|
||||
; Head (Ironlich)
|
||||
$shootwad \art\monsters\head\head
|
||||
|
||||
|
||||
|
||||
; EPISODE 2 AND 3 MONSTERS
|
||||
|
||||
; Clink (Sabreclaw)
|
||||
$shootwad \art\monsters\clink\clink
|
||||
; Beast (Weredragon)
|
||||
$shootwad \art\monsters\beast\beast
|
||||
; Snake (Ophidian)
|
||||
$shootwad \art\monsters\snake\snake
|
||||
; Minotaur (Maulotaur)
|
||||
$shootwad \art\monsters\minotaur\walk
|
||||
$shootwad \art\monsters\minotaur\pain
|
||||
$shootwad \art\monsters\minotaur\death
|
||||
$shootwad \art\monsters\minotaur\attack
|
||||
$shootwad \art\monsters\minotaur\fx
|
||||
; Sorcerer (D'Sparil)
|
||||
$shootwad \art\monsters\sorcerer\d1
|
||||
$shootwad \art\monsters\sorcerer\d2
|
||||
$shootwad \art\monsters\sorcerer\s1
|
||||
$shootwad \art\monsters\sorcerer\s2
|
||||
|
||||
|
||||
|
||||
; STATIC SPRITES
|
||||
|
||||
$shootwad \art\sprites\e1spr
|
||||
|
||||
$shootwad \art\weapons\images\images
|
||||
$shootwad \art\artifcts\artifcts
|
||||
$shootwad \art\items\items
|
||||
$shootwad \art\ammo\ammo
|
||||
|
||||
|
||||
|
||||
|
||||
$shootwad \art\sprites\e23spr
|
||||
|
||||
|
||||
; END SPRITES
|
||||
|
||||
$label s_end
|
||||
|
||||
; START PATCHES
|
||||
|
||||
$label p_start
|
||||
|
||||
; EPSIDOE 1 PATCHES
|
||||
|
||||
$label p1_start
|
||||
$shootwad \art\walls\e1\e1walls
|
||||
$shootwad \art\backdrop\e1sky
|
||||
$label p1_end
|
||||
|
||||
; EPISODE 2 AND 3 PATCHES
|
||||
|
||||
|
||||
$label p2_start
|
||||
$shootwad \art\walls\e23\e23walls
|
||||
$shootwad \art\backdrop\e23sky
|
||||
$label p2_end
|
||||
|
||||
|
||||
; END PATCHES
|
||||
|
||||
$label p_end
|
||||
|
||||
; START FLATS
|
||||
|
||||
$label f_start
|
||||
|
||||
; EPISODE 1 FLATS
|
||||
|
||||
$label f1_start
|
||||
$shootwad \art\flats\e1\e1flats
|
||||
$label f1_end
|
||||
|
||||
; EPISODE 2 AND 3 FLATS
|
||||
|
||||
|
||||
$label f2_start
|
||||
$shootwad \art\flats\e23\e23flats
|
||||
$label f2_end
|
||||
|
||||
|
||||
; END FLATS
|
||||
|
||||
$label f_end
|
6
Heretic Source/WS.BAT
Normal file
6
Heretic Source/WS.BAT
Normal file
|
@ -0,0 +1,6 @@
|
|||
@echo off
|
||||
echo Making shareware WAD (HERETIC1.WAD)
|
||||
echo Preprocessing: wadlink.txt to wadlink.wl
|
||||
\tools\wcc386 /p /fo=wadlink.wl wadlink.txt
|
||||
echo wadlinking ...
|
||||
\tools\exe\wadlink
|
495
Heretic Source/W_WAD.C
Normal file
495
Heretic Source/W_WAD.C
Normal file
|
@ -0,0 +1,495 @@
|
|||
// W_wad.c
|
||||
|
||||
#ifdef NeXT
|
||||
#include <libc.h>
|
||||
#include <ctype.h>
|
||||
|
||||
// next doesn't need a binary flag in open call
|
||||
#define O_BINARY 0
|
||||
|
||||
#else
|
||||
|
||||
#include <malloc.h>
|
||||
#include <io.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
|
||||
#include "DoomDef.h"
|
||||
|
||||
//===============
|
||||
// TYPES
|
||||
//===============
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char identification[4]; // should be IWAD
|
||||
int numlumps;
|
||||
int infotableofs;
|
||||
} wadinfo_t;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int filepos;
|
||||
int size;
|
||||
char name[8];
|
||||
} filelump_t;
|
||||
|
||||
|
||||
//=============
|
||||
// GLOBALS
|
||||
//=============
|
||||
|
||||
lumpinfo_t *lumpinfo; // location of each lump on disk
|
||||
int numlumps;
|
||||
|
||||
void **lumpcache;
|
||||
|
||||
|
||||
//===================
|
||||
|
||||
#ifdef NeXT
|
||||
|
||||
#define strcmpi strcasecmp
|
||||
|
||||
void strupr (char *s)
|
||||
{
|
||||
while (*s)
|
||||
*s++ = toupper(*s);
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
=
|
||||
= filelength
|
||||
=
|
||||
================
|
||||
*/
|
||||
|
||||
int filelength (int handle)
|
||||
{
|
||||
struct stat fileinfo;
|
||||
|
||||
if (fstat (handle,&fileinfo) == -1)
|
||||
I_Error ("Error fstating");
|
||||
|
||||
return fileinfo.st_size;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
void ExtractFileBase (char *path, char *dest)
|
||||
{
|
||||
char *src;
|
||||
int length;
|
||||
|
||||
src = path + strlen(path) - 1;
|
||||
|
||||
//
|
||||
// back up until a \ or the start
|
||||
//
|
||||
while (src != path && *(src-1) != '\\' && *(src-1) != '/')
|
||||
src--;
|
||||
|
||||
//
|
||||
// copy up to eight characters
|
||||
//
|
||||
memset (dest,0,8);
|
||||
length = 0;
|
||||
while (*src && *src != '.')
|
||||
{
|
||||
if (++length == 9)
|
||||
I_Error ("Filename base of %s >8 chars",path);
|
||||
*dest++ = toupper((int)*src++);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
============================================================================
|
||||
|
||||
LUMP BASED ROUTINES
|
||||
|
||||
============================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
====================
|
||||
=
|
||||
= W_AddFile
|
||||
=
|
||||
= All files are optional, but at least one file must be found
|
||||
= Files with a .wad extension are wadlink files with multiple lumps
|
||||
= Other files are single lumps with the base filename for the lump name
|
||||
=
|
||||
====================
|
||||
*/
|
||||
|
||||
void W_AddFile (char *filename)
|
||||
{
|
||||
wadinfo_t header;
|
||||
lumpinfo_t *lump_p;
|
||||
unsigned i;
|
||||
int handle, length;
|
||||
int startlump;
|
||||
filelump_t *fileinfo, singleinfo;
|
||||
|
||||
//
|
||||
// open the file and add to directory
|
||||
//
|
||||
if ( (handle = open (filename,O_RDONLY | O_BINARY)) == -1)
|
||||
return;
|
||||
|
||||
startlump = numlumps;
|
||||
|
||||
if (strcmpi (filename+strlen(filename)-3 , "wad" ) )
|
||||
{
|
||||
// single lump file
|
||||
fileinfo = &singleinfo;
|
||||
singleinfo.filepos = 0;
|
||||
singleinfo.size = LONG(filelength(handle));
|
||||
ExtractFileBase (filename, singleinfo.name);
|
||||
numlumps++;
|
||||
}
|
||||
else
|
||||
{
|
||||
// WAD file
|
||||
read (handle, &header, sizeof(header));
|
||||
if (strncmp(header.identification,"IWAD",4))
|
||||
{
|
||||
if (strncmp(header.identification,"PWAD",4))
|
||||
I_Error ("Wad file %s doesn't have IWAD or PWAD id\n"
|
||||
,filename);
|
||||
}
|
||||
header.numlumps = LONG(header.numlumps);
|
||||
header.infotableofs = LONG(header.infotableofs);
|
||||
length = header.numlumps*sizeof(filelump_t);
|
||||
fileinfo = alloca (length);
|
||||
lseek (handle, header.infotableofs, SEEK_SET);
|
||||
read (handle, fileinfo, length);
|
||||
numlumps += header.numlumps;
|
||||
}
|
||||
|
||||
//
|
||||
// Fill in lumpinfo
|
||||
//
|
||||
lumpinfo = realloc (lumpinfo, numlumps*sizeof(lumpinfo_t));
|
||||
if (!lumpinfo)
|
||||
I_Error ("Couldn't realloc lumpinfo");
|
||||
lump_p = &lumpinfo[startlump];
|
||||
|
||||
for (i=startlump ; i<numlumps ; i++,lump_p++, fileinfo++)
|
||||
{
|
||||
lump_p->handle = handle;
|
||||
lump_p->position = LONG(fileinfo->filepos);
|
||||
lump_p->size = LONG(fileinfo->size);
|
||||
strncpy (lump_p->name, fileinfo->name, 8);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
====================
|
||||
=
|
||||
= W_InitMultipleFiles
|
||||
=
|
||||
= Pass a null terminated list of files to use.
|
||||
=
|
||||
= All files are optional, but at least one file must be found
|
||||
=
|
||||
= Files with a .wad extension are idlink files with multiple lumps
|
||||
=
|
||||
= Other files are single lumps with the base filename for the lump name
|
||||
=
|
||||
= Lump names can appear multiple times. The name searcher looks backwards,
|
||||
= so a later file can override an earlier one.
|
||||
=
|
||||
====================
|
||||
*/
|
||||
|
||||
void W_InitMultipleFiles (char **filenames)
|
||||
{
|
||||
int size;
|
||||
|
||||
//
|
||||
// open all the files, load headers, and count lumps
|
||||
//
|
||||
numlumps = 0;
|
||||
lumpinfo = malloc(1); // will be realloced as lumps are added
|
||||
|
||||
for ( ; *filenames ; filenames++)
|
||||
W_AddFile (*filenames);
|
||||
|
||||
if (!numlumps)
|
||||
I_Error ("W_InitFiles: no files found");
|
||||
|
||||
//
|
||||
// set up caching
|
||||
//
|
||||
size = numlumps * sizeof(*lumpcache);
|
||||
lumpcache = malloc (size);
|
||||
if (!lumpcache)
|
||||
I_Error ("Couldn't allocate lumpcache");
|
||||
memset (lumpcache,0, size);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
====================
|
||||
=
|
||||
= W_InitFile
|
||||
=
|
||||
= Just initialize from a single file
|
||||
=
|
||||
====================
|
||||
*/
|
||||
|
||||
void W_InitFile (char *filename)
|
||||
{
|
||||
char *names[2];
|
||||
|
||||
names[0] = filename;
|
||||
names[1] = NULL;
|
||||
W_InitMultipleFiles (names);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
====================
|
||||
=
|
||||
= W_NumLumps
|
||||
=
|
||||
====================
|
||||
*/
|
||||
|
||||
int W_NumLumps (void)
|
||||
{
|
||||
return numlumps;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
====================
|
||||
=
|
||||
= W_CheckNumForName
|
||||
=
|
||||
= Returns -1 if name not found
|
||||
=
|
||||
====================
|
||||
*/
|
||||
|
||||
int W_CheckNumForName (char *name)
|
||||
{
|
||||
char name8[9];
|
||||
int v1,v2;
|
||||
lumpinfo_t *lump_p;
|
||||
|
||||
// make the name into two integers for easy compares
|
||||
|
||||
strncpy (name8,name,8);
|
||||
name8[8] = 0; // in case the name was a fill 8 chars
|
||||
strupr (name8); // case insensitive
|
||||
|
||||
v1 = *(int *)name8;
|
||||
v2 = *(int *)&name8[4];
|
||||
|
||||
|
||||
// scan backwards so patch lump files take precedence
|
||||
|
||||
lump_p = lumpinfo + numlumps;
|
||||
|
||||
while (lump_p-- != lumpinfo)
|
||||
if ( *(int *)lump_p->name == v1 && *(int *)&lump_p->name[4] == v2)
|
||||
return lump_p - lumpinfo;
|
||||
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
====================
|
||||
=
|
||||
= W_GetNumForName
|
||||
=
|
||||
= Calls W_CheckNumForName, but bombs out if not found
|
||||
=
|
||||
====================
|
||||
*/
|
||||
|
||||
int W_GetNumForName (char *name)
|
||||
{
|
||||
int i;
|
||||
|
||||
i = W_CheckNumForName (name);
|
||||
if (i != -1)
|
||||
return i;
|
||||
|
||||
I_Error ("W_GetNumForName: %s not found!",name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
====================
|
||||
=
|
||||
= W_LumpLength
|
||||
=
|
||||
= Returns the buffer size needed to load the given lump
|
||||
=
|
||||
====================
|
||||
*/
|
||||
|
||||
int W_LumpLength (int lump)
|
||||
{
|
||||
if (lump >= numlumps)
|
||||
I_Error ("W_LumpLength: %i >= numlumps",lump);
|
||||
return lumpinfo[lump].size;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
====================
|
||||
=
|
||||
= W_ReadLump
|
||||
=
|
||||
= Loads the lump into the given buffer, which must be >= W_LumpLength()
|
||||
=
|
||||
====================
|
||||
*/
|
||||
|
||||
void W_ReadLump (int lump, void *dest)
|
||||
{
|
||||
int c;
|
||||
lumpinfo_t *l;
|
||||
|
||||
if (lump >= numlumps)
|
||||
I_Error ("W_ReadLump: %i >= numlumps",lump);
|
||||
l = lumpinfo+lump;
|
||||
|
||||
I_BeginRead ();
|
||||
|
||||
lseek (l->handle, l->position, SEEK_SET);
|
||||
c = read (l->handle, dest, l->size);
|
||||
if (c < l->size)
|
||||
I_Error ("W_ReadLump: only read %i of %i on lump %i",c,l->size,lump);
|
||||
I_EndRead ();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
====================
|
||||
=
|
||||
= W_CacheLumpNum
|
||||
=
|
||||
====================
|
||||
*/
|
||||
|
||||
void *W_CacheLumpNum (int lump, int tag)
|
||||
{
|
||||
byte *ptr;
|
||||
|
||||
if ((unsigned)lump >= numlumps)
|
||||
I_Error ("W_CacheLumpNum: %i >= numlumps",lump);
|
||||
|
||||
if (!lumpcache[lump])
|
||||
{ // read the lump in
|
||||
//printf ("cache miss on lump %i\n",lump);
|
||||
ptr = Z_Malloc (W_LumpLength (lump), tag, &lumpcache[lump]);
|
||||
W_ReadLump (lump, lumpcache[lump]);
|
||||
}
|
||||
else
|
||||
{
|
||||
//printf ("cache hit on lump %i\n",lump);
|
||||
Z_ChangeTag (lumpcache[lump],tag);
|
||||
}
|
||||
|
||||
return lumpcache[lump];
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
====================
|
||||
=
|
||||
= W_CacheLumpName
|
||||
=
|
||||
====================
|
||||
*/
|
||||
|
||||
void *W_CacheLumpName (char *name, int tag)
|
||||
{
|
||||
return W_CacheLumpNum (W_GetNumForName(name), tag);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
====================
|
||||
=
|
||||
= W_Profile
|
||||
=
|
||||
====================
|
||||
*/
|
||||
|
||||
// Ripped out for Heretic
|
||||
/*
|
||||
int info[2500][10];
|
||||
int profilecount;
|
||||
|
||||
void W_Profile (void)
|
||||
{
|
||||
int i;
|
||||
memblock_t *block;
|
||||
void *ptr;
|
||||
char ch;
|
||||
FILE *f;
|
||||
int j;
|
||||
char name[9];
|
||||
|
||||
|
||||
for (i=0 ; i<numlumps ; i++)
|
||||
{
|
||||
ptr = lumpcache[i];
|
||||
if (!ptr)
|
||||
{
|
||||
ch = ' ';
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
block = (memblock_t *) ( (byte *)ptr - sizeof(memblock_t));
|
||||
if (block->tag < PU_PURGELEVEL)
|
||||
ch = 'S';
|
||||
else
|
||||
ch = 'P';
|
||||
}
|
||||
info[i][profilecount] = ch;
|
||||
}
|
||||
profilecount++;
|
||||
|
||||
f = fopen ("waddump.txt","w");
|
||||
name[8] = 0;
|
||||
for (i=0 ; i<numlumps ; i++)
|
||||
{
|
||||
memcpy (name,lumpinfo[i].name,8);
|
||||
for (j=0 ; j<8 ; j++)
|
||||
if (!name[j])
|
||||
break;
|
||||
for ( ; j<8 ; j++)
|
||||
name[j] = ' ';
|
||||
fprintf (f,"%s ",name);
|
||||
for (j=0 ; j<profilecount ; j++)
|
||||
fprintf (f," %c",info[i][j]);
|
||||
fprintf (f,"\n");
|
||||
}
|
||||
fclose (f);
|
||||
}
|
||||
*/
|
389
Heretic Source/Z_ZONE.C
Normal file
389
Heretic Source/Z_ZONE.C
Normal file
|
@ -0,0 +1,389 @@
|
|||
// Z_zone.c
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "DoomDef.h"
|
||||
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
ZONE MEMORY ALLOCATION
|
||||
|
||||
There is never any space between memblocks, and there will never be two
|
||||
contiguous free memblocks.
|
||||
|
||||
The rover can be left pointing at a non-empty block
|
||||
|
||||
It is of no value to free a cachable block, because it will get overwritten
|
||||
automatically if needed
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#define ZONEID 0x1d4a11
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int size; // total bytes malloced, including header
|
||||
memblock_t blocklist; // start / end cap for linked list
|
||||
memblock_t *rover;
|
||||
} memzone_t;
|
||||
|
||||
boolean MallocFailureOk;
|
||||
memzone_t *mainzone;
|
||||
|
||||
/*
|
||||
========================
|
||||
=
|
||||
= Z_ClearZone
|
||||
=
|
||||
========================
|
||||
*/
|
||||
|
||||
void Z_ClearZone (memzone_t *zone)
|
||||
{
|
||||
memblock_t *block;
|
||||
|
||||
// set the entire zone to one free block
|
||||
|
||||
zone->blocklist.next = zone->blocklist.prev = block =
|
||||
(memblock_t *)( (byte *)zone + sizeof(memzone_t) );
|
||||
zone->blocklist.user = (void *)zone;
|
||||
zone->blocklist.tag = PU_STATIC;
|
||||
zone->rover = block;
|
||||
|
||||
block->prev = block->next = &zone->blocklist;
|
||||
block->user = NULL; // free block
|
||||
block->size = zone->size - sizeof(memzone_t);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
========================
|
||||
=
|
||||
= Z_Init
|
||||
=
|
||||
========================
|
||||
*/
|
||||
|
||||
void Z_Init (void)
|
||||
{
|
||||
memblock_t *block;
|
||||
int size;
|
||||
|
||||
MallocFailureOk = false;
|
||||
mainzone = (memzone_t *)I_ZoneBase (&size);
|
||||
mainzone->size = size;
|
||||
|
||||
// set the entire zone to one free block
|
||||
|
||||
mainzone->blocklist.next = mainzone->blocklist.prev = block =
|
||||
(memblock_t *)( (byte *)mainzone + sizeof(memzone_t) );
|
||||
mainzone->blocklist.user = (void *)mainzone;
|
||||
mainzone->blocklist.tag = PU_STATIC;
|
||||
mainzone->rover = block;
|
||||
|
||||
block->prev = block->next = &mainzone->blocklist;
|
||||
block->user = NULL; // free block
|
||||
block->size = mainzone->size - sizeof(memzone_t);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
========================
|
||||
=
|
||||
= Z_Free
|
||||
=
|
||||
========================
|
||||
*/
|
||||
|
||||
void Z_Free (void *ptr)
|
||||
{
|
||||
memblock_t *block, *other;
|
||||
|
||||
block = (memblock_t *) ( (byte *)ptr - sizeof(memblock_t));
|
||||
if (block->id != ZONEID)
|
||||
I_Error ("Z_Free: freed a pointer without ZONEID");
|
||||
|
||||
if (block->user > (void **)0x100) // smaller values are not pointers
|
||||
*block->user = 0; // clear the user's mark
|
||||
block->user = NULL; // mark as free
|
||||
block->tag = 0;
|
||||
block->id = 0;
|
||||
|
||||
other = block->prev;
|
||||
if (!other->user)
|
||||
{ // merge with previous free block
|
||||
other->size += block->size;
|
||||
other->next = block->next;
|
||||
other->next->prev = other;
|
||||
if (block == mainzone->rover)
|
||||
mainzone->rover = other;
|
||||
block = other;
|
||||
}
|
||||
|
||||
other = block->next;
|
||||
if (!other->user)
|
||||
{ // merge the next free block onto the end
|
||||
block->size += other->size;
|
||||
block->next = other->next;
|
||||
block->next->prev = block;
|
||||
if (other == mainzone->rover)
|
||||
mainzone->rover = block;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
========================
|
||||
=
|
||||
= Z_Malloc
|
||||
=
|
||||
= You can pass a NULL user if the tag is < PU_PURGELEVEL
|
||||
========================
|
||||
*/
|
||||
|
||||
#define MINFRAGMENT 64
|
||||
|
||||
void *Z_Malloc (int size, int tag, void *user)
|
||||
{
|
||||
int extra;
|
||||
memblock_t *start, *rover, *new, *base;
|
||||
|
||||
//
|
||||
// scan through the block list looking for the first free block
|
||||
// of sufficient size, throwing out any purgable blocks along the way
|
||||
//
|
||||
size += sizeof(memblock_t); // account for size of block header
|
||||
|
||||
|
||||
//
|
||||
// if there is a free block behind the rover, back up over them
|
||||
//
|
||||
base = mainzone->rover;
|
||||
if (!base->prev->user)
|
||||
base = base->prev;
|
||||
|
||||
rover = base;
|
||||
start = base->prev;
|
||||
|
||||
do
|
||||
{
|
||||
if(rover == start)
|
||||
{ // Scanned all the way around the list
|
||||
if(MallocFailureOk == true)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
I_Error("Z_Malloc: failed on allocation of %i bytes", size);
|
||||
}
|
||||
}
|
||||
if (rover->user)
|
||||
{
|
||||
if (rover->tag < PU_PURGELEVEL)
|
||||
// hit a block that can't be purged, so move base past it
|
||||
base = rover = rover->next;
|
||||
else
|
||||
{
|
||||
// free the rover block (adding the size to base)
|
||||
base = base->prev; // the rover can be the base block
|
||||
Z_Free ((byte *)rover+sizeof(memblock_t));
|
||||
base = base->next;
|
||||
rover = base->next;
|
||||
}
|
||||
}
|
||||
else
|
||||
rover = rover->next;
|
||||
} while (base->user || base->size < size);
|
||||
|
||||
//
|
||||
// found a block big enough
|
||||
//
|
||||
extra = base->size - size;
|
||||
if (extra > MINFRAGMENT)
|
||||
{ // there will be a free fragment after the allocated block
|
||||
new = (memblock_t *) ((byte *)base + size );
|
||||
new->size = extra;
|
||||
new->user = NULL; // free block
|
||||
new->tag = 0;
|
||||
new->prev = base;
|
||||
new->next = base->next;
|
||||
new->next->prev = new;
|
||||
base->next = new;
|
||||
base->size = size;
|
||||
}
|
||||
|
||||
if (user)
|
||||
{
|
||||
base->user = user; // mark as an in use block
|
||||
*(void **)user = (void *) ((byte *)base + sizeof(memblock_t));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (tag >= PU_PURGELEVEL)
|
||||
I_Error ("Z_Malloc: an owner is required for purgable blocks");
|
||||
base->user = (void *)2; // mark as in use, but unowned
|
||||
}
|
||||
base->tag = tag;
|
||||
|
||||
mainzone->rover = base->next; // next allocation will start looking here
|
||||
|
||||
base->id = ZONEID;
|
||||
return (void *) ((byte *)base + sizeof(memblock_t));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
========================
|
||||
=
|
||||
= Z_FreeTags
|
||||
=
|
||||
========================
|
||||
*/
|
||||
|
||||
void Z_FreeTags (int lowtag, int hightag)
|
||||
{
|
||||
memblock_t *block, *next;
|
||||
|
||||
for (block = mainzone->blocklist.next ; block != &mainzone->blocklist
|
||||
; block = next)
|
||||
{
|
||||
next = block->next; // get link before freeing
|
||||
if (!block->user)
|
||||
continue; // free block
|
||||
if (block->tag >= lowtag && block->tag <= hightag)
|
||||
Z_Free ( (byte *)block+sizeof(memblock_t));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
=
|
||||
= Z_DumpHeap
|
||||
=
|
||||
========================
|
||||
*/
|
||||
|
||||
void Z_DumpHeap (int lowtag, int hightag)
|
||||
{
|
||||
memblock_t *block;
|
||||
|
||||
printf ("zone size: %i location: %p\n",mainzone->size,mainzone);
|
||||
printf ("tag range: %i to %i\n",lowtag, hightag);
|
||||
|
||||
for (block = mainzone->blocklist.next ; ; block = block->next)
|
||||
{
|
||||
if (block->tag >= lowtag && block->tag <= hightag)
|
||||
printf ("block:%p size:%7i user:%p tag:%3i\n",
|
||||
block, block->size, block->user, block->tag);
|
||||
|
||||
if (block->next == &mainzone->blocklist)
|
||||
break; // all blocks have been hit
|
||||
if ( (byte *)block + block->size != (byte *)block->next)
|
||||
printf ("ERROR: block size does not touch the next block\n");
|
||||
if ( block->next->prev != block)
|
||||
printf ("ERROR: next block doesn't have proper back link\n");
|
||||
if (!block->user && !block->next->user)
|
||||
printf ("ERROR: two consecutive free blocks\n");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
=
|
||||
= Z_FileDumpHeap
|
||||
=
|
||||
========================
|
||||
*/
|
||||
|
||||
void Z_FileDumpHeap (FILE *f)
|
||||
{
|
||||
memblock_t *block;
|
||||
|
||||
fprintf (f,"zone size: %i location: %p\n",mainzone->size,mainzone);
|
||||
|
||||
for (block = mainzone->blocklist.next ; ; block = block->next)
|
||||
{
|
||||
fprintf (f,"block:%p size:%7i user:%p tag:%3i\n",
|
||||
block, block->size, block->user, block->tag);
|
||||
|
||||
if (block->next == &mainzone->blocklist)
|
||||
break; // all blocks have been hit
|
||||
if ( (byte *)block + block->size != (byte *)block->next)
|
||||
fprintf (f,"ERROR: block size does not touch the next block\n");
|
||||
if ( block->next->prev != block)
|
||||
fprintf (f,"ERROR: next block doesn't have proper back link\n");
|
||||
if (!block->user && !block->next->user)
|
||||
fprintf (f,"ERROR: two consecutive free blocks\n");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
=
|
||||
= Z_CheckHeap
|
||||
=
|
||||
========================
|
||||
*/
|
||||
|
||||
void Z_CheckHeap (void)
|
||||
{
|
||||
memblock_t *block;
|
||||
|
||||
for (block = mainzone->blocklist.next ; ; block = block->next)
|
||||
{
|
||||
if (block->next == &mainzone->blocklist)
|
||||
break; // all blocks have been hit
|
||||
if ( (byte *)block + block->size != (byte *)block->next)
|
||||
I_Error ("Z_CheckHeap: block size does not touch the next block\n");
|
||||
if ( block->next->prev != block)
|
||||
I_Error ("Z_CheckHeap: next block doesn't have proper back link\n");
|
||||
if (!block->user && !block->next->user)
|
||||
I_Error ("Z_CheckHeap: two consecutive free blocks\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
========================
|
||||
=
|
||||
= Z_ChangeTag
|
||||
=
|
||||
========================
|
||||
*/
|
||||
|
||||
void Z_ChangeTag2 (void *ptr, int tag)
|
||||
{
|
||||
memblock_t *block;
|
||||
|
||||
block = (memblock_t *) ( (byte *)ptr - sizeof(memblock_t));
|
||||
if (block->id != ZONEID)
|
||||
I_Error ("Z_ChangeTag: freed a pointer without ZONEID");
|
||||
if (tag >= PU_PURGELEVEL && (unsigned)block->user < 0x100)
|
||||
I_Error ("Z_ChangeTag: an owner is required for purgable blocks");
|
||||
block->tag = tag;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
========================
|
||||
=
|
||||
= Z_FreeMemory
|
||||
=
|
||||
========================
|
||||
*/
|
||||
|
||||
int Z_FreeMemory (void)
|
||||
{
|
||||
memblock_t *block;
|
||||
int free;
|
||||
|
||||
free = 0;
|
||||
for (block = mainzone->blocklist.next ; block != &mainzone->blocklist
|
||||
; block = block->next)
|
||||
if (!block->user || block->tag >= PU_PURGELEVEL)
|
||||
free += block->size;
|
||||
return free;
|
||||
}
|
||||
|
339
LICENSE.txt
Normal file
339
LICENSE.txt
Normal file
|
@ -0,0 +1,339 @@
|
|||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Lesser General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License.
|
7
SourceReadme.txt
Normal file
7
SourceReadme.txt
Normal file
|
@ -0,0 +1,7 @@
|
|||
Activision and Raven are releasing this code for people to learn from and play with.
|
||||
This code is copyright Activision 1996-1998
|
||||
[edit 2 Sep 2008] The code is release under GNU GPLv2 (see LICENSE)
|
||||
|
||||
Issues:
|
||||
The DMX sound library is not included with the source due to license issues,
|
||||
so you won't be able to link until those sound calls are replaced or removed.
|
Loading…
Reference in a new issue