mirror of
https://github.com/Laupetin/OpenAssetTools.git
synced 2026-06-06 00:32:34 +00:00
feat: removed ents file, worldspawn and intermission are added through gltf nodes now
This commit is contained in:
@@ -164,14 +164,18 @@ namespace BSP
|
||||
BSPWorld gfxWorld;
|
||||
BSPWorld colWorld;
|
||||
|
||||
bool hasSunlightBeenSet;
|
||||
BSPLight sunlight;
|
||||
std::vector<BSPLight> lights;
|
||||
|
||||
std::vector<BSPSpawnPoint> spawnpoints;
|
||||
std::vector<BSPZoneZM> zm_zones;
|
||||
std::vector<BSPZSpawnerZM> zm_spawners;
|
||||
std::vector<BSPEntity> entities;
|
||||
|
||||
bool hasSunlightBeenSet;
|
||||
BSPLight sunlight;
|
||||
bool containsWorldspawn;
|
||||
bool containsIntermssion;
|
||||
std::vector<BSPEntity> entities;
|
||||
BSPEntity worldspawn;
|
||||
|
||||
std::vector<BSPModel> models;
|
||||
};
|
||||
|
||||
@@ -374,10 +374,7 @@ namespace
|
||||
light.innerConeAngle = 0.0f;
|
||||
if (jsLight.type == JsonPunctualLightType::DIRECTIONAL)
|
||||
{
|
||||
if (m_bsp->hasSunlightBeenSet)
|
||||
con::warn("WARNING: multiple sunlight nodes found, only one will be used as the sun.");
|
||||
light.type = LIGHT_TYPE_DIRECTIONAL;
|
||||
m_bsp->hasSunlightBeenSet = true;
|
||||
}
|
||||
else if (jsLight.type == JsonPunctualLightType::POINT)
|
||||
{
|
||||
@@ -435,7 +432,12 @@ namespace
|
||||
RhcToLhcCoordinates(light.direction.v);
|
||||
|
||||
if (jsLight.type == JsonPunctualLightType::DIRECTIONAL)
|
||||
{
|
||||
if (m_bsp->hasSunlightBeenSet)
|
||||
con::warn("WARNING: multiple sunlight nodes found, only one will be used as the sun.");
|
||||
m_bsp->sunlight = light;
|
||||
m_bsp->hasSunlightBeenSet = true;
|
||||
}
|
||||
else
|
||||
m_bsp->lights.emplace_back(light);
|
||||
|
||||
@@ -949,7 +951,21 @@ namespace
|
||||
entity.rotationQuaternion.w = rotationQuat.w();
|
||||
RhcToLhcQuaternion(entity.rotationQuaternion.v);
|
||||
|
||||
m_bsp->entities.emplace_back(entity);
|
||||
if (!classname.compare("worldspawn"))
|
||||
{
|
||||
if (m_bsp->containsWorldspawn)
|
||||
con::warn("WARNING: multiple worldspawn classes found, only one will be used.");
|
||||
m_bsp->worldspawn = entity;
|
||||
m_bsp->containsWorldspawn = true;
|
||||
}
|
||||
else if (!classname.compare("mp_global_intermission"))
|
||||
{
|
||||
if (m_bsp->containsIntermssion)
|
||||
con::warn("WARNING: multiple mp_global_intermission classes found, only one will be used.");
|
||||
m_bsp->containsIntermssion = true;
|
||||
}
|
||||
else
|
||||
m_bsp->entities.emplace_back(entity);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1296,6 +1312,8 @@ namespace BSP
|
||||
bsp->bspName = "maps/mp/" + mapName + ".d3dbsp";
|
||||
bsp->isZombiesMap = isZombiesMap;
|
||||
bsp->hasSunlightBeenSet = false;
|
||||
bsp->containsIntermssion = false;
|
||||
bsp->containsWorldspawn = false;
|
||||
|
||||
con::warn("XModels don't support scale currently, keep it at 1 in your editor");
|
||||
|
||||
@@ -1356,6 +1374,17 @@ namespace BSP
|
||||
bsp->sunlight.outerConeAngle = 0.0f;
|
||||
}
|
||||
|
||||
if (!bsp->containsIntermssion)
|
||||
{
|
||||
con::error("Map does not contain a mp_global_intermission class");
|
||||
return nullptr;
|
||||
}
|
||||
if (!bsp->containsWorldspawn)
|
||||
{
|
||||
con::error("Map does not contain a worldspawn class");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return bsp;
|
||||
}
|
||||
} // namespace BSP
|
||||
|
||||
@@ -7,38 +7,6 @@ using namespace nlohmann;
|
||||
|
||||
namespace
|
||||
{
|
||||
bool addJSONToEntString(json& entArrayJs, std::string& entityString)
|
||||
{
|
||||
for (size_t entIdx = 0; entIdx < entArrayJs.size(); entIdx++)
|
||||
{
|
||||
auto& entity = entArrayJs[entIdx];
|
||||
|
||||
if (entIdx == 0)
|
||||
{
|
||||
std::string className;
|
||||
entity.at("classname").get_to(className);
|
||||
if (className.compare("worldspawn") != 0)
|
||||
{
|
||||
con::error("ERROR: first entity in the map entity string must be the worldspawn class!");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
entityString.append("{\n");
|
||||
|
||||
for (auto& element : entity.items())
|
||||
{
|
||||
std::string key = element.key();
|
||||
std::string value = element.value();
|
||||
entityString.append(std::format("\"{}\" \"{}\"\n", key, value));
|
||||
}
|
||||
|
||||
entityString.append("}\n");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline const std::vector<const char*> DEFENDER_SPAWN_POINT_NAMES = {"mp_ctf_spawn_allies",
|
||||
"mp_ctf_spawn_allies_start",
|
||||
"mp_sd_spawn_defender",
|
||||
@@ -170,24 +138,6 @@ namespace
|
||||
entityString.append("}\n");
|
||||
}
|
||||
}
|
||||
|
||||
constexpr const char* DEFAULT_MAP_ENTS_STRING = R"({
|
||||
"entities": [
|
||||
{
|
||||
"classname": "worldspawn"
|
||||
},
|
||||
{
|
||||
"angles": "0 0 0",
|
||||
"classname": "info_player_start",
|
||||
"origin": "0 0 0"
|
||||
},
|
||||
{
|
||||
"angles": "0 0 0",
|
||||
"classname": "mp_global_intermission",
|
||||
"origin": "0 0 0"
|
||||
}
|
||||
]
|
||||
})";
|
||||
} // namespace
|
||||
|
||||
namespace BSP
|
||||
@@ -201,52 +151,35 @@ namespace BSP
|
||||
|
||||
MapEnts* MapEntsLinker::linkMapEnts(BSPData* bsp)
|
||||
{
|
||||
try
|
||||
{
|
||||
json entJs;
|
||||
std::string entityFileName = "entities.json";
|
||||
std::string entityFilePath = BSPUtil::getFileNameForBSPAsset(entityFileName);
|
||||
const auto entFile = m_search_path.Open(entityFilePath);
|
||||
if (!entFile.IsOpen())
|
||||
{
|
||||
con::warn("Can't find entity file {}, using default entities instead", entityFilePath);
|
||||
entJs = json::parse(DEFAULT_MAP_ENTS_STRING);
|
||||
}
|
||||
else
|
||||
{
|
||||
entJs = json::parse(*entFile.m_stream);
|
||||
}
|
||||
std::string entityString;
|
||||
if (!addJSONToEntString(entJs["entities"], entityString))
|
||||
return nullptr;
|
||||
std::string entityString;
|
||||
|
||||
addSpawnsToEntString(bsp, entityString);
|
||||
// worldspawn must be the first entity
|
||||
entityString.append("{\n");
|
||||
for (auto& entry : bsp->worldspawn.entries)
|
||||
entityString.append(std::format("\"{}\" \"{}\"\n", entry.key, entry.value));
|
||||
entityString.append("}\n");
|
||||
|
||||
if (bsp->isZombiesMap)
|
||||
addZombiesEntitiesToEntString(bsp, entityString);
|
||||
addSpawnsToEntString(bsp, entityString);
|
||||
|
||||
addClassEntitiesToEntString(bsp, entityString);
|
||||
if (bsp->isZombiesMap)
|
||||
addZombiesEntitiesToEntString(bsp, entityString);
|
||||
|
||||
MapEnts* mapEnts = m_memory.Alloc<MapEnts>();
|
||||
mapEnts->name = m_memory.Dup(bsp->bspName.c_str());
|
||||
addClassEntitiesToEntString(bsp, entityString);
|
||||
|
||||
mapEnts->entityString = m_memory.Dup(entityString.c_str());
|
||||
mapEnts->numEntityChars = static_cast<int>(entityString.length() + 1); // numEntityChars includes the null character
|
||||
MapEnts* mapEnts = m_memory.Alloc<MapEnts>();
|
||||
mapEnts->name = m_memory.Dup(bsp->bspName.c_str());
|
||||
|
||||
// don't need these, unused by the game
|
||||
mapEnts->trigger.count = 0;
|
||||
mapEnts->trigger.models = nullptr;
|
||||
mapEnts->trigger.hullCount = 0;
|
||||
mapEnts->trigger.hulls = nullptr;
|
||||
mapEnts->trigger.slabCount = 0;
|
||||
mapEnts->trigger.slabs = nullptr;
|
||||
mapEnts->entityString = m_memory.Dup(entityString.c_str());
|
||||
mapEnts->numEntityChars = static_cast<int>(entityString.length() + 1); // numEntityChars includes the null character
|
||||
|
||||
return mapEnts;
|
||||
}
|
||||
catch (const json::exception& e)
|
||||
{
|
||||
con::error("JSON error when parsing map ents and spawns: {}", e.what());
|
||||
return nullptr;
|
||||
}
|
||||
// don't need these, unused by the game
|
||||
mapEnts->trigger.count = 0;
|
||||
mapEnts->trigger.models = nullptr;
|
||||
mapEnts->trigger.hullCount = 0;
|
||||
mapEnts->trigger.hulls = nullptr;
|
||||
mapEnts->trigger.slabCount = 0;
|
||||
mapEnts->trigger.slabs = nullptr;
|
||||
|
||||
return mapEnts;
|
||||
}
|
||||
} // namespace BSP
|
||||
|
||||
Reference in New Issue
Block a user