Merge branch 'master' of https://git.teknik.io/scuti/reflex2q3
This commit is contained in:
commit
6ef6745d29
@ -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)
|
||||
|
||||
|
@ -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
176
docs/doc-entities.txt
Normal 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
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
Loading…
Reference in New Issue
Block a user