# The Pyrogenesis Engine/Printable version

The current, editable version of this book is available in Wikibooks, the open-content textbooks collection, at
https://en.wikibooks.org/wiki/The_Pyrogenesis_Engine

# Introduction

Pyrogenesis is an open source game engine developed for the real-time strategy game 0 A.D. by Wildfire Games. Wildfire Games originated as a mod developer, releasing the mod Rome at War for Age of Empires II: The Age of Kings in 2001. The same year, development commenced on their next title, 0 A.D. Originally envisioned as a comprehensive total conversion mod of Age of Empires II: The Age of Kings, the team eventually decided to instead develop their own engine for the project - the Pyrogenesis engine. True to its roots, the engine was designed from the ground up to be easily moddable and in 2008 the team finally decided to release the whole project, including the Pyrogenesis engine, as open source.

### Features
#### Core

* Pathfinder.
* Support for saving and loading games.

#### Graphics

* OpenGL-based rendering engine with support for both ARB and GLSL shaders.
* Realistic shadows with shadow mapping and shadow filtering (PCF).
* Materials system for both models and terrain.
* Normal, parallax, specular and emissive mapping.
* Ambient occlusion.
* HDR rendering and bloom.
* Animated water plane with refraction and reflection.
* Hierarchal skeletal animation and deformation system based on COLLADA.
* Particle effects.
* Triplanar texture mapping.
* Environmental lighting effects (time of day, sunset).
* Flexible terrain renderer using alpha maps to seamlessly blend terrain.

#### Audio

* OpenAL-based sound manager.

#### User Interface
### Platforms
#### Supported languages

C++ and JavaScript.

#### Supported operating systems

Windows, OS X and Linux.

### License

GPL.

### Where to get it?

The Pyrogenesis engine is not yet packaged separately, but all the source code for 0 A.D. can be downloaded from: svn.wildfiregames.com or github.com/0ad.

# Overview

Pyrogenesis has two faces: one, the core engine itself, is written in C++. Ideally, only the most low-level functionality, which requires access to system interfaces or crucially needs to be very fast, is implemented here.
The other face of Pyrogenesis is a Javascript interface, which is accessed by specialized scripts through a number of runtimes.
Each runtime can be thought of as an instance of the SpiderMonkey Javascript interpreter used by the Pyrogenesis engine - it is a scripting environment or sandbox in which Javascript scripts are executed. Every runtime runs in isolation and can not immediately interact with the state of the other runtimes.
About scripting: engine creates multiple JS runtimes, one for simulation, one for AI, one for GUI and one for RMS. (Others?)

# Simulation

The most important aspect of any game is its gameplay. In Pyrogenesis, the simulation can be thought of as the place where gameplay is executed. The simulation is the part of the engine that takes commands from the players (including the AI) and turns them into actions in the game world.
The simulation subsystem is defined in simulation2/Simulation2.cpp. Its central class, CSimulation2Impl is instantiated by ???, constructed from a unit manager (CUnitManager) and a terrain (CTerrain). From this alone, we can deduce that the simulation deals with how units interact with each other and with the terrain of a map.
When CSimulation2Impl is instantiated, it also initializes a component manager (CComponentManager?). Components are one of the most crucial concepts to grasp in order to understand how the simulation works. Programatically, components are merely subsystems accessed via the component manager. For instance, there is a pathfinder component for deriving the shortest path across a terrain, a sound manager component for outputting music and sound effects, and a projectile manager component for driving ballistic calculations of things like arrows and spears.
However, though each of these subsystems (components) are instantiated only once by the component manager (I think), they can be associated with any entity in the game world (I think) and will only ever be used in relation to one such entity at a time (I think). Thus, as a user of the simulation, it may be easier to think of the simulation as consisting of a set of entities, each "having" (being associated with) one or more components. For instance, a soldier unit may have a Pathfinder component, so it can find its way over the map, and an Attack component, so it can fight any enemies it comes across, and an Armour component, so it can handle damage dealt by other units.
Regarding how to load a single instance of a component for one whole session: For a single component you need to attach it to the system entity which unfortunately requires a C++ change. The location is: source/simulation2/Simulation2.cpp:128

# Actors

"Actors" is a concept that is used when dealing with all the visual aspects of entities, such as which models and textures to use for rendering it etc. (TODO: give more examples).
The logic governing actors is mainly found in the VisualActor component (TODO: wikilinkify "component").
CCmpVisualActor.Init
This function takes a "paramNode" as argument. I'm not quite sure what that is, but it's probably some kind of XML-derived data structure.
If the paramNode has a "Foundation" or "FoundationActor" child, that will be used as the "actor name". If it doesn't, it will use the "Actor" child of the paramNode as "actor name".
The function then creates a new "unit" from the "actor name", GetActorSeed and null selections. (TODO: explain)
CUnitManager.CreateUnit
This function tries instantiating a new CUnit with the actor name, seed and selection given in its arguments and some private object manager. (TODO: explain)
If it succeeds in doing so, the new unit is added to the unit manager and returned to the call site.
CUnit::Create
This is a factory function.
First it finds the base object with the given actor name in the object manager. If a base object with that name is not found, it returns null.
It then calculates random variations from the seed.
It then finds the object that matches them. If object not found, return null.
It then returns a new CUnit with that object, object manager and selections.
CUnit::CUnit
This just initializes a bunch of variables.

# 0 A.D.

* GUI
** Session