This commit is contained in:
2017-07-17 22:22:10 -07:00
commit 6ef6745d29
5 changed files with 203 additions and 65 deletions

View File

@ -1,24 +1,17 @@
EX=reflex2q3
CC=g++
CFLAGS=-std=c++11 -I"./includes" -I"./includes/Catch/single_include" -I"./includes/cxxopts/include" -I"/usr/include/eigen3"
TESTEX=test/test-parser
UNITEX=test/catch
TESTEX=test/catch
all: main unittest
all: main test
main: planes.o brushdef.o oopless-parser.o EntityConverter.o
$(CC) $^ main.cpp $(CFLAGS) -o $(EX) 2>error8.log
test: planes.o brushdef.o oopless-parser.o test-parser.o
test: EntityConverter.o catch.o
$(CC) $^ $(CFLAGS) -o $(TESTEX)
unittest: EntityConverter.o catch.o
$(CC) $^ $(CFLAGS) -o $(UNITEX)
mv test/catch ../.git/hooks/pre-commit
test-parser.o: test/test-parser.cpp
$(CC) -c $^ $(CFLAGS)
catch.o: test/catch.cpp
$(CC) -c $^ $(CFLAGS)

View File

@ -249,7 +249,7 @@ EntityConverter::convertPickup(const std::vector<std::string> &lines) const
if ( lines.size() < 2 ) {
throw std::runtime_error(
makeErrorMessage( "error: Pickup entity requires at least type and ID", lines ));
makeErrorMessage( "error: Pickup entity requires minimum of two lines (type and ID)", lines ));
}
for (int i = 1; i < lines.size(); i++) {
@ -260,7 +260,7 @@ EntityConverter::convertPickup(const std::vector<std::string> &lines) const
if ( ! (iss >> trash >> trash >>
coords[0] >> coords[1] >> coords[2])) {
throw std::runtime_error(
makeErrorMessage( "error: Pickup entity requires coordinates", lines ));
makeErrorMessage( "error: Invalid Pickup position", lines ));
}
}
else if ( type == "pickupType" ) {
@ -268,7 +268,7 @@ EntityConverter::convertPickup(const std::vector<std::string> &lines) const
// UInt8 pickupType ID
if ( ! (iss >> trash >> trash >> pickupID) ) {
throw std::runtime_error(
makeErrorMessage( "error: Pickup entity requires Pickup ID", lines ));
makeErrorMessage( "error: Format of Pickup ID line is invalid", lines ));
}
havePickupID = true;
}
@ -278,12 +278,12 @@ EntityConverter::convertPickup(const std::vector<std::string> &lines) const
auto pickupIter = pickupMap_.find(pickupID);
if ( pickupIter == pickupMap_.end() ) {
throw std::runtime_error(
makeErrorMessage( "error: Pickup ID must be valid", lines ));
makeErrorMessage( "error: Pickup ID is invalid", lines ));
}
std::stringstream pickupStream;
pickupStream << "\"classname\" \"" << pickupIter->second << "\"" << std::endl;
convertedLines.push_back ( pickupStream.str() );
// coordinates reordered to x, z, y
// coordinates reordered to x, z, yentity
std::stringstream positionStream;
positionStream << "\"origin\" \"" << coords[0] << " " << coords[2] << " " <<
offset(coords[1], OFFSET_PICKUP) << "\"" << std::endl;
@ -292,7 +292,7 @@ EntityConverter::convertPickup(const std::vector<std::string> &lines) const
}
else {
throw std::runtime_error(
makeErrorMessage( "error: Pickup requires position and pickup ID, missing 1 or both", lines ));
makeErrorMessage( "error: Pickup ID was not in the entity", lines ));
}
}
@ -335,7 +335,7 @@ EntityConverter::convertPlayerSpawn(const std::vector<std::string> &lines) const
if ( ! (iss >> trash >> trash >>
coords[0] >> coords[1] >> coords[2])) {
throw std::runtime_error(
makeErrorMessage( "error: PlayerSpawn entity must have valid position coordinates if specified", lines ));
makeErrorMessage( "error: Invalid PlayerSpawn position", lines ));
}
}
else if ( type == "angles" ) {
@ -343,7 +343,7 @@ EntityConverter::convertPlayerSpawn(const std::vector<std::string> &lines) const
// UInt8 pickupType ID
if ( ! (iss >> trash >> trash >> angle )) {
throw std::runtime_error(
makeErrorMessage( "error: Pickup entity requires Pickup ID", lines ));
makeErrorMessage( "error: Invalid PlayerSpawn angle", lines ));
}
}
// Bool8 modeX 0 indicates this spawn is not for game mode X
@ -414,13 +414,13 @@ EntityConverter::convertJumpPad(const std::vector<std::string> &lines) const
if ( lines.size() < 2 ) {
throw std::runtime_error(
makeErrorMessage( "error: JumpPad entity requires at least type and target name", lines ));
makeErrorMessage( "error: JumpPad entity requires minimum of two lines (type and target)", lines ));
}
std::istringstream iss(lines[1]);
// String32 target targetName
if ( ! (iss >> trash >> trash >> targetName) ) {
throw std::runtime_error(
makeErrorMessage( "error: JumpPad entity requires target name", lines ));
makeErrorMessage( "error: Invalid JumpPad target", lines ));
}
convertedLines.push_back ( "\"classname\" \"trigger_push\"\n" );
@ -441,13 +441,13 @@ EntityConverter::convertTeleporter(const std::vector<std::string> &lines) const
if ( lines.size() < 2 ) {
throw std::runtime_error(
makeErrorMessage( "error: Teleport entity requires at least type and target name", lines ));
makeErrorMessage( "error: Teleport entity requires minimum of two lines (type and target)", lines ));
}
std::istringstream iss(lines[1]);
// String32 target targetName
if ( ! (iss >> trash >> trash >> targetName) ) {
throw std::runtime_error(
makeErrorMessage( "error: Teleport entity requires target name", lines ));
makeErrorMessage( "error: Invalid Teleport target", lines ));
}
convertedLines.push_back ( "\"classname\" \"trigger_teleport\"\n" );
@ -473,7 +473,7 @@ EntityConverter::convertTarget(const std::vector<std::string> &lines) const
if ( lines.size() < 3 ) {
throw std::runtime_error(
makeErrorMessage( "error: Target entity requires at least type and name", lines ));
makeErrorMessage( "error: Target entity requires minimum of two lines (type and name)", lines ));
}
for (int i = 1; i < lines.size(); i++) {
@ -484,7 +484,7 @@ EntityConverter::convertTarget(const std::vector<std::string> &lines) const
if ( ! (iss >> trash >> trash >>
coords[0] >> coords[1] >> coords[2])) {
throw std::runtime_error(
makeErrorMessage( "error: Target entity requires coordinates", lines ));
makeErrorMessage( "error: Invalid Target position", lines ));
}
}
else if ( type == "name" ) {
@ -492,7 +492,7 @@ EntityConverter::convertTarget(const std::vector<std::string> &lines) const
// UInt8 name uniqueName
if ( ! (iss >> trash >> trash >> targetName) ) {
throw std::runtime_error(
makeErrorMessage( "error: Target entity requires target name", lines ));
makeErrorMessage( "error: Invalid Target \"target\"", lines ));
}
haveName = true;
}
@ -501,7 +501,7 @@ EntityConverter::convertTarget(const std::vector<std::string> &lines) const
// Vector3 angles angle notapplicable notapplicable
if ( ! (iss >> trash >> trash >> angle) ) {
throw std::runtime_error(
makeErrorMessage( "error: Target entity requires target angle if specified", lines ));
makeErrorMessage( "error: Invalid Target angle", lines ));
}
}
@ -510,7 +510,7 @@ EntityConverter::convertTarget(const std::vector<std::string> &lines) const
if ( haveName) {
auto targetIter = targetMap_.find(targetName);
if ( targetIter == targetMap_.end() ) {
std::cerr << makeErrorMessage("EntityConverter doesn't know what the source of a Target entity with the following attributes. This entity will not be converted. It is probably an unsupported entity type or feature. (e.g. game over camera)", lines);
std::cerr << makeErrorMessage("End-game camera Target is not a supported feature in id Tech games. Skipping", lines);
std::vector<std::string> empty;
return empty;
@ -544,7 +544,7 @@ EntityConverter::convertTarget(const std::vector<std::string> &lines) const
}
else {
throw std::runtime_error(
makeErrorMessage( "error: Target entity requires position coordinates and targetname", lines ));
makeErrorMessage( "error: \"target\" was not found in this Target entity", lines ));
}
}
@ -592,7 +592,7 @@ EntityConverter::convertPointLight(const std::vector<std::string> &lines) const
if ( lines.size() < 2 ) {
throw std::runtime_error(
makeErrorMessage( "error: PointLight entity requires at least type", lines ));
makeErrorMessage( "error: PointLight entity requires at least one line (type)", lines ));
}
for (int i = 1; i < lines.size(); i++) {
@ -603,7 +603,7 @@ EntityConverter::convertPointLight(const std::vector<std::string> &lines) const
if ( ! (iss >> trash >> trash >>
coords[0] >> coords[1] >> coords[2])) {
throw std::runtime_error(
makeErrorMessage( "error: PointLight entity requires valid position coordinates", lines ));
makeErrorMessage( "error: Invalid PointLight position", lines ));
}
}
else if ( type == "intensity" ) {
@ -611,7 +611,7 @@ EntityConverter::convertPointLight(const std::vector<std::string> &lines) const
// Float intensity validFloat
if ( ! (iss >> trash >> trash >> intensity) ) {
throw std::runtime_error(
makeErrorMessage( "error: PointLight intensity keyword must be followed by a value", lines ));
makeErrorMessage( "error: Invalid PointLight intensity", lines ));
}
}
else if ( type == "color" ) {
@ -619,7 +619,7 @@ EntityConverter::convertPointLight(const std::vector<std::string> &lines) const
// ColourXRGB32 color eightDigitHexValue
if ( ! (iss >> trash >> trash >> color) ) {
throw std::runtime_error(
makeErrorMessage( "error: PointLight color keyword must be followed by a value", lines ));
makeErrorMessage( "error: Invalid PointLight color", lines ));
}
haveColor = true;
}
@ -792,7 +792,7 @@ EntityConverter::makeErrorMessage(const std::string message,
const std::vector<std::string> entity) const
{
std::stringstream ss;
ss << std::endl << message << std::endl;
ss << std::endl << message << ":" << std::endl;
std::vector<std::string>::const_iterator it;
for ( it=entity.begin(); it!=entity.end(); ++it ) {

176
docs/doc-entities.txt Normal file
View File

@ -0,0 +1,176 @@
Differences between Reflex and id Tech entities
Reflex uses a right-handed coordinate system and id Tech uses a left-handed
system so many positions and angles must take this into account when being
converted.
Position of Players and Pickups are stored differently in Reflex. Player
positions are stored at a players feet, while in id Tech, at the center of
the character. Converting from Reflex requires the vertical component of
position to be offset by 32 units. Similarly, pickups must be offset by
two units.
Entity attributes are often implicit; i.e. if an attribute is required but
unspecified, a default is used
-All game modes are enabled by default and attributes are used to
disable undesired modes or to set 2v2
-Entities without a position are implicitly at the origin
-PointLights without a color default to white
Attributes set in a WorldSpawn are used by all the entities it contains.
-id Tech maps have a maximum of one WorldSpawn. Many are allowed
in Reflex
-WorldSpawns often group PlayerSpawns by game mode
Angles
-Can be stored as a Vector3, since rotation about any axis is possible
-Keyword angle is also supported (rotation about the vertical axis)
Race Entities
-Unlike id Tech games, is limited by not having checkpoint brushes
-CTS only
Reflex entity types and all known attributes
* is used to denote unsupported attributes and entity types
** For parsing purposes, is handled differently than other entities
**WorldSpawn
*String32 targetGameOverCamera
*Float timeOfDay
*Float skyAngle
*UInt8 playersMin
*UInt8 playersMax
Bool8 modeFFA
Bool8 modeTDM
Bool8 modeCTF
Bool8 mode1v1
Bool8 modeRace
Bool8 mode2v2
Pickup
(pickupType Required)
Vector3 position
Vector3 angles
UInt8 pickupType - See list of pickup IDs in this document
PlayerSpawn
Vector3 position
Vector3 angles
Vector3 angle
bool8 teamA
bool8 teamB
Bool8 modeFFA
Bool8 modeTDM
Bool8 modeCTF
Bool8 mode1v1
Bool8 modeRace
*Bool8 mode2v2
JumpPad
String32 target
brush
Teleporter
String32 target
brush
Target
(name Required)
Vector3 position
Vector3 angles
Vector3 angle
String32 name
RaceStart
brush
RaceFinish
brush
PointLight
Vector3 position
ColourXRGB32 color - ARGB, alpha channel always full for PointLights
Float nearAttenuation
Float farAttenuation
*Prefab
Vector3 position
String64 prefabName
*CameraPath
(No direct id Tech equivalent)
UInt8 posLerp
Uint8angleLerp
*Effect
Vector3 position
Vector3 angles
String64 effectName
String256 material0Name
ColourARGB32 material0Albedo
Pickup IDs (of pickups suitable for conversion)
Burst Gun (spawn weapon)
This entity will not have a pickupType field.
Weapons
If the player doesn't have the weapon, then s/he will acquire it.
If it is present, the player gains some ammo respective to the gun.
pickupType 1 = Shotgun
pickupType 2 = Grenade Launcher
pickupType 3 = Plasma Rifle
pickupType 4 = Rocket Launcher
pickupType 5 = Ion Cannon
pickupType 6 = Bolt Rifle
Ammo
Ammunition for weapons gained on pickup.
pickupType 20 = Burst Gun Ammo
pickupType 21 = Shotgun Ammo
pickupType 22 = Grenade launcher Ammo
pickupType 23 = Plasma Rifle Ammo
pickupType 24 = Rocket Launcher Ammo
pickupType 25 = Ion Cannon Ammo
pickupType 26 = Bolt Rifle Ammo
Power Up
A temporary buff granted to the player.
pickupType 60 = Carnage (increases a player's outgoing damage)
pickupType 62 = Resist (decreases a player's incoming damage)
Flags
For use in Capture the Flag
pickupType 70 = Team Alpha Flag (red team)
pickupType 71 = Team Zeta Flag (blue team)
Health
Restores the player's hitpoints.
pickupType 40 = Small health
pickupType 41 = Medium health
pickupType 42 = large health
pickupType 43 = Mega Health
Armor
Restores the player's armor.
Reflex has a tiered Armor system.
Green absorbs the least damage, and Red absorbs the most.
pickupType 50 = Armor shard
pickupType 51 = Green Armor
pickupType 52 = Yellow Armor
pickupType 53 = Red Armor

View File

@ -13,7 +13,7 @@ Features, and Responsibilities of the Program: For Mappers
During the conversion process, face related data (texture & color) are
preserved. This is both because of the differences between engines and the
numerous games built in idTech engines. Meaning the map converter does not
numerous games built in idTech engines. That is, the map converter does not
attempt to retexture the map with generic idTech engine equivalents or
per-game equivalents. It is the individual mappers' responsibility to
appropriately adapt the map for the target game. Some of the following

View File

@ -1,31 +0,0 @@
=======================
=The Reflex Map Format=
=======================
Worldspawn contains all brushes and entities. The maps I've seen contain only a single Worldspawn.
"Pickup" denoted by ID number. We stored the Reflex to Xonotic conversion in r2x.pck
<Table of ID to their pickup name>
"PlayerSpawn" consists of coordinate (Vector3),
angle (first element of Vector3),
team indicator (on individual lines),
game type indicator (on individual lines)
-"JumpPad" stored as a brush and a Target
-"Teleporter" stored as a brush and a Target
-"Target" stored as a position (Vector3) and
a "name" (String32)
***Target can be destination of teleports OR jump pads
-"RaceStart" stored as a brush
-"RaceFinish" stored as a brush
That's all we have converted so far but we intend to convert Effect,
PointLight, Prefab, CameraPath, and possibly liquids.