The source of the game, which is written in C++, is freely available under the GPL.
Get the latest version from the Subversion repository on the
SourceForge site.
A Visual Studio 2008 (9.0) project is included to build the game on Windows. On Linux, cmake is used.
There is also a KDevelop 3 project which uses cmake internally and a (probably outdated) Code::Blocks project.
Technology
Forever War uses the following libraries which you must install in order to compile the code:
Library
|
|
Version
|
Ogre |
graphics engine |
1.6.x or 1.7.x |
bullet |
physics engine |
2.75 or later |
CEGUI |
graphical user interface
system |
0.7.1 |
OIS |
input system |
1.2.0, custom for linux* |
boost::thread |
thread support |
1.38 or later |
TinyXML |
xml file loader |
included in code |
lua |
scripting
language |
5.1.4 |
luabind |
C++ / lua binding |
0.9 |
* 1.2.0 with a patch for smoother mouse movement at low framerates - see the compiling instructions.
... and of course a modified version of the
PolyVox technology (included in code)!
If you need further assistance, have problems with the code or want to contribute, don't hesitate to post at the
developer forum.
Setting up a development environment for Forever War
Depending on your operating system, the required steps are quite different. Forever War supports two platforms:
Setting up a development environment on Windows (32 bit) using MinGW
Setting up a development environment on Linux
You might also be interested in a
rough overview of the game code.
Note that, sadly, this is a very length process. You will need some time.
You can find the recent download locations of the various required libraries and tools by doing a quick search.
Developer Tools
- Download and install CMake and Subversion (I used TortoiseSVN).
- Download and install MinGW (make sure you use the same compiler version as the one used to build the MinGW Ogre SDK which will be installed later; see the notes on this page for the required version)
- Download and install Code::Blocks
- You will have to add include and lib paths of the installed libraries to gcc's specs file so it can find them automatically, see this wiki page on how to do this.
Ogre
- Download the MinGW Ogre SDK and add the relevant paths (if you don't want to use the prebuilt SDK, you will have to install the DirectX SDK, OIS input system, boost and possibly further dependencies separatly).
- Also add the paths to the included boost files of version 1_42_0.
- Copy the boost thread library .lib file and rename the copy to libboost_thread-mt.a so it will be found by forever war.
- The included boost distribution is not complete. Luabind needs dynamic_bitset and pending which are not included. Luckily, they are header-only, so you can download boost in the same version as included with OGRE separatly and add the boost/dynamic_bitset and boost/pending directories to OGRE's boost distribution.
Bullet
- Download bullet, use CMake to generate the build files, and build it (theoretically).
- In practice, errors ocurred for me with bullet-2.76. Read this thread for help.
- Add the paths to <build directory>/lib and <bullet directory>/src
Lua
- Download and build Lua 5.1 (using "mindw32-make mingw"). Enter the src subdirectory as include and library path for gcc.
Luabind
- Download luabind. As I didn't succeed in using bjam, I created a Code::Blocks static link library project containing all luabind source files, added the paths to the headers and dependencies (boost and lua), and built the library this way using the Release build target.
- Add the paths to <luabind>/luabind and the library.
FreeType
- Download FreeType2 and invoke mingw32-make in the root directory of the extracted files two times(!).
- Add the paths <freetype>/include and <freetype>/objs
PCRE
- Download and build PCRE using CMake.
- Add paths to the build directory.
Expat
- Download the Expat parser (I used the binary files)
FreeImage
- Download it and add the paths to the <freeimage>/Dist directory.
CEGUI
- Download CEGUI
- Switch to the premake directory, carefully adjust the options in config.lua and run: "premake --file cegui.lua --target cb-gcc" to generate a Code::Blocks workspace called CEGUI.workspace in the same directory
- Add the paths to the freetype and pcre files in the build options of CEGUIBase. I had to rename freetype.a to libfreetype.a so the linker could find it. Also, the source files used a wrong config.h (not the one generated by premake); to resolve this, add the path to the own include files in the build options at the topmost position (move the entry with the arrows to the right).
- Add the paths to OGRE and boost to the build options of CEGUIOgreRenderer.
- Add the paths to <Expat>/Bin (libraries) and <Expat>/Source/Lib (headers) to the build options of CEGUIExpatParser
- Add the paths to the FreeImage files (<FreeImage>/Dist) to the build options of CEGUIFreeImageImageCodec
- Use this workspace to build CEGUIBase, CEGUIFalagardWRBase, CEGUIExpatParser, CEGUIFreeImageImageCodec and CEGUIOgreRenderer (make sure to set every project to the Release target)
- Add the paths to <CEGUI>/bin and <CEGUI>/cegui/include
ForeverWar
- Check out the source code using Subversion from the repository https://foreverwar.svn.sourceforge.net/svnroot/foreverwar
- Adjust the include and library paths for Windows in CMakeLists.txt to your system
- Run CMake and generate MinGW build files for ForeverWar. You will have to specify LUA51_INCLUDE_FILES and LUA51_LIBRARIES.
- cd into the directory where you generated the build files and run mingw32-make. Good luck! :-)
- Copy all needed dlls into the <trunk>/bin directory
- Start foreverwar.exe and enjoy!
This is a step-by-step guide on how to prepare Ubuntu 9.10 for Forever War development. For other Linux distributions the process should be similar. Let's begin:
Installing required packages
You need to install the following packages:
sudo apt-get install
subversion libboost1.38-dev libxaw7-dev libfreetype6-dev libpcre3-dev libglu1-mesa-dev libfreeimage-dev liblua5.1-0-dev boost-build libzzip-dev libxrandr-dev nvidia-cg-toolkit cmake freeglut3-dev
The remaining external libraries will be installed separately so you get the latest version and not the version in the Ubuntu repositories which is usually outdated. Follow the given order, or you may run into problems!
A general tip: if you have a multi-core machine, you can speed up compilation greatly by using the -j option to create multiple jobs, like this:
make -j4
Installing OIS
Download the latest release
here. The linux mouse support has a bug with low framerates in OIS 1.2.0, so you should take the
fixed LinuxMouse.cpp and replace ois/src/linux/LinuxMouse.cpp with it before compiling like this:
./bootstrap
./configure
make && sudo make install
Installing Bullet
Download the latest release of bullet, cd into the extracted folder and type:
./autogen.sh
./configure
make && sudo make install
Installing luabind
Warning: don't install the package from the repositories! As of Ubuntu 9.10, the version there (0.8.1) is outdated, using it results in irregular crashes.
Instead, download version 0.9. Then cd into the top folder and type:
sudo bjam install release
Installing Ogre
To check out the latest 1.6.x version of Ogre into a directory called "ogre", execute the following command:
svn co https://svn.ogre3d.org/svnroot/ogre/branches/v1-6 ogre
cd into the new directory and type:
./bootstrap
./configure
make && sudo make install
Installing CEGUI
Download the latest release of CEGUI, cd into the extracted folder and type:
./bootstrap
./configure
make && sudo make install
Getting the Forever War source from SVN
To check out all files into a directory called "ForeverWar", execute the following command:
svn co https://foreverwar.svn.sourceforge.net/svnroot/foreverwar/ ForeverWar
Compiling Forever War
In the ForeverWar trunk directory, create a direcory called "build" and cd into it, then type "cmake ../"
Now you can build the project from this directory using make. Run "sudo ldconfig" before so the linker finds the recently installed libraries.
Running Forever War
Copy the following files from /usr/local/lib/OGRE/ to trunk/bin:
Plugin_CgProgramManager.so
Plugin_OctreeSceneManager.so
Plugin_ParticleFX.so
RenderSystem_GL.so
You're ready, finally! :-)
Now you should be able to run the program (execute foreverwar in trunk/bin). Have fun!
If you want to debug the program, it's a good idea to change trunk/bin/settings.xml now (this file is generated on the first run).
There you can specify the resolution and that the program should run in windowed mode.
This is a
very rough overview of the inner workings of Forever War to get
you started if you want to have a look at the source code. If you have
a specific question, please post at the
developer forum!
The code is documented with Doxygen comments, but the frequency of these comments varies from file to file.
So don't expect that everything is completely documented if you generate a code overview using this tool.
Major parts of the program:
Part | Associated classes or files |
Voxel System | VoxelVolume, VoxelBlock and subclasses, VoxelBlockPersistent, SurfacePatch, SurfacePatchRenderable |
Object system | Object, Component, ObjectManager, Classes beginning with Component |
Lua integration | luaFunctions.h/cpp and exposeToLua.h |
Physics integration | Physics |
State manager | StateManager and Game, Menu ins stateGame.h/cpp and stateMenu.h/cpp |
AI | classes beginning with AI |
Other ... | |
Program startThe main method (which is in src/main.cpp, surprise!) is simple:
First it sets everything up (Ogre, Object Manager, etc.).
Then it gives control to the state manager (stateManager.h), which manages the menu and game state.
If the state manager signalizes that the game has ended, the main method cleans everything up.
Gamestate: Menu (class Menu in stateMenu.cpp/h)
The menu gamestate is just a placeholder which will be replaced when a real menu is necessary.
Gamestate: Game (class Game in stateGame.cpp/h)
Because
the "editor mode" (fly around and use the editor hud) and the "game
mode" (run through the world as player) are closely linked together,
the
Game state manages them both. To find out if the game mode is currently
active, you can check if the mPlayer member of Game is non-NULL.
The code for the editor mode is in stateGame.cpp, while most code for the player mode is in componentPlayer.cpp.
Voxel SystemThe
voxel system (based on the PolyVox technology) is responsible for the
world geometry. It keeps a 3D voxel grid which stores the voxel value
(a
signed char) and the texture number (an unsigned char) for every grid
point. If the voxel value is negative, the voxel represents air, if it
is positive, it represents ground. Smooth geometry is possible by
smoothly grading the values.
To
create triangles out of the voxel data, the Marching Cubes algorithm is
used. If the voxel values have changed (if the geometry was edited),
the triangles are simply regenerated from the voxels.
The class representing the world is called VoxelVolume (volume.cpp/h).
The
volume is separated into small "blocks" (size: 16x16x16 voxels). Every
block stores its own triangle data, so if a part of the world changes,
only the geometry of the affected blocks has to be regenerated.
The blocks are filled with voxel data in a separate loading thread.
VoxelVolume contains two equally-sized arrays (
blocks and
blocksPersistent).
blocks holds subclasses of the VoxelBlock class which
store the voxel data in different ways, while
blocksPersistent holds data which is needed always for every block and can be reused if the block type changes.
There are the following VoxelBlock subclasses:
VoxelBlockPlaceholderThis
type is used if the block is not loaded yet. The loading thread is
still working on it or this block doesn't need to be loaded for now. No
voxel data is stored in this type of block.
VoxelBlockLoadedA fully loaded block, stores voxel and texture data.
VoxelBlockEmptyA
block which contains only air. The voxel and texture values don't need
to be stored because there is no (triangle-) geometry in this block.
If you look up the value of a voxel in this block, -128 (minimum of signed char) will be returned.
VoxelBlockFullSimilar to the empty block. This type also doesn't store voxel data, but it stores texture data.
If you look up the value of a voxel in this block, 127 (maximum of signed char) will be returned.
Object SystemAlmost
everything you see in the world except the voxel geometry is handled as
an "object" by Forever War, for example enemies, weapons,
explosions, dust particles, or bullets.
The object system is based on the article "Component Based Object Management" from Game Programming Gems 5.
So,
every object is a ( std :: ) list of components which do all the work.
Object definitions are read in at startup from the .object files in
resource/object. To get a feeling for the way the objects are
assembled, it's best to view some of these files.
Every object
definition is a list of component templates. These templates must store
all neccessary parameters to create instances of the real components
when an instance of the object is created.
There are the following components:
MeshDisplays a 3D model
PhysicsInserts the object into the physics world
ParticleDisplays a particle system
WeaponLets the player take the object when running over it and use it as a weapon
TimerExecutes a lua script after the given time (for example: "blink every 1.5 seconds")
PlayerThe player
HealthAdds a health value to the object. A lua script is executed when the health decreases
ItemShows the object's name if the player targets it; allows the player to take the object (WIP)
CollisionListenerExecutes a lua script if the object collides with something
DamageEffects
Displays damage effects when the object is hit
AIExecutes an AI model for the object
BulletControls a bullet
Lua integration
To
be more flexible, the objects are scripted using lua. The game engine
functions callable by lua scripts are defined in luaFunctions.cpp/h and
exposed in exposeToLua.cpp/h.