Compare commits

..

18 commits

Author SHA1 Message Date
fd790a8022 fix lit path 2025-01-29 23:34:10 -08:00
3c70aeb70a make_map.sh: copy .lit file for individual maps as well. 2025-01-29 23:12:23 -08:00
a1c4cf7394 build_wads.sh: fix typo 2025-01-29 22:58:45 -08:00
5708e6ea7a Build wads without fullbrights by default. 2025-01-29 22:40:26 -08:00
e1060dc993 More entity documentation, rename some filesystem stuff. 2025-01-29 04:37:35 -08:00
9876ddea5a WC/JACK palette ain't JASC afterall. 2025-01-26 02:29:08 -08:00
84bcc183ec Some QUAKED stuff, tiny fixes. 2025-01-26 00:12:18 -08:00
60e39270ab Update BUILDING 2025-01-24 15:24:25 -08:00
041d2ed2bb Makefile: manage targets netradiant-custom and add NRC gamepack integration. 2025-01-24 15:02:23 -08:00
10697cfb7a Minor other tool changes. 2025-01-24 02:32:11 -08:00
d44e890e14 Makefile: simple name change of qlight 2025-01-24 02:31:03 -08:00
9d2f0a562f ncPlayer: add JumpPressedInAir callback 2025-01-24 02:24:17 -08:00
fd00f55db4 Makefile: tga2lmp needed for palette/gfx 2025-01-24 02:01:48 -08:00
2da70886e9 Makefile: game needs fteqcc 2025-01-24 01:57:43 -08:00
2a42fa475f small tweaks 2025-01-24 01:55:37 -08:00
586008044a Port over radiant integration 2025-01-23 23:36:30 -08:00
4db1c33265 Dump more tools in, plus add ncAnimationManager object. 2025-01-23 22:16:24 -08:00
75256d8ead Rename the game dirs to integrate directly with vanilla engines. 2025-01-22 14:38:36 -08:00
124 changed files with 4136 additions and 240 deletions

27
.gitignore vendored Normal file
View file

@ -0,0 +1,27 @@
*.bsp
*.dat
*.def
*.lmp
*.lno
*.mdl
*.pal
*.prt
*.lux
*.lit
*.wad
Tools/base_entities.def
conhistory.txt
fteqcc
fteqw
imgtool
installed.lst
iqmtool
pal2colormap
pal2pal
qbsp
qfiles
qlight
qvis
radiant
tga2lmp
tga2pal

112
BUILDING Normal file
View file

@ -0,0 +1,112 @@
# Building Manual
## Introduction
The Makefile (tested with GNU Make) contains an assortment of targets
that will make building of assets and code into the game easier.
Here we will discuss the various targets mentioned, you can build
any of them at any time (dependencies should resolve themselves)
using the usual `make` syntax:
make _target_ GAME=id1
Where `_target_` is to be substituted with a valid target. The `GAME=`
override decides which game directory to consider using.
Generally, you want to make a copy of either `id1`, `qw` or `data1`,
name it something original (say `foobar`) and then you would pass
`GAME=foobar` instead of `GAME=id1`.
If the GAME variable isn't passed, `id1` is assumed.
## Targets
### help
Will display some short help information on important targets that
are available. Also the default result when no target is specified.
### all
Build all of the code, models, maps, textures and 2D graphics for a
given game. You probably want to run this sparingly (or on the first time).
### wad
Builds all texture wads for a given game. The textures are to
be placed within a sub-directory within your game's `texturesrc/`
directory. Each directory gets compiled into its own WAD. If you
want to target WAD3, simply place an empty file named `WAD3` within
the desired directory.
### maps
Builds all the maps (and texture wads) for a given game.
### GAME/maps/mapname.bsp
Will compile GAME/maps/mapname.bsp. So if you were to run
`make id1/maps/start.bsp`, that would be valid - as long as
`id1/mapsrc/start.map` was to exist.
### models
Builds all models for a given game using FTEQW's iqmtool.
### defs
Builds an entities.def file for use in QED/Radiant and integrates
it into the editors that are present in the local installation.
Currently it will also build all available editors, but that will
probably change.
### gfx
Builds all the 2D graphics (menu related, mainly) for a given game.
### palette
Rebuilds the palette for the given game. Reads from
GAME/gfxsrc/palette.png and will ensure to build a new palette.lmp for
use in the engine, as well as a colormap.lmp for software renderers
as well as a palette.pal for use in WorldCraft based editors.
You will probably want to rebuild all your other assets after this.
### update
Updates tools + game repos.
### radiant
Builds GtkRadiant and gives it with a launcher: ./radiant
### netradiant-custom
Builds NetRadiant-Custom, a popular alternative to the upstream
GtkRadiant. You can use this to update + rebuild a new version.
Will also place a launcher in your game directory: ./netradiant-custom
### launcher
Builds a launcher for your game using FTEQW. Will accept command-line arguments
and will execute a config file with your username if present. This way
developers can stay out of each others way, even on a non-versioned
filesystem. This is for development purposes only.
### pak
Will build pak0.pak and pak1.pak files (shareware and registered
archives) for your game. Ensure you use the right Precache_* APIs so
the tool knows which data belongs to shareware and which to registered
versions of your game.
## Legal advice regarding pop.lmp
Do not ship Quake's gfx/pop.lmp. Vanilla engines will look for it, but
forks/source-ports will not. Feel free to compile your own proof-of-purchase
check in your own custom engine.

400
Makefile Normal file
View file

@ -0,0 +1,400 @@
# 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
NUCLIDE_DIR=`pwd`
QCC_DIR=$(NUCLIDE_DIR)
BUILD_DIR=$(NUCLIDE_DIR)/build
NAME=idtech2-$(GAME)
RADIANT_GAME="$(NUCLIDE_DIR)/ThirdParty/gtkradiant/install/games/$(GAME).game"
RADIANT_XLINK="$(NUCLIDE_DIR)/ThirdParty/gtkradiant/install/installs/$(NAME)Pack/game/game.xlink"
RADIANT_SYNAPSE="$(NUCLIDE_DIR)/ThirdParty/gtkradiant/install/installs/$(NAME)Pack/game/synapse.config"
RADIANT_PROJECT="$(NUCLIDE_DIR)/ThirdParty/gtkradiant/install/installs/$(NAME)Pack/install/$(GAME)/scripts/default_project.proj"
RADIANT_TEXTURES="$(NUCLIDE_DIR)/ThirdParty/gtkradiant/install/installs/$(NAME)Pack/install/$(GAME)/textures"
RADIANT_DEF="$(NUCLIDE_DIR)/ThirdParty/gtkradiant/install/installs/$(NAME)Pack/install/$(GAME)/scripts/entities.def"
NRC_GAME="$(NUCLIDE_DIR)/ThirdParty/netradiant-custom/install/gamepacks/games/$(NAME).game"
NRC_GAMEDIR="$(NUCLIDE_DIR)/ThirdParty/netradiant-custom/install/gamepacks/$(NAME).game/$(GAME)/"
NRC_DEF="$(NRC_GAMEDIR)/entities.def"
NRC_SYNAPSE="$(NRC_GAMEDIR)/../default_build_menu.xml"
EDITOR_QBSP="$(ARGSTR)TEMPLATEenginepath/qbsp"
EDITOR_QVIS="$(ARGSTR)TEMPLATEenginepath/qvis"
EDITOR_QRAD="$(ARGSTR)TEMPLATEenginepath/qrad"
EDITOR_ENGINEPATH="$(ARGSTR)TEMPLATEenginepath"
EDITOR_BASEPATH="$(ARGSTR)TEMPLATEbasedir"
EDITOR_HOMEPATH="$(ARGSTR)TEMPLATEuserhomepath"
define CMDSTR
#
endef
define ARGSTR
\$
endef
help:
@printf "Available targets:\n"
@printf "\thelp\n"
@printf "\tgame\n"
@printf "\tfteqcc\n"
@printf "\tfteqw\n"
all: models maps game gfx
game: fteqcc
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)
wads: imgtool palette
./Tools/build_wads.sh $(GAME)
maps: wads
./Tools/build_maps.sh $(GAME)
empty:
printf "\n"
$(GAME)/maps/%.bsp: qbsp qrad qvis empty
Tools/make_map.sh $(GAME) "$@"
$(GAME)/models/%.mdl: iqmtool empty
Tools/make_model.sh $(GAME) "$@"
models: iqmtool palette
./Tools/build_models.sh $(GAME)
gfx: imgtool palette
cd $(GAME)/gfxsrc/ && ls | grep -v palette | grep \.xcf | xargs ../../imgtool --rgb8 --ext png
cd $(GAME)/gfxsrc/ && ls | grep -v palette | 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 | 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:
$(CC) -o tga2pal Tools/Source/tga2pal.c
wav2loop:
$(CC) -o wav2loop Tools/Source/wav2loop.c
tga2lmp:
$(CC) -o tga2lmp Tools/Source/tga2lmp.c
pal2pal:
$(CC) -o pal2pal Tools/Source/pal2pal.c
pal2wc:
$(CC) -o pal2wc Tools/Source/pal2wc.c
pal2colormap:
$(CC) -o pal2colormap Tools/Source/pal2colormap.c
qfiles:
$(CC) -o qfiles Tools/Source/qfiles.c Tools/Source/cmdlib.c
palette: pal2colormap tga2pal tga2lmp
if [ ! -d $(GAME)/gfx ];then mkdir $(GAME)/gfx; fi
convert $(GAME)/gfxsrc/palette.png -strokewidth 0 -fill "rgb( 255, 0, 255 )" -draw "rectangle 0,14 16,16" $(GAME)/gfxsrc/palette_nofb.png
convert $(GAME)/gfxsrc/palette.png -strokewidth 0 -fill "rgb( 255, 0, 255 )" -draw "rectangle 0,0 16,13" $(GAME)/gfxsrc/palette_fbonly.png
mogrify -type TrueColor -compress None -flip -format tga $(GAME)/gfxsrc/palette.png
mogrify -type TrueColor -compress None -flip -format tga $(GAME)/gfxsrc/palette_nofb.png
mogrify -type TrueColor -compress None -flip -format tga $(GAME)/gfxsrc/palette_fbonly.png
cd $(GAME)/gfxsrc/ && ../../tga2pal palette.tga
cd $(GAME)/gfxsrc/ && ../../tga2pal palette_nofb.tga
cd $(GAME)/gfxsrc/ && ../../tga2pal palette_fbonly.tga
cd $(GAME)/gfxsrc/ && ../../pal2colormap palette.lmp
mv $(GAME)/gfxsrc/palette.lmp $(GAME)/gfx/palette.lmp
mv $(GAME)/gfxsrc/palette_nofb.lmp $(GAME)/gfx/palette_nofb.lmp
mv $(GAME)/gfxsrc/colormap.lmp $(GAME)/gfx/colormap.lmp
cp $(GAME)/gfx/palette.lmp $(GAME)/gfx/palette.pal
-mkdir -p $(GAME)/gfxsrc
#rm $(GAME)/gfxsrc/palette.tga
#rm $(GAME)/gfxsrc/palette_nofb.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"
qrad:
printf "qrad build\n"
radiant: update
if [ ! -d ThirdParty/gtkradiant ];then git clone https://github.com/TTimo/gtkradiant ThirdParty/gtkradiant;fi
cd ./ThirdParty/gtkradiant && scons target="radiant"
mkdir -p ./ThirdParty/gtkradiant/install/games
mkdir -p ./ThirdParty/gtkradiant/install/installs
Tools/make_launcher.sh ./ThirdParty/gtkradiant/install/ ./radiant.bin radiant
netradiant-custom:
if [ ! -d ThirdParty/netradiant-custom ];then git clone https://github.com/Garux/netradiant-custom ThirdParty/netradiant-custom;fi
cd ThirdParty/netradiant-custom && $(MAKE) DOWNLOAD_GAMEPACKS=no BUILD=debug RADIANT_ABOUTMSG="NuclideLite managed build."
mkdir -p ./ThirdParty/netradiant-custom/install/gamepacks/games
Tools/make_launcher.sh ./ThirdParty/netradiant-custom/install/ ./radiant.x86_64 netradiant-custom
launcher:
Tools/make_launcher.sh "./" "./fteqw -readonly -basedir ./ -netquake -game $(GAME) +exec $(USER).cfg" $(GAME).sh
defs:
Tools/make_mapdef.sh $(GAME)
echo "<?xml version=\"1.0\" encoding=\"iso-8859-1\" standalone=\"yes\"?>" > "$(RADIANT_GAME)"
echo "<game" >> "$(RADIANT_GAME)"
echo " name=\"$(NAME)\"" >> "$(RADIANT_GAME)"
echo " enginepath_linux=\"$(NUCLIDE_DIR)\"" >> "$(RADIANT_GAME)"
echo " gametools_linux=\"$(NUCLIDE_DIR)/ThirdParty/gtkradiant/install/installs/$(NAME)Pack/game\"" >> "$(RADIANT_GAME)"
echo " prefix=\".$(GAME)\"" >> "$(RADIANT_GAME)"
echo " basegame=\"$(GAME)\"" >> "$(RADIANT_GAME)"
echo "/>" >> "$(RADIANT_GAME)"
mkdir -p "$(NUCLIDE_DIR)/ThirdParty/gtkradiant/install/installs/$(NAME)Pack/game"
echo "<?xml version=\"1.0\" encoding=\"iso-8859-1\" standalone=\"yes\"?>" > "$(RADIANT_XLINK)"
echo "<!-- Links for the $(NAME) game pack -->" >> "$(RADIANT_XLINK)"
echo "<links>" >> "$(RADIANT_XLINK)"
echo "<item name=\"Nuclide Developer Reference\" url=\"http://developer.vera-visions.com/\"/>" >> "$(RADIANT_XLINK)"
echo "<item name=\"Vera Visions\" url=\"http://www.vera-visions.com/\"/>" >> "$(RADIANT_XLINK)"
echo "</links>" >> "$(RADIANT_XLINK)"
echo "<?xml version=\"1.0\" encoding=\"iso-8859-1\" standalone=\"yes\"?><synapseconfig><client name=\"core\"><api name=\"image\">" > "$(RADIANT_SYNAPSE)"
echo "pcx tga mip" >> "$(RADIANT_SYNAPSE)"
echo "</api><api name=\"VFS\">" >> "$(RADIANT_SYNAPSE)"
echo "wad" >> "$(RADIANT_SYNAPSE)"
echo "</api><api name=\"shaders\">" >> "$(RADIANT_SYNAPSE)"
echo "idtech2" >> "$(RADIANT_SYNAPSE)"
echo "</api><api name=\"map\">" >> "$(RADIANT_SYNAPSE)"
echo "maphl" >> "$(RADIANT_SYNAPSE)"
echo "</api><api name=\"eclass\">" >> "$(RADIANT_SYNAPSE)"
echo "def" >> "$(RADIANT_SYNAPSE)"
echo "</api><api name=\"surfdialog\">" >> "$(RADIANT_SYNAPSE)"
echo "idtech2" >> "$(RADIANT_SYNAPSE)"
echo "</api></client><client name=\"image\"><api name=\"VFS\">" >> "$(RADIANT_SYNAPSE)"
echo "wad" >> "$(RADIANT_SYNAPSE)"
echo "</api></client><client name=\"shaders\"><api name=\"shaders\">" >> "$(RADIANT_SYNAPSE)"
echo "idtech2" >> "$(RADIANT_SYNAPSE)"
echo "</api><api name=\"VFS\">" >> "$(RADIANT_SYNAPSE)"
echo "wad" >> "$(RADIANT_SYNAPSE)"
echo "</api></client><client name=\"map\"><api name=\"shaders\">" >> "$(RADIANT_SYNAPSE)"
echo "idtech2" >> "$(RADIANT_SYNAPSE)"
echo "</api></client><client name=\"xmap\"><api name=\"shaders\">" >> "$(RADIANT_SYNAPSE)"
echo "idtech2" >> "$(RADIANT_SYNAPSE)"
echo "</api></client><client name=\"model\"><api name=\"shaders\">" >> "$(RADIANT_SYNAPSE)"
echo "idtech2" >> "$(RADIANT_SYNAPSE)"
echo "</api><api name=\"VFS\">" >> "$(RADIANT_SYNAPSE)"
echo "wad" >> "$(RADIANT_SYNAPSE)"
echo "</api></client></synapseconfig>" >> "$(RADIANT_SYNAPSE)"
mkdir -p "$(NUCLIDE_DIR)/ThirdParty/gtkradiant/install/installs/$(NAME)Pack/install/$(GAME)/scripts"
cp "$(GAME)/scripts/entities.def" "$(RADIANT_DEF)"
echo "<?xml version=\"1.0\"?>" > "$(RADIANT_PROJECT)"
echo "<!DOCTYPE project SYSTEM \"dtds/project.dtd\">" >> "$(RADIANT_PROJECT)"
echo "<project>" >> "$(RADIANT_PROJECT)"
echo "<key name=\"version\" value=\"2\"/>" >> "$(RADIANT_PROJECT)"
echo "<key name=\"template_version\" value=\"8\"/>" >> "$(RADIANT_PROJECT)"
echo "<key name=\"basepath\" value=\"$(EDITOR_ENGINEPATH)$(EDITOR_BASEPATH)/\"/>" >> "$(RADIANT_PROJECT)"
echo "<key name=\"rshcmd\" value=\"\"/>" >> "$(RADIANT_PROJECT)"
echo "<key name=\"remotebasepath\" value=\"$(EDITOR_ENGINEPATH)$(EDITOR_BASEPATH)/\"/>" >> "$(RADIANT_PROJECT)"
echo "<key name=\"entitypath\" value=\"$(ARGSTR)TEMPLATEtoolspath$(EDITOR_BASEPATH)/scripts/entities.def\"/>" >> "$(RADIANT_PROJECT)"
echo "<key name=\"texturepath\" value=\"$(EDITOR_ENGINEPATH)$(EDITOR_BASEPATH)/textures/\"/>" >> "$(RADIANT_PROJECT)"
echo "<key name=\"autosave\" value=\"$(EDITOR_HOMEPATH)$(EDITOR_BASEPATH)/maps/autosave.map\"/>" >> "$(RADIANT_PROJECT)"
echo "<key name=\"mapspath\" value=\"$(EDITOR_HOMEPATH)$(EDITOR_BASEPATH)/maps/\"/>" >> "$(RADIANT_PROJECT)"
echo "<key name=\"bsp_VMAP: (Fast Fullbright)\" value=\"! &quot;$(EDITOR_VMAP)&quot; -v $(CMDSTR) -game $(GAME) -fs_basepath &quot;$(EDITOR_ENGINEPATH)&quot; -custinfoparms -threads 4 -samplesize 8 $(ARGSTR) &amp;&amp; ! &quot;$(EDITOR_VMAP)&quot; $(CMDSTR) -game $(GAME) -fs_basepath &quot;$(EDITOR_ENGINEPATH)&quot; -vis -saveprt$(ARGSTR)\" />" >> "$(RADIANT_PROJECT)"
echo "<key name=\"bsp_VMAP: (Fast Light)\" value=\"! &quot;$(EDITOR_VMAP)&quot; -v $(CMDSTR) -game $(GAME) -fs_basepath &quot;$(EDITOR_ENGINEPATH)&quot; -custinfoparms -threads 4 -samplesize 8 $(ARGSTR) &amp;&amp; ! &quot;$(EDITOR_VMAP)&quot; $(CMDSTR) -game $(GAME) -fs_basepath &quot;$(EDITOR_ENGINEPATH)&quot; -vis -saveprt $(ARGSTR) &amp;&amp; ! &quot;$(EDITOR_VMAP)&quot; $(CMDSTR) -game $(GAME) -fs_basepath &quot;$(EDITOR_ENGINEPATH)&quot; -light -custinfoparms -v -samplesize 8 -fast -threads 4 -samples 4 -shade -shadeangle 60 -patchshadows $(ARGSTR)\" />" >> "$(RADIANT_PROJECT)"
echo "<key name=\"bsp_VMAP: (Full)\" value=\"! &quot;$(EDITOR_VMAP)&quot; -v $(CMDSTR) -game $(GAME) -fs_basepath &quot;$(EDITOR_ENGINEPATH)&quot; -custinfoparms -threads 4 -samplesize 8 $(ARGSTR) &amp;&amp; ! &quot;$(EDITOR_VMAP)&quot; $(CMDSTR) -game $(GAME) -fs_basepath &quot;$(EDITOR_ENGINEPATH)&quot; -vis -saveprt $(ARGSTR) &amp;&amp; ! &quot;$(EDITOR_VMAP)&quot; $(CMDSTR) -game $(GAME) -fs_basepath &quot;$(EDITOR_ENGINEPATH)&quot; -light -custinfoparms -samplesize 8 -fast -threads 4 -samples 4 -shade -shadeangle 60 -patchshadows $(ARGSTR)\" />" >> "$(RADIANT_PROJECT)"
echo "</project>" >> "$(RADIANT_PROJECT)"
mkdir -p "$(RADIANT_TEXTURES)/."
cp "$(GAME)/gfx/palette.lmp" "$(RADIANT_TEXTURES)/palette.lmp"
mkdir -p "$(HOME)/.$(GAME)/$(GAME)/scripts"
rsync -rva "$(NUCLIDE_DIR)/ThirdParty/gtkradiant/install/installs/$(NAME)Pack/install/$(GAME)/." "$(HOME)/.$(GAME)/$(GAME)/."
rsync -rva "$(NUCLIDE_DIR)/ThirdParty/gtkradiant/install/installs/$(NAME)Pack/install/$(GAME)/." "./$(GAME)/."
mkdir -p "$(NRC_GAMEDIR)"
echo "<?xml version=\"1.0\" encoding=\"iso-8859-1\" standalone=\"yes\"?>" > "$(NRC_GAME)"
echo "<game" >> "$(NRC_GAME)"
echo " type=\"q1\"" >> "$(NRC_GAME)"
echo " name=\"$(NAME)\"" >> "$(NRC_GAME)"
echo " enginepath_linux=\"c:$(NUCLIDE_DIR)\"" >> "$(NRC_GAME)"
echo " enginepath_win32=\"c:$(NUCLIDE_DIR)\"" >> "$(NRC_GAME)"
echo " engine_win32=\"fteqw.exe\"" >> "$(NRC_GAME)"
echo " engine_linux=\"fteqw\"" >> "$(NRC_GAME)"
echo " basegame=\"$(GAME)\"" >> "$(NRC_GAME)"
echo " basegamename=\"$(NAME)\"" >> "$(NRC_GAME)"
echo " unknowngamename=\"Custom Quake modification\"" >> "$(NRC_GAME)"
echo " default_scale=\"1.0\"" >> "$(NRC_GAME)"
echo " no_patch=\"1\"" >> "$(NRC_GAME)"
echo " no_bsp_monitor=\"1\"" >> "$(NRC_GAME)"
echo " show_wads=\"1\"" >> "$(NRC_GAME)"
echo " archivetypes=\"pak wad\"" >> "$(NRC_GAME)"
echo " texturetypes=\"tga jpg mip hlw\"" >> "$(NRC_GAME)"
echo " modeltypes=\"mdl\"" >> "$(NRC_GAME)"
echo " maptypes=\"mapq1\"" >> "$(NRC_GAME)"
echo " shaders=\"quake3\"" >> "$(NRC_GAME)"
echo " entityclass=\"quake3\"" >> "$(NRC_GAME)"
echo " entityclasstype=\"def xml\"" >> "$(NRC_GAME)"
echo " entities=\"quake3\"" >> "$(NRC_GAME)"
echo " brushtypes=\"quake\"" >> "$(NRC_GAME)"
echo " patchtypes=\"quake3\"" >> "$(NRC_GAME)"
echo "/>" >> "$(NRC_GAME)"
cp "$(GAME)/scripts/entities.def" "$(NRC_DEF)"
echo "<?xml version=\"1.0\"?>" > $(NRC_SYNAPSE)
echo "<project version=\"2.0\">" >> $(NRC_SYNAPSE)
echo " <var name=\"bsp\">\"[EnginePath]qbsp\"</var>" >> $(NRC_SYNAPSE)
echo " <var name=\"vis\">\"[EnginePath]qvis\"</var>" >> $(NRC_SYNAPSE)
echo " <var name=\"light\">\"[EnginePath]qrad\"</var>" >> $(NRC_SYNAPSE)
echo " <build name=\"qbsp\">" >> $(NRC_SYNAPSE)
echo " <command>[bsp] \"[MapFile]\"</command>" >> $(NRC_SYNAPSE)
echo " </build>" >> $(NRC_SYNAPSE)
echo " <build name=\"qbsp -onlyents\">" >> $(NRC_SYNAPSE)
echo " <command>[bsp] -onlyents \"[MapFile]\"</command>" >> $(NRC_SYNAPSE)
echo " </build>" >> $(NRC_SYNAPSE)
echo " <build name=\"qvis\">" >> $(NRC_SYNAPSE)
echo " <command>[bsp] \"[MapFile]\"</command>" >> $(NRC_SYNAPSE)
echo " <command>[vis] \"[MapFile]\"</command>" >> $(NRC_SYNAPSE)
echo " </build>" >> $(NRC_SYNAPSE)
echo " <build name=\"qvis -fast\">" >> $(NRC_SYNAPSE)
echo " <command>[bsp] \"[MapFile]\"</command>" >> $(NRC_SYNAPSE)
echo " <command>[vis] -fast \"[MapFile]\"</command>" >> $(NRC_SYNAPSE)
echo " </build>" >> $(NRC_SYNAPSE)
echo " <build name=\"qvis -noambient\">" >> $(NRC_SYNAPSE)
echo " <command>[bsp] \"[MapFile]\"</command>" >> $(NRC_SYNAPSE)
echo " <command>[vis] -noambient \"[MapFile]\"</command>" >> $(NRC_SYNAPSE)
echo " </build>" >> $(NRC_SYNAPSE)
echo " <build name=\"qvis -noambient -fast\">" >> $(NRC_SYNAPSE)
echo " <command>[bsp] \"[MapFile]\"</command>" >> $(NRC_SYNAPSE)
echo " <command>[vis] -noambient -fast \"[MapFile]\"</command>" >> $(NRC_SYNAPSE)
echo " </build>" >> $(NRC_SYNAPSE)
echo " <build name=\"qrad\">" >> $(NRC_SYNAPSE)
echo " <command>[bsp] \"[MapFile]\"</command>" >> $(NRC_SYNAPSE)
echo " <command>[light] \"[MapFile]\"</command>" >> $(NRC_SYNAPSE)
echo " </build>" >> $(NRC_SYNAPSE)
echo " <build name=\"qrad -extra\">" >> $(NRC_SYNAPSE)
echo " <command>[bsp] \"[MapFile]\"</command>" >> $(NRC_SYNAPSE)
echo " <command>[light] -extra \"[MapFile]\"</command>" >> $(NRC_SYNAPSE)
echo " </build>" >> $(NRC_SYNAPSE)
echo " <build name=\"qrad -extra4x4\">" >> $(NRC_SYNAPSE)
echo " <command>[bsp] \"[MapFile]\"</command>" >> $(NRC_SYNAPSE)
echo " <command>[light] -extra4x4 \"[MapFile]\"</command>" >> $(NRC_SYNAPSE)
echo " </build>" >> $(NRC_SYNAPSE)
echo " <build name=\"qbsp\">" >> $(NRC_SYNAPSE)
echo " <command>[bsp] \"[MapFile]\"</command>" >> $(NRC_SYNAPSE)
echo " </build>" >> $(NRC_SYNAPSE)
echo " <build name=\"qbsp, qrad\">" >> $(NRC_SYNAPSE)
echo " <command>[bsp] \"[MapFile]\"</command>" >> $(NRC_SYNAPSE)
echo " <command>[light] \"[MapFile]\"</command>" >> $(NRC_SYNAPSE)
echo " </build>" >> $(NRC_SYNAPSE)
echo " <build name=\"qbsp, qrad -extra\">" >> $(NRC_SYNAPSE)
echo " <command>[bsp] \"[MapFile]\"</command>" >> $(NRC_SYNAPSE)
echo " <command>[light] -extra \"[MapFile]\"</command>" >> $(NRC_SYNAPSE)
echo " </build>" >> $(NRC_SYNAPSE)
echo " <build name=\"qbsp, qrad -extra4x4\">" >> $(NRC_SYNAPSE)
echo " <command>[bsp] \"[MapFile]\"</command>" >> $(NRC_SYNAPSE)
echo " <command>[light] -extra4x4 \"[MapFile]\"</command>" >> $(NRC_SYNAPSE)
echo " </build>" >> $(NRC_SYNAPSE)
echo " <build name=\"qbsp, qvis\">" >> $(NRC_SYNAPSE)
echo " <command>[bsp] \"[MapFile]\"</command>" >> $(NRC_SYNAPSE)
echo " <command>[vis] \"[MapFile]\"</command>" >> $(NRC_SYNAPSE)
echo " </build>" >> $(NRC_SYNAPSE)
echo " <build name=\"qbsp, qvis, qrad\">" >> $(NRC_SYNAPSE)
echo " <command>[bsp] \"[MapFile]\"</command>" >> $(NRC_SYNAPSE)
echo " <command>[vis] \"[MapFile]\"</command>" >> $(NRC_SYNAPSE)
echo " <command>[light] \"[MapFile]\"</command> </build>" >> $(NRC_SYNAPSE)
echo " <build name=\"qbsp, qvis, qrad -extra\">" >> $(NRC_SYNAPSE)
echo " <command>[bsp] \"[MapFile]\"</command>" >> $(NRC_SYNAPSE)
echo " <command>[vis] \"[MapFile]\"</command>" >> $(NRC_SYNAPSE)
echo " <command>[light] -extra \"[MapFile]\"</command>" >> $(NRC_SYNAPSE)
echo " </build>" >> $(NRC_SYNAPSE)
echo " <build name=\"qbsp, qvis, qrad -extra4x4\">" >> $(NRC_SYNAPSE)
echo " <command>[bsp] \"[MapFile]\"</command>" >> $(NRC_SYNAPSE)
echo " <command>[vis] \"[MapFile]\"</command>" >> $(NRC_SYNAPSE)
echo " <command>[light] -extra4x4 \"[MapFile]\"</command>" >> $(NRC_SYNAPSE)
echo " </build>" >> $(NRC_SYNAPSE)
echo " <build name=\"qbsp, qvis -fast\">" >> $(NRC_SYNAPSE)
echo " <command>[bsp] \"[MapFile]\"</command>" >> $(NRC_SYNAPSE)
echo " <command>[vis] -fast \"[MapFile]\"</command>" >> $(NRC_SYNAPSE)
echo " </build>" >> $(NRC_SYNAPSE)
echo " <build name=\"qbsp, qvis -fast, qrad\">" >> $(NRC_SYNAPSE)
echo " <command>[bsp] \"[MapFile]\"</command>" >> $(NRC_SYNAPSE)
echo " <command>[vis] -fast \"[MapFile]\"</command>" >> $(NRC_SYNAPSE)
echo " <command>[light] \"[MapFile]\"</command>" >> $(NRC_SYNAPSE)
echo " </build>" >> $(NRC_SYNAPSE)
echo " <build name=\"qbsp, qvis -fast, qrad -extra\">" >> $(NRC_SYNAPSE)
echo " <command>[bsp] \"[MapFile]\"</command>" >> $(NRC_SYNAPSE)
echo " <command>[vis] -fast \"[MapFile]\"</command>" >> $(NRC_SYNAPSE)
echo " <command>[light] -extra \"[MapFile]\"</command>" >> $(NRC_SYNAPSE)
echo " </build>" >> $(NRC_SYNAPSE)
echo " <build name=\"qbsp, qvis -fast, qrad -extra4x4\">" >> $(NRC_SYNAPSE)
echo " <command>[bsp] \"[MapFile]\"</command>" >> $(NRC_SYNAPSE)
echo " <command>[vis] -fast \"[MapFile]\"</command>" >> $(NRC_SYNAPSE)
echo " <command>[light] -extra4x4 \"[MapFile]\"</command>" >> $(NRC_SYNAPSE)
echo " </build>" >> $(NRC_SYNAPSE)
echo " <build name=\"qbsp, qvis -noambient\">" >> $(NRC_SYNAPSE)
echo " <command>[bsp] \"[MapFile]\"</command>" >> $(NRC_SYNAPSE)
echo " <command>[vis] -noambient \"[MapFile]\"</command>" >> $(NRC_SYNAPSE)
echo " </build>" >> $(NRC_SYNAPSE)
echo " <build name=\"qbsp, qvis -noambient, qrad\">" >> $(NRC_SYNAPSE)
echo " <command>[bsp] \"[MapFile]\"</command>" >> $(NRC_SYNAPSE)
echo " <command>[vis] -noambient \"[MapFile]\"</command>" >> $(NRC_SYNAPSE)
echo " <command>[light] \"[MapFile]\"</command>" >> $(NRC_SYNAPSE)
echo " </build>" >> $(NRC_SYNAPSE)
echo " <build name=\"qbsp, qvis -noambient, qrad -extra\">" >> $(NRC_SYNAPSE)
echo " <command>[bsp] \"[MapFile]\"</command>" >> $(NRC_SYNAPSE)
echo " <command>[vis] -noambient \"[MapFile]\"</command>" >> $(NRC_SYNAPSE)
echo " <command>[light] -extra \"[MapFile]\"</command>" >> $(NRC_SYNAPSE)
echo " </build>" >> $(NRC_SYNAPSE)
echo " <build name=\"qbsp, qvis -noambient, qrad -extra4x4\">" >> $(NRC_SYNAPSE)
echo " <command>[bsp] \"[MapFile]\"</command>" >> $(NRC_SYNAPSE)
echo " <command>[vis] -noambient \"[MapFile]\"</command>" >> $(NRC_SYNAPSE)
echo " <command>[light] -extra4x4 \"[MapFile]\"</command>" >> $(NRC_SYNAPSE)
echo " </build>" >> $(NRC_SYNAPSE)
echo " <build name=\"qbsp, qvis -noambient -fast\">" >> $(NRC_SYNAPSE)
echo " <command>[bsp] \"[MapFile]\"</command>" >> $(NRC_SYNAPSE)
echo " <command>[vis] -noambient -fast \"[MapFile]\"</command>" >> $(NRC_SYNAPSE)
echo " </build>" >> $(NRC_SYNAPSE)
echo " <build name=\"qbsp, qvis -noambient -fast, qrad\">" >> $(NRC_SYNAPSE)
echo " <command>[bsp] \"[MapFile]\"</command>" >> $(NRC_SYNAPSE)
echo " <command>[vis] -noambient -fast \"[MapFile]\"</command>" >> $(NRC_SYNAPSE)
echo " <command>[light] \"[MapFile]\"</command> </build>" >> $(NRC_SYNAPSE)
echo " <build name=\"qbsp, qvis -noambient -fast, qrad -extra\">" >> $(NRC_SYNAPSE)
echo " <command>[bsp] \"[MapFile]\"</command>" >> $(NRC_SYNAPSE)
echo " <command>[vis] -noambient -fast \"[MapFile]\"</command>" >> $(NRC_SYNAPSE)
echo " <command>[light] -extra \"[MapFile]\"</command>" >> $(NRC_SYNAPSE)
echo " </build>" >> $(NRC_SYNAPSE)
echo " <build name=\"qbsp, qvis -noambient -fast, qrad -extra4x4\">" >> $(NRC_SYNAPSE)
echo " <command>[bsp] \"[MapFile]\"</command>" >> $(NRC_SYNAPSE)
echo " <command>[vis] -noambient -fast \"[MapFile]\"</command>" >> $(NRC_SYNAPSE)
echo " <command>[light] -extra4x4 \"[MapFile]\"</command>" >> $(NRC_SYNAPSE)
echo " </build>" >> $(NRC_SYNAPSE)
echo "</project>" >> $(NRC_SYNAPSE)

11
README
View file

@ -1,4 +1,4 @@
Nuclide-Vanilla
Nuclide-Lite
This is a tiny pet project that will offer you a bit of Nuclide
for the most barebone Quake engine on planet Earth: Quake.
@ -12,7 +12,7 @@ such as the Dreamcast without doing any heavy engine modifications.
Games can then query a very simple API and get started making games rather quickly!
There are 3 sample directories. Each has a different engine/protocol target:
q1 = Quake, qw = QuakeWorld, h2 = Hexen II.
id1 = Quake, qw = QuakeWorld, data1 = Hexen II.
Copy the base you'd like to target. If you need to switch targets later down the
line simply either this to your progs.src:
@ -24,5 +24,10 @@ This will make Nuclide target those protocol standards instead.
Games should ideally not break. Nuclide tries its best to ensure the code
builds, but the behaviour may be slightly different between the targets.
Read BUILDING for details on how to make use of the Makefile switches
available in the project.
Hope you enjoy,
Marco
Marco Cawthorne
Vera Visions, LLC

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, "NuclideLite", 11))
{
strncpy (qdir, path, c+12-path);
printf ("qdir: %s\n", qdir);
c += 12;
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 'NuclideLite' 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;
}

128
Tools/Source/wav2loop.c Normal file
View file

@ -0,0 +1,128 @@
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <unistd.h>
/* so it's easier to fwrite */
typedef struct
{
char cuehead[4];
int chunk_size;
int numcues;
int cueid;
int cuepos;
char datahead[4];
int chunk_start;
int block_start;
int sample_offset;
} loop_t;
/* -o enables users to specify at which point in the sample to start */
static int sample_offset;
void process_wav2loop(char *filename)
{
FILE *fWAV;
FILE *fLOOP;
size_t szWAV;
char *buffer;
loop_t loopy;
fWAV = fopen(filename, "rb");
if (!fWAV) {
fprintf(stderr, "couldn't find %s\n", filename);
return;
}
/* get wav file size */
fseek(fWAV, 0L, SEEK_END);
szWAV = (size_t)ftell(fWAV);
fseek(fWAV, 0L, SEEK_SET);
/* load wav into memory */
buffer = (char *)malloc(szWAV);
if (buffer == NULL) {
fprintf(stderr, "error: Memory allocation failed. Exiting.\n");
exit(0);
}
fread(buffer, 1, szWAV, fWAV);
fclose(fWAV);
/* this is LAZY, however we're not going to bother writing a full WAV loader LMAO */
for (int i = 0; i < (szWAV - 4); i++ ) {
if (buffer[i] == 'c')
if (buffer[i+1] == 'u')
if (buffer[i+2] == 'e')
if (buffer[i+3] == ' ') {
fprintf(stderr, "wav file %s has cue info already\n", filename);
goto end;
}
}
/* this is quite stupid, we're just appending it at the end,
we don't even care if there already are other cue marks */
fLOOP = fopen(filename, "w+b");
fwrite(buffer, 1, szWAV, fLOOP);
loopy.cuehead[0] = 'c';
loopy.cuehead[1] = 'u';
loopy.cuehead[2] = 'e';
loopy.cuehead[3] = ' ';
loopy.chunk_size = 28;
loopy.numcues = 1;
loopy.cueid = 0;
loopy.cuepos = 0;
loopy.datahead[0] = 'd';
loopy.datahead[1] = 'a';
loopy.datahead[2] = 't';
loopy.datahead[3] = 'a';
loopy.chunk_start = 0;
loopy.block_start = 0;
loopy.sample_offset = sample_offset;
/* append our data to the end of the file */
fwrite(&loopy, 1, sizeof(loop_t), fLOOP);
fclose(fLOOP);
/* inb4 goto considered harmful */
end:
free(buffer);
}
int main(int argc, char *argv[])
{
int c, ch;
if (argc <= 1) {
fprintf(stderr, "usage: wav2loop [-o offset] file.wav ...\n");
return 1;
}
/* by default, we loop at the very start */
sample_offset = 0;
/* process arguments: TODO: add more? probably not */
while ((ch = getopt(argc, argv, "o")) != -1) {
switch (ch) {
case 'o':
sample_offset = atoi(argv[optind]);
optind++;
printf("sample offset: %i\n", sample_offset);
break;
default:
return 1;
}
}
argc -= optind;
argv += optind;
for (c = 0; c < argc; c++)
process_wav2loop(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

40
Tools/build_maps.sh Executable file
View file

@ -0,0 +1,40 @@
#!/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")"
LD_LIBRARY_PATH="$CWD" PATH="$PATH:$OLDDIR" qbsp -wadpath "$CWD/$GAMEDIR" "$MAPFILE"
LD_LIBRARY_PATH="$CWD" PATH="$PATH:$OLDDIR" qvis "$MAPFILE"
LD_LIBRARY_PATH="$CWD" PATH="$PATH:$OLDDIR" qrad -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
find "$GAMEDIR/mapsrc/" -name "*.lit" | 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"
"$CWD/iqmtool" $(basename "$LINE")
done
}
build_models $1

51
Tools/build_wads.sh Executable file
View file

@ -0,0 +1,51 @@
#!/bin/sh
# ensure we use the tools provided in root
export PATH="$(pwd):$PATH"
CWD=$(pwd)
PALETTE="palette_nofb.lmp"
# 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" = "gfx" ]
then
PALETTE="palette.lmp"
fi
if [ ! "$DIRNAME" = "." ]
then
if [ -f "$WADDIR/WAD3" ]
then
printf "WAD3 building %s:\n" "$DIRNAME"
imgtool --genwad3 ../"$DIRNAME".wad ./"$DIRNAME"
else
if [ -f "../gfx/$PALETTE" ]
then
printf "WAD2 Building %s:\n" "$DIRNAME"
if [ -f "$CWD/$1/texturesrc/$DIRNAME/palette.lmp" ]
then
imgtool --palette "$CWD/$1/texturesrc/$DIRNAME/palette.lmp" --genwad2 ../"$DIRNAME".wad ./"$DIRNAME"
else
imgtool --palette ../gfx/$PALETTE --genwad2 ../"$DIRNAME".wad ./"$DIRNAME"
fi
else
printf "WAD2 (using Quake palette) building %s:\n" "$DIRNAME"
imgtool --genwad2 ../"$DIRNAME".wad ./"$DIRNAME"
fi
fi
fi
done
}
build_wads $1

14
Tools/make_launcher.sh Executable file
View file

@ -0,0 +1,14 @@
#!/bin/sh
if [ $# -lt 3 ]; then
printf "make_launcher.sh DIR COMMAND DESTINATION\n"
exit
fi
DIR="$1"
COMMAND="$2"
DEST="$3"
printf "#/bin/sh\ncd \"$DIR\"\n$COMMAND \$*\n" > "$DEST"
chmod +x "$DEST"

27
Tools/make_map.sh Executable file
View file

@ -0,0 +1,27 @@
#!/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')
LITOUT=$(echo "$TARGET" | sed 's/\.bsp/\.lit/g')
LITFILE=$(echo "$TARGET" | sed 's/\.bsp/\.lit/g' | 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" qrad -extra4 "$MAPFILE"
cd "$OLDDIR"
mv -v "$MAPOUT" "$TARGET"
mv -v "$LITFILE" "$LITOUT"
fi

47
Tools/make_mapdef.sh Executable file
View file

@ -0,0 +1,47 @@
#!/bin/sh
CWD="$(pwd)"
ent_for_mod()
{
# don't bother if we don't have sources
if ! [ -f "$CWD/$1/src/progs.src" ]; then
exit
fi
mkdir -p "$CWD/$1/scripts"
ENT_OUTFILE="$CWD/$1/scripts/entities.def"
echo '' > "$ENT_OUTFILE"
echo "Scanning for definitions inside the game directory."
find "$CWD/src/" -type f \( -iname \*.qc \) | while read EDEF_N; do
echo "... $EDEF_N"
sed -n '/\/*QUAKED/,/*\//p' $EDEF_N >> "$ENT_OUTFILE"
done;
echo "Scanning for definitions inside the game directory."
find "$CWD/$1/src/" -type f \( -iname \*.qc \) | while read EDEF_N; do
echo "... $EDEF_N"
sed -n '/\/*QUAKED/,/*\//p' $EDEF_N >> "$ENT_OUTFILE"
done;
cat "$CWD/Tools/base_entities.def" >> $ENT_OUTFILE
}
# first dump all the general purpose entities
BASE_ENT="$CWD/Tools/base_entities.def"
echo '' > "$BASE_ENT"
echo "Scanning for definitions inside the general entity codebase."
find "$CWD/src/entities/" -type f \( -iname \*.qc \) | while read EDEF_N; do
echo "... $EDEF_N"
sed -n '/\/*!QUAKED/,/*\//p' $EDEF_N >> "$BASE_ENT"
# fix doxygen markup
done;
sed -i 's/*!QUAKED/*QUAKED/g' "$BASE_ENT"
# each game gets its own ents + general purpose ents appended at the end
if [ $# -gt 0 ]; then
ent_for_mod $1
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(H2CubeOfForce)
INIT_ITEM(H2Invincibility)
}
}

View file

@ -24,4 +24,5 @@ items/torch.qc
rules.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

34
id1/src/decor/flame.qc Normal file
View file

@ -0,0 +1,34 @@
class quakeFlame:ncDecor {
void quakeFlame( void );
virtual void Spawn( void );
};
void quakeFlame::quakeFlame( void ) {
}
void quakeFlame::Spawn( void ) {
StaticDecor( "progs/flame2.mdl", "ambience/fire1.wav" );
}
/*QUAKED light_flame_large_yellow (0 .5 0) (-10 -10 -20) (10 10 20)
# OVERVIEW
Large yellow flame. Respects the light values from the `light` entity.
*/
LINK_ENTITY_TO_CLASS(light_flame_large_yellow, quakeFlame)
/*QUAKED light_flame_small_yellow (0 .5 0) (-10 -10 -20) (10 10 20)
# OVERVIEW
Small yellow flame. Respects the light values from the `light` entity.
*/
LINK_ENTITY_TO_CLASS(light_flame_small_yellow, quakeFlame)
/*QUAKED light_flame_small_white (0 .5 0) (-10 -10 -20) (10 10 20)
# OVERVIEW
Small white flame. Respects the light values from the `light` entity.
*/
LINK_ENTITY_TO_CLASS(light_flame_small_white, quakeFlame)

20
id1/src/decor/globe.qc Normal file
View file

@ -0,0 +1,20 @@
class quakeLightGlobe:ncDecor {
void quakeLightGlobe( void );
virtual void Spawn( void );
};
void quakeLightGlobe::quakeLightGlobe( void ) {
}
void quakeLightGlobe::Spawn( void ) {
StaticDecor( "progs/s_light.spr", "" );
}
/*QUAKED light_globe (0 1 0) (-8 -8 -8) (8 8 8)
# OVERVIEW
Sphere globe light. Respects the light values from the `light` entity.
*/
LINK_ENTITY_TO_CLASS(light_globe, quakeLightGlobe)

21
id1/src/decor/torch.qc Normal file
View file

@ -0,0 +1,21 @@
class quakeTorch:ncDecor
{
void quakeTorch( void );
virtual void Spawn( void );
};
void quakeTorch::quakeTorch( void ) {
}
void quakeTorch::Spawn( void ) {
StaticDecor( "progs/flame.mdl", "ambience/fire1.wav" );
}
/*QUAKED light_torch_small_walltorch (0 .5 0) (-10 -10 -20) (10 10 20)
# OVERVIEW
Wall torch. Respects the light values from the `light` entity.
*/
LINK_ENTITY_TO_CLASS(light_torch_small_walltorch, quakeTorch)

View file

@ -7,3 +7,5 @@ float WEAPON_GRENADE_LAUNCHER = 16;
float WEAPON_ROCKET_LAUNCHER = 32;
float WEAPON_LIGHTNING = 64;
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( Q1Lightning )
INIT_ITEM( Q1Quad )
}
}

165
id1/src/monsters/army.qc Normal file
View file

@ -0,0 +1,165 @@
enum
{
armyAnim_stand1,
armyAnim_stand2,
armyAnim_stand3,
armyAnim_stand4,
armyAnim_stand5,
armyAnim_stand6,
armyAnim_stand7,
armyAnim_stand8,
armyAnim_death1,
armyAnim_death2,
armyAnim_death3,
armyAnim_death4,
armyAnim_death5,
armyAnim_death6,
armyAnim_death7,
armyAnim_death8,
armyAnim_death9,
armyAnim_death10,
armyAnim_deathc1,
armyAnim_deathc2,
armyAnim_deathc3,
armyAnim_deathc4,
armyAnim_deathc5,
armyAnim_deathc6,
armyAnim_deathc7,
armyAnim_deathc8,
armyAnim_deathc9,
armyAnim_deathc10,
armyAnim_deathc11,
armyAnim_load1,
armyAnim_load2,
armyAnim_load3,
armyAnim_load4,
armyAnim_load5,
armyAnim_load6,
armyAnim_load7,
armyAnim_load8,
armyAnim_load9,
armyAnim_load10,
armyAnim_load11,
armyAnim_pain1,
armyAnim_pain2,
armyAnim_pain3,
armyAnim_pain4,
armyAnim_pain5,
armyAnim_pain6,
armyAnim_painb1,
armyAnim_painb2,
armyAnim_painb3,
armyAnim_painb4,
armyAnim_painb5,
armyAnim_painb6,
armyAnim_painb7,
armyAnim_painb8,
armyAnim_painb9,
armyAnim_painb10,
armyAnim_painb11,
armyAnim_painb12,
armyAnim_painb13,
armyAnim_painb14,
armyAnim_painc1,
armyAnim_painc2,
armyAnim_painc3,
armyAnim_painc4,
armyAnim_painc5,
armyAnim_painc6,
armyAnim_painc7,
armyAnim_painc8,
armyAnim_painc9,
armyAnim_painc10,
armyAnim_painc11,
armyAnim_painc12,
armyAnim_painc13,
armyAnim_run1,
armyAnim_run2,
armyAnim_run3,
armyAnim_run4,
armyAnim_run5,
armyAnim_run6,
armyAnim_run7,
armyAnim_run8,
armyAnim_shoot1,
armyAnim_shoot2,
armyAnim_shoot3,
armyAnim_shoot4,
armyAnim_shoot5,
armyAnim_shoot6,
armyAnim_shoot7,
armyAnim_shoot8,
armyAnim_shoot9,
armyAnim_prowl_1,
armyAnim_prowl_2,
armyAnim_prowl_3,
armyAnim_prowl_4,
armyAnim_prowl_5,
armyAnim_prowl_6,
armyAnim_prowl_7,
armyAnim_prowl_8,
armyAnim_prowl_9,
armyAnim_prowl_10,
armyAnim_prowl_11,
armyAnim_prowl_12,
armyAnim_prowl_13,
armyAnim_prowl_14,
armyAnim_prowl_15,
armyAnim_prowl_16,
armyAnim_prowl_17,
armyAnim_prowl_18,
armyAnim_prowl_19,
armyAnim_prowl_20,
armyAnim_prowl_21,
armyAnim_prowl_22,
armyAnim_prowl_23,
armyAnim_prowl_24,
};
class quakeSoldier:ncActor {
void quakeSoldier( void );
virtual void Precache( void );
virtual void Spawn( void );
};
void quakeSoldier::quakeSoldier( void ) {
}
void quakeSoldier::Precache( void ) {
ncEngine::Precache_Model( "progs/soldier.mdl" );
ncEngine::Precache_Model( "progs/gib1.mdl" );
ncEngine::Precache_Model( "progs/gib2.mdl" );
ncEngine::Precache_Model( "progs/gib3.mdl" );
ncEngine::Precache_Model( "progs/h_guard.mdl" );
ncEngine::Precache_Sound( "player/udeath.wav" );
ncEngine::Precache_Sound( "soldier/death1.wav" );
ncEngine::Precache_Sound( "soldier/idle.wav" );
ncEngine::Precache_Sound( "soldier/pain1.wav" );
ncEngine::Precache_Sound( "soldier/pain2.wav" );
ncEngine::Precache_Sound( "soldier/sattck1.wav" );
ncEngine::Precache_Sound( "soldier/sight1.wav" );
}
void quakeSoldier::Spawn( void ) {
SetModel( "progs/soldier.mdl" );
SetSize( VEC_HULL_MIN, VEC_HULL_MAX );
SetWalkCycle( armyAnim_run1, armyAnim_run8, 10.0f );
SetIdleCycle( armyAnim_stand1, armyAnim_stand8, 10.0f );
SetHealth( 30 );
}
/*QUAKED monster_army (1 0 0) (-16 -16 -24) (16 16 32) AMBUSH
# OVERVIEW
Soldier. Health: 30.
# KEYS
- "targetname" : Name
# SPAWNFLAGS
- AMBUSH (1) : Ambush!
*/
LINK_ENTITY_TO_CLASS(monster_army, quakeSoldier)

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

@ -12,10 +12,15 @@ weapons/rocketlauncher.qc
weapons/shotgun.qc
weapons/supernailgun.qc
weapons/supershotgun.qc
monsters/army.qc
decor/flame.qc
decor/globe.qc
decor/torch.qc
items/quad.qc
rules.qc
player.qc
init.qc
files.qc
#endlist

View file

@ -0,0 +1,46 @@
class Q1Shotgun:ncItem {
void Q1Shotgun( void );
virtual void Precache( void );
virtual void Draw( ncEntity );
virtual void PrimaryAttack( ncEntity );
virtual void OnPickup( ncEntity );
virtual void OnWorldImpact( vector, vector );
};
void Q1Shotgun::Q1Shotgun( void ) {
}
void Q1Shotgun::Precache( void ) {
ncEngine::Precache_Model( "progs/v_shot.mdl" );
SetWeaponID( WEAPON_SHOTGUN );
}
void Q1Shotgun::Draw( ncEntity carrier ) {
carrier.hud.SetWeaponModel("progs/v_shot.mdl");
carrier.hud.SetWeaponFrame( 0 );
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 ) {
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 ) {
carrier.SPrint( PRINT_LOW, carrier.netname );
carrier.SPrint( PRINT_LOW, " picked up a shotgun!\n" );
}
void Q1Shotgun::OnWorldImpact( vector endPos, vector planeNormal ) {
ncFX::CastBlood( endPos );
}
LINK_ENTITY_TO_CLASS(weapon_shotgun, Q1Shotgun)

View file

@ -1,37 +0,0 @@
class Q1Shotgun:ncItem {
void Q1Shotgun( void );
virtual void Precache( void );
virtual void Draw( ncEntity );
virtual void PrimaryAttack( ncEntity );
virtual void OnPickup( ncEntity );
};
void Q1Shotgun::Q1Shotgun( void ) {
}
void Q1Shotgun::Precache( void ) {
ncEngine::Precache_Model( "progs/v_shot.mdl" );
SetWeaponID( WEAPON_SHOTGUN );
}
void Q1Shotgun::Draw( ncEntity carrier ) {
carrier.hud.SetWeaponModel("progs/v_shot.mdl");
carrier.hud.SetWeaponFrame(0);
carrier.hud.SetAmmo(AMMO_CURRENT, 20);
}
void Q1Shotgun::PrimaryAttack( ncEntity carrier ) {
carrier.SPrint(PRINT_LOW, "Pew\n");
carrier.SetNextPrimaryAttack(0.5f);
}
void Q1Shotgun::OnPickup( ncEntity carrier ) {
carrier.SPrint(PRINT_LOW, carrier.netname );
carrier.SPrint(PRINT_LOW, " picked up a shotgun!\n");
}
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
#pragma progs_dat "../progs.dat"
#pragma progs_dat "../qwprogs.dat"
#includelist
../../src/include.src
files.qc
#endlist

View file

@ -9,4 +9,12 @@ void idFuncCroucharea::idFuncCroucharea( void ) {
SetModel(GetModel()); /* relink with the above properties */
}
/*QUAKED func_croucharea (1 0 0) ?
# OVERVIEW
Crouch area. Will become non-solid when the player is crouched.
# KEYS
- "targetname" : Name
*/
LINK_ENTITY_TO_CLASS(func_croucharea, idFuncCroucharea)

View file

@ -0,0 +1,50 @@
/*QUAKED func_detail (0.5 0.5 0.9) ?
# OVERVIEW
Detail brush. Special compiler specific entity that
will be ignored by the vis compiler operations, but
the surrounding geometry may still be cut up.
# KEYS
- "_shadow" : When 0, will not cast a shadow.
*/
/*QUAKED func_detail_illusionary (0.5 0.5 0.9) ?
# OVERVIEW
Non-solid variant of func_detail.
# KEYS
- "_shadow" : When 1, will cast a shadow.
*/
/*QUAKED func_detail_wall (0.5 0.5 0.9) ?
# OVERVIEW
Detail brush that will not cut up geometry, unlike func_detail.
Will still clip surfaces away that are obscured, unlike func_detail_fence.
# KEYS
- "_shadow" : When 0, will not cast a shadow.
*/
/*QUAKED func_detail_fence (0.5 0.5 0.9) ?
# OVERVIEW
Detail brush. Special compiler specific entity that
will be ignored by the vis compiler operations.
# KEYS
- "_shadow" : When 0, will not cast a shadow.
*/
/*QUAKED func_illusionary_visblocker (0.5 0.5 0.9) ?
# OVERVIEW
Non-solid func_detail brush that still culls rendering behind it.
Much like liquid brushes pre WaterVis patches behaved.
# KEYS
- "_shadow" : When 1, will cast a shadow.
*/

View file

@ -126,4 +126,16 @@ void ncFuncDoor::MoverFinishesMoving( void ) {
}
}
/*QUAKED func_door (0 .5 .8) ? STARTOPEN x DONTLINK x x TOGGLE
# OVERVIEW
Door that moves along an axis.
# KEYS
- "targetname" : Name
- "angles" : Movement direction.
- "speed" : Movement speed in units per second.
- "wait" : Wait this many seconds before returning. -1 means wait infinitely.
- "lip" : Leave this many units of the door showing.
*/
LINK_ENTITY_TO_CLASS( func_door, ncFuncDoor )

View file

@ -13,4 +13,12 @@ void idFuncIllusionary::idFuncIllusionary( void ) {
SetAbsoluteLightlevel(0.1);
}
/*QUAKED func_illusionary (0 .5 .8) ?
# OVERVIEW
Non-solid wall.
# KEYS
- "targetname" : Name
*/
LINK_ENTITY_TO_CLASS(func_illusionary, idFuncIllusionary)

View file

@ -9,4 +9,12 @@ void idFuncWall::idFuncWall( void ) {
SetModel(GetModel()); /* relink with the above properties */
}
/*QUAKED func_wall (0 .5 .8) ?
# OVERVIEW
Solid wall.
# KEYS
- "targetname" : Name
*/
LINK_ENTITY_TO_CLASS(func_wall, idFuncWall)

View file

@ -6,6 +6,17 @@ void idNull::idNull( void ) {
}
/*QUAKED info_null (0 .5 0) (-4 -4 -4) (4 4 4)
*/
LINK_ENTITY_TO_CLASS(info_null, idNull)
/*QUAKED info_notnull (0 .5 0) (-4 -4 -4) (4 4 4)
*/
LINK_ENTITY_TO_CLASS(info_notnull, idNull)
LINK_ENTITY_TO_CLASS(info_teleport_destination, idNull)
/*QUAKED info_teleport_destination (.5 .5 .5) (-8 -8 -8) (8 8 32)
*/
LINK_ENTITY_TO_CLASS(info_teleport_destination, idNull)

View file

@ -23,7 +23,18 @@ ncEntity ncPlayerStart::MovePlayerToStart( ncPlayer player ) {
}
}
/*QUAKED info_player_start (1 0 0) (-16 -16 -24) (16 16 32)
*/
LINK_ENTITY_TO_CLASS(info_player_start, ncPlayerStart)
/*QUAKED info_player_deathmatch (1 0 1) (-16 -16 -24) (16 16 32)
*/
LINK_ENTITY_TO_CLASS(info_player_deathmatch, ncPlayerStart)
/*QUAKED info_player_coop (1 0 1) (-16 -16 -24) (16 16 32)
*/
LINK_ENTITY_TO_CLASS(info_player_coop, ncPlayerStart)
LINK_ENTITY_TO_CLASS(info_player_start2, ncPlayerStart)
/*QUAKED info_player_start2 (1 0 0) (-16 -16 -24) (16 16 32)
*/
LINK_ENTITY_TO_CLASS(info_player_start2, ncPlayerStart)

View file

@ -1,31 +0,0 @@
class ncLight:ncEntity {
void ncLight( void );
nonvirtual float LightLevelForEntity( ncEntity );
};
void ncLight::ncLight( void ) {
}
#ifndef TARGET_HEXEN2
.float light_level;
#endif
float ncLight::LightLevelForEntity( ncEntity target ) {
float maxDistance = 150; /* Q1/H2 = linear falloff */
float currDistance = ncMath::VLen(GetOrigin() - target.GetOrigin());
if (currDistance > maxDistance)
return 0.0f;
ncEngine::TraceLine(GetOrigin(), target.GetOrigin(), FALSE, this);
if ( ( trace_ent == target ) || ( trace_fraction == 1.0f ) ) {
return maxDistance - currDistance;
} else {
return 0.0f;
}
}
LINK_ENTITY_TO_CLASS(light, ncLight)

View file

@ -4,10 +4,13 @@ func_door.qc
func_illusionary.qc
info_null.qc
info_player_start.qc
light.qc
trigger_auto.qc
trigger_changelevel.qc
trigger_teleport.qc
trigger_multiple.qc
trigger_once.qc
trigger_relay.qc
trigger_secret.qc
camera_node.qc
worldspawn.qc
#endlist

View file

@ -13,8 +13,7 @@ void idTriggerChangelevel::idTriggerChangelevel( void ) {
SetTouchCallback( ChangelevelTouched );
}
string idTriggerChangelevel::GetNextLevel( void )
{
string idTriggerChangelevel::GetNextLevel( void ) {
return map;
}
@ -24,4 +23,4 @@ void idTriggerChangelevel::ChangelevelTouched( ncEntity toucher ) {
}
}
LINK_ENTITY_TO_CLASS(trigger_changelevel, idTriggerChangelevel)
LINK_ENTITY_TO_CLASS(trigger_changelevel, idTriggerChangelevel)

View file

View file

View file

@ -0,0 +1,77 @@
class ncTriggerMultiple:ncEntity {
void ncTriggerMultiple( void );
nonvirtual void TriggerVolumeTouched( ncEntity );
};
void ncTriggerMultiple::ncTriggerMultiple( void ) {
InitTrigger();
SetTouchCallback( TriggerVolumeTouched );
SPAWNDEFAULT( wait, 0.2f )
}
.float trigger_next;
void ncTriggerMultiple::TriggerVolumeTouched( ncEntity toucher ) {
vector moveDir = ncMath::AnglesToMoveDir( GetAngles() );
if ( trigger_next > time ) {
return;
}
if ( !toucher.IsPlayer() ) {
return;
}
if (moveDir != g_vec_null) {
if (ncMath::AnglesToForward(toucher.GetAngles()) * moveDir < 0.0f) {
return;
}
}
if (classname == "ncTriggerSecret") {
if (toucher.classname != "player") {
return;
}
found_secrets = found_secrets + 1;
ncNet::WriteByte( MSG_ALL, SVC_FOUNDSECRET );
ncNet::MultiCast( [0,0,0], MSG_ALL );
}
ActivateTargets();
toucher.CenterPrint(message);
/* remove */
if (wait == -1) {
Remove();
return;
}
trigger_next = time + wait;
}
/*QUAKED trigger_multiple (.5 .5 .5) ? TRIGGER_ONLY
# OVERVIEW
Variable sized trigger volume.
# KEYS
- "targetname" : Name.
- "target" : Name of entities to activate.
- "health" : If set will need to be be destroyed to be activated, and will have this much health.
- "wait" : Waiting period until it can activate again. 0.2 is the default.
- "delay" : Delay before activating its targets.
- "killtarget" : Removes these entities upon use.
- "angle" : Activator has to face this direction in order to activate.
- "message" : Print this message upon use.
- "sounds" : One of the following:
1) Secret Sound: misc/secret.wav
2) Chat Sound: misc/talk.wav
3) Trigger: misc/trigger1.wav
# SPAWNFLAGS
- TRIGGER_ONLY (1) : Cannot touch this trigger volume.
*/
LINK_ENTITY_TO_CLASS(trigger_multiple, ncTriggerMultiple)

View file

@ -0,0 +1,32 @@
class ncTriggerOnce:ncTriggerMultiple {
void ncTriggerOnce( void );
};
void ncTriggerOnce::ncTriggerOnce( void ) {
wait = -1;
}
/*QUAKED trigger_once (.5 .5 .5) ? TRIGGER_ONLY
# OVERVIEW
Variable sized trigger volume.
Triggers once, then removes itself.
# KEYS
- "targetname" : Name.
- "target" : Name of entities to trigger.
- "health" : If set will need to be be destroyed to be triggered, and will have this much health.
- "killtarget" : Removes these entities upon use.
- "angle" : Activator has to face this direction in order to trigger.
- "message" : Print this message upon use.
- "sounds" : One of the following:
1) Secret Sound: misc/secret.wav
2) Chat Sound: misc/talk.wav
3) Trigger: misc/trigger1.wav
# SPAWNFLAGS
- TRIGGER_ONLY (1) : Cannot touch this trigger volume.
*/
LINK_ENTITY_TO_CLASS(trigger_once, ncTriggerOnce)

View file

View file

View file

@ -0,0 +1,28 @@
class ncTriggerRelay:ncEntity {
void ncTriggerRelay( void );
};
void ncTriggerRelay::ncTriggerRelay( void ) {
InitTrigger();
SetTriggerCallback( ActivateTargets );
}
/*QUAKED trigger_relay (.5 .5 .5) (-8 -8 -8) (8 8 8)
# OVERVIEW
Point trigger.
# KEYS
- "targetname" : Name.
- "target" : Name of entities to activate.
- "delay" : Delay before activating its targets.
- "killtarget" : Removes these entities upon use.
- "message" : Print this message upon use.
- "sounds" : One of the following:
1) Secret Sound: misc/secret.wav
2) Chat Sound: misc/talk.wav
3) Trigger: misc/trigger1.wav
*/
LINK_ENTITY_TO_CLASS(trigger_relay, ncTriggerRelay)

View file

@ -0,0 +1,35 @@
class ncTriggerSecret:ncTriggerMultiple {
void ncTriggerSecret( void );
};
void ncTriggerSecret::ncTriggerSecret( void ) {
SPAWNDEFAULT( message, "You found a secret area!" )
SPAWNDEFAULT( sounds, 1 )
wait = -1;
total_secrets = total_secrets + 1;
}
/*QUAKED trigger_secret (.5 .5 .5) ? TRIGGER_ONLY
# OVERVIEW
Variable sized trigger volume.
Triggers once, then removes itself.
# KEYS
- "targetname" : Name.
- "target" : Name of entities to trigger.
- "health" : If set will need to be be destroyed to be triggered, and will have this much health.
- "killtarget" : Removes these entities upon use.
- "angle" : Activator has to face this direction in order to trigger.
- "message" : Print this message upon use.
- "sounds" : One of the following:
1) Secret Sound: misc/secret.wav
2) Chat Sound: misc/talk.wav
3) Trigger: misc/trigger1.wav
# SPAWNFLAGS
- TRIGGER_ONLY (1) : Cannot touch this trigger volume.
*/
LINK_ENTITY_TO_CLASS(trigger_secret, ncTriggerSecret)

View file

View file

@ -1,92 +1,4 @@
/* 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 ) {
if (time)
g_world_initialized = true;
@ -130,6 +42,9 @@ void PlayerPreThink( void ) {
if (pl.HasFlag(FL_JUMPRELEASED) && pl.HasFlag(FL_ONGROUND)) {
pl.RemoveFlags(FL_JUMPRELEASED | FL_ONGROUND);
pl.JumpPressed();
} else if (pl.HasFlag(FL_JUMPRELEASED)) {
pl.RemoveFlags(FL_JUMPRELEASED);
pl.JumpPressedInAir();
}
} else {
bool alreadyReleased = pl.HasFlag(FL_JUMPRELEASED) ? false : true;
@ -254,6 +169,7 @@ void ClientKill( void ) {
void ClientConnect( void ) {
Class_Player();
self.classname = "player";
g_gameRules.PlayerConnects( ( ncPlayer ) self );
}

18
src/system/Actor.qc Normal file
View file

@ -0,0 +1,18 @@
.movementType_t ncActor_movementType;
void ncActor::ncActor ( void ) {
}
void ncActor::_InternalPostSpawn ( void ) {
/* monsters are auto-aim by default */
SetTakedamage( DAMAGE_AIM );
SetSolid( SOLID_SLIDEBOX );
SetMovetype( MOVETYPE_STEP );
}
void ncActor::SetMovementType ( movementType_t newMovement ) {
/* monsters are auto-aim by default */
ncActor_movementType = newMovement;
}

14
src/system/Actor.qh Normal file
View file

@ -0,0 +1,14 @@
typedef enum
{
MOVEMENTTYPE_GROUND,
MOVEMENTTYPE_FLOATING,
MOVEMENTTYPE_SUBMERGED,
} movementType_t;
class ncActor : ncEntity {
void ncActor( void );
virtual void _InternalPostSpawn( void );
nonvirtual void SetMovementType( movementType_t );
};

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

@ -124,7 +124,7 @@ vector ncCamera::GetCameraAngles( void ) {
newAngle = ncMath::VecToAngles(newAngle);
#if 1
#if 0
newAngle[0] = ncMath::Rint(newAngle[0]);
newAngle[1] = ncMath::Rint(newAngle[1]);
newAngle[2] = ncMath::Rint(newAngle[2]);
@ -189,7 +189,7 @@ vector ncCamera::GetCameraOrigin( void ) {
break;
}
#if 1
#if 0
newOrigin[0] = ncMath::Rint(newOrigin[0]);
newOrigin[1] = ncMath::Rint(newOrigin[1]);
newOrigin[2] = ncMath::Rint(newOrigin[2]);
@ -217,4 +217,4 @@ ncCamera ncCamera::GetLastCamera( void ) {
ncCamera ncCamera::GetVeryNextCamera( void ) {
ncCamera nextCamera = GetNextCamera();
return ncEngine::Find( (ncEntity) world, ::targetname, nextCamera.next);
}
}

18
src/system/Decor.qc Normal file
View file

@ -0,0 +1,18 @@
void ncDecor::ncDecor( void ) {
}
void ncDecor::StaticDecor( string modelPath, string ambientSound ) {
if (ambientSound != "" && ambientSound != __NULL__) {
ncEngine::Precache_Sound( ambientSound );
ambientsound( GetOrigin(), ambientSound, 0.5, ATTN_STATIC );
}
if (modelPath != "" && modelPath != __NULL__) {
ncEngine::Precache_Model( modelPath );
SetModel( modelPath );
}
MakeStatic();
}

6
src/system/Decor.qh Normal file
View file

@ -0,0 +1,6 @@
class ncDecor:ncEntity {
void ncDecor( void );
nonvirtual void StaticDecor(string, string);
};

View file

@ -41,7 +41,9 @@ void ncEntity::PreThink( void ) {
}
void ncEntity::Trigger( ncEntity activatorEntity, triggerstate_t triggerType ) {
TriggerCallback(activatorEntity, triggerType);
if (TriggerCallback) {
TriggerCallback(activatorEntity, triggerType);
}
}
/* set functions */
@ -372,6 +374,11 @@ dead_t ncEntity::GetDeadFlag( void ) {
return (dead_t)deadflag;
}
vector ncEntity::GetEyePos( void ) {
return origin + view_ofs;
}
vector ncEntity::GetViewOffset( void ) {
return view_ofs;
}
@ -712,6 +719,16 @@ bool ncEntity::WithinBounds( ncEntity check ) {
return ( true );
}
.float delay;
void ncEntity::ActivateTargets( void )
{
static void ActivateTargets_Done( void ) {
TriggerTargets( this, TRIGGERSTATE_AUTO );
}
ScheduleThink(ActivateTargets_Done, delay);
}
void ncEntity::TriggerTargets( ncEntity activator, triggerstate_t triggertype )
{
string targetIdent = GetTarget();
@ -746,12 +763,58 @@ void ncEntity::PrimaryAttack( ncEntity 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;
}
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);
}
#ifndef TARGET_HEXEN2
.float light_level;
#endif
/* wannabe thief */
void ncEntity::CalculateLightLevel( void )
@ -770,4 +833,4 @@ void ncEntity::CalculateLightLevel( void )
light_level = lightValue;
#endif
}
}

View file

@ -190,6 +190,8 @@ public:
nonvirtual dead_t GetDeadFlag( void );
/** Returns the eye position of the entity relative to its origin. */
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. */
nonvirtual bool HasFlag( flags_t );
/** Returns the colormap id of the entity. */
@ -282,6 +284,7 @@ public:
/** Trigger all targets with their `targetname` set as the entity it's `target`. */
nonvirtual void TriggerTargets( ncEntity, triggerstate_t );
nonvirtual void ActivateTargets( void );
/** Overridable: When the entity has initialized, it will execute this method. */
virtual void Spawn( void );
@ -297,6 +300,12 @@ public:
virtual void PrimaryAttack( ncEntity );
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. */
nonvirtual void CalculateLightLevel( void );
@ -309,4 +318,4 @@ private:
var bool g_world_initialized;
.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
ncNet::WriteByte( FX_MSGTYPE, SVC_TEMP_ENTITY );
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[1] );
ncNet::WriteCoord( FX_MSGTYPE, targetPos[2] );
ncNet::MultiCast( targetPos, MULTICAST_PVS );
#else
Particle( targetPos, [0, 0, 0], 73, 1 );
Particle( targetPos, [0, 0, 0], 73, 8 );
#endif
}
@ -195,4 +195,4 @@ void ncFX::CastLightningBlood( ncEntity boltOwner, vector startPos, vector endPo
#ifndef TARGET_QUAKEWORLD
CastBlood(endPos);
#endif
}
}

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