Dump more tools in, plus add ncAnimationManager object.

This commit is contained in:
Marco Cawthorne 2025-01-23 22:15:59 -08:00
parent 75256d8ead
commit 4db1c33265
41 changed files with 2682 additions and 110 deletions

120
Makefile Normal file
View file

@ -0,0 +1,120 @@
# Nuclide-Lite Makefile
# 2025-01-22
# id1 = Quake; data1 = Hexen 2; qw = QuakeWorld
GAME=id1
ENGINE_CLBUILD=m-dbg
EDITOR=radiant
ENGINE_URL=https://www.github.com/fte-team/fteqw
NAME=`./Tools/get-name.sh $(GAME)`
NUCLIDE_DIR=`pwd`
QCC_DIR=$(NUCLIDE_DIR)
BUILD_DIR=$(NUCLIDE_DIR)/build
help:
@printf "Available targets:\n"
@printf "\thelp\n"
@printf "\tgame\n"
@printf "\tfteqcc\n"
@printf "\tfteqw\n"
all: models maps game gfx
game:
cd $(GAME)/src/ && ../../fteqcc
pak: game qfiles
./Tools/build_filesdat.sh id1
cd $(GAME)/src && ../../qfiles -pak 0
cd $(GAME)/src && ../../qfiles -pak 1
run: fteqw game
./fteqw -basedir `pwd` -netquake -game $(GAME)
wad: imgtool palette
./Tools/build_wads.sh $(GAME)
maps: wad
./Tools/build_maps.sh $(GAME)
$(GAME)/maps/%.bsp: qbsp qlight qvis
Tools/make_map.sh $(GAME) "$@"
models: iqmtool palette
./Tools/build_models.sh $(GAME)
gfx: imgtool palette
cd $(GAME)/gfxsrc/ && ls | grep -v palette\.lmp | grep \.xcf | xargs ../../imgtool --rgb8 --ext png
cd $(GAME)/gfxsrc/ && ls | grep -v palette\.png | grep \.png | xargs mogrify -type TrueColor -compress None -flip -format tga
cp $(GAME)/gfx/palette.lmp $(GAME)/gfxsrc/palette.lmp
cd $(GAME)/gfxsrc/ && ls | grep -v palette\.tga | grep \.tga | xargs ../../tga2lmp
rm $(GAME)/gfxsrc/*.tga
cp $(GAME)/gfx/palette.lmp $(GAME)/gfxsrc/palette.lmp
rsync -va $(GAME)/gfxsrc/*.lmp $(GAME)/gfx/
rm $(GAME)/gfxsrc/*.lmp
# various palette utilities needed
tga2pal:
gcc -o tga2pal Tools/Source/tga2pal.c
tga2lmp:
gcc -o tga2lmp Tools/Source/tga2lmp.c
pal2pal:
gcc -o pal2pal Tools/Source/pal2pal.c
pal2colormap:
gcc -o pal2colormap Tools/Source/pal2colormap.c
qfiles:
gcc -o qfiles Tools/Source/qfiles.c Tools/Source/cmdlib.c
palette: pal2colormap pal2pal tga2pal
if [ ! -d $(GAME)/gfx ];then mkdir $(GAME)/gfx; fi
mogrify -type TrueColor -compress None -flip -format tga $(GAME)/gfxsrc/palette.png
cd $(GAME)/gfxsrc/ && ../../tga2pal palette.tga
cd $(GAME)/gfxsrc/ && ../../pal2pal palette.lmp
cd $(GAME)/gfxsrc/ && ../../pal2colormap palette.lmp
mv $(GAME)/gfxsrc/palette.lmp $(GAME)/gfx/palette.lmp
mv $(GAME)/gfxsrc/colormap.lmp $(GAME)/gfx/colormap.lmp
mv $(GAME)/gfxsrc/palette.pal $(GAME)/gfx/palette.pal
-mkdir -p $(GAME)/gfxsrc
-mkdir -p $(GAME)/textures # needed by gtkradiant
cp $(GAME)/gfx/palette.lmp $(GAME)/textures/palette.lmp
rm $(GAME)/gfxsrc/palette.tga
# fteqw repo
update:
if [ ! -d ThirdParty/fteqw ];then mkdir ThirdParty && git clone $(ENGINE_URL) ThirdParty/fteqw;else cd ./ThirdParty/fteqw && git pull;fi
if [ ! -d ThirdParty/gtkradiant ];then git clone https://github.com/TTimo/gtkradiant ThirdParty/gtkradiant;else cd ./ThirdParty/gtkradiant && git pull;fi
fteqcc: update
cd ThirdParty/fteqw/engine && $(MAKE) qcc-rel
install -m 0777 ./ThirdParty/fteqw/engine/release/fteqcc ./
fteqw: update
cd ThirdParty/fteqw/engine && $(MAKE) makelibs ARCH=x86_64
cd ThirdParty/fteqw/engine && $(MAKE) $(ENGINE_CLBUILD) ARCH=x86_64
install -m 0777 ./ThirdParty/fteqw/engine/debug/fteqw ./
imgtool: update
cd ThirdParty/fteqw/engine && $(MAKE) imgtool ARCH=x86_64
install -m 0777 ./ThirdParty/fteqw/engine/release/imgtool ./
iqmtool: update
cd ThirdParty/fteqw/engine && $(MAKE) iqmtool ARCH=x86_64
install -m 0777 ./ThirdParty/fteqw/engine/release/iqmtool ./
qbsp:
printf "qbsp build\n"
qvis:
printf "qvis build\n"
qlight:
printf "qlight build\n"
radiant: update
if [ ! -d ThirdParty/gtkradiant ];then git clone https://github.com/TTimo/gtkradiant ThirdParty/gtkradiant;fi
cd ThirdParty/gtkradiant && scons
Tools/make_launcher.sh ./ThirdParty/gtkradiant/install/ ./radiant.bin radiant

869
Tools/Source/cmdlib.c Normal file
View file

@ -0,0 +1,869 @@
// cmdlib.c
#include "cmdlib.h"
#include <sys/types.h>
#include <sys/stat.h>
#ifdef WIN32
#include <direct.h>
#else
#include <unistd.h>
#endif
#ifdef NeXT
#include <libc.h>
#endif
#define PATHSEPERATOR '/'
// set these before calling CheckParm
int myargc;
char **myargv;
char com_token[1024];
qboolean com_eof;
qboolean archive;
char archivedir[1024];
/*
=================
Error
For abnormal program terminations
=================
*/
void Error (char *error, ...)
{
va_list argptr;
printf ("************ ERROR ************\n");
va_start (argptr,error);
vprintf (error,argptr);
va_end (argptr);
printf ("\n");
exit (1);
}
/*
qdir will hold the path up to the quake directory, including the slash
f:\quake\
/raid/quake/
gamedir will hold qdir + the game directory (id1, id2, etc)
*/
char qdir[1024];
char gamedir[1024];
void SetQdirFromPath (char *path)
{
char temp[1024];
char *c;
if (!(path[0] == '/' || path[0] == '\\' || path[1] == ':'))
{ // path is partial
Q_getwd (temp);
strcat (temp, path);
path = temp;
}
// search for "quake" in path
for (c=path ; *c ; c++)
if (!Q_strncasecmp (c, "Nuclide-Lite", 12))
{
strncpy (qdir, path, c+13-path);
printf ("qdir: %s\n", qdir);
c += 13;
while (*c)
{
if (*c == '/' || *c == '\\')
{
strncpy (gamedir, path, c+1-path);
printf ("gamedir: %s\n", gamedir);
return;
}
c++;
}
Error ("No gamedir in %s", path);
return;
}
Error ("SeetQdirFromPath: no 'Nuclide' in %s", path);
}
char *ExpandPath (char *path)
{
static char full[1024];
if (!qdir)
Error ("ExpandPath called without qdir set");
if (path[0] == '/' || path[0] == '\\' || path[1] == ':')
return path;
sprintf (full, "%s%s", qdir, path);
return full;
}
char *ExpandPathAndArchive (char *path)
{
char *expanded;
char archivename[1024];
expanded = ExpandPath (path);
if (archive)
{
sprintf (archivename, "%s/%s", archivedir, path);
CopyFile (expanded, archivename);
}
return expanded;
}
char *copystring(char *s)
{
char *b;
b = malloc(strlen(s)+1);
strcpy (b, s);
return b;
}
/*
================
I_FloatTime
================
*/
double I_FloatTime (void)
{
time_t t;
time (&t);
return t;
#if 0
// more precise, less portable
struct timeval tp;
struct timezone tzp;
static int secbase;
gettimeofday(&tp, &tzp);
if (!secbase)
{
secbase = tp.tv_sec;
return tp.tv_usec/1000000.0;
}
return (tp.tv_sec - secbase) + tp.tv_usec/1000000.0;
#endif
}
void Q_getwd (char *out)
{
#ifdef WIN32
_getcwd (out, 256);
strcat (out, "\\");
#else
getcwd (out, 256);
#endif
}
void Q_mkdir (char *path)
{
#ifdef WIN32
if (_mkdir (path) != -1)
return;
#else
if (mkdir (path, 0777) != -1)
return;
#endif
if (errno != EEXIST)
Error ("mkdir %s: %s",path, strerror(errno));
}
/*
============
FileTime
returns -1 if not present
============
*/
int FileTime (char *path)
{
struct stat buf;
if (stat (path,&buf) == -1)
return -1;
return buf.st_mtime;
}
/*
==============
COM_Parse
Parse a token out of a string
==============
*/
char *COM_Parse (char *data)
{
int c;
int len;
len = 0;
com_token[0] = 0;
if (!data)
return NULL;
// skip whitespace
skipwhite:
while ( (c = *data) <= ' ')
{
if (c == 0)
{
com_eof = true;
return NULL; // end of file;
}
data++;
}
// skip // comments
if (c=='/' && data[1] == '/')
{
while (*data && *data != '\n')
data++;
goto skipwhite;
}
// handle quoted strings specially
if (c == '\"')
{
data++;
do
{
c = *data++;
if (c=='\"')
{
com_token[len] = 0;
return data;
}
com_token[len] = c;
len++;
} while (1);
}
// parse single characters
if (c=='{' || c=='}'|| c==')'|| c=='(' || c=='\'' || c==':')
{
com_token[len] = c;
len++;
com_token[len] = 0;
return data+1;
}
// parse a regular word
do
{
com_token[len] = c;
data++;
len++;
c = *data;
if (c=='{' || c=='}'|| c==')'|| c=='(' || c=='\'' || c==':')
break;
} while (c>32);
com_token[len] = 0;
return data;
}
int Q_strncasecmp (char *s1, char *s2, int n)
{
int c1, c2;
while (1)
{
c1 = *s1++;
c2 = *s2++;
if (!n--)
return 0; // strings are equal until end point
if (c1 != c2)
{
if (c1 >= 'a' && c1 <= 'z')
c1 -= ('a' - 'A');
if (c2 >= 'a' && c2 <= 'z')
c2 -= ('a' - 'A');
if (c1 != c2)
return -1; // strings not equal
}
if (!c1)
return 0; // strings are equal
}
return -1;
}
int Q_strcasecmp (char *s1, char *s2)
{
return Q_strncasecmp (s1, s2, 99999);
}
char *strupr (char *start)
{
char *in;
in = start;
while (*in)
{
*in = toupper(*in);
in++;
}
return start;
}
char *strlower (char *start)
{
char *in;
in = start;
while (*in)
{
*in = tolower(*in);
in++;
}
return start;
}
/*
=============================================================================
MISC FUNCTIONS
=============================================================================
*/
/*
=================
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 CheckParm (char *check)
{
int i;
for (i = 1;i<myargc;i++)
{
if ( !Q_strcasecmp(check, myargv[i]) )
return i;
}
return 0;
}
/*
================
filelength
================
*/
int filelength (FILE *f)
{
int pos;
int end;
pos = ftell (f);
fseek (f, 0, SEEK_END);
end = ftell (f);
fseek (f, pos, SEEK_SET);
return end;
}
FILE *SafeOpenWrite (char *filename)
{
FILE *f;
f = fopen(filename, "wb");
if (!f)
Error ("Error opening %s: %s",filename,strerror(errno));
return f;
}
FILE *SafeOpenRead (char *filename)
{
FILE *f;
f = fopen(filename, "rb");
if (!f)
Error ("Error opening %s: %s",filename,strerror(errno));
return f;
}
void SafeRead (FILE *f, void *buffer, int count)
{
if ( fread (buffer, 1, count, f) != (size_t)count)
Error ("File read failure");
}
void SafeWrite (FILE *f, void *buffer, int count)
{
if (fwrite (buffer, 1, count, f) != (size_t)count)
Error ("File read failure");
}
/*
==============
LoadFile
==============
*/
int LoadFile (char *filename, void **bufferptr)
{
FILE *f;
int length;
void *buffer;
f = SafeOpenRead (filename);
length = filelength (f);
buffer = malloc (length+1);
((char *)buffer)[length] = 0;
SafeRead (f, buffer, length);
fclose (f);
*bufferptr = buffer;
return length;
}
/*
==============
SaveFile
==============
*/
void SaveFile (char *filename, void *buffer, int count)
{
FILE *f;
f = SafeOpenWrite (filename);
SafeWrite (f, buffer, count);
fclose (f);
}
void DefaultExtension (char *path, char *extension)
{
char *src;
//
// if path doesn't have a .EXT, append extension
// (extension should include the .)
//
src = path + strlen(path) - 1;
while (*src != PATHSEPERATOR && src != path)
{
if (*src == '.')
return; // it has an extension
src--;
}
strcat (path, extension);
}
void DefaultPath (char *path, char *basepath)
{
char temp[128];
if (path[0] == PATHSEPERATOR)
return; // absolute path location
strcpy (temp,path);
strcpy (path,basepath);
strcat (path,temp);
}
void StripFilename (char *path)
{
int length;
length = strlen(path)-1;
while (length > 0 && path[length] != PATHSEPERATOR)
length--;
path[length] = 0;
}
void StripExtension (char *path)
{
int length;
length = strlen(path)-1;
while (length > 0 && path[length] != '.')
{
length--;
if (path[length] == '/')
return; // no extension
}
if (length)
path[length] = 0;
}
/*
====================
Extract file parts
====================
*/
void ExtractFilePath (char *path, char *dest)
{
char *src;
src = path + strlen(path) - 1;
//
// back up until a \ or the start
//
while (src != path && *(src-1) != PATHSEPERATOR)
src--;
memcpy (dest, path, src-path);
dest[src-path] = 0;
}
void ExtractFileBase (char *path, char *dest)
{
char *src;
src = path + strlen(path) - 1;
//
// back up until a \ or the start
//
while (src != path && *(src-1) != PATHSEPERATOR)
src--;
while (*src && *src != '.')
{
*dest++ = *src++;
}
*dest = 0;
}
void ExtractFileExtension (char *path, char *dest)
{
char *src;
src = path + strlen(path) - 1;
//
// back up until a . or the start
//
while (src != path && *(src-1) != '.')
src--;
if (src == path)
{
*dest = 0; // no extension
return;
}
strcpy (dest,src);
}
/*
==============
ParseNum / ParseHex
==============
*/
int ParseHex (char *hex)
{
char *str;
int num;
num = 0;
str = hex;
while (*str)
{
num <<= 4;
if (*str >= '0' && *str <= '9')
num += *str-'0';
else if (*str >= 'a' && *str <= 'f')
num += 10 + *str-'a';
else if (*str >= 'A' && *str <= 'F')
num += 10 + *str-'A';
else
Error ("Bad hex number: %s",hex);
str++;
}
return num;
}
int ParseNum (char *str)
{
if (str[0] == '$')
return ParseHex (str+1);
if (str[0] == '0' && str[1] == 'x')
return ParseHex (str+2);
return atol (str);
}
/*
============================================================================
BYTE ORDER FUNCTIONS
============================================================================
*/
#ifdef _SGI_SOURCE
#define __BIG_ENDIAN__
#endif
#ifdef __BIG_ENDIAN__
short LittleShort (short l)
{
byte b1,b2;
b1 = l&255;
b2 = (l>>8)&255;
return (b1<<8) + b2;
}
short BigShort (short l)
{
return l;
}
int LittleLong (int l)
{
byte b1,b2,b3,b4;
b1 = l&255;
b2 = (l>>8)&255;
b3 = (l>>16)&255;
b4 = (l>>24)&255;
return ((int)b1<<24) + ((int)b2<<16) + ((int)b3<<8) + b4;
}
int BigLong (int l)
{
return l;
}
float LittleFloat (float l)
{
union {byte b[4]; float f;} in, out;
in.f = l;
out.b[0] = in.b[3];
out.b[1] = in.b[2];
out.b[2] = in.b[1];
out.b[3] = in.b[0];
return out.f;
}
float BigFloat (float l)
{
return l;
}
#else
short BigShort (short l)
{
byte b1,b2;
b1 = l&255;
b2 = (l>>8)&255;
return (b1<<8) + b2;
}
short LittleShort (short l)
{
return l;
}
int BigLong (int l)
{
byte b1,b2,b3,b4;
b1 = l&255;
b2 = (l>>8)&255;
b3 = (l>>16)&255;
b4 = (l>>24)&255;
return ((int)b1<<24) + ((int)b2<<16) + ((int)b3<<8) + b4;
}
int LittleLong (int l)
{
return l;
}
float BigFloat (float l)
{
union {byte b[4]; float f;} in, out;
in.f = l;
out.b[0] = in.b[3];
out.b[1] = in.b[2];
out.b[2] = in.b[1];
out.b[3] = in.b[0];
return out.f;
}
float LittleFloat (float l)
{
return l;
}
#endif
//=======================================================
// FIXME: byte swap?
// this is a 16 bit, non-reflected CRC using the polynomial 0x1021
// and the initial and final xor values shown below... in other words, the
// CCITT standard CRC used by XMODEM
#define CRC_INIT_VALUE 0xffff
#define CRC_XOR_VALUE 0x0000
static unsigned short crctable[256] =
{
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
};
void CRC_Init(unsigned short *crcvalue)
{
*crcvalue = CRC_INIT_VALUE;
}
void CRC_ProcessByte(unsigned short *crcvalue, byte data)
{
*crcvalue = (*crcvalue << 8) ^ crctable[(*crcvalue >> 8) ^ data];
}
unsigned short CRC_Value(unsigned short crcvalue)
{
return crcvalue ^ CRC_XOR_VALUE;
}
//=============================================================================
/*
============
CreatePath
============
*/
void CreatePath (char *path)
{
char *ofs, c;
for (ofs = path+1 ; *ofs ; ofs++)
{
c = *ofs;
if (c == '/' || c == '\\')
{ // create the directory
*ofs = 0;
Q_mkdir (path);
*ofs = c;
}
}
}
/*
============
CopyFile
Used to archive source files
============
*/
void CopyFile (char *from, char *to)
{
void *buffer;
int length;
length = LoadFile (from, &buffer);
CreatePath (to);
SaveFile (to, buffer, length);
free (buffer);
}

97
Tools/Source/cmdlib.h Normal file
View file

@ -0,0 +1,97 @@
// cmdlib.h
#ifndef __CMDLIB__
#define __CMDLIB__
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <ctype.h>
#include <time.h>
#include <stdarg.h>
#ifndef __BYTEBOOL__
#define __BYTEBOOL__
typedef enum {false, true} qboolean;
typedef unsigned char byte;
#endif
// the dec offsetof macro doesn't work very well...
#define myoffsetof(type,identifier) ((size_t)&((type *)0)->identifier)
// set these before calling CheckParm
extern int myargc;
extern char **myargv;
char *strupr (char *in);
char *strlower (char *in);
int Q_strncasecmp (char *s1, char *s2, int n);
int Q_strcasecmp (char *s1, char *s2);
void Q_getwd (char *out);
int filelength (FILE *f);
int FileTime (char *path);
void Q_mkdir (char *path);
extern char qdir[1024];
extern char gamedir[1024];
void SetQdirFromPath (char *path);
char *ExpandPath (char *path);
char *ExpandPathAndArchive (char *path);
double I_FloatTime (void);
void Error (char *error, ...);
int CheckParm (char *check);
FILE *SafeOpenWrite (char *filename);
FILE *SafeOpenRead (char *filename);
void SafeRead (FILE *f, void *buffer, int count);
void SafeWrite (FILE *f, void *buffer, int count);
int LoadFile (char *filename, void **bufferptr);
void SaveFile (char *filename, void *buffer, int count);
void DefaultExtension (char *path, char *extension);
void DefaultPath (char *path, char *basepath);
void StripFilename (char *path);
void StripExtension (char *path);
void ExtractFilePath (char *path, char *dest);
void ExtractFileBase (char *path, char *dest);
void ExtractFileExtension (char *path, char *dest);
int ParseNum (char *str);
short BigShort (short l);
short LittleShort (short l);
int BigLong (int l);
int LittleLong (int l);
float BigFloat (float l);
float LittleFloat (float l);
char *COM_Parse (char *data);
extern char com_token[1024];
extern qboolean com_eof;
char *copystring(char *s);
void CRC_Init(unsigned short *crcvalue);
void CRC_ProcessByte(unsigned short *crcvalue, byte data);
unsigned short CRC_Value(unsigned short crcvalue);
void CreatePath (char *path);
void CopyFile (char *from, char *to);
extern qboolean archive;
extern char archivedir[1024];
#endif

131
Tools/Source/pal2colormap.c Normal file
View file

@ -0,0 +1,131 @@
/*
PAL 2 COLORMAP SOURCECODE
The MIT License (MIT)
Copyright (c) 2016-2019 Marco "eukara" Hladik <marco at icculus.org>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <stdlib.h>
#define TGAHEADER 18
#define QPALSIZE 768
#define QCOLORSIZE 16384
/* sample a 24-bit RGB value to one of the colours on the existing 8-bit palette */
unsigned char
convert_24_to_8 (const unsigned char palette[768], const int rgb[3])
{
int i, j;
int best_index = -1;
int best_dist = 0;
for (i = 0; i < 256; i++) {
int dist = 0;
for (j = 0; j < 3; j++) {
/* note that we could use RGB luminosity bias for greater accuracy, but quake's colormap apparently didn't do this */
int d = abs(rgb[j] - palette[i * 3 + j]);
dist += d * d;
}
if (best_index == -1 || dist < best_dist) {
best_index = i;
best_dist = dist;
}
}
return (unsigned char) best_index;
}
void
process_pal2colormap(char *filename)
{
FILE *fLMP;
unsigned char pal_buff[QPALSIZE];
FILE *fTGA;
unsigned char colormap_buff[QCOLORSIZE];
short pal_loop, tga_loop;
struct stat pal_st;
int num_fullbrights = 0; /* the last 32 colours will be full bright */
int x, y, i;
fLMP = fopen(filename, "rb");
if (!fLMP) {
fprintf(stderr, "couldn't find %s\n", filename);
return;
}
/* There are no other types of palette lumps. Sorry */
stat(filename, &pal_st);
if (pal_st.st_size != QPALSIZE) {
fprintf(stderr, "invalid palette lump %s, skipping\n", filename);
return;
}
fread(pal_buff, 1, QPALSIZE, fLMP);
fclose(fLMP);
for ( x = 0; x < 256; x++ ) {
for ( y = 0; y < 64; y++ ) {
if ( x < 256 - num_fullbrights ) {
int rgb[3];
for ( i = 0; i < 3; i++ ) {
/* divide by 32, rounding to nearest integer */
rgb[i] = ( pal_buff[x * 3 + i] * ( 63 - y ) + 16 ) >> 5;
if ( rgb[i] > 255 )
rgb[i] = 255;
}
colormap_buff[y * 256 + x] = convert_24_to_8( pal_buff, rgb );
} else {
/* this colour is a fullbright, just keep the original colour */
colormap_buff[y * 256 + x] = x;
}
}
}
fTGA = fopen("colormap.lmp", "w+b");
fwrite(colormap_buff, 1, QCOLORSIZE, fTGA);
fclose(fTGA);
}
int
main(int argc, char *argv[])
{
int c;
if (argc <= 1) {
fprintf(stderr, "usage: pal2colormap [file.lmp ...]\n");
return 1;
}
for (c = 1; c < argc; c++)
process_pal2colormap(argv[c]);
return 0;
}

91
Tools/Source/pal2pal.c Normal file
View file

@ -0,0 +1,91 @@
/*
PAL 2 TGA SOURCECODE
The MIT License (MIT)
Copyright (c) 2016-2019 Marco "eukara" Hladik <marco at icculus.org>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#define TGAHEADER 18
#define QPALSIZE 768
#define T2PVERSION "1.1"
void process_pal2tga(char *filename)
{
FILE *fLMP;
unsigned char pal_buff[QPALSIZE];
FILE *fTGA;
unsigned char tga_buff[QPALSIZE + TGAHEADER];
short pal_loop, tga_loop;
struct stat pal_st;
fLMP = fopen(filename, "rb");
if (!fLMP) {
fprintf(stderr, "couldn't find %s\n", filename);
return;
}
/* There are no other types of palette lumps. Sorry */
stat(filename, &pal_st);
if (pal_st.st_size != QPALSIZE) {
fprintf(stderr, "invalid palette lump %s, skipping\n", filename);
return;
}
fread(pal_buff, 1, QPALSIZE, fLMP);
fclose(fLMP);
/* FIXME: We assume too much!
* Save the output to FILENAME.tga
* This is ugly when the input name has no .lmp extension.
* But who's going to try that. ...right? */
filename[strlen(filename)-3] = 'p';
filename[strlen(filename)-2] = 'a';
filename[strlen(filename)-1] = 'l';
fprintf(stdout, "writing %s\n", filename);
fTGA = fopen(filename, "w");
fprintf(fTGA, "JASC-PAL\r\n");
fprintf(fTGA, "0100\r\n");
fprintf(fTGA, "256\r\n");
for (int i = 0; i < QPALSIZE; i+=3)
fprintf(fTGA, "%d %d %d\r\n", pal_buff[i], pal_buff[i+1], pal_buff[i+2]);
fclose(fTGA);
}
int main(int argc, char *argv[])
{
int c;
if (argc <= 1) {
fprintf(stderr, "usage: pal2tga [file.lmp ...]\n");
return 1;
}
for (c = 1; c < argc; c++)
process_pal2tga(argv[c]);
return 0;
}

179
Tools/Source/qfiles.c Normal file
View file

@ -0,0 +1,179 @@
#include "cmdlib.h"
#define MAX_FILES 4096
#define MAX_DATA_PATH 512
char precache_files[MAX_FILES][MAX_DATA_PATH];
int precache_files_block[MAX_FILES];
int numfiles;
typedef struct
{
char name[56];
int filepos, filelen;
} packfile_t;
typedef struct
{
char id[4];
int dirofs;
int dirlen;
} packheader_t;
packfile_t pfiles[4096], *pf;
FILE *packhandle;
int packbytes;
/*
===========
PackFile
Copy a file into the pak file
===========
*/
void PackFile (char *src, char *name)
{
FILE *in;
int remaining, count;
char buf[4096];
if ( (byte *)pf - (byte *)pfiles > sizeof(pfiles) )
Error ("Too many files in pak file");
in = SafeOpenRead (src);
remaining = filelength (in);
pf->filepos = LittleLong (ftell (packhandle));
pf->filelen = LittleLong (remaining);
strcpy (pf->name, name);
printf ("%64s : %7i\n", pf->name, remaining);
packbytes += remaining;
while (remaining)
{
if (remaining < sizeof(buf))
count = remaining;
else
count = sizeof(buf);
SafeRead (in, buf, count);
SafeWrite (packhandle, buf, count);
remaining -= count;
}
fclose (in);
pf++;
}
/*
===========
CopyQFiles
===========
*/
void CopyQFiles (int blocknum)
{
int i, p;
char srcfile[1024];
char destfile[1024];
char name[1024];
packheader_t header;
int dirlen;
unsigned short crc;
// create a pak file
pf = pfiles;
sprintf (destfile, "%spak%i.pak", gamedir, blocknum);
packhandle = SafeOpenWrite (destfile);
SafeWrite (packhandle, &header, sizeof(header));
blocknum++;
for (i=0 ; i<numfiles ; i++)
{
if (precache_files_block[i] != blocknum)
continue;
sprintf (srcfile,"%s%s",gamedir, precache_files[i]);
PackFile (srcfile, precache_files[i]);
}
header.id[0] = 'P';
header.id[1] = 'A';
header.id[2] = 'C';
header.id[3] = 'K';
dirlen = (byte *)pf - (byte *)pfiles;
header.dirofs = LittleLong(ftell (packhandle));
header.dirlen = LittleLong(dirlen);
SafeWrite (packhandle, pfiles, dirlen);
fseek (packhandle, 0, SEEK_SET);
SafeWrite (packhandle, &header, sizeof(header));
fclose (packhandle);
// do a crc of the file
CRC_Init (&crc);
for (i=0 ; i<dirlen ; i++)
CRC_ProcessByte (&crc, ((byte *)pfiles)[i]);
i = pf - pfiles;
printf ("%i files packed in %i bytes (%i crc)\n",i, packbytes, crc);
}
/*
=============
ReadFiles
=============
*/
int ReadFiles (void)
{
FILE *f;
int i;
f = SafeOpenRead ("files.dat");
fscanf(f, "%i\n", &numfiles);
for (i = 0; i < numfiles ; i++) {
fscanf (f, "%i %s\n", &precache_files_block[i], precache_files[i]);
printf("%s\n", precache_files[i]);
}
fclose (f);
printf ("%i files\n", numfiles);
}
/*
=============
main
=============
*/
int main (int argc, char **argv)
{
if (argc == 1)
{
printf ("qfiles -pak <0 / 1> : build a .pak file\n");
exit (1);
}
SetQdirFromPath ("");
ReadFiles ();
if (!strcmp (argv[1], "-pak"))
{
CopyQFiles (atoi(argv[2]));
}
else
Error ("unknown command: %s", argv[1]);
return 0;
}

262
Tools/Source/tga2lmp.c Normal file
View file

@ -0,0 +1,262 @@
/*
TGA 2 LMP SOURCECODE
The MIT License (MIT)
Copyright (c) 2016-2019 Marco "eukara" Hladik <marco at icculus.org>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <string.h>
#define TGAHEADER 18
#define QPALSIZE 768
#define VERSION "1.1"
typedef unsigned char byte;
typedef union {
int rgba:32;
struct {
byte b:8;
byte g:8;
byte r:8;
byte a:8;
} u;
} pixel_t;
byte cust_pal[QPALSIZE]; /* custom 256 color palette */
/* fallback palette from Quake, put into the Public Domain by John Carmack */
pixel_t pal_fallb[256] = {
0x000000,0x0f0f0f,0x1f1f1f,0x2f2f2f,0x3f3f3f,0x4b4b4b,0x5b5b5b,0x6b6b6b,
0x7b7b7b,0x8b8b8b,0x9b9b9b,0xababab,0xbbb,0xcbcbcb,0xdbdbdb,0xebebeb,
0x0f0b07,0x170f0b,0x1f170b,0x271b0f,0x2f2313,0x372b17,0x3f2f17,0x4b371b,
0x533b1b,0x5b431f,0x634b1f,0x6b531f,0x73571f,0x7b5f23,0x836723,0x8f6f23,
0x0b0b0f,0x13131b,0x1b1b27,0x272733,0x2f2f3f,0x37374b,0x3f3f57,0x474767,
0x4f4f73,0x5b5b7f,0x63638b,0x6b6b97,0x7373a3,0x7b7baf,0x8383b,0x8b8bcb,
0x000000,0x070700,0x0b0b00,0x131300,0x1b1b00,0x232300,0x2b2b07,0x2f2f07,
0x373707,0x3f3f07,0x474707,0x4b4b0b,0x53530b,0x5b5b0b,0x63630b,0x6b6b0f,
0x070000,0x0f0000,0x170000,0x1f0000,0x270000,0x2f0000,0x370000,0x3f0000,
0x470000,0x4f0000,0x570000,0x5f0000,0x670000,0x6f0000,0x770000,0x7f0000,
0x131300,0x1b1b00,0x232300,0x2f2b00,0x372f00,0x433700,0x4b3b07,0x574307,
0x5f4707,0x6b4b0b,0x77530f,0x835713,0x8b5b13,0x975f1b,0xa3631f,0xaf6723,
0x231307,0x2f170b,0x3b1f0f,0x4b2313,0x572b17,0x632f1f,0x733723,0x7f3b2b,
0x8f4333,0x9f4f33,0xaf632f,0xbf772f,0xcf8f2b,0xdfab27,0xefcb1f,0xfff31b,
0x0b0700,0x1b1300,0x2b230f,0x372b13,0x47331b,0x533723,0x633f2b,0x6f4733,
0x7f533f,0x8b5f47,0x9b6b53,0xa77b5f,0xb7876b,0xc3937b,0xd3a38b,0xe3b397,
0xab8ba3,0x9f7f97,0x937387,0x8b677b,0x7f5b6f,0x775363,0x6b4b57,0x5f3f4b,
0x573743,0x4b2f37,0x43272f,0x371f23,0x2b171b,0x231313,0x170b0b,0x0f0707,
0xb739f,0xaf6b8f,0xa35f83,0x975777,0x8b4f6b,0x7f4b5f,0x734353,0x6b3b4b,
0x5f333f,0x532b37,0x47232b,0x3b1f23,0x2f171b,0x231313,0x170b0b,0x0f0707,
0xdbc3b,0xcb3a7,0xbfa39b,0xaf978b,0xa3877b,0x977b6f,0x876f5f,0x7b6353,
0x6b5747,0x5f4b3b,0x533f33,0x433327,0x372b1f,0x271f17,0x1b130f,0x0f0b07,
0x6f837b,0x677b6f,0x5f7367,0x576b5f,0x4f6357,0x475b4f,0x3f5347,0x374b3f,
0x2f4337,0x2b3b2f,0x233327,0x1f2b1f,0x172317,0x0f1b13,0x0b130b,0x070b07,
0xfff31b,0xefdf17,0xdbcb13,0xcb70f,0xba70f,0xab970b,0x9b8307,0x8b7307,
0x7b6307,0x6b5300,0x5b4700,0x4b3700,0x3b2b00,0x2b1f00,0x1b0f00,0x0b0700,
0x0000ff,0x0b0bef,0x1313df,0x1b1bcf,0x2323bf,0x2b2baf,0x2f2f9f,0x2f2f8f,
0x2f2f7f,0x2f2f6f,0x2f2f5f,0x2b2b4f,0x23233f,0x1b1b2f,0x13131f,0x0b0b0f,
0x2b0000,0x3b0000,0x4b0700,0x5f0700,0x6f0f00,0x7f1707,0x931f07,0xa3270b,
0xb7330f,0xc34b1b,0xcf632b,0xdb7f3b,0xe3974f,0xe7ab5f,0xefbf77,0xf7d38b,
0xa77b3b,0xb79b37,0xc7c337,0xe7e357,0x7fbfff,0xabe7ff,0xd7ffff,0x670000,
0x8b0000,0xb30000,0xd70000,0xff0000,0xfff393,0xfff7c7,0xffffff,0x9f5b53
};
byte c_last; /* last palette index we chose */
pixel_t last_px; /* last RGB value we chose */
/* quickly translate 24 bit RGB value to our palette */
byte pal24to8(byte r, byte g, byte b)
{
pixel_t px;
byte c_red, c_green, c_blue, c_best, l;
int dist, best;
/* compare the last with the current pixel color for speed */
if ((last_px.u.r == r) && (last_px.u.g == g) && (last_px.u.b == b)) {
return c_last;
}
px.u.r = last_px.u.r = r;
px.u.g = last_px.u.g = g;
px.u.b = last_px.u.b = b;
best = 255 + 255 + 255;
c_last = c_best = c_red = c_green = c_blue = 255;
l = 0;
while (1) {
if ((cust_pal[l * 3 + 0] == r) && (cust_pal[l * 3 + 0] == g)
&& (cust_pal[l * 3 + 0] == b))
{
last_px.u.r = cust_pal[l * 3 + 0];
last_px.u.g = cust_pal[l * 3 + 1];
last_px.u.b = cust_pal[l * 3 + 2];
c_last = l;
return l;
}
c_red = abs(cust_pal[l * 3 + 0] - px.u.r);
c_green = abs(cust_pal[l * 3 + 1] - px.u.g);
c_blue = abs(cust_pal[l * 3 + 2] - px.u.b);
dist = (c_red + c_green + c_blue);
/* is it better than the last? */
if (dist < best) {
best = dist;
c_best = l;
}
if (l != 255) {
l++;
} else {
break;
}
}
c_last = c_best;
return c_best;
}
void process_tga2lmp(char *filename)
{
FILE *fLMP; /* file Ident of the LUMP */
byte *lmp_buff; /* buffer of the LUMP */
FILE *fTGA; /* file Ident of the TARGA */
byte tga_header[TGAHEADER]; /* TARGA Header (18 bytes usually) */
byte *tga_buff; /* 24bit gR input buffer + TGA header */
int col, row, done; /* used for the sorting loop */
int img_w, img_h; /* dimensions */
/* load the TARGA */
fTGA = fopen(filename, "rb");
/* check whether the file exists or not */
if (!fTGA) {
fprintf(stderr, "couldn't find %s\n", filename);
return;
}
/* put the TARGA header into the buffer for validation */
fread(tga_header, 1, TGAHEADER, fTGA);
/* only allow uncompressed, 24bit TARGAs */
if (tga_header[2] != 2) {
fprintf(stderr, "%s should be an uncompressed, RGB image\n", filename);
return;
}
if (tga_header[16] != 24) {
fprintf(stderr, "%s is not 24 bit in depth\n", filename);
return;
}
/* read the resolution into an int (TGA uses shorts for the dimensions) */
img_w = (tga_header[12]) | (tga_header[13] << 8);
img_h = (tga_header[14]) | (tga_header[15] << 8);
tga_buff = malloc(img_w * img_h * 3);
if (tga_buff == NULL) {
fprintf(stderr, "mem alloc failed at %d bytes\n", (img_w * img_h * 3));
return;
}
/* skip to after the TARGA HEADER... and then read the buffer */
fseek(fTGA, TGAHEADER, SEEK_SET);
fread(tga_buff, 1, img_w * img_h * 3, fTGA);
fclose(fTGA);
/* start generating the lump data */
lmp_buff = malloc(img_w * img_h + 8);
if (lmp_buff == NULL) {
fprintf(stderr, "mem alloc failed at %d bytes\n", (img_w * img_h + 8));
return;
}
/* split the integer dimensions into 4 bytes */
lmp_buff[3] = (img_w >> 24) & 0xFF;
lmp_buff[2] = (img_w >> 16) & 0xFF;
lmp_buff[1] = (img_w >> 8) & 0xFF;
lmp_buff[0] = img_w & 0xFF;
lmp_buff[7] = (img_h >> 24) & 0xFF;
lmp_buff[6] = (img_h >> 16) & 0xFF;
lmp_buff[5] = (img_h >> 8) & 0xFF;
lmp_buff[4] = img_h & 0xFF;
/* translate the rgb values into indexed entries and flip */
done = 0;
for (row = img_h - 1; row >= 0; row--) {
for (col = 0; col < img_w; col++) {
lmp_buff[8 + done] =
pal24to8(tga_buff[((row * (img_w * 3)) + (col * 3 + 2))],
tga_buff[((row * (img_w * 3)) + (col * 3 + 1))],
tga_buff[((row * (img_w * 3)) + (col * 3 + 0))]);
done++;
}
}
/* FIXME: We assume too much!
* Save the output to FILENAME.tga
* This is ugly when the input name has no .lmp extension.
* But who's going to try that. ...right? */
filename[strlen(filename)-3] = 'l';
filename[strlen(filename)-2] = 'm';
filename[strlen(filename)-1] = 'p';
fprintf(stdout, "writing %s\n", filename);
fLMP = fopen(filename, "w+b");
fwrite(lmp_buff, 1, (img_w * img_h) + 8, fLMP);
fclose(fLMP);
}
int main(int argc, char *argv[])
{
int c;
short p;
FILE *fPAL;
if (argc <= 1) {
fprintf(stderr, "usage: tga2lmp [file.tga ...]\n");
return 1;
}
fPAL = fopen("palette.lmp", "rb");
if (!fPAL) {
fprintf(stdout, "no palette.lmp found, using builtin palette.\n");
for (p = 0; p < 256; p++) {
cust_pal[p * 3 + 0] = pal_fallb[p].u.r;
cust_pal[p * 3 + 1] = pal_fallb[p].u.g;
cust_pal[p * 3 + 2] = pal_fallb[p].u.b;
}
} else {
fprintf(stdout, "custom palette.lmp found\n");
fread(cust_pal, 1, QPALSIZE, fPAL);
fclose(fPAL);
}
for (c = 1; c < argc; c++)
process_tga2lmp(argv[c]);
return 0;
}

109
Tools/Source/tga2pal.c Normal file
View file

@ -0,0 +1,109 @@
/*
TGA 2 PAL SOURCECODE
The MIT License (MIT)
Copyright (c) 2016-2019 Marco "eukara" Hladik <marco at icculus.org>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include <stdio.h>
#include <string.h>
#define TGAHEADER 18
#define QPALSIZE 768
void process_tga2pal(char *filename)
{
FILE *fTGA;
unsigned char tga_header[TGAHEADER];
unsigned char tga_buff[QPALSIZE];
FILE *fLMP;
unsigned char pal_buff[QPALSIZE];
short loop_pal, loop_tga;
fTGA = fopen(filename, "rb");
if (!fTGA) {
fprintf(stderr, "couldn't find %s\n", filename);
return;
}
/* Put the TARGA header into the buffer for validation */
fread(tga_header, 1, TGAHEADER, fTGA);
/* only allow uncompressed, 24bit TARGAs */
if (tga_header[2] != 2) {
fprintf(stderr, "%s should be an uncompressed, RGB image\n", filename);
return;
}
if (tga_header[16] != 24) {
fprintf(stderr, "%s is not 24 bit in depth\n", filename);
return;
}
if (tga_header[12] != 16 || tga_header[14] != 16) {
fprintf(stderr, "%s is not a 16x16 image\n", filename);
return;
}
/* Skip to after the TARGA HEADER... and then read the buffer */
fseek(fTGA, 18, SEEK_SET);
fread(tga_buff, 1, QPALSIZE, fTGA);
fclose(fTGA);
/* TARGAs are flipped in an odd way,
* so we gotta do the sorting dance */
for(loop_tga = 15; loop_tga >= 0; loop_tga--) {
for(loop_pal = 0; loop_pal < 16; loop_pal++) {
pal_buff[((15 - loop_tga) * 48) + (loop_pal * 3) + 0] =
tga_buff[(loop_tga * 48) + (loop_pal * 3) + 2];
pal_buff[((15 - loop_tga) * 48) + (loop_pal * 3) + 1] =
tga_buff[(loop_tga * 48) + (loop_pal * 3) + 1];
pal_buff[((15 - loop_tga) * 48) + (loop_pal * 3) + 2] =
tga_buff[(loop_tga * 48) + (loop_pal * 3) + 0];
}
}
/* FIXME: We assume too much!
* Save the output to FILENAME.tga
* This is ugly when the input name has no .lmp extension.
* But who's going to try that. ...right? */
filename[strlen(filename)-3] = 'l';
filename[strlen(filename)-2] = 'm';
filename[strlen(filename)-1] = 'p';
fprintf(stdout, "writing %s\n", filename);
fLMP = fopen(filename, "w+b");
fwrite(pal_buff, 1, QPALSIZE, fLMP);
fclose(fLMP);
}
int main(int argc, char *argv[])
{
int c;
if (argc <= 1) {
fprintf(stderr, "usage: tga2pal [file.tga ...]\n");
return 1;
}
for (c = 1; c < argc; c++)
process_tga2pal(argv[c]);
return 0;
}

39
Tools/build_filesdat.sh Executable file
View file

@ -0,0 +1,39 @@
#!/bin/sh
# ensure we use the tools provided in ./bin
export PATH="$(pwd)/Tools:$PATH"
CWD=$(pwd)
# build src/files.dat
dump_filelist()
{
FILE_F="$CWD/$1/src/files_f.dat"
FILE="$CWD/$1/src/files.dat"
rm -v "$FILE"
cd "$CWD/$1/src/"
grep -r Precache_Sound\(\ \" | cut -d '"' -f 2 | awk '{ print "sound/"$1; }' > "$FILE_F"
grep -r Precache_Model\(\ \" | cut -d '"' -f 2 >> "$FILE_F"
grep -r Precache_File\(\ \" | cut -d '"' -f 2 >> "$FILE_F"
# print the counter for sounds
FIL_COUNT=$(cat "$FILE_F" | wc -l)
if [ -z "$FIL_COUNT" ]
then
FIL_COUNT="0"
fi
# misc files
echo "$FIL_COUNT" >> "$FILE"
cat "$FILE_F" | while read LINE
do
echo "1 $LINE" >> "$FILE"
done
rm -v "$FILE_F"
}
dump_filelist $1

17
Tools/build_gfx.sh Normal file
View file

@ -0,0 +1,17 @@
#!/bin/sh
# ensure we use the tools provided in ./bin
export PATH="$(pwd)/Tools:$PATH"
CWD=$(pwd)
# gfx lumps (built first)
build_gfx()
{
echo "building gfx/*.lmp"
cd "$CWD/$1/gfxsrc/"
ls | grep -v palette | grep "\.tga" | xargs -n 1 tga2lmp
}
build_gfx $1

32
Tools/build_maps.sh Executable file
View file

@ -0,0 +1,32 @@
#!/bin/sh
if [ $# -lt 1 ]
then
exit 1
fi
GAMEDIR="$1"
CWD=$(pwd)
if [ -d "$CWD/$GAMEDIR/mapsrc/" ]
then
OLDDIR="$(pwd)"
find "$GAMEDIR/mapsrc/" -name "*.map" | while read QEDMAP
do
cd "$(dirname "$QEDMAP")"
MAPFILE="$(basename "$QEDMAP")"
PATH="$PATH:$OLDDIR" qbsp -wadpath "$CWD/$GAMEDIR" "$MAPFILE"
PATH="$PATH:$OLDDIR" qvis "$MAPFILE"
PATH="$PATH:$OLDDIR" qlight -extra4 "$MAPFILE"
cd "$OLDDIR"
done
find "$GAMEDIR/mapsrc/" -name "*.bsp" | while read MAPFILE
do
NEWPATH="$(echo "$MAPFILE" | sed 's/\/mapsrc\//\/maps\//g')"
NEWPATHDIR=$(dirname "$NEWPATH")
mkdir -p "$NEWPATHDIR"
mv -v "$MAPFILE" "$NEWPATH"
done
fi

21
Tools/build_models.sh Executable file
View file

@ -0,0 +1,21 @@
#!/bin/sh
# ensure we use the tools provided in ./bin
export PATH="$(pwd)/Tools:$PATH"
CWD=$(pwd)
build_models()
{
cd "$CWD/$1/modelsrc/"
mkdir -p "$CWD/$1/progs/"
find "$CWD/$1/modelsrc/" -name "*.qc" | while read LINE
do
DIR=$(dirname "$LINE")
cd "$DIR"
iqmtool $(basename "$LINE")
done
}
build_models $1

27
Tools/build_wads.sh Executable file
View file

@ -0,0 +1,27 @@
#!/bin/sh
# ensure we use the tools provided in root
export PATH="$(pwd):$PATH"
CWD=$(pwd)
# texture wads
build_wads()
{
echo "building texturesrc/*.wad"
cd "$CWD/$1/texturesrc/"
# will make a .wad out of every sub directory.
find ./ -type d -maxdepth 1 | while read WADDIR
do
DIRNAME=$(basename "$WADDIR")
if [ ! "$DIRNAME" = "." ]
then
echo "$DIRNAME"
imgtool --palette ../gfx/palette.lmp --genwad2 ../"$DIRNAME".wad ./"$DIRNAME"
fi
done
}
build_wads $1

24
Tools/make_map.sh Executable file
View file

@ -0,0 +1,24 @@
#!/bin/sh
if [ $# -lt 1 ]
then
exit 1
fi
CWD="$(pwd)"
GAMEDIR="$1"
TARGET="$2"
MAPFILE=$(echo "$TARGET" | sed 's/\.bsp/\.map/g' | sed 's/\/maps\//\/mapsrc\//g')
MAPOUT=$(echo "$TARGET" | sed 's/\/maps\//\/mapsrc\//g')
OLDDIR="$(pwd)"
if [ -d "$CWD/$GAMEDIR/mapsrc/" ]
then
cd "$(dirname "$MAPFILE")"
MAPFILE="$(basename "$MAPFILE")"
PATH="$PATH:$OLDDIR" qbsp -wadpath "$CWD/$GAMEDIR" "$MAPFILE"
PATH="$PATH:$OLDDIR" qvis "$MAPFILE"
PATH="$PATH:$OLDDIR" qlight -extra4 "$MAPFILE"
cd "$OLDDIR"
mv -v "$MAPOUT" "$TARGET"
fi

15
data1/src/files.qc Normal file
View file

@ -0,0 +1,15 @@
void main( void ) {
/* all the files that Hexen II needs to boot. */
ncEngine::Precache_File( "maps/demo1.bsp" );
ncEngine::Precache_File( "raven/menu1.wav" );
ncEngine::Precache_File( "raven/menu2.wav" );
ncEngine::Precache_File( "raven/menu3.wav" );
ncEngine::Precache_File( "misc/barmovup.wav" );
ncEngine::Precache_File( "misc/barmovdn.wav" );
ncEngine::Precache_File( "misc/invmove.wav" );
ncEngine::Precache_File( "misc/invuse.wav" );
ncEngine::Precache_File( "progs.dat");
ncEngine::Precache_File2( "gfx/pop.lmp" );
ncEngine::Precache_File( "gfx.wad" );
ncEngine::Precache_File( "default.cfg" );
}

View file

@ -20,4 +20,4 @@ void Precaches(void)
INIT_ITEM(H2Flight) INIT_ITEM(H2Flight)
INIT_ITEM(H2CubeOfForce) INIT_ITEM(H2CubeOfForce)
INIT_ITEM(H2Invincibility) INIT_ITEM(H2Invincibility)
} }

View file

@ -24,4 +24,5 @@ items/torch.qc
rules.qc rules.qc
init.qc init.qc
#endlist files.qc
#endlist

16
data1/src/rules.qc Normal file
View file

@ -0,0 +1,16 @@
class H2Rules:ncRules {
void H2Rules(void);
virtual void PlayerFinishesJoining( ncPlayer );
};
void H2Rules::H2Rules(void) {
}
void H2Rules::PlayerFinishesJoining( ncPlayer ourPlayer ) {
ourPlayer.hud.SetHealth(100);
/* place them somewhere into the world */
super::PlayerFinishesJoining( ourPlayer );
}

BIN
id1/gfxsrc/palette.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

View file

@ -7,3 +7,5 @@ float WEAPON_GRENADE_LAUNCHER = 16;
float WEAPON_ROCKET_LAUNCHER = 32; float WEAPON_ROCKET_LAUNCHER = 32;
float WEAPON_LIGHTNING = 64; float WEAPON_LIGHTNING = 64;
float WEAPON_EXTRA_WEAPON = 128; float WEAPON_EXTRA_WEAPON = 128;
#include "player.qh"

70
id1/src/files.qc Normal file
View file

@ -0,0 +1,70 @@
void main( void ) {
/* all the files that DOSQuake needs to boot. */
ncEngine::Precache_File( "progs.dat");
ncEngine::Precache_File( "quake.rc" );
ncEngine::Precache_File( "gfx/palette.lmp" );
ncEngine::Precache_File( "gfx/colormap.lmp" );
ncEngine::Precache_File( "gfx/complete.lmp" );
ncEngine::Precache_File( "gfx/inter.lmp" );
ncEngine::Precache_File( "gfx/ranking.lmp" );
ncEngine::Precache_File( "gfx/vidmodes.lmp" );
ncEngine::Precache_File( "gfx/finale.lmp" );
ncEngine::Precache_File( "gfx/conback.lmp" );
ncEngine::Precache_File( "gfx/qplaque.lmp" );
ncEngine::Precache_File( "gfx/menudot1.lmp" );
ncEngine::Precache_File( "gfx/menudot2.lmp" );
ncEngine::Precache_File( "gfx/menudot3.lmp" );
ncEngine::Precache_File( "gfx/menudot4.lmp" );
ncEngine::Precache_File( "gfx/menudot5.lmp" );
ncEngine::Precache_File( "gfx/menudot6.lmp" );
ncEngine::Precache_File( "gfx/menuplyr.lmp" );
ncEngine::Precache_File( "gfx/bigbox.lmp" );
ncEngine::Precache_File( "gfx/dim_modm.lmp" );
ncEngine::Precache_File( "gfx/dim_drct.lmp" );
ncEngine::Precache_File( "gfx/dim_ipx.lmp" );
ncEngine::Precache_File( "gfx/dim_tcp.lmp" );
ncEngine::Precache_File( "gfx/dim_mult.lmp" );
ncEngine::Precache_File( "gfx/mainmenu.lmp" );
ncEngine::Precache_File( "gfx/box_tl.lmp" );
ncEngine::Precache_File( "gfx/box_tm.lmp" );
ncEngine::Precache_File( "gfx/box_tr.lmp" );
ncEngine::Precache_File( "gfx/box_ml.lmp" );
ncEngine::Precache_File( "gfx/box_mm.lmp" );
ncEngine::Precache_File( "gfx/box_mm2.lmp" );
ncEngine::Precache_File( "gfx/box_mr.lmp" );
ncEngine::Precache_File( "gfx/box_bl.lmp" );
ncEngine::Precache_File( "gfx/box_bm.lmp" );
ncEngine::Precache_File( "gfx/box_br.lmp" );
ncEngine::Precache_File( "gfx/sp_menu.lmp" );
ncEngine::Precache_File( "gfx/ttl_sgl.lmp" );
ncEngine::Precache_File( "gfx/ttl_main.lmp" );
ncEngine::Precache_File( "gfx/ttl_cstm.lmp" );
ncEngine::Precache_File( "gfx/mp_menu.lmp" );
ncEngine::Precache_File( "gfx/netmen1.lmp" );
ncEngine::Precache_File( "gfx/netmen2.lmp" );
ncEngine::Precache_File( "gfx/netmen3.lmp" );
ncEngine::Precache_File( "gfx/netmen4.lmp" );
ncEngine::Precache_File( "gfx/netmen5.lmp" );
ncEngine::Precache_File( "gfx/sell.lmp" );
ncEngine::Precache_File( "gfx/help0.lmp" );
ncEngine::Precache_File( "gfx/help1.lmp" );
ncEngine::Precache_File( "gfx/help2.lmp" );
ncEngine::Precache_File( "gfx/help3.lmp" );
ncEngine::Precache_File( "gfx/help4.lmp" );
ncEngine::Precache_File( "gfx/help5.lmp" );
ncEngine::Precache_File( "gfx/pause.lmp" );
ncEngine::Precache_File( "gfx/loading.lmp" );
ncEngine::Precache_File( "gfx/p_option.lmp" );
ncEngine::Precache_File( "gfx/p_load.lmp" );
ncEngine::Precache_File( "gfx/p_save.lmp" );
ncEngine::Precache_File( "gfx/p_multi.lmp" );
ncEngine::Precache_Sound( "misc/menu1.wav" );
ncEngine::Precache_Sound( "misc/menu2.wav" );
ncEngine::Precache_Sound( "misc/menu3.wav" );
ncEngine::Precache_Sound( "ambience/water1.wav" );
ncEngine::Precache_Sound( "ambience/wind2.wav" );
ncEngine::Precache_File( "maps/start.bsp" );
ncEngine::Precache_File2( "gfx/pop.lmp" );
ncEngine::Precache_File( "gfx.wad" );
ncEngine::Precache_File( "default.cfg" );
}

View file

@ -17,4 +17,4 @@ void Precaches(void)
INIT_ITEM( Q1RocketLauncher ) INIT_ITEM( Q1RocketLauncher )
INIT_ITEM( Q1Lightning ) INIT_ITEM( Q1Lightning )
INIT_ITEM( Q1Quad ) INIT_ITEM( Q1Quad )
} }

146
id1/src/player.qh Normal file
View file

@ -0,0 +1,146 @@
enum
{
playerAnim_axrun1 = 0,
playerAnim_axrun2,
playerAnim_axrun3,
playerAnim_axrun4,
playerAnim_axrun5,
playerAnim_axrun6,
playerAnim_rockrun1,
playerAnim_rockrun2,
playerAnim_rockrun3,
playerAnim_rockrun4,
playerAnim_rockrun5,
playerAnim_rockrun6,
playerAnim_stand1,
playerAnim_stand2,
playerAnim_stand3,
playerAnim_stand4,
playerAnim_stand5,
playerAnim_axstnd1,
playerAnim_axstnd2,
playerAnim_axstnd3,
playerAnim_axstnd4,
playerAnim_axstnd5,
playerAnim_axstnd6,
playerAnim_axstnd7,
playerAnim_axstnd8,
playerAnim_axstnd9,
playerAnim_axstnd10,
playerAnim_axstnd11,
playerAnim_axstnd12,
playerAnim_axpain1,
playerAnim_axpain2,
playerAnim_axpain3,
playerAnim_axpain4,
playerAnim_axpain5,
playerAnim_axpain6,
playerAnim_pain1,
playerAnim_pain2,
playerAnim_pain3,
playerAnim_pain4,
playerAnim_pain5,
playerAnim_pain6,
playerAnim_axdeth1,
playerAnim_axdeth2,
playerAnim_axdeth3,
playerAnim_axdeth4,
playerAnim_axdeth5,
playerAnim_axdeth6,
playerAnim_axdeth7,
playerAnim_axdeth8,
playerAnim_axdeth9,
playerAnim_deatha1,
playerAnim_deatha2,
playerAnim_deatha3,
playerAnim_deatha4,
playerAnim_deatha5,
playerAnim_deatha6,
playerAnim_deatha7,
playerAnim_deatha8,
playerAnim_deatha9,
playerAnim_deatha10,
playerAnim_deatha11,
playerAnim_deathb1,
playerAnim_deathb2,
playerAnim_deathb3,
playerAnim_deathb4,
playerAnim_deathb5,
playerAnim_deathb6,
playerAnim_deathb7,
playerAnim_deathb8,
playerAnim_deathb9,
playerAnim_deathc1,
playerAnim_deathc2,
playerAnim_deathc3,
playerAnim_deathc4,
playerAnim_deathc5,
playerAnim_deathc6,
playerAnim_deathc7,
playerAnim_deathc8,
playerAnim_deathc9,
playerAnim_deathc10,
playerAnim_deathc11,
playerAnim_deathc12,
playerAnim_deathc13,
playerAnim_deathc14,
playerAnim_deathc15,
playerAnim_deathd1,
playerAnim_deathd2,
playerAnim_deathd3,
playerAnim_deathd4,
playerAnim_deathd5,
playerAnim_deathd6,
playerAnim_deathd7,
playerAnim_deathd8,
playerAnim_deathd9,
playerAnim_deathe1,
playerAnim_deathe2,
playerAnim_deathe3,
playerAnim_deathe4,
playerAnim_deathe5,
playerAnim_deathe6,
playerAnim_deathe7,
playerAnim_deathe8,
playerAnim_deathe9,
playerAnim_nailatt1,
playerAnim_nailatt2,
playerAnim_light1,
playerAnim_light2,
playerAnim_rockatt1,
playerAnim_rockatt2,
playerAnim_rockatt3,
playerAnim_rockatt4,
playerAnim_rockatt5,
playerAnim_rockatt6,
playerAnim_shotatt1,
playerAnim_shotatt2,
playerAnim_shotatt3,
playerAnim_shotatt4,
playerAnim_shotatt5,
playerAnim_shotatt6,
playerAnim_axatt1,
playerAnim_axatt2,
playerAnim_axatt3,
playerAnim_axatt4,
playerAnim_axatt5,
playerAnim_axatt6,
playerAnim_axattb1,
playerAnim_axattb2,
playerAnim_axattb3,
playerAnim_axattb4,
playerAnim_axattb5,
playerAnim_axattb6,
playerAnim_axattc1,
playerAnim_axattc2,
playerAnim_axattc3,
playerAnim_axattc4,
playerAnim_axattc5,
playerAnim_axattc6,
playerAnim_axattd1,
playerAnim_axattd2,
playerAnim_axattd3,
playerAnim_axattd4,
playerAnim_axattd5,
playerAnim_axattd6,
};

View file

@ -18,4 +18,5 @@ items/quad.qc
rules.qc rules.qc
player.qc player.qc
init.qc init.qc
files.qc
#endlist #endlist

View file

@ -7,6 +7,7 @@ class Q1Shotgun:ncItem {
virtual void Draw( ncEntity ); virtual void Draw( ncEntity );
virtual void PrimaryAttack( ncEntity ); virtual void PrimaryAttack( ncEntity );
virtual void OnPickup( ncEntity ); virtual void OnPickup( ncEntity );
virtual void OnWorldImpact( vector, vector );
}; };
void Q1Shotgun::Q1Shotgun( void ) { void Q1Shotgun::Q1Shotgun( void ) {
@ -20,18 +21,26 @@ void Q1Shotgun::Precache( void ) {
void Q1Shotgun::Draw( ncEntity carrier ) { void Q1Shotgun::Draw( ncEntity carrier ) {
carrier.hud.SetWeaponModel("progs/v_shot.mdl"); carrier.hud.SetWeaponModel("progs/v_shot.mdl");
carrier.hud.SetWeaponFrame(0); carrier.hud.SetWeaponFrame( 0 );
carrier.hud.SetAmmo(AMMO_CURRENT, 20); carrier.hud.SetAmmo( AMMO_CURRENT, 20 );
carrier.SetWalkCycle( playerAnim_rockrun1, playerAnim_rockrun6, 10.0f );
carrier.SetIdleCycle( playerAnim_stand1, playerAnim_stand5, 10.0f );
} }
void Q1Shotgun::PrimaryAttack( ncEntity carrier ) { void Q1Shotgun::PrimaryAttack( ncEntity carrier ) {
carrier.SPrint(PRINT_LOW, "Pew\n"); carrier.SetNextPrimaryAttack( 0.5f );
carrier.SetNextPrimaryAttack(0.5f); carrier.PlayFrameSequence( playerAnim_shotatt1, playerAnim_shotatt6, 10.0f );
carrier.PlayWeaponFrameSequence( 1, 7, 10.0f );
ncProjectile::HitScan( carrier, [0.1, 0.1], 1, 12, this );
} }
void Q1Shotgun::OnPickup( ncEntity carrier ) { void Q1Shotgun::OnPickup( ncEntity carrier ) {
carrier.SPrint(PRINT_LOW, carrier.netname ); carrier.SPrint( PRINT_LOW, carrier.netname );
carrier.SPrint(PRINT_LOW, " picked up a shotgun!\n"); carrier.SPrint( PRINT_LOW, " picked up a shotgun!\n" );
} }
LINK_ENTITY_TO_CLASS(weapon_shotgun, Q1Shotgun) void Q1Shotgun::OnWorldImpact( vector endPos, vector planeNormal ) {
ncFX::CastBlood( endPos );
}
LINK_ENTITY_TO_CLASS(weapon_shotgun, Q1Shotgun)

69
qw/src/files.qc Normal file
View file

@ -0,0 +1,69 @@
void main( void ) {
/* all the files that QuakeWorld needs to boot. */
ncEngine::Precache_File( "qwprogs.dat");
ncEngine::Precache_File( "quake.rc" );
ncEngine::Precache_File( "gfx/palette.lmp" );
ncEngine::Precache_File( "gfx/colormap.lmp" );
ncEngine::Precache_File( "gfx/complete.lmp" );
ncEngine::Precache_File( "gfx/inter.lmp" );
ncEngine::Precache_File( "gfx/ranking.lmp" );
ncEngine::Precache_File( "gfx/vidmodes.lmp" );
ncEngine::Precache_File( "gfx/finale.lmp" );
ncEngine::Precache_File( "gfx/conback.lmp" );
ncEngine::Precache_File( "gfx/qplaque.lmp" );
ncEngine::Precache_File( "gfx/menudot1.lmp" );
ncEngine::Precache_File( "gfx/menudot2.lmp" );
ncEngine::Precache_File( "gfx/menudot3.lmp" );
ncEngine::Precache_File( "gfx/menudot4.lmp" );
ncEngine::Precache_File( "gfx/menudot5.lmp" );
ncEngine::Precache_File( "gfx/menudot6.lmp" );
ncEngine::Precache_File( "gfx/menuplyr.lmp" );
ncEngine::Precache_File( "gfx/bigbox.lmp" );
ncEngine::Precache_File( "gfx/dim_modm.lmp" );
ncEngine::Precache_File( "gfx/dim_drct.lmp" );
ncEngine::Precache_File( "gfx/dim_ipx.lmp" );
ncEngine::Precache_File( "gfx/dim_tcp.lmp" );
ncEngine::Precache_File( "gfx/dim_mult.lmp" );
ncEngine::Precache_File( "gfx/mainmenu.lmp" );
ncEngine::Precache_File( "gfx/box_tl.lmp" );
ncEngine::Precache_File( "gfx/box_tm.lmp" );
ncEngine::Precache_File( "gfx/box_tr.lmp" );
ncEngine::Precache_File( "gfx/box_ml.lmp" );
ncEngine::Precache_File( "gfx/box_mm.lmp" );
ncEngine::Precache_File( "gfx/box_mm2.lmp" );
ncEngine::Precache_File( "gfx/box_mr.lmp" );
ncEngine::Precache_File( "gfx/box_bl.lmp" );
ncEngine::Precache_File( "gfx/box_bm.lmp" );
ncEngine::Precache_File( "gfx/box_br.lmp" );
ncEngine::Precache_File( "gfx/sp_menu.lmp" );
ncEngine::Precache_File( "gfx/ttl_sgl.lmp" );
ncEngine::Precache_File( "gfx/ttl_main.lmp" );
ncEngine::Precache_File( "gfx/ttl_cstm.lmp" );
ncEngine::Precache_File( "gfx/mp_menu.lmp" );
ncEngine::Precache_File( "gfx/netmen1.lmp" );
ncEngine::Precache_File( "gfx/netmen2.lmp" );
ncEngine::Precache_File( "gfx/netmen3.lmp" );
ncEngine::Precache_File( "gfx/netmen4.lmp" );
ncEngine::Precache_File( "gfx/netmen5.lmp" );
ncEngine::Precache_File( "gfx/sell.lmp" );
ncEngine::Precache_File( "gfx/help0.lmp" );
ncEngine::Precache_File( "gfx/help1.lmp" );
ncEngine::Precache_File( "gfx/help2.lmp" );
ncEngine::Precache_File( "gfx/help3.lmp" );
ncEngine::Precache_File( "gfx/help4.lmp" );
ncEngine::Precache_File( "gfx/help5.lmp" );
ncEngine::Precache_File( "gfx/pause.lmp" );
ncEngine::Precache_File( "gfx/loading.lmp" );
ncEngine::Precache_File( "gfx/p_option.lmp" );
ncEngine::Precache_File( "gfx/p_load.lmp" );
ncEngine::Precache_File( "gfx/p_save.lmp" );
ncEngine::Precache_File( "gfx/p_multi.lmp" );
ncEngine::Precache_Sound( "misc/menu1.wav" );
ncEngine::Precache_Sound( "misc/menu2.wav" );
ncEngine::Precache_Sound( "misc/menu3.wav" );
ncEngine::Precache_Sound( "ambience/water1.wav" );
ncEngine::Precache_Sound( "ambience/wind2.wav" );
ncEngine::Precache_File2( "gfx/pop.lmp" );
ncEngine::Precache_File( "gfx.wad" );
ncEngine::Precache_File( "default.cfg" );
}

View file

@ -1,6 +1,7 @@
#define TARGET_QUAKEWORLD #define TARGET_QUAKEWORLD
#pragma progs_dat "../progs.dat" #pragma progs_dat "../qwprogs.dat"
#includelist #includelist
../../src/include.src ../../src/include.src
files.qc
#endlist #endlist

View file

@ -1,92 +1,4 @@
/* all standard game entry functions live here */ /* all standard game entry functions live here */
void main( void ) {
/* all the files that DOSQuake needs to boot. */
#ifdef TARGET_HEXEN2
ncEngine::Precache_File( "maps/demo1.bsp" );
ncEngine::Precache_File( "raven/menu1.wav" );
ncEngine::Precache_File( "raven/menu2.wav" );
ncEngine::Precache_File( "raven/menu3.wav" );
ncEngine::Precache_File( "misc/barmovup.wav" );
ncEngine::Precache_File( "misc/barmovdn.wav" );
ncEngine::Precache_File( "misc/invmove.wav" );
ncEngine::Precache_File( "misc/invuse.wav" );
#else
#ifndef TARGET_QUAKEWORLD
ncEngine::Precache_File( "progs.dat");
#else
ncEngine::Precache_File( "qwprogs.dat");
#endif
ncEngine::Precache_File( "quake.rc" );
ncEngine::Precache_File( "gfx/palette.lmp" );
ncEngine::Precache_File( "gfx/colormap.lmp" );
ncEngine::Precache_File( "gfx/complete.lmp" );
ncEngine::Precache_File( "gfx/inter.lmp" );
ncEngine::Precache_File( "gfx/ranking.lmp" );
ncEngine::Precache_File( "gfx/vidmodes.lmp" );
ncEngine::Precache_File( "gfx/finale.lmp" );
ncEngine::Precache_File( "gfx/conback.lmp" );
ncEngine::Precache_File( "gfx/qplaque.lmp" );
ncEngine::Precache_File( "gfx/menudot1.lmp" );
ncEngine::Precache_File( "gfx/menudot2.lmp" );
ncEngine::Precache_File( "gfx/menudot3.lmp" );
ncEngine::Precache_File( "gfx/menudot4.lmp" );
ncEngine::Precache_File( "gfx/menudot5.lmp" );
ncEngine::Precache_File( "gfx/menudot6.lmp" );
ncEngine::Precache_File( "gfx/menuplyr.lmp" );
ncEngine::Precache_File( "gfx/bigbox.lmp" );
ncEngine::Precache_File( "gfx/dim_modm.lmp" );
ncEngine::Precache_File( "gfx/dim_drct.lmp" );
ncEngine::Precache_File( "gfx/dim_ipx.lmp" );
ncEngine::Precache_File( "gfx/dim_tcp.lmp" );
ncEngine::Precache_File( "gfx/dim_mult.lmp" );
ncEngine::Precache_File( "gfx/mainmenu.lmp" );
ncEngine::Precache_File( "gfx/box_tl.lmp" );
ncEngine::Precache_File( "gfx/box_tm.lmp" );
ncEngine::Precache_File( "gfx/box_tr.lmp" );
ncEngine::Precache_File( "gfx/box_ml.lmp" );
ncEngine::Precache_File( "gfx/box_mm.lmp" );
ncEngine::Precache_File( "gfx/box_mm2.lmp" );
ncEngine::Precache_File( "gfx/box_mr.lmp" );
ncEngine::Precache_File( "gfx/box_bl.lmp" );
ncEngine::Precache_File( "gfx/box_bm.lmp" );
ncEngine::Precache_File( "gfx/box_br.lmp" );
ncEngine::Precache_File( "gfx/sp_menu.lmp" );
ncEngine::Precache_File( "gfx/ttl_sgl.lmp" );
ncEngine::Precache_File( "gfx/ttl_main.lmp" );
ncEngine::Precache_File( "gfx/ttl_cstm.lmp" );
ncEngine::Precache_File( "gfx/mp_menu.lmp" );
ncEngine::Precache_File( "gfx/netmen1.lmp" );
ncEngine::Precache_File( "gfx/netmen2.lmp" );
ncEngine::Precache_File( "gfx/netmen3.lmp" );
ncEngine::Precache_File( "gfx/netmen4.lmp" );
ncEngine::Precache_File( "gfx/netmen5.lmp" );
ncEngine::Precache_File( "gfx/sell.lmp" );
ncEngine::Precache_File( "gfx/help0.lmp" );
ncEngine::Precache_File( "gfx/help1.lmp" );
ncEngine::Precache_File( "gfx/help2.lmp" );
ncEngine::Precache_File( "gfx/help3.lmp" );
ncEngine::Precache_File( "gfx/help4.lmp" );
ncEngine::Precache_File( "gfx/help5.lmp" );
ncEngine::Precache_File( "gfx/pause.lmp" );
ncEngine::Precache_File( "gfx/loading.lmp" );
ncEngine::Precache_File( "gfx/p_option.lmp" );
ncEngine::Precache_File( "gfx/p_load.lmp" );
ncEngine::Precache_File( "gfx/p_save.lmp" );
ncEngine::Precache_File( "gfx/p_multi.lmp" );
ncEngine::Precache_Sound( "misc/menu1.wav" );
ncEngine::Precache_Sound( "misc/menu2.wav" );
ncEngine::Precache_Sound( "misc/menu3.wav" );
ncEngine::Precache_Sound( "ambience/water1.wav" );
ncEngine::Precache_Sound( "ambience/wind2.wav" );
ncEngine::Precache_File( "maps/start.bsp" );
#endif
ncEngine::Precache_File2( "gfx/pop.lmp" );
ncEngine::Precache_File( "gfx.wad" );
ncEngine::Precache_File( "default.cfg" );
}
void StartFrame( void ) { void StartFrame( void ) {
if (time) if (time)
g_world_initialized = true; g_world_initialized = true;

View file

@ -11,5 +11,7 @@ ncFX.qh
ncCamera.qh ncCamera.qh
ncHud.qh ncHud.qh
ncNet.qh ncNet.qh
ncAnimationManager.qh
ncProjectile.qh
classes.qh classes.qh
#endlist #endlist

View file

@ -0,0 +1,203 @@
.float idle_firstFrame;
.float idle_lastFrame;
.float idle_frameRate;
.float walk_firstFrame;
.float walk_lastFrame;
.float walk_frameRate;
.float override_firstFrame;
.float override_lastFrame;
.float override_frameRate;
.float wasWalking;
void ncAnimationManager::ncAnimationManager( void )
{
idle_firstFrame = 0;
idle_lastFrame = 0;
idle_frameRate = 0;
walk_firstFrame = 0;
walk_lastFrame = 0;
walk_frameRate = 0;
override_firstFrame = 0;
override_lastFrame = 0;
override_frameRate = 0;
wasWalking = 0;
}
void ncAnimationManager::ProgressCycle( void )
{
float playerSpeed = ncMath::VLen(owner.velocity);
bool isWalking = (playerSpeed > 2.0f) ? (true) : (false);
bool isReverse = false;
/* state switched */
if (isWalking != wasWalking) {
if (isWalking) {
wasWalking = 1;
owner.frame = walk_firstFrame;
nextthink = time + walk_frameRate;
} else {
wasWalking = 0;
owner.frame = idle_firstFrame;
nextthink = time + idle_frameRate;
}
return;
}
/* at the end */
if (isWalking) {
wasWalking = 1;
isReverse = ( walk_firstFrame > walk_lastFrame ) ? ( true ) : ( false );
nextthink = time + walk_frameRate;
if (owner.frame == walk_lastFrame) {
owner.frame = walk_firstFrame;
return;
}
} else {
wasWalking = 0;
isReverse = ( idle_firstFrame > idle_lastFrame ) ? ( true ) : ( false );
nextthink = time + idle_frameRate;
if (owner.frame == idle_lastFrame) {
owner.frame = idle_firstFrame;
return;
}
}
/* is reverse */
if (isReverse) {
owner.frame--;
} else {
owner.frame++;
}
}
void ncAnimationManager::ProgressOverride( void )
{
bool isReverse = ( override_firstFrame > override_lastFrame ) ? ( true ) : ( false );
/* at the end, back to idle/walk cycle */
if (owner.frame == override_lastFrame) {
nextthink = time + override_frameRate;
think = ProgressCycle;
wasWalking = 3; /* force state switch */
return;
}
/* is reverse */
if (isReverse) {
owner.frame--;
} else {
owner.frame++;
}
nextthink = time + health;
}
void ncAnimationManager::ProgressWeaponIdle( void )
{
ncEntity carrier = ( ncEntity )owner;
float currentFrame = carrier.weaponframe;
/* at the end */
if (currentFrame == idle_lastFrame) {
carrier.hud.SetWeaponFrame(idle_firstFrame);
} else {
/* is reverse */
if (skin) {
carrier.hud.SetWeaponFrame(currentFrame - 1);
} else {
carrier.hud.SetWeaponFrame(currentFrame + 1);
}
}
nextthink = time + idle_frameRate;
}
void ncAnimationManager::ProgressWeapon( void )
{
ncEntity carrier = ( ncEntity )owner;
float currentFrame = carrier.weaponframe;
/* at the end */
if (currentFrame == override_lastFrame) {
carrier.hud.SetWeaponFrame(idle_firstFrame);
nextthink = time + idle_frameRate;
think = ProgressWeaponIdle;
return;
}
/* is reverse */
if (skin) {
carrier.hud.SetWeaponFrame(currentFrame - 1);
} else {
carrier.hud.SetWeaponFrame(currentFrame + 1);
}
nextthink = time + override_frameRate;
}
float ncAnimationManager::FPSToRate(float framesPerSecond)
{
if (framesPerSecond <= 0.0) {
return (0.1f); /* default is 10 fps. */
} else {
return (1 / framesPerSecond);
}
}
void ncAnimationManager::SetIdleCycle( float firstFrame, float lastFrame, float frameRate )
{
ncEntity targetEntity = ( ncEntity )owner;
idle_firstFrame = firstFrame;
idle_lastFrame = lastFrame;
idle_frameRate = FPSToRate( frameRate );
/* there may be a sequence active already, that's okay as its exit will go to cycle */
if (!think) {
think = ncAnimationManager::ProgressCycle;
nextthink = ( time + idle_frameRate );
targetEntity.SetFrame( firstFrame );
}
}
void ncAnimationManager::SetWalkCycle( float firstFrame, float lastFrame, float frameRate )
{
ncEntity targetEntity = ( ncEntity )owner;
walk_firstFrame = firstFrame;
walk_lastFrame = lastFrame;
walk_frameRate = FPSToRate( frameRate );
/* ditto, see SetIdleCycle */
if (!think) {
think = ncAnimationManager::ProgressCycle;
nextthink = ( time + walk_frameRate );
targetEntity.SetFrame( firstFrame );
}
}
void ncAnimationManager::PlayFrameSequence( float firstFrame, float lastFrame, float frameRate )
{
ncEntity targetEntity = ( ncEntity )owner;
override_firstFrame = firstFrame;
override_lastFrame = lastFrame;
override_frameRate = FPSToRate( frameRate );
nextthink = ( time + override_frameRate );
think = ncAnimationManager::ProgressOverride;
targetEntity.SetFrame( firstFrame );
}
void ncAnimationManager::PlayWeaponFrameSequence( float firstFrame, float lastFrame, float frameRate )
{
ncEntity targetEntity = ( ncEntity )owner;
override_firstFrame = firstFrame;
override_lastFrame = lastFrame;
override_frameRate = FPSToRate( frameRate );
nextthink = ( time + override_frameRate );
think = ncAnimationManager::ProgressWeapon;
targetEntity.hud.SetWeaponFrame( firstFrame );
}

View file

@ -0,0 +1,14 @@
class ncAnimationManager {
void ncAnimationManager( void );
nonvirtual void ProgressCycle( void );
nonvirtual void ProgressOverride( void );
nonvirtual void ProgressWeaponIdle( void );
nonvirtual void ProgressWeapon( void );
nonvirtual float FPSToRate( float );
nonvirtual void SetWalkCycle( float firstFrame, float lastFrame, float frameRate );
nonvirtual void SetIdleCycle( float firstFrame, float lastFrame, float frameRate );
nonvirtual void PlayFrameSequence( float firstFrame, float lastFrame, float frameRate );
nonvirtual void PlayWeaponFrameSequence( float firstFrame, float lastFrame, float frameRate );
};

View file

@ -372,6 +372,11 @@ dead_t ncEntity::GetDeadFlag( void ) {
return (dead_t)deadflag; return (dead_t)deadflag;
} }
vector ncEntity::GetEyePos( void ) {
return origin + view_ofs;
}
vector ncEntity::GetViewOffset( void ) { vector ncEntity::GetViewOffset( void ) {
return view_ofs; return view_ofs;
} }
@ -746,12 +751,53 @@ void ncEntity::PrimaryAttack( ncEntity carrier ) {
currentweapon.PrimaryAttack(carrier); currentweapon.PrimaryAttack(carrier);
} }
void ncEntity::SetNextPrimaryAttack(float attackDelay) .ncAnimationManager animation_manager;
.ncAnimationManager weapon_animation_manager;
void ncEntity::SetIdleCycle( float firstFrame, float lastFrame, float frameRate )
{
if (!animation_manager) {
animation_manager = spawn( ncAnimationManager );
animation_manager.owner = this;
}
animation_manager.SetIdleCycle( firstFrame, lastFrame, frameRate );
}
void ncEntity::SetWalkCycle( float firstFrame, float lastFrame, float frameRate )
{
if (!animation_manager) {
animation_manager = spawn( ncAnimationManager );
animation_manager.owner = this;
}
animation_manager.SetWalkCycle( firstFrame, lastFrame, frameRate );
}
void ncEntity::SetNextPrimaryAttack( float attackDelay )
{ {
next_primary_attack = time + attackDelay; next_primary_attack = time + attackDelay;
} }
void ncEntity::PlayFrameSequence( float firstFrame, float lastFrame, float frameDelay )
{
if (!animation_manager) {
animation_manager = spawn( ncAnimationManager );
animation_manager.owner = this;
}
animation_manager.PlayFrameSequence( firstFrame, lastFrame, frameDelay);
}
void ncEntity::PlayWeaponFrameSequence( float firstFrame, float lastFrame, float frameDelay )
{
if (!weapon_animation_manager) {
weapon_animation_manager = spawn( ncAnimationManager );
weapon_animation_manager.owner = this;
}
weapon_animation_manager.PlayWeaponFrameSequence( firstFrame, lastFrame, frameDelay);
}
/* wannabe thief */ /* wannabe thief */
void ncEntity::CalculateLightLevel( void ) void ncEntity::CalculateLightLevel( void )
@ -770,4 +816,4 @@ void ncEntity::CalculateLightLevel( void )
light_level = lightValue; light_level = lightValue;
#endif #endif
} }

View file

@ -190,6 +190,8 @@ public:
nonvirtual dead_t GetDeadFlag( void ); nonvirtual dead_t GetDeadFlag( void );
/** Returns the eye position of the entity relative to its origin. */ /** Returns the eye position of the entity relative to its origin. */
nonvirtual vector GetViewOffset( void ); nonvirtual vector GetViewOffset( void );
/** Returns the absolute eye position. */
nonvirtual vector GetEyePos( void );
/** Returns either TRUE or FALSE if the entity has a given flag. */ /** Returns either TRUE or FALSE if the entity has a given flag. */
nonvirtual bool HasFlag( flags_t ); nonvirtual bool HasFlag( flags_t );
/** Returns the colormap id of the entity. */ /** Returns the colormap id of the entity. */
@ -297,6 +299,12 @@ public:
virtual void PrimaryAttack( ncEntity ); virtual void PrimaryAttack( ncEntity );
nonvirtual void SetNextPrimaryAttack( float ); nonvirtual void SetNextPrimaryAttack( float );
nonvirtual void PlayFrameSequence(float, float, float);
nonvirtual void PlayWeaponFrameSequence(float, float, float);
nonvirtual void SetIdleCycle(float, float, float);
nonvirtual void SetWalkCycle(float, float, float);
/** Recalculate the light level of the entity, run automatically on players during PreThink. */ /** Recalculate the light level of the entity, run automatically on players during PreThink. */
nonvirtual void CalculateLightLevel( void ); nonvirtual void CalculateLightLevel( void );
@ -309,4 +317,4 @@ private:
var bool g_world_initialized; var bool g_world_initialized;
.bool isIdEntity; .bool isIdEntity;
#define SPAWNDEFAULT(x,y) if (x == 0) { x = y; } #define SPAWNDEFAULT(x,y) if (x == 0) { x = y; }

View file

@ -149,13 +149,13 @@ void ncFX::CastBlood( vector targetPos ) {
#ifdef TARGET_QUAKEWORLD #ifdef TARGET_QUAKEWORLD
ncNet::WriteByte( FX_MSGTYPE, SVC_TEMP_ENTITY ); ncNet::WriteByte( FX_MSGTYPE, SVC_TEMP_ENTITY );
ncNet::WriteByte( FX_MSGTYPE, TE_BLOOD ); ncNet::WriteByte( FX_MSGTYPE, TE_BLOOD );
ncNet::WriteByte( FX_MSGTYPE, 1 ); ncNet::WriteByte( FX_MSGTYPE, 8 );
ncNet::WriteCoord( FX_MSGTYPE, targetPos[0] ); ncNet::WriteCoord( FX_MSGTYPE, targetPos[0] );
ncNet::WriteCoord( FX_MSGTYPE, targetPos[1] ); ncNet::WriteCoord( FX_MSGTYPE, targetPos[1] );
ncNet::WriteCoord( FX_MSGTYPE, targetPos[2] ); ncNet::WriteCoord( FX_MSGTYPE, targetPos[2] );
ncNet::MultiCast( targetPos, MULTICAST_PVS ); ncNet::MultiCast( targetPos, MULTICAST_PVS );
#else #else
Particle( targetPos, [0, 0, 0], 73, 1 ); Particle( targetPos, [0, 0, 0], 73, 8 );
#endif #endif
} }
@ -195,4 +195,4 @@ void ncFX::CastLightningBlood( ncEntity boltOwner, vector startPos, vector endPo
#ifndef TARGET_QUAKEWORLD #ifndef TARGET_QUAKEWORLD
CastBlood(endPos); CastBlood(endPos);
#endif #endif
} }

View file

@ -153,7 +153,7 @@ void ncItem::OnPickup(ncEntity carrier) {
carrier.SPrint( PRINT_LOW, GetItemName() ); carrier.SPrint( PRINT_LOW, GetItemName() );
carrier.SPrint( PRINT_LOW, "!\n" ); carrier.SPrint( PRINT_LOW, "!\n" );
ncFX::CastScreenFlash( carrier ); ncFX::CastScreenFlash( (ncPlayer)carrier );
if (nc_pckupsnd) if (nc_pckupsnd)
Sound( CHAN_ITEM, nc_pckupsnd, 1.0f, ATTN_NORM ); Sound( CHAN_ITEM, nc_pckupsnd, 1.0f, ATTN_NORM );
@ -167,6 +167,10 @@ void ncItem::OnInventoryUse( ncEntity carrier ) {
carrier.SPrint(PRINT_LOW, " which is unimplemented\n" ); carrier.SPrint(PRINT_LOW, " which is unimplemented\n" );
} }
void ncItem::OnWorldImpact(vector endPos, vector planeNormal) {
}
ncItem ncItem::ItemForID( float itemNum ) { ncItem ncItem::ItemForID( float itemNum ) {
ncEntity e; ncEntity e;
while ( ( e = ncEngine::NextEnt( e ) ) ) { while ( ( e = ncEngine::NextEnt( e ) ) ) {
@ -184,4 +188,4 @@ void ncItem::_InternalPostPrecache( void ) {
ncEngine::Precache_Sound( nc_pckupsnd ); ncEngine::Precache_Sound( nc_pckupsnd );
if (nc_model) if (nc_model)
ncEngine::Precache_Model( nc_model ); ncEngine::Precache_Model( nc_model );
} }

View file

@ -34,6 +34,8 @@ public:
virtual void OnPickup(ncEntity); virtual void OnPickup(ncEntity);
virtual void OnInventoryUse( ncEntity ); virtual void OnInventoryUse( ncEntity );
virtual void OnWorldImpact(vector, vector);
nonvirtual ncItem ItemForID( float ); nonvirtual ncItem ItemForID( float );
private: private:
@ -44,4 +46,4 @@ private:
.float nc_wepnid; .float nc_wepnid;
.string nc_model; .string nc_model;
.string nc_name; .string nc_name;
.string nc_pckupsnd; .string nc_pckupsnd;

View file

@ -3,6 +3,11 @@ void ncMath::MakeVectors( vector ang ) {
return makevectors( ang ); return makevectors( ang );
} }
vector ncMath::AnglesToForward( vector ang ) {
makevectors( ang );
return v_forward;
}
float ncMath::Random( void ) { float ncMath::Random( void ) {
return random(); return random();
} }
@ -170,4 +175,4 @@ float ncMath::Clamp( float min, float max, float x ) {
} }
return x; return x;
} }

View file

@ -1,5 +1,6 @@
class ncMath { class ncMath {
nonvirtual void MakeVectors( vector ang ); nonvirtual void MakeVectors( vector ang );
nonvirtual vector AnglesToForward( vector ang );
nonvirtual float Random( void ); nonvirtual float Random( void );
nonvirtual vector Normalize( vector v ); nonvirtual vector Normalize( vector v );
nonvirtual float VLen( vector v ); nonvirtual float VLen( vector v );
@ -31,4 +32,4 @@ const float MATH_ACOS_CURVE_B = 0.872664625997165;
/** If a is bigger than b, return b. */ /** If a is bigger than b, return b. */
#define min(a, b) ((a)>(b)?(b):(a)) #define min(a, b) ((a)>(b)?(b):(a))
/** If a is bigger than b, return a. */ /** If a is bigger than b, return a. */
#define max(a, b) ((a)>(b)?(a):(b)) #define max(a, b) ((a)>(b)?(a):(b))

View file

@ -0,0 +1,19 @@
void ncProjectile::ncProjectile( void )
{
}
bool ncProjectile::HitScan( ncEntity shootingEntity, vector spread2D, float shotCount, float damageValue, ncItem weaponItem )
{
vector startPos = shootingEntity.GetEyePos();
vector endPos = startPos + ncMath::AnglesToForward( shootingEntity.v_angle ) * 4096.0f;
ncEngine::TraceLine( startPos, endPos, false, shootingEntity );
if (trace_fraction >= 1.0f) {
return (false);
}
weaponItem.OnWorldImpact(trace_endpos, trace_plane_normal);
return (true);
}

View file

@ -0,0 +1,6 @@
class ncProjectile:ncEntity
{
void ncProjectile( void );
nonvirtual bool HitScan( ncEntity shootingEntity, vector spread2D, float shotCount, float damage, ncItem weaponItem );
};

View file

@ -11,5 +11,7 @@ ncCamera.qc
ncMath.qc ncMath.qc
ncHud.qc ncHud.qc
ncNet.qc ncNet.qc
ncAnimationManager.qc
ncProjectile.qc
classes.qc classes.qc
#endlist #endlist