as re-released 2008-09-04

This commit is contained in:
archive 2008-09-04 00:00:00 +00:00
commit 3ae84e87c6
87 changed files with 80377 additions and 0 deletions

107
Hexen Source/AM_DATA.H Normal file
View File

@ -0,0 +1,107 @@
//**************************************************************************
//**
//** am_data.h : Heretic 2 : Raven Software, Corp.
//**
//** $RCSfile: am_data.h,v $
//** $Revision: 1.2 $
//** $Date: 96/01/06 18:37:22 $
//** $Author: bgokey $
//**
//**************************************************************************
#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

1400
Hexen Source/AM_MAP.C Normal file

File diff suppressed because it is too large Load Diff

143
Hexen Source/AM_MAP.H Normal file
View File

@ -0,0 +1,143 @@
//**************************************************************************
//**
//** am_map.h : Heretic 2 : Raven Software, Corp.
//**
//** $RCSfile: am_map.h,v $
//** $Revision: 1.3 $
//** $Date: 95/12/31 19:47:21 $
//** $Author: bgokey $
//**
//**************************************************************************
#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 177
#define BLUEKEY 157
#define YELLOWKEY 137
#define GREENKEY 198
// Automap colors
#define AM_PLR1_COLOR 157 // Blue
#define AM_PLR2_COLOR 177 // Red
#define AM_PLR3_COLOR 137 // Yellow
#define AM_PLR4_COLOR 198 // Green
#define AM_PLR5_COLOR 215 // Jade
#define AM_PLR6_COLOR 32 // White
#define AM_PLR7_COLOR 106 // Hazel
#define AM_PLR8_COLOR 234 // Purple
#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

1319
Hexen Source/A_ACTION.C Normal file

File diff suppressed because it is too large Load Diff

497
Hexen Source/CT_CHAT.C Normal file
View File

@ -0,0 +1,497 @@
//**************************************************************************
//**
//** ct_chat.c : Heretic 2 : Raven Software, Corp.
//**
//** $RCSfile: ct_chat.c,v $
//** $Revision: 1.12 $
//** $Date: 96/01/16 10:35:26 $
//** $Author: bgokey $
//**
//**************************************************************************
#include <string.h>
#include <ctype.h>
#include "h2def.h"
#include "p_local.h"
#include "soundst.h"
#define NUMKEYS 256
#define QUEUESIZE 128
#define MESSAGESIZE 128
#define MESSAGELEN 265
// 8-player note: Change this stuff (CT_PLR_*, and the key mappings)
enum
{
CT_PLR_BLUE = 1,
CT_PLR_RED,
CT_PLR_YELLOW,
CT_PLR_GREEN,
CT_PLR_PLAYER5,
CT_PLR_PLAYER6,
CT_PLR_PLAYER7,
CT_PLR_PLAYER8,
CT_PLR_ALL
};
#define CT_KEY_BLUE 'b'
#define CT_KEY_RED 'r'
#define CT_KEY_YELLOW 'y'
#define CT_KEY_GREEN 'g'
#define CT_KEY_PLAYER5 'j' // Jade
#define CT_KEY_PLAYER6 'w' // White
#define CT_KEY_PLAYER7 'h' // Hazel
#define CT_KEY_PLAYER8 'p' // Purple
#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];
int msgptr[MAXPLAYERS];
int msglen[MAXPLAYERS];
boolean cheated;
static int FontABaseLump;
char *CT_FromPlrText[MAXPLAYERS] =
{
"BLUE: ",
"RED: ",
"YELLOW: ",
"GREEN: ",
"JADE: ",
"WHITE: ",
"HAZEL: ",
"PURPLE: "
};
char *chat_macros[10];
boolean altdown;
boolean shiftdown;
extern boolean usearti;
//===========================================================================
//
// 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_RALT)
{
altdown = (ev->type == ev_keydown);
return false;
}
if(ev->data1 == KEY_RSHIFT)
{
shiftdown = (ev->type == ev_keydown);
return false;
}
if(gamestate != GS_LEVEL || 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;
}
else if(ev->data1 == CT_KEY_PLAYER5)
{
sendto = CT_PLR_PLAYER5;
}
else if(ev->data1 == CT_KEY_PLAYER6)
{
sendto = CT_PLR_PLAYER6;
}
else if(ev->data1 == CT_KEY_PLAYER7)
{
sendto = CT_PLR_PLAYER7;
}
else if(ev->data1 == CT_KEY_PLAYER8)
{
sendto = CT_PLR_PLAYER8;
}
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);
usearti = false;
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;
}
}
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 <= CT_PLR_ALL)
{
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],
"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
Hexen Source/CT_CHAT.H Normal file
View 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'

52
Hexen Source/DEFS.INC Normal file
View File

@ -0,0 +1,52 @@
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 _tinttable: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

29
Hexen Source/DRCOORD.H Normal file
View File

@ -0,0 +1,29 @@
//**************************************************************************
//**
//** DRCoord.h : Heretic 2 : Raven Software, Corp.
//**
//** $RCSfile: DRCoord.h,v $
//** $Revision: 1.1 $
//** $Date: 95/05/11 00:19:30 $
//** $Author: bgokey $
//**
//**************************************************************************
#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

205
Hexen Source/DSTRINGS.H Normal file
View File

@ -0,0 +1,205 @@
//**************************************************************************
//**
//** DStrings.H
//**
//**************************************************************************
// MN_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"
// M_misc.c ----------------------------------------------------------------
#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"
// AM_map.c ----------------------------------------------------------------
#define AMSTR_FOLLOWON "FOLLOW MODE ON"
#define AMSTR_FOLLOWOFF "FOLLOW MODE OFF"
// 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?"

927
Hexen Source/D_NET.C Normal file
View File

@ -0,0 +1,927 @@
//**************************************************************************
//**
//** d_net.c : Heretic 2 : Raven Software, Corp.
//**
//** $RCSfile: d_net.c,v $
//** $Revision: 1.16 $
//** $Date: 96/01/01 03:39:44 $
//** $Author: bgokey $
//**
//** This version has the fixed ticdup code.
//**
//**************************************************************************
#include "h2def.h"
#include "p_local.h"
#include <stdlib.h> // for atoi()
#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 H2_ProcessEvents (void);
void G_BuildTiccmd (ticcmd_t *cmd);
void H2_DoAdvanceDemo (void);
extern void ST_NetProgress(void);
extern void ST_NetDone(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 ();
}
//==========================================================================
//
// NET_SendFrags
//
//==========================================================================
void NET_SendFrags(player_t *player)
{
int i;
int frags;
netbuffer->checksum = NetbufferChecksum();
if (demoplayback)
{
return;
}
if (!netgame)
{
I_Error ("Tried to transmit to another node");
}
frags = 0;
for(i = 0; i < MAXPLAYERS; i++)
{
frags += player->frags[i];
}
doomcom->command = CMD_FRAG;
doomcom->remotenode = frags;
doomcom->datalength = NetbufferSize ();
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;
P_SetMessage(&players[consoleplayer], exitmsg, true);
S_StartSound(NULL, SFX_CHAT);
// 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 ();
H2_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];
boolean gotClass[MAXNETNODES];
#ifdef __WATCOMC__
int nextTic;
extern volatile int ticcount;
nextTic = ticcount+8;
#endif
autostart = true;
memset (gotClass,0,sizeof(gotClass));
memset (gotinfo,0,sizeof(gotinfo));
gotClass[doomcom->consoleplayer] = true;
do
{
i = 0;
CheckAbort();
while(HGetPacket())
{ // Check for any incoming packets
if(netbuffer->checksum&NCMD_SETUP && netbuffer->starttic >= 64)
{
PlayerClass[netbuffer->player] = netbuffer->starttic&0x3f;
if(!gotClass[netbuffer->player])
{
gotClass[netbuffer->player] = true;
ST_NetProgress();
ST_Message("\n");
}
if(netbuffer->retransmitfrom)
{ // that node has received info from all other nodes
gotinfo[netbuffer->player] = true;
}
}
}
#ifdef __WATCOMC__
if(ticcount <= nextTic)
{ // only send packets every half second
continue;
}
nextTic = ticcount+8;
#endif
// Keep sending out packets containing the console class
for(i = 0; i < doomcom->numnodes; i++)
{
netbuffer->player = doomcom->consoleplayer;
netbuffer->starttic = PlayerClass[doomcom->consoleplayer]+64;
netbuffer->retransmitfrom = gotinfo[doomcom->consoleplayer];
netbuffer->numtics = 0;
HSendPacket(i, NCMD_SETUP);
}
for(i = 0; i < doomcom->numnodes; i++)
{ // Make sure that all nodes have sent class info
if (!gotClass[i])
{
ST_Message(".");
break;
}
}
if(i < doomcom->numnodes)
{
continue;
}
else
{ // consoleplayer has received all player classes
if(gotinfo[doomcom->consoleplayer])
{
CheckAbort();
}
else
{
gotinfo[doomcom->consoleplayer] = true;
ST_Message("All player classes received, ready to proceed\n");
ST_NetDone();
}
}
for (i = 0; i < doomcom->numnodes; i++)
{ // Make sure that all nodes are ready to proceed
if (!gotinfo[i])
{
break;
}
}
} while(i < doomcom->numnodes);
memset (gotinfo,0,sizeof(gotinfo));
if (doomcom->consoleplayer)
{ // listen for setup info from key player
// ST_Message ("listening for network start info...\n");
while (1)
{
CheckAbort ();
if (!HGetPacket ())
continue;
if(netbuffer->checksum & NCMD_SETUP && netbuffer->starttic < 64)
{
if (netbuffer->player != VERSION)
I_Error ("Different HEXEN 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 = 1;
return;
}
}
}
else
{ // key player, send the setup info
// ST_Message ("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 = startmap&0x3f;
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;
int pClass;
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;
pClass = PCLASS_FIGHTER;
if(i = M_CheckParm("-class"))
{
pClass = atoi(myargv[i+1]);
if(pClass > PCLASS_MAGE || pClass < PCLASS_FIGHTER)
{
I_Error("Invalid player class: %d\n", pClass);
}
ST_Message("\nPlayer Class: %d\n", pClass);
}
PlayerClass[consoleplayer] = pClass;
if (netgame)
D_ArbitrateNetStart ();
//ST_Message ("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;
//ST_Message ("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)
H2_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
}
}

376
Hexen Source/F_FINALE.C Normal file
View File

@ -0,0 +1,376 @@
//**************************************************************************
//**
//** f_finale.c : Heretic 2 : Raven Software, Corp.
//**
//** $RCSfile: f_finale.c,v $
//** $Revision: 1.7 $
//** $Date: 96/01/05 23:33:26 $
//** $Author: bgokey $
//**
//**************************************************************************
// HEADER FILES ------------------------------------------------------------
#include "h2def.h"
#include "soundst.h"
#include "p_local.h"
#include <ctype.h>
// MACROS ------------------------------------------------------------------
#define TEXTSPEED 3
#define TEXTWAIT 250
// TYPES -------------------------------------------------------------------
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
// PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
static void TextWrite(void);
static void DrawPic(void);
static void InitializeFade(boolean fadeIn);
static void DeInitializeFade(void);
static void FadePic(void);
static char *GetFinaleText(int sequence);
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
extern boolean automapactive;
extern boolean viewactive;
// PUBLIC DATA DECLARATIONS ------------------------------------------------
// PRIVATE DATA DEFINITIONS ------------------------------------------------
static int FinaleStage;
static int FinaleCount;
static int FinaleEndCount;
static int FinaleLumpNum;
static int FontABaseLump;
static char *FinaleText;
static fixed_t *Palette;
static fixed_t *PaletteDelta;
static byte *RealPalette;
// CODE --------------------------------------------------------------------
//===========================================================================
//
// F_StartFinale
//
//===========================================================================
void F_StartFinale (void)
{
gameaction = ga_nothing;
gamestate = GS_FINALE;
viewactive = false;
automapactive = false;
P_ClearMessage(&players[consoleplayer]);
FinaleStage = 0;
FinaleCount = 0;
FinaleText = GetFinaleText(0);
FinaleEndCount = 70;
FinaleLumpNum = W_GetNumForName("FINALE1");
FontABaseLump = W_GetNumForName("FONTA_S")+1;
InitializeFade(1);
// S_ChangeMusic(mus_victor, true);
S_StartSongName("hall", false); // don't loop the song
}
//===========================================================================
//
// F_Responder
//
//===========================================================================
boolean F_Responder(event_t *event)
{
return false;
}
//===========================================================================
//
// F_Ticker
//
//===========================================================================
void F_Ticker (void)
{
FinaleCount++;
if(FinaleStage < 5 && FinaleCount >= FinaleEndCount)
{
FinaleCount = 0;
FinaleStage++;
switch(FinaleStage)
{
case 1: // Text 1
FinaleEndCount = strlen(FinaleText)*TEXTSPEED+TEXTWAIT;
break;
case 2: // Pic 2, Text 2
FinaleText = GetFinaleText(1);
FinaleEndCount = strlen(FinaleText)*TEXTSPEED+TEXTWAIT;
FinaleLumpNum = W_GetNumForName("FINALE2");
S_StartSongName("orb", false);
break;
case 3: // Pic 2 -- Fade out
FinaleEndCount = 70;
DeInitializeFade();
InitializeFade(0);
break;
case 4: // Pic 3 -- Fade in
FinaleLumpNum = W_GetNumForName("FINALE3");
FinaleEndCount = 71;
DeInitializeFade();
InitializeFade(1);
S_StartSongName("chess", true);
break;
case 5: // Pic 3 , Text 3
FinaleText = GetFinaleText(2);
DeInitializeFade();
break;
default:
break;
}
return;
}
if(FinaleStage == 0 || FinaleStage == 3 || FinaleStage == 4)
{
FadePic();
}
}
//===========================================================================
//
// TextWrite
//
//===========================================================================
static void TextWrite (void)
{
int count;
char *ch;
int c;
int cx, cy;
patch_t *w;
memcpy(screen, W_CacheLumpNum(FinaleLumpNum, PU_CACHE),
SCREENWIDTH*SCREENHEIGHT);
if(FinaleStage == 5)
{ // Chess pic, draw the correct character graphic
if(netgame)
{
V_DrawPatch(20, 0, W_CacheLumpName("chessall", PU_CACHE));
}
else if(PlayerClass[consoleplayer])
{
V_DrawPatch(60, 0, W_CacheLumpNum(W_GetNumForName("chessc")
+PlayerClass[consoleplayer]-1, PU_CACHE));
}
}
// Draw the actual text
if(FinaleStage == 5)
{
cy = 135;
}
else
{
cy = 5;
}
cx = 20;
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;
}
if(c < 32)
{
continue;
}
c = toupper(c);
if(c == 32)
{
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;
}
}
//===========================================================================
//
// InitializeFade
//
//===========================================================================
static void InitializeFade(boolean fadeIn)
{
unsigned i;
Palette = Z_Malloc(768*sizeof(fixed_t), PU_STATIC, 0);
PaletteDelta = Z_Malloc(768*sizeof(fixed_t), PU_STATIC, 0);
RealPalette = Z_Malloc(768*sizeof(byte), PU_STATIC, 0);
if(fadeIn)
{
memset(RealPalette, 0, 768*sizeof(byte));
for(i = 0; i < 768; i++)
{
Palette[i] = 0;
PaletteDelta[i] = FixedDiv((*((byte *)W_CacheLumpName("playpal",
PU_CACHE)+i))<<FRACBITS, 70*FRACUNIT);
}
}
else
{
for(i = 0; i < 768; i++)
{
RealPalette[i] = *((byte *)W_CacheLumpName("playpal", PU_CACHE)+i);
Palette[i] = RealPalette[i]<<FRACBITS;
PaletteDelta[i] = FixedDiv(Palette[i], -70*FRACUNIT);
}
}
I_SetPalette(RealPalette);
}
//===========================================================================
//
// DeInitializeFade
//
//===========================================================================
static void DeInitializeFade(void)
{
Z_Free(Palette);
Z_Free(PaletteDelta);
Z_Free(RealPalette);
}
//===========================================================================
//
// FadePic
//
//===========================================================================
static void FadePic(void)
{
unsigned i;
for(i = 0; i < 768; i++)
{
Palette[i] += PaletteDelta[i];
RealPalette[i] = Palette[i]>>FRACBITS;
}
I_SetPalette(RealPalette);
}
//===========================================================================
//
// DrawPic
//
//===========================================================================
static void DrawPic(void)
{
memcpy(screen, W_CacheLumpNum(FinaleLumpNum, PU_CACHE),
SCREENWIDTH*SCREENHEIGHT);
if(FinaleStage == 4 || FinaleStage == 5)
{ // Chess pic, draw the correct character graphic
if(netgame)
{
V_DrawPatch(20, 0, W_CacheLumpName("chessall", PU_CACHE));
}
else if(PlayerClass[consoleplayer])
{
V_DrawPatch(60, 0, W_CacheLumpNum(W_GetNumForName("chessc")
+PlayerClass[consoleplayer]-1, PU_CACHE));
}
}
}
//===========================================================================
//
// F_Drawer
//
//===========================================================================
void F_Drawer(void)
{
switch(FinaleStage)
{
case 0: // Fade in initial finale screen
DrawPic();
break;
case 1:
case 2:
TextWrite();
break;
case 3: // Fade screen out
DrawPic();
break;
case 4: // Fade in chess screen
DrawPic();
break;
case 5:
TextWrite();
break;
}
UpdateState |= I_FULLSCRN;
}
//==========================================================================
//
// GetFinaleText
//
//==========================================================================
static char *GetFinaleText(int sequence)
{
char *msgLumpName;
int msgSize;
int msgLump;
static char *winMsgLumpNames[] =
{
"win1msg",
"win2msg",
"win3msg"
};
msgLumpName = winMsgLumpNames[sequence];
msgLump = W_GetNumForName(msgLumpName);
msgSize = W_LumpLength(msgLump);
if(msgSize >= MAX_INTRMSN_MESSAGE_SIZE)
{
I_Error("Finale message too long (%s)", msgLumpName);
}
W_ReadLump(msgLump, ClusterMessage);
ClusterMessage[msgSize] = 0; // Append terminator
return ClusterMessage;
}

2014
Hexen Source/G_GAME.C Normal file

File diff suppressed because it is too large Load Diff

1459
Hexen Source/H2DEF.H Normal file

File diff suppressed because it is too large Load Diff

934
Hexen Source/H2_MAIN.C Normal file
View File

@ -0,0 +1,934 @@
//**************************************************************************
//**
//** h2_main.c : Heretic 2 : Raven Software, Corp.
//**
//** $RCSfile: h2_main.c,v $
//** $Revision: 1.50 $
//** $Date: 96/01/16 13:02:28 $
//** $Author: bgokey $
//**
//**************************************************************************
// HEADER FILES ------------------------------------------------------------
#ifdef __WATCOMC__
#include <dos.h>
#include <sys\types.h>
#include <direct.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "h2def.h"
#include "p_local.h"
#include "soundst.h"
// MACROS ------------------------------------------------------------------
#define CONFIG_FILE_NAME "hexen.cfg"
#define MAXWADFILES 20
// TYPES -------------------------------------------------------------------
typedef struct
{
char *name;
void (*func)(char **args, int tag);
int requiredArgs;
int tag;
} execOpt_t;
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
void R_ExecuteSetViewSize(void);
void D_CheckNetGame(void);
void G_BuildTiccmd(ticcmd_t *cmd);
void F_Drawer(void);
boolean F_Responder(event_t *ev);
void I_StartupKeyboard(void);
void I_StartupJoystick(void);
void I_ShutdownKeyboard(void);
void S_InitScript(void);
// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
void H2_ProcessEvents(void);
void H2_DoAdvanceDemo(void);
void H2_AdvanceDemo(void);
void H2_StartTitle(void);
void H2_PageTicker(void);
// PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
static void DrawMessage(void);
static void PageDrawer(void);
static void HandleArgs(void);
static void CheckRecordFrom(void);
static void AddWADFile(char *file);
static void DrawAndBlit(void);
static void ExecOptionFILE(char **args, int tag);
static void ExecOptionSCRIPTS(char **args, int tag);
static void ExecOptionDEVMAPS(char **args, int tag);
static void ExecOptionSKILL(char **args, int tag);
static void ExecOptionPLAYDEMO(char **args, int tag);
static void ExecOptionMAXZONE(char **args, int tag);
static void CreateSavePath(void);
static void WarpCheck(void);
#ifdef TIMEBOMB
static void DoTimeBomb(void);
#endif
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
extern boolean automapactive;
extern boolean MenuActive;
extern boolean askforquit;
extern char *SavePath;
// PUBLIC DATA DEFINITIONS -------------------------------------------------
boolean DevMaps; // true = Map development mode
char *DevMapsDir = ""; // development maps directory
boolean shareware; // true if only episode 1 present
boolean nomonsters; // checkparm of -nomonsters
boolean respawnparm; // checkparm of -respawn
boolean randomclass; // checkparm of -randclass
boolean debugmode; // checkparm of -debug
boolean ravpic; // checkparm of -ravpic
boolean cdrom; // true if cd-rom mode active
boolean cmdfrag; // true if a CMD_FRAG packet should be sent out
boolean singletics; // debug flag to cancel adaptiveness
boolean artiskip; // whether shift-enter skips an artifact
int maxzone = 0x800000; // Maximum allocated for zone heap (8meg default)
skill_t startskill;
int startepisode;
int startmap;
boolean autostart;
boolean advancedemo;
FILE *debugfile;
event_t events[MAXEVENTS];
int eventhead;
int eventtail;
// PRIVATE DATA DEFINITIONS ------------------------------------------------
static int WarpMap;
static int demosequence;
static int pagetic;
static char *pagename;
#ifdef __NeXT__
static char *wadfiles[MAXWADFILES] =
{
"/Novell/H2/source/hexen.wad"
};
#else
static char *wadfiles[MAXWADFILES] =
{
"hexen.wad"
};
#endif
static execOpt_t ExecOptions[] =
{
{ "-file", ExecOptionFILE, 1, 0 },
{ "-scripts", ExecOptionSCRIPTS, 1, 0 },
{ "-devmaps", ExecOptionDEVMAPS, 1, 0 },
{ "-skill", ExecOptionSKILL, 1, 0 },
{ "-playdemo", ExecOptionPLAYDEMO, 1, 0 },
{ "-timedemo", ExecOptionPLAYDEMO, 1, 0 },
{ "-maxzone", ExecOptionMAXZONE, 1, 0 },
{ NULL, NULL, 0, 0 } // Terminator
};
// CODE --------------------------------------------------------------------
//==========================================================================
//
// H2_Main
//
//==========================================================================
void InitMapMusicInfo(void);
void H2_Main(void)
{
int p;
M_FindResponseFile();
setbuf(stdout, NULL);
startepisode = 1;
autostart = false;
startskill = sk_medium;
startmap = 1;
shareware = false; // Always false for Hexen
HandleArgs();
// Initialize subsystems
ST_Message("V_Init: allocate screens.\n");
V_Init();
// Load defaults before initing other systems
ST_Message("M_LoadDefaults: Load system defaults.\n");
M_LoadDefaults(CONFIG_FILE_NAME);
// Now that the savedir is loaded from .CFG, make sure it exists
CreateSavePath();
// HEXEN MODIFICATION:
// There is a realloc() in W_AddFile() that might fail if the zone
// heap has been previously allocated, so we need to initialize the
// WAD files BEFORE the zone memory initialization.
ST_Message("W_Init: Init WADfiles.\n");
W_InitMultipleFiles(wadfiles);
#ifdef TIMEBOMB
DoTimeBomb();
#endif
ST_Message("Z_Init: Init zone memory allocation daemon.\n");
Z_Init();
#ifdef __WATCOMC__
I_StartupKeyboard();
I_StartupJoystick();
#endif
ST_Message("MN_Init: Init menu system.\n");
MN_Init();
ST_Message("CT_Init: Init chat mode data.\n");
CT_Init();
InitMapMusicInfo(); // Init music fields in mapinfo
#ifdef __WATCOMC__
ST_Message("S_InitScript\n");
S_InitScript();
#endif
ST_Message("SN_InitSequenceScript: Registering sound sequences.\n");
SN_InitSequenceScript();
ST_Message("I_Init: Setting up machine state.\n");
I_Init();
ST_Message("ST_Init: Init startup screen.\n");
ST_Init();
S_StartSongName("orb", true);
// Show version message now, so it's visible during R_Init()
ST_Message("Executable: "VERSIONTEXT".\n");
ST_Message("R_Init: Init Hexen refresh daemon");
R_Init();
ST_Message("\n");
if (M_CheckParm("-net")) ST_NetProgress(); // Console player found
ST_Message("P_Init: Init Playloop state.\n");
P_Init();
// Check for command line warping. Follows P_Init() because the
// MAPINFO.TXT script must be already processed.
WarpCheck();
if(autostart)
{
ST_Message("Warp to Map %d (\"%s\":%d), Skill %d\n",
WarpMap, P_GetMapName(startmap), startmap, startskill+1);
}
ST_Message("D_CheckNetGame: Checking network game status.\n");
D_CheckNetGame();
ST_Message("SB_Init: Loading patches.\n");
SB_Init();
CheckRecordFrom();
p = M_CheckParm("-record");
if(p && p < myargc-1)
{
G_RecordDemo(startskill, 1, startepisode, startmap, myargv[p+1]);
H2_GameLoop(); // Never returns
}
p = M_CheckParm("-playdemo");
if(p && p < myargc-1)
{
singledemo = true; // Quit after one demo
G_DeferedPlayDemo(myargv[p+1]);
H2_GameLoop(); // Never returns
}
p = M_CheckParm("-timedemo");
if(p && p < myargc-1)
{
G_TimeDemo(myargv[p+1]);
H2_GameLoop(); // Never returns
}
p = M_CheckParm("-loadgame");
if(p && p < myargc-1)
{
G_LoadGame(atoi(myargv[p+1]));
}
if(gameaction != ga_loadgame)
{
UpdateState |= I_FULLSCRN;
BorderNeedRefresh = true;
if(autostart || netgame)
{
G_StartNewInit();
G_InitNew(startskill, startepisode, startmap);
}
else
{
H2_StartTitle();
}
}
H2_GameLoop(); // Never returns
}
//==========================================================================
//
// HandleArgs
//
//==========================================================================
static void HandleArgs(void)
{
int p;
execOpt_t *opt;
nomonsters = M_ParmExists("-nomonsters");
respawnparm = M_ParmExists("-respawn");
randomclass = M_ParmExists("-randclass");
ravpic = M_ParmExists("-ravpic");
artiskip = M_ParmExists("-artiskip");
debugmode = M_ParmExists("-debug");
deathmatch = M_ParmExists("-deathmatch");
cdrom = M_ParmExists("-cdrom");
cmdfrag = M_ParmExists("-cmdfrag");
// Process command line options
for(opt = ExecOptions; opt->name != NULL; opt++)
{
p = M_CheckParm(opt->name);
if(p && p < myargc-opt->requiredArgs)
{
opt->func(&myargv[p], opt->tag);
}
}
// Look for an external device driver
I_CheckExternDriver();
}
//==========================================================================
//
// WarpCheck
//
//==========================================================================
static void WarpCheck(void)
{
int p;
int map;
p = M_CheckParm("-warp");
if(p && p < myargc-1)
{
WarpMap = atoi(myargv[p+1]);
map = P_TranslateMap(WarpMap);
if(map == -1)
{ // Couldn't find real map number
startmap = 1;
ST_Message("-WARP: Invalid map number.\n");
}
else
{ // Found a valid startmap
startmap = map;
autostart = true;
}
}
else
{
WarpMap = 1;
startmap = P_TranslateMap(1);
if(startmap == -1)
{
startmap = 1;
}
}
}
//==========================================================================
//
// ExecOptionSKILL
//
//==========================================================================
static void ExecOptionSKILL(char **args, int tag)
{
startskill = args[1][0]-'1';
autostart = true;
}
//==========================================================================
//
// ExecOptionFILE
//
//==========================================================================
static void ExecOptionFILE(char **args, int tag)
{
int p;
p = M_CheckParm("-file");
while(++p != myargc && myargv[p][0] != '-')
{
AddWADFile(myargv[p]);
}
}
//==========================================================================
//
// ExecOptionPLAYDEMO
//
//==========================================================================
static void ExecOptionPLAYDEMO(char **args, int tag)
{
char file[256];
sprintf(file, "%s.lmp", args[1]);
AddWADFile(file);
ST_Message("Playing demo %s.lmp.\n", args[1]);
}
//==========================================================================
//
// ExecOptionSCRIPTS
//
//==========================================================================
static void ExecOptionSCRIPTS(char **args, int tag)
{
sc_FileScripts = true;
sc_ScriptsDir = args[1];
}
//==========================================================================
//
// ExecOptionDEVMAPS
//
//==========================================================================
static void ExecOptionDEVMAPS(char **args, int tag)
{
DevMaps = true;
ST_Message("Map development mode enabled:\n");
ST_Message("[config ] = %s\n", args[1]);
SC_OpenFileCLib(args[1]);
SC_MustGetStringName("mapsdir");
SC_MustGetString();
ST_Message("[mapsdir ] = %s\n", sc_String);
DevMapsDir = malloc(strlen(sc_String)+1);
strcpy(DevMapsDir, sc_String);
SC_MustGetStringName("scriptsdir");
SC_MustGetString();
ST_Message("[scriptsdir] = %s\n", sc_String);
sc_FileScripts = true;
sc_ScriptsDir = malloc(strlen(sc_String)+1);
strcpy(sc_ScriptsDir, sc_String);
while(SC_GetString())
{
if(SC_Compare("file"))
{
SC_MustGetString();
AddWADFile(sc_String);
}
else
{
SC_ScriptError(NULL);
}
}
SC_Close();
}
long superatol(char *s)
{
long int n=0, r=10, x, mul=1;
char *c=s;
for (; *c; c++)
{
x = (*c & 223) - 16;
if (x == -3)
{
mul = -mul;
}
else if (x == 72 && r == 10)
{
n -= (r=n);
if (!r) r=16;
if (r<2 || r>36) return -1;
}
else
{
if (x>10) x-=39;
if (x >= r) return -1;
n = (n*r) + x;
}
}
return(mul*n);
}
static void ExecOptionMAXZONE(char **args, int tag)
{
int size;
size = superatol(args[1]);
if (size < MINIMUM_HEAP_SIZE) size = MINIMUM_HEAP_SIZE;
if (size > MAXIMUM_HEAP_SIZE) size = MAXIMUM_HEAP_SIZE;
maxzone = size;
}
//==========================================================================
//
// H2_GameLoop
//
//==========================================================================
void H2_GameLoop(void)
{
if(M_CheckParm("-debugfile"))
{
char filename[20];
sprintf(filename, "debug%i.txt", consoleplayer);
debugfile = fopen(filename,"w");
}
I_InitGraphics();
while(1)
{
// Frame syncronous IO operations
I_StartFrame();
// Process one or more tics
if(singletics)
{
I_StartTic();
H2_ProcessEvents();
G_BuildTiccmd(&netcmds[consoleplayer][maketic%BACKUPTICS]);
if(advancedemo)
{
H2_DoAdvanceDemo();
}
G_Ticker();
gametic++;
maketic++;
}
else
{
// Will run at least one tic
TryRunTics();
}
// Move positional sounds
S_UpdateSounds(players[displayplayer].mo);
DrawAndBlit();
}
}
//==========================================================================
//
// H2_ProcessEvents
//
// Send all the events of the given timestamp down the responder chain.
//
//==========================================================================
void H2_ProcessEvents(void)
{
event_t *ev;
for(; eventtail != eventhead; eventtail = (++eventtail)&(MAXEVENTS-1))
{
ev = &events[eventtail];
if(F_Responder(ev))
{
continue;
}
if(MN_Responder(ev))
{
continue;
}
G_Responder(ev);
}
}
//==========================================================================
//
// H2_PostEvent
//
// Called by the I/O functions when input is detected.
//
//==========================================================================
void H2_PostEvent(event_t *ev)
{
events[eventhead] = *ev;
eventhead = (++eventhead)&(MAXEVENTS-1);
}
//==========================================================================
//
// DrawAndBlit
//
//==========================================================================
static void DrawAndBlit(void)
{
// Change the view size if needed
if(setsizeneeded)
{
R_ExecuteSetViewSize();
}
// Do buffered drawing
switch(gamestate)
{
case GS_LEVEL:
if(!gametic)
{
break;
}
if(automapactive)
{
AM_Drawer();
}
else
{
R_RenderPlayerView(&players[displayplayer]);
}
CT_Drawer();
UpdateState |= I_FULLVIEW;
SB_Drawer();
break;
case GS_INTERMISSION:
IN_Drawer();
break;
case GS_FINALE:
F_Drawer();
break;
case GS_DEMOSCREEN:
PageDrawer();
break;
}
if(paused && !MenuActive && !askforquit)
{
if(!netgame)
{
V_DrawPatch(160, viewwindowy+5, W_CacheLumpName("PAUSED",
PU_CACHE));
}
else
{
V_DrawPatch(160, 70, W_CacheLumpName("PAUSED",
PU_CACHE));
}
}
// Draw current message
DrawMessage();
// Draw Menu
MN_Drawer();
// Send out any new accumulation
NetUpdate();
// Flush buffered stuff to screen
I_Update();
}
//==========================================================================
//
// DrawMessage
//
//==========================================================================
static void DrawMessage(void)
{
player_t *player;
player = &players[consoleplayer];
if(player->messageTics <= 0 || !player->message)
{ // No message
return;
}
if(player->yellowMessage)
{
MN_DrTextAYellow(player->message,
160-MN_TextAWidth(player->message)/2, 1);
}
else
{
MN_DrTextA(player->message, 160-MN_TextAWidth(player->message)/2, 1);
}
}
//==========================================================================
//
// H2_PageTicker
//
//==========================================================================
void H2_PageTicker(void)
{
if(--pagetic < 0)
{
H2_AdvanceDemo();
}
}
//==========================================================================
//
// PageDrawer
//
//==========================================================================
static void PageDrawer(void)
{
V_DrawRawScreen(W_CacheLumpName(pagename, PU_CACHE));
if(demosequence == 1)
{
V_DrawPatch(4, 160, W_CacheLumpName("ADVISOR", PU_CACHE));
}
UpdateState |= I_FULLSCRN;
}
//==========================================================================
//
// H2_AdvanceDemo
//
// Called after each demo or intro demosequence finishes.
//
//==========================================================================
void H2_AdvanceDemo(void)
{
advancedemo = true;
}
//==========================================================================
//
// H2_DoAdvanceDemo
//
//==========================================================================
void H2_DoAdvanceDemo(void)
{
players[consoleplayer].playerstate = PST_LIVE; // don't reborn
advancedemo = false;
usergame = false; // can't save/end game here
paused = false;
gameaction = ga_nothing;
demosequence = (demosequence+1)%7;
switch(demosequence)
{
case 0:
pagetic = 280;
gamestate = GS_DEMOSCREEN;
pagename = "TITLE";
S_StartSongName("hexen", true);
break;
case 1:
pagetic = 210;
gamestate = GS_DEMOSCREEN;
pagename = "TITLE";
break;
case 2:
BorderNeedRefresh = true;
UpdateState |= I_FULLSCRN;
G_DeferedPlayDemo("demo1");
break;
case 3:
pagetic = 200;
gamestate = GS_DEMOSCREEN;
pagename = "CREDIT";
break;
case 4:
BorderNeedRefresh = true;
UpdateState |= I_FULLSCRN;
G_DeferedPlayDemo("demo2");
break;
case 5:
pagetic = 200;
gamestate = GS_DEMOSCREEN;
pagename = "CREDIT";
break;
case 6:
BorderNeedRefresh = true;
UpdateState |= I_FULLSCRN;
G_DeferedPlayDemo("demo3");
break;
}
}
//==========================================================================
//
// H2_StartTitle
//
//==========================================================================
void H2_StartTitle(void)
{
gameaction = ga_nothing;
demosequence = -1;
H2_AdvanceDemo();
}
//==========================================================================
//
// CheckRecordFrom
//
// -recordfrom <savegame num> <demoname>
//
//==========================================================================
static void CheckRecordFrom(void)
{
int p;
p = M_CheckParm("-recordfrom");
if(!p || p > myargc-2)
{ // Bad args
return;
}
G_LoadGame(atoi(myargv[p+1]));
G_DoLoadGame(); // Load the gameskill etc info from savegame
G_RecordDemo(gameskill, 1, gameepisode, gamemap, myargv[p+2]);
H2_GameLoop(); // Never returns
}
//==========================================================================
//
// AddWADFile
//
//==========================================================================
static void AddWADFile(char *file)
{
int i;
char *new;
ST_Message("Adding external file: %s\n", file);
i = 0;
while(wadfiles[i])
{
i++;
}
new = malloc(strlen(file)+1);
strcpy(new, file);
wadfiles[i] = new;
}
#ifdef __WATCOMC__
/*
void CleanExit(void)
{
union REGS regs;
I_ShutdownKeyboard();
regs.x.eax = 0x3;
int386(0x10, &regs, &regs);
printf("Exited from HEXEN: Beyond Heretic.\n");
exit(1);
}
*/
#endif
//==========================================================================
//
// FixedDiv
//
//==========================================================================
fixed_t FixedDiv(fixed_t a, fixed_t b)
{
if((abs(a)>>14) >= abs(b))
{
return((a^b)<0 ? MININT : MAXINT);
}
return(FixedDiv2(a, b));
}
//==========================================================================
//
// CreateSavePath
//
//==========================================================================
static void CreateSavePath(void)
{
char creationPath[121];
int len;
if(cdrom == true)
{
SavePath = "c:\\hexndata\\";
}
len = strlen(SavePath);
if (len >= 120) I_Error("Save path too long\n");
strcpy(creationPath, SavePath);
#ifdef __WATCOMC__
creationPath[len-1] = 0;
mkdir(creationPath);
#endif
}
#ifdef TIMEBOMB
//==========================================================================
//
// DoTimeBomb
//
//==========================================================================
static void DoTimeBomb(void)
{
#ifdef __WATCOMC__
time_t timeOfDay;
struct tm timeBuffer;
timeOfDay = time(NULL);
_localtime(&timeOfDay, &timeBuffer);
if(timeBuffer.tm_year != TIMEBOMB_YEAR
|| timeBuffer.tm_yday < TIMEBOMB_STARTDATE
|| timeBuffer.tm_yday > TIMEBOMB_ENDDATE)
{
I_Error("W_InitWadfiles: Wad file doesn't have IWAD or PWAD id\n");
}
printf("\n===============================================================================\n");
printf(" Hexen: Beyond Heretic\n\n");
printf(" Beta -- Do Not Distribute!\n");
printf(" Press any key to continue.\n");
printf("===============================================================================\n");
getch();
printf("\n");
#endif
}
#endif

73
Hexen Source/HEX.LNK Normal file
View File

@ -0,0 +1,73 @@
# HEX.EXE Linker directive file
option quiet
option map
option statics
option stack=65536
option stub=wstub
debug all
libpath %WATCOM%\lib386
libpath %WATCOM%\lib386\dos
lib noemu387.lib
lib dmx
format os2 le
name hex
file i_cyber.obj
file i_ibm.obj
file i_ibm_a.obj
file i_sound.obj
file i_cdmus.obj
file linear.obj
file am_map.obj
file a_action.obj
file ct_chat.obj
file d_net.obj
file f_finale.obj
file g_game.obj
file h2_main.obj
file info.obj
file in_lude.obj
file mn_menu.obj
file m_misc.obj
file p_acs.obj
file p_anim.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_things.obj
file p_user.obj
file po_man.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 sc_man.obj
file sn_sonix.obj
file st_start.obj
file sv_save.obj
file sounds.obj
file tables.obj
file v_video.obj
file w_wad.obj
file z_zone.obj

13862
Hexen Source/INFO.C Normal file

File diff suppressed because it is too large Load Diff

3601
Hexen Source/INFO.H Normal file

File diff suppressed because it is too large Load Diff

597
Hexen Source/IN_LUDE.C Normal file
View File

@ -0,0 +1,597 @@
//**************************************************************************
//**
//** in_lude.c : Heretic 2 : Raven Software, Corp.
//**
//** $RCSfile: in_lude.c,v $
//** $Revision: 1.19 $
//** $Date: 96/01/05 23:33:19 $
//** $Author: bgokey $
//**
//**************************************************************************
#include "h2def.h"
#include <ctype.h>
// MACROS ------------------------------------------------------------------
#define TEXTSPEED 3
#define TEXTWAIT 140
// TYPES -------------------------------------------------------------------
typedef enum
{
SINGLE,
COOPERATIVE,
DEATHMATCH
} gametype_t;
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
void IN_Start(void);
void IN_Ticker(void);
void IN_Drawer(void);
// PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
static void WaitStop(void);
static void Stop(void);
static void LoadPics(void);
static void UnloadPics(void);
static void CheckForSkip(void);
static void InitStats(void);
static void DrDeathTally(void);
static void DrNumber(int val, int x, int y, int wrapThresh);
static void DrNumberBold(int val, int x, int y, int wrapThresh);
static void DrawHubText(void);
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
// PUBLIC DATA DECLARATIONS ------------------------------------------------
boolean intermission;
char ClusterMessage[MAX_INTRMSN_MESSAGE_SIZE];
// PRIVATE DATA DEFINITIONS ------------------------------------------------
static boolean skipintermission;
static int interstate = 0;
static int intertime = -1;
static gametype_t gametype;
static int cnt;
static int slaughterboy; // in DM, the player with the most kills
static patch_t *patchINTERPIC;
static patch_t *FontBNumbers[10];
static patch_t *FontBNegative;
static patch_t *FontBSlash;
static patch_t *FontBPercent;
static int FontABaseLump;
static int FontBLump;
static int FontBLumpBase;
static signed int totalFrags[MAXPLAYERS];
static int HubCount;
static char *HubText;
// CODE --------------------------------------------------------------------
//========================================================================
//
// IN_Start
//
//========================================================================
extern void AM_Stop (void);
void IN_Start(void)
{
int i;
I_SetPalette(W_CacheLumpName("PLAYPAL", PU_CACHE));
InitStats();
LoadPics();
intermission = true;
interstate = 0;
skipintermission = false;
intertime = 0;
AM_Stop();
for(i = 0; i < MAXPLAYERS; i++)
{
players[i].messageTics = 0;
players[i].message[0] = 0;
}
SN_StopAllSequences();
}
//========================================================================
//
// WaitStop
//
//========================================================================
void WaitStop(void)
{
if(!--cnt)
{
Stop();
// gamestate = GS_LEVEL;
// G_DoLoadLevel();
gameaction = ga_leavemap;
// G_WorldDone();
}
}
//========================================================================
//
// Stop
//
//========================================================================
static void Stop(void)
{
intermission = false;
UnloadPics();
SB_state = -1;
BorderNeedRefresh = true;
}
//========================================================================
//
// InitStats
//
// Initializes the stats for single player mode
//========================================================================
static char *ClusMsgLumpNames[] =
{
"clus1msg",
"clus2msg",
"clus3msg",
"clus4msg",
"clus5msg"
};
static void InitStats(void)
{
int i;
int j;
int oldCluster;
signed int slaughterfrags;
int posnum;
int slaughtercount;
int playercount;
char *msgLumpName;
int msgSize;
int msgLump;
extern int LeaveMap;
if(!deathmatch)
{
gametype = SINGLE;
HubCount = 0;
oldCluster = P_GetMapCluster(gamemap);
if(oldCluster != P_GetMapCluster(LeaveMap))
{
if(oldCluster >= 1 && oldCluster <= 5)
{
msgLumpName = ClusMsgLumpNames[oldCluster-1];
msgLump = W_GetNumForName(msgLumpName);
msgSize = W_LumpLength(msgLump);
if(msgSize >= MAX_INTRMSN_MESSAGE_SIZE)
{
I_Error("Cluster message too long (%s)", msgLumpName);
}
W_ReadLump(msgLump, ClusterMessage);
ClusterMessage[msgSize] = 0; // Append terminator
HubText = ClusterMessage;
HubCount = strlen(HubText)*TEXTSPEED+TEXTWAIT;
S_StartSongName("hub", true);
}
}
}
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];
}
}
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;
}
S_StartSongName("hub", true);
}
}
//========================================================================
//
// LoadPics
//
//========================================================================
static void LoadPics(void)
{
int i;
if(HubCount || gametype == DEATHMATCH)
{
patchINTERPIC = W_CacheLumpName("INTERPIC", 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);
FontABaseLump = W_GetNumForName("FONTA_S")+1;
FontBSlash = W_CacheLumpName("FONTB15", PU_STATIC);
FontBPercent = W_CacheLumpName("FONTB05", PU_STATIC);
}
}
//========================================================================
//
// UnloadPics
//
//========================================================================
static void UnloadPics(void)
{
int i;
if(HubCount || gametype == DEATHMATCH)
{
Z_ChangeTag(patchINTERPIC, 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)
{
WaitStop();
return;
}
skipintermission = false;
CheckForSkip();
intertime++;
if(skipintermission || (gametype == SINGLE && !HubCount))
{
interstate = 1;
cnt = 10;
skipintermission = false;
//S_StartSound(NULL, sfx_dorcls);
}
}
//========================================================================
//
// CheckForSkip
//
// Check to see if any player hit a key
//========================================================================
static void CheckForSkip(void)
{
int i;
player_t *player;
static boolean triedToSkip;
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;
}
}
}
if(deathmatch && intertime < 140)
{ // wait for 4 seconds before allowing a skip
if(skipintermission == 1)
{
triedToSkip = true;
skipintermission = 0;
}
}
else
{
if(triedToSkip)
{
skipintermission = 1;
triedToSkip = false;
}
}
}
//========================================================================
//
// IN_Drawer
//
//========================================================================
void IN_Drawer(void)
{
if(!intermission)
{
return;
}
if(interstate)
{
return;
}
UpdateState |= I_FULLSCRN;
memcpy(screen, (byte *)patchINTERPIC, SCREENWIDTH*SCREENHEIGHT);
if(gametype == SINGLE)
{
if(HubCount)
{
DrawHubText();
}
}
else
{
DrDeathTally();
}
}
//========================================================================
//
// DrDeathTally
//
//========================================================================
#define TALLY_EFFECT_TICKS 20
#define TALLY_FINAL_X_DELTA (23*FRACUNIT)
#define TALLY_FINAL_Y_DELTA (13*FRACUNIT)
#define TALLY_START_XPOS (178*FRACUNIT)
#define TALLY_STOP_XPOS (90*FRACUNIT)
#define TALLY_START_YPOS (132*FRACUNIT)
#define TALLY_STOP_YPOS (83*FRACUNIT)
#define TALLY_TOP_X 85
#define TALLY_TOP_Y 9
#define TALLY_LEFT_X 7
#define TALLY_LEFT_Y 71
#define TALLY_TOTALS_X 291
static void DrDeathTally(void)
{
int i, j;
fixed_t xPos, yPos;
fixed_t xDelta, yDelta;
fixed_t xStart, scale;
int x, y;
boolean bold;
static boolean showTotals;
int temp;
V_DrawPatch(TALLY_TOP_X, TALLY_TOP_Y,
W_CacheLumpName("tallytop", PU_CACHE));
V_DrawPatch(TALLY_LEFT_X, TALLY_LEFT_Y,
W_CacheLumpName("tallylft", PU_CACHE));
if(intertime < TALLY_EFFECT_TICKS)
{
showTotals = false;
scale = (intertime*FRACUNIT)/TALLY_EFFECT_TICKS;
xDelta = FixedMul(scale, TALLY_FINAL_X_DELTA);
yDelta = FixedMul(scale, TALLY_FINAL_Y_DELTA);
xStart = TALLY_START_XPOS-FixedMul(scale,
TALLY_START_XPOS-TALLY_STOP_XPOS);
yPos = TALLY_START_YPOS-FixedMul(scale,
TALLY_START_YPOS-TALLY_STOP_YPOS);
}
else
{
xDelta = TALLY_FINAL_X_DELTA;
yDelta = TALLY_FINAL_Y_DELTA;
xStart = TALLY_STOP_XPOS;
yPos = TALLY_STOP_YPOS;
}
if(intertime >= TALLY_EFFECT_TICKS && showTotals == false)
{
showTotals = true;
S_StartSound(NULL, SFX_PLATFORM_STOP);
}
y = yPos>>FRACBITS;
for(i = 0; i < MAXPLAYERS; i++)
{
xPos = xStart;
for(j = 0; j < MAXPLAYERS; j++, xPos += xDelta)
{
x = xPos>>FRACBITS;
bold = (i == consoleplayer || j == consoleplayer);
if(playeringame[i] && playeringame[j])
{
if(bold)
{
DrNumberBold(players[i].frags[j], x, y, 100);
}
else
{
DrNumber(players[i].frags[j], x, y, 100);
}
}
else
{
temp = MN_TextAWidth("--")/2;
if(bold)
{
MN_DrTextAYellow("--", x-temp, y);
}
else
{
MN_DrTextA("--", x-temp, y);
}
}
}
if(showTotals && playeringame[i]
&& !((slaughterboy&(1<<i)) && !(intertime&16)))
{
DrNumber(totalFrags[i], TALLY_TOTALS_X, y, 1000);
}
yPos += yDelta;
y = yPos>>FRACBITS;
}
}
//==========================================================================
//
// DrNumber
//
//==========================================================================
static void DrNumber(int val, int x, int y, int wrapThresh)
{
char buff[8] = "XX";
if(!(val < -9 && wrapThresh < 1000))
{
sprintf(buff, "%d", val >= wrapThresh ? val%wrapThresh : val);
}
MN_DrTextA(buff, x-MN_TextAWidth(buff)/2, y);
}
//==========================================================================
//
// DrNumberBold
//
//==========================================================================
static void DrNumberBold(int val, int x, int y, int wrapThresh)
{
char buff[8] = "XX";
if(!(val < -9 && wrapThresh < 1000))
{
sprintf(buff, "%d", val >= wrapThresh ? val%wrapThresh : val);
}
MN_DrTextAYellow(buff, x-MN_TextAWidth(buff)/2, y);
}
//===========================================================================
//
// DrawHubText
//
//===========================================================================
static void DrawHubText(void)
{
int count;
char *ch;
int c;
int cx, cy;
patch_t *w;
cy = 5;
cx = 10;
ch = HubText;
count = (intertime-10)/TEXTSPEED;
if (count < 0)
{
count = 0;
}
for(; count; count--)
{
c = *ch++;
if(!c)
{
break;
}
if(c == '\n')
{
cx = 10;
cy += 9;
continue;
}
if(c < 32)
{
continue;
}
c = toupper(c);
if(c == 32)
{
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;
}
}

1023
Hexen Source/I_CDMUS.C Normal file

File diff suppressed because it is too large Load Diff

26
Hexen Source/I_CDMUS.H Normal file
View File

@ -0,0 +1,26 @@
// i_cdmus.h
#ifndef __ICDMUS__
#define __ICDMUS__
#define CDERR_NOTINSTALLED 10 // MSCDEX not installed
#define CDERR_NOAUDIOSUPPORT 11 // CD-ROM Doesn't support audio
#define CDERR_NOAUDIOTRACKS 12 // Current CD has no audio tracks
#define CDERR_BADDRIVE 20 // Bad drive number
#define CDERR_BADTRACK 21 // Bad track number
#define CDERR_IOCTLBUFFMEM 22 // Not enough low memory for IOCTL
#define CDERR_DEVREQBASE 100 // DevReq errors
extern int cd_Error;
int I_CDMusInit(void);
int I_CDMusPlay(int track);
int I_CDMusStop(void);
int I_CDMusResume(void);
int I_CDMusSetVolume(int volume);
int I_CDMusFirstTrack(void);
int I_CDMusLastTrack(void);
int I_CDMusTrackLength(int track);
#endif

277
Hexen Source/I_CYBER.C Normal file
View File

@ -0,0 +1,277 @@
// I_cyber.c
#include <dos.h>
#include <stdlib.h>
#include <string.h>
#include "st_start.h" // For ST_Message()
// Prototypes
unsigned char *I_AllocLow (int length);
/*
====================================================
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.
====================================================
*/
/* old ticcmd_t
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;
*/
// ticcmd_t as it appears in h2def.h
typedef struct
{
char forwardmove;
char sidemove;
short angleturn;
short consistancy;
unsigned char chatchar;
unsigned char buttons;
unsigned char lookfly;
unsigned char arti;
}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;
ST_Message(" CyberMan: ");
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, &regs, &regs, &sregs );
if ((short)RMI.EAX != 1)
{
// SWIFT functions not present
ST_Message("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)
{
ST_Message("no SWIFT device connected.\n");
}
else
{
ST_Message("SWIFT device is not a CyberMan! (type=%d)\n",
pbuf->deviceType);
}
}
else
{
ST_Message("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, &regs, &regs, &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, &regs, &regs, &sregs );
}

77
Hexen Source/I_HEADER.H Normal file
View File

@ -0,0 +1,77 @@
#ifndef __I_HEADER_H__
#define __I_HEADER_H__
#include "h2def.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

2782
Hexen Source/I_IBM.C Normal file

File diff suppressed because it is too large Load Diff

135
Hexen Source/I_IBM_A.ASM Normal file
View 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_
pushad
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
popad
mov eax,1 ; read was ok
ret
bad:
popf ; restore interrupt flag
popad
xor eax, eax ; read was bad
ret
ENDP
END

369
Hexen Source/I_SOUND.C Normal file
View File

@ -0,0 +1,369 @@
// I_SOUND.C
#include <stdio.h>
#include "h2def.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);
ST_Message(" I_StartupTimer()\n");
// 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) ST_Message(" MUS_Reg() returned %d\n", rc);
#endif
return rc;
}
void I_UnRegisterSong(int handle)
{
int rc = MUS_UnregisterSong(handle);
#ifdef SNDDEBUG
if (rc < 0) ST_Message(" MUS_Unreg() returned %d\n", rc);
#endif
}
int I_QrySongPlaying(int handle)
{
int rc = MUS_QrySongPlaying(handle);
#ifdef SNDDEBUG
if (rc < 0) ST_Message(" 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) ST_Message(" 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) ST_Message(" MUS_ChainSong() returned %d\n", rc);
#endif
rc = MUS_PlaySong(handle, snd_MusicVolume);
#ifdef SNDDEBUG
if (rc < 0) ST_Message(" 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)
{
return W_GetNumForName(sound->lumpname);
}
int I_StartSound (int id, void *data, int vol, int sep, int pitch, int priority)
{
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_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()) ST_Message(" Dude. The GUS ain't responding.\n");
else
{
dmxlump = W_GetNumForName("dmxgus");
GF1_SetMap(W_CacheLumpNum(dmxlump, PU_CACHE), lumpinfo[dmxlump].size);
}
}
if (sb)
{
if(debugmode)
{
ST_Message(" Sound cfg p=0x%x, i=%d, d=%d\n",
snd_SBport, snd_SBirq, snd_SBdma);
}
if (SB_Detect(&snd_SBport, &snd_SBirq, &snd_SBdma, 0))
{
ST_Message(" SB isn't responding at p=0x%x, i=%d, d=%d\n",
snd_SBport, snd_SBirq, snd_SBdma);
}
else SB_SetCard(snd_SBport, snd_SBirq, snd_SBdma);
if(debugmode)
{
ST_Message(" SB_Detect returned p=0x%x, i=%d, d=%d\n",
snd_SBport, snd_SBirq, snd_SBdma);
}
}
if (adlib)
{
if (AL_Detect(&wait,0))
{
ST_Message(" Dude. The Adlib isn't responding.\n");
}
else
{
AL_SetCard(wait, W_CacheLumpName("genmidi", PU_STATIC));
}
}
if (midi)
{
if (debugmode)
{
ST_Message(" cfg p=0x%x\n", snd_Mport);
}
if (MPU_Detect(&snd_Mport, &i))
{
ST_Message(" The MPU-401 isn't reponding @ p=0x%x.\n", snd_Mport);
}
else MPU_SetCard(snd_Mport);
}
}
// inits all sound stuff
void I_StartupSound (void)
{
int rc, i;
if (debugmode)
ST_Message("I_StartupSound: Hope you hear a pop.\n");
// 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_MPU2] = AHW_MPU_401;
dmxCodes[snd_MPU3] = AHW_MPU_401;
dmxCodes[snd_AWE] = AHW_AWE32;
dmxCodes[snd_CDMUSIC] = 0;
// inits sound library timer stuff
I_StartupTimer();
// pick the sound cards i'm going to use
//
I_sndArbitrateCards();
if (debugmode)
{
ST_Message(" Music device #%d & dmxCode=%d,", snd_MusicDevice,
dmxCodes[snd_MusicDevice]);
ST_Message(" Sfx device #%d & dmxCode=%d\n", snd_SfxDevice,
dmxCodes[snd_SfxDevice]);
}
// inits DMX sound library
ST_Message(" Calling DMX_Init...");
rc = DMX_Init(SND_TICRATE, SND_MAXSONGS, dmxCodes[snd_MusicDevice],
dmxCodes[snd_SfxDevice]);
if (debugmode)
{
ST_Message(" DMX_Init() returned %d\n", rc);
}
}
// shuts down all sound stuff
void I_ShutdownSound (void)
{
DMX_DeInit();
I_ShutdownTimer();
}
void I_SetChannels(int channels)
{
WAV_PlayMode(channels, SND_SAMPLERATE);
}

68
Hexen Source/I_SOUND.H Normal file
View File

@ -0,0 +1,68 @@
#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,
snd_CDMUSIC,
NUM_SCARDS
} cardenum_t;
void I_PauseSong(int handle);
void I_ResumeSong(int handle);
void I_SetMusicVolume(int volume);
void I_SetSfxVolume(int volume);
int I_RegisterSong(void *data);
void I_UnRegisterSong(int handle);
int I_QrySongPlaying(int handle);
void I_StopSong(int handle);
void I_PlaySong(int handle, int looping);
int I_GetSfxLumpNum(sfxinfo_t *sound);
int I_StartSound (int id, void *data, int vol, int sep, int pitch, int priority);
void I_StopSound(int handle);
int I_SoundIsPlaying(int handle);
void I_UpdateSoundParams(int handle, int vol, int sep, int pitch);
void I_sndArbitrateCards(void);
void I_StartupSound (void);
void I_ShutdownSound (void);
void I_SetChannels(int channels);
#endif
#ifndef __ICDMUS__
#define __ICDMUS__
#define CDERR_NOTINSTALLED 10 // MSCDEX not installed
#define CDERR_NOAUDIOSUPPORT 11 // CD-ROM Doesn't support audio
#define CDERR_NOAUDIOTRACKS 12 // Current CD has no audio tracks
#define CDERR_BADDRIVE 20 // Bad drive number
#define CDERR_BADTRACK 21 // Bad track number
#define CDERR_IOCTLBUFFMEM 22 // Not enough low memory for IOCTL
#define CDERR_DEVREQBASE 100 // DevReq errors
extern int cd_Error;
int I_CDMusInit(void);
int I_CDMusPlay(int track);
int I_CDMusStop(void);
int I_CDMusResume(void);
int I_CDMusSetVolume(int volume);
int I_CDMusFirstTrack(void);
int I_CDMusLastTrack(void);
int I_CDMusTrackLength(int track);
#endif

349
Hexen Source/LINEAR.ASM Normal file
View File

@ -0,0 +1,349 @@
.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
FUZZSCALEDEFINE MACRO number
dd fuzzvscale&number
ENDM
ALIGN 4
fuzzscalecalls LABEL
LINE = 0
REPT SCREENHEIGHT+1
FUZZSCALEDEFINE %LINE
LINE = LINE+1
ENDM
calladdr dd ?
;=================================
.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
;================
;
; R_DrawFuzz
;
;================
PROC R_DrawFuzzColumn_
PUBLIC R_DrawFuzzColumn_
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 fuzzdone
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
mov ebp, [fuzzscalecalls+4+ebp*4]
mov calladdr, ebp
mov ebp, ecx
xor ecx, ecx
call [calladdr]
fuzzdone:
POPR
ret
FUZZSCALELABEL MACRO number
fuzzvscale&number:
ENDM
LINE = SCREENHEIGHT
REPT SCREENHEIGHT-1
FUZZSCALELABEL %LINE
mov al, byte ptr [esi+ebx] ; get source pixel
add edx, ebp ; calculate next location
mov cl, byte ptr [edi-(LINE-1)*SCREENWIDTH]
mov ch, [eax]
add ecx, [_tinttable]
mov ebx, edx
shr ebx, 25
mov al, [ecx]
mov [edi-(LINE-1)*SCREENWIDTH],al ; draw a pixel to the buffer
xor ecx, ecx
LINE = LINE-1
ENDM
fuzzvscale1:
mov al,[esi+ebx]
mov cl, byte ptr [edi-(LINE-1)*SCREENWIDTH]
mov ch, [eax]
add ecx, [_tinttable]
mov al, [ecx]
mov [edi],al
fuzzvscale0:
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

50
Hexen Source/M.BAT Normal file
View File

@ -0,0 +1,50 @@
@REM Hexen make batch
@echo off
if "%1"=="/?" goto usage
if "%1"=="f" goto final
if "%1"=="F" goto final
if "%1"=="d" goto debug
if "%1"=="D" goto debug
goto normal
:usage
echo.
echo Hexen make batch
echo Usage: M [/?] [build-type]
echo.
echo build-type f = Final build (no RANGECHECK)
echo build-type d = Debug build (include debugging info)
echo.
goto end
:final
echo.
echo.
echo *** Building Hexen FINAL executable
echo.
echo.
shift
wmake hex.exe EXTERNOPT=/dNORANGECHECKING %1 %2 %3 %4 %5 %6 %7 %8 %9
goto end
:debug
echo.
echo.
echo *** Building Hexen DEBUG executable
echo.
echo.
shift
wmake hex.exe EXTERNOPT=/d2 %1 %2 %3 %4 %5 %6 %7 %8 %9
goto end
:normal
echo.
echo.
echo *** Building Hexen DEVELOPMENT executable
echo.
echo.
wmake hex.exe %1 %2 %3 %4 %5 %6 %7 %8 %9
goto end
:end

1
Hexen Source/MAKE.BAT Normal file
View File

@ -0,0 +1 @@
wmake

120
Hexen Source/MAKEFILE Normal file
View File

@ -0,0 +1,120 @@
# --------------------------------------------------------------------------
#
# WCC386 Options:
#
# 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
#
# --------------------------------------------------------------------------
LOCOBJS = &
i_cdmus.obj &
i_cyber.obj &
i_ibm.obj &
i_ibm_a.obj &
i_sound.obj &
linear.obj
GLOBOBJS = &
am_map.obj &
a_action.obj &
ct_chat.obj &
d_net.obj &
f_finale.obj &
g_game.obj &
h2_main.obj &
info.obj &
in_lude.obj &
mn_menu.obj &
m_misc.obj &
p_acs.obj &
p_anim.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_things.obj &
p_user.obj &
po_man.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 &
sc_man.obj &
sn_sonix.obj &
st_start.obj &
sv_save.obj &
sounds.obj &
tables.obj &
v_video.obj &
w_wad.obj &
z_zone.obj
default: .SYMBOLIC
@echo.
@echo You must use M.BAT to build Hexen.
@echo Type "M /?" for help.
@echo.
#
# DEBUG Build:
#
# The EXTERNOPT macro should be set to /d2
#
# FINAL Build:
#
# The EXTERNOPT macro should be set to /dNORANGECHECKING
#
VERSION_ID = BCP
VERSIONOPT = /dVER_ID="$(VERSION_ID)"
CCOPTS = $(EXTERNOPT) $(VERSIONOPT) /omaxet /zp1 /4r /ei /j /zq /i=dmx
hex.exe : $(LOCOBJS) $(GLOBOBJS)
wlink @hex.lnk
ncopy hex.exe striphex.exe
wstrip striphex.exe
4gwbind 4gwpro.exe striphex.exe hexen.exe -V
ncopy hex.map v_$(VERSION_ID).map
prsucc
.c.obj :
wcc386 $(CCOPTS) $[*
.asm.obj :
tasm /mx $[*

1743
Hexen Source/MN_MENU.C Normal file

File diff suppressed because it is too large Load Diff

878
Hexen Source/M_MISC.C Normal file
View File

@ -0,0 +1,878 @@
//**************************************************************************
//**
//** m_misc.c : Heretic 2 : Raven Software, Corp.
//**
//** $RCSfile: m_misc.c,v $
//** $Revision: 1.18 $
//** $Date: 96/01/07 16:51:18 $
//** $Author: bgokey $
//**
//**************************************************************************
// HEADER FILES ------------------------------------------------------------
#ifdef __NeXT__
#include <libc.h>
#else
#include <sys/stat.h>
#include <sys/types.h>
#include <direct.h>
#include <fcntl.h>
#include <stdlib.h>
#include <io.h>
#include <conio.h>
#endif
#include <ctype.h>
#include "h2def.h"
#include "p_local.h"
#include "soundst.h"
// MACROS ------------------------------------------------------------------
#define MALLOC_CLIB 1
#define MALLOC_ZONE 2
// TYPES -------------------------------------------------------------------
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
// PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
static int ReadFile(char const *name, byte **buffer, int mallocType);
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
extern char *SavePath;
// PUBLIC DATA DEFINITIONS -------------------------------------------------
int myargc;
char **myargv;
// PRIVATE DATA DEFINITIONS ------------------------------------------------
// CODE --------------------------------------------------------------------
//==========================================================================
//
// 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_ParmExists
//
// Returns true if the given parameter exists in the program's command
// line arguments, false if not.
//
//==========================================================================
boolean M_ParmExists(char *check)
{
return M_CheckParm(check) != 0 ? true : false;
}
//==========================================================================
//
// M_ExtractFileBase
//
//==========================================================================
void M_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++);
}
}
/*
===============
=
= M_Random
=
= Returns a 0-255 number
=
===============
*/
// This is the new flat distribution table
unsigned char rndtable[256] = {
201, 1,243, 19, 18, 42,183,203,101,123,154,137, 34,118, 10,216,
135,246, 0,107,133,229, 35,113,177,211,110, 17,139, 84,251,235,
182,166,161,230,143, 91, 24, 81, 22, 94, 7, 51,232,104,122,248,
175,138,127,171,222,213, 44, 16, 9, 33, 88,102,170,150,136,114,
62, 3,142,237, 6,252,249, 56, 74, 30, 13, 21,180,199, 32,132,
187,234, 78,210, 46,131,197, 8,206,244, 73, 4,236,178,195, 70,
121, 97,167,217,103, 40,247,186,105, 39, 95,163, 99,149,253, 29,
119, 83,254, 26,202, 65,130,155, 60, 64,184,106,221, 93,164,196,
112,108,179,141, 54,109, 11,126, 75,165,191,227, 87,225,156, 15,
98,162,116, 79,169,140,190,205,168,194, 41,250, 27, 20, 14,241,
50,214, 72,192,220,233, 67,148, 96,185,176,181,215,207,172, 85,
89, 90,209,128,124, 2, 55,173, 66,152, 47,129, 59, 43,159,240,
239, 12,189,212,144, 28,200, 77,219,198,134,228, 45, 92,125,151,
5, 53,255, 52, 68,245,160,158, 61, 86, 58, 82,117, 37,242,145,
69,188,115, 76, 63,100, 49,111,153, 80, 38, 57,174,224, 71,231,
23, 25, 48,218,120,147,208, 36,226,223,193,238,157,204,146, 31
};
int rndindex = 0;
int prndindex = 0;
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
//
// Read a file into a buffer allocated using Z_Malloc().
//
//==========================================================================
int M_ReadFile(char const *name, byte **buffer)
{
return ReadFile(name, buffer, MALLOC_ZONE);
}
//==========================================================================
//
// M_ReadFileCLib
//
// Read a file into a buffer allocated using malloc().
//
//==========================================================================
int M_ReadFileCLib(char const *name, byte **buffer)
{
return ReadFile(name, buffer, MALLOC_CLIB);
}
//==========================================================================
//
// ReadFile
//
//==========================================================================
static int ReadFile(char const *name, byte **buffer, int mallocType)
{
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;
if(mallocType == MALLOC_ZONE)
{ // Use zone memory allocation
buf = Z_Malloc(length, PU_STATIC, NULL);
}
else
{ // Use c library memory allocation
buf = malloc(length);
if(buf == NULL)
{
I_Error("Couldn't malloc buffer %d for file %s.",
length, name);
}
}
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);
}
ST_Message("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"))
{
ST_Message("%d command-line args:\n", myargc);
for(k = 1; k < myargc; k++)
{
ST_Message("%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, key_jump;
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 mousebjump;
extern int joybfire;
extern int joybstrafe;
extern int joybuse;
extern int joybspeed;
extern int joybjump;
extern boolean messageson;
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
#define SC_SLASH 0X35
{ "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_jump", &key_jump, SC_SLASH, 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_jump", &key_jump, '/'},
{ "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 },
{ "mouseb_jump", &mousebjump, -1 },
{ "use_joystick", &usejoystick, 0 },
{ "joyb_fire", &joybfire, 0 },
{ "joyb_strafe", &joybstrafe, 1 },
{ "joyb_use", &joybuse, 3 },
{ "joyb_speed", &joybspeed, 2 },
{ "joyb_jump", &joybjump, -1 },
{ "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 },
#ifdef __NeXT__
#define DEFAULT_SAVEPATH "hexndata/"
#endif
#ifdef __WATCOMC__
#define DEFAULT_SAVEPATH "hexndata\\"
#endif
{ "savedir", (int *) &SavePath, (int) DEFAULT_SAVEPATH },
{ "messageson", (int *) &messageson, 1 },
{ "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[128];
/*
==============
=
= 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];
void M_LoadDefaults(char *fileName)
{
int i;
int 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 config file
i = M_CheckParm("-config");
if(i && i < myargc-1)
{
strcpy(defaultfile, myargv[i+1]);
ST_Message("config file: %s\n", defaultfile);
}
else if(cdrom)
{
sprintf(defaultfile, "c:\\hexndata\\%s", fileName);
}
else
{
strcpy(defaultfile, fileName);
}
// Scan the config file
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);
if (newstring == NULL) I_Error("can't malloc newstring");
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__
// Translate the key scancodes
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,"HEXEN00.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);
P_SetMessage(&players[consoleplayer], "SCREEN SHOT", false);
#ifdef __WATCOMC__
Z_Free(pal);
#endif
}

790
Hexen Source/OLDD_NET.C Normal file
View 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++;
}
}

1482
Hexen Source/PO_MAN.C Normal file

File diff suppressed because it is too large Load Diff

1782
Hexen Source/P_ACS.C Normal file

File diff suppressed because it is too large Load Diff

473
Hexen Source/P_ANIM.C Normal file
View File

@ -0,0 +1,473 @@
//**************************************************************************
//**
//** p_anim.c : Heretic 2 : Raven Software, Corp.
//**
//** $RCSfile: p_anim.c,v $
//** $Revision: 1.9 $
//** $Date: 95/07/17 18:50:37 $
//** $Author: bgokey $
//**
//**************************************************************************
// HEADER FILES ------------------------------------------------------------
#include "h2def.h"
#include "p_local.h"
// MACROS ------------------------------------------------------------------
#define ANIM_SCRIPT_NAME "ANIMDEFS"
#define MAX_ANIM_DEFS 20
#define MAX_FRAME_DEFS 96
#define ANIM_FLAT 0
#define ANIM_TEXTURE 1
#define SCI_FLAT "flat"
#define SCI_TEXTURE "texture"
#define SCI_PIC "pic"
#define SCI_TICS "tics"
#define SCI_RAND "rand"
#define LIGHTNING_SPECIAL 198
#define LIGHTNING_SPECIAL2 199
#define SKYCHANGE_SPECIAL 200
// TYPES -------------------------------------------------------------------
typedef struct
{
int index;
int tics;
} frameDef_t;
typedef struct
{
int type;
int index;
int tics;
int currentFrameDef;
int startFrameDef;
int endFrameDef;
} animDef_t;
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
// PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
static void P_LightningFlash(void);
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
extern fixed_t Sky1ColumnOffset;
extern fixed_t Sky2ColumnOffset;
extern int Sky1Texture;
extern boolean DoubleSky;
// PUBLIC DATA DEFINITIONS -------------------------------------------------
fixed_t Sky1ScrollDelta;
fixed_t Sky2ScrollDelta;
// PRIVATE DATA DEFINITIONS ------------------------------------------------
static animDef_t AnimDefs[MAX_ANIM_DEFS];
static frameDef_t FrameDefs[MAX_FRAME_DEFS];
static int AnimDefCount;
static boolean LevelHasLightning;
static int NextLightningFlash;
static int LightningFlash;
static int *LightningLightLevels;
// CODE --------------------------------------------------------------------
//==========================================================================
//
// P_AnimateSurfaces
//
//==========================================================================
void P_AnimateSurfaces(void)
{
int i;
animDef_t *ad;
line_t *line;
// Animate flats and textures
for(i = 0; i < AnimDefCount; i++)
{
ad = &AnimDefs[i];
ad->tics--;
if(ad->tics == 0)
{
if(ad->currentFrameDef == ad->endFrameDef)
{
ad->currentFrameDef = ad->startFrameDef;
}
else
{
ad->currentFrameDef++;
}
ad->tics = FrameDefs[ad->currentFrameDef].tics;
if(ad->tics > 255)
{ // Random tics
ad->tics = (ad->tics>>16)
+P_Random()%((ad->tics&0xff00)>>8);
}
if(ad->type == ANIM_FLAT)
{
flattranslation[ad->index] =
FrameDefs[ad->currentFrameDef].index;
}
else
{ // Texture
texturetranslation[ad->index] =
FrameDefs[ad->currentFrameDef].index;
}
}
}
// Update scrolling textures
for(i = 0; i < numlinespecials; i++)
{
line = linespeciallist[i];
switch(line->special)
{
case 100: // Scroll_Texture_Left
sides[line->sidenum[0]].textureoffset += line->arg1<<10;
break;
case 101: // Scroll_Texture_Right
sides[line->sidenum[0]].textureoffset -= line->arg1<<10;
break;
case 102: // Scroll_Texture_Up
sides[line->sidenum[0]].rowoffset += line->arg1<<10;
break;
case 103: // Scroll_Texture_Down
sides[line->sidenum[0]].rowoffset -= line->arg1<<10;
break;
}
}
// Update sky column offsets
Sky1ColumnOffset += Sky1ScrollDelta;
Sky2ColumnOffset += Sky2ScrollDelta;
if(LevelHasLightning)
{
if(!NextLightningFlash || LightningFlash)
{
P_LightningFlash();
}
else
{
NextLightningFlash--;
}
}
}
//==========================================================================
//
// P_LightningFlash
//
//==========================================================================
static void P_LightningFlash(void)
{
int i;
sector_t *tempSec;
int *tempLight;
boolean foundSec;
int flashLight;
if(LightningFlash)
{
LightningFlash--;
if(LightningFlash)
{
tempLight = LightningLightLevels;
tempSec = sectors;
for(i = 0; i < numsectors; i++, tempSec++)
{
if(tempSec->ceilingpic == skyflatnum
|| tempSec->special == LIGHTNING_SPECIAL
|| tempSec->special == LIGHTNING_SPECIAL2)
{
if(*tempLight < tempSec->lightlevel-4)
{
tempSec->lightlevel -= 4;
}
tempLight++;
}
}
}
else
{ // remove the alternate lightning flash special
tempLight = LightningLightLevels;
tempSec = sectors;
for(i = 0; i < numsectors; i++, tempSec++)
{
if(tempSec->ceilingpic == skyflatnum
|| tempSec->special == LIGHTNING_SPECIAL
|| tempSec->special == LIGHTNING_SPECIAL2)
{
tempSec->lightlevel = *tempLight;
tempLight++;
}
}
Sky1Texture = P_GetMapSky1Texture(gamemap);
}
return;
}
LightningFlash = (P_Random()&7)+8;
flashLight = 200+(P_Random()&31);
tempSec = sectors;
tempLight = LightningLightLevels;
foundSec = false;
for(i = 0; i < numsectors; i++, tempSec++)
{
if(tempSec->ceilingpic == skyflatnum
|| tempSec->special == LIGHTNING_SPECIAL
|| tempSec->special == LIGHTNING_SPECIAL2)
{
*tempLight = tempSec->lightlevel;
if(tempSec->special == LIGHTNING_SPECIAL)
{
tempSec->lightlevel += 64;
if(tempSec->lightlevel > flashLight)
{
tempSec->lightlevel = flashLight;
}
}
else if(tempSec->special == LIGHTNING_SPECIAL2)
{
tempSec->lightlevel += 32;
if(tempSec->lightlevel > flashLight)
{
tempSec->lightlevel = flashLight;
}
}
else
{
tempSec->lightlevel = flashLight;
}
if(tempSec->lightlevel < *tempLight)
{
tempSec->lightlevel = *tempLight;
}
tempLight++;
foundSec = true;
}
}
if(foundSec)
{
Sky1Texture = P_GetMapSky2Texture(gamemap); // set alternate sky
S_StartSound(NULL, SFX_THUNDER_CRASH);
}
// Calculate the next lighting flash
if(!NextLightningFlash)
{
if(P_Random() < 50)
{ // Immediate Quick flash
NextLightningFlash = (P_Random()&15)+16;
}
else
{
if(P_Random() < 128 && !(leveltime&32))
{
NextLightningFlash = ((P_Random()&7)+2)*35;
}
else
{
NextLightningFlash = ((P_Random()&15)+5)*35;
}
}
}
}
//==========================================================================
//
// P_ForceLightning
//
//==========================================================================
void P_ForceLightning(void)
{
NextLightningFlash = 0;
}
//==========================================================================
//
// P_InitLightning
//
//==========================================================================
void P_InitLightning(void)
{
int i;
int secCount;
if(!P_GetMapLightning(gamemap))
{
LevelHasLightning = false;
LightningFlash = 0;
return;
}
LightningFlash = 0;
secCount = 0;
for(i = 0; i < numsectors; i++)
{
if(sectors[i].ceilingpic == skyflatnum
|| sectors[i].special == LIGHTNING_SPECIAL
|| sectors[i].special == LIGHTNING_SPECIAL2)
{
secCount++;
}
}
if(secCount)
{
LevelHasLightning = true;
}
else
{
LevelHasLightning = false;
return;
}
LightningLightLevels = (int *)Z_Malloc(secCount*sizeof(int), PU_LEVEL,
NULL);
NextLightningFlash = ((P_Random()&15)+5)*35; // don't flash at level start
}
//==========================================================================
//
// P_InitFTAnims
//
// Initialize flat and texture animation lists.
//
//==========================================================================
void P_InitFTAnims(void)
{
int base;
int mod;
int fd;
animDef_t *ad;
boolean ignore;
boolean done;
fd = 0;
ad = AnimDefs;
AnimDefCount = 0;
SC_Open(ANIM_SCRIPT_NAME);
while(SC_GetString())
{
if(AnimDefCount == MAX_ANIM_DEFS)
{
I_Error("P_InitFTAnims: too many AnimDefs.");
}
if(SC_Compare(SCI_FLAT))
{
ad->type = ANIM_FLAT;
}
else if(SC_Compare(SCI_TEXTURE))
{
ad->type = ANIM_TEXTURE;
}
else
{
SC_ScriptError(NULL);
}
SC_MustGetString(); // Name
ignore = false;
if(ad->type == ANIM_FLAT)
{
if(W_CheckNumForName(sc_String) == -1)
{
ignore = true;
}
else
{
ad->index = R_FlatNumForName(sc_String);
}
}
else
{ // Texture
if(R_CheckTextureNumForName(sc_String) == -1)
{
ignore = true;
}
else
{
ad->index = R_TextureNumForName(sc_String);
}
}
ad->startFrameDef = fd;
done = false;
while(done == false)
{
if(SC_GetString())
{
if(SC_Compare(SCI_PIC))
{
if(fd == MAX_FRAME_DEFS)
{
I_Error("P_InitFTAnims: too many FrameDefs.");
}
SC_MustGetNumber();
if(ignore == false)
{
FrameDefs[fd].index = ad->index+sc_Number-1;
}
SC_MustGetString();
if(SC_Compare(SCI_TICS))
{
SC_MustGetNumber();
if(ignore == false)
{
FrameDefs[fd].tics = sc_Number;
fd++;
}
}
else if(SC_Compare(SCI_RAND))
{
SC_MustGetNumber();
base = sc_Number;
SC_MustGetNumber();
if(ignore == false)
{
mod = sc_Number-base+1;
FrameDefs[fd].tics = (base<<16)+(mod<<8);
fd++;
}
}
else
{
SC_ScriptError(NULL);
}
}
else
{
SC_UnGet();
done = true;
}
}
else
{
done = true;
}
}
if((ignore == false) && (fd-ad->startFrameDef < 2))
{
I_Error("P_InitFTAnims: AnimDef has framecount < 2.");
}
if(ignore == false)
{
ad->endFrameDef = fd-1;
ad->currentFrameDef = ad->endFrameDef;
ad->tics = 1; // Force 1st game tic to animate
AnimDefCount++;
ad++;
}
}
SC_Close();
}

294
Hexen Source/P_CEILNG.C Normal file
View File

@ -0,0 +1,294 @@
//**************************************************************************
//**
//** p_ceilng.c : Heretic 2 : Raven Software, Corp.
//**
//** $RCSfile: p_ceilng.c,v $
//** $Revision: 1.17 $
//** $Date: 95/09/11 22:06:25 $
//** $Author: cjr $
//**
//**************************************************************************
#include "h2def.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 (res == RES_PASTDEST)
{
SN_StopSequence((mobj_t *)&ceiling->sector->soundorg);
switch(ceiling->type)
{
case CLEV_CRUSHANDRAISE:
ceiling->direction = -1;
ceiling->speed = ceiling->speed*2;
break;
default:
P_RemoveActiveCeiling(ceiling);
break;
}
}
break;
case -1: // DOWN
res = T_MovePlane(ceiling->sector,ceiling->speed,
ceiling->bottomheight, ceiling->crush, 1, ceiling->direction);
if(res == RES_PASTDEST)
{
SN_StopSequence((mobj_t *)&ceiling->sector->soundorg);
switch(ceiling->type)
{
case CLEV_CRUSHANDRAISE:
case CLEV_CRUSHRAISEANDSTAY:
ceiling->direction = 1;
ceiling->speed = ceiling->speed/2;
break;
default:
P_RemoveActiveCeiling(ceiling);
break;
}
}
else if(res == RES_CRUSHED)
{
switch(ceiling->type)
{
case CLEV_CRUSHANDRAISE:
case CLEV_LOWERANDCRUSH:
case CLEV_CRUSHRAISEANDSTAY:
//ceiling->speed = ceiling->speed/4;
break;
default:
break;
}
}
break;
}
}
//==================================================================
//
// EV_DoCeiling
// Move a ceiling up/down and all around!
//
//==================================================================
int EV_DoCeiling (line_t *line, byte *arg, ceiling_e type)
{
int secnum,rtn;
sector_t *sec;
ceiling_t *ceiling;
secnum = -1;
rtn = 0;
/* Old Ceiling stasis code
//
// Reactivate in-stasis ceilings...for certain types.
//
switch(type)
{
case CLEV_CRUSHANDRAISE:
P_ActivateInStasisCeiling(line);
default:
break;
}
*/
while ((secnum = P_FindSectorFromTag(arg[0], secnum)) >= 0)
{
sec = &sectors[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 = 0;
ceiling->speed = arg[1]*(FRACUNIT/8);
switch(type)
{
case CLEV_CRUSHRAISEANDSTAY:
ceiling->crush = arg[2]; // arg[2] = crushing value
ceiling->topheight = sec->ceilingheight;
ceiling->bottomheight = sec->floorheight + (8*FRACUNIT);
ceiling->direction = -1;
break;
case CLEV_CRUSHANDRAISE:
ceiling->topheight = sec->ceilingheight;
case CLEV_LOWERANDCRUSH:
ceiling->crush = arg[2]; // arg[2] = crushing value
case CLEV_LOWERTOFLOOR:
ceiling->bottomheight = sec->floorheight;
if(type != CLEV_LOWERTOFLOOR)
{
ceiling->bottomheight += 8*FRACUNIT;
}
ceiling->direction = -1;
break;
case CLEV_RAISETOHIGHEST:
ceiling->topheight = P_FindHighestCeilingSurrounding(sec);
ceiling->direction = 1;
break;
case CLEV_LOWERBYVALUE:
ceiling->bottomheight = sec->ceilingheight-arg[2]*FRACUNIT;
ceiling->direction = -1;
break;
case CLEV_RAISEBYVALUE:
ceiling->topheight = sec->ceilingheight+arg[2]*FRACUNIT;
ceiling->direction = 1;
break;
case CLEV_MOVETOVALUETIMES8:
{
int destHeight = arg[2]*FRACUNIT*8;
if(arg[3])
{
destHeight = -destHeight;
}
if(sec->ceilingheight <= destHeight)
{
ceiling->direction = 1;
ceiling->topheight = destHeight;
if(sec->ceilingheight == destHeight)
{
rtn = 0;
}
}
else if(sec->ceilingheight > destHeight)
{
ceiling->direction = -1;
ceiling->bottomheight = destHeight;
}
break;
}
default:
rtn = 0;
break;
}
ceiling->tag = sec->tag;
ceiling->type = type;
P_AddActiveCeiling(ceiling);
if(rtn)
{
SN_StartSequence((mobj_t *)&ceiling->sector->soundorg,
SEQ_PLATFORM+ceiling->sector->seqType);
}
}
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);
P_TagFinished(activeceilings[i]->sector->tag);
activeceilings[i] = NULL;
break;
}
}
#if 0
//==================================================================
//
// 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->arg1) &&
(activeceilings[i]->direction == 0))
{
activeceilings[i]->direction = activeceilings[i]->olddirection;
activeceilings[i]->thinker.function = T_MoveCeiling;
SN_StartSequence((mobj_t *)&activeceilings[i]->sector->soundorg,
SEQ_PLATFORM+activeceilings[i]->sector->seqType);
}
}
#endif
//==================================================================
//
// EV_CeilingCrushStop
// Stop a ceiling from crushing!
//
//==================================================================
int EV_CeilingCrushStop(line_t *line, byte *args)
{
int i;
int rtn;
rtn = 0;
for (i = 0;i < MAXCEILINGS;i++)
{
if(activeceilings[i] && activeceilings[i]->tag == args[0])
{
rtn = 1;
SN_StopSequence((mobj_t*)&activeceilings[i]->sector->soundorg);
activeceilings[i]->sector->specialdata = NULL;
P_RemoveThinker (&activeceilings[i]->thinker);
P_TagFinished(activeceilings[i]->sector->tag);
activeceilings[i] = NULL;
break;
}
}
return rtn;
}

314
Hexen Source/P_DOORS.C Normal file
View File

@ -0,0 +1,314 @@
//**************************************************************************
//**
//** p_doors.c : Heretic 2 : Raven Software, Corp.
//**
//** $RCSfile: p_doors.c,v $
//** $Revision: 1.13 $
//** $Date: 96/01/06 03:23:47 $
//** $Author: bgokey $
//**
//**************************************************************************
#include "h2def.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 DREV_NORMAL:
door->direction = -1; // time to go back down
SN_StartSequence((mobj_t *)&door->sector->soundorg,
SEQ_DOOR_STONE+door->sector->seqType);
break;
case DREV_CLOSE30THENOPEN:
door->direction = 1;
break;
default:
break;
}
break;
case 2: // INITIAL WAIT
if(!--door->topcountdown)
{
switch(door->type)
{
case DREV_RAISEIN5MINS:
door->direction = 1;
door->type = DREV_NORMAL;
break;
default:
break;
}
}
break;
case -1: // DOWN
res = T_MovePlane(door->sector, door->speed,
door->sector->floorheight, false, 1, door->direction);
if(res == RES_PASTDEST)
{
SN_StopSequence((mobj_t *)&door->sector->soundorg);
switch(door->type)
{
case DREV_NORMAL:
case DREV_CLOSE:
door->sector->specialdata = NULL;
P_TagFinished(door->sector->tag);
P_RemoveThinker(&door->thinker); // unlink and free
break;
case DREV_CLOSE30THENOPEN:
door->direction = 0;
door->topcountdown = 35*30;
break;
default:
break;
}
}
else if(res == RES_CRUSHED)
{
switch(door->type)
{
case DREV_CLOSE: // DON'T GO BACK UP!
break;
default:
door->direction = 1;
break;
}
}
break;
case 1: // UP
res = T_MovePlane(door->sector, door->speed,
door->topheight, false, 1, door->direction);
if(res == RES_PASTDEST)
{
SN_StopSequence((mobj_t *)&door->sector->soundorg);
switch(door->type)
{
case DREV_NORMAL:
door->direction = 0; // wait at top
door->topcountdown = door->topwait;
break;
case DREV_CLOSE30THENOPEN:
case DREV_OPEN:
door->sector->specialdata = NULL;
P_TagFinished(door->sector->tag);
P_RemoveThinker (&door->thinker); // unlink and free
break;
default:
break;
}
}
break;
}
}
//----------------------------------------------------------------------------
//
// EV_DoDoor
//
// Move a door up/down
//
//----------------------------------------------------------------------------
int EV_DoDoor(line_t *line, byte *args, vldoor_e type)
{
int secnum;
int retcode;
sector_t *sec;
vldoor_t *door;
fixed_t speed;
speed = args[1]*FRACUNIT/8;
secnum = -1;
retcode = 0;
while((secnum = P_FindSectorFromTag(args[0], secnum)) >= 0)
{
sec = &sectors[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 DREV_CLOSE:
door->topheight = P_FindLowestCeilingSurrounding(sec);
door->topheight -= 4*FRACUNIT;
door->direction = -1;
break;
case DREV_CLOSE30THENOPEN:
door->topheight = sec->ceilingheight;
door->direction = -1;
break;
case DREV_NORMAL:
case DREV_OPEN:
door->direction = 1;
door->topheight = P_FindLowestCeilingSurrounding(sec);
door->topheight -= 4*FRACUNIT;
break;
default:
break;
}
door->type = type;
door->speed = speed;
door->topwait = args[2]; // line->arg3
SN_StartSequence((mobj_t *)&door->sector->soundorg,
SEQ_DOOR_STONE+door->sector->seqType);
}
return(retcode);
}
//==================================================================
//
// EV_VerticalDoor : open a door manually, no tag value
//
//==================================================================
boolean EV_VerticalDoor(line_t *line, mobj_t *thing)
{
int secnum;
sector_t *sec;
vldoor_t *door;
int side;
side = 0; // only front sides can be used
// if the sector has an active thinker, use it
sec = sides[line->sidenum[side^1]].sector;
secnum = sec-sectors;
if(sec->specialdata)
{
return false;
/*
door = sec->specialdata;
switch(line->special)
{ // only for raise doors
case 12:
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;
}
*/
}
//
// 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 11:
door->type = DREV_OPEN;
line->special = 0;
break;
case 12:
case 13:
door->type = DREV_NORMAL;
break;
default:
door->type = DREV_NORMAL;
break;
}
door->speed = line->arg2*(FRACUNIT/8);
door->topwait = line->arg3;
//
// find the top and bottom of the movement range
//
door->topheight = P_FindLowestCeilingSurrounding(sec);
door->topheight -= 4*FRACUNIT;
SN_StartSequence((mobj_t *)&door->sector->soundorg,
SEQ_DOOR_STONE+door->sector->seqType);
return true;
}
//==================================================================
//
// 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 = DREV_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 = DREV_RAISEIN5MINS;
door->speed = VDOORSPEED;
door->topheight = P_FindLowestCeilingSurrounding(sec);
door->topheight -= 4*FRACUNIT;
door->topwait = VDOORWAIT;
door->topcountdown = 5*60*35;
}
*/

5308
Hexen Source/P_ENEMY.C Normal file

File diff suppressed because it is too large Load Diff

931
Hexen Source/P_FLOOR.C Normal file
View File

@ -0,0 +1,931 @@
//**************************************************************************
//**
//** p_floor.c : Heretic 2 : Raven Software, Corp.
//**
//** $RCSfile: p_floor.c,v $
//** $Revision: 1.23 $
//** $Date: 95/10/06 16:53:19 $
//** $Author: paul $
//**
//**************************************************************************
#include "h2def.h"
#include "p_local.h"
#include "soundst.h"
extern fixed_t FloatBobOffsets[64];
//==================================================================
//==================================================================
//
// FLOORS
//
//==================================================================
//==================================================================
//==================================================================
//
// Move a plane (floor or ceiling) and check for crushing
//
//==================================================================
result_e T_MovePlane(sector_t *sector,fixed_t speed,
fixed_t dest, int 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 RES_CRUSHED;
}
return RES_PASTDEST;
}
else
{
lastpos = sector->floorheight;
sector->floorheight -= speed;
flag = P_ChangeSector(sector,crush);
if (flag == true)
{
sector->floorheight = lastpos;
P_ChangeSector(sector,crush);
return RES_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 RES_CRUSHED;
}
return RES_PASTDEST;
}
else // COULD GET CRUSHED
{
lastpos = sector->floorheight;
sector->floorheight += speed;
flag = P_ChangeSector(sector,crush);
if (flag == true)
{
//if (crush == true)
//{
// return RES_CRUSHED;
//}
sector->floorheight = lastpos;
P_ChangeSector(sector,crush);
return RES_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 RES_CRUSHED;
}
return RES_PASTDEST;
}
else // COULD GET CRUSHED
{
lastpos = sector->ceilingheight;
sector->ceilingheight -= speed;
flag = P_ChangeSector(sector,crush);
if (flag == true)
{
//if (crush == true)
//{
// return RES_CRUSHED;
//}
sector->ceilingheight = lastpos;
P_ChangeSector(sector,crush);
return RES_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 RES_CRUSHED;
}
return RES_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 RES_CRUSHED;
}
#endif
}
break;
}
break;
}
return RES_OK;
}
//==================================================================
//
// MOVE A FLOOR TO IT'S DESTINATION (UP OR DOWN)
//
//==================================================================
void T_MoveFloor(floormove_t *floor)
{
result_e res;
if(floor->resetDelayCount)
{
floor->resetDelayCount--;
if(!floor->resetDelayCount)
{
floor->floordestheight = floor->resetHeight;
floor->direction = -floor->direction;
floor->resetDelay = 0;
floor->delayCount = 0;
floor->delayTotal = 0;
}
}
if(floor->delayCount)
{
floor->delayCount--;
if(!floor->delayCount && floor->textureChange)
{
floor->sector->floorpic += floor->textureChange;
}
return;
}
res = T_MovePlane(floor->sector,floor->speed,
floor->floordestheight,floor->crush,0,floor->direction);
if(floor->type == FLEV_RAISEBUILDSTEP)
{
if((floor->direction == 1 && floor->sector->floorheight >=
floor->stairsDelayHeight) || (floor->direction == -1 &&
floor->sector->floorheight <= floor->stairsDelayHeight))
{
floor->delayCount = floor->delayTotal;
floor->stairsDelayHeight += floor->stairsDelayHeightDelta;
}
}
if (res == RES_PASTDEST)
{
SN_StopSequence((mobj_t *)&floor->sector->soundorg);
if(floor->delayTotal)
{
floor->delayTotal = 0;
}
if(floor->resetDelay)
{
// floor->resetDelayCount = floor->resetDelay;
// floor->resetDelay = 0;
return;
}
floor->sector->specialdata = NULL;
/*
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;
}
*/
if(floor->textureChange)
{
floor->sector->floorpic -= floor->textureChange;
}
P_TagFinished(floor->sector->tag);
P_RemoveThinker(&floor->thinker);
}
}
//==================================================================
//
// HANDLE FLOOR TYPES
//
//==================================================================
int EV_DoFloor(line_t *line, byte *args, floor_e floortype)
{
int secnum;
int rtn;
sector_t *sec;
floormove_t *floor=NULL;
secnum = -1;
rtn = 0;
while ((secnum = P_FindSectorFromTag(args[0], secnum)) >= 0)
{
sec = &sectors[secnum];
// ALREADY MOVING? IF SO, KEEP GOING...
if (sec->specialdata)
continue;
//
// new floor thinker
//
rtn = 1;
floor = Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0);
memset(floor, 0, sizeof(*floor));
P_AddThinker (&floor->thinker);
sec->specialdata = floor;
floor->thinker.function = T_MoveFloor;
floor->type = floortype;
floor->crush = 0;
floor->speed = args[1]*(FRACUNIT/8);
if(floortype == FLEV_LOWERTIMES8INSTANT ||
floortype == FLEV_RAISETIMES8INSTANT)
{
floor->speed = 2000<<FRACBITS;
}
switch(floortype)
{
case FLEV_LOWERFLOOR:
floor->direction = -1;
floor->sector = sec;
floor->floordestheight =
P_FindHighestFloorSurrounding(sec);
break;
case FLEV_LOWERFLOORTOLOWEST:
floor->direction = -1;
floor->sector = sec;
floor->floordestheight =
P_FindLowestFloorSurrounding(sec);
break;
case FLEV_LOWERFLOORBYVALUE:
floor->direction = -1;
floor->sector = sec;
floor->floordestheight = floor->sector->floorheight-
args[2]*FRACUNIT;
break;
case FLEV_LOWERTIMES8INSTANT:
case FLEV_LOWERBYVALUETIMES8:
floor->direction = -1;
floor->sector = sec;
floor->floordestheight = floor->sector->floorheight-
args[2]*FRACUNIT*8;
break;
case FLEV_RAISEFLOORCRUSH:
floor->crush = args[2]; // arg[2] = crushing value
floor->direction = 1;
floor->sector = sec;
floor->floordestheight = sec->ceilingheight-8*FRACUNIT;
break;
case FLEV_RAISEFLOOR:
floor->direction = 1;
floor->sector = sec;
floor->floordestheight =
P_FindLowestCeilingSurrounding(sec);
if (floor->floordestheight > sec->ceilingheight)
floor->floordestheight = sec->ceilingheight;
break;
case FLEV_RAISEFLOORTONEAREST:
floor->direction = 1;
floor->sector = sec;
floor->floordestheight =
P_FindNextHighestFloor(sec,sec->floorheight);
break;
case FLEV_RAISEFLOORBYVALUE:
floor->direction = 1;
floor->sector = sec;
floor->floordestheight = floor->sector->floorheight+
args[2]*FRACUNIT;
break;
case FLEV_RAISETIMES8INSTANT:
case FLEV_RAISEBYVALUETIMES8:
floor->direction = 1;
floor->sector = sec;
floor->floordestheight = floor->sector->floorheight+
args[2]*FRACUNIT*8;
break;
case FLEV_MOVETOVALUETIMES8:
floor->sector = sec;
floor->floordestheight = args[2]*FRACUNIT*8;
if(args[3])
{
floor->floordestheight = -floor->floordestheight;
}
if(floor->floordestheight > floor->sector->floorheight)
{
floor->direction = 1;
}
else if(floor->floordestheight < floor->sector->floorheight)
{
floor->direction = -1;
}
else
{ // already at lowest position
rtn = 0;
}
break;
default:
rtn = 0;
break;
}
}
if(rtn)
{
SN_StartSequence((mobj_t *)&floor->sector->soundorg,
SEQ_PLATFORM+floor->sector->seqType);
}
return rtn;
}
//============================================================================
//
// EV_DoFloorAndCeiling
//
//============================================================================
int EV_DoFloorAndCeiling(line_t *line, byte *args, boolean raise)
{
boolean floor, ceiling;
int secnum;
sector_t *sec;
if(raise)
{
floor = EV_DoFloor(line, args, FLEV_RAISEFLOORBYVALUE);
secnum = -1;
while((secnum = P_FindSectorFromTag(args[0], secnum)) >= 0)
{
sec = &sectors[secnum];
sec->specialdata = NULL;
}
ceiling = EV_DoCeiling(line, args, CLEV_RAISEBYVALUE);
}
else
{
floor = EV_DoFloor(line, args, FLEV_LOWERFLOORBYVALUE);
secnum = -1;
while ((secnum = P_FindSectorFromTag(args[0], secnum)) >= 0)
{
sec = &sectors[secnum];
sec->specialdata = NULL;
}
ceiling = EV_DoCeiling(line, args, CLEV_LOWERBYVALUE);
}
return (floor|ceiling);
}
// ===== Build Stairs Private Data =====
#define STAIR_SECTOR_TYPE 26
#define STAIR_QUEUE_SIZE 32
struct
{
sector_t *sector;
int type;
int height;
} StairQueue[STAIR_QUEUE_SIZE];
static int QueueHead;
static int QueueTail;
static int StepDelta;
static int Direction;
static int Speed;
static int Texture;
static int StartDelay;
static int StartDelayDelta;
static int TextureChange;
static int StartHeight;
//==========================================================================
//
// QueueStairSector
//
//==========================================================================
static void QueueStairSector(sector_t *sec, int type, int height)
{
if((QueueTail+1)%STAIR_QUEUE_SIZE == QueueHead)
{
I_Error("BuildStairs: Too many branches located.\n");
}
StairQueue[QueueTail].sector = sec;
StairQueue[QueueTail].type = type;
StairQueue[QueueTail].height = height;
QueueTail = (QueueTail+1)%STAIR_QUEUE_SIZE;
}
//==========================================================================
//
// DequeueStairSector
//
//==========================================================================
static sector_t *DequeueStairSector(int *type, int *height)
{
sector_t *sec;
if(QueueHead == QueueTail)
{ // queue is empty
return NULL;
}
*type = StairQueue[QueueHead].type;
*height = StairQueue[QueueHead].height;
sec = StairQueue[QueueHead].sector;
QueueHead = (QueueHead+1)%STAIR_QUEUE_SIZE;
return sec;
}
//==========================================================================
//
// ProcessStairSector
//
//==========================================================================
static void ProcessStairSector(sector_t *sec, int type, int height,
stairs_e stairsType, int delay, int resetDelay)
{
int i;
sector_t *tsec;
floormove_t *floor;
//
// new floor thinker
//
height += StepDelta;
floor = Z_Malloc(sizeof(*floor), PU_LEVSPEC, 0);
memset(floor, 0, sizeof(*floor));
P_AddThinker(&floor->thinker);
sec->specialdata = floor;
floor->thinker.function = T_MoveFloor;
floor->type = FLEV_RAISEBUILDSTEP;
floor->direction = Direction;
floor->sector = sec;
floor->floordestheight = height;
switch(stairsType)
{
case STAIRS_NORMAL:
floor->speed = Speed;
if(delay)
{
floor->delayTotal = delay;
floor->stairsDelayHeight = sec->floorheight+StepDelta;
floor->stairsDelayHeightDelta = StepDelta;
}
floor->resetDelay = resetDelay;
floor->resetDelayCount = resetDelay;
floor->resetHeight = sec->floorheight;
break;
case STAIRS_SYNC:
floor->speed = FixedMul(Speed, FixedDiv(height-StartHeight,
StepDelta));
floor->resetDelay = delay; //arg4
floor->resetDelayCount = delay;
floor->resetHeight = sec->floorheight;
break;
/*
case STAIRS_PHASED:
floor->floordestheight = sec->floorheight+StepDelta;
floor->speed = Speed;
floor->delayCount = StartDelay;
StartDelay += StartDelayDelta;
floor->textureChange = TextureChange;
floor->resetDelayCount = StartDelay;
break;
*/
default:
break;
}
SN_StartSequence((mobj_t *)&sec->soundorg, SEQ_PLATFORM+sec->seqType);
//
// Find next sector to raise
// Find nearby sector with sector special equal to type
//
for (i = 0; i < sec->linecount; i++)
{
if(!((sec->lines[i])->flags&ML_TWOSIDED))
{
continue;
}
tsec = (sec->lines[i])->frontsector;
if(tsec->special == type+STAIR_SECTOR_TYPE && !tsec->specialdata
&& tsec->floorpic == Texture && tsec->validcount != validcount)
{
QueueStairSector(tsec, type^1, height);
tsec->validcount = validcount;
//tsec->special = 0;
}
tsec = (sec->lines[i])->backsector;
if(tsec->special == type+STAIR_SECTOR_TYPE && !tsec->specialdata
&& tsec->floorpic == Texture && tsec->validcount != validcount)
{
QueueStairSector(tsec, type^1, height);
tsec->validcount = validcount;
//tsec->special = 0;
}
}
}
//==================================================================
//
// BUILD A STAIRCASE!
//
// Direction is either positive or negative, denoting build stairs
// up or down.
//==================================================================
int EV_BuildStairs(line_t *line, byte *args, int direction,
stairs_e stairsType)
{
int secnum;
int height;
int delay;
int resetDelay;
sector_t *sec;
sector_t *qSec;
int type;
// Set global stairs variables
TextureChange = 0;
Direction = direction;
StepDelta = Direction*(args[2]*FRACUNIT);
Speed = args[1]*(FRACUNIT/8);
resetDelay = args[4];
delay = args[3];
if(stairsType == STAIRS_PHASED)
{
StartDelayDelta = args[3];
StartDelay = StartDelayDelta;
resetDelay = StartDelayDelta;
delay = 0;
TextureChange = args[4];
}
secnum = -1;
validcount++;
while ((secnum = P_FindSectorFromTag(args[0], secnum)) >= 0)
{
sec = &sectors[secnum];
Texture = sec->floorpic;
StartHeight = sec->floorheight;
// ALREADY MOVING? IF SO, KEEP GOING...
if (sec->specialdata)
continue;
QueueStairSector(sec, 0, sec->floorheight);
sec->special = 0;
}
while((qSec = DequeueStairSector(&type, &height)) != NULL)
{
ProcessStairSector(qSec, type, height, stairsType, delay, resetDelay);
}
return(1);
}
//=========================================================================
//
// T_BuildPillar
//
//=========================================================================
void T_BuildPillar(pillar_t *pillar)
{
result_e res1;
result_e res2;
// First, raise the floor
res1 = T_MovePlane(pillar->sector, pillar->floorSpeed, pillar->floordest,
pillar->crush, 0, pillar->direction); // floorOrCeiling, direction
// Then, lower the ceiling
res2 = T_MovePlane(pillar->sector, pillar->ceilingSpeed,
pillar->ceilingdest, pillar->crush, 1, -pillar->direction);
if (res1 == RES_PASTDEST && res2 == RES_PASTDEST)
{
pillar->sector->specialdata = NULL;
SN_StopSequence((mobj_t *)&pillar->sector->soundorg);
P_TagFinished(pillar->sector->tag);
P_RemoveThinker(&pillar->thinker);
}
}
//=========================================================================
//
// EV_BuildPillar
//
//=========================================================================
int EV_BuildPillar(line_t *line, byte *args, boolean crush)
{
int secnum;
sector_t *sec;
pillar_t *pillar;
int newHeight;
int rtn;
rtn = 0;
secnum = -1;
while((secnum = P_FindSectorFromTag(args[0], secnum)) >= 0)
{
sec = &sectors[secnum];
if(sec->specialdata)
continue; // already moving
if(sec->floorheight == sec->ceilingheight)
{ // pillar is already closed
continue;
}
rtn = 1;
if(!args[2])
{
newHeight = sec->floorheight+
((sec->ceilingheight-sec->floorheight)/2);
}
else
{
newHeight = sec->floorheight+(args[2]<<FRACBITS);
}
pillar = Z_Malloc(sizeof(*pillar), PU_LEVSPEC, 0);
sec->specialdata = pillar;
P_AddThinker(&pillar->thinker);
pillar->thinker.function = T_BuildPillar;
pillar->sector = sec;
if(!args[2])
{
pillar->ceilingSpeed = pillar->floorSpeed = args[1]*(FRACUNIT/8);
}
else if(newHeight-sec->floorheight > sec->ceilingheight-newHeight)
{
pillar->floorSpeed = args[1]*(FRACUNIT/8);
pillar->ceilingSpeed = FixedMul(sec->ceilingheight-newHeight,
FixedDiv(pillar->floorSpeed, newHeight-sec->floorheight));
}
else
{
pillar->ceilingSpeed = args[1]*(FRACUNIT/8);
pillar->floorSpeed = FixedMul(newHeight-sec->floorheight,
FixedDiv(pillar->ceilingSpeed, sec->ceilingheight-newHeight));
}
pillar->floordest = newHeight;
pillar->ceilingdest = newHeight;
pillar->direction = 1;
pillar->crush = crush*args[3];
SN_StartSequence((mobj_t *)&pillar->sector->soundorg,
SEQ_PLATFORM+pillar->sector->seqType);
}
return rtn;
}
//=========================================================================
//
// EV_OpenPillar
//
//=========================================================================
int EV_OpenPillar(line_t *line, byte *args)
{
int secnum;
sector_t *sec;
pillar_t *pillar;
int rtn;
rtn = 0;
secnum = -1;
while((secnum = P_FindSectorFromTag(args[0], secnum)) >= 0)
{
sec = &sectors[secnum];
if(sec->specialdata)
continue; // already moving
if(sec->floorheight != sec->ceilingheight)
{ // pillar isn't closed
continue;
}
rtn = 1;
pillar = Z_Malloc(sizeof(*pillar), PU_LEVSPEC, 0);
sec->specialdata = pillar;
P_AddThinker(&pillar->thinker);
pillar->thinker.function = T_BuildPillar;
pillar->sector = sec;
if(!args[2])
{
pillar->floordest = P_FindLowestFloorSurrounding(sec);
}
else
{
pillar->floordest = sec->floorheight-(args[2]<<FRACBITS);
}
if(!args[3])
{
pillar->ceilingdest = P_FindHighestCeilingSurrounding(sec);
}
else
{
pillar->ceilingdest = sec->ceilingheight+(args[3]<<FRACBITS);
}
if(sec->floorheight-pillar->floordest >= pillar->ceilingdest-
sec->ceilingheight)
{
pillar->floorSpeed = args[1]*(FRACUNIT/8);
pillar->ceilingSpeed = FixedMul(sec->ceilingheight-
pillar->ceilingdest, FixedDiv(pillar->floorSpeed,
pillar->floordest-sec->floorheight));
}
else
{
pillar->ceilingSpeed = args[1]*(FRACUNIT/8);
pillar->floorSpeed = FixedMul(pillar->floordest-sec->floorheight,
FixedDiv(pillar->ceilingSpeed, sec->ceilingheight-
pillar->ceilingdest));
}
pillar->direction = -1; // open the pillar
SN_StartSequence((mobj_t *)&pillar->sector->soundorg,
SEQ_PLATFORM+pillar->sector->seqType);
}
return rtn;
}
//=========================================================================
//
// EV_FloorCrushStop
//
//=========================================================================
int EV_FloorCrushStop(line_t *line, byte *args)
{
thinker_t *think;
floormove_t *floor;
boolean rtn;
rtn = 0;
for(think = thinkercap.next; think != &thinkercap; think = think->next)
{
if(think->function != T_MoveFloor)
{
continue;
}
floor = (floormove_t *)think;
if(floor->type != FLEV_RAISEFLOORCRUSH)
{
continue;
}
// Completely remove the crushing floor
SN_StopSequence((mobj_t *)&floor->sector->soundorg);
floor->sector->specialdata = NULL;
P_TagFinished(floor->sector->tag);
P_RemoveThinker(&floor->thinker);
rtn = 1;
}
return rtn;
}
//==========================================================================
//
// T_FloorWaggle
//
//==========================================================================
#define WGLSTATE_EXPAND 1
#define WGLSTATE_STABLE 2
#define WGLSTATE_REDUCE 3
void T_FloorWaggle(floorWaggle_t *waggle)
{
switch(waggle->state)
{
case WGLSTATE_EXPAND:
if((waggle->scale += waggle->scaleDelta)
>= waggle->targetScale)
{
waggle->scale = waggle->targetScale;
waggle->state = WGLSTATE_STABLE;
}
break;
case WGLSTATE_REDUCE:
if((waggle->scale -= waggle->scaleDelta) <= 0)
{ // Remove
waggle->sector->floorheight = waggle->originalHeight;
P_ChangeSector(waggle->sector, true);
waggle->sector->specialdata = NULL;
P_TagFinished(waggle->sector->tag);
P_RemoveThinker(&waggle->thinker);
return;
}
break;
case WGLSTATE_STABLE:
if(waggle->ticker != -1)
{
if(!--waggle->ticker)
{
waggle->state = WGLSTATE_REDUCE;
}
}
break;
}
waggle->accumulator += waggle->accDelta;
waggle->sector->floorheight = waggle->originalHeight
+FixedMul(FloatBobOffsets[(waggle->accumulator>>FRACBITS)&63],
waggle->scale);
P_ChangeSector(waggle->sector, true);
}
//==========================================================================
//
// EV_StartFloorWaggle
//
//==========================================================================
boolean EV_StartFloorWaggle(int tag, int height, int speed, int offset,
int timer)
{
int sectorIndex;
sector_t *sector;
floorWaggle_t *waggle;
boolean retCode;
retCode = false;
sectorIndex = -1;
while((sectorIndex = P_FindSectorFromTag(tag, sectorIndex)) >= 0)
{
sector = &sectors[sectorIndex];
if(sector->specialdata)
{ // Already busy with another thinker
continue;
}
retCode = true;
waggle = Z_Malloc(sizeof(*waggle), PU_LEVSPEC, 0);
sector->specialdata = waggle;
waggle->thinker.function = T_FloorWaggle;
waggle->sector = sector;
waggle->originalHeight = sector->floorheight;
waggle->accumulator = offset*FRACUNIT;
waggle->accDelta = speed<<10;
waggle->scale = 0;
waggle->targetScale = height<<10;
waggle->scaleDelta = waggle->targetScale
/(35+((3*35)*height)/255);
waggle->ticker = timer ? timer*35 : -1;
waggle->state = WGLSTATE_EXPAND;
P_AddThinker(&waggle->thinker);
}
return retCode;
}

2252
Hexen Source/P_INTER.C Normal file

File diff suppressed because it is too large Load Diff

351
Hexen Source/P_LIGHTS.C Normal file
View File

@ -0,0 +1,351 @@
//**************************************************************************
//**
//** p_lights.c : Heretic 2 : Raven Software, Corp.
//**
//** $RCSfile: p_lights.c,v $
//** $Revision: 1.2 $
//** $Date: 95/07/11 10:23:36 $
//** $Author: cjr $
//**
//**************************************************************************
#include "h2def.h"
#include "p_local.h"
//============================================================================
//
// T_Light
//
//============================================================================
void T_Light(light_t *light)
{
if(light->count)
{
light->count--;
return;
}
switch(light->type)
{
case LITE_FADE:
light->sector->lightlevel = ((light->sector->lightlevel<<FRACBITS)
+light->value2)>>FRACBITS;
if(light->tics2 == 1)
{
if(light->sector->lightlevel >= light->value1)
{
light->sector->lightlevel = light->value1;
P_RemoveThinker(&light->thinker);
}
}
else if(light->sector->lightlevel <= light->value1)
{
light->sector->lightlevel = light->value1;
P_RemoveThinker(&light->thinker);
}
break;
case LITE_GLOW:
light->sector->lightlevel = ((light->sector->lightlevel<<FRACBITS)
+light->tics1)>>FRACBITS;
if(light->tics2 == 1)
{
if(light->sector->lightlevel >= light->value1)
{
light->sector->lightlevel = light->value1;
light->tics1 = -light->tics1;
light->tics2 = -1; // reverse direction
}
}
else if(light->sector->lightlevel <= light->value2)
{
light->sector->lightlevel = light->value2;
light->tics1 = -light->tics1;
light->tics2 = 1; // reverse direction
}
break;
case LITE_FLICKER:
if(light->sector->lightlevel == light->value1)
{
light->sector->lightlevel = light->value2;
light->count = (P_Random()&7)+1;
}
else
{
light->sector->lightlevel = light->value1;
light->count = (P_Random()&31)+1;
}
break;
case LITE_STROBE:
if(light->sector->lightlevel == light->value1)
{
light->sector->lightlevel = light->value2;
light->count = light->tics2;
}
else
{
light->sector->lightlevel = light->value1;
light->count = light->tics1;
}
break;
default:
break;
}
}
//============================================================================
//
// EV_SpawnLight
//
//============================================================================
boolean EV_SpawnLight(line_t *line, byte *arg, lighttype_t type)
{
light_t *light;
sector_t *sec;
int secNum;
int arg1, arg2, arg3, arg4;
boolean think;
boolean rtn;
arg1 = arg[1] > 255 ? 255 : arg[1];
arg1 = arg1 < 0 ? 0 : arg1;
arg2 = arg[2] > 255 ? 255 : arg[2];
arg2 = arg2 < 0 ? 0 : arg2;
arg3 = arg[3] > 255 ? 255 : arg[3];
arg3 = arg3 < 0 ? 0 : arg3;
arg4 = arg[4] > 255 ? 255 : arg[4];
arg4 = arg4 < 0 ? 0 : arg4;
secNum = -1;
rtn = false;
think = false;
while((secNum = P_FindSectorFromTag(arg[0], secNum)) >= 0)
{
think = false;
sec = &sectors[secNum];
light = (light_t *)Z_Malloc(sizeof(light_t), PU_LEVSPEC, 0);
light->type = type;
light->sector = sec;
light->count = 0;
rtn = true;
switch(type)
{
case LITE_RAISEBYVALUE:
sec->lightlevel += arg1;
if(sec->lightlevel > 255)
{
sec->lightlevel = 255;
}
break;
case LITE_LOWERBYVALUE:
sec->lightlevel -= arg1;
if(sec->lightlevel < 0)
{
sec->lightlevel = 0;
}
break;
case LITE_CHANGETOVALUE:
sec->lightlevel = arg1;
if(sec->lightlevel < 0)
{
sec->lightlevel = 0;
}
else if(sec->lightlevel > 255)
{
sec->lightlevel = 255;
}
break;
case LITE_FADE:
think = true;
light->value1 = arg1; // destination lightlevel
light->value2 = FixedDiv((arg1-sec->lightlevel)<<FRACBITS,
arg2<<FRACBITS); // delta lightlevel
if(sec->lightlevel <= arg1)
{
light->tics2 = 1; // get brighter
}
else
{
light->tics2 = -1;
}
break;
case LITE_GLOW:
think = true;
light->value1 = arg1; // upper lightlevel
light->value2 = arg2; // lower lightlevel
light->tics1 = FixedDiv((arg1-sec->lightlevel)<<FRACBITS,
arg3<<FRACBITS); // lightlevel delta
if(sec->lightlevel <= arg1)
{
light->tics2 = 1; // get brighter
}
else
{
light->tics2 = -1;
}
break;
case LITE_FLICKER:
think = true;
light->value1 = arg1; // upper lightlevel
light->value2 = arg2; // lower lightlevel
sec->lightlevel = light->value1;
light->count = (P_Random()&64)+1;
break;
case LITE_STROBE:
think = true;
light->value1 = arg1; // upper lightlevel
light->value2 = arg2; // lower lightlevel
light->tics1 = arg3; // upper tics
light->tics2 = arg4; // lower tics
light->count = arg3;
sec->lightlevel = light->value1;
break;
default:
rtn = false;
break;
}
if(think)
{
P_AddThinker(&light->thinker);
light->thinker.function = T_Light;
}
else
{
Z_Free(light);
}
}
return rtn;
}
//============================================================================
//
// T_Phase
//
//============================================================================
int PhaseTable[64] =
{
128, 112, 96, 80, 64, 48, 32, 32,
16, 16, 16, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 16, 16, 16,
32, 32, 48, 64, 80, 96, 112, 128
};
void T_Phase(phase_t *phase)
{
phase->index = (phase->index+1)&63;
phase->sector->lightlevel = phase->base+PhaseTable[phase->index];
}
//==========================================================================
//
// P_SpawnPhasedLight
//
//==========================================================================
void P_SpawnPhasedLight(sector_t *sector, int base, int index)
{
phase_t *phase;
phase = Z_Malloc(sizeof(*phase), PU_LEVSPEC, 0);
P_AddThinker(&phase->thinker);
phase->sector = sector;
if(index == -1)
{ // sector->lightlevel as the index
phase->index = sector->lightlevel&63;
}
else
{
phase->index = index&63;
}
phase->base = base&255;
sector->lightlevel = phase->base+PhaseTable[phase->index];
phase->thinker.function = T_Phase;
sector->special = 0;
}
//==========================================================================
//
// P_SpawnLightSequence
//
//==========================================================================
void P_SpawnLightSequence(sector_t *sector, int indexStep)
{
sector_t *sec;
sector_t *nextSec;
sector_t *tempSec;
int seqSpecial;
int i;
int count;
fixed_t index;
fixed_t indexDelta;
int base;
seqSpecial = LIGHT_SEQUENCE; // look for Light_Sequence, first
sec = sector;
count = 1;
do
{
nextSec = NULL;
sec->special = LIGHT_SEQUENCE_START; // make sure that the search doesn't back up.
for(i = 0; i < sec->linecount; i++)
{
tempSec = getNextSector(sec->lines[i], sec);
if(!tempSec)
{
continue;
}
if(tempSec->special == seqSpecial)
{
if(seqSpecial == LIGHT_SEQUENCE)
{
seqSpecial = LIGHT_SEQUENCE_ALT;
}
else
{
seqSpecial = LIGHT_SEQUENCE;
}
nextSec = tempSec;
count++;
}
}
sec = nextSec;
} while(sec);
sec = sector;
count *= indexStep;
index = 0;
indexDelta = FixedDiv(64*FRACUNIT, count*FRACUNIT);
base = sector->lightlevel;
do
{
nextSec = NULL;
if(sec->lightlevel)
{
base = sec->lightlevel;
}
P_SpawnPhasedLight(sec, base, index>>FRACBITS);
index += indexDelta;
for(i = 0; i < sec->linecount; i++)
{
tempSec = getNextSector(sec->lines[i], sec);
if(!tempSec)
{
continue;
}
if(tempSec->special == LIGHT_SEQUENCE_START)
{
nextSec = tempSec;
}
}
sec = nextSec;
} while(sec);
}

372
Hexen Source/P_LOCAL.H Normal file
View File

@ -0,0 +1,372 @@
//**************************************************************************
//**
//** p_local.h : Heretic 2 : Raven Software, Corp.
//**
//** $RCSfile: p_local.h,v $
//** $Revision: 1.64 $
//** $Date: 95/10/13 03:00:16 $
//** $Author: cjr $
//**
//**************************************************************************
#ifndef __P_LOCAL__
#define __P_LOCAL__
#ifndef __R_LOCAL__
#include "r_local.h"
#endif
#define STARTREDPALS 1
#define STARTBONUSPALS 9
#define STARTPOISONPALS 13
#define STARTICEPAL 21
#define STARTHOLYPAL 22
#define STARTSCOURGEPAL 25
#define NUMREDPALS 8
#define NUMBONUSPALS 4
#define NUMPOISONPALS 8
#define TOCENTER -8
#define FLOATSPEED (FRACUNIT*4)
#define MAXHEALTH 100
#define MAXMORPHHEALTH 30
#define VIEWHEIGHT (48*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_MANA1 1
#define USE_MANA2 1
void P_SetPsprite(player_t *player, int position, statenum_t stnum);
void P_SetPspriteNF(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_ActivateMorphWeapon(player_t *player);
void P_PostMorphWeapon(player_t *player, weapontype_t weapon);
// ***** P_USER *****
extern int PStateNormal[NUMCLASSES];
extern int PStateRun[NUMCLASSES];
extern int PStateAttack[NUMCLASSES];
extern int PStateAttackEnd[NUMCLASSES];
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);
void P_TeleportOther(mobj_t *victim);
void ResetBlasted(mobj_t *mo);
// ***** P_MOBJ *****
// Any floor type >= FLOOR_LIQUID will floorclip sprites
enum
{
FLOOR_SOLID,
FLOOR_ICE,
FLOOR_LIQUID,
FLOOR_WATER,
FLOOR_LAVA,
FLOOR_SLUDGE
};
#define ONFLOORZ MININT
#define ONCEILINGZ MAXINT
#define FLOATRANDZ (MAXINT-1)
#define FROMCEILINGZ128 (MAXINT-2)
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_BloodSplatter2(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_SpawnMissileXYZ(fixed_t x, fixed_t y, fixed_t z,
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_SpawnMissileAngleSpeed(mobj_t *source, mobjtype_t type,
angle_t angle, fixed_t momz, fixed_t speed);
mobj_t *P_SpawnPlayerMissile(mobj_t *source, mobjtype_t type);
mobj_t *P_SPMAngle(mobj_t *source, mobjtype_t type, angle_t angle);
mobj_t *P_SPMAngleXYZ(mobj_t *source, fixed_t x, fixed_t y,
fixed_t z, mobjtype_t type, angle_t angle);
void P_CreateTIDList(void);
void P_RemoveMobjFromTIDList(mobj_t *mobj);
void P_InsertMobjIntoTIDList(mobj_t *mobj, int tid);
mobj_t *P_FindMobjFromTID(int tid, int *searchPosition);
mobj_t *P_SpawnKoraxMissile(fixed_t x, fixed_t y, fixed_t z,
mobj_t *source, mobj_t *dest, mobjtype_t type);
// ***** P_ENEMY *****
void P_NoiseAlert (mobj_t *target, mobj_t *emmiter);
int P_Massacre(void);
boolean A_RaiseMobj(mobj_t *actor);
boolean A_SinkMobj(mobj_t *actor);
void A_NoBlocking(mobj_t *actor);
boolean P_LookForMonsters(mobj_t *actor);
void P_InitCreatureCorpseQueue(boolean corpseScan);
void A_DeQueueCorpse(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);
mobj_t *P_RoughMonsterSearch(mobj_t *mo, int distance);
// ***** P_MAP *****
extern boolean floatok; // if true, move would be ok if
extern fixed_t tmfloorz, tmceilingz; // within tmfloorz - tmceilingz
extern int tmfloorpic;
extern mobj_t *BlockingMobj;
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);
void P_BounceWall(mobj_t *mo);
boolean P_CheckSight(mobj_t *t1, mobj_t *t2);
void P_UseLines(player_t *player);
boolean P_UsePuzzleItem(player_t *player, int itemType);
void PIT_ThrustSpike(mobj_t *actor);
boolean P_ChangeSector (sector_t *sector, int crunch);
extern mobj_t *PuffSpawned; // true if a puff was spawned
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, int distance,
boolean damageSource);
// ***** 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 clipmana[NUMMANA];
void P_SetMessage(player_t *player, char *message, boolean ultmsg);
void P_SetYellowMessage(player_t *player, char *message, boolean ultmsg);
void P_ClearMessage(player_t *player);
void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher);
void P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source,
int damage);
void P_FallingDamage(player_t *player);
void P_PoisonPlayer(player_t *player, mobj_t *poisoner, int poison);
void P_PoisonDamage(player_t *player, mobj_t *source, int damage,
boolean playPainSound);
boolean P_GiveMana(player_t *player, manatype_t mana, int count);
boolean P_GiveArtifact(player_t *player, artitype_t arti, mobj_t *mo);
boolean P_GiveArmor(player_t *player, armortype_t armortype, int amount);
boolean P_GiveBody(player_t *player, int num);
boolean P_GivePower(player_t *player, powertype_t power);
boolean P_MorphPlayer(player_t *player);
// ***** AM_MAP *****
boolean AM_Responder(event_t *ev);
void AM_Ticker(void);
void AM_Drawer(void);
// ***** A_ACTION *****
boolean A_LocalQuake(byte *args, mobj_t *victim);
void P_SpawnDirt(mobj_t *actor, fixed_t radius);
void A_BridgeRemove(mobj_t *actor);
// ***** SB_BAR *****
extern int SB_state;
extern int ArtifactFlash;
void SB_PaletteFlash(boolean forceChange);
// ===== PO_MAN =====
typedef enum
{
PODOOR_NONE,
PODOOR_SLIDE,
PODOOR_SWING,
} podoortype_t;
typedef struct
{
thinker_t thinker;
int polyobj;
int speed;
unsigned int dist;
int angle;
fixed_t xSpeed; // for sliding walls
fixed_t ySpeed;
} polyevent_t;
typedef struct
{
thinker_t thinker;
int polyobj;
int speed;
int dist;
int totalDist;
int direction;
fixed_t xSpeed, ySpeed;
int tics;
int waitTics;
podoortype_t type;
boolean close;
} polydoor_t;
enum
{
PO_ANCHOR_TYPE = 3000,
PO_SPAWN_TYPE,
PO_SPAWNCRUSH_TYPE
};
#define PO_LINE_START 1 // polyobj line start special
#define PO_LINE_EXPLICIT 5
extern polyobj_t *polyobjs; // list of all poly-objects on the level
extern int po_NumPolyobjs;
void T_PolyDoor(polydoor_t *pd);
void T_RotatePoly(polyevent_t *pe);
boolean EV_RotatePoly(line_t *line, byte *args, int direction, boolean
overRide);
void T_MovePoly(polyevent_t *pe);
boolean EV_MovePoly(line_t *line, byte *args, boolean timesEight, boolean
overRide);
boolean EV_OpenPolyDoor(line_t *line, byte *args, podoortype_t type);
boolean PO_MovePolyobj(int num, int x, int y);
boolean PO_RotatePolyobj(int num, angle_t angle);
void PO_Init(int lump);
boolean PO_Busy(int polyobj);
#include "p_spec.h"
#endif // __P_LOCAL__

2296
Hexen Source/P_MAP.C Normal file

File diff suppressed because it is too large Load Diff

1056
Hexen Source/P_MAPUTL.C Normal file

File diff suppressed because it is too large Load Diff

2441
Hexen Source/P_MOBJ.C Normal file

File diff suppressed because it is too large Load Diff

266
Hexen Source/P_PLATS.C Normal file
View File

@ -0,0 +1,266 @@
//**************************************************************************
//**
//** p_plats.c : Heretic 2 : Raven Software, Corp.
//**
//** $RCSfile: p_plats.c,v $
//** $Revision: 1.11 $
//** $Date: 95/09/11 22:06:30 $
//** $Author: cjr $
//**
//**************************************************************************
#include "h2def.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 PLAT_UP:
res = T_MovePlane(plat->sector, plat->speed,
plat->high, plat->crush, 0, 1);
if (res == RES_CRUSHED && (!plat->crush))
{
plat->count = plat->wait;
plat->status = PLAT_DOWN;
SN_StartSequence((mobj_t *)&plat->sector->soundorg,
SEQ_PLATFORM+plat->sector->seqType);
}
else
if (res == RES_PASTDEST)
{
plat->count = plat->wait;
plat->status = PLAT_WAITING;
SN_StopSequence((mobj_t *)&plat->sector->soundorg);
switch(plat->type)
{
case PLAT_DOWNWAITUPSTAY:
case PLAT_DOWNBYVALUEWAITUPSTAY:
P_RemoveActivePlat(plat);
break;
default:
break;
}
}
break;
case PLAT_DOWN:
res = T_MovePlane(plat->sector,plat->speed,plat->low,false,0,-1);
if (res == RES_PASTDEST)
{
plat->count = plat->wait;
plat->status = PLAT_WAITING;
switch(plat->type)
{
case PLAT_UPWAITDOWNSTAY:
case PLAT_UPBYVALUEWAITDOWNSTAY:
P_RemoveActivePlat(plat);
break;
default:
break;
}
SN_StopSequence((mobj_t *)&plat->sector->soundorg);
}
break;
case PLAT_WAITING:
if (!--plat->count)
{
if (plat->sector->floorheight == plat->low)
plat->status = PLAT_UP;
else
plat->status = PLAT_DOWN;
SN_StartSequence((mobj_t *)&plat->sector->soundorg,
SEQ_PLATFORM+plat->sector->seqType);
}
// case PLAT_IN_STASIS:
// break;
}
}
//==================================================================
//
// Do Platforms
// "amount" is only used for SOME platforms.
//
//==================================================================
int EV_DoPlat(line_t *line, byte *args, 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 PLAT_PERPETUALRAISE:
P_ActivateInStasis(args[0]);
break;
default:
break;
}
*/
while ((secnum = P_FindSectorFromTag(args[0], secnum)) >= 0)
{
sec = &sectors[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 = args[0];
plat->speed = args[1]*(FRACUNIT/8);
switch(type)
{
case PLAT_DOWNWAITUPSTAY:
plat->low = P_FindLowestFloorSurrounding(sec)+8*FRACUNIT;
if (plat->low > sec->floorheight)
plat->low = sec->floorheight;
plat->high = sec->floorheight;
plat->wait = args[2];
plat->status = PLAT_DOWN;
break;
case PLAT_DOWNBYVALUEWAITUPSTAY:
plat->low = sec->floorheight-args[3]*8*FRACUNIT;
if (plat->low > sec->floorheight)
plat->low = sec->floorheight;
plat->high = sec->floorheight;
plat->wait = args[2];
plat->status = PLAT_DOWN;
break;
case PLAT_UPWAITDOWNSTAY:
plat->high = P_FindHighestFloorSurrounding(sec);
if (plat->high < sec->floorheight)
plat->high = sec->floorheight;
plat->low = sec->floorheight;
plat->wait = args[2];
plat->status = PLAT_UP;
break;
case PLAT_UPBYVALUEWAITDOWNSTAY:
plat->high = sec->floorheight+args[3]*8*FRACUNIT;
if (plat->high < sec->floorheight)
plat->high = sec->floorheight;
plat->low = sec->floorheight;
plat->wait = args[2];
plat->status = PLAT_UP;
break;
case PLAT_PERPETUALRAISE:
plat->low = P_FindLowestFloorSurrounding(sec)+8*FRACUNIT;
if (plat->low > sec->floorheight)
plat->low = sec->floorheight;
plat->high = P_FindHighestFloorSurrounding(sec);
if (plat->high < sec->floorheight)
plat->high = sec->floorheight;
plat->wait = args[2];
plat->status = P_Random()&1;
break;
}
P_AddActivePlat(plat);
SN_StartSequence((mobj_t *)&sec->soundorg, SEQ_PLATFORM+sec->seqType);
}
return rtn;
}
#if 0
void P_ActivateInStasis(int tag)
{
int i;
for (i = 0;i < MAXPLATS;i++)
if (activeplats[i] &&
(activeplats[i])->tag == tag &&
(activeplats[i])->status == PLAT_IN_STASIS)
{
(activeplats[i])->status = (activeplats[i])->oldstatus;
(activeplats[i])->thinker.function = T_PlatRaise;
}
}
#endif
void EV_StopPlat(line_t *line, byte *args)
{
int i;
for(i = 0; i < MAXPLATS; i++)
{
if((activeplats[i])->tag = args[0])
{
(activeplats[i])->sector->specialdata = NULL;
P_TagFinished((activeplats[i])->sector->tag);
P_RemoveThinker(&(activeplats[i])->thinker);
activeplats[i] = NULL;
return;
}
}
/*
int j;
for (j = 0;j < MAXPLATS;j++)
{
if (activeplats[j] && ((activeplats[j])->status != PLAT_IN_STASIS) &&
((activeplats[j])->tag == args[0]))
{
(activeplats[j])->oldstatus = (activeplats[j])->status;
(activeplats[j])->status = PLAT_IN_STASIS;
(activeplats[j])->thinker.function = NULL;
SN_StopSequence((mobj_t *)&(activeplats[j])->sector->soundorg);
}
}
*/
}
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_TagFinished(plat->sector->tag);
P_RemoveThinker(&(activeplats[i])->thinker);
activeplats[i] = NULL;
return;
}
I_Error ("P_RemoveActivePlat: can't find plat!");
}

2456
Hexen Source/P_PSPR.C Normal file

File diff suppressed because it is too large Load Diff

1218
Hexen Source/P_SETUP.C Normal file

File diff suppressed because it is too large Load Diff

395
Hexen Source/P_SIGHT.C Normal file
View File

@ -0,0 +1,395 @@
//**************************************************************************
//**
//** p_sight.c : Heretic 2 : Raven Software, Corp.
//**
//** $RCSfile: p_sight.c,v $
//** $Revision: 1.1 $
//** $Date: 95/05/11 00:22:50 $
//** $Author: bgokey $
//**
//**************************************************************************
#include "h2def.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;
polyblock_t *polyLink;
seg_t **segList;
int i;
extern polyblock_t **PolyBlockMap;
offset = y*bmapwidth+x;
polyLink = PolyBlockMap[offset];
while(polyLink)
{
if(polyLink->polyobj)
{ // only check non-empty links
if(polyLink->polyobj->validcount != validcount)
{
segList = polyLink->polyobj->segs;
for(i = 0; i < polyLink->polyobj->numsegs; i++, segList++)
{
ld = (*segList)->linedef;
if(ld->validcount == validcount)
{
continue;
}
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++;
}
polyLink->polyobj->validcount = validcount;
}
}
polyLink = polyLink->next;
}
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 );
}

1152
Hexen Source/P_SPEC.C Normal file

File diff suppressed because it is too large Load Diff

563
Hexen Source/P_SPEC.H Normal file
View File

@ -0,0 +1,563 @@
//**************************************************************************
//**
//** p_spec.h : Heretic 2 : Raven Software, Corp.
//**
//** $RCSfile: p_spec.h,v $
//** $Revision: 1.38 $
//** $Date: 96/01/06 18:37:35 $
//** $Author: bgokey $
//**
//**************************************************************************
extern int *TerrainTypes;
//
// scrolling 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_InitTerrainTypes(void);
void P_InitLava(void);
// at map load
void P_SpawnSpecials(void);
// every tic
void P_UpdateSpecials(void);
// when needed
boolean P_ExecuteLineSpecial(int special, byte *args, line_t *line, int side,
mobj_t *mo);
boolean P_ActivateLine(line_t *ld, mobj_t *mo, int side, int activationType);
//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);
void P_PlayerOnSpecialFlat(player_t *player, int floorType);
//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_FindSectorFromTag(int tag, int start);
//int P_FindMinSurroundingLight(sector_t *sector,int max);
sector_t *getNextSector(line_t *line,sector_t *sec);
line_t *P_FindLine(int lineTag, int *searchPosition);
//
// SPECIAL
//
//int EV_DoDonut(line_t *line);
//-------------------------------
// P_anim.c
//-------------------------------
void P_AnimateSurfaces(void);
void P_InitFTAnims(void);
void P_InitLightning(void);
void P_ForceLightning(void);
/*
===============================================================================
P_LIGHTS
===============================================================================
*/
typedef enum
{
LITE_RAISEBYVALUE,
LITE_LOWERBYVALUE,
LITE_CHANGETOVALUE,
LITE_FADE,
LITE_GLOW,
LITE_FLICKER,
LITE_STROBE
} lighttype_t;
typedef struct
{
thinker_t thinker;
sector_t *sector;
lighttype_t type;
int value1;
int value2;
int tics1;
int tics2;
int count;
} light_t;
typedef struct
{
thinker_t thinker;
sector_t *sector;
int index;
int base;
} phase_t;
#define LIGHT_SEQUENCE_START 2
#define LIGHT_SEQUENCE 3
#define LIGHT_SEQUENCE_ALT 4
void T_Phase(phase_t *phase);
void T_Light(light_t *light);
void P_SpawnPhasedLight(sector_t *sector, int base, int index);
void P_SpawnLightSequence(sector_t *sector, int indexStep);
boolean EV_SpawnLight(line_t *line, byte *arg, lighttype_t type);
#if 0
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;
typedef struct
{
thinker_t thinker;
sector_t *sector;
int index;
int base;
} phase_t;
#define GLOWSPEED 8
#define STROBEBRIGHT 5
#define FASTDARK 15
#define SLOWDARK 35
#define LIGHT_SEQUENCE_START 2
#define LIGHT_SEQUENCE 3
#define LIGHT_SEQUENCE_ALT 4
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);
void T_Phase(phase_t *phase);
void P_SpawnPhasedLight(sector_t *sector, int base, int index);
void P_SpawnLightSequence(sector_t *sector, int indexStep);
#endif
/*
===============================================================================
P_SWITCH
===============================================================================
*/
typedef struct
{
char name1[9];
char name2[9];
int soundID;
} switchlist_t;
typedef enum
{
SWTCH_TOP,
SWTCH_MIDDLE,
SWTCH_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
{
PLAT_UP,
PLAT_DOWN,
PLAT_WAITING,
// PLAT_IN_STASIS
} plat_e;
typedef enum
{
PLAT_PERPETUALRAISE,
PLAT_DOWNWAITUPSTAY,
PLAT_DOWNBYVALUEWAITUPSTAY,
PLAT_UPWAITDOWNSTAY,
PLAT_UPBYVALUEWAITDOWNSTAY,
//PLAT_RAISEANDCHANGE,
//PLAT_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;
int 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, byte *args, plattype_e type, int amount);
void P_AddActivePlat(plat_t *plat);
void P_RemoveActivePlat(plat_t *plat);
void EV_StopPlat(line_t *line, byte *args);
/*
===============================================================================
P_DOORS
===============================================================================
*/
typedef enum
{
DREV_NORMAL,
DREV_CLOSE30THENOPEN,
DREV_CLOSE,
DREV_OPEN,
DREV_RAISEIN5MINS,
} vldoor_e;
typedef struct
{
thinker_t thinker;
sector_t *sector;
vldoor_e type;
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
boolean EV_VerticalDoor(line_t *line, mobj_t *thing);
int EV_DoDoor(line_t *line, byte *args, vldoor_e type);
void T_VerticalDoor(vldoor_t *door);
//void P_SpawnDoorCloseIn30(sector_t *sec);
//void P_SpawnDoorRaiseIn5Mins(sector_t *sec, int secnum);
/*
===============================================================================
P_CEILNG
===============================================================================
*/
typedef enum
{
CLEV_LOWERTOFLOOR,
CLEV_RAISETOHIGHEST,
CLEV_LOWERANDCRUSH,
CLEV_CRUSHANDRAISE,
CLEV_LOWERBYVALUE,
CLEV_RAISEBYVALUE,
CLEV_CRUSHRAISEANDSTAY,
CLEV_MOVETOVALUETIMES8
} ceiling_e;
typedef struct
{
thinker_t thinker;
sector_t *sector;
ceiling_e type;
fixed_t bottomheight, topheight;
fixed_t speed;
int 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, byte *args, 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, byte *args);
/*
===============================================================================
P_FLOOR
===============================================================================
*/
typedef enum
{
FLEV_LOWERFLOOR, // lower floor to highest surrounding floor
FLEV_LOWERFLOORTOLOWEST, // lower floor to lowest surrounding floor
FLEV_LOWERFLOORBYVALUE,
FLEV_RAISEFLOOR, // raise floor to lowest surrounding CEILING
FLEV_RAISEFLOORTONEAREST, // raise floor to next highest surrounding floor
FLEV_RAISEFLOORBYVALUE,
FLEV_RAISEFLOORCRUSH,
FLEV_RAISEBUILDSTEP, // One step of a staircase
FLEV_RAISEBYVALUETIMES8,
FLEV_LOWERBYVALUETIMES8,
FLEV_LOWERTIMES8INSTANT,
FLEV_RAISETIMES8INSTANT,
FLEV_MOVETOVALUETIMES8
} floor_e;
typedef struct
{
thinker_t thinker;
sector_t *sector;
floor_e type;
int crush;
int direction;
int newspecial;
short texture;
fixed_t floordestheight;
fixed_t speed;
int delayCount;
int delayTotal;
fixed_t stairsDelayHeight;
fixed_t stairsDelayHeightDelta;
fixed_t resetHeight;
short resetDelay;
short resetDelayCount;
byte textureChange;
} floormove_t;
typedef struct
{
thinker_t thinker;
sector_t *sector;
int ceilingSpeed;
int floorSpeed;
int floordest;
int ceilingdest;
int direction;
int crush;
} pillar_t;
typedef struct
{
thinker_t thinker;
sector_t *sector;
fixed_t originalHeight;
fixed_t accumulator;
fixed_t accDelta;
fixed_t targetScale;
fixed_t scale;
fixed_t scaleDelta;
int ticker;
int state;
} floorWaggle_t;
#define FLOORSPEED FRACUNIT
typedef enum
{
RES_OK,
RES_CRUSHED,
RES_PASTDEST
} result_e;
typedef enum
{
STAIRS_NORMAL,
STAIRS_SYNC,
STAIRS_PHASED
} stairs_e;
result_e T_MovePlane(sector_t *sector, fixed_t speed,
fixed_t dest, int crush, int floorOrCeiling, int direction);
int EV_BuildStairs(line_t *line, byte *args, int direction, stairs_e type);
int EV_DoFloor(line_t *line, byte *args, floor_e floortype);
void T_MoveFloor(floormove_t *floor);
void T_BuildPillar(pillar_t *pillar);
void T_FloorWaggle(floorWaggle_t *waggle);
int EV_BuildPillar(line_t *line, byte *args, boolean crush);
int EV_OpenPillar(line_t *line, byte *args);
int EV_DoFloorAndCeiling(line_t *line, byte *args, boolean raise);
int EV_FloorCrushStop(line_t *line, byte *args);
boolean EV_StartFloorWaggle(int tag, int height, int speed, int offset,
int timer);
//--------------------------------------------------------------------------
//
// p_telept
//
//--------------------------------------------------------------------------
boolean P_Teleport(mobj_t *thing, fixed_t x, fixed_t y, angle_t angle,
boolean useFog);
boolean EV_Teleport(int tid, mobj_t *thing, boolean fog);
//--------------------------------------------------------------------------
//
// p_acs
//
//--------------------------------------------------------------------------
#define MAX_ACS_SCRIPT_VARS 10
#define MAX_ACS_MAP_VARS 32
#define MAX_ACS_WORLD_VARS 64
#define ACS_STACK_DEPTH 32
#define MAX_ACS_STORE 20
typedef enum
{
ASTE_INACTIVE,
ASTE_RUNNING,
ASTE_SUSPENDED,
ASTE_WAITINGFORTAG,
ASTE_WAITINGFORPOLY,
ASTE_WAITINGFORSCRIPT,
ASTE_TERMINATING
} aste_t;
typedef struct acs_s acs_t;
typedef struct acsInfo_s acsInfo_t;
struct acsInfo_s
{
int number;
int *address;
int argCount;
aste_t state;
int waitValue;
};
struct acs_s
{
thinker_t thinker;
mobj_t *activator;
line_t *line;
int side;
int number;
int infoIndex;
int delayCount;
int stack[ACS_STACK_DEPTH];
int stackPtr;
int vars[MAX_ACS_SCRIPT_VARS];
int *ip;
};
typedef struct
{
int map; // Target map
int script; // Script number on target map
byte args[4]; // Padded to 4 for alignment
} acsstore_t;
void P_LoadACScripts(int lump);
boolean P_StartACS(int number, int map, byte *args, mobj_t *activator,
line_t *line, int side);
boolean P_StartLockedACS(line_t *line, byte *args, mobj_t *mo, int side);
boolean P_TerminateACS(int number, int map);
boolean P_SuspendACS(int number, int map);
void T_InterpretACS(acs_t *script);
void P_TagFinished(int tag);
void P_PolyobjFinished(int po);
void P_ACSInitNewGame(void);
void P_CheckACSStore(void);
extern int ACScriptCount;
extern byte *ActionCodeBase;
extern acsInfo_t *ACSInfo;
extern int MapVars[MAX_ACS_MAP_VARS];
extern int WorldVars[MAX_ACS_WORLD_VARS];
extern acsstore_t ACSStore[MAX_ACS_STORE+1]; // +1 for termination marker
//--------------------------------------------------------------------------
//
// p_things
//
//--------------------------------------------------------------------------
extern mobjtype_t TranslateThingType[];
boolean EV_ThingProjectile(byte *args, boolean gravity);
boolean EV_ThingSpawn(byte *args, boolean fog);
boolean EV_ThingActivate(int tid);
boolean EV_ThingDeactivate(int tid);
boolean EV_ThingRemove(int tid);
boolean EV_ThingDestroy(int tid);

146
Hexen Source/P_SWITCH.C Normal file
View File

@ -0,0 +1,146 @@
//**************************************************************************
//**
//** p_switch.c : Heretic 2 : Raven Software, Corp.
//**
//** $RCSfile: p_switch.c,v $
//** $Revision: 1.8 $
//** $Date: 95/09/05 13:58:59 $
//** $Author: cjr $
//**
//**************************************************************************
#include "h2def.h"
#include "p_local.h"
#include "soundst.h"
//==================================================================
//
// CHANGE THE TEXTURE OF A WALL SWITCH TO ITS OPPOSITE
//
//==================================================================
switchlist_t alphSwitchList[] =
{
{ "SW_1_UP", "SW_1_DN", SFX_SWITCH1 },
{ "SW_2_UP", "SW_2_DN", SFX_SWITCH1 },
{ "VALVE1", "VALVE2", SFX_VALVE_TURN },
{ "SW51_OFF", "SW51_ON", SFX_SWITCH2 },
{ "SW52_OFF", "SW52_ON", SFX_SWITCH2 },
{ "SW53_UP", "SW53_DN", SFX_ROPE_PULL },
{ "PUZZLE5", "PUZZLE9", SFX_SWITCH1 },
{ "PUZZLE6", "PUZZLE10", SFX_SWITCH1 },
{ "PUZZLE7", "PUZZLE11", SFX_SWITCH1 },
{ "PUZZLE8", "PUZZLE12", SFX_SWITCH1 },
{"\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;
for (index = 0, i = 0; i < MAXSWITCHES; i++)
{
if(!alphSwitchList[i].soundID)
{
numswitches = index/2;
switchlist[index] = -1;
break;
}
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;
texTop = sides[line->sidenum[0]].toptexture;
texMid = sides[line->sidenum[0]].midtexture;
texBot = sides[line->sidenum[0]].bottomtexture;
for (i = 0; i < numswitches*2; i++)
{
if (switchlist[i] == texTop)
{
S_StartSound((mobj_t *)&line->frontsector->soundorg,
alphSwitchList[i/2].soundID);
sides[line->sidenum[0]].toptexture = switchlist[i^1];
if(useAgain)
{
P_StartButton(line, SWTCH_TOP, switchlist[i], BUTTONTIME);
}
return;
}
else if (switchlist[i] == texMid)
{
S_StartSound((mobj_t *)&line->frontsector->soundorg,
alphSwitchList[i/2].soundID);
sides[line->sidenum[0]].midtexture = switchlist[i^1];
if(useAgain)
{
P_StartButton(line, SWTCH_MIDDLE, switchlist[i], BUTTONTIME);
}
return;
}
else if (switchlist[i] == texBot)
{
S_StartSound((mobj_t *)&line->frontsector->soundorg,
alphSwitchList[i/2].soundID);
sides[line->sidenum[0]].bottomtexture = switchlist[i^1];
if(useAgain)
{
P_StartButton(line, SWTCH_BOTTOM, switchlist[i], BUTTONTIME);
}
return;
}
}
}

177
Hexen Source/P_TELEPT.C Normal file
View File

@ -0,0 +1,177 @@
//**************************************************************************
//**
//** p_telept.c : Heretic 2 : Raven Software, Corp.
//**
//** $RCSfile: p_telept.c,v $
//** $Revision: 1.13 $
//** $Date: 95/10/08 04:23:24 $
//** $Author: paul $
//**
//**************************************************************************
// HEADER FILES ------------------------------------------------------------
#include "h2def.h"
#include "p_local.h"
#include "soundst.h"
// MACROS ------------------------------------------------------------------
// TYPES -------------------------------------------------------------------
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
// PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
// PUBLIC DATA DEFINITIONS -------------------------------------------------
// PRIVATE DATA DEFINITIONS ------------------------------------------------
// CODE --------------------------------------------------------------------
//==========================================================================
//
// P_Teleport
//
//==========================================================================
boolean P_Teleport(mobj_t *thing, fixed_t x, fixed_t y, angle_t angle,
boolean useFog)
{
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;
if(useFog)
{
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
if(useFog)
{
fogDelta = thing->flags&MF_MISSILE ? 0 : TELEFOGHEIGHT;
fog = P_SpawnMobj(oldx, oldy, oldz+fogDelta, MT_TFOG);
S_StartSound(fog, SFX_TELEPORT);
an = angle>>ANGLETOFINESHIFT;
fog = P_SpawnMobj(x+20*finecosine[an],
y+20*finesine[an], thing->z+fogDelta, MT_TFOG);
S_StartSound(fog, SFX_TELEPORT);
if(thing->player && !thing->player->powers[pw_speed])
{ // Freeze player for about .5 sec
thing->reactiontime = 18;
}
thing->angle = angle;
}
if(thing->flags2&MF2_FLOORCLIP)
{
if(thing->z == thing->subsector->sector->floorheight
&& P_GetThingFloorType(thing) > FLOOR_SOLID)
{
thing->floorclip = 10*FRACUNIT;
}
else
{
thing->floorclip = 0;
}
}
if(thing->flags&MF_MISSILE)
{
angle >>= ANGLETOFINESHIFT;
thing->momx = FixedMul(thing->info->speed, finecosine[angle]);
thing->momy = FixedMul(thing->info->speed, finesine[angle]);
}
else if(useFog) // no fog doesn't alter the player's momentums
{
thing->momx = thing->momy = thing->momz = 0;
}
return true;
}
//==========================================================================
//
// EV_Teleport
//
//==========================================================================
boolean EV_Teleport(int tid, mobj_t *thing, boolean fog)
{
int i;
int count;
mobj_t *mo;
int searcher;
if(!thing)
{ // Teleport function called with an invalid mobj
return false;
}
if(thing->flags2&MF2_NOTELEPORT)
{
return false;
}
count = 0;
searcher = -1;
while(P_FindMobjFromTID(tid, &searcher) != NULL)
{
count++;
}
if(count == 0)
{
return false;
}
count = 1+(P_Random()%count);
searcher = -1;
for(i = 0; i < count; i++)
{
mo = P_FindMobjFromTID(tid, &searcher);
}
if (!mo) I_Error("Can't find teleport mapspot\n");
return P_Teleport(thing, mo->x, mo->y, mo->angle, fog);
}

533
Hexen Source/P_THINGS.C Normal file
View File

@ -0,0 +1,533 @@
//**************************************************************************
//**
//** p_things.c : Heretic 2 : Raven Software, Corp.
//**
//** $RCSfile: p_things.c,v $
//** $Revision: 1.36 $
//** $Date: 96/02/08 15:16:13 $
//** $Author: bgokey $
//**
//**************************************************************************
// HEADER FILES ------------------------------------------------------------
#include "h2def.h"
#include "p_local.h"
#include "soundst.h"
// MACROS ------------------------------------------------------------------
// TYPES -------------------------------------------------------------------
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
// PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
static boolean ActivateThing(mobj_t *mobj);
static boolean DeactivateThing(mobj_t *mobj);
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
// PUBLIC DATA DEFINITIONS -------------------------------------------------
mobjtype_t TranslateThingType[] =
{
MT_MAPSPOT, // T_NONE
MT_CENTAUR, // T_CENTAUR
MT_CENTAURLEADER, // T_CENTAURLEADER
MT_DEMON, // T_DEMON
MT_ETTIN, // T_ETTIN
MT_FIREDEMON, // T_FIREGARGOYLE
MT_SERPENT, // T_WATERLURKER
MT_SERPENTLEADER, // T_WATERLURKERLEADER
MT_WRAITH, // T_WRAITH
MT_WRAITHB, // T_WRAITHBURIED
MT_FIREBALL1, // T_FIREBALL1
MT_MANA1, // T_MANA1
MT_MANA2, // T_MANA2
MT_SPEEDBOOTS, // T_ITEMBOOTS
MT_ARTIEGG, // T_ITEMEGG
MT_ARTIFLY, // T_ITEMFLIGHT
MT_SUMMONMAULATOR, // T_ITEMSUMMON
MT_TELEPORTOTHER, // T_ITEMTPORTOTHER
MT_ARTITELEPORT, // T_ITEMTELEPORT
MT_BISHOP, // T_BISHOP
MT_ICEGUY, // T_ICEGOLEM
MT_BRIDGE, // T_BRIDGE
MT_BOOSTARMOR, // T_DRAGONSKINBRACERS
MT_HEALINGBOTTLE, // T_ITEMHEALTHPOTION
MT_HEALTHFLASK, // T_ITEMHEALTHFLASK
MT_ARTISUPERHEAL, // T_ITEMHEALTHFULL
MT_BOOSTMANA, // T_ITEMBOOSTMANA
MT_FW_AXE, // T_FIGHTERAXE
MT_FW_HAMMER, // T_FIGHTERHAMMER
MT_FW_SWORD1, // T_FIGHTERSWORD1
MT_FW_SWORD2, // T_FIGHTERSWORD2
MT_FW_SWORD3, // T_FIGHTERSWORD3
MT_CW_SERPSTAFF, // T_CLERICSTAFF
MT_CW_HOLY1, // T_CLERICHOLY1
MT_CW_HOLY2, // T_CLERICHOLY2
MT_CW_HOLY3, // T_CLERICHOLY3
MT_MW_CONE, // T_MAGESHARDS
MT_MW_STAFF1, // T_MAGESTAFF1
MT_MW_STAFF2, // T_MAGESTAFF2
MT_MW_STAFF3, // T_MAGESTAFF3
MT_EGGFX, // T_MORPHBLAST
MT_ROCK1, // T_ROCK1
MT_ROCK2, // T_ROCK2
MT_ROCK3, // T_ROCK3
MT_DIRT1, // T_DIRT1
MT_DIRT2, // T_DIRT2
MT_DIRT3, // T_DIRT3
MT_DIRT4, // T_DIRT4
MT_DIRT5, // T_DIRT5
MT_DIRT6, // T_DIRT6
MT_ARROW, // T_ARROW
MT_DART, // T_DART
MT_POISONDART, // T_POISONDART
MT_RIPPERBALL, // T_RIPPERBALL
MT_SGSHARD1, // T_STAINEDGLASS1
MT_SGSHARD2, // T_STAINEDGLASS2
MT_SGSHARD3, // T_STAINEDGLASS3
MT_SGSHARD4, // T_STAINEDGLASS4
MT_SGSHARD5, // T_STAINEDGLASS5
MT_SGSHARD6, // T_STAINEDGLASS6
MT_SGSHARD7, // T_STAINEDGLASS7
MT_SGSHARD8, // T_STAINEDGLASS8
MT_SGSHARD9, // T_STAINEDGLASS9
MT_SGSHARD0, // T_STAINEDGLASS0
MT_PROJECTILE_BLADE, // T_BLADE
MT_ICESHARD, // T_ICESHARD
MT_FLAME_SMALL, // T_FLAME_SMALL
MT_FLAME_LARGE, // T_FLAME_LARGE
MT_ARMOR_1, // T_MESHARMOR
MT_ARMOR_2, // T_FALCONSHIELD
MT_ARMOR_3, // T_PLATINUMHELM
MT_ARMOR_4, // T_AMULETOFWARDING
MT_ARTIPOISONBAG, // T_ITEMFLECHETTE
MT_ARTITORCH, // T_ITEMTORCH
MT_BLASTRADIUS, // T_ITEMREPULSION
MT_MANA3, // T_MANA3
MT_ARTIPUZZSKULL, // T_PUZZSKULL
MT_ARTIPUZZGEMBIG, // T_PUZZGEMBIG
MT_ARTIPUZZGEMRED, // T_PUZZGEMRED
MT_ARTIPUZZGEMGREEN1, // T_PUZZGEMGREEN1
MT_ARTIPUZZGEMGREEN2, // T_PUZZGEMGREEN2
MT_ARTIPUZZGEMBLUE1, // T_PUZZGEMBLUE1
MT_ARTIPUZZGEMBLUE2, // T_PUZZGEMBLUE2
MT_ARTIPUZZBOOK1, // T_PUZZBOOK1
MT_ARTIPUZZBOOK2, // T_PUZZBOOK2
MT_KEY1, // T_METALKEY
MT_KEY2, // T_SMALLMETALKEY
MT_KEY3, // T_AXEKEY
MT_KEY4, // T_FIREKEY
MT_KEY5, // T_GREENKEY
MT_KEY6, // T_MACEKEY
MT_KEY7, // T_SILVERKEY
MT_KEY8, // T_RUSTYKEY
MT_KEY9, // T_HORNKEY
MT_KEYA, // T_SERPENTKEY
MT_WATER_DRIP, // T_WATERDRIP
MT_FLAME_SMALL_TEMP, // T_TEMPSMALLFLAME
MT_FLAME_SMALL, // T_PERMSMALLFLAME
MT_FLAME_LARGE_TEMP, // T_TEMPLARGEFLAME
MT_FLAME_LARGE, // T_PERMLARGEFLAME
MT_DEMON_MASH, // T_DEMON_MASH
MT_DEMON2_MASH, // T_DEMON2_MASH
MT_ETTIN_MASH, // T_ETTIN_MASH
MT_CENTAUR_MASH, // T_CENTAUR_MASH
MT_THRUSTFLOOR_UP, // T_THRUSTSPIKEUP
MT_THRUSTFLOOR_DOWN, // T_THRUSTSPIKEDOWN
MT_WRAITHFX4, // T_FLESH_DRIP1
MT_WRAITHFX5, // T_FLESH_DRIP2
MT_WRAITHFX2 // T_SPARK_DRIP
};
// PRIVATE DATA DEFINITIONS ------------------------------------------------
// CODE --------------------------------------------------------------------
//==========================================================================
//
// EV_ThingProjectile
//
//==========================================================================
boolean EV_ThingProjectile(byte *args, boolean gravity)
{
int tid;
angle_t angle;
int fineAngle;
fixed_t speed;
fixed_t vspeed;
mobjtype_t moType;
mobj_t *mobj;
mobj_t *newMobj;
int searcher;
boolean success;
success = false;
searcher = -1;
tid = args[0];
moType = TranslateThingType[args[1]];
if(nomonsters && (mobjinfo[moType].flags&MF_COUNTKILL))
{ // Don't spawn monsters if -nomonsters
return false;
}
angle = (int)args[2]<<24;
fineAngle = angle>>ANGLETOFINESHIFT;
speed = (int)args[3]<<13;
vspeed = (int)args[4]<<13;
while((mobj = P_FindMobjFromTID(tid, &searcher)) != NULL)
{
newMobj = P_SpawnMobj(mobj->x, mobj->y, mobj->z, moType);
if(newMobj->info->seesound)
{
S_StartSound(newMobj, newMobj->info->seesound);
}
newMobj->target = mobj; // Originator
newMobj->angle = angle;
newMobj->momx = FixedMul(speed, finecosine[fineAngle]);
newMobj->momy = FixedMul(speed, finesine[fineAngle]);
newMobj->momz = vspeed;
newMobj->flags2 |= MF2_DROPPED; // Don't respawn
if(gravity == true)
{
newMobj->flags &= ~MF_NOGRAVITY;
newMobj->flags2 |= MF2_LOGRAV;
}
if(P_CheckMissileSpawn(newMobj) == true)
{
success = true;
}
}
return success;
}
//==========================================================================
//
// EV_ThingSpawn
//
//==========================================================================
boolean EV_ThingSpawn(byte *args, boolean fog)
{
int tid;
angle_t angle;
mobj_t *mobj;
mobj_t *newMobj;
mobj_t *fogMobj;
mobjtype_t moType;
int searcher;
boolean success;
fixed_t z;
success = false;
searcher = -1;
tid = args[0];
moType = TranslateThingType[args[1]];
if(nomonsters && (mobjinfo[moType].flags&MF_COUNTKILL))
{ // Don't spawn monsters if -nomonsters
return false;
}
angle = (int)args[2]<<24;
while((mobj = P_FindMobjFromTID(tid, &searcher)) != NULL)
{
if (mobjinfo[moType].flags2&MF2_FLOATBOB)
{
z = mobj->z - mobj->floorz;
}
else
{
z = mobj->z;
}
newMobj = P_SpawnMobj(mobj->x, mobj->y, z, moType);
if(P_TestMobjLocation(newMobj) == false)
{ // Didn't fit
P_RemoveMobj(newMobj);
}
else
{
newMobj->angle = angle;
if(fog == true)
{
fogMobj = P_SpawnMobj(mobj->x, mobj->y,
mobj->z+TELEFOGHEIGHT, MT_TFOG);
S_StartSound(fogMobj, SFX_TELEPORT);
}
newMobj->flags2 |= MF2_DROPPED; // Don't respawn
if (newMobj->flags2&MF2_FLOATBOB)
{
newMobj->special1 = newMobj->z - newMobj->floorz;
}
success = true;
}
}
return success;
}
//==========================================================================
//
// EV_ThingActivate
//
//==========================================================================
boolean EV_ThingActivate(int tid)
{
mobj_t *mobj;
int searcher;
boolean success;
success = false;
searcher = -1;
while((mobj = P_FindMobjFromTID(tid, &searcher)) != NULL)
{
if(ActivateThing(mobj) == true)
{
success = true;
}
}
return success;
}
//==========================================================================
//
// EV_ThingDeactivate
//
//==========================================================================
boolean EV_ThingDeactivate(int tid)
{
mobj_t *mobj;
int searcher;
boolean success;
success = false;
searcher = -1;
while((mobj = P_FindMobjFromTID(tid, &searcher)) != NULL)
{
if(DeactivateThing(mobj) == true)
{
success = true;
}
}
return success;
}
//==========================================================================
//
// EV_ThingRemove
//
//==========================================================================
boolean EV_ThingRemove(int tid)
{
mobj_t *mobj;
int searcher;
boolean success;
success = false;
searcher = -1;
while((mobj = P_FindMobjFromTID(tid, &searcher)) != NULL)
{
if (mobj->type == MT_BRIDGE)
{
A_BridgeRemove(mobj);
return true;
}
P_RemoveMobj(mobj);
success = true;
}
return success;
}
//==========================================================================
//
// EV_ThingDestroy
//
//==========================================================================
boolean EV_ThingDestroy(int tid)
{
mobj_t *mobj;
int searcher;
boolean success;
success = false;
searcher = -1;
while((mobj = P_FindMobjFromTID(tid, &searcher)) != NULL)
{
if(mobj->flags&MF_SHOOTABLE)
{
P_DamageMobj(mobj, NULL, NULL, 10000);
success = true;
}
}
return success;
}
//==========================================================================
//
// EV_ThingMove
//
// arg[0] = tid
// arg[1] = speed
// arg[2] = angle (255 = use mobj angle)
// arg[3] = distance (pixels>>2)
//
//==========================================================================
/*
boolean EV_ThingMove(byte *args)
{
return false;
}
*/
//==========================================================================
//
// ActivateThing
//
//==========================================================================
static boolean ActivateThing(mobj_t *mobj)
{
if(mobj->flags&MF_COUNTKILL)
{ // Monster
if(mobj->flags2&MF2_DORMANT)
{
mobj->flags2 &= ~MF2_DORMANT;
mobj->tics = 1;
return true;
}
return false;
}
switch(mobj->type)
{
case MT_ZTWINEDTORCH:
case MT_ZTWINEDTORCH_UNLIT:
P_SetMobjState(mobj, S_ZTWINEDTORCH_1);
S_StartSound(mobj, SFX_IGNITE);
break;
case MT_ZWALLTORCH:
case MT_ZWALLTORCH_UNLIT:
P_SetMobjState(mobj, S_ZWALLTORCH1);
S_StartSound(mobj, SFX_IGNITE);
break;
case MT_ZGEMPEDESTAL:
P_SetMobjState(mobj, S_ZGEMPEDESTAL2);
break;
case MT_ZWINGEDSTATUENOSKULL:
P_SetMobjState(mobj, S_ZWINGEDSTATUENOSKULL2);
break;
case MT_THRUSTFLOOR_UP:
case MT_THRUSTFLOOR_DOWN:
if (mobj->args[0]==0)
{
S_StartSound(mobj, SFX_THRUSTSPIKE_LOWER);
mobj->flags2 &= ~MF2_DONTDRAW;
if (mobj->args[1])
P_SetMobjState(mobj, S_BTHRUSTRAISE1);
else
P_SetMobjState(mobj, S_THRUSTRAISE1);
}
break;
case MT_ZFIREBULL:
case MT_ZFIREBULL_UNLIT:
P_SetMobjState(mobj, S_ZFIREBULL_BIRTH);
S_StartSound(mobj, SFX_IGNITE);
break;
case MT_ZBELL:
if(mobj->health > 0)
{
P_DamageMobj(mobj, NULL, NULL, 10); // 'ring' the bell
}
break;
case MT_ZCAULDRON:
case MT_ZCAULDRON_UNLIT:
P_SetMobjState(mobj, S_ZCAULDRON1);
S_StartSound(mobj, SFX_IGNITE);
break;
case MT_FLAME_SMALL:
S_StartSound(mobj, SFX_IGNITE);
P_SetMobjState(mobj, S_FLAME_SMALL1);
break;
case MT_FLAME_LARGE:
S_StartSound(mobj, SFX_IGNITE);
P_SetMobjState(mobj, S_FLAME_LARGE1);
break;
case MT_BAT_SPAWNER:
P_SetMobjState(mobj, S_SPAWNBATS1);
break;
default:
return false;
break;
}
return true;
}
//==========================================================================
//
// DeactivateThing
//
//==========================================================================
static boolean DeactivateThing(mobj_t *mobj)
{
if(mobj->flags&MF_COUNTKILL)
{ // Monster
if(!(mobj->flags2&MF2_DORMANT))
{
mobj->flags2 |= MF2_DORMANT;
mobj->tics = -1;
return true;
}
return false;
}
switch(mobj->type)
{
case MT_ZTWINEDTORCH:
case MT_ZTWINEDTORCH_UNLIT:
P_SetMobjState(mobj, S_ZTWINEDTORCH_UNLIT);
break;
case MT_ZWALLTORCH:
case MT_ZWALLTORCH_UNLIT:
P_SetMobjState(mobj, S_ZWALLTORCH_U);
break;
case MT_THRUSTFLOOR_UP:
case MT_THRUSTFLOOR_DOWN:
if (mobj->args[0]==1)
{
S_StartSound(mobj, SFX_THRUSTSPIKE_RAISE);
if (mobj->args[1])
P_SetMobjState(mobj, S_BTHRUSTLOWER);
else
P_SetMobjState(mobj, S_THRUSTLOWER);
}
break;
case MT_ZFIREBULL:
case MT_ZFIREBULL_UNLIT:
P_SetMobjState(mobj, S_ZFIREBULL_DEATH);
break;
case MT_ZCAULDRON:
case MT_ZCAULDRON_UNLIT:
P_SetMobjState(mobj, S_ZCAULDRON_U);
break;
case MT_FLAME_SMALL:
P_SetMobjState(mobj, S_FLAME_SDORM1);
break;
case MT_FLAME_LARGE:
P_SetMobjState(mobj, S_FLAME_LDORM1);
break;
case MT_BAT_SPAWNER:
P_SetMobjState(mobj, S_SPAWNBATS_OFF);
break;
default:
return false;
break;
}
return true;
}

142
Hexen Source/P_TICK.C Normal file
View File

@ -0,0 +1,142 @@
//**************************************************************************
//**
//** p_tick.c : Heretic 2 : Raven Software, Corp.
//**
//** $RCSfile: p_tick.c,v $
//** $Revision: 1.5 $
//** $Date: 95/10/08 21:53:00 $
//** $Author: bgokey $
//**
//**************************************************************************
// HEADER FILES ------------------------------------------------------------
#include "h2def.h"
#include "p_local.h"
// MACROS ------------------------------------------------------------------
// TYPES -------------------------------------------------------------------
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
// PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
static void RunThinkers(void);
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
// PUBLIC DATA DEFINITIONS -------------------------------------------------
int leveltime;
int TimerGame;
thinker_t thinkercap; // The head and tail of the thinker list
// PRIVATE DATA DEFINITIONS ------------------------------------------------
// CODE --------------------------------------------------------------------
//==========================================================================
//
// 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_Completed(P_TranslateMap(P_GetMapNextMap(gamemap)), 0);
}
}
RunThinkers();
P_UpdateSpecials();
P_AnimateSurfaces();
leveltime++;
}
//==========================================================================
//
// RunThinkers
//
//==========================================================================
static void 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;
}
}
//==========================================================================
//
// 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;
}

1652
Hexen Source/P_USER.C Normal file

File diff suppressed because it is too large Load Diff

504
Hexen Source/R_BSP.C Normal file
View File

@ -0,0 +1,504 @@
//**************************************************************************
//**
//** r_bsp.c : Heretic 2 : Raven Software, Corp.
//**
//** $RCSfile: r_bsp.c,v $
//** $Revision: 1.2 $
//** $Date: 95/07/13 15:17:10 $
//** $Author: cjr $
//**
//**************************************************************************
#include "h2def.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
&& backsector->special == frontsector->special
&& 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;
int polyCount;
seg_t **polySeg;
#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);
if(sub->poly)
{ // Render the polyobj in the subsector first
polyCount = sub->poly->numsegs;
polySeg = sub->poly->segs;
while(polyCount--)
{
R_AddLine(*polySeg++);
}
}
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]);
}

676
Hexen Source/R_DATA.C Normal file
View File

@ -0,0 +1,676 @@
//**************************************************************************
//**
//** r_data.c : Heretic 2 : Raven Software, Corp.
//**
//** $RCSfile: r_data.c,v $
//** $Revision: 1.8 $
//** $Date: 96/03/12 12:04:04 $
//** $Author: bgokey $
//**
//**************************************************************************
#include "h2def.h"
#include "r_local.h"
#include "p_local.h"
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])
{
ST_Message ("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;
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++)
{
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);
if(!(i&31)) ST_Progress();
}
//
// 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++)
{
if (!(i&127)) ST_Progress();
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)
{
R_InitTextures();
R_InitFlats();
R_InitSpriteLumps();
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[Sky1Texture] = 1;
texturepresent[Sky2Texture] = 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);
}
}
}
}

576
Hexen Source/R_DRAW.C Normal file
View File

@ -0,0 +1,576 @@
//**************************************************************************
//**
//** r_draw.c : Heretic 2 : Raven Software, Corp.
//**
//** $RCSfile: r_draw.c,v $
//** $Revision: 1.11 $
//** $Date: 96/01/06 18:37:37 $
//** $Author: bgokey $
//**
//**************************************************************************
#include "h2def.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;
*/
#ifndef __WATCOMC__
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+
(dc_colormap[dc_source[(frac>>FRACBITS)&127]]<<8)];
dest += SCREENWIDTH;
frac += fracstep;
} while(count--);
}
#endif
//============================================================================
//
// R_DrawAltFuzzColumn
//
//============================================================================
void R_DrawAltFuzzColumn (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;
do
{
*dest = tinttable[((*dest)<<8)
+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--);
}
//============================================================================
//
// R_DrawTranslatedFuzzColumn
//
//============================================================================
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--);
}
//============================================================================
//
// R_DrawTranslatedAltFuzzColumn
//
//============================================================================
/*
void R_DrawTranslatedAltFuzzColumn (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
+(dc_colormap[dc_translation[dc_source[frac>>FRACBITS]]]<<8)];
dest += SCREENWIDTH;
frac += fracstep;
} while (count--);
}
*/
//--------------------------------------------------------------------------
//
// PROC R_InitTranslationTables
//
//--------------------------------------------------------------------------
void R_InitTranslationTables (void)
{
int i;
byte *transLump;
// Load tint table
tinttable = W_CacheLumpName("TINTTAB", PU_STATIC);
// Allocate translation tables
translationtables = Z_Malloc(256*3*(MAXPLAYERS-1)+255,
PU_STATIC, 0);
translationtables = (byte *)(((int)translationtables+255)&~255);
for(i = 0; i < 3*(MAXPLAYERS-1); i++)
{
transLump = W_CacheLumpNum(W_GetNumForName("trantbl0")+i, PU_STATIC);
memcpy(translationtables+i*256, transLump, 256);
Z_Free(transLump);
}
}
/*
================
=
= 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;
src = W_CacheLumpName("F_022", 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);
}
*/
src = W_CacheLumpName("F_022", PU_CACHE);
dest = screen;
for (y=0 ; y<34 ; 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 < 35)
{
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));
}
}

538
Hexen Source/R_LOCAL.H Normal file
View File

@ -0,0 +1,538 @@
//**************************************************************************
//**
//** r_local.h : Heretic 2 : Raven Software, Corp.
//**
//** $RCSfile: r_local.h,v $
//** $Revision: 1.12 $
//** $Date: 96/01/06 18:37:38 $
//** $Author: bgokey $
//**
//**************************************************************************
#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)
seqtype_t seqType; // stone, metal, heavy, etc...
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 line_s
{
vertex_t *v1;
vertex_t *v2;
fixed_t dx;
fixed_t dy;
short flags;
byte special;
byte arg1;
byte arg2;
byte arg3;
byte arg4;
byte arg5;
short sidenum[2];
fixed_t bbox[4];
slopetype_t slopetype;
sector_t *frontsector;
sector_t *backsector;
int validcount;
void *specialdata;
} line_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;
// ===== Polyobj data =====
typedef struct
{
int numsegs;
seg_t **segs;
degenmobj_t startSpot;
vertex_t *originalPts; // used as the base for the rotations
vertex_t *prevPts; // use to restore the old point values
angle_t angle;
int tag; // reference tag assigned in HereticEd
int bbox[4];
int validcount;
boolean crush; // should the polyobj attempt to crush mobjs?
int seqType;
fixed_t size; // polyobj size (area of POLY_AREAUNIT == size of FRACUNIT)
void *specialdata; // pointer a thinker, if the poly is moving
} polyobj_t;
typedef struct polyblock_s
{
polyobj_t *polyobj;
struct polyblock_s *prev;
struct polyblock_s *next;
} polyblock_t;
typedef struct subsector_s
{
sector_t *sector;
short numlines;
short firstline;
polyobj_t *poly;
} subsector_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 160
#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
int class; // player class (used in translation)
fixed_t floorclip;
} 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
extern int TransTextureStart;
extern int TransTextureEnd;
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;
extern boolean LevelUseFullBright;
byte *R_GetColumn (int tex, int col);
void R_InitData (void);
void R_PrecacheLevel (void);
//
// R_things.c
//
#define MAXVISSPRITES 192
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);
void R_DrawAltFuzzColumn(void);
//void R_DrawTranslatedAltFuzzColumn(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__

860
Hexen Source/R_MAIN.C Normal file
View File

@ -0,0 +1,860 @@
//**************************************************************************
//**
//** r_main.c : Heretic 2 : Raven Software, Corp.
//**
//** $RCSfile: r_main.c,v $
//** $Revision: 1.16 $
//** $Date: 96/01/06 18:37:41 $
//** $Author: bgokey $
//**
//**************************************************************************
#include <math.h>
#include "h2def.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*161/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)
{
R_InitData();
R_InitPointToAngle();
R_InitTables();
// viewwidth / viewheight / detailLevel are set by the defaults
R_SetViewSize(screenblocks, detailLevel);
R_InitPlanes();
R_InitLightTables();
R_InitSkyMap();
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;
int intensity;
//drawbsp = 1;
viewplayer = player;
#ifdef __WATCOMC__
if(newViewAngleOff)
{
viewangleoffset = newViewAngleOff<<ANGLETOFINESHIFT;
}
#endif
viewangle = player->mo->angle+viewangleoffset;
tableAngle = viewangle>>ANGLETOFINESHIFT;
viewx = player->mo->x;
viewy = player->mo->y;
if(localQuakeHappening[displayplayer] && !paused)
{
intensity = localQuakeHappening[displayplayer];
viewx += ((M_Random() % (intensity<<2))
-(intensity<<1))<<FRACBITS;
viewy += ((M_Random()%(intensity<<2))
-(intensity<<1))<<FRACBITS;
}
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
// Make displayed player invisible locally
if (localQuakeHappening[displayplayer] && gamestate == GS_LEVEL)
{
players[displayplayer].mo->flags2 |= MF2_DONTDRAW;
R_RenderBSPNode (numnodes-1); // head node is the last node output
players[displayplayer].mo->flags2 &= ~MF2_DONTDRAW;
}
else
{
R_RenderBSPNode (numnodes-1); // 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
}

559
Hexen Source/R_PLANE.C Normal file
View File

@ -0,0 +1,559 @@
//**************************************************************************
//**
//** r_plane.c : Heretic 2 : Raven Software, Corp.
//**
//** $RCSfile: r_plane.c,v $
//** $Revision: 1.5 $
//** $Date: 95/07/13 15:17:12 $
//** $Author: cjr $
//**
//**************************************************************************
// HEADER FILES ------------------------------------------------------------
#include "h2def.h"
#include "r_local.h"
// MACROS ------------------------------------------------------------------
// TYPES -------------------------------------------------------------------
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
// PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
extern fixed_t Sky1ScrollDelta;
extern fixed_t Sky2ScrollDelta;
// PUBLIC DATA DEFINITIONS -------------------------------------------------
int Sky1Texture;
int Sky2Texture;
fixed_t Sky1ColumnOffset;
fixed_t Sky2ColumnOffset;
int skyflatnum;
int skytexturemid;
fixed_t skyiscale;
boolean DoubleSky;
planefunction_t floorfunc, ceilingfunc;
// Opening
visplane_t visplanes[MAXVISPLANES], *lastvisplane;
visplane_t *floorplane, *ceilingplane;
short openings[MAXOPENINGS], *lastopening;
// Clip values are the solid pixel bounding the range.
// floorclip start out SCREENHEIGHT
// ceilingclip starts out -1
short floorclip[SCREENWIDTH];
short ceilingclip[SCREENWIDTH];
// spanstart holds the start of a plane span, initialized to 0
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];
// PRIVATE DATA DEFINITIONS ------------------------------------------------
// CODE --------------------------------------------------------------------
//==========================================================================
//
// R_InitSky
//
// Called at level load.
//
//==========================================================================
void R_InitSky(int map)
{
Sky1Texture = P_GetMapSky1Texture(map);
Sky2Texture = P_GetMapSky2Texture(map);
Sky1ScrollDelta = P_GetMapSky1ScrollDelta(map);
Sky2ScrollDelta = P_GetMapSky2ScrollDelta(map);
Sky1ColumnOffset = 0;
Sky2ColumnOffset = 0;
DoubleSky = P_GetMapDoubleSky(map);
}
//==========================================================================
//
// R_InitSkyMap
//
// Called whenever the view size changes.
//
//==========================================================================
void R_InitSkyMap(void)
{
skyflatnum = R_FlatNumForName("F_SKY");
skytexturemid = 200*FRACUNIT;
skyiscale = FRACUNIT;
}
//==========================================================================
//
// R_InitPlanes
//
// Called at game startup.
//
//==========================================================================
void R_InitPlanes(void)
{
}
//==========================================================================
//
// R_MapPlane
//
// Globals used: planeheight, ds_source, basexscale, baseyscale,
// viewx, viewy.
//
//==========================================================================
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
//
// Called at the beginning of each 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(special < 150)
{ // Don't let low specials affect search
special = 0;
}
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 visplane
}
// 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
//
//==========================================================================
#define SKYTEXTUREMIDSHIFTED 200
void R_DrawPlanes(void)
{
visplane_t *pl;
int light;
int x, stop;
int angle;
byte *tempSource;
byte *source;
byte *source2;
byte *dest;
int count;
int offset;
int skyTexture;
int offset2;
int skyTexture2;
int scrollOffset;
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;
}
if(pl->picnum == skyflatnum)
{ // Sky flat
if(DoubleSky)
{ // Render 2 layers, sky 1 in front
offset = Sky1ColumnOffset>>16;
skyTexture = texturetranslation[Sky1Texture];
offset2 = Sky2ColumnOffset>>16;
skyTexture2 = texturetranslation[Sky2Texture];
for(x = pl->minx; x <= pl->maxx; x++)
{
dc_yl = pl->top[x];
dc_yh = pl->bottom[x];
if(dc_yl <= dc_yh)
{
count = dc_yh-dc_yl;
if(count < 0)
{
return;
}
angle = (viewangle+xtoviewangle[x])
>>ANGLETOSKYSHIFT;
source = R_GetColumn(skyTexture, angle+offset)
+SKYTEXTUREMIDSHIFTED+(dc_yl-centery);
source2 = R_GetColumn(skyTexture2, angle+offset2)
+SKYTEXTUREMIDSHIFTED+(dc_yl-centery);
dest = ylookup[dc_yl]+columnofs[x];
do
{
if(*source)
{
*dest = *source++;
source2++;
}
else
{
*dest = *source2++;
source++;
}
dest += SCREENWIDTH;
} while(count--);
}
}
continue; // Next visplane
}
else
{ // Render single layer
if(pl->special == 200)
{ // Use sky 2
offset = Sky2ColumnOffset>>16;
skyTexture = texturetranslation[Sky2Texture];
}
else
{ // Use sky 1
offset = Sky1ColumnOffset>>16;
skyTexture = texturetranslation[Sky1Texture];
}
for(x = pl->minx; x <= pl->maxx; x++)
{
dc_yl = pl->top[x];
dc_yh = pl->bottom[x];
if(dc_yl <= dc_yh)
{
count = dc_yh-dc_yl;
if(count < 0)
{
return;
}
angle = (viewangle+xtoviewangle[x])
>>ANGLETOSKYSHIFT;
source = R_GetColumn(skyTexture, angle+offset)
+SKYTEXTUREMIDSHIFTED+(dc_yl-centery);
dest = ylookup[dc_yl]+columnofs[x];
do
{
*dest = *source++;
dest += SCREENWIDTH;
} while(count--);
}
}
continue; // Next visplane
}
}
// Regular flat
tempSource = W_CacheLumpNum(firstflat+
flattranslation[pl->picnum], PU_STATIC);
scrollOffset = leveltime>>1&63;
switch(pl->special)
{ // Handle scrolling flats
case 201: case 202: case 203: // Scroll_North_xxx
ds_source = tempSource+((scrollOffset
<<(pl->special-201)&63)<<6);
break;
case 204: case 205: case 206: // Scroll_East_xxx
ds_source = tempSource+((63-scrollOffset)
<<(pl->special-204)&63);
break;
case 207: case 208: case 209: // Scroll_South_xxx
ds_source = tempSource+(((63-scrollOffset)
<<(pl->special-207)&63)<<6);
break;
case 210: case 211: case 212: // Scroll_West_xxx
ds_source = tempSource+(scrollOffset
<<(pl->special-210)&63);
break;
case 213: case 214: case 215: // Scroll_NorthWest_xxx
ds_source = tempSource+(scrollOffset
<<(pl->special-213)&63)+((scrollOffset
<<(pl->special-213)&63)<<6);
break;
case 216: case 217: case 218: // Scroll_NorthEast_xxx
ds_source = tempSource+((63-scrollOffset)
<<(pl->special-216)&63)+((scrollOffset
<<(pl->special-216)&63)<<6);
break;
case 219: case 220: case 221: // Scroll_SouthEast_xxx
ds_source = tempSource+((63-scrollOffset)
<<(pl->special-219)&63)+(((63-scrollOffset)
<<(pl->special-219)&63)<<6);
break;
case 222: case 223: case 224: // Scroll_SouthWest_xxx
ds_source = tempSource+(scrollOffset
<<(pl->special-222)&63)+(((63-scrollOffset)
<<(pl->special-222)&63)<<6);
break;
default:
ds_source = tempSource;
break;
}
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);
}
}

651
Hexen Source/R_SEGS.C Normal file
View File

@ -0,0 +1,651 @@
//**************************************************************************
//**
//** r_segs.c : Heretic 2 : Raven Software, Corp.
//**
//** $RCSfile: r_segs.c,v $
//** $Revision: 1.4 $
//** $Date: 95/08/28 17:02:44 $
//** $Author: cjr $
//**
//** This version has the tall-sector-crossing-precision-bug fixed.
//**
//**************************************************************************
#include "h2def.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];
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
|| backsector->special != frontsector->special)
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];
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++;
}

1033
Hexen Source/R_THINGS.C Normal file

File diff suppressed because it is too large Load Diff

2240
Hexen Source/SB_BAR.C Normal file

File diff suppressed because it is too large Load Diff

485
Hexen Source/SC_MAN.C Normal file
View File

@ -0,0 +1,485 @@
//**************************************************************************
//**
//** sc_man.c : Heretic 2 : Raven Software, Corp.
//**
//** $RCSfile: sc_man.c,v $
//** $Revision: 1.3 $
//** $Date: 96/01/06 03:23:43 $
//** $Author: bgokey $
//**
//**************************************************************************
// HEADER FILES ------------------------------------------------------------
#include <string.h>
#include <stdlib.h>
#include "h2def.h"
// MACROS ------------------------------------------------------------------
#define MAX_STRING_SIZE 64
#define ASCII_COMMENT (';')
#define ASCII_QUOTE (34)
#define LUMP_SCRIPT 1
#define FILE_ZONE_SCRIPT 2
#define FILE_CLIB_SCRIPT 3
// TYPES -------------------------------------------------------------------
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
// PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
static void CheckOpen(void);
static void OpenScript(char *name, int type);
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
// PUBLIC DATA DEFINITIONS -------------------------------------------------
char *sc_String;
int sc_Number;
int sc_Line;
boolean sc_End;
boolean sc_Crossed;
boolean sc_FileScripts = false;
char *sc_ScriptsDir = "";
// PRIVATE DATA DEFINITIONS ------------------------------------------------
static char ScriptName[16];
static char *ScriptBuffer;
static char *ScriptPtr;
static char *ScriptEndPtr;
static char StringBuffer[MAX_STRING_SIZE];
static boolean ScriptOpen = false;
static boolean ScriptFreeCLib; // true = de-allocate using free()
static int ScriptSize;
static boolean AlreadyGot = false;
// CODE --------------------------------------------------------------------
//==========================================================================
//
// SC_Open
//
//==========================================================================
void SC_Open(char *name)
{
char fileName[128];
if(sc_FileScripts == true)
{
sprintf(fileName, "%s%s.txt", sc_ScriptsDir, name);
SC_OpenFile(fileName);
}
else
{
SC_OpenLump(name);
}
}
//==========================================================================
//
// SC_OpenLump
//
// Loads a script (from the WAD files) and prepares it for parsing.
//
//==========================================================================
void SC_OpenLump(char *name)
{
OpenScript(name, LUMP_SCRIPT);
}
//==========================================================================
//
// SC_OpenFile
//
// Loads a script (from a file) and prepares it for parsing. Uses the
// zone memory allocator for memory allocation and de-allocation.
//
//==========================================================================
void SC_OpenFile(char *name)
{
OpenScript(name, FILE_ZONE_SCRIPT);
}
//==========================================================================
//
// SC_OpenFileCLib
//
// Loads a script (from a file) and prepares it for parsing. Uses C
// library function calls for memory allocation and de-allocation.
//
//==========================================================================
void SC_OpenFileCLib(char *name)
{
OpenScript(name, FILE_CLIB_SCRIPT);
}
//==========================================================================
//
// OpenScript
//
//==========================================================================
static void OpenScript(char *name, int type)
{
SC_Close();
if(type == LUMP_SCRIPT)
{ // Lump script
ScriptBuffer = (char *)W_CacheLumpName(name, PU_STATIC);
ScriptSize = W_LumpLength(W_GetNumForName(name));
strcpy(ScriptName, name);
ScriptFreeCLib = false; // De-allocate using Z_Free()
}
else if(type == FILE_ZONE_SCRIPT)
{ // File script - zone
ScriptSize = M_ReadFile(name, (byte **)&ScriptBuffer);
M_ExtractFileBase(name, ScriptName);
ScriptFreeCLib = false; // De-allocate using Z_Free()
}
else
{ // File script - clib
ScriptSize = M_ReadFileCLib(name, (byte **)&ScriptBuffer);
M_ExtractFileBase(name, ScriptName);
ScriptFreeCLib = true; // De-allocate using free()
}
ScriptPtr = ScriptBuffer;
ScriptEndPtr = ScriptPtr+ScriptSize;
sc_Line = 1;
sc_End = false;
ScriptOpen = true;
sc_String = StringBuffer;
AlreadyGot = false;
}
//==========================================================================
//
// SC_Close
//
//==========================================================================
void SC_Close(void)
{
if(ScriptOpen)
{
if(ScriptFreeCLib == true)
{
free(ScriptBuffer);
}
else
{
Z_Free(ScriptBuffer);
}
ScriptOpen = false;
}
}
//==========================================================================
//
// SC_GetString
//
//==========================================================================
boolean SC_GetString(void)
{
char *text;
boolean foundToken;
CheckOpen();
if(AlreadyGot)
{
AlreadyGot = false;
return true;
}
foundToken = false;
sc_Crossed = false;
if(ScriptPtr >= ScriptEndPtr)
{
sc_End = true;
return false;
}
while(foundToken == false)
{
while(*ScriptPtr <= 32)
{
if(ScriptPtr >= ScriptEndPtr)
{
sc_End = true;
return false;
}
if(*ScriptPtr++ == '\n')
{
sc_Line++;
sc_Crossed = true;
}
}
if(ScriptPtr >= ScriptEndPtr)
{
sc_End = true;
return false;
}
if(*ScriptPtr != ASCII_COMMENT)
{ // Found a token
foundToken = true;
}
else
{ // Skip comment
while(*ScriptPtr++ != '\n')
{
if(ScriptPtr >= ScriptEndPtr)
{
sc_End = true;
return false;
}
}
sc_Line++;
sc_Crossed = true;
}
}
text = sc_String;
if(*ScriptPtr == ASCII_QUOTE)
{ // Quoted string
ScriptPtr++;
while(*ScriptPtr != ASCII_QUOTE)
{
*text++ = *ScriptPtr++;
if(ScriptPtr == ScriptEndPtr
|| text == &sc_String[MAX_STRING_SIZE-1])
{
break;
}
}
ScriptPtr++;
}
else
{ // Normal string
while((*ScriptPtr > 32) && (*ScriptPtr != ASCII_COMMENT))
{
*text++ = *ScriptPtr++;
if(ScriptPtr == ScriptEndPtr
|| text == &sc_String[MAX_STRING_SIZE-1])
{
break;
}
}
}
*text = 0;
return true;
}
//==========================================================================
//
// SC_MustGetString
//
//==========================================================================
void SC_MustGetString(void)
{
if(SC_GetString() == false)
{
SC_ScriptError("Missing string.");
}
}
//==========================================================================
//
// SC_MustGetStringName
//
//==========================================================================
void SC_MustGetStringName(char *name)
{
SC_MustGetString();
if(SC_Compare(name) == false)
{
SC_ScriptError(NULL);
}
}
//==========================================================================
//
// SC_GetNumber
//
//==========================================================================
boolean SC_GetNumber(void)
{
char *stopper;
CheckOpen();
if(SC_GetString())
{
sc_Number = strtol(sc_String, &stopper, 0);
if(*stopper != 0)
{
I_Error("SC_GetNumber: Bad numeric constant \"%s\".\n"
"Script %s, Line %d", sc_String, ScriptName, sc_Line);
}
return true;
}
else
{
return false;
}
}
//==========================================================================
//
// SC_MustGetNumber
//
//==========================================================================
void SC_MustGetNumber(void)
{
if(SC_GetNumber() == false)
{
SC_ScriptError("Missing integer.");
}
}
//==========================================================================
//
// SC_UnGet
//
// Assumes there is a valid string in sc_String.
//
//==========================================================================
void SC_UnGet(void)
{
AlreadyGot = true;
}
//==========================================================================
//
// SC_Check
//
// Returns true if another token is on the current line.
//
//==========================================================================
/*
boolean SC_Check(void)
{
char *text;
CheckOpen();
text = ScriptPtr;
if(text >= ScriptEndPtr)
{
return false;
}
while(*text <= 32)
{
if(*text == '\n')
{
return false;
}
text++;
if(text == ScriptEndPtr)
{
return false;
}
}
if(*text == ASCII_COMMENT)
{
return false;
}
return true;
}
*/
//==========================================================================
//
// SC_MatchString
//
// Returns the index of the first match to sc_String from the passed
// array of strings, or -1 if not found.
//
//==========================================================================
int SC_MatchString(char **strings)
{
int i;
for(i = 0; *strings != NULL; i++)
{
if(SC_Compare(*strings++))
{
return i;
}
}
return -1;
}
//==========================================================================
//
// SC_MustMatchString
//
//==========================================================================
int SC_MustMatchString(char **strings)
{
int i;
i = SC_MatchString(strings);
if(i == -1)
{
SC_ScriptError(NULL);
}
return i;
}
//==========================================================================
//
// SC_Compare
//
//==========================================================================
boolean SC_Compare(char *text)
{
if(strcasecmp(text, sc_String) == 0)
{
return true;
}
return false;
}
//==========================================================================
//
// SC_ScriptError
//
//==========================================================================
void SC_ScriptError(char *message)
{
if(message == NULL)
{
message = "Bad syntax.";
}
I_Error("Script error, \"%s\" line %d: %s", ScriptName,
sc_Line, message);
}
//==========================================================================
//
// CheckOpen
//
//==========================================================================
static void CheckOpen(void)
{
if(ScriptOpen == false)
{
I_Error("SC_ call before SC_Open().");
}
}

506
Hexen Source/SN_SONIX.C Normal file
View File

@ -0,0 +1,506 @@
//**************************************************************************
//**
//** sn_sonix.c : Heretic 2 : Raven Software, Corp.
//**
//** $RCSfile: sn_sonix.c,v $
//** $Revision: 1.17 $
//** $Date: 95/10/05 18:25:44 $
//** $Author: paul $
//**
//**************************************************************************
// HEADER FILES ------------------------------------------------------------
#include <string.h>
#include "h2def.h"
#include "soundst.h"
// MACROS ------------------------------------------------------------------
#define SS_MAX_SCRIPTS 64
#define SS_TEMPBUFFER_SIZE 1024
#define SS_SEQUENCE_NAME_LENGTH 32
#define SS_SCRIPT_NAME "SNDSEQ"
#define SS_STRING_PLAY "play"
#define SS_STRING_PLAYUNTILDONE "playuntildone"
#define SS_STRING_PLAYTIME "playtime"
#define SS_STRING_PLAYREPEAT "playrepeat"
#define SS_STRING_DELAY "delay"
#define SS_STRING_DELAYRAND "delayrand"
#define SS_STRING_VOLUME "volume"
#define SS_STRING_END "end"
#define SS_STRING_STOPSOUND "stopsound"
// TYPES -------------------------------------------------------------------
typedef enum
{
SS_CMD_NONE,
SS_CMD_PLAY,
SS_CMD_WAITUNTILDONE, // used by PLAYUNTILDONE
SS_CMD_PLAYTIME,
SS_CMD_PLAYREPEAT,
SS_CMD_DELAY,
SS_CMD_DELAYRAND,
SS_CMD_VOLUME,
SS_CMD_STOPSOUND,
SS_CMD_END
} sscmds_t;
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
// PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
static void VerifySequencePtr(int *base, int *ptr);
static int GetSoundOffset(char *name);
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
extern sfxinfo_t S_sfx[];
// PUBLIC DATA DEFINITIONS -------------------------------------------------
// PRIVATE DATA DEFINITIONS ------------------------------------------------
static struct
{
char name[SS_SEQUENCE_NAME_LENGTH];
int scriptNum;
int stopSound;
} SequenceTranslate[SEQ_NUMSEQ] =
{
{ "Platform", 0, 0 },
{ "Platform", 0, 0 }, // a 'heavy' platform is just a platform
{ "PlatformMetal", 0, 0 },
{ "Platform", 0, 0 }, // same with a 'creak' platform
{ "Silence", 0, 0 },
{ "Lava", 0, 0 },
{ "Water", 0, 0 },
{ "Ice", 0, 0 },
{ "Earth", 0, 0 },
{ "PlatformMetal2", 0, 0 },
{ "DoorNormal", 0, 0 },
{ "DoorHeavy", 0, 0 },
{ "DoorMetal", 0, 0 },
{ "DoorCreak", 0, 0 },
{ "Silence", 0, 0 },
{ "Lava", 0, 0 },
{ "Water", 0, 0},
{ "Ice", 0, 0 },
{ "Earth", 0, 0},
{ "DoorMetal2", 0, 0 },
{ "Wind", 0, 0 }
};
static int *SequenceData[SS_MAX_SCRIPTS];
int ActiveSequences;
seqnode_t *SequenceListHead;
// CODE --------------------------------------------------------------------
//==========================================================================
//
// VerifySequencePtr
//
// Verifies the integrity of the temporary ptr, and ensures that the ptr
// isn't exceeding the size of the temporary buffer
//==========================================================================
static void VerifySequencePtr(int *base, int *ptr)
{
if(ptr-base > SS_TEMPBUFFER_SIZE)
{
I_Error("VerifySequencePtr: tempPtr >= %d\n", SS_TEMPBUFFER_SIZE);
}
}
//==========================================================================
//
// GetSoundOffset
//
//==========================================================================
static int GetSoundOffset(char *name)
{
int i;
for(i = 0; i < NUMSFX; i++)
{
if(!strcasecmp(name, S_sfx[i].tagName))
{
return i;
}
}
SC_ScriptError("GetSoundOffset: Unknown sound name\n");
return 0;
}
//==========================================================================
//
// SN_InitSequenceScript
//
//==========================================================================
void SN_InitSequenceScript(void)
{
int i, j;
int inSequence;
int *tempDataStart;
int *tempDataPtr;
inSequence = -1;
ActiveSequences = 0;
for(i = 0; i < SS_MAX_SCRIPTS; i++)
{
SequenceData[i] = NULL;
}
SC_Open(SS_SCRIPT_NAME);
while(SC_GetString())
{
if(*sc_String == ':')
{
if(inSequence != -1)
{
SC_ScriptError("SN_InitSequenceScript: Nested Script Error");
}
tempDataStart = (int *)Z_Malloc(SS_TEMPBUFFER_SIZE,
PU_STATIC, NULL);
memset(tempDataStart, 0, SS_TEMPBUFFER_SIZE);
tempDataPtr = tempDataStart;
for(i = 0; i < SS_MAX_SCRIPTS; i++)
{
if(SequenceData[i] == NULL)
{
break;
}
}
if(i == SS_MAX_SCRIPTS)
{
I_Error("Number of SS Scripts >= SS_MAX_SCRIPTS");
}
for(j = 0; j < SEQ_NUMSEQ; j++)
{
if(!strcasecmp(SequenceTranslate[j].name, sc_String+1))
{
SequenceTranslate[j].scriptNum = i;
inSequence = j;
break;
}
}
continue; // parse the next command
}
if(inSequence == -1)
{
continue;
}
if(SC_Compare(SS_STRING_PLAYUNTILDONE))
{
VerifySequencePtr(tempDataStart, tempDataPtr);
SC_MustGetString();
*tempDataPtr++ = SS_CMD_PLAY;
*tempDataPtr++ = GetSoundOffset(sc_String);
*tempDataPtr++ = SS_CMD_WAITUNTILDONE;
}
else if(SC_Compare(SS_STRING_PLAY))
{
VerifySequencePtr(tempDataStart, tempDataPtr);
SC_MustGetString();
*tempDataPtr++ = SS_CMD_PLAY;
*tempDataPtr++ = GetSoundOffset(sc_String);
}
else if(SC_Compare(SS_STRING_PLAYTIME))
{
VerifySequencePtr(tempDataStart, tempDataPtr);
SC_MustGetString();
*tempDataPtr++ = SS_CMD_PLAY;
*tempDataPtr++ = GetSoundOffset(sc_String);
SC_MustGetNumber();
*tempDataPtr++ = SS_CMD_DELAY;
*tempDataPtr++ = sc_Number;
}
else if(SC_Compare(SS_STRING_PLAYREPEAT))
{
VerifySequencePtr(tempDataStart, tempDataPtr);
SC_MustGetString();
*tempDataPtr++ = SS_CMD_PLAYREPEAT;
*tempDataPtr++ = GetSoundOffset(sc_String);
}
else if(SC_Compare(SS_STRING_DELAY))
{
VerifySequencePtr(tempDataStart, tempDataPtr);
*tempDataPtr++ = SS_CMD_DELAY;
SC_MustGetNumber();
*tempDataPtr++ = sc_Number;
}
else if(SC_Compare(SS_STRING_DELAYRAND))
{
VerifySequencePtr(tempDataStart, tempDataPtr);
*tempDataPtr++ = SS_CMD_DELAYRAND;
SC_MustGetNumber();
*tempDataPtr++ = sc_Number;
SC_MustGetNumber();
*tempDataPtr++ = sc_Number;
}
else if(SC_Compare(SS_STRING_VOLUME))
{
VerifySequencePtr(tempDataStart, tempDataPtr);
*tempDataPtr++ = SS_CMD_VOLUME;
SC_MustGetNumber();
*tempDataPtr++ = sc_Number;
}
else if(SC_Compare(SS_STRING_END))
{
int dataSize;
*tempDataPtr++ = SS_CMD_END;
dataSize = (tempDataPtr-tempDataStart)*sizeof(int);
SequenceData[i] = (int *)Z_Malloc(dataSize, PU_STATIC,
NULL);
memcpy(SequenceData[i], tempDataStart, dataSize);
Z_Free(tempDataStart);
inSequence = -1;
}
else if(SC_Compare(SS_STRING_STOPSOUND))
{
SC_MustGetString();
SequenceTranslate[inSequence].stopSound =
GetSoundOffset(sc_String);
*tempDataPtr++ = SS_CMD_STOPSOUND;
}
else
{
SC_ScriptError("SN_InitSequenceScript: Unknown commmand.\n");
}
}
}
//==========================================================================
//
// SN_StartSequence
//
//==========================================================================
void SN_StartSequence(mobj_t *mobj, int sequence)
{
seqnode_t *node;
SN_StopSequence(mobj); // Stop any previous sequence
node = (seqnode_t *)Z_Malloc(sizeof(seqnode_t), PU_STATIC, NULL);
node->sequencePtr = SequenceData[SequenceTranslate[sequence].scriptNum];
node->sequence = sequence;
node->mobj = mobj;
node->delayTics = 0;
node->stopSound = SequenceTranslate[sequence].stopSound;
node->volume = 127; // Start at max volume
if(!SequenceListHead)
{
SequenceListHead = node;
node->next = node->prev = NULL;
}
else
{
SequenceListHead->prev = node;
node->next = SequenceListHead;
node->prev = NULL;
SequenceListHead = node;
}
ActiveSequences++;
return;
}
//==========================================================================
//
// SN_StartSequenceName
//
//==========================================================================
void SN_StartSequenceName(mobj_t *mobj, char *name)
{
int i;
for(i = 0; i < SEQ_NUMSEQ; i++)
{
if(!strcmp(name, SequenceTranslate[i].name))
{
SN_StartSequence(mobj, i);
return;
}
}
}
//==========================================================================
//
// SN_StopSequence
//
//==========================================================================
void SN_StopSequence(mobj_t *mobj)
{
seqnode_t *node;
for(node = SequenceListHead; node; node = node->next)
{
if(node->mobj == mobj)
{
S_StopSound(mobj);
if(node->stopSound)
{
S_StartSoundAtVolume(mobj, node->stopSound, node->volume);
}
if(SequenceListHead == node)
{
SequenceListHead = node->next;
}
if(node->prev)
{
node->prev->next = node->next;
}
if(node->next)
{
node->next->prev = node->prev;
}
Z_Free(node);
ActiveSequences--;
}
}
}
//==========================================================================
//
// SN_UpdateActiveSequences
//
//==========================================================================
void SN_UpdateActiveSequences(void)
{
seqnode_t *node;
boolean sndPlaying;
if(!ActiveSequences || paused)
{ // No sequences currently playing/game is paused
return;
}
for(node = SequenceListHead; node; node = node->next)
{
if(node->delayTics)
{
node->delayTics--;
continue;
}
sndPlaying = S_GetSoundPlayingInfo(node->mobj, node->currentSoundID);
switch(*node->sequencePtr)
{
case SS_CMD_PLAY:
if(!sndPlaying)
{
node->currentSoundID = *(node->sequencePtr+1);
S_StartSoundAtVolume(node->mobj, node->currentSoundID,
node->volume);
}
node->sequencePtr += 2;
break;
case SS_CMD_WAITUNTILDONE:
if(!sndPlaying)
{
node->sequencePtr++;
node->currentSoundID = 0;
}
break;
case SS_CMD_PLAYREPEAT:
if(!sndPlaying)
{
node->currentSoundID = *(node->sequencePtr+1);
S_StartSoundAtVolume(node->mobj, node->currentSoundID,
node->volume);
}
break;
case SS_CMD_DELAY:
node->delayTics = *(node->sequencePtr+1);
node->sequencePtr += 2;
node->currentSoundID = 0;
break;
case SS_CMD_DELAYRAND:
node->delayTics = *(node->sequencePtr+1)+
M_Random()%(*(node->sequencePtr+2)-*(node->sequencePtr+1));
node->sequencePtr += 2;
node->currentSoundID = 0;
break;
case SS_CMD_VOLUME:
node->volume = (127*(*(node->sequencePtr+1)))/100;
node->sequencePtr += 2;
break;
case SS_CMD_STOPSOUND:
// Wait until something else stops the sequence
break;
case SS_CMD_END:
SN_StopSequence(node->mobj);
break;
default:
break;
}
}
}
//==========================================================================
//
// SN_StopAllSequences
//
//==========================================================================
void SN_StopAllSequences(void)
{
seqnode_t *node;
for(node = SequenceListHead; node; node = node->next)
{
node->stopSound = 0; // don't play any stop sounds
SN_StopSequence(node->mobj);
}
}
//==========================================================================
//
// SN_GetSequenceOffset
//
//==========================================================================
int SN_GetSequenceOffset(int sequence, int *sequencePtr)
{
return (sequencePtr-SequenceData[SequenceTranslate[sequence].scriptNum]);
}
//==========================================================================
//
// SN_ChangeNodeData
//
// nodeNum zero is the first node
//==========================================================================
void SN_ChangeNodeData(int nodeNum, int seqOffset, int delayTics, int volume,
int currentSoundID)
{
int i;
seqnode_t *node;
i = 0;
node = SequenceListHead;
while(node && i < nodeNum)
{
node = node->next;
i++;
}
if(!node)
{ // reach the end of the list before finding the nodeNum-th node
return;
}
node->delayTics = delayTics;
node->volume = volume;
node->sequencePtr += seqOffset;
node->currentSoundID = currentSoundID;
}

306
Hexen Source/SOUNDS.C Normal file
View File

@ -0,0 +1,306 @@
//**************************************************************************
//**
//** sounds.c : Heretic 2 : Raven Software, Corp.
//**
//** $RCSfile: sounds.c,v $
//** $Revision: 1.83 $
//** $Date: 96/01/06 18:37:44 $
//** $Author: bgokey $
//**
//**************************************************************************
#include "h2def.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_TITL", 0 },
{ "MUS_INTR", 0 },
{ "MUS_CPTD", 0 }
};
*/
// Sound info
sfxinfo_t S_sfx[] =
{
// tagname, lumpname, priority, usefulness, snd_ptr, lumpnum, numchannels,
// pitchshift
{ "", "", 0, -1, NULL, 0, 0, 0 },
{ "PlayerFighterNormalDeath", "", 256, -1, NULL, 0, 2, 1 },
{ "PlayerFighterCrazyDeath", "", 256, -1, NULL, 0, 2, 1 },
{ "PlayerFighterExtreme1Death", "", 256, -1, NULL, 0, 2, 1 },
{ "PlayerFighterExtreme2Death", "", 256, -1, NULL, 0, 2, 1 },
{ "PlayerFighterExtreme3Death", "", 256, -1, NULL, 0, 2, 1 },
{ "PlayerFighterBurnDeath", "", 256, -1, NULL, 0, 2, 1 },
{ "PlayerClericNormalDeath", "", 256, -1, NULL, 0, 2, 1 },
{ "PlayerClericCrazyDeath", "", 256, -1, NULL, 0, 2, 1 },
{ "PlayerClericExtreme1Death", "", 256, -1, NULL, 0, 2, 1 },
{ "PlayerClericExtreme2Death", "", 256, -1, NULL, 0, 2, 1 },
{ "PlayerClericExtreme3Death", "", 256, -1, NULL, 0, 2, 1 },
{ "PlayerClericBurnDeath", "", 256, -1, NULL, 0, 2, 1 },
{ "PlayerMageNormalDeath", "", 256, -1, NULL, 0, 2, 0 },
{ "PlayerMageCrazyDeath", "", 256, -1, NULL, 0, 2, 0 },
{ "PlayerMageExtreme1Death", "", 256, -1, NULL, 0, 2, 0 },
{ "PlayerMageExtreme2Death", "", 256, -1, NULL, 0, 2, 0 },
{ "PlayerMageExtreme3Death", "", 256, -1, NULL, 0, 2, 0 },
{ "PlayerMageBurnDeath", "", 256, -1, NULL, 0, 2, 0 },
{ "PlayerFighterPain", "", 256, -1, NULL, 0, 2, 1 },
{ "PlayerClericPain", "", 256, -1, NULL, 0, 2, 1 },
{ "PlayerMagePain", "", 256, -1, NULL, 0, 2, 0 },
{ "PlayerFighterGrunt", "", 256, -1, NULL, 0, 2, 1 },
{ "PlayerClericGrunt", "", 256, -1, NULL, 0, 2, 1 },
{ "PlayerMageGrunt", "", 256, -1, NULL, 0, 2, 0 },
{ "PlayerLand", "", 32, -1, NULL, 0, 2, 1 },
{ "PlayerPoisonCough", "", 256, -1, NULL, 0, 2, 1 },
{ "PlayerFighterFallingScream", "", 256, -1, NULL, 0, 2, 1 },
{ "PlayerClericFallingScream", "", 256, -1, NULL, 0, 2, 1 },
{ "PlayerMageFallingScream", "", 256, -1, NULL, 0, 2, 0 },
{ "PlayerFallingSplat", "", 256, -1, NULL, 0, 2, 1 },
{ "PlayerFighterFailedUse", "", 256, -1, NULL, 0, 1, 1 },
{ "PlayerClericFailedUse", "", 256, -1, NULL, 0, 1, 1 },
{ "PlayerMageFailedUse", "", 256, -1, NULL, 0, 1, 0 },
{ "PlatformStart", "", 36, -1, NULL, 0, 2, 1 },
{ "PlatformStartMetal", "", 36, -1, NULL, 0, 2, 1 },
{ "PlatformStop", "", 40, -1, NULL, 0, 2, 1 },
{ "StoneMove", "", 32, -1, NULL, 0, 2, 1 },
{ "MetalMove", "", 32, -1, NULL, 0, 2, 1 },
{ "DoorOpen", "", 36, -1, NULL, 0, 2, 1 },
{ "DoorLocked", "", 36, -1, NULL, 0, 2, 1 },
{ "DoorOpenMetal", "", 36, -1, NULL, 0, 2, 1 },
{ "DoorCloseMetal", "", 36, -1, NULL, 0, 2, 1 },
{ "DoorCloseLight", "", 36, -1, NULL, 0, 2, 1 },
{ "DoorCloseHeavy", "", 36, -1, NULL, 0, 2, 1 },
{ "DoorCreak", "", 36, -1, NULL, 0, 2, 1 },
{ "PickupWeapon", "", 36, -1, NULL, 0, 2, 0 },
{ "PickupArtifact", "", 36, -1, NULL, 0, 2, 1 },
{ "PickupKey", "", 36, -1, NULL, 0, 2, 1 },
{ "PickupItem", "", 36, -1, NULL, 0, 2, 1 },
{ "PickupPiece", "", 36, -1, NULL, 0, 2, 0 },
{ "WeaponBuild", "", 36, -1, NULL, 0, 2, 0 },
{ "UseArtifact", "", 36, -1, NULL, 0, 2, 1 },
{ "BlastRadius", "", 36, -1, NULL, 0, 2, 1 },
{ "Teleport", "", 256, -1, NULL, 0, 2, 1 },
{ "ThunderCrash", "", 30, -1, NULL, 0, 2, 1 },
{ "FighterPunchMiss", "", 80, -1, NULL, 0, 2, 1 },
{ "FighterPunchHitThing", "", 80, -1, NULL, 0, 2, 1 },
{ "FighterPunchHitWall", "", 80, -1, NULL, 0, 2, 1 },
{ "FighterGrunt", "", 80, -1, NULL, 0, 2, 1 },
{ "FighterAxeHitThing", "", 80, -1, NULL, 0, 2, 1 },
{ "FighterHammerMiss", "", 80, -1, NULL, 0, 2, 1 },
{ "FighterHammerHitThing", "", 80, -1, NULL, 0, 2, 1 },
{ "FighterHammerHitWall", "", 80, -1, NULL, 0, 2, 1 },
{ "FighterHammerContinuous", "", 32, -1, NULL, 0, 2, 1 },
{ "FighterHammerExplode", "", 80, -1, NULL, 0, 2, 1 },
{ "FighterSwordFire", "", 80, -1, NULL, 0, 2, 1 },
{ "FighterSwordExplode", "", 80, -1, NULL, 0, 2, 1 },
{ "ClericCStaffFire", "", 80, -1, NULL, 0, 2, 1 },
{ "ClericCStaffExplode", "", 40, -1, NULL, 0, 2, 1 },
{ "ClericCStaffHitThing", "", 80, -1, NULL, 0, 2, 1 },
{ "ClericFlameFire", "", 80, -1, NULL, 0, 2, 1 },
{ "ClericFlameExplode", "", 80, -1, NULL, 0, 2, 1 },
{ "ClericFlameCircle", "", 80, -1, NULL, 0, 2, 1 },
{ "MageWandFire", "", 80, -1, NULL, 0, 2, 1 },
{ "MageLightningFire", "", 80, -1, NULL, 0, 2, 1 },
{ "MageLightningZap", "", 32, -1, NULL, 0, 2, 1 },
{ "MageLightningContinuous", "", 32, -1, NULL, 0, 2, 1 },
{ "MageLightningReady", "", 30, -1, NULL, 0, 2, 1 },
{ "MageShardsFire","", 80, -1, NULL, 0, 2, 1 },
{ "MageShardsExplode","", 36, -1, NULL, 0, 2, 1 },
{ "MageStaffFire","", 80, -1, NULL, 0, 2, 1 },
{ "MageStaffExplode","", 40, -1, NULL, 0, 2, 1 },
{ "Switch1", "", 32, -1, NULL, 0, 2, 1 },
{ "Switch2", "", 32, -1, NULL, 0, 2, 1 },
{ "SerpentSight", "", 32, -1, NULL, 0, 2, 1 },
{ "SerpentActive", "", 32, -1, NULL, 0, 2, 1 },
{ "SerpentPain", "", 32, -1, NULL, 0, 2, 1 },
{ "SerpentAttack", "", 32, -1, NULL, 0, 2, 1 },
{ "SerpentMeleeHit", "", 32, -1, NULL, 0, 2, 1 },
{ "SerpentDeath", "", 40, -1, NULL, 0, 2, 1 },
{ "SerpentBirth", "", 32, -1, NULL, 0, 2, 1 },
{ "SerpentFXContinuous", "", 32, -1, NULL, 0, 2, 1 },
{ "SerpentFXHit", "", 32, -1, NULL, 0, 2, 1 },
{ "PotteryExplode", "", 32, -1, NULL, 0, 2, 1 },
{ "Drip", "", 32, -1, NULL, 0, 2, 1 },
{ "CentaurSight", "", 32, -1, NULL, 0, 2, 1 },
{ "CentaurActive", "", 32, -1, NULL, 0, 2, 1 },
{ "CentaurPain", "", 32, -1, NULL, 0, 2, 1 },
{ "CentaurAttack", "", 32, -1, NULL, 0, 2, 1 },
{ "CentaurDeath", "", 40, -1, NULL, 0, 2, 1 },
{ "CentaurLeaderAttack", "", 32, -1, NULL, 0, 2, 1 },
{ "CentaurMissileExplode", "", 32, -1, NULL, 0, 2, 1 },
{ "Wind", "", 1, -1, NULL, 0, 2, 1 },
{ "BishopSight", "", 32, -1, NULL, 0, 2, 1 },
{ "BishopActive", "", 32, -1, NULL, 0, 2, 1 },
{ "BishopPain", "", 32, -1, NULL, 0, 2, 1 },
{ "BishopAttack", "", 32, -1, NULL, 0, 2, 1 },
{ "BishopDeath", "", 40, -1, NULL, 0, 2, 1 },
{ "BishopMissileExplode", "", 32, -1, NULL, 0, 2, 1 },
{ "BishopBlur", "", 32, -1, NULL, 0, 2, 1 },
{ "DemonSight", "", 32, -1, NULL, 0, 2, 1 },
{ "DemonActive", "", 32, -1, NULL, 0, 2, 1 },
{ "DemonPain", "", 32, -1, NULL, 0, 2, 1 },
{ "DemonAttack", "", 32, -1, NULL, 0, 2, 1 },
{ "DemonMissileFire", "", 32, -1, NULL, 0, 2, 1 },
{ "DemonMissileExplode", "", 32, -1, NULL, 0, 2, 1 },
{ "DemonDeath", "", 40, -1, NULL, 0, 2, 1 },
{ "WraithSight", "", 32, -1, NULL, 0, 2, 1 },
{ "WraithActive", "", 32, -1, NULL, 0, 2, 1 },
{ "WraithPain", "", 32, -1, NULL, 0, 2, 1 },
{ "WraithAttack", "", 32, -1, NULL, 0, 2, 1 },
{ "WraithMissileFire", "", 32, -1, NULL, 0, 2, 1 },
{ "WraithMissileExplode", "", 32, -1, NULL, 0, 2, 1 },
{ "WraithDeath", "", 40, -1, NULL, 0, 2, 1 },
{ "PigActive1", "", 32, -1, NULL, 0, 2, 1 },
{ "PigActive2", "", 32, -1, NULL, 0, 2, 1 },
{ "PigPain", "", 32, -1, NULL, 0, 2, 1 },
{ "PigAttack", "", 32, -1, NULL, 0, 2, 1 },
{ "PigDeath", "", 40, -1, NULL, 0, 2, 1 },
{ "MaulatorSight", "", 32, -1, NULL, 0, 2, 1 },
{ "MaulatorActive", "", 32, -1, NULL, 0, 2, 1 },
{ "MaulatorPain", "", 32, -1, NULL, 0, 2, 1 },
{ "MaulatorHamSwing", "", 32, -1, NULL, 0, 2, 1 },
{ "MaulatorHamHit", "", 32, -1, NULL, 0, 2, 1 },
{ "MaulatorMissileHit", "", 32, -1, NULL, 0, 2, 1 },
{ "MaulatorDeath", "", 40, -1, NULL, 0, 2, 1 },
{ "FreezeDeath", "", 40, -1, NULL, 0, 2, 1 },
{ "FreezeShatter", "", 40, -1, NULL, 0, 2, 1 },
{ "EttinSight", "", 32, -1, NULL, 0, 2, 1 },
{ "EttinActive", "", 32, -1, NULL, 0, 2, 1 },
{ "EttinPain", "", 32, -1, NULL, 0, 2, 1 },
{ "EttinAttack", "", 32, -1, NULL, 0, 2, 1 },
{ "EttinDeath", "", 40, -1, NULL, 0, 2, 1 },
{ "FireDemonSpawn", "", 32, -1, NULL, 0, 2, 1 },
{ "FireDemonActive", "", 32, -1, NULL, 0, 2, 1 },
{ "FireDemonPain", "", 32, -1, NULL, 0, 2, 1 },
{ "FireDemonAttack", "", 32, -1, NULL, 0, 2, 1 },
{ "FireDemonMissileHit", "", 32, -1, NULL, 0, 2, 1 },
{ "FireDemonDeath", "", 40, -1, NULL, 0, 2, 1 },
{ "IceGuySight", "", 32, -1, NULL, 0, 2, 1 },
{ "IceGuyActive", "", 32, -1, NULL, 0, 2, 1 },
{ "IceGuyAttack", "", 32, -1, NULL, 0, 2, 1 },
{ "IceGuyMissileExplode", "", 32, -1, NULL, 0, 2, 1 },
{ "SorcererSight", "", 256, -1, NULL, 0, 2, 1 },
{ "SorcererActive", "", 256, -1, NULL, 0, 2, 1 },
{ "SorcererPain", "", 256, -1, NULL, 0, 2, 1 },
{ "SorcererSpellCast", "", 256, -1, NULL, 0, 2, 1 },
{ "SorcererBallWoosh", "", 256, -1, NULL, 0, 4, 1 },
{ "SorcererDeathScream", "", 256, -1, NULL, 0, 2, 1 },
{ "SorcererBishopSpawn", "", 80, -1, NULL, 0, 2, 1 },
{ "SorcererBallPop", "", 80, -1, NULL, 0, 2, 1 },
{ "SorcererBallBounce", "", 80, -1, NULL, 0, 3, 1 },
{ "SorcererBallExplode", "", 80, -1, NULL, 0, 3, 1 },
{ "SorcererBigBallExplode", "", 80, -1, NULL, 0, 3, 1 },
{ "SorcererHeadScream", "", 256, -1, NULL, 0, 2, 1 },
{ "DragonSight", "", 64, -1, NULL, 0, 2, 1 },
{ "DragonActive", "", 64, -1, NULL, 0, 2, 1 },
{ "DragonWingflap", "", 64, -1, NULL, 0, 2, 1 },
{ "DragonAttack", "", 64, -1, NULL, 0, 2, 1 },
{ "DragonPain", "", 64, -1, NULL, 0, 2, 1 },
{ "DragonDeath", "", 64, -1, NULL, 0, 2, 1 },
{ "DragonFireballExplode", "", 32, -1, NULL, 0, 2, 1 },
{ "KoraxSight", "", 256, -1, NULL, 0, 2, 1 },
{ "KoraxActive", "", 256, -1, NULL, 0, 2, 1 },
{ "KoraxPain", "", 256, -1, NULL, 0, 2, 1 },
{ "KoraxAttack", "", 256, -1, NULL, 0, 2, 1 },
{ "KoraxCommand", "", 256, -1, NULL, 0, 2, 1 },
{ "KoraxDeath", "", 256, -1, NULL, 0, 2, 1 },
{ "KoraxStep", "", 128, -1, NULL, 0, 2, 1 },
{ "ThrustSpikeRaise", "", 32, -1, NULL, 0, 2, 1 },
{ "ThrustSpikeLower", "", 32, -1, NULL, 0, 2, 1 },
{ "GlassShatter", "", 32, -1, NULL, 0, 2, 1 },
{ "FlechetteBounce", "", 32, -1, NULL, 0, 2, 1 },
{ "FlechetteExplode", "", 32, -1, NULL, 0, 2, 1 },
{ "LavaMove", "", 36, -1, NULL, 0, 2, 1 },
{ "WaterMove", "", 36, -1, NULL, 0, 2, 1 },
{ "IceStartMove", "", 36, -1, NULL, 0, 2, 1 },
{ "EarthStartMove", "", 36, -1, NULL, 0, 2, 1 },
{ "WaterSplash", "", 32, -1, NULL, 0, 2, 1 },
{ "LavaSizzle", "", 32, -1, NULL, 0, 2, 1 },
{ "SludgeGloop", "", 32, -1, NULL, 0, 2, 1 },
{ "HolySymbolFire", "", 64, -1, NULL, 0, 2, 1 },
{ "SpiritActive", "", 32, -1, NULL, 0, 2, 1 },
{ "SpiritAttack", "", 32, -1, NULL, 0, 2, 1 },
{ "SpiritDie", "", 32, -1, NULL, 0, 2, 1 },
{ "ValveTurn", "", 36, -1, NULL, 0, 2, 1 },
{ "RopePull", "", 36, -1, NULL, 0, 2, 1 },
{ "FlyBuzz", "", 20, -1, NULL, 0, 2, 1 },
{ "Ignite", "", 32, -1, NULL, 0, 2, 1 },
{ "PuzzleSuccess", "", 256, -1, NULL, 0, 2, 1 },
{ "PuzzleFailFighter", "", 256, -1, NULL, 0, 2, 1 },
{ "PuzzleFailCleric", "", 256, -1, NULL, 0, 2, 1 },
{ "PuzzleFailMage", "", 256, -1, NULL, 0, 2, 1 },
{ "Earthquake", "", 32, -1, NULL, 0, 2, 1 },
{ "BellRing", "", 32, -1, NULL, 0, 2, 0 },
{ "TreeBreak", "", 32, -1, NULL, 0, 2, 1 },
{ "TreeExplode", "", 32, -1, NULL, 0, 2, 1 },
{ "SuitofArmorBreak", "", 32, -1, NULL, 0, 2, 1 },
{ "PoisonShroomPain", "", 20, -1, NULL, 0, 2, 1 },
{ "PoisonShroomDeath", "", 32, -1, NULL, 0, 2, 1 },
{ "Ambient1", "", 1, -1, NULL, 0, 1, 1 },
{ "Ambient2", "", 1, -1, NULL, 0, 1, 1 },
{ "Ambient3", "", 1, -1, NULL, 0, 1, 1 },
{ "Ambient4", "", 1, -1, NULL, 0, 1, 1 },
{ "Ambient5", "", 1, -1, NULL, 0, 1, 1 },
{ "Ambient6", "", 1, -1, NULL, 0, 1, 1 },
{ "Ambient7", "", 1, -1, NULL, 0, 1, 1 },
{ "Ambient8", "", 1, -1, NULL, 0, 1, 1 },
{ "Ambient9", "", 1, -1, NULL, 0, 1, 1 },
{ "Ambient10", "", 1, -1, NULL, 0, 1, 1 },
{ "Ambient11", "", 1, -1, NULL, 0, 1, 1 },
{ "Ambient12", "", 1, -1, NULL, 0, 1, 1 },
{ "Ambient13", "", 1, -1, NULL, 0, 1, 1 },
{ "Ambient14", "", 1, -1, NULL, 0, 1, 1 },
{ "Ambient15", "", 1, -1, NULL, 0, 1, 1 },
{ "StartupTick", "", 32, -1, NULL, 0, 2, 1 },
{ "SwitchOtherLevel", "", 32, -1, NULL, 0, 2, 1 },
{ "Respawn", "", 32, -1, NULL, 0, 2, 1 },
{ "KoraxVoiceGreetings", "", 512, -1, NULL, 0, 2, 1 },
{ "KoraxVoiceReady", "", 512, -1, NULL, 0, 2, 1 },
{ "KoraxVoiceBlood", "", 512, -1, NULL, 0, 2, 1 },
{ "KoraxVoiceGame", "", 512, -1, NULL, 0, 2, 1 },
{ "KoraxVoiceBoard", "", 512, -1, NULL, 0, 2, 1 },
{ "KoraxVoiceWorship", "", 512, -1, NULL, 0, 2, 1 },
{ "KoraxVoiceMaybe", "", 512, -1, NULL, 0, 2, 1 },
{ "KoraxVoiceStrong", "", 512, -1, NULL, 0, 2, 1 },
{ "KoraxVoiceFace", "", 512, -1, NULL, 0, 2, 1 },
{ "BatScream", "", 32, -1, NULL, 0, 2, 1 },
{ "Chat", "", 512, -1, NULL, 0, 2, 1 },
{ "MenuMove", "", 32, -1, NULL, 0, 2, 1 },
{ "ClockTick", "", 32, -1, NULL, 0, 2, 1 },
{ "Fireball", "", 32, -1, NULL, 0, 2, 1 },
{ "PuppyBeat", "", 30, -1, NULL, 0, 2, 1 },
{ "MysticIncant", "", 32, -1, NULL, 0, 4, 1 }
};

311
Hexen Source/SOUNDS.H Normal file
View File

@ -0,0 +1,311 @@
//**************************************************************************
//**
//** sounds.h : Heretic 2 : Raven Software, Corp.
//**
//** $RCSfile: sounds.h,v $
//** $Revision: 1.74 $
//** $Date: 95/10/10 21:51:20 $
//** $Author: paul $
//**
//**************************************************************************
#ifndef __SOUNDSH__
#define __SOUNDSH__
#include "soundst.h"
#define MAX_SND_DIST 2025
#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_titl,
mus_intr,
mus_cptd,
NUMMUSIC
} musicenum_t;
// Sound identifiers
typedef enum
{
SFX_NONE,
SFX_PLAYER_FIGHTER_NORMAL_DEATH, // class specific death screams
SFX_PLAYER_FIGHTER_CRAZY_DEATH,
SFX_PLAYER_FIGHTER_EXTREME1_DEATH,
SFX_PLAYER_FIGHTER_EXTREME2_DEATH,
SFX_PLAYER_FIGHTER_EXTREME3_DEATH,
SFX_PLAYER_FIGHTER_BURN_DEATH,
SFX_PLAYER_CLERIC_NORMAL_DEATH,
SFX_PLAYER_CLERIC_CRAZY_DEATH,
SFX_PLAYER_CLERIC_EXTREME1_DEATH,
SFX_PLAYER_CLERIC_EXTREME2_DEATH,
SFX_PLAYER_CLERIC_EXTREME3_DEATH,
SFX_PLAYER_CLERIC_BURN_DEATH,
SFX_PLAYER_MAGE_NORMAL_DEATH,
SFX_PLAYER_MAGE_CRAZY_DEATH,
SFX_PLAYER_MAGE_EXTREME1_DEATH,
SFX_PLAYER_MAGE_EXTREME2_DEATH,
SFX_PLAYER_MAGE_EXTREME3_DEATH,
SFX_PLAYER_MAGE_BURN_DEATH,
SFX_PLAYER_FIGHTER_PAIN,
SFX_PLAYER_CLERIC_PAIN,
SFX_PLAYER_MAGE_PAIN,
SFX_PLAYER_FIGHTER_GRUNT,
SFX_PLAYER_CLERIC_GRUNT,
SFX_PLAYER_MAGE_GRUNT,
SFX_PLAYER_LAND,
SFX_PLAYER_POISONCOUGH,
SFX_PLAYER_FIGHTER_FALLING_SCREAM, // class specific falling screams
SFX_PLAYER_CLERIC_FALLING_SCREAM,
SFX_PLAYER_MAGE_FALLING_SCREAM,
SFX_PLAYER_FALLING_SPLAT,
SFX_PLAYER_FIGHTER_FAILED_USE,
SFX_PLAYER_CLERIC_FAILED_USE,
SFX_PLAYER_MAGE_FAILED_USE,
SFX_PLATFORM_START,
SFX_PLATFORM_STARTMETAL,
SFX_PLATFORM_STOP,
SFX_STONE_MOVE,
SFX_METAL_MOVE,
SFX_DOOR_OPEN,
SFX_DOOR_LOCKED,
SFX_DOOR_METAL_OPEN,
SFX_DOOR_METAL_CLOSE,
SFX_DOOR_LIGHT_CLOSE,
SFX_DOOR_HEAVY_CLOSE,
SFX_DOOR_CREAK,
SFX_PICKUP_WEAPON,
SFX_PICKUP_ARTIFACT,
SFX_PICKUP_KEY,
SFX_PICKUP_ITEM,
SFX_PICKUP_PIECE,
SFX_WEAPON_BUILD,
SFX_ARTIFACT_USE,
SFX_ARTIFACT_BLAST,
SFX_TELEPORT,
SFX_THUNDER_CRASH,
SFX_FIGHTER_PUNCH_MISS,
SFX_FIGHTER_PUNCH_HITTHING,
SFX_FIGHTER_PUNCH_HITWALL,
SFX_FIGHTER_GRUNT,
SFX_FIGHTER_AXE_HITTHING,
SFX_FIGHTER_HAMMER_MISS,
SFX_FIGHTER_HAMMER_HITTHING,
SFX_FIGHTER_HAMMER_HITWALL,
SFX_FIGHTER_HAMMER_CONTINUOUS,
SFX_FIGHTER_HAMMER_EXPLODE,
SFX_FIGHTER_SWORD_FIRE,
SFX_FIGHTER_SWORD_EXPLODE,
SFX_CLERIC_CSTAFF_FIRE,
SFX_CLERIC_CSTAFF_EXPLODE,
SFX_CLERIC_CSTAFF_HITTHING,
SFX_CLERIC_FLAME_FIRE,
SFX_CLERIC_FLAME_EXPLODE,
SFX_CLERIC_FLAME_CIRCLE,
SFX_MAGE_WAND_FIRE,
SFX_MAGE_LIGHTNING_FIRE,
SFX_MAGE_LIGHTNING_ZAP,
SFX_MAGE_LIGHTNING_CONTINUOUS,
SFX_MAGE_LIGHTNING_READY,
SFX_MAGE_SHARDS_FIRE,
SFX_MAGE_SHARDS_EXPLODE,
SFX_MAGE_STAFF_FIRE,
SFX_MAGE_STAFF_EXPLODE,
SFX_SWITCH1,
SFX_SWITCH2,
SFX_SERPENT_SIGHT,
SFX_SERPENT_ACTIVE,
SFX_SERPENT_PAIN,
SFX_SERPENT_ATTACK,
SFX_SERPENT_MELEEHIT,
SFX_SERPENT_DEATH,
SFX_SERPENT_BIRTH,
SFX_SERPENTFX_CONTINUOUS,
SFX_SERPENTFX_HIT,
SFX_POTTERY_EXPLODE,
SFX_DRIP,
SFX_CENTAUR_SIGHT,
SFX_CENTAUR_ACTIVE,
SFX_CENTAUR_PAIN,
SFX_CENTAUR_ATTACK,
SFX_CENTAUR_DEATH,
SFX_CENTAURLEADER_ATTACK,
SFX_CENTAUR_MISSILE_EXPLODE,
SFX_WIND,
SFX_BISHOP_SIGHT,
SFX_BISHOP_ACTIVE,
SFX_BISHOP_PAIN,
SFX_BISHOP_ATTACK,
SFX_BISHOP_DEATH,
SFX_BISHOP_MISSILE_EXPLODE,
SFX_BISHOP_BLUR,
SFX_DEMON_SIGHT,
SFX_DEMON_ACTIVE,
SFX_DEMON_PAIN,
SFX_DEMON_ATTACK,
SFX_DEMON_MISSILE_FIRE,
SFX_DEMON_MISSILE_EXPLODE,
SFX_DEMON_DEATH,
SFX_WRAITH_SIGHT,
SFX_WRAITH_ACTIVE,
SFX_WRAITH_PAIN,
SFX_WRAITH_ATTACK,
SFX_WRAITH_MISSILE_FIRE,
SFX_WRAITH_MISSILE_EXPLODE,
SFX_WRAITH_DEATH,
SFX_PIG_ACTIVE1,
SFX_PIG_ACTIVE2,
SFX_PIG_PAIN,
SFX_PIG_ATTACK,
SFX_PIG_DEATH,
SFX_MAULATOR_SIGHT,
SFX_MAULATOR_ACTIVE,
SFX_MAULATOR_PAIN,
SFX_MAULATOR_HAMMER_SWING,
SFX_MAULATOR_HAMMER_HIT,
SFX_MAULATOR_MISSILE_HIT,
SFX_MAULATOR_DEATH,
SFX_FREEZE_DEATH,
SFX_FREEZE_SHATTER,
SFX_ETTIN_SIGHT,
SFX_ETTIN_ACTIVE,
SFX_ETTIN_PAIN,
SFX_ETTIN_ATTACK,
SFX_ETTIN_DEATH,
SFX_FIRED_SPAWN,
SFX_FIRED_ACTIVE,
SFX_FIRED_PAIN,
SFX_FIRED_ATTACK,
SFX_FIRED_MISSILE_HIT,
SFX_FIRED_DEATH,
SFX_ICEGUY_SIGHT,
SFX_ICEGUY_ACTIVE,
SFX_ICEGUY_ATTACK,
SFX_ICEGUY_FX_EXPLODE,
SFX_SORCERER_SIGHT,
SFX_SORCERER_ACTIVE,
SFX_SORCERER_PAIN,
SFX_SORCERER_SPELLCAST,
SFX_SORCERER_BALLWOOSH,
SFX_SORCERER_DEATHSCREAM,
SFX_SORCERER_BISHOPSPAWN,
SFX_SORCERER_BALLPOP,
SFX_SORCERER_BALLBOUNCE,
SFX_SORCERER_BALLEXPLODE,
SFX_SORCERER_BIGBALLEXPLODE,
SFX_SORCERER_HEADSCREAM,
SFX_DRAGON_SIGHT,
SFX_DRAGON_ACTIVE,
SFX_DRAGON_WINGFLAP,
SFX_DRAGON_ATTACK,
SFX_DRAGON_PAIN,
SFX_DRAGON_DEATH,
SFX_DRAGON_FIREBALL_EXPLODE,
SFX_KORAX_SIGHT,
SFX_KORAX_ACTIVE,
SFX_KORAX_PAIN,
SFX_KORAX_ATTACK,
SFX_KORAX_COMMAND,
SFX_KORAX_DEATH,
SFX_KORAX_STEP,
SFX_THRUSTSPIKE_RAISE,
SFX_THRUSTSPIKE_LOWER,
SFX_STAINEDGLASS_SHATTER,
SFX_FLECHETTE_BOUNCE,
SFX_FLECHETTE_EXPLODE,
SFX_LAVA_MOVE,
SFX_WATER_MOVE,
SFX_ICE_STARTMOVE,
SFX_EARTH_STARTMOVE,
SFX_WATER_SPLASH,
SFX_LAVA_SIZZLE,
SFX_SLUDGE_GLOOP,
SFX_CHOLY_FIRE,
SFX_SPIRIT_ACTIVE,
SFX_SPIRIT_ATTACK,
SFX_SPIRIT_DIE,
SFX_VALVE_TURN,
SFX_ROPE_PULL,
SFX_FLY_BUZZ,
SFX_IGNITE,
SFX_PUZZLE_SUCCESS,
SFX_PUZZLE_FAIL_FIGHTER,
SFX_PUZZLE_FAIL_CLERIC,
SFX_PUZZLE_FAIL_MAGE,
SFX_EARTHQUAKE,
SFX_BELLRING,
SFX_TREE_BREAK,
SFX_TREE_EXPLODE,
SFX_SUITOFARMOR_BREAK,
SFX_POISONSHROOM_PAIN,
SFX_POISONSHROOM_DEATH,
SFX_AMBIENT1,
SFX_AMBIENT2,
SFX_AMBIENT3,
SFX_AMBIENT4,
SFX_AMBIENT5,
SFX_AMBIENT6,
SFX_AMBIENT7,
SFX_AMBIENT8,
SFX_AMBIENT9,
SFX_AMBIENT10,
SFX_AMBIENT11,
SFX_AMBIENT12,
SFX_AMBIENT13,
SFX_AMBIENT14,
SFX_AMBIENT15,
SFX_STARTUP_TICK,
SFX_SWITCH_OTHERLEVEL,
SFX_RESPAWN,
SFX_KORAX_VOICE_1,
SFX_KORAX_VOICE_2,
SFX_KORAX_VOICE_3,
SFX_KORAX_VOICE_4,
SFX_KORAX_VOICE_5,
SFX_KORAX_VOICE_6,
SFX_KORAX_VOICE_7,
SFX_KORAX_VOICE_8,
SFX_KORAX_VOICE_9,
SFX_BAT_SCREAM,
SFX_CHAT,
SFX_MENU_MOVE,
SFX_CLOCK_TICK,
SFX_FIREBALL,
SFX_PUPPYBEAT,
SFX_MYSTICINCANT,
NUMSFX
} sfxenum_t;
#endif

81
Hexen Source/SOUNDST.H Normal file
View File

@ -0,0 +1,81 @@
//**************************************************************************
//**
//** soundst.h : Heretic 2 : Raven Software, Corp.
//**
//** $RCSfile: soundst.h,v $
//** $Revision: 1.13 $
//** $Date: 95/10/12 18:01:27 $
//** $Author: cjr $
//**
//**************************************************************************
#ifndef __SOUNDSTH__
#define __SOUNDSTH__
typedef struct
{
char name[8];
int p1;
} musicinfo_t;
typedef struct sfxinfo_s
{
char tagName[32];
char lumpname[12]; // Only need 9 bytes, but padded out to be dword aligned
//struct sfxinfo_s *link; // Make alias for another sound
int 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
boolean changePitch;
} sfxinfo_t;
typedef struct
{
mobj_t *mo;
int sound_id;
int handle;
int volume;
int 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;
extern int snd_MaxVolume;
extern int snd_MusicVolume;
void S_Start(void);
void S_StartSound(mobj_t *origin, int sound_id);
int S_GetSoundID(char *name);
void S_StartSoundAtVolume(mobj_t *origin, int sound_id, int volume);
void S_StopSound(mobj_t *origin);
void S_StopAllSound(void);
void S_PauseSound(void);
void S_ResumeSound(void);
void S_UpdateSounds(mobj_t *listener);
void S_StartSong(int song, boolean loop);
void S_StartSongName(char *songLump, boolean loop);
void S_Init(void);
void S_GetChannelInfo(SoundInfo_t *s);
void S_SetMusicVolume(void);
boolean S_GetSoundPlayingInfo(mobj_t *mobj, int sound_id);
#endif

347
Hexen Source/ST_START.C Normal file
View File

@ -0,0 +1,347 @@
//**************************************************************************
//**
//** st_start.c : Heretic 2 : Raven Software, Corp.
//**
//** $RCSfile: st_start.c,v $
//** $Revision: 1.21 $
//** $Date: 95/12/21 15:03:51 $
//** $Author: bgokey $
//**
//**************************************************************************
// HEADER FILES ------------------------------------------------------------
#ifdef __WATCOMC__
#include <sys\stat.h>
#include <sys\types.h>
#include <io.h>
#else
#include <libc.h>
#include <ctype.h>
#define O_BINARY 0
#endif
#include "h2def.h"
#include <fcntl.h>
#include <stdarg.h> // Needed for next as well as dos
#include "st_start.h"
// MACROS ------------------------------------------------------------------
#define ST_MAX_NOTCHES 32
#define ST_NOTCH_WIDTH 16
#define ST_NOTCH_HEIGHT 23
#define ST_PROGRESS_X 64 // Start of notches x screen pos.
#define ST_PROGRESS_Y 441 // Start of notches y screen pos.
#define ST_NETPROGRESS_X 288
#define ST_NETPROGRESS_Y 32
#define ST_NETNOTCH_WIDTH 8
#define ST_NETNOTCH_HEIGHT 16
#define ST_MAX_NETNOTCHES 8
// TYPES -------------------------------------------------------------------
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
extern void SetVideoModeHR(void);
extern void ClearScreenHR(void);
extern void SlamHR(char *buffer);
extern void SlamBlockHR(int x, int y, int w, int h, char *src);
extern void InitPaletteHR(void);
extern void SetPaletteHR(byte *palette);
extern void GetPaletteHR(byte *palette);
extern void FadeToPaletteHR(byte *palette);
extern void FadeToBlackHR(void);
extern void BlackPaletteHR(void);
extern void I_StartupReadKeys(void);
// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
// PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
char *ST_LoadScreen(void);
void ST_UpdateNotches(int notchPosition);
void ST_UpdateNetNotches(int notchPosition);
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
// PUBLIC DATA DEFINITIONS -------------------------------------------------
// PRIVATE DATA DEFINITIONS ------------------------------------------------
char *bitmap = NULL;
char notchTable[]=
{
// plane 0
0x00, 0x80, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x40,
0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x03, 0xC0,
0x0F, 0x90, 0x1B, 0x68, 0x3D, 0xBC, 0x3F, 0xFC, 0x20, 0x08, 0x20, 0x08,
0x2F, 0xD8, 0x37, 0xD8, 0x37, 0xF8, 0x1F, 0xF8, 0x1C, 0x50,
// plane 1
0x00, 0x80, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x02, 0x40, 0x02, 0x40,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x01, 0xA0,
0x30, 0x6C, 0x24, 0x94, 0x42, 0x4A, 0x60, 0x0E, 0x60, 0x06, 0x7F, 0xF6,
0x7F, 0xF6, 0x7F, 0xF6, 0x5E, 0xF6, 0x38, 0x16, 0x23, 0xAC,
// plane 2
0x00, 0x80, 0x01, 0x80, 0x01, 0x80, 0x00, 0x00, 0x02, 0x40, 0x02, 0x40,
0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x03, 0xE0,
0x30, 0x6C, 0x24, 0x94, 0x52, 0x6A, 0x7F, 0xFE, 0x60, 0x0E, 0x60, 0x0E,
0x6F, 0xD6, 0x77, 0xD6, 0x56, 0xF6, 0x38, 0x36, 0x23, 0xAC,
// plane 3
0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80,
0x03, 0xC0, 0x03, 0xC0, 0x03, 0xC0, 0x03, 0xC0, 0x03, 0x80, 0x02, 0x40,
0x0F, 0x90, 0x1B, 0x68, 0x3D, 0xB4, 0x1F, 0xF0, 0x1F, 0xF8, 0x1F, 0xF8,
0x10, 0x28, 0x08, 0x28, 0x29, 0x08, 0x07, 0xE8, 0x1C, 0x50
};
// Red Network Progress notches
char netnotchTable[]=
{
// plane 0
0x80, 0x50, 0xD0, 0xf0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xD0, 0xF0, 0xC0,
0x70, 0x50, 0x80, 0x60,
// plane 1
0x60, 0xE0, 0xE0, 0xA0, 0xA0, 0xA0, 0xE0, 0xA0, 0xA0, 0xA0, 0xE0, 0xA0,
0xA0, 0xE0, 0x60, 0x00,
// plane 2
0x80, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00,
0x10, 0x10, 0x80, 0x60,
// plane 3
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00
};
// CODE --------------------------------------------------------------------
//--------------------------------------------------------------------------
//
// Startup Screen Functions
//
//--------------------------------------------------------------------------
//==========================================================================
//
// ST_Init - Do the startup screen
//
//==========================================================================
void ST_Init(void)
{
#ifdef __WATCOMC__
char *pal;
char *buffer;
if (!debugmode)
{
// Set 640x480x16 mode
SetVideoModeHR();
ClearScreenHR();
InitPaletteHR();
BlackPaletteHR();
// Load graphic
buffer = ST_LoadScreen();
pal = buffer;
bitmap = buffer + 16*3;
SlamHR(bitmap);
FadeToPaletteHR(pal);
Z_Free(buffer);
}
#endif
}
void ST_Done(void)
{
#ifdef __WATCOMC__
ClearScreenHR();
#endif
}
//==========================================================================
//
// ST_UpdateNotches
//
//==========================================================================
void ST_UpdateNotches(int notchPosition)
{
#ifdef __WATCOMC__
int x = ST_PROGRESS_X + notchPosition*ST_NOTCH_WIDTH;
int y = ST_PROGRESS_Y;
SlamBlockHR(x,y, ST_NOTCH_WIDTH,ST_NOTCH_HEIGHT, notchTable);
#endif
}
//==========================================================================
//
// ST_UpdateNetNotches - indicates network progress
//
//==========================================================================
void ST_UpdateNetNotches(int notchPosition)
{
#ifdef __WATCOMC__
int x = ST_NETPROGRESS_X + notchPosition*ST_NETNOTCH_WIDTH;
int y = ST_NETPROGRESS_Y;
SlamBlockHR(x,y, ST_NETNOTCH_WIDTH, ST_NETNOTCH_HEIGHT, netnotchTable);
#endif
}
//==========================================================================
//
// ST_Progress - increments progress indicator
//
//==========================================================================
void ST_Progress(void)
{
#ifdef __WATCOMC__
static int notchPosition=0;
// Check for ESC press -- during startup all events eaten here
I_StartupReadKeys();
if (debugmode)
{
printf(".");
}
else
{
if(notchPosition<ST_MAX_NOTCHES)
{
ST_UpdateNotches(notchPosition);
S_StartSound(NULL, SFX_STARTUP_TICK);
notchPosition++;
}
}
#else
printf(".");
#endif
}
//==========================================================================
//
// ST_NetProgress - indicates network progress
//
//==========================================================================
void ST_NetProgress(void)
{
#ifdef __WATCOMC__
static int netnotchPosition=0;
if (debugmode)
{
printf("*");
}
else
{
if(netnotchPosition<ST_MAX_NETNOTCHES)
{
ST_UpdateNetNotches(netnotchPosition);
S_StartSound(NULL, SFX_DRIP);
netnotchPosition++;
}
}
#endif
}
//==========================================================================
//
// ST_NetDone - net progress complete
//
//==========================================================================
void ST_NetDone(void)
{
S_StartSound(NULL, SFX_PICKUP_WEAPON);
}
//==========================================================================
//
// ST_Message - gives debug message
//
//==========================================================================
void ST_Message(char *message, ...)
{
va_list argptr;
char buffer[80];
va_start(argptr, message);
vsprintf(buffer, message, argptr);
va_end(argptr);
if ( strlen(buffer) >= 80 )
{
I_Error("Long debug message has overwritten memory");
}
#ifdef __WATCOMC__
if (debugmode)
{
printf(buffer);
}
#else
printf(buffer);
#endif
}
//==========================================================================
//
// ST_RealMessage - gives user message
//
//==========================================================================
void ST_RealMessage(char *message, ...)
{
va_list argptr;
char buffer[80];
va_start(argptr, message);
vsprintf(buffer, message, argptr);
va_end(argptr);
if ( strlen(buffer) >= 80 )
{
I_Error("Long debug message has overwritten memory\n");
}
printf(buffer); // Always print these messages
}
//==========================================================================
//
// ST_LoadScreen - loads startup graphic
//
//==========================================================================
char *ST_LoadScreen(void)
{
int length,lump;
char *buffer;
lump = W_GetNumForName("STARTUP");
length = W_LumpLength(lump);
buffer = (char *)Z_Malloc(length, PU_STATIC, NULL);
W_ReadLump(lump, buffer);
return(buffer);
}

28
Hexen Source/ST_START.H Normal file
View File

@ -0,0 +1,28 @@
//**************************************************************************
//**
//** template.h : Heretic 2 : Raven Software, Corp.
//**
//** $RCSfile: st_start.h,v $
//** $Revision: 1.5 $
//** $Date: 95/10/11 23:35:33 $
//** $Author: paul $
//**
//**************************************************************************
// HEADER FILES ------------------------------------------------------------
// MACROS ------------------------------------------------------------------
// TYPES -------------------------------------------------------------------
// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
extern void ST_Init(void);
extern void ST_Done(void);
extern void ST_Message(char *message, ...);
extern void ST_RealMessage(char *message, ...);
extern void ST_Progress(void);
extern void ST_NetProgress(void);
extern void ST_NetDone(void);
// PUBLIC DATA DECLARATIONS ------------------------------------------------

1756
Hexen Source/SV_SAVE.C Normal file

File diff suppressed because it is too large Load Diff

162
Hexen Source/T.BAT Normal file
View File

@ -0,0 +1,162 @@
@REM Hexen startup batch file
@echo off
echo :
call castoff
echo :
if "%1x"=="x" goto badargs
set hticargs=-devmaps dev.txt -warp %1
set hticwads=-file
set hticnplay=
:parseloop
if "%2x"=="x" goto doneparse
if "%2"=="m" goto nomonsters
if "%2"=="M" goto nomonsters
if "%2"=="s1" goto skill1
if "%2"=="S1" goto skill1
if "%2"=="s2" goto skill2
if "%2"=="S2" goto skill2
if "%2"=="s3" goto skill3
if "%2"=="S3" goto skill3
if "%2"=="s4" goto skill4
if "%2"=="S4" goto skill4
if "%2"=="s5" goto skill5
if "%2"=="S5" goto skill5
if "%2"=="n1" goto nplay1
if "%2"=="N1" goto nplay1
if "%2"=="n2" goto nplay2
if "%2"=="N2" goto nplay2
if "%2"=="n3" goto nplay3
if "%2"=="N3" goto nplay3
if "%2"=="n4" goto nplay4
if "%2"=="N4" goto nplay4
if "%2"=="p" goto altport
if "%2"=="P" goto altport
if "%2"=="c0" goto class0
if "%2"=="C0" goto class0
if "%2"=="c1" goto class1
if "%2"=="C1" goto class1
if "%2"=="c2" goto class2
if "%2"=="C2" goto class2
if "%2"=="r" goto randclass
if "%2"=="R" goto randclass
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 2
shift
goto parseloop
:class0
set hticargs=%hticargs% -class 0
shift
goto parseloop
:class1
set hticargs=%hticargs% -class 1
shift
goto parseloop
:class2
set hticargs=%hticargs% -class 2
shift
goto parseloop
:randclass
set hticargs=%hticargs% -randclass
shift
goto parseloop
:addwad
set hticwads=%hticwads% %3.wad
shift
goto parseloop
:badargs
echo HEXEN STARTUP
echo Usage: H 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 [r] = random player class
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%
hexipx -nodes %hticnplay% -deathmatch %hticargs%
goto end
:normalplay
echo %hticargs%
hexen %hticargs%
goto end
:end
set hticargs=
set hticwads=
set hticnplay=
echo :
@call caston
echo :

2074
Hexen Source/TABLES.C Normal file

File diff suppressed because it is too large Load Diff

32
Hexen Source/TEMPLATE.C Normal file
View File

@ -0,0 +1,32 @@
//**************************************************************************
//**
//** TEMPLATE.C
//**
//**************************************************************************
// HEADER FILES ------------------------------------------------------------
// MACROS ------------------------------------------------------------------
// TYPES -------------------------------------------------------------------
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
// PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
// PUBLIC DATA DEFINITIONS -------------------------------------------------
// PRIVATE DATA DEFINITIONS ------------------------------------------------
// CODE --------------------------------------------------------------------
//==========================================================================
//
//
//
//==========================================================================

167
Hexen Source/TEXTDEFS.H Normal file
View File

@ -0,0 +1,167 @@
//**************************************************************************
//**
//** textdefs.h : Heretic 2 : Raven Software, Corp.
//**
//** $RCSfile: textdefs.h,v $
//** $Revision: 1.34 $
//** $Date: 96/01/05 23:33:22 $
//** $Author: bgokey $
//**
//**************************************************************************
// MN_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 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 TXT_GAMMA_LEVEL_OFF "GAMMA CORRECTION OFF"
#define TXT_GAMMA_LEVEL_1 "GAMMA CORRECTION LEVEL 1"
#define TXT_GAMMA_LEVEL_2 "GAMMA CORRECTION LEVEL 2"
#define TXT_GAMMA_LEVEL_3 "GAMMA CORRECTION LEVEL 3"
#define TXT_GAMMA_LEVEL_4 "GAMMA CORRECTION LEVEL 4"
#define EMPTYSTRING "empty slot"
// P_inter.c ---------------------------------------------------------------
// Mana
#define TXT_MANA_1 "BLUE MANA"
#define TXT_MANA_2 "GREEN MANA"
#define TXT_MANA_BOTH "COMBINED MANA"
// Keys
#define TXT_KEY_STEEL "STEEL KEY"
#define TXT_KEY_CAVE "CAVE KEY"
#define TXT_KEY_AXE "AXE KEY"
#define TXT_KEY_FIRE "FIRE KEY"
#define TXT_KEY_EMERALD "EMERALD KEY"
#define TXT_KEY_DUNGEON "DUNGEON KEY"
#define TXT_KEY_SILVER "SILVER KEY"
#define TXT_KEY_RUSTED "RUSTED KEY"
#define TXT_KEY_HORN "HORN KEY"
#define TXT_KEY_SWAMP "SWAMP KEY"
#define TXT_KEY_CASTLE "CASTLE KEY"
// Artifacts
#define TXT_ARTIINVULNERABILITY "ICON OF THE DEFENDER"
#define TXT_ARTIHEALTH "QUARTZ FLASK"
#define TXT_ARTISUPERHEALTH "MYSTIC URN"
#define TXT_ARTISUMMON "DARK SERVANT"
#define TXT_ARTITORCH "TORCH"
#define TXT_ARTIEGG "PORKALATOR"
#define TXT_ARTIFLY "WINGS OF WRATH"
#define TXT_ARTITELEPORT "CHAOS DEVICE"
#define TXT_ARTIPOISONBAG "FLECHETTE"
#define TXT_ARTITELEPORTOTHER "BANISHMENT DEVICE"
#define TXT_ARTISPEED "BOOTS OF SPEED"
#define TXT_ARTIBOOSTMANA "KRATER OF MIGHT"
#define TXT_ARTIBOOSTARMOR "DRAGONSKIN BRACERS"
#define TXT_ARTIBLASTRADIUS "DISC OF REPULSION"
#define TXT_ARTIHEALINGRADIUS "MYSTIC AMBIT INCANT"
// Puzzle artifacts
#define TXT_ARTIPUZZSKULL "YORICK'S SKULL"
#define TXT_ARTIPUZZGEMBIG "HEART OF D'SPARIL"
#define TXT_ARTIPUZZGEMRED "RUBY PLANET"
#define TXT_ARTIPUZZGEMGREEN1 "EMERALD PLANET"
#define TXT_ARTIPUZZGEMGREEN2 "EMERALD PLANET"
#define TXT_ARTIPUZZGEMBLUE1 "SAPPHIRE PLANET"
#define TXT_ARTIPUZZGEMBLUE2 "SAPPHIRE PLANET"
#define TXT_ARTIPUZZBOOK1 "DAEMON CODEX"
#define TXT_ARTIPUZZBOOK2 "LIBER OSCURA"
#define TXT_ARTIPUZZSKULL2 "FLAME MASK"
#define TXT_ARTIPUZZFWEAPON "GLAIVE SEAL"
#define TXT_ARTIPUZZCWEAPON "HOLY RELIC"
#define TXT_ARTIPUZZMWEAPON "SIGIL OF THE MAGUS"
#define TXT_ARTIPUZZGEAR "CLOCK GEAR"
#define TXT_USEPUZZLEFAILED "YOU CANNOT USE THIS HERE"
// 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"
#define TXT_ARMOR1 "MESH ARMOR"
#define TXT_ARMOR2 "FALCON SHIELD"
#define TXT_ARMOR3 "PLATINUM HELMET"
#define TXT_ARMOR4 "AMULET OF WARDING"
// Weapons
#define TXT_WEAPON_F2 "TIMON'S AXE"
#define TXT_WEAPON_F3 "HAMMER OF RETRIBUTION"
#define TXT_WEAPON_F4 "QUIETUS ASSEMBLED"
#define TXT_WEAPON_C2 "SERPENT STAFF"
#define TXT_WEAPON_C3 "FIRESTORM"
#define TXT_WEAPON_C4 "WRAITHVERGE ASSEMBLED"
#define TXT_WEAPON_M2 "FROST SHARDS"
#define TXT_WEAPON_M3 "ARC OF DEATH"
#define TXT_WEAPON_M4 "BLOODSCOURGE ASSEMBLED"
#define TXT_QUIETUS_PIECE "SEGMENT OF QUIETUS"
#define TXT_WRAITHVERGE_PIECE "SEGMENT OF WRAITHVERGE"
#define TXT_BLOODSCOURGE_PIECE "SEGMENT OF BLOODSCOURGE"
// 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_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_CHEATARTIFACTS3 "ALL ARTIFACTS"
#define TXT_CHEATARTIFACTSFAIL "BAD INPUT"
#define TXT_CHEATWARP "LEVEL WARP"
#define TXT_CHEATSCREENSHOT "SCREENSHOT"
#define TXT_CHEATIDDQD "TRYING TO CHEAT, EH? NOW YOU DIE!"
#define TXT_CHEATIDKFA "CHEATER - YOU DON'T DESERVE WEAPONS"
#define TXT_CHEATBADINPUT "BAD INPUT"
#define TXT_CHEATNOMAP "CAN'T FIND MAP"
// G_game.c ----------------------------------------------------------------
#define TXT_GAMESAVED "GAME SAVED"
// M_misc.c ----------------------------------------------------------------
#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"
// AM_map.c ----------------------------------------------------------------
#define AMSTR_FOLLOWON "FOLLOW MODE ON"
#define AMSTR_FOLLOWOFF "FOLLOW MODE OFF"

34
Hexen Source/VGAVIEW.H Normal file
View File

@ -0,0 +1,34 @@
//**************************************************************************
//**
//** VGAView.h : Heretic 2 : Raven Software, Corp.
//**
//** $RCSfile: VGAView.h,v $
//** $Revision: 1.1 $
//** $Date: 95/05/11 00:19:48 $
//** $Author: bgokey $
//**
//**************************************************************************
#import <appkit/appkit.h>
#import "h2def.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

261
Hexen Source/V_VIDEO.C Normal file
View File

@ -0,0 +1,261 @@
//**************************************************************************
//**
//** v_video.c : Heretic 2 : Raven Software, Corp.
//**
//** $RCSfile: v_video.c,v $
//** $Revision: 1.2 $
//** $Date: 95/09/11 14:58:16 $
//** $Author: cjr $
//**
//**************************************************************************
#include "h2def.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 + ((*source++)<<8)];
dest += SCREENWIDTH;
}
column = (column_t *)((byte *)column+column->length+4);
}
}
}
/*
==================
=
= V_DrawAltFuzzPatch
=
= Masks a column based translucent masked pic to the screen.
=
==================
*/
extern byte *tinttable;
void V_DrawAltFuzzPatch (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);
}

6
Hexen Source/W.BAT Normal file
View File

@ -0,0 +1,6 @@
@echo off
echo Making HEXEN.WAD
echo Preprocessing: wadlink.txt to wadlink.wl
wcc386 /dNOMAPS /dREGISTERED /p /fo=wadlink.wl \data\wadlink.txt
echo wadlinking ...
\tools\exe\wadlink

265
Hexen Source/WADLINK.WL Normal file
View File

@ -0,0 +1,265 @@
; WAD NAME
$WADNAME HEXEN
; VERSION ID
\data\xxtic.lmp
; STARTUP SCREEN
\art\startup\startup.lmp
; PALETTES AND COLOR MAPS
\art\palette\playpal.lmp
\art\palette\colormap.lmp
\art\palette\fogmap.lmp
\art\palette\tinttab.lmp
; TRANSLATION TABLES
$shootwad \art\palette\trans-8.wad
; DEMOS
\data\demos\demo1.lmp
\data\demos\demo2.lmp
\data\demos\demo3.lmp
; SCREENS
$shootwad \art\screens\screens.wad
; \data\txtscrn2\endtext.bin
; LEVEL MAPS
; CLUSTER CONCLUSION MESSAGES
\data\text\clus1msg.txt
\data\text\clus2msg.txt
\data\text\clus3msg.txt
\data\text\clus4msg.txt
; WIN GAME MESSAGES
\data\text\win1msg.txt
\data\text\win2msg.txt
\data\text\win3msg.txt
; TEXTURE INFO AND PATCH NAMES
\maps\pnames.lmp
\maps\texture1.lmp
\maps\texture2.lmp
; SCRIPTS
\data\scripts\animdefs.txt
\data\scripts\mapinfo.txt
\data\scripts\sndinfo.txt
\data\scripts\sndseq.txt
; AUTOMAP
$shootwad \art\automap\automap
; STATUS BAR
$shootwad \art\statbar\statbar
; MENU
$shootwad \art\menu\menu
; FONTS
$label fonta_s
$shootwad \art\fonts\fonta
$label fonta_e
$label fontay_s
$shootwad \art\fonts\fonta_y
$label fontay_e
$label fontb_s
$shootwad \art\fonts\fontb
$label fontb_e
; START SPRITES
$label s_start
; Fighter weapons
$shootwad \art\weapons\fighter\punch\punch.wad
$shootwad \art\weapons\fighter\axe\axe.wad
$shootwad \art\weapons\fighter\hammer\hammer.wad
$shootwad \art\weapons\fighter\sword\sword.wad
; Cleric weapons
$shootwad \art\weapons\cleric\mace\mace.wad
$shootwad \art\weapons\cleric\sstaff\sstaff.wad
$shootwad \art\weapons\cleric\flame\flame.wad
$shootwad \art\weapons\cleric\holy\holy.wad
; Mage weapons
$shootwad \art\weapons\mage\wand\wand.wad
$shootwad \art\weapons\mage\cone\cone.wad
$shootwad \art\weapons\mage\lightng\lightng.wad
$shootwad \art\weapons\mage\staff\mstaff.wad
; Morphed player weapons
; $shootwad \art\weapons\beak\beak.wad
$shootwad \art\weapons\snout\snout.wad
; PLAYER
$shootwad \art\player\fighter\fighter
$shootwad \art\player\fighter\fighter2
$shootwad \art\player\mage\mage
$shootwad \art\player\mage\mage2
$shootwad \art\player\mage\mage3
$shootwad \art\player\cleric\cleric
$shootwad \art\player\cleric\cleric2
$shootwad \art\player\cleric\cleric3
; MONSTERS
; Sea Serpent
$shootwad \art\monsters\serpent\serpent
; Centaur
$shootwad \art\monsters\centaur\centaur
$shootwad \art\monsters\centaur\centaur2
$shootwad \art\monsters\centaur\centaur3
$shootwad \art\monsters\centaur\centfx
; Demon
$shootwad \art\monsters\demon\demon
; Demon2
$shootwad \art\monsters\demon2\demon2
; Wraith
$shootwad \art\monsters\wraith\wraith
; Dragon Lich
$shootwad \art\monsters\dragon\dragon
; Bishop
$shootwad \art\monsters\bishop\bishop
; Ettin
$shootwad \art\monsters\ettin\ettin
; Fire Demon
$shootwad \art\monsters\firedemn\fired
; Ice Guy
$shootwad \art\monsters\ice\iceguy
; Sorcerer Boss Guy
$shootwad \art\monsters\boss1\sorc
; Korax
$shootwad \art\monsters\korax\korax
; Chicken
; $shootwad \art\monsters\chicken\chicken
; Pig
$shootwad \art\monsters\pig\pig
; 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
; STATIC SPRITES
$shootwad \art\sprites\e1spr
$shootwad \art\sprites\s\sprite_s
; World projectile sprites
$shootwad \art\sprites\prjtile\prjtile
$shootwad \art\sprites\r\sprite_r
$shootwad \art\sprites\fogpatch\fogpatch.wad
$shootwad \art\weapons\images\images
$shootwad \art\artifcts\artifcts
$shootwad \art\items\items
; $shootwad \art\ammo\ammo
; Mana
$shootwad \art\mana\mana
; END SPRITES
$label s_end
;---------------------------------------------------------------------------
; WALL PATCHES
$label p_start
; Shareware wall patches
$label p1_start
$shootwad \art\walls\s\walls_s
$shootwad \art\backdrop\sky_s
$label p1_end
; Registered wall patches
$label p2_start
$shootwad \art\walls\r\walls_r
$shootwad \art\backdrop\sky_r
$label p2_end
$label p_end
;---------------------------------------------------------------------------
; FLATS
$label f_start
; Shareware flats
$label f1_start
$shootwad \art\flats\s\flats_s
$label f1_end
; Registered flats
$label f2_start
$shootwad \art\flats\r\flats_r
$label f2_end
$label f_end
; SOUND
\sound\misc\genmidi.op2
\sound\misc\dmxgus.lmp
\sound\misc\sndcurve.lmp
$shootwad \sound\archive\sndwad_r

596
Hexen Source/W_WAD.C Normal file
View File

@ -0,0 +1,596 @@
//**************************************************************************
//**
//** w_wad.c : Heretic 2 : Raven Software, Corp.
//**
//** $RCSfile: w_wad.c,v $
//** $Revision: 1.6 $
//** $Date: 95/10/06 20:56:47 $
//** $Author: cjr $
//**
//**************************************************************************
// HEADER FILES ------------------------------------------------------------
#ifdef NeXT
#include <libc.h>
#include <ctype.h>
#else
#include <malloc.h>
#include <io.h>
#include <fcntl.h>
#include <sys/stat.h>
#endif
#include "h2def.h"
// MACROS ------------------------------------------------------------------
#ifdef NeXT
// NeXT doesn't need a binary flag in open call
#define O_BINARY 0
#define strcmpi strcasecmp
#endif
// TYPES -------------------------------------------------------------------
typedef struct
{
char identification[4];
int numlumps;
int infotableofs;
} wadinfo_t;
typedef struct
{
int filepos;
int size;
char name[8];
} filelump_t;
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
// PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
// PUBLIC DATA DEFINITIONS -------------------------------------------------
lumpinfo_t *lumpinfo;
int numlumps;
void **lumpcache;
// PRIVATE DATA DEFINITIONS ------------------------------------------------
static lumpinfo_t *PrimaryLumpInfo;
static int PrimaryNumLumps;
static void **PrimaryLumpCache;
static lumpinfo_t *AuxiliaryLumpInfo;
static int AuxiliaryNumLumps;
static void **AuxiliaryLumpCache;
static int AuxiliaryHandle = 0;
boolean AuxiliaryOpened = false;
// CODE --------------------------------------------------------------------
#ifdef NeXT
//==========================================================================
//
// strupr
//
//==========================================================================
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
//==========================================================================
//
// W_AddFile
//
// 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;
filelump_t *freeFileInfo;
if((handle = open(filename, O_RDONLY|O_BINARY)) == -1)
{ // Didn't find file
return;
}
startlump = numlumps;
if(strcmpi(filename+strlen(filename)-3, "wad"))
{ // Single lump file
fileinfo = &singleinfo;
freeFileInfo = NULL;
singleinfo.filepos = 0;
singleinfo.size = LONG(filelength(handle));
M_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))
{ // Bad file id
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);
if(!(fileinfo = malloc(length)))
{
I_Error("W_AddFile: fileinfo malloc failed\n");
}
freeFileInfo = fileinfo;
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);
}
if(freeFileInfo)
{
free(freeFileInfo);
}
}
//==========================================================================
//
// W_InitMultipleFiles
//
// Pass a null terminated list of files to use. All files are optional,
// but at least one file must be found. 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_InitMultipleFiles: 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);
PrimaryLumpInfo = lumpinfo;
PrimaryLumpCache = lumpcache;
PrimaryNumLumps = numlumps;
}
//==========================================================================
//
// W_InitFile
//
// Initialize the primary from a single file.
//
//==========================================================================
void W_InitFile(char *filename)
{
char *names[2];
names[0] = filename;
names[1] = NULL;
W_InitMultipleFiles(names);
}
//==========================================================================
//
// W_OpenAuxiliary
//
//==========================================================================
void W_OpenAuxiliary(char *filename)
{
int i;
int size;
wadinfo_t header;
int handle;
int length;
filelump_t *fileinfo;
filelump_t *sourceLump;
lumpinfo_t *destLump;
if(AuxiliaryOpened)
{
W_CloseAuxiliary();
}
if((handle = open(filename, O_RDONLY|O_BINARY)) == -1)
{
I_Error("W_OpenAuxiliary: %s not found.", filename);
return;
}
AuxiliaryHandle = handle;
read(handle, &header, sizeof(header));
if(strncmp(header.identification, "IWAD", 4))
{
if(strncmp(header.identification, "PWAD", 4))
{ // Bad file id
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 = Z_Malloc(length, PU_STATIC, 0);
lseek(handle, header.infotableofs, SEEK_SET);
read(handle, fileinfo, length);
numlumps = header.numlumps;
// Init the auxiliary lumpinfo array
lumpinfo = Z_Malloc(numlumps*sizeof(lumpinfo_t), PU_STATIC, 0);
sourceLump = fileinfo;
destLump = lumpinfo;
for(i = 0; i < numlumps; i++, destLump++, sourceLump++)
{
destLump->handle = handle;
destLump->position = LONG(sourceLump->filepos);
destLump->size = LONG(sourceLump->size);
strncpy(destLump->name, sourceLump->name, 8);
}
Z_Free(fileinfo);
// Allocate the auxiliary lumpcache array
size = numlumps*sizeof(*lumpcache);
lumpcache = Z_Malloc(size, PU_STATIC, 0);
memset(lumpcache, 0, size);
AuxiliaryLumpInfo = lumpinfo;
AuxiliaryLumpCache = lumpcache;
AuxiliaryNumLumps = numlumps;
AuxiliaryOpened = true;
}
//==========================================================================
//
// W_CloseAuxiliary
//
//==========================================================================
void W_CloseAuxiliary(void)
{
int i;
if(AuxiliaryOpened)
{
W_UseAuxiliary();
for(i = 0; i < numlumps; i++)
{
if(lumpcache[i])
{
Z_Free(lumpcache[i]);
}
}
Z_Free(AuxiliaryLumpInfo);
Z_Free(AuxiliaryLumpCache);
W_CloseAuxiliaryFile();
AuxiliaryOpened = false;
}
W_UsePrimary();
}
//==========================================================================
//
// W_CloseAuxiliaryFile
//
// WARNING: W_CloseAuxiliary() must be called before any further
// auxiliary lump processing.
//
//==========================================================================
void W_CloseAuxiliaryFile(void)
{
if(AuxiliaryHandle)
{
close(AuxiliaryHandle);
AuxiliaryHandle = 0;
}
}
//==========================================================================
//
// W_UsePrimary
//
//==========================================================================
void W_UsePrimary(void)
{
lumpinfo = PrimaryLumpInfo;
numlumps = PrimaryNumLumps;
lumpcache = PrimaryLumpCache;
}
//==========================================================================
//
// W_UseAuxiliary
//
//==========================================================================
void W_UseAuxiliary(void)
{
if(AuxiliaryOpened == false)
{
I_Error("W_UseAuxiliary: WAD not opened.");
}
lumpinfo = AuxiliaryLumpInfo;
numlumps = AuxiliaryNumLumps;
lumpcache = AuxiliaryLumpCache;
}
//==========================================================================
//
// 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 full 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])
{ // Need to read the lump in
ptr = Z_Malloc(W_LumpLength(lump), tag, &lumpcache[lump]);
W_ReadLump(lump, lumpcache[lump]);
}
else
{
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);
}
*/

231
Hexen Source/XDDEFS.H Normal file
View File

@ -0,0 +1,231 @@
//**************************************************************************
//**
//** xddefs.h : Heretic 2 : Raven Software, Corp.
//**
//** $RCSfile: xddefs.h,v $
//** $Revision: 1.4 $
//** $Date: 95/08/11 10:22:08 $
//** $Author: bgokey $
//**
//**************************************************************************
#ifndef __XDDEFS__
#define __XDDEFS__
#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,
ML_BEHAVIOR
};
typedef struct
{
short x;
short y;
} mapvertex_t;
typedef struct
{
short textureoffset;
short rowoffset;
char toptexture[8];
char bottomtexture[8];
char midtexture[8];
short sector; // on viewer's side
} mapsidedef_t;
typedef struct
{
short v1;
short v2;
short flags;
byte special;
byte arg1;
byte arg2;
byte arg3;
byte arg4;
byte arg5;
short sidenum[2]; // sidenum[1] will be -1 if one sided
} maplinedef_t;
#define ML_BLOCKING 0x0001
#define ML_BLOCKMONSTERS 0x0002
#define ML_TWOSIDED 0x0004
#define ML_DONTPEGTOP 0x0008
#define ML_DONTPEGBOTTOM 0x0010
#define ML_SECRET 0x0020 // don't map as two sided: IT'S A SECRET!
#define ML_SOUNDBLOCK 0x0040 // don't let sound cross two of these
#define ML_DONTDRAW 0x0080 // don't draw on the automap
#define ML_MAPPED 0x0100 // set if already drawn in automap
#define ML_REPEAT_SPECIAL 0x0200 // special is repeatable
#define ML_SPAC_SHIFT 10
#define ML_SPAC_MASK 0x1c00
#define GET_SPAC(flags) ((flags&ML_SPAC_MASK)>>ML_SPAC_SHIFT)
// Special activation types
#define SPAC_CROSS 0 // when player crosses line
#define SPAC_USE 1 // when player uses line
#define SPAC_MCROSS 2 // when monster crosses line
#define SPAC_IMPACT 3 // when projectile hits line
#define SPAC_PUSH 4 // when player/monster pushes line
#define SPAC_PCROSS 5 // when projectile crosses line
typedef struct
{
short floorheight;
short ceilingheight;
char floorpic[8];
char ceilingpic[8];
short lightlevel;
short special;
short tag;
} mapsector_t;
typedef struct
{
short numsegs;
short firstseg; // segs are stored sequentially
} mapsubsector_t;
typedef struct
{
short v1;
short v2;
short angle;
short linedef;
short side;
short offset;
} mapseg_t;
enum
{ // bbox coordinates
BOXTOP,
BOXBOTTOM,
BOXLEFT,
BOXRIGHT
};
#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 tid;
short x;
short y;
short height;
short angle;
short type;
short options;
byte special;
byte arg1;
byte arg2;
byte arg3;
byte arg4;
byte arg5;
} mapthing_t;
#define MTF_EASY 1
#define MTF_NORMAL 2
#define MTF_HARD 4
#define MTF_AMBUSH 8
#define MTF_DORMANT 16
#define MTF_FIGHTER 32
#define MTF_CLERIC 64
#define MTF_MAGE 128
#define MTF_GSINGLE 256
#define MTF_GCOOP 512
#define MTF_GDEATHMATCH 1024
//--------------------------------------------------------------------------
//
// 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;
#endif // __XDDEFS__

396
Hexen Source/Z_ZONE.C Normal file
View File

@ -0,0 +1,396 @@
//**************************************************************************
//**
//** z_zone.c : Heretic 2 : Raven Software, Corp.
//**
//** $RCSfile: z_zone.c,v $
//** $Revision: 1.2 $
//** $Date: 96/01/06 03:23:53 $
//** $Author: bgokey $
//**
//**************************************************************************
#include <stdlib.h>
#include "h2def.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;
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;
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) // scaned all the way around the list
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
View 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
View 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.