2
0
mirror of https://github.com/Laupetin/OpenAssetTools.git synced 2025-11-24 21:52:06 +00:00

Merge fixup

This commit is contained in:
LJW-Dev
2025-10-09 00:05:49 +08:00
771 changed files with 27490 additions and 14332 deletions

View File

@@ -1,5 +1,7 @@
#include "AssetCreationContext.h"
#include "Utils/Logging/Log.h"
#include <cassert>
#include <format>
#include <iostream>
@@ -65,7 +67,7 @@ std::unique_ptr<XAssetInfoGeneric> GenericAssetRegistration::CreateXAssetInfo()
AssetCreationContext::AssetCreationContext(Zone& zone, const AssetCreatorCollection* creators, const IgnoredAssetLookup* ignoredAssetLookup)
: ZoneAssetCreationStateContainer(zone),
m_zone(zone),
m_forced_asset_pools(ZoneAssetPools::CreateForGame(zone.m_game->GetId(), &zone, zone.m_priority)),
m_forced_asset_pools(ZoneAssetPools::CreateForGame(zone.m_game_id, &zone, zone.m_priority)),
m_creators(creators),
m_ignored_asset_lookup(ignoredAssetLookup),
m_forced_load_depth(0u)
@@ -87,7 +89,7 @@ XAssetInfoGeneric* AssetCreationContext::AddAssetGeneric(GenericAssetRegistratio
addedAsset = m_zone.m_pools->AddAsset(std::move(xAssetInfo));
if (addedAsset == nullptr)
std::cerr << std::format("Failed to add asset of type \"{}\" to pool: \"{}\"\n", *m_zone.m_pools->GetAssetTypeName(assetType), pAssetName);
con::error("Failed to add asset of type \"{}\" to pool: \"{}\"", *m_zone.m_pools->GetAssetTypeName(assetType), pAssetName);
return addedAsset;
}
@@ -97,7 +99,7 @@ XAssetInfoGeneric* AssetCreationContext::LoadDefaultAssetDependency(const asset_
if (result.HasTakenAction() && !result.HasFailed())
return result.GetAssetInfo();
std::cerr << std::format("Failed to create default asset of type {}\n", *m_zone.m_pools->GetAssetTypeName(assetType));
con::error("Failed to create default asset of type {}", *m_zone.m_pools->GetAssetTypeName(assetType));
return nullptr;
}
@@ -127,11 +129,11 @@ XAssetInfoGeneric* AssetCreationContext::LoadDependencyGeneric(const asset_type_
if (!result.HasFailed())
return result.GetAssetInfo();
std::cerr << std::format("Could not load asset \"{}\" of type \"{}\"\n", assetName, *m_zone.m_pools->GetAssetTypeName(assetType));
con::error("Could not load asset \"{}\" of type \"{}\"", assetName, *m_zone.m_pools->GetAssetTypeName(assetType));
}
else
{
std::cerr << std::format("Missing asset \"{}\" of type \"{}\"\n", assetName, *m_zone.m_pools->GetAssetTypeName(assetType));
con::error("Missing asset \"{}\" of type \"{}\"", assetName, *m_zone.m_pools->GetAssetTypeName(assetType));
}
return nullptr;
@@ -149,7 +151,7 @@ IndirectAssetReference AssetCreationContext::LoadIndirectAssetReferenceGeneric(c
const auto result = m_creators->CreateAsset(assetType, assetName, *this);
if (!result.HasTakenAction() && !result.HasFailed())
{
std::cerr << std::format("Could not load indirectly referenced asset \"{}\" of type \"{}\"\n", assetName, *m_zone.m_pools->GetAssetTypeName(assetType));
con::warn("Could not load indirectly referenced asset \"{}\" of type \"{}\"", assetName, *m_zone.m_pools->GetAssetTypeName(assetType));
}
return IndirectAssetReference(assetType, assetName);
}
@@ -185,11 +187,11 @@ XAssetInfoGeneric* AssetCreationContext::ForceLoadDependencyGeneric(const asset_
if (!result.HasFailed())
return result.GetAssetInfo();
std::cerr << std::format("Could not load asset \"{}\" of type \"{}\"\n", assetName, *m_zone.m_pools->GetAssetTypeName(assetType));
con::error("Could not load asset \"{}\" of type \"{}\"", assetName, *m_zone.m_pools->GetAssetTypeName(assetType));
}
else
{
std::cerr << std::format("Missing asset \"{}\" of type \"{}\"\n", assetName, *m_zone.m_pools->GetAssetTypeName(assetType));
con::error("Missing asset \"{}\" of type \"{}\"", assetName, *m_zone.m_pools->GetAssetTypeName(assetType));
}
return nullptr;

View File

@@ -52,14 +52,15 @@ public:
static_assert(std::is_base_of_v<IZoneAssetCreationState, T>, "T must inherit IZoneAssetCreationState");
// T must also have a public default constructor
const auto foundEntry = m_zone_asset_creation_states.find(typeid(T));
std::type_index typeId = typeid(T);
const auto foundEntry = m_zone_asset_creation_states.find(typeId);
if (foundEntry != m_zone_asset_creation_states.end())
return *dynamic_cast<T*>(foundEntry->second.get());
auto newState = std::make_unique<T>();
newState->Inject(m_injection);
auto* newStatePtr = newState.get();
m_zone_asset_creation_states.emplace(std::make_pair<std::type_index, std::unique_ptr<IZoneAssetCreationState>>(typeid(T), std::move(newState)));
m_zone_asset_creation_states.emplace(std::move(typeId), std::move(newState));
return *newStatePtr;
}

View File

@@ -4,6 +4,7 @@
#include "Image/DdsLoader.h"
#include "Image/IwiTypes.h"
#include "Pool/GlobalAssetPool.h"
#include "Utils/Logging/Log.h"
#include <algorithm>
#include <cstring>
@@ -40,7 +41,7 @@ namespace
const auto texture = dds::LoadDds(*file.m_stream);
if (!texture)
{
std::cerr << std::format("Failed to load dds file for image asset \"{}\"\n", assetName);
con::error("Failed to load dds file for image asset \"{}\"", assetName);
return AssetCreationResult::Failure();
}
@@ -122,10 +123,10 @@ namespace
};
} // namespace
namespace IW3
namespace image
{
std::unique_ptr<AssetCreator<AssetImage>> CreateImageLoader(MemoryManager& memory, ISearchPath& searchPath)
std::unique_ptr<AssetCreator<AssetImage>> CreateLoaderIW3(MemoryManager& memory, ISearchPath& searchPath)
{
return std::make_unique<ImageLoader>(memory, searchPath);
}
} // namespace IW3
} // namespace image

View File

@@ -7,7 +7,7 @@
#include <memory>
namespace IW3
namespace image
{
std::unique_ptr<AssetCreator<AssetImage>> CreateImageLoader(MemoryManager& memory, ISearchPath& searchPath);
} // namespace IW3
std::unique_ptr<AssetCreator<IW3::AssetImage>> CreateLoaderIW3(MemoryManager& memory, ISearchPath& searchPath);
} // namespace image

View File

@@ -36,10 +36,10 @@ namespace
};
} // namespace
namespace IW3
namespace localize
{
std::unique_ptr<AssetCreator<AssetLocalize>> CreateLocalizeLoader(MemoryManager& memory, ISearchPath& searchPath, Zone& zone)
std::unique_ptr<AssetCreator<AssetLocalize>> CreateLoaderIW3(MemoryManager& memory, ISearchPath& searchPath, Zone& zone)
{
return std::make_unique<LocalizeLoader>(memory, searchPath, zone);
}
} // namespace IW3
} // namespace localize

View File

@@ -8,7 +8,7 @@
#include <memory>
namespace IW3
namespace localize
{
std::unique_ptr<AssetCreator<AssetLocalize>> CreateLocalizeLoader(MemoryManager& memory, ISearchPath& searchPath, Zone& zone);
} // namespace IW3
std::unique_ptr<AssetCreator<IW3::AssetLocalize>> CreateLoaderIW3(MemoryManager& memory, ISearchPath& searchPath, Zone& zone);
} // namespace localize

View File

@@ -0,0 +1,55 @@
#include "LoaderMaterialIW3.h"
#include "Game/IW3/IW3.h"
#include "Game/IW3/Material/JsonMaterialLoaderIW3.h"
#include "Material/MaterialCommon.h"
#include "Utils/Logging/Log.h"
#include <format>
#include <iostream>
using namespace IW3;
namespace
{
class MaterialLoader final : public AssetCreator<AssetMaterial>
{
public:
MaterialLoader(MemoryManager& memory, ISearchPath& searchPath)
: m_memory(memory),
m_search_path(searchPath)
{
}
AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override
{
const auto file = m_search_path.Open(material::GetFileNameForAssetName(assetName));
if (!file.IsOpen())
return AssetCreationResult::NoAction();
auto* material = m_memory.Alloc<Material>();
material->info.name = m_memory.Dup(assetName.c_str());
AssetRegistration<AssetMaterial> registration(assetName, material);
if (!LoadMaterialAsJson(*file.m_stream, *material, m_memory, context, registration))
{
con::error("Failed to load material \"{}\"", assetName);
return AssetCreationResult::Failure();
}
return AssetCreationResult::Success(context.AddAsset(std::move(registration)));
}
private:
MemoryManager& m_memory;
ISearchPath& m_search_path;
};
} // namespace
namespace material
{
std::unique_ptr<AssetCreator<AssetMaterial>> CreateLoaderIW3(MemoryManager& memory, ISearchPath& searchPath)
{
return std::make_unique<MaterialLoader>(memory, searchPath);
}
} // namespace material

View File

@@ -0,0 +1,12 @@
#pragma once
#include "Asset/IAssetCreator.h"
#include "Game/IW3/IW3.h"
#include "Gdt/IGdtQueryable.h"
#include "SearchPath/ISearchPath.h"
#include "Utils/MemoryManager.h"
namespace material
{
std::unique_ptr<AssetCreator<IW3::AssetMaterial>> CreateLoaderIW3(MemoryManager& memory, ISearchPath& searchPath);
} // namespace material

View File

@@ -3,8 +3,10 @@
#include "Asset/GlobalAssetPoolsLoader.h"
#include "Game/IW3/GameIW3.h"
#include "Game/IW3/IW3.h"
#include "Game/IW3/XModel/LoaderXModelIW3.h"
#include "Image/AssetLoaderImageIW3.h"
#include "Localize/AssetLoaderLocalizeIW3.h"
#include "Material/LoaderMaterialIW3.h"
#include "ObjLoading.h"
#include "RawFile/AssetLoaderRawFileIW3.h"
#include "StringTable/AssetLoaderStringTableIW3.h"
@@ -89,10 +91,10 @@ namespace
// collection.AddAssetCreator(std::make_unique<AssetLoaderPhysPreset>(memory));
// collection.AddAssetCreator(std::make_unique<AssetLoaderXAnim>(memory));
// collection.AddAssetCreator(std::make_unique<AssetLoaderXModel>(memory));
// collection.AddAssetCreator(std::make_unique<AssetLoaderMaterial>(memory));
collection.AddAssetCreator(xmodel::CreateLoaderIW3(memory, searchPath, zone));
collection.AddAssetCreator(material::CreateLoaderIW3(memory, searchPath));
// collection.AddAssetCreator(std::make_unique<AssetLoaderTechniqueSet>(memory));
collection.AddAssetCreator(CreateImageLoader(memory, searchPath));
collection.AddAssetCreator(image::CreateLoaderIW3(memory, searchPath));
// collection.AddAssetCreator(std::make_unique<AssetLoaderSound>(memory));
// collection.AddAssetCreator(std::make_unique<AssetLoaderSoundCurve>(memory));
// collection.AddAssetCreator(std::make_unique<AssetLoaderLoadedSound>(memory));
@@ -106,13 +108,13 @@ namespace
// collection.AddAssetCreator(std::make_unique<AssetLoaderFont>(memory));
// collection.AddAssetCreator(std::make_unique<AssetLoaderMenuList>(memory));
// collection.AddAssetCreator(std::make_unique<AssetLoaderMenu>(memory));
collection.AddAssetCreator(CreateLocalizeLoader(memory, searchPath, zone));
collection.AddAssetCreator(localize::CreateLoaderIW3(memory, searchPath, zone));
// collection.AddAssetCreator(std::make_unique<AssetLoaderWeapon>(memory));
// collection.AddAssetCreator(std::make_unique<AssetLoaderSoundDriverGlobals>(memory));
// collection.AddAssetCreator(std::make_unique<AssetLoaderFx>(memory));
// collection.AddAssetCreator(std::make_unique<AssetLoaderImpactFx>(memory));
collection.AddAssetCreator(CreateRawFileLoader(memory, searchPath));
collection.AddAssetCreator(CreateStringTableLoader(memory, searchPath));
collection.AddAssetCreator(raw_file::CreateLoaderIW3(memory, searchPath));
collection.AddAssetCreator(string_table::CreateLoaderIW3(memory, searchPath));
}
} // namespace

View File

@@ -44,10 +44,10 @@ namespace
};
} // namespace
namespace IW3
namespace raw_file
{
std::unique_ptr<AssetCreator<AssetRawFile>> CreateRawFileLoader(MemoryManager& memory, ISearchPath& searchPath)
std::unique_ptr<AssetCreator<AssetRawFile>> CreateLoaderIW3(MemoryManager& memory, ISearchPath& searchPath)
{
return std::make_unique<RawFileLoader>(memory, searchPath);
}
} // namespace IW3
} // namespace raw_file

View File

@@ -7,7 +7,7 @@
#include <memory>
namespace IW3
namespace raw_file
{
std::unique_ptr<AssetCreator<AssetRawFile>> CreateRawFileLoader(MemoryManager& memory, ISearchPath& searchPath);
} // namespace IW3
std::unique_ptr<AssetCreator<IW3::AssetRawFile>> CreateLoaderIW3(MemoryManager& memory, ISearchPath& searchPath);
} // namespace raw_file

View File

@@ -38,10 +38,10 @@ namespace
};
} // namespace
namespace IW3
namespace string_table
{
std::unique_ptr<AssetCreator<AssetStringTable>> CreateStringTableLoader(MemoryManager& memory, ISearchPath& searchPath)
std::unique_ptr<AssetCreator<AssetStringTable>> CreateLoaderIW3(MemoryManager& memory, ISearchPath& searchPath)
{
return std::make_unique<StringTableLoader>(memory, searchPath);
}
} // namespace IW3
} // namespace string_table

View File

@@ -7,7 +7,7 @@
#include <memory>
namespace IW3
namespace string_table
{
std::unique_ptr<AssetCreator<AssetStringTable>> CreateStringTableLoader(MemoryManager& memory, ISearchPath& searchPath);
} // namespace IW3
std::unique_ptr<AssetCreator<IW3::AssetStringTable>> CreateLoaderIW3(MemoryManager& memory, ISearchPath& searchPath);
} // namespace string_table

View File

@@ -1,5 +1,7 @@
#include "InfoStringToStructConverter.h"
#include "Utils/Logging/Log.h"
#include <cassert>
#include <format>
#include <iostream>
@@ -63,7 +65,7 @@ bool InfoStringToStructConverter::ConvertBaseField(const cspField_t& field, cons
if (fx == nullptr)
{
std::cerr << std::format("Failed to load fx asset \"{}\"\n", value);
con::error("Failed to load fx asset \"{}\"", value);
return false;
}
@@ -85,7 +87,7 @@ bool InfoStringToStructConverter::ConvertBaseField(const cspField_t& field, cons
if (xmodel == nullptr)
{
std::cerr << std::format("Failed to load xmodel asset \"{}\"\n", value);
con::error("Failed to load xmodel asset \"{}\"", value);
return false;
}
@@ -107,7 +109,7 @@ bool InfoStringToStructConverter::ConvertBaseField(const cspField_t& field, cons
if (material == nullptr)
{
std::cerr << std::format("Failed to load material asset \"{}\"\n", value);
con::error("Failed to load material asset \"{}\"", value);
return false;
}
@@ -129,7 +131,7 @@ bool InfoStringToStructConverter::ConvertBaseField(const cspField_t& field, cons
if (tracer == nullptr)
{
std::cerr << std::format("Failed to load tracer asset \"{}\"\n", value);
con::error("Failed to load tracer asset \"{}\"", value);
return false;
}
@@ -146,7 +148,7 @@ bool InfoStringToStructConverter::ConvertBaseField(const cspField_t& field, cons
if (endPtr != &value[value.size()])
{
std::cerr << std::format("Failed to parse value \"{}\" as mph\n", value);
con::error("Failed to parse value \"{}\" as mph", value);
return false;
}
@@ -165,7 +167,7 @@ bool InfoStringToStructConverter::ConvertBaseField(const cspField_t& field, cons
if (collmap == nullptr)
{
std::cerr << std::format("Failed to load collmap asset \"{}\"\n", value);
con::error("Failed to load collmap asset \"{}\"", value);
return false;
}

View File

@@ -1,114 +0,0 @@
#include "JsonLeaderboardDefLoader.h"
#include "Game/IW4/CommonIW4.h"
#include "Game/IW4/Leaderboard/JsonLeaderboardDef.h"
#include <format>
#include <iostream>
#include <nlohmann/json.hpp>
using namespace nlohmann;
using namespace IW4;
namespace
{
class JsonLoader
{
public:
JsonLoader(std::istream& stream, MemoryManager& memory)
: m_stream(stream),
m_memory(memory)
{
}
bool Load(LeaderboardDef& leaderboardDef) const
{
const auto jRoot = json::parse(m_stream);
std::string type;
unsigned version;
jRoot.at("_type").get_to(type);
jRoot.at("_version").get_to(version);
if (type != "leaderboard" || version != 1u)
{
std::cerr << std::format("Tried to load leaderboard \"{}\" but did not find expected type leaderboard of version 1\n", leaderboardDef.name);
return false;
}
try
{
const auto jLeaderboard = jRoot.get<JsonLeaderboardDef>();
return CreateLeaderboardFromJson(jLeaderboard, leaderboardDef);
}
catch (const json::exception& e)
{
std::cerr << std::format("Failed to parse json of leaderboard: {}\n", e.what());
}
return false;
}
private:
bool CreateColumnDefFromJson(const JsonColumnDef& jColumn, LbColumnDef& lbColumnDef, LeaderboardDef& leaderboardDef) const
{
lbColumnDef.name = m_memory.Dup(jColumn.name.c_str());
lbColumnDef.id = jColumn.colId;
lbColumnDef.propertyId = jColumn.propertyId.value_or(0);
lbColumnDef.hidden = jColumn.hidden.value_or(false);
if (jColumn.statName)
lbColumnDef.statName = m_memory.Dup(jColumn.statName->c_str());
else
lbColumnDef.statName = nullptr;
lbColumnDef.type = jColumn.type;
lbColumnDef.precision = jColumn.precision.value_or(0);
lbColumnDef.agg = jColumn.aggregationFunction;
return true;
}
bool CreateLeaderboardFromJson(const JsonLeaderboardDef& jLeaderboardDef, LeaderboardDef& leaderboardDef) const
{
leaderboardDef.id = jLeaderboardDef.id;
leaderboardDef.xpColId = jLeaderboardDef.xpColId.value_or(-1);
leaderboardDef.prestigeColId = jLeaderboardDef.prestigeColId.value_or(-1);
if (!jLeaderboardDef.columns.empty())
{
leaderboardDef.columnCount = static_cast<int>(jLeaderboardDef.columns.size());
leaderboardDef.columns = m_memory.Alloc<LbColumnDef>(leaderboardDef.columnCount);
for (auto i = 0; i < leaderboardDef.columnCount; i++)
{
if (!CreateColumnDefFromJson(jLeaderboardDef.columns[i], leaderboardDef.columns[i], leaderboardDef))
return false;
}
}
else
{
leaderboardDef.columnCount = 0;
leaderboardDef.columns = nullptr;
}
return true;
}
std::istream& m_stream;
MemoryManager& m_memory;
};
} // namespace
namespace IW4
{
bool LoadLeaderboardAsJson(std::istream& stream, LeaderboardDef& leaderboard, MemoryManager* memory)
{
const JsonLoader loader(stream, *memory);
return loader.Load(leaderboard);
}
} // namespace IW4

View File

@@ -1,11 +0,0 @@
#pragma once
#include "Game/IW4/IW4.h"
#include "Utils/MemoryManager.h"
#include <istream>
namespace IW4
{
bool LoadLeaderboardAsJson(std::istream& stream, LeaderboardDef& leaderboard, MemoryManager* memory);
} // namespace IW4

View File

@@ -1,16 +1,110 @@
#include "LoaderLeaderboardIW4.h"
#include "Game/IW4/IW4.h"
#include "JsonLeaderboardDefLoader.h"
#include "Game/IW4/Leaderboard/JsonLeaderboardDef.h"
#include "Leaderboard/LeaderboardCommon.h"
#include "Utils/Logging/Log.h"
#include <cstring>
#include <format>
#include <iostream>
#include <nlohmann/json.hpp>
using namespace nlohmann;
using namespace IW4;
namespace
{
class JsonLoader
{
public:
JsonLoader(std::istream& stream, MemoryManager& memory)
: m_stream(stream),
m_memory(memory)
{
}
bool Load(LeaderboardDef& leaderboardDef) const
{
try
{
const auto jRoot = json::parse(m_stream);
std::string type;
unsigned version;
jRoot.at("_type").get_to(type);
jRoot.at("_version").get_to(version);
if (type != "leaderboard" || version != 1u)
{
con::error("Tried to load leaderboard \"{}\" but did not find expected type leaderboard of version 1", leaderboardDef.name);
return false;
}
const auto jLeaderboard = jRoot.get<JsonLeaderboardDef>();
return CreateLeaderboardFromJson(jLeaderboard, leaderboardDef);
}
catch (const json::exception& e)
{
con::error("Failed to parse json of leaderboard: {}", e.what());
}
return false;
}
private:
bool CreateColumnDefFromJson(const JsonColumnDef& jColumn, LbColumnDef& lbColumnDef, LeaderboardDef& leaderboardDef) const
{
lbColumnDef.name = m_memory.Dup(jColumn.name.c_str());
lbColumnDef.id = jColumn.colId;
lbColumnDef.propertyId = jColumn.propertyId.value_or(0);
lbColumnDef.hidden = jColumn.hidden.value_or(false);
if (jColumn.statName)
lbColumnDef.statName = m_memory.Dup(jColumn.statName->c_str());
else
lbColumnDef.statName = nullptr;
lbColumnDef.type = jColumn.type;
lbColumnDef.precision = jColumn.precision.value_or(0);
lbColumnDef.agg = jColumn.aggregationFunction;
return true;
}
bool CreateLeaderboardFromJson(const JsonLeaderboardDef& jLeaderboardDef, LeaderboardDef& leaderboardDef) const
{
leaderboardDef.id = jLeaderboardDef.id;
leaderboardDef.xpColId = jLeaderboardDef.xpColId.value_or(-1);
leaderboardDef.prestigeColId = jLeaderboardDef.prestigeColId.value_or(-1);
if (!jLeaderboardDef.columns.empty())
{
leaderboardDef.columnCount = static_cast<int>(jLeaderboardDef.columns.size());
leaderboardDef.columns = m_memory.Alloc<LbColumnDef>(leaderboardDef.columnCount);
for (auto i = 0; i < leaderboardDef.columnCount; i++)
{
if (!CreateColumnDefFromJson(jLeaderboardDef.columns[i], leaderboardDef.columns[i], leaderboardDef))
return false;
}
}
else
{
leaderboardDef.columnCount = 0;
leaderboardDef.columns = nullptr;
}
return true;
}
std::istream& m_stream;
MemoryManager& m_memory;
};
class LeaderboardLoader final : public AssetCreator<AssetLeaderboard>
{
public:
@@ -22,16 +116,17 @@ namespace
AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override
{
const auto file = m_search_path.Open(std::format("leaderboards/{}.json", assetName));
const auto file = m_search_path.Open(leaderboard::GetJsonFileNameForAsset(assetName));
if (!file.IsOpen())
return AssetCreationResult::NoAction();
auto* leaderboardDef = m_memory.Alloc<LeaderboardDef>();
leaderboardDef->name = m_memory.Dup(assetName.c_str());
if (!LoadLeaderboardAsJson(*file.m_stream, *leaderboardDef, &m_memory))
const JsonLoader loader(*file.m_stream, m_memory);
if (!loader.Load(*leaderboardDef))
{
std::cerr << std::format("Failed to load leaderboard \"{}\"\n", assetName);
con::error("Failed to load leaderboard \"{}\"", assetName);
return AssetCreationResult::Failure();
}
@@ -44,10 +139,10 @@ namespace
};
} // namespace
namespace IW4
namespace leaderboard
{
std::unique_ptr<AssetCreator<AssetLeaderboard>> CreateLeaderboardLoader(MemoryManager& memory, ISearchPath& searchPath)
std::unique_ptr<AssetCreator<AssetLeaderboard>> CreateLoaderIW4(MemoryManager& memory, ISearchPath& searchPath)
{
return std::make_unique<LeaderboardLoader>(memory, searchPath);
}
} // namespace IW4
} // namespace leaderboard

View File

@@ -7,7 +7,7 @@
#include <memory>
namespace IW4
namespace leaderboard
{
std::unique_ptr<AssetCreator<AssetLeaderboard>> CreateLeaderboardLoader(MemoryManager& memory, ISearchPath& searchPath);
} // namespace IW4
std::unique_ptr<AssetCreator<IW4::AssetLeaderboard>> CreateLoaderIW4(MemoryManager& memory, ISearchPath& searchPath);
} // namespace leaderboard

View File

@@ -1,6 +1,8 @@
#include "LoaderLightDefIW4.h"
#include "LightDefLoaderIW4.h"
#include "Game/IW4/IW4.h"
#include "LightDef/LightDefCommon.h"
#include "Utils/Logging/Log.h"
#include <cstring>
#include <format>
@@ -23,7 +25,7 @@ namespace
AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override
{
const auto filename = GetAssetFilename(assetName);
const auto filename = light_def::GetFileNameForAsset(assetName);
const auto file = m_search_path.Open(filename);
if (!file.IsOpen())
return AssetCreationResult::NoAction();
@@ -48,7 +50,7 @@ namespace
auto* imageDependency = context.LoadDependency<AssetImage>(imageName);
if (!imageDependency)
{
std::cerr << std::format("Could not load GfxLightDef \"{}\" due to missing image \"{}\"\n", assetName, imageName);
con::error("Could not load GfxLightDef \"{}\" due to missing image \"{}\"", assetName, imageName);
return AssetCreationResult::Failure();
}
registration.AddDependency(imageDependency);
@@ -61,20 +63,15 @@ namespace
}
private:
std::string GetAssetFilename(const std::string& assetName)
{
return std::format("lights/{}", assetName);
}
MemoryManager& m_memory;
ISearchPath& m_search_path;
};
} // namespace
namespace IW4
namespace light_def
{
std::unique_ptr<AssetCreator<AssetLightDef>> CreateLightDefLoader(MemoryManager& memory, ISearchPath& searchPath)
std::unique_ptr<AssetCreator<AssetLightDef>> CreateLoaderIW4(MemoryManager& memory, ISearchPath& searchPath)
{
return std::make_unique<LoaderLightDef>(memory, searchPath);
}
} // namespace IW4
} // namespace light_def

View File

@@ -7,7 +7,7 @@
#include <memory>
namespace IW4
namespace light_def
{
std::unique_ptr<AssetCreator<AssetLightDef>> CreateLightDefLoader(MemoryManager& memory, ISearchPath& searchPath);
} // namespace IW4
std::unique_ptr<AssetCreator<IW4::AssetLightDef>> CreateLoaderIW4(MemoryManager& memory, ISearchPath& searchPath);
} // namespace light_def

View File

@@ -35,10 +35,10 @@ namespace
};
} // namespace
namespace IW4
namespace localize
{
std::unique_ptr<AssetCreator<AssetLocalize>> CreateLocalizeLoader(MemoryManager& memory, ISearchPath& searchPath, Zone& zone)
std::unique_ptr<AssetCreator<AssetLocalize>> CreateLoaderIW4(MemoryManager& memory, ISearchPath& searchPath, Zone& zone)
{
return std::make_unique<LocalizeLoader>(memory, searchPath, zone);
}
} // namespace IW4
} // namespace localize

View File

@@ -8,7 +8,7 @@
#include <memory>
namespace IW4
namespace localize
{
std::unique_ptr<AssetCreator<AssetLocalize>> CreateLocalizeLoader(MemoryManager& memory, ISearchPath& searchPath, Zone& zone);
} // namespace IW4
std::unique_ptr<AssetCreator<IW4::AssetLocalize>> CreateLoaderIW4(MemoryManager& memory, ISearchPath& searchPath, Zone& zone);
} // namespace localize

View File

@@ -3,6 +3,7 @@
#include "Game/IW4/IW4.h"
#include "Game/IW4/Material/JsonMaterialLoaderIW4.h"
#include "Material/MaterialCommon.h"
#include "Utils/Logging/Log.h"
#include <format>
#include <iostream>
@@ -32,7 +33,7 @@ namespace
AssetRegistration<AssetMaterial> registration(assetName, material);
if (!LoadMaterialAsJson(*file.m_stream, *material, m_memory, context, registration))
{
std::cerr << std::format("Failed to load material \"{}\"\n", assetName);
con::error("Failed to load material \"{}\"", assetName);
return AssetCreationResult::Failure();
}
@@ -45,10 +46,10 @@ namespace
};
} // namespace
namespace IW4
namespace material
{
std::unique_ptr<AssetCreator<AssetMaterial>> CreateMaterialLoader(MemoryManager& memory, ISearchPath& searchPath)
std::unique_ptr<AssetCreator<AssetMaterial>> CreateLoaderIW4(MemoryManager& memory, ISearchPath& searchPath)
{
return std::make_unique<MaterialLoader>(memory, searchPath);
}
} // namespace IW4
} // namespace material

View File

@@ -6,7 +6,7 @@
#include "SearchPath/ISearchPath.h"
#include "Utils/MemoryManager.h"
namespace IW4
namespace material
{
std::unique_ptr<AssetCreator<AssetMaterial>> CreateMaterialLoader(MemoryManager& memory, ISearchPath& searchPath);
} // namespace IW4
std::unique_ptr<AssetCreator<IW4::AssetMaterial>> CreateLoaderIW4(MemoryManager& memory, ISearchPath& searchPath);
} // namespace material

View File

@@ -5,6 +5,7 @@
#include "Game/IW4/Menu/MenuConverterIW4.h"
#include "ObjLoading.h"
#include "Parsing/Menu/MenuFileReader.h"
#include "Utils/Logging/Log.h"
#include <cstring>
#include <format>
@@ -88,7 +89,7 @@ namespace
const auto alreadyLoadedMenuFile = conversionState.m_menus_by_filename.find(menuFilePath);
if (alreadyLoadedMenuFile != conversionState.m_menus_by_filename.end())
{
std::cout << std::format("Already loaded \"{}\", skipping\n", menuFilePath);
con::debug("Already loaded \"{}\", skipping", menuFilePath);
for (auto* menu : alreadyLoadedMenuFile->second)
{
menus.emplace_back(menu->Asset());
@@ -100,7 +101,7 @@ namespace
const auto file = m_search_path.Open(menuFilePath);
if (!file.IsOpen())
{
std::cerr << std::format("Could not open menu file \"{}\"\n", menuFilePath);
con::error("Could not open menu file \"{}\"", menuFilePath);
return false;
}
@@ -109,12 +110,12 @@ namespace
{
ProcessParsedResults(menuFilePath, context, *menuFileResult, zoneState, conversionState, menus, registration);
if (!menuFileResult->m_menus_to_load.empty())
std::cout << std::format("WARNING: Menu file has menus to load even though it is not a menu list, ignoring: \"{}\"\n", menuFilePath);
con::warn("Menu file has menus to load even though it is not a menu list, ignoring: \"{}\"", menuFilePath);
return true;
}
else
std::cerr << std::format("Could not read menu file \"{}\"\n", menuFilePath);
con::error("Could not read menu file \"{}\"", menuFilePath);
return false;
}
@@ -134,12 +135,12 @@ namespace
for (const auto& menu : parsingResult.m_menus)
totalItemCount += menu->m_items.size();
std::cout << std::format("Successfully read menu file \"{}\" ({} loads, {} menus, {} functions, {} items)\n",
fileName,
menuLoadCount,
menuCount,
functionCount,
totalItemCount);
con::info("Successfully read menu file \"{}\" ({} loads, {} menus, {} functions, {} items)",
fileName,
menuLoadCount,
menuCount,
functionCount,
totalItemCount);
// Add all functions to the zone state to make them available for all menus to be converted
for (auto& function : parsingResult.m_functions)
@@ -160,7 +161,7 @@ namespace
converter->ConvertMenu(*commonMenu, *menuAsset, menuRegistration);
if (menuAsset == nullptr)
{
std::cerr << std::format("Failed to convert menu file \"{}\"\n", commonMenu->m_name);
con::error("Failed to convert menu file \"{}\"", commonMenu->m_name);
return false;
}
@@ -212,10 +213,10 @@ namespace
};
} // namespace
namespace IW4
namespace menu
{
std::unique_ptr<AssetCreator<AssetMenuList>> CreateMenuListLoader(MemoryManager& memory, ISearchPath& searchPath)
std::unique_ptr<AssetCreator<AssetMenuList>> CreateMenuListLoaderIW4(MemoryManager& memory, ISearchPath& searchPath)
{
return std::make_unique<MenuListLoader>(memory, searchPath);
}
} // namespace IW4
} // namespace menu

View File

@@ -7,7 +7,7 @@
#include <memory>
namespace IW4
namespace menu
{
std::unique_ptr<AssetCreator<AssetMenuList>> CreateMenuListLoader(MemoryManager& memory, ISearchPath& searchPath);
} // namespace IW4
std::unique_ptr<AssetCreator<IW4::AssetMenuList>> CreateMenuListLoaderIW4(MemoryManager& memory, ISearchPath& searchPath);
} // namespace menu

View File

@@ -3,8 +3,9 @@
#include "Asset/GlobalAssetPoolsLoader.h"
#include "Game/IW4/GameIW4.h"
#include "Game/IW4/IW4.h"
#include "Game/IW4/XModel/LoaderXModelIW4.h"
#include "Leaderboard/LoaderLeaderboardIW4.h"
#include "LightDef/LoaderLightDefIW4.h"
#include "LightDef/LightDefLoaderIW4.h"
#include "Localize/LoaderLocalizeIW4.h"
#include "Material/LoaderMaterialIW4.h"
#include "Menu/LoaderMenuListIW4.h"
@@ -118,19 +119,19 @@ namespace
{
auto& memory = zone.Memory();
collection.AddAssetCreator(std::make_unique<RawLoaderPhysPreset>(memory, searchPath, zone));
collection.AddAssetCreator(std::make_unique<GdtLoaderPhysPreset>(memory, gdt, zone));
collection.AddAssetCreator(phys_preset::CreateRawLoaderIW4(memory, searchPath, zone));
collection.AddAssetCreator(phys_preset::CreateGdtLoaderIW4(memory, gdt, zone));
// collection.AddAssetCreator(std::make_unique<AssetLoaderPhysCollMap>(memory));
// collection.AddAssetCreator(std::make_unique<AssetLoaderXAnim>(memory));
// collection.AddAssetCreator(std::make_unique<AssetLoaderXModelSurfs>(memory));
// collection.AddAssetCreator(std::make_unique<AssetLoaderXModel>(memory));
collection.AddAssetCreator(CreateMaterialLoader(memory, searchPath));
collection.AddAssetCreator(CreatePixelShaderLoader(memory, searchPath));
collection.AddAssetCreator(CreateVertexShaderLoader(memory, searchPath));
collection.AddAssetCreator(xmodel::CreateLoaderIW4(memory, searchPath, zone));
collection.AddAssetCreator(material::CreateLoaderIW4(memory, searchPath));
collection.AddAssetCreator(shader::CreatePixelShaderLoaderIW4(memory, searchPath));
collection.AddAssetCreator(shader::CreateVertexShaderLoaderIW4(memory, searchPath));
// collection.AddAssetCreator(std::make_unique<AssetLoaderTechset>(memory));
// collection.AddAssetCreator(std::make_unique<AssetLoaderImage>(memory));
// collection.AddAssetCreator(std::make_unique<AssetLoaderSound>(memory));
collection.AddAssetCreator(CreateSoundCurveLoader(memory, searchPath));
collection.AddAssetCreator(sound_curve::CreateLoaderIW4(memory, searchPath));
// collection.AddAssetCreator(std::make_unique<AssetLoaderLoadedSound>(memory));
// collection.AddAssetCreator(std::make_unique<AssetLoaderClipMap>(memory));
// collection.AddAssetCreator(std::make_unique<AssetLoaderComWorld>(memory));
@@ -139,19 +140,19 @@ namespace
// collection.AddAssetCreator(std::make_unique<AssetLoaderMapEnts>(memory));
// collection.AddAssetCreator(std::make_unique<AssetLoaderFxWorld>(memory));
// collection.AddAssetCreator(std::make_unique<AssetLoaderGfxWorld>(memory));
collection.AddAssetCreator(CreateLightDefLoader(memory, searchPath));
collection.AddAssetCreator(light_def::CreateLoaderIW4(memory, searchPath));
// collection.AddAssetCreator(std::make_unique<AssetLoaderFont>(memory));
collection.AddAssetCreator(CreateMenuListLoader(memory, searchPath));
collection.AddAssetCreator(menu::CreateMenuListLoaderIW4(memory, searchPath));
// collection.AddAssetCreator(std::make_unique<AssetLoaderMenu>(memory));
collection.AddAssetCreator(CreateLocalizeLoader(memory, searchPath, zone));
collection.AddAssetCreator(CreateRawWeaponLoader(memory, searchPath, zone));
collection.AddAssetCreator(CreateGdtWeaponLoader(memory, searchPath, gdt, zone));
collection.AddAssetCreator(localize::CreateLoaderIW4(memory, searchPath, zone));
collection.AddAssetCreator(weapon::CreateRawLoaderIW4(memory, searchPath, zone));
collection.AddAssetCreator(weapon::CreateGdtLoaderIW4(memory, searchPath, gdt, zone));
// collection.AddAssetCreator(std::make_unique<AssetLoaderFx>(memory));
// collection.AddAssetCreator(std::make_unique<AssetLoaderImpactFx>(memory));
collection.AddAssetCreator(CreateRawFileLoader(memory, searchPath));
collection.AddAssetCreator(CreateStringTableLoader(memory, searchPath));
collection.AddAssetCreator(CreateLeaderboardLoader(memory, searchPath));
collection.AddAssetCreator(CreateStructuredDataDefLoader(memory, searchPath));
collection.AddAssetCreator(raw_file::CreateLoaderIW4(memory, searchPath));
collection.AddAssetCreator(string_table::CreateLoaderIW4(memory, searchPath));
collection.AddAssetCreator(leaderboard::CreateLoaderIW4(memory, searchPath));
collection.AddAssetCreator(structured_data_def::CreateLoaderIW4(memory, searchPath));
// collection.AddAssetCreator(std::make_unique<AssetLoaderTracer>(memory));
// collection.AddAssetCreator(std::make_unique<AssetLoaderVehicle>(memory));
// collection.AddAssetCreator(std::make_unique<AssetLoaderAddonMapEnts>(memory));

View File

@@ -4,32 +4,50 @@
#include "Game/IW4/ObjConstantsIW4.h"
#include "InfoString/InfoString.h"
#include "InfoStringLoaderPhysPresetIW4.h"
#include "Utils/Logging/Log.h"
#include <format>
#include <iostream>
using namespace IW4;
GdtLoaderPhysPreset::GdtLoaderPhysPreset(MemoryManager& memory, IGdtQueryable& gdt, Zone& zone)
: m_memory(memory),
m_gdt(gdt),
m_zone(zone)
namespace
{
}
AssetCreationResult GdtLoaderPhysPreset::CreateAsset(const std::string& assetName, AssetCreationContext& context)
{
auto* gdtEntry = m_gdt.GetGdtEntryByGdfAndName(ObjConstants::GDF_FILENAME_PHYS_PRESET, assetName);
if (gdtEntry == nullptr)
return AssetCreationResult::NoAction();
InfoString infoString;
if (!infoString.FromGdtProperties(*gdtEntry))
class GdtLoaderPhysPreset final : public AssetCreator<AssetPhysPreset>
{
std::cerr << std::format("Failed to read phys preset gdt entry: \"{}\"\n", assetName);
return AssetCreationResult::Failure();
}
public:
GdtLoaderPhysPreset(MemoryManager& memory, IGdtQueryable& gdt, Zone& zone)
: m_gdt(gdt),
m_info_string_loader(memory, zone)
{
}
InfoStringLoaderPhysPreset infoStringLoader(m_memory, m_zone);
return infoStringLoader.CreateAsset(assetName, infoString, context);
}
AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override
{
const auto* gdtEntry = m_gdt.GetGdtEntryByGdfAndName(ObjConstants::GDF_FILENAME_PHYS_PRESET, assetName);
if (gdtEntry == nullptr)
return AssetCreationResult::NoAction();
InfoString infoString;
if (!infoString.FromGdtProperties(*gdtEntry))
{
con::error("Failed to read phys preset gdt entry: \"{}\"", assetName);
return AssetCreationResult::Failure();
}
return m_info_string_loader.CreateAsset(assetName, infoString, context);
}
private:
IGdtQueryable& m_gdt;
phys_preset::InfoStringLoaderIW4 m_info_string_loader;
};
} // namespace
namespace phys_preset
{
std::unique_ptr<AssetCreator<IW4::AssetPhysPreset>> CreateGdtLoaderIW4(MemoryManager& memory, IGdtQueryable& gdt, Zone& zone)
{
return std::make_unique<GdtLoaderPhysPreset>(memory, gdt, zone);
}
} // namespace phys_preset

View File

@@ -3,20 +3,12 @@
#include "Asset/IAssetCreator.h"
#include "Game/IW4/IW4.h"
#include "Gdt/IGdtQueryable.h"
#include "SearchPath/ISearchPath.h"
#include "Utils/MemoryManager.h"
namespace IW4
#include <memory>
namespace phys_preset
{
class GdtLoaderPhysPreset final : public AssetCreator<AssetPhysPreset>
{
public:
GdtLoaderPhysPreset(MemoryManager& memory, IGdtQueryable& gdt, Zone& zone);
AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override;
private:
MemoryManager& m_memory;
IGdtQueryable& m_gdt;
Zone& m_zone;
};
} // namespace IW4
std::unique_ptr<AssetCreator<IW4::AssetPhysPreset>> CreateGdtLoaderIW4(MemoryManager& memory, IGdtQueryable& gdt, Zone& zone);
} // namespace phys_preset

View File

@@ -3,6 +3,7 @@
#include "Game/IW4/IW4.h"
#include "Game/IW4/InfoString/InfoStringToStructConverter.h"
#include "Game/IW4/PhysPreset/PhysPresetFields.h"
#include "Utils/Logging/Log.h"
#include <algorithm>
#include <cassert>
@@ -58,30 +59,33 @@ namespace
}
} // namespace
InfoStringLoaderPhysPreset::InfoStringLoaderPhysPreset(MemoryManager& memory, Zone& zone)
: m_memory(memory),
m_zone(zone)
namespace phys_preset
{
}
AssetCreationResult InfoStringLoaderPhysPreset::CreateAsset(const std::string& assetName, const InfoString& infoString, AssetCreationContext& context)
{
PhysPresetInfo presetInfo;
std::memset(&presetInfo, 0, sizeof(presetInfo));
auto* physPreset = m_memory.Alloc<PhysPreset>();
AssetRegistration<AssetPhysPreset> registration(assetName, physPreset);
InfoStringToPhysPresetConverter converter(
infoString, &presetInfo, m_zone.m_script_strings, m_memory, context, registration, phys_preset_fields, std::extent_v<decltype(phys_preset_fields)>);
if (!converter.Convert())
InfoStringLoaderIW4::InfoStringLoaderIW4(MemoryManager& memory, Zone& zone)
: m_memory(memory),
m_zone(zone)
{
std::cerr << std::format("Failed to parse phys preset: \"{}\"\n", assetName);
return AssetCreationResult::Failure();
}
CopyFromPhysPresetInfo(presetInfo, *physPreset);
physPreset->name = m_memory.Dup(assetName.c_str());
AssetCreationResult InfoStringLoaderIW4::CreateAsset(const std::string& assetName, const InfoString& infoString, AssetCreationContext& context)
{
PhysPresetInfo presetInfo;
std::memset(&presetInfo, 0, sizeof(presetInfo));
return AssetCreationResult::Success(context.AddAsset(std::move(registration)));
}
auto* physPreset = m_memory.Alloc<PhysPreset>();
AssetRegistration<AssetPhysPreset> registration(assetName, physPreset);
InfoStringToPhysPresetConverter converter(
infoString, &presetInfo, m_zone.m_script_strings, m_memory, context, registration, phys_preset_fields, std::extent_v<decltype(phys_preset_fields)>);
if (!converter.Convert())
{
con::error("Failed to parse phys preset: \"{}\"", assetName);
return AssetCreationResult::Failure();
}
CopyFromPhysPresetInfo(presetInfo, *physPreset);
physPreset->name = m_memory.Dup(assetName.c_str());
return AssetCreationResult::Success(context.AddAsset(std::move(registration)));
}
} // namespace phys_preset

View File

@@ -4,12 +4,12 @@
#include "Asset/AssetCreationResult.h"
#include "InfoString/InfoString.h"
namespace IW4
namespace phys_preset
{
class InfoStringLoaderPhysPreset
class InfoStringLoaderIW4
{
public:
InfoStringLoaderPhysPreset(MemoryManager& memory, Zone& zone);
InfoStringLoaderIW4(MemoryManager& memory, Zone& zone);
AssetCreationResult CreateAsset(const std::string& assetName, const InfoString& infoString, AssetCreationContext& context);
@@ -17,4 +17,4 @@ namespace IW4
MemoryManager& m_memory;
Zone& m_zone;
};
} // namespace IW4
} // namespace phys_preset

View File

@@ -4,33 +4,52 @@
#include "Game/IW4/ObjConstantsIW4.h"
#include "InfoString/InfoString.h"
#include "InfoStringLoaderPhysPresetIW4.h"
#include "PhysPreset/PhysPresetCommon.h"
#include "Utils/Logging/Log.h"
#include <format>
#include <iostream>
using namespace IW4;
RawLoaderPhysPreset::RawLoaderPhysPreset(MemoryManager& memory, ISearchPath& searchPath, Zone& zone)
: m_memory(memory),
m_search_path(searchPath),
m_zone(zone)
namespace
{
}
AssetCreationResult RawLoaderPhysPreset::CreateAsset(const std::string& assetName, AssetCreationContext& context)
{
const auto fileName = std::format("physic/{}", assetName);
const auto file = m_search_path.Open(fileName);
if (!file.IsOpen())
return AssetCreationResult::NoAction();
InfoString infoString;
if (!infoString.FromStream(ObjConstants::INFO_STRING_PREFIX_PHYS_PRESET, *file.m_stream))
class RawLoaderPhysPreset final : public AssetCreator<AssetPhysPreset>
{
std::cerr << std::format("Could not parse as info string file: \"{}\"\n", fileName);
return AssetCreationResult::Failure();
}
public:
RawLoaderPhysPreset(MemoryManager& memory, ISearchPath& searchPath, Zone& zone)
: m_search_path(searchPath),
m_info_string_loader(memory, zone)
{
}
InfoStringLoaderPhysPreset infoStringLoader(m_memory, m_zone);
return infoStringLoader.CreateAsset(assetName, infoString, context);
}
AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override
{
const auto fileName = phys_preset::GetFileNameForAssetName(assetName);
const auto file = m_search_path.Open(fileName);
if (!file.IsOpen())
return AssetCreationResult::NoAction();
InfoString infoString;
if (!infoString.FromStream(ObjConstants::INFO_STRING_PREFIX_PHYS_PRESET, *file.m_stream))
{
con::error("Could not parse as info string file: \"{}\"", fileName);
return AssetCreationResult::Failure();
}
return m_info_string_loader.CreateAsset(assetName, infoString, context);
}
private:
ISearchPath& m_search_path;
phys_preset::InfoStringLoaderIW4 m_info_string_loader;
};
} // namespace
namespace phys_preset
{
std::unique_ptr<AssetCreator<AssetPhysPreset>> CreateRawLoaderIW4(MemoryManager& memory, ISearchPath& searchPath, Zone& zone)
{
return std::make_unique<RawLoaderPhysPreset>(memory, searchPath, zone);
}
} // namespace phys_preset

View File

@@ -5,18 +5,9 @@
#include "SearchPath/ISearchPath.h"
#include "Utils/MemoryManager.h"
namespace IW4
#include <memory>
namespace phys_preset
{
class RawLoaderPhysPreset final : public AssetCreator<AssetPhysPreset>
{
public:
RawLoaderPhysPreset(MemoryManager& memory, ISearchPath& searchPath, Zone& zone);
AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override;
private:
MemoryManager& m_memory;
ISearchPath& m_search_path;
Zone& m_zone;
};
} // namespace IW4
std::unique_ptr<AssetCreator<IW4::AssetPhysPreset>> CreateRawLoaderIW4(MemoryManager& memory, ISearchPath& searchPath, Zone& zone);
} // namespace phys_preset

View File

@@ -1,6 +1,7 @@
#include "LoaderRawFileIW4.h"
#include "Game/IW4/IW4.h"
#include "Utils/Logging/Log.h"
#include <cstring>
#include <filesystem>
@@ -58,7 +59,7 @@ namespace
if (ret != Z_STREAM_END)
{
std::cerr << std::format("Deflate failed for loading rawfile \"{}\"\n", assetName);
con::error("Deflate failed for loading rawfile \"{}\"", assetName);
deflateEnd(&zs);
return AssetCreationResult::Failure();
}
@@ -82,10 +83,10 @@ namespace
};
} // namespace
namespace IW4
namespace raw_file
{
std::unique_ptr<AssetCreator<AssetRawFile>> CreateRawFileLoader(MemoryManager& memory, ISearchPath& searchPath)
std::unique_ptr<AssetCreator<AssetRawFile>> CreateLoaderIW4(MemoryManager& memory, ISearchPath& searchPath)
{
return std::make_unique<RawFileLoader>(memory, searchPath);
}
} // namespace IW4
} // namespace raw_file

View File

@@ -7,7 +7,7 @@
#include <memory>
namespace IW4
namespace raw_file
{
std::unique_ptr<AssetCreator<AssetRawFile>> CreateRawFileLoader(MemoryManager& memory, ISearchPath& searchPath);
} // namespace IW4
std::unique_ptr<AssetCreator<IW4::AssetRawFile>> CreateLoaderIW4(MemoryManager& memory, ISearchPath& searchPath);
} // namespace raw_file

View File

@@ -1,6 +1,8 @@
#include "LoaderPixelShaderIW4.h"
#include "Game/IW4/IW4.h"
#include "Shader/ShaderCommon.h"
#include "Utils/Logging/Log.h"
#include <cstdint>
#include <format>
@@ -21,14 +23,14 @@ namespace
AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override
{
const auto fileName = GetPixelShaderFileName(assetName);
const auto fileName = shader::GetFileNameForPixelShaderAssetName(assetName);
const auto file = m_search_path.Open(fileName);
if (!file.IsOpen())
return AssetCreationResult::NoAction();
if (file.m_length % sizeof(uint32_t) != 0)
{
std::cerr << std::format("Invalid pixel shader \"{}\": Size must be dividable by {}\n", assetName, sizeof(uint32_t));
con::error("Invalid pixel shader \"{}\": Size must be dividable by {}", assetName, sizeof(uint32_t));
return AssetCreationResult::Failure();
}
@@ -53,15 +55,10 @@ namespace
};
} // namespace
namespace IW4
namespace shader
{
std::string GetPixelShaderFileName(const std::string& pixelShaderAssetName)
{
return std::format("shader_bin/ps_{}.cso", pixelShaderAssetName);
}
std::unique_ptr<AssetCreator<AssetPixelShader>> CreatePixelShaderLoader(MemoryManager& memory, ISearchPath& searchPath)
std::unique_ptr<AssetCreator<AssetPixelShader>> CreatePixelShaderLoaderIW4(MemoryManager& memory, ISearchPath& searchPath)
{
return std::make_unique<PixelShaderLoader>(memory, searchPath);
}
} // namespace IW4
} // namespace shader

View File

@@ -7,9 +7,7 @@
#include <memory>
namespace IW4
namespace shader
{
[[nodiscard]] std::string GetPixelShaderFileName(const std::string& pixelShaderAssetName);
std::unique_ptr<AssetCreator<AssetPixelShader>> CreatePixelShaderLoader(MemoryManager& memory, ISearchPath& searchPath);
} // namespace IW4
std::unique_ptr<AssetCreator<IW4::AssetPixelShader>> CreatePixelShaderLoaderIW4(MemoryManager& memory, ISearchPath& searchPath);
} // namespace shader

View File

@@ -1,6 +1,8 @@
#include "LoaderVertexShaderIW4.h"
#include "Game/IW4/IW4.h"
#include "Shader/ShaderCommon.h"
#include "Utils/Logging/Log.h"
#include <cstdint>
#include <format>
@@ -21,14 +23,14 @@ namespace
AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override
{
const auto fileName = GetVertexShaderFileName(assetName);
const auto fileName = shader::GetFileNameForVertexShaderAssetName(assetName);
const auto file = m_search_path.Open(fileName);
if (!file.IsOpen())
return AssetCreationResult::NoAction();
if (file.m_length % sizeof(uint32_t) != 0)
{
std::cerr << std::format("Invalid vertex shader \"{}\": Size must be dividable by {}\n", assetName, sizeof(uint32_t));
con::error("Invalid vertex shader \"{}\": Size must be dividable by {}", assetName, sizeof(uint32_t));
return AssetCreationResult::Failure();
}
@@ -53,15 +55,10 @@ namespace
};
} // namespace
namespace IW4
namespace shader
{
std::string GetVertexShaderFileName(const std::string& vertexShaderAssetName)
{
return std::format("shader_bin/vs_{}.cso", vertexShaderAssetName);
}
std::unique_ptr<AssetCreator<AssetVertexShader>> CreateVertexShaderLoader(MemoryManager& memory, ISearchPath& searchPath)
std::unique_ptr<AssetCreator<AssetVertexShader>> CreateVertexShaderLoaderIW4(MemoryManager& memory, ISearchPath& searchPath)
{
return std::make_unique<VertexShaderLoader>(memory, searchPath);
}
} // namespace IW4
} // namespace shader

View File

@@ -7,9 +7,7 @@
#include <memory>
namespace IW4
namespace shader
{
[[nodiscard]] std::string GetVertexShaderFileName(const std::string& vertexShaderAssetName);
std::unique_ptr<AssetCreator<AssetVertexShader>> CreateVertexShaderLoader(MemoryManager& memory, ISearchPath& searchPath);
} // namespace IW4
std::unique_ptr<AssetCreator<IW4::AssetVertexShader>> CreateVertexShaderLoaderIW4(MemoryManager& memory, ISearchPath& searchPath);
} // namespace shader

View File

@@ -4,6 +4,8 @@
#include "ObjLoading.h"
#include "Parsing/Graph2D/Graph2DReader.h"
#include "Pool/GlobalAssetPool.h"
#include "Sound/SoundCurveCommon.h"
#include "Utils/Logging/Log.h"
#include <cstring>
#include <format>
@@ -25,7 +27,7 @@ namespace
AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override
{
const auto fileName = std::format("soundaliases/{}.vfcurve", assetName);
const auto fileName = sound_curve::GetFileNameForAssetName(assetName);
const auto file = m_search_path.Open(fileName);
if (!file.IsOpen())
return AssetCreationResult::NoAction();
@@ -37,7 +39,7 @@ namespace
if (sndCurveData->knots.size() > std::extent_v<decltype(SndCurve::knots)>)
{
std::cerr << std::format("Failed to load SndCurve \"{}\": Too many knots ({})\n", assetName, sndCurveData->knots.size());
con::error("Failed to load SndCurve \"{}\": Too many knots ({})", assetName, sndCurveData->knots.size());
return AssetCreationResult::Failure();
}
@@ -69,10 +71,10 @@ namespace
};
} // namespace
namespace IW4
namespace sound_curve
{
std::unique_ptr<AssetCreator<AssetSoundCurve>> CreateSoundCurveLoader(MemoryManager& memory, ISearchPath& searchPath)
std::unique_ptr<AssetCreator<AssetSoundCurve>> CreateLoaderIW4(MemoryManager& memory, ISearchPath& searchPath)
{
return std::make_unique<LoaderSoundCurve>(memory, searchPath);
}
} // namespace IW4
} // namespace sound_curve

View File

@@ -7,7 +7,7 @@
#include <memory>
namespace IW4
namespace sound_curve
{
std::unique_ptr<AssetCreator<AssetSoundCurve>> CreateSoundCurveLoader(MemoryManager& memory, ISearchPath& searchPath);
} // namespace IW4
std::unique_ptr<AssetCreator<IW4::AssetSoundCurve>> CreateLoaderIW4(MemoryManager& memory, ISearchPath& searchPath);
} // namespace sound_curve

View File

@@ -38,10 +38,10 @@ namespace
};
} // namespace
namespace IW4
namespace string_table
{
std::unique_ptr<AssetCreator<AssetStringTable>> CreateStringTableLoader(MemoryManager& memory, ISearchPath& searchPath)
std::unique_ptr<AssetCreator<AssetStringTable>> CreateLoaderIW4(MemoryManager& memory, ISearchPath& searchPath)
{
return std::make_unique<LoaderStringTable>(memory, searchPath);
}
} // namespace IW4
} // namespace string_table

View File

@@ -7,7 +7,7 @@
#include <memory>
namespace IW4
namespace string_table
{
std::unique_ptr<AssetCreator<AssetStringTable>> CreateStringTableLoader(MemoryManager& memory, ISearchPath& searchPath);
} // namespace IW4
std::unique_ptr<AssetCreator<IW4::AssetStringTable>> CreateLoaderIW4(MemoryManager& memory, ISearchPath& searchPath);
} // namespace string_table

View File

@@ -207,10 +207,10 @@ namespace
};
} // namespace
namespace IW4
namespace structured_data_def
{
std::unique_ptr<AssetCreator<AssetStructuredDataDef>> CreateStructuredDataDefLoader(MemoryManager& memory, ISearchPath& searchPath)
std::unique_ptr<AssetCreator<AssetStructuredDataDef>> CreateLoaderIW4(MemoryManager& memory, ISearchPath& searchPath)
{
return std::make_unique<StructuredDataDefLoader>(memory, searchPath);
}
} // namespace IW4
} // namespace structured_data_def

View File

@@ -7,7 +7,7 @@
#include <memory>
namespace IW4
namespace structured_data_def
{
std::unique_ptr<AssetCreator<AssetStructuredDataDef>> CreateStructuredDataDefLoader(MemoryManager& memory, ISearchPath& searchPath);
} // namespace IW4
std::unique_ptr<AssetCreator<IW4::AssetStructuredDataDef>> CreateLoaderIW4(MemoryManager& memory, ISearchPath& searchPath);
} // namespace structured_data_def

View File

@@ -4,6 +4,7 @@
#include "Game/IW4/ObjConstantsIW4.h"
#include "InfoString/InfoString.h"
#include "InfoStringLoaderWeaponIW4.h"
#include "Utils/Logging/Log.h"
#include <cstring>
#include <format>
@@ -31,7 +32,7 @@ namespace
InfoString infoString;
if (!infoString.FromGdtProperties(*gdtEntry))
{
std::cerr << std::format("Failed to read weapon gdt entry: \"{}\"\n", assetName);
con::error("Failed to read weapon gdt entry: \"{}\"", assetName);
return AssetCreationResult::Failure();
}
@@ -40,14 +41,14 @@ namespace
private:
IGdtQueryable& m_gdt;
InfoStringLoaderWeapon m_info_string_loader;
weapon::InfoStringLoaderIW4 m_info_string_loader;
};
} // namespace
namespace IW4
namespace weapon
{
std::unique_ptr<AssetCreator<AssetWeapon>> CreateGdtWeaponLoader(MemoryManager& memory, ISearchPath& searchPath, IGdtQueryable& gdt, Zone& zone)
std::unique_ptr<AssetCreator<IW4::AssetWeapon>> CreateGdtLoaderIW4(MemoryManager& memory, ISearchPath& searchPath, IGdtQueryable& gdt, Zone& zone)
{
return std::make_unique<GdtLoaderWeapon>(memory, searchPath, gdt, zone);
}
} // namespace IW4
} // namespace weapon

View File

@@ -8,7 +8,7 @@
#include <memory>
namespace IW4
namespace weapon
{
std::unique_ptr<AssetCreator<AssetWeapon>> CreateGdtWeaponLoader(MemoryManager& memory, ISearchPath& searchPath, IGdtQueryable& gdt, Zone& zone);
} // namespace IW4
std::unique_ptr<AssetCreator<IW4::AssetWeapon>> CreateGdtLoaderIW4(MemoryManager& memory, ISearchPath& searchPath, IGdtQueryable& gdt, Zone& zone);
} // namespace weapon

View File

@@ -4,6 +4,7 @@
#include "Game/IW4/InfoString/EnumStrings.h"
#include "Game/IW4/InfoString/InfoStringToStructConverter.h"
#include "Game/IW4/Weapon/WeaponFields.h"
#include "Utils/Logging/Log.h"
#include "Weapon/AccuracyGraphLoader.h"
#include <cassert>
@@ -23,13 +24,13 @@ namespace
std::vector<std::string> valueArray;
if (!ParseAsArray(value, valueArray))
{
std::cerr << "Failed to parse hide tags as array\n";
con::error("Failed to parse hide tags as array");
return false;
}
if (valueArray.size() > std::extent_v<decltype(WeaponFullDef::hideTags)>)
{
std::cerr << std::format("Cannot have more than {} hide tags!\n", std::extent_v<decltype(WeaponFullDef::hideTags)>);
con::error("Cannot have more than {} hide tags!", std::extent_v<decltype(WeaponFullDef::hideTags)>);
return false;
}
@@ -85,14 +86,13 @@ namespace
std::vector<std::array<std::string, 2>> pairs;
if (!ParseAsArray(value, pairs))
{
std::cerr << std::format("Failed to parse notetrack{}map as pairs\n", mapName);
con::error("Failed to parse notetrack{}map as pairs", mapName);
return false;
}
if (pairs.size() > std::extent_v<decltype(WeaponFullDef::notetrackSoundMapKeys)>)
{
std::cerr << std::format(
"Cannot have more than {} notetrack{}map entries!\n", std::extent_v<decltype(WeaponFullDef::notetrackSoundMapKeys)>, mapName);
con::error("Cannot have more than {} notetrack{}map entries!", std::extent_v<decltype(WeaponFullDef::notetrackSoundMapKeys)>, mapName);
return false;
}
@@ -267,28 +267,27 @@ namespace
void CheckProjectileValues(const WeaponCompleteDef& weaponCompleteDef, const WeaponDef& weaponDef)
{
if (weaponDef.iProjectileSpeed <= 0)
std::cerr << std::format("Projectile speed for WeapType {} must be greater than 0.0", weaponCompleteDef.szDisplayName);
con::error("Projectile speed for WeapType {} must be greater than 0.0", weaponCompleteDef.szDisplayName);
if (weaponDef.destabilizationCurvatureMax >= 1000000000.0f || weaponDef.destabilizationCurvatureMax < 0.0f)
std::cerr << std::format("Destabilization angle for for WeapType {} must be between 0 and 45 degrees", weaponCompleteDef.szDisplayName);
con::error("Destabilization angle for for WeapType {} must be between 0 and 45 degrees", weaponCompleteDef.szDisplayName);
if (weaponDef.destabilizationRateTime < 0.0f)
std::cerr << std::format("Destabilization rate time for for WeapType {} must be non-negative", weaponCompleteDef.szDisplayName);
con::error("Destabilization rate time for for WeapType {} must be non-negative", weaponCompleteDef.szDisplayName);
}
void CheckTurretBarrelSpin(const WeaponCompleteDef& weaponCompleteDef, const WeaponDef& weaponDef)
{
if (weaponDef.weapClass != WEAPCLASS_TURRET)
std::cerr << std::format("Rotating barrel set for non-turret weapon {}.", weaponCompleteDef.szInternalName);
con::error("Rotating barrel set for non-turret weapon {}.", weaponCompleteDef.szInternalName);
if (0.0f == weaponDef.turretBarrelSpinSpeed)
{
std::cerr << std::format(
"Rotating barrel spin speed '{}' is invalid for weapon {}.", weaponDef.turretBarrelSpinSpeed, weaponCompleteDef.szInternalName);
con::error("Rotating barrel spin speed '{}' is invalid for weapon {}.", weaponDef.turretBarrelSpinSpeed, weaponCompleteDef.szInternalName);
}
if (0.0f < weaponDef.turretOverheatUpRate && 0.0f >= weaponDef.turretOverheatDownRate)
{
std::cerr << std::format("Turret overheat Up rate is set, but the down rate '{}' is invalid for weapon {}.",
weaponDef.turretOverheatDownRate,
weaponCompleteDef.szInternalName);
con::error("Turret overheat Up rate is set, but the down rate '{}' is invalid for weapon {}.",
weaponDef.turretOverheatDownRate,
weaponCompleteDef.szInternalName);
}
}
@@ -296,18 +295,18 @@ namespace
{
if (0.0f != weaponDef.fAdsZoomInFrac)
{
std::cerr << std::format("Weapon {} ({}) has thermal scope set. ADS Zoom In frac should be 0 to prevent zoom-in blur ({}).\n",
weaponCompleteDef.szInternalName,
weaponCompleteDef.szDisplayName,
weaponDef.fAdsZoomInFrac);
con::error("Weapon {} ({}) has thermal scope set. ADS Zoom In frac should be 0 to prevent zoom-in blur ({}).",
weaponCompleteDef.szInternalName,
weaponCompleteDef.szDisplayName,
weaponDef.fAdsZoomInFrac);
}
if (0.0f != weaponDef.fAdsZoomOutFrac)
{
std::cerr << std::format("Weapon {} ({}) has thermal scope set. ADS Zoom Out frac should be 0 to prevent zoom-out blur ({}).\n",
weaponCompleteDef.szInternalName,
weaponCompleteDef.szDisplayName,
weaponDef.fAdsZoomOutFrac);
con::error("Weapon {} ({}) has thermal scope set. ADS Zoom Out frac should be 0 to prevent zoom-out blur ({}).",
weaponCompleteDef.szInternalName,
weaponCompleteDef.szDisplayName,
weaponDef.fAdsZoomOutFrac);
}
}
@@ -337,7 +336,7 @@ namespace
weaponDef.fMinDamageRange = 999999.12f;
if (weaponDef.enemyCrosshairRange > 15000.0f)
std::cerr << std::format("Enemy crosshair ranges should be less than {}\n", 15000.0f);
con::error("Enemy crosshair ranges should be less than {}", 15000.0f);
if (weaponDef.weapType == WEAPTYPE_PROJECTILE)
CheckProjectileValues(weaponCompleteDef, weaponDef);
@@ -350,22 +349,21 @@ namespace
if (weaponDef.offhandClass && !weaponDef.bClipOnly)
{
std::cerr << std::format(
"Weapon {} ({}) is an offhand weapon but is not set to clip only, which is not supported since we can't reload the offhand slot.\n",
weaponCompleteDef.szInternalName,
weaponCompleteDef.szDisplayName);
con::error("Weapon {} ({}) is an offhand weapon but is not set to clip only, which is not supported since we can't reload the offhand slot.",
weaponCompleteDef.szInternalName,
weaponCompleteDef.szDisplayName);
}
if (weaponDef.weapType == WEAPTYPE_BULLET)
{
if (weaponDef.bulletExplDmgMult <= 0.0f)
std::cerr << std::format("Detected invalid bulletExplDmgMult of '{}' for weapon '{}'; please update weapon settings.\n",
weaponDef.bulletExplDmgMult,
weaponCompleteDef.szInternalName);
con::error("Detected invalid bulletExplDmgMult of '{}' for weapon '{}'; please update weapon settings.",
weaponDef.bulletExplDmgMult,
weaponCompleteDef.szInternalName);
if (weaponDef.bulletExplRadiusMult <= 0.0f)
std::cerr << std::format("Detected invalid bulletExplRadiusMult of '{}' for weapon '{}'; please update weapon settings.\n",
weaponDef.bulletExplRadiusMult,
weaponCompleteDef.szInternalName);
con::error("Detected invalid bulletExplRadiusMult of '{}' for weapon '{}'; please update weapon settings.",
weaponDef.bulletExplRadiusMult,
weaponCompleteDef.szInternalName);
}
}
@@ -426,33 +424,36 @@ namespace
}
} // namespace
InfoStringLoaderWeapon::InfoStringLoaderWeapon(MemoryManager& memory, ISearchPath& searchPath, Zone& zone)
: m_memory(memory),
m_search_path(searchPath),
m_zone(zone)
namespace weapon
{
}
AssetCreationResult InfoStringLoaderWeapon::CreateAsset(const std::string& assetName, const InfoString& infoString, AssetCreationContext& context)
{
auto* weaponFullDef = m_memory.Alloc<WeaponFullDef>();
InitWeaponFullDef(*weaponFullDef);
weaponFullDef->weapCompleteDef.szInternalName = m_memory.Dup(assetName.c_str());
AssetRegistration<AssetWeapon> registration(assetName, &weaponFullDef->weapCompleteDef);
InfoStringToWeaponConverter converter(
infoString, *weaponFullDef, m_zone.m_script_strings, m_memory, context, registration, weapon_fields, std::extent_v<decltype(weapon_fields)>);
if (!converter.Convert())
InfoStringLoaderIW4::InfoStringLoaderIW4(MemoryManager& memory, ISearchPath& searchPath, Zone& zone)
: m_memory(memory),
m_search_path(searchPath),
m_zone(zone)
{
std::cerr << std::format("Failed to parse weapon: \"{}\"\n", assetName);
return AssetCreationResult::Failure();
}
CalculateWeaponFields(*weaponFullDef, m_memory);
AssetCreationResult InfoStringLoaderIW4::CreateAsset(const std::string& assetName, const InfoString& infoString, AssetCreationContext& context)
{
auto* weaponFullDef = m_memory.Alloc<WeaponFullDef>();
LoadAccuracyGraphs(*weaponFullDef, m_memory, m_search_path, context);
InitWeaponFullDef(*weaponFullDef);
weaponFullDef->weapCompleteDef.szInternalName = m_memory.Dup(assetName.c_str());
return AssetCreationResult::Success(context.AddAsset(std::move(registration)));
}
AssetRegistration<AssetWeapon> registration(assetName, &weaponFullDef->weapCompleteDef);
InfoStringToWeaponConverter converter(
infoString, *weaponFullDef, m_zone.m_script_strings, m_memory, context, registration, weapon_fields, std::extent_v<decltype(weapon_fields)>);
if (!converter.Convert())
{
con::error("Failed to parse weapon: \"{}\"", assetName);
return AssetCreationResult::Failure();
}
CalculateWeaponFields(*weaponFullDef, m_memory);
LoadAccuracyGraphs(*weaponFullDef, m_memory, m_search_path, context);
return AssetCreationResult::Success(context.AddAsset(std::move(registration)));
}
} // namespace weapon

View File

@@ -4,12 +4,12 @@
#include "Asset/AssetCreationResult.h"
#include "InfoString/InfoString.h"
namespace IW4
namespace weapon
{
class InfoStringLoaderWeapon
class InfoStringLoaderIW4
{
public:
InfoStringLoaderWeapon(MemoryManager& memory, ISearchPath& searchPath, Zone& zone);
InfoStringLoaderIW4(MemoryManager& memory, ISearchPath& searchPath, Zone& zone);
AssetCreationResult CreateAsset(const std::string& assetName, const InfoString& infoString, AssetCreationContext& context);
@@ -18,4 +18,4 @@ namespace IW4
ISearchPath& m_search_path;
Zone& m_zone;
};
} // namespace IW4
} // namespace weapon

View File

@@ -4,6 +4,8 @@
#include "Game/IW4/ObjConstantsIW4.h"
#include "InfoString/InfoString.h"
#include "InfoStringLoaderWeaponIW4.h"
#include "Utils/Logging/Log.h"
#include "Weapon/WeaponCommon.h"
#include <cstring>
#include <format>
@@ -24,7 +26,7 @@ namespace
AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override
{
const auto fileName = std::format("weapons/{}", assetName);
const auto fileName = weapon::GetFileNameForAssetName(assetName);
const auto file = m_search_path.Open(fileName);
if (!file.IsOpen())
return AssetCreationResult::NoAction();
@@ -32,7 +34,7 @@ namespace
InfoString infoString;
if (!infoString.FromStream(ObjConstants::INFO_STRING_PREFIX_WEAPON, *file.m_stream))
{
std::cerr << std::format("Could not parse as info string file: \"{}\"\n", fileName);
con::error("Could not parse as info string file: \"{}\"", fileName);
return AssetCreationResult::Failure();
}
@@ -41,14 +43,14 @@ namespace
private:
ISearchPath& m_search_path;
InfoStringLoaderWeapon m_info_string_loader;
weapon::InfoStringLoaderIW4 m_info_string_loader;
};
} // namespace
namespace IW4
namespace weapon
{
std::unique_ptr<AssetCreator<AssetWeapon>> CreateRawWeaponLoader(MemoryManager& memory, ISearchPath& searchPath, Zone& zone)
std::unique_ptr<AssetCreator<AssetWeapon>> CreateRawLoaderIW4(MemoryManager& memory, ISearchPath& searchPath, Zone& zone)
{
return std::make_unique<RawLoaderWeapon>(memory, searchPath, zone);
}
} // namespace IW4
} // namespace weapon

View File

@@ -7,7 +7,7 @@
#include <memory>
namespace IW4
namespace weapon
{
std::unique_ptr<AssetCreator<AssetWeapon>> CreateRawWeaponLoader(MemoryManager& memory, ISearchPath& searchPath, Zone& zone);
} // namespace IW4
std::unique_ptr<AssetCreator<IW4::AssetWeapon>> CreateRawLoaderIW4(MemoryManager& memory, ISearchPath& searchPath, Zone& zone);
} // namespace weapon

View File

@@ -1,7 +1,9 @@
#include "LoaderImageIW5.h"
#include "Game/IW5/IW5.h"
#include "Image/ImageCommon.h"
#include "Image/IwiLoader.h"
#include "Utils/Logging/Log.h"
#include <cstring>
#include <format>
@@ -25,7 +27,7 @@ namespace
AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override
{
const auto fileName = std::format("images/{}.iwi", assetName);
const auto fileName = image::GetFileNameForAsset(assetName, ".iwi");
const auto file = m_search_path.Open(fileName);
if (!file.IsOpen())
return AssetCreationResult::NoAction();
@@ -38,7 +40,7 @@ namespace
const auto texture = iwi::LoadIwi(ss);
if (!texture)
{
std::cerr << std::format("Failed to load texture from: {}\n", fileName);
con::error("Failed to load texture from: {}", fileName);
return AssetCreationResult::Failure();
}
@@ -60,10 +62,10 @@ namespace
};
} // namespace
namespace IW5
namespace image
{
std::unique_ptr<AssetCreator<AssetImage>> CreateImageLoader(MemoryManager& memory, ISearchPath& searchPath)
std::unique_ptr<AssetCreator<AssetImage>> CreateLoaderIW5(MemoryManager& memory, ISearchPath& searchPath)
{
return std::make_unique<ImageLoader>(memory, searchPath);
}
} // namespace IW5
} // namespace image

View File

@@ -7,7 +7,7 @@
#include <memory>
namespace IW5
namespace image
{
std::unique_ptr<AssetCreator<AssetImage>> CreateImageLoader(MemoryManager& memory, ISearchPath& searchPath);
} // namespace IW5
std::unique_ptr<AssetCreator<IW5::AssetImage>> CreateLoaderIW5(MemoryManager& memory, ISearchPath& searchPath);
} // namespace image

View File

@@ -1,5 +1,7 @@
#include "InfoStringToStructConverter.h"
#include "Utils/Logging/Log.h"
#include <cassert>
#include <format>
#include <iostream>
@@ -63,7 +65,7 @@ bool InfoStringToStructConverter::ConvertBaseField(const cspField_t& field, cons
if (fx == nullptr)
{
std::cerr << std::format("Failed to load fx asset \"{}\"\n", value);
con::error("Failed to load fx asset \"{}\"", value);
return false;
}
@@ -85,7 +87,7 @@ bool InfoStringToStructConverter::ConvertBaseField(const cspField_t& field, cons
if (xmodel == nullptr)
{
std::cerr << std::format("Failed to load xmodel asset \"{}\"\n", value);
con::error("Failed to load xmodel asset \"{}\"", value);
return false;
}
@@ -107,7 +109,7 @@ bool InfoStringToStructConverter::ConvertBaseField(const cspField_t& field, cons
if (material == nullptr)
{
std::cerr << std::format("Failed to load material asset \"{}\"\n", value);
con::error("Failed to load material asset \"{}\"", value);
return false;
}
@@ -129,7 +131,7 @@ bool InfoStringToStructConverter::ConvertBaseField(const cspField_t& field, cons
if (tracer == nullptr)
{
std::cerr << std::format("Failed to load tracer asset \"{}\"\n", value);
con::error("Failed to load tracer asset \"{}\"", value);
return false;
}
@@ -146,7 +148,7 @@ bool InfoStringToStructConverter::ConvertBaseField(const cspField_t& field, cons
if (endPtr != &value[value.size()])
{
std::cout << "Failed to parse value \"" << value << "\" as mph\n";
con::error("Failed to parse value \"{}\" as mph", value);
return false;
}
@@ -165,7 +167,7 @@ bool InfoStringToStructConverter::ConvertBaseField(const cspField_t& field, cons
if (collmap == nullptr)
{
std::cerr << std::format("Failed to load collmap asset \"{}\"\n", value);
con::error("Failed to load collmap asset \"{}\"", value);
return false;
}

View File

@@ -1,131 +0,0 @@
#include "JsonLeaderboardDefLoader.h"
#include "Game/IW5/CommonIW5.h"
#include "Game/IW5/Leaderboard/JsonLeaderboardDef.h"
#include <format>
#include <iostream>
#include <nlohmann/json.hpp>
using namespace nlohmann;
using namespace IW5;
namespace
{
class JsonLoader
{
public:
JsonLoader(std::istream& stream, MemoryManager& memory)
: m_stream(stream),
m_memory(memory)
{
}
bool Load(LeaderboardDef& leaderboardDef) const
{
const auto jRoot = json::parse(m_stream);
std::string type;
unsigned version;
jRoot.at("_type").get_to(type);
jRoot.at("_version").get_to(version);
if (type != "leaderboard" || version != 1u)
{
std::cerr << std::format("Tried to load leaderboard \"{}\" but did not find expected type leaderboard of version 1\n", leaderboardDef.name);
return false;
}
try
{
const auto jLeaderboard = jRoot.get<JsonLeaderboardDef>();
return CreateLeaderboardFromJson(jLeaderboard, leaderboardDef);
}
catch (const json::exception& e)
{
std::cerr << std::format("Failed to parse json of leaderboard: {}\n", e.what());
}
return false;
}
private:
static bool CreateTrackTypeFlagsFromJson(const JsonLeaderboardDef& jLeaderboardDef, int& trackTypeFlags)
{
for (const auto trackType : jLeaderboardDef.trackTypes)
trackTypeFlags |= 1 << trackType;
return true;
}
bool CreateColumnDefFromJson(const JsonColumnDef& jColumn, LbColumnDef& lbColumnDef, LeaderboardDef& leaderboardDef) const
{
lbColumnDef.name = m_memory.Dup(jColumn.name.c_str());
lbColumnDef.id = jColumn.colId;
lbColumnDef.propertyId = jColumn.propertyId.value_or(0);
lbColumnDef.hidden = jColumn.hidden.value_or(false);
if (jColumn.statName)
lbColumnDef.statName = m_memory.Dup(jColumn.statName->c_str());
else
lbColumnDef.statName = nullptr;
lbColumnDef.type = jColumn.type;
lbColumnDef.precision = jColumn.precision.value_or(0);
lbColumnDef.agg = jColumn.aggregationFunction;
lbColumnDef.uiCalColX = jColumn.uiCalColX.value_or(0);
lbColumnDef.uiCalColY = jColumn.uiCalColY.value_or(0);
return true;
}
bool CreateLeaderboardFromJson(const JsonLeaderboardDef& jLeaderboardDef, LeaderboardDef& leaderboardDef) const
{
leaderboardDef.id = jLeaderboardDef.id;
leaderboardDef.xpColId = jLeaderboardDef.xpColId.value_or(-1);
leaderboardDef.prestigeColId = jLeaderboardDef.prestigeColId.value_or(-1);
if (!jLeaderboardDef.columns.empty())
{
leaderboardDef.columnCount = static_cast<int>(jLeaderboardDef.columns.size());
leaderboardDef.columns = m_memory.Alloc<LbColumnDef>(leaderboardDef.columnCount);
for (auto i = 0; i < leaderboardDef.columnCount; i++)
{
if (!CreateColumnDefFromJson(jLeaderboardDef.columns[i], leaderboardDef.columns[i], leaderboardDef))
return false;
}
}
else
{
leaderboardDef.columnCount = 0;
leaderboardDef.columns = nullptr;
}
leaderboardDef.updateType = jLeaderboardDef.updateType;
if (!CreateTrackTypeFlagsFromJson(jLeaderboardDef, leaderboardDef.trackTypes))
return false;
return true;
}
std::istream& m_stream;
MemoryManager& m_memory;
};
} // namespace
namespace IW5
{
bool LoadLeaderboardAsJson(std::istream& stream, LeaderboardDef& leaderboard, MemoryManager& memory)
{
const JsonLoader loader(stream, memory);
return loader.Load(leaderboard);
}
} // namespace IW5

View File

@@ -1,11 +0,0 @@
#pragma once
#include "Game/IW5/IW5.h"
#include "Utils/MemoryManager.h"
#include <istream>
namespace IW5
{
bool LoadLeaderboardAsJson(std::istream& stream, LeaderboardDef& leaderboard, MemoryManager& memory);
} // namespace IW5

View File

@@ -1,16 +1,127 @@
#include "LoaderLeaderboardIW5.h"
#include "Game/IW5/IW5.h"
#include "JsonLeaderboardDefLoader.h"
#include "Game/IW5/Leaderboard/JsonLeaderboardDef.h"
#include "Leaderboard/LeaderboardCommon.h"
#include "Utils/Logging/Log.h"
#include <cstring>
#include <format>
#include <iostream>
#include <nlohmann/json.hpp>
using namespace nlohmann;
using namespace IW5;
namespace
{
class JsonLoader
{
public:
JsonLoader(std::istream& stream, MemoryManager& memory)
: m_stream(stream),
m_memory(memory)
{
}
bool Load(LeaderboardDef& leaderboardDef) const
{
try
{
const auto jRoot = json::parse(m_stream);
std::string type;
unsigned version;
jRoot.at("_type").get_to(type);
jRoot.at("_version").get_to(version);
if (type != "leaderboard" || version != 1u)
{
con::error("Tried to load leaderboard \"{}\" but did not find expected type leaderboard of version 1", leaderboardDef.name);
return false;
}
const auto jLeaderboard = jRoot.get<JsonLeaderboardDef>();
return CreateLeaderboardFromJson(jLeaderboard, leaderboardDef);
}
catch (const json::exception& e)
{
con::error("Failed to parse json of leaderboard: {}", e.what());
}
return false;
}
private:
static bool CreateTrackTypeFlagsFromJson(const JsonLeaderboardDef& jLeaderboardDef, int& trackTypeFlags)
{
for (const auto trackType : jLeaderboardDef.trackTypes)
trackTypeFlags |= 1 << trackType;
return true;
}
bool CreateColumnDefFromJson(const JsonColumnDef& jColumn, LbColumnDef& lbColumnDef, LeaderboardDef& leaderboardDef) const
{
lbColumnDef.name = m_memory.Dup(jColumn.name.c_str());
lbColumnDef.id = jColumn.colId;
lbColumnDef.propertyId = jColumn.propertyId.value_or(0);
lbColumnDef.hidden = jColumn.hidden.value_or(false);
if (jColumn.statName)
lbColumnDef.statName = m_memory.Dup(jColumn.statName->c_str());
else
lbColumnDef.statName = nullptr;
lbColumnDef.type = jColumn.type;
lbColumnDef.precision = jColumn.precision.value_or(0);
lbColumnDef.agg = jColumn.aggregationFunction;
lbColumnDef.uiCalColX = jColumn.uiCalColX.value_or(0);
lbColumnDef.uiCalColY = jColumn.uiCalColY.value_or(0);
return true;
}
bool CreateLeaderboardFromJson(const JsonLeaderboardDef& jLeaderboardDef, LeaderboardDef& leaderboardDef) const
{
leaderboardDef.id = jLeaderboardDef.id;
leaderboardDef.xpColId = jLeaderboardDef.xpColId.value_or(-1);
leaderboardDef.prestigeColId = jLeaderboardDef.prestigeColId.value_or(-1);
if (!jLeaderboardDef.columns.empty())
{
leaderboardDef.columnCount = static_cast<int>(jLeaderboardDef.columns.size());
leaderboardDef.columns = m_memory.Alloc<LbColumnDef>(leaderboardDef.columnCount);
for (auto i = 0; i < leaderboardDef.columnCount; i++)
{
if (!CreateColumnDefFromJson(jLeaderboardDef.columns[i], leaderboardDef.columns[i], leaderboardDef))
return false;
}
}
else
{
leaderboardDef.columnCount = 0;
leaderboardDef.columns = nullptr;
}
leaderboardDef.updateType = jLeaderboardDef.updateType;
if (!CreateTrackTypeFlagsFromJson(jLeaderboardDef, leaderboardDef.trackTypes))
return false;
return true;
}
std::istream& m_stream;
MemoryManager& m_memory;
};
class LeaderboardLoader final : public AssetCreator<AssetLeaderboard>
{
public:
@@ -22,16 +133,17 @@ namespace
AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override
{
const auto file = m_search_path.Open(std::format("leaderboards/{}.json", assetName));
const auto file = m_search_path.Open(leaderboard::GetJsonFileNameForAsset(assetName));
if (!file.IsOpen())
return AssetCreationResult::NoAction();
auto* leaderboardDef = m_memory.Alloc<LeaderboardDef>();
leaderboardDef->name = m_memory.Dup(assetName.c_str());
if (!LoadLeaderboardAsJson(*file.m_stream, *leaderboardDef, m_memory))
const JsonLoader loader(*file.m_stream, m_memory);
if (!loader.Load(*leaderboardDef))
{
std::cerr << std::format("Failed to load leaderboard \"{}\"\n", assetName);
con::error("Failed to load leaderboard \"{}\"", assetName);
return AssetCreationResult::Failure();
}
@@ -44,10 +156,10 @@ namespace
};
} // namespace
namespace IW5
namespace leaderboard
{
std::unique_ptr<AssetCreator<AssetLeaderboard>> CreateLeaderboardLoader(MemoryManager& memory, ISearchPath& searchPath)
std::unique_ptr<AssetCreator<AssetLeaderboard>> CreateLoaderIW5(MemoryManager& memory, ISearchPath& searchPath)
{
return std::make_unique<LeaderboardLoader>(memory, searchPath);
}
} // namespace IW5
} // namespace leaderboard

View File

@@ -7,7 +7,7 @@
#include <memory>
namespace IW5
namespace leaderboard
{
std::unique_ptr<AssetCreator<AssetLeaderboard>> CreateLeaderboardLoader(MemoryManager& memory, ISearchPath& searchPath);
} // namespace IW5
std::unique_ptr<AssetCreator<IW5::AssetLeaderboard>> CreateLoaderIW5(MemoryManager& memory, ISearchPath& searchPath);
} // namespace leaderboard

View File

@@ -35,10 +35,10 @@ namespace
};
} // namespace
namespace IW5
namespace localize
{
std::unique_ptr<AssetCreator<AssetLocalize>> CreateLocalizeLoader(MemoryManager& memory, ISearchPath& searchPath, Zone& zone)
std::unique_ptr<AssetCreator<AssetLocalize>> CreateLoaderIW5(MemoryManager& memory, ISearchPath& searchPath, Zone& zone)
{
return std::make_unique<LocalizeLoader>(memory, searchPath, zone);
}
} // namespace IW5
} // namespace localize

View File

@@ -8,7 +8,7 @@
#include <memory>
namespace IW5
namespace localize
{
std::unique_ptr<AssetCreator<AssetLocalize>> CreateLocalizeLoader(MemoryManager& memory, ISearchPath& searchPath, Zone& zone);
} // namespace IW5
std::unique_ptr<AssetCreator<IW5::AssetLocalize>> CreateLoaderIW5(MemoryManager& memory, ISearchPath& searchPath, Zone& zone);
} // namespace localize

View File

@@ -3,6 +3,7 @@
#include "Game/IW5/IW5.h"
#include "Game/IW5/Material/JsonMaterialLoaderIW5.h"
#include "Material/MaterialCommon.h"
#include "Utils/Logging/Log.h"
#include <format>
#include <iostream>
@@ -32,7 +33,7 @@ namespace
AssetRegistration<AssetMaterial> registration(assetName, material);
if (!LoadMaterialAsJson(*file.m_stream, *material, m_memory, context, registration))
{
std::cerr << std::format("Failed to load material \"{}\"\n", assetName);
con::error("Failed to load material \"{}\"", assetName);
return AssetCreationResult::Failure();
}
@@ -45,10 +46,10 @@ namespace
};
} // namespace
namespace IW5
namespace material
{
std::unique_ptr<AssetCreator<AssetMaterial>> CreateMaterialLoader(MemoryManager& memory, ISearchPath& searchPath)
std::unique_ptr<AssetCreator<AssetMaterial>> CreateLoaderIW5(MemoryManager& memory, ISearchPath& searchPath)
{
return std::make_unique<MaterialLoader>(memory, searchPath);
}
} // namespace IW5
} // namespace material

View File

@@ -7,7 +7,7 @@
#include <memory>
namespace IW5
namespace material
{
std::unique_ptr<AssetCreator<AssetMaterial>> CreateMaterialLoader(MemoryManager& memory, ISearchPath& searchPath);
} // namespace IW5
std::unique_ptr<AssetCreator<IW5::AssetMaterial>> CreateLoaderIW5(MemoryManager& memory, ISearchPath& searchPath);
} // namespace material

View File

@@ -5,6 +5,7 @@
#include "Game/IW5/Menu/MenuConverterIW5.h"
#include "ObjLoading.h"
#include "Parsing/Menu/MenuFileReader.h"
#include "Utils/Logging/Log.h"
#include <cstring>
#include <format>
@@ -88,7 +89,7 @@ namespace
const auto alreadyLoadedMenuFile = conversionState.m_menus_by_filename.find(menuFilePath);
if (alreadyLoadedMenuFile != conversionState.m_menus_by_filename.end())
{
std::cout << std::format("Already loaded \"{}\", skipping\n", menuFilePath);
con::debug("Already loaded \"{}\", skipping", menuFilePath);
for (auto* menu : alreadyLoadedMenuFile->second)
{
menus.emplace_back(menu->Asset());
@@ -100,7 +101,7 @@ namespace
const auto file = m_search_path.Open(menuFilePath);
if (!file.IsOpen())
{
std::cerr << std::format("Could not open menu file \"{}\"\n", menuFilePath);
con::error("Could not open menu file \"{}\"", menuFilePath);
return false;
}
@@ -109,12 +110,12 @@ namespace
{
ProcessParsedResults(menuFilePath, context, *menuFileResult, zoneState, conversionState, menus, registration);
if (!menuFileResult->m_menus_to_load.empty())
std::cout << std::format("WARNING: Menu file has menus to load even though it is not a menu list, ignoring: \"{}\"\n", menuFilePath);
con::warn("Menu file has menus to load even though it is not a menu list, ignoring: \"{}\"", menuFilePath);
return true;
}
else
std::cerr << std::format("Could not read menu file \"{}\"\n", menuFilePath);
con::error("Could not read menu file \"{}\"", menuFilePath);
return false;
}
@@ -134,12 +135,12 @@ namespace
for (const auto& menu : parsingResult.m_menus)
totalItemCount += static_cast<unsigned>(menu->m_items.size());
std::cout << std::format("Successfully read menu file \"{}\" ({} loads, {} menus, {} functions, {} items)\n",
fileName,
menuLoadCount,
menuCount,
functionCount,
totalItemCount);
con::info("Successfully read menu file \"{}\" ({} loads, {} menus, {} functions, {} items)",
fileName,
menuLoadCount,
menuCount,
functionCount,
totalItemCount);
// Add all functions to the zone state to make them available for all menus to be converted
for (auto& function : parsingResult.m_functions)
@@ -160,7 +161,7 @@ namespace
converter->ConvertMenu(*commonMenu, *menuAsset, menuRegistration);
if (menuAsset == nullptr)
{
std::cerr << std::format("Failed to convert menu file \"{}\"\n", commonMenu->m_name);
con::error("Failed to convert menu file \"{}\"", commonMenu->m_name);
return false;
}
@@ -212,10 +213,10 @@ namespace
};
} // namespace
namespace IW5
namespace menu
{
std::unique_ptr<AssetCreator<AssetMenuList>> CreateMenuListLoader(MemoryManager& memory, ISearchPath& searchPath)
std::unique_ptr<AssetCreator<AssetMenuList>> CreateMenuListLoaderIW5(MemoryManager& memory, ISearchPath& searchPath)
{
return std::make_unique<MenuListLoader>(memory, searchPath);
}
} // namespace IW5
} // namespace menu

View File

@@ -7,7 +7,7 @@
#include <memory>
namespace IW5
namespace menu
{
std::unique_ptr<AssetCreator<AssetMenuList>> CreateMenuListLoader(MemoryManager& memory, ISearchPath& searchPath);
} // namespace IW5
std::unique_ptr<AssetCreator<IW5::AssetMenuList>> CreateMenuListLoaderIW5(MemoryManager& memory, ISearchPath& searchPath);
} // namespace menu

View File

@@ -14,7 +14,7 @@ namespace IW5
IMenuConverter() = default;
virtual ~IMenuConverter() = default;
virtual void ConvertMenu(const menu::CommonMenuDef& commonMenu, menuDef_t& menu, AssetRegistration<AssetMenu>& registration) = 0;
virtual void ConvertMenu(const ::menu::CommonMenuDef& commonMenu, menuDef_t& menu, AssetRegistration<AssetMenu>& registration) = 0;
static std::unique_ptr<IMenuConverter> Create(bool disableOptimizations, ISearchPath& searchPath, MemoryManager& memory, AssetCreationContext& context);
};

View File

@@ -125,13 +125,13 @@ namespace
// collection.AddAssetCreator(std::make_unique<AssetLoaderPhysCollMap>(memory));
// collection.AddAssetCreator(std::make_unique<AssetLoaderXAnim>(memory));
// collection.AddAssetCreator(std::make_unique<AssetLoaderXModelSurfs>(memory));
collection.AddAssetCreator(CreateXModelLoader(memory, searchPath, zone));
collection.AddAssetCreator(CreateMaterialLoader(memory, searchPath));
collection.AddAssetCreator(xmodel::CreateLoaderIW5(memory, searchPath, zone));
collection.AddAssetCreator(material::CreateLoaderIW5(memory, searchPath));
// collection.AddAssetCreator(std::make_unique<AssetLoaderPixelShader>(memory));
// collection.AddAssetCreator(std::make_unique<AssetLoaderVertexShader>(memory));
// collection.AddAssetCreator(std::make_unique<AssetLoaderVertexDecl>(memory));
// collection.AddAssetCreator(std::make_unique<AssetLoaderTechniqueSet>(memory));
collection.AddAssetCreator(CreateImageLoader(memory, searchPath));
collection.AddAssetCreator(image::CreateLoaderIW5(memory, searchPath));
// collection.AddAssetCreator(std::make_unique<AssetLoaderSound>(memory));
// collection.AddAssetCreator(std::make_unique<AssetLoaderSoundCurve>(memory));
// collection.AddAssetCreator(std::make_unique<AssetLoaderLoadedSound>(memory));
@@ -145,19 +145,19 @@ namespace
// collection.AddAssetCreator(std::make_unique<AssetLoaderGfxWorld>(memory));
// collection.AddAssetCreator(std::make_unique<AssetLoaderLightDef>(memory));
// collection.AddAssetCreator(std::make_unique<AssetLoaderFont>(memory));
collection.AddAssetCreator(CreateMenuListLoader(memory, searchPath));
collection.AddAssetCreator(menu::CreateMenuListLoaderIW5(memory, searchPath));
// collection.AddAssetCreator(std::make_unique<AssetLoaderMenu>(memory));
collection.AddAssetCreator(CreateLocalizeLoader(memory, searchPath, zone));
collection.AddAssetCreator(CreateAttachmentLoader(memory, searchPath));
collection.AddAssetCreator(CreateRawWeaponLoader(memory, searchPath, zone));
collection.AddAssetCreator(CreateGdtWeaponLoader(memory, searchPath, gdt, zone));
collection.AddAssetCreator(localize::CreateLoaderIW5(memory, searchPath, zone));
collection.AddAssetCreator(attachment::CreateLoaderIW5(memory, searchPath));
collection.AddAssetCreator(weapon::CreateRawLoaderIW5(memory, searchPath, zone));
collection.AddAssetCreator(weapon::CreateGdtLoaderIW5(memory, searchPath, gdt, zone));
// collection.AddAssetCreator(std::make_unique<AssetLoaderFx>(memory));
// collection.AddAssetCreator(std::make_unique<AssetLoaderImpactFx>(memory));
// collection.AddAssetCreator(std::make_unique<AssetLoaderSurfaceFx>(memory));
collection.AddAssetCreator(CreateRawFileLoader(memory, searchPath));
collection.AddAssetCreator(CreateScriptLoader(memory, searchPath));
collection.AddAssetCreator(CreateStringTableLoader(memory, searchPath));
collection.AddAssetCreator(CreateLeaderboardLoader(memory, searchPath));
collection.AddAssetCreator(raw_file::CreateLoaderIW5(memory, searchPath));
collection.AddAssetCreator(script::CreateLoaderIW5(memory, searchPath));
collection.AddAssetCreator(string_table::CreateLoaderIW5(memory, searchPath));
collection.AddAssetCreator(leaderboard::CreateLoaderIW5(memory, searchPath));
// collection.AddAssetCreator(std::make_unique<AssetLoaderStructuredDataDef>(memory));
// collection.AddAssetCreator(std::make_unique<AssetLoaderTracer>(memory));
// collection.AddAssetCreator(std::make_unique<AssetLoaderVehicle>(memory));

View File

@@ -2,6 +2,7 @@
#include "Game/IW5/IW5.h"
#include "Pool/GlobalAssetPool.h"
#include "Utils/Logging/Log.h"
#include <cstring>
#include <filesystem>
@@ -57,7 +58,7 @@ namespace
if (ret != Z_STREAM_END)
{
std::cerr << std::format("Deflate failed for loading rawfile \"{}\"\n", assetName);
con::error("Deflate failed for loading rawfile \"{}\"", assetName);
deflateEnd(&zs);
return AssetCreationResult::Failure();
}
@@ -81,10 +82,10 @@ namespace
};
} // namespace
namespace IW5
namespace raw_file
{
std::unique_ptr<AssetCreator<AssetRawFile>> CreateRawFileLoader(MemoryManager& memory, ISearchPath& searchPath)
std::unique_ptr<AssetCreator<AssetRawFile>> CreateLoaderIW5(MemoryManager& memory, ISearchPath& searchPath)
{
return std::make_unique<RawFileLoader>(memory, searchPath);
}
} // namespace IW5
} // namespace raw_file

View File

@@ -7,7 +7,7 @@
#include <memory>
namespace IW5
namespace raw_file
{
std::unique_ptr<AssetCreator<AssetRawFile>> CreateRawFileLoader(MemoryManager& memory, ISearchPath& searchPath);
} // namespace IW5
std::unique_ptr<AssetCreator<IW5::AssetRawFile>> CreateLoaderIW5(MemoryManager& memory, ISearchPath& searchPath);
} // namespace raw_file

View File

@@ -2,6 +2,7 @@
#include "Game/IW5/IW5.h"
#include "Pool/GlobalAssetPool.h"
#include "Utils/Logging/Log.h"
#include <cstring>
#include <filesystem>
@@ -53,13 +54,13 @@ namespace
if (scriptFile->compressedLen <= 0 || scriptFile->bytecodeLen <= 0)
{
std::cerr << std::format("Error: Invalid length of the buffers in {} specified\n", assetName);
con::error("Invalid length of the buffers in {} specified", assetName);
return AssetCreationResult::Failure();
}
if (offset + static_cast<size_t>(scriptFile->compressedLen + scriptFile->bytecodeLen) > static_cast<size_t>(file.m_length))
{
std::cerr << std::format("Error: Specified length in {} GSC BIN structure exceeds the actual file size\n", assetName);
con::error("Specified length in {} GSC BIN structure exceeds the actual file size", assetName);
return AssetCreationResult::Failure();
}
@@ -79,10 +80,10 @@ namespace
};
} // namespace
namespace IW5
namespace script
{
std::unique_ptr<AssetCreator<AssetScript>> CreateScriptLoader(MemoryManager& memory, ISearchPath& searchPath)
std::unique_ptr<AssetCreator<AssetScript>> CreateLoaderIW5(MemoryManager& memory, ISearchPath& searchPath)
{
return std::make_unique<ScriptLoader>(memory, searchPath);
}
} // namespace IW5
} // namespace script

View File

@@ -7,7 +7,7 @@
#include <memory>
namespace IW5
namespace script
{
std::unique_ptr<AssetCreator<AssetScript>> CreateScriptLoader(MemoryManager& memory, ISearchPath& searchPath);
} // namespace IW5
std::unique_ptr<AssetCreator<IW5::AssetScript>> CreateLoaderIW5(MemoryManager& memory, ISearchPath& searchPath);
} // namespace script

View File

@@ -40,10 +40,10 @@ namespace
};
} // namespace
namespace IW5
namespace string_table
{
std::unique_ptr<AssetCreator<AssetStringTable>> CreateStringTableLoader(MemoryManager& memory, ISearchPath& searchPath)
std::unique_ptr<AssetCreator<AssetStringTable>> CreateLoaderIW5(MemoryManager& memory, ISearchPath& searchPath)
{
return std::make_unique<StringTableLoader>(memory, searchPath);
}
} // namespace IW5
} // namespace string_table

View File

@@ -7,7 +7,7 @@
#include <memory>
namespace IW5
namespace string_table
{
std::unique_ptr<AssetCreator<AssetStringTable>> CreateStringTableLoader(MemoryManager& memory, ISearchPath& searchPath);
} // namespace IW5
std::unique_ptr<AssetCreator<IW5::AssetStringTable>> CreateLoaderIW5(MemoryManager& memory, ISearchPath& searchPath);
} // namespace string_table

View File

@@ -4,6 +4,7 @@
#include "Game/IW5/ObjConstantsIW5.h"
#include "InfoString/InfoString.h"
#include "InfoStringLoaderWeaponIW5.h"
#include "Utils/Logging/Log.h"
#include <cstring>
#include <format>
@@ -31,7 +32,7 @@ namespace
InfoString infoString;
if (!infoString.FromGdtProperties(*gdtEntry))
{
std::cerr << std::format("Failed to read weapon gdt entry: \"{}\"\n", assetName);
con::error("Failed to read weapon gdt entry: \"{}\"", assetName);
return AssetCreationResult::Failure();
}
@@ -40,14 +41,14 @@ namespace
private:
IGdtQueryable& m_gdt;
InfoStringLoaderWeapon m_info_string_loader;
weapon::InfoStringLoaderIW5 m_info_string_loader;
};
} // namespace
namespace IW5
namespace weapon
{
std::unique_ptr<AssetCreator<AssetWeapon>> CreateGdtWeaponLoader(MemoryManager& memory, ISearchPath& searchPath, IGdtQueryable& gdt, Zone& zone)
std::unique_ptr<AssetCreator<AssetWeapon>> CreateGdtLoaderIW5(MemoryManager& memory, ISearchPath& searchPath, IGdtQueryable& gdt, Zone& zone)
{
return std::make_unique<GdtLoaderWeapon>(memory, searchPath, gdt, zone);
}
} // namespace IW5
} // namespace weapon

View File

@@ -8,7 +8,7 @@
#include <memory>
namespace IW5
namespace weapon
{
std::unique_ptr<AssetCreator<AssetWeapon>> CreateGdtWeaponLoader(MemoryManager& memory, ISearchPath& searchPath, IGdtQueryable& gdt, Zone& zone);
} // namespace IW5
std::unique_ptr<AssetCreator<IW5::AssetWeapon>> CreateGdtLoaderIW5(MemoryManager& memory, ISearchPath& searchPath, IGdtQueryable& gdt, Zone& zone);
} // namespace weapon

View File

@@ -3,6 +3,7 @@
#include "Game/IW5/IW5.h"
#include "Game/IW5/InfoString/InfoStringToStructConverter.h"
#include "Game/IW5/Weapon/WeaponFields.h"
#include "Utils/Logging/Log.h"
#include "Weapon/AccuracyGraphLoader.h"
#include <cassert>
@@ -22,13 +23,13 @@ namespace
std::vector<std::string> valueArray;
if (!ParseAsArray(value, valueArray))
{
std::cerr << "Failed to parse hide tags as array\n";
con::error("Failed to parse hide tags as array");
return false;
}
if (valueArray.size() > std::extent_v<decltype(WeaponFullDef::hideTags)>)
{
std::cerr << std::format("Cannot have more than {} hide tags!\n", std::extent_v<decltype(WeaponFullDef::hideTags)>);
con::error("Cannot have more than {} hide tags!", std::extent_v<decltype(WeaponFullDef::hideTags)>);
return false;
}
@@ -83,14 +84,13 @@ namespace
std::vector<std::array<std::string, 2>> pairs;
if (!ParseAsArray(value, pairs))
{
std::cerr << std::format("Failed to parse notetrack{}map as pairs\n", mapName);
con::error("Failed to parse notetrack{}map as pairs", mapName);
return false;
}
if (pairs.size() > std::extent_v<decltype(WeaponFullDef::notetrackSoundMapKeys)>)
{
std::cerr << std::format(
"Cannot have more than {} notetrack{}map entries!\n", std::extent_v<decltype(WeaponFullDef::notetrackSoundMapKeys)>, mapName);
con::error("Cannot have more than {} notetrack{}map entries!", std::extent_v<decltype(WeaponFullDef::notetrackSoundMapKeys)>, mapName);
return false;
}
@@ -146,7 +146,7 @@ namespace
std::vector<std::string> valueArray;
if (!ParseAsArray(value, valueArray))
{
std::cerr << "Failed to parse attachments as array\n";
con::error("Failed to parse attachments as array");
return false;
}
@@ -165,7 +165,7 @@ namespace
{
if (currentScope >= std::extent_v<decltype(WeaponFullDef::scopes)>)
{
std::cerr << std::format("Cannot have more than {} scopes\n", std::extent_v<decltype(WeaponFullDef::scopes)>);
con::error("Cannot have more than {} scopes", std::extent_v<decltype(WeaponFullDef::scopes)>);
return false;
}
@@ -175,7 +175,7 @@ namespace
{
if (currentUnderBarrel >= std::extent_v<decltype(WeaponFullDef::underBarrels)>)
{
std::cerr << std::format("Cannot have more than {} under barrels\n", std::extent_v<decltype(WeaponFullDef::underBarrels)>);
con::error("Cannot have more than {} under barrels", std::extent_v<decltype(WeaponFullDef::underBarrels)>);
return false;
}
@@ -185,7 +185,7 @@ namespace
{
if (currentOther >= std::extent_v<decltype(WeaponFullDef::others)>)
{
std::cerr << std::format("Cannot have more than {} other attachments\n", std::extent_v<decltype(WeaponFullDef::others)>);
con::error("Cannot have more than {} other attachments", std::extent_v<decltype(WeaponFullDef::others)>);
return false;
}
@@ -201,7 +201,7 @@ namespace
std::vector<std::array<std::string, 7>> valueArray;
if (!ParseAsArray(value, valueArray))
{
std::cerr << "Failed to parse anim overrides as array\n";
con::error("Failed to parse anim overrides as array");
return false;
}
@@ -242,7 +242,7 @@ namespace
std::vector<std::array<std::string, 5>> valueArray;
if (!ParseAsArray(value, valueArray))
{
std::cerr << "Failed to parse sound overrides as array\n";
con::error("Failed to parse sound overrides as array");
return false;
}
@@ -277,7 +277,7 @@ namespace
std::vector<std::array<std::string, 5>> valueArray;
if (!ParseAsArray(value, valueArray))
{
std::cerr << "Failed to parse attachments as array\n";
con::error("Failed to parse attachments as array");
return false;
}
@@ -315,7 +315,7 @@ namespace
std::vector<std::array<std::string, 3>> valueArray;
if (!ParseAsArray(value, valueArray))
{
std::cerr << "Failed to parse reload overrides as array\n";
con::error("Failed to parse reload overrides as array");
return false;
}
@@ -349,7 +349,7 @@ namespace
std::vector<std::array<std::string, 3>> valueArray;
if (!ParseAsArray(value, valueArray))
{
std::cerr << "Failed to parse note track overrides as array\n";
con::error("Failed to parse note track overrides as array");
return false;
}
@@ -378,7 +378,7 @@ namespace
if (currentOverrideKeyOffset >= 24u)
{
std::cerr << std::format("Cannot have more than {} note track overrides per attachment\n", 24u);
con::error("Cannot have more than {} note track overrides per attachment", 24u);
return false;
}
@@ -433,7 +433,7 @@ namespace
}
}
std::cerr << std::format("Weapon does not have attachment \"{}\"\n", value);
con::error("Weapon does not have attachment \"{}\"", value);
return false;
}
@@ -473,7 +473,7 @@ namespace
auto* fxInfo = m_context.LoadDependency<AssetFx>(value);
if (!fxInfo)
{
std::cerr << std::format("Failed to load fx for override \"{}\"\n", value);
con::error("Failed to load fx for override \"{}\"", value);
return false;
}
@@ -494,7 +494,7 @@ namespace
}
}
std::cerr << std::format("Unknown anim file \"{}\"\n", value);
con::error("Unknown anim file \"{}\"", value);
return false;
}
@@ -509,7 +509,7 @@ namespace
}
}
std::cerr << std::format("Unknown sound type \"{}\"\n", value);
con::error("Unknown sound type \"{}\"", value);
return false;
}
@@ -524,7 +524,7 @@ namespace
}
}
std::cerr << std::format("Unknown fx type \"{}\"\n", value);
con::error("Unknown fx type \"{}\"", value);
return false;
}
@@ -535,7 +535,7 @@ namespace
if (size != value.size())
{
std::cerr << std::format("Invalid int value: \"{}\"\n", value);
con::error("Invalid int value: \"{}\"", value);
return false;
}
@@ -697,28 +697,27 @@ namespace
void CheckProjectileValues(const WeaponCompleteDef& weaponCompleteDef, const WeaponDef& weaponDef)
{
if (weaponDef.iProjectileSpeed <= 0)
std::cerr << std::format("Projectile speed for WeapType {} must be greater than 0.0", weaponCompleteDef.szDisplayName);
con::error("Projectile speed for WeapType {} must be greater than 0.0", weaponCompleteDef.szDisplayName);
if (weaponDef.destabilizationCurvatureMax >= 1000000000.0f || weaponDef.destabilizationCurvatureMax < 0.0f)
std::cerr << std::format("Destabilization angle for for WeapType {} must be between 0 and 45 degrees", weaponCompleteDef.szDisplayName);
con::error("Destabilization angle for for WeapType {} must be between 0 and 45 degrees", weaponCompleteDef.szDisplayName);
if (weaponDef.destabilizationRateTime < 0.0f)
std::cerr << std::format("Destabilization rate time for for WeapType {} must be non-negative", weaponCompleteDef.szDisplayName);
con::error("Destabilization rate time for for WeapType {} must be non-negative", weaponCompleteDef.szDisplayName);
}
void CheckTurretBarrelSpin(const WeaponCompleteDef& weaponCompleteDef, const WeaponDef& weaponDef)
{
if (weaponDef.weapClass != WEAPCLASS_TURRET)
std::cerr << std::format("Rotating barrel set for non-turret weapon {}.", weaponCompleteDef.szInternalName);
con::error("Rotating barrel set for non-turret weapon {}.", weaponCompleteDef.szInternalName);
if (0.0f == weaponDef.turretBarrelSpinSpeed)
{
std::cerr << std::format(
"Rotating barrel spin speed '{}' is invalid for weapon {}.", weaponDef.turretBarrelSpinSpeed, weaponCompleteDef.szInternalName);
con::error("Rotating barrel spin speed '{}' is invalid for weapon {}.", weaponDef.turretBarrelSpinSpeed, weaponCompleteDef.szInternalName);
}
if (0.0f < weaponDef.turretOverheatUpRate && 0.0f >= weaponDef.turretOverheatDownRate)
{
std::cerr << std::format("Turret overheat Up rate is set, but the down rate '{}' is invalid for weapon {}.",
weaponDef.turretOverheatDownRate,
weaponCompleteDef.szInternalName);
con::error("Turret overheat Up rate is set, but the down rate '{}' is invalid for weapon {}.",
weaponDef.turretOverheatDownRate,
weaponCompleteDef.szInternalName);
}
}
@@ -726,18 +725,18 @@ namespace
{
if (0.0f != weaponDef.fAdsZoomInFrac)
{
std::cerr << std::format("Weapon {} ({}) has thermal scope set. ADS Zoom In frac should be 0 to prevent zoom-in blur ({}).\n",
weaponCompleteDef.szInternalName,
weaponCompleteDef.szDisplayName,
weaponDef.fAdsZoomInFrac);
con::error("Weapon {} ({}) has thermal scope set. ADS Zoom In frac should be 0 to prevent zoom-in blur ({}).",
weaponCompleteDef.szInternalName,
weaponCompleteDef.szDisplayName,
weaponDef.fAdsZoomInFrac);
}
if (0.0f != weaponDef.fAdsZoomOutFrac)
{
std::cerr << std::format("Weapon {} ({}) has thermal scope set. ADS Zoom Out frac should be 0 to prevent zoom-out blur ({}).\n",
weaponCompleteDef.szInternalName,
weaponCompleteDef.szDisplayName,
weaponDef.fAdsZoomOutFrac);
con::error("Weapon {} ({}) has thermal scope set. ADS Zoom Out frac should be 0 to prevent zoom-out blur ({}).",
weaponCompleteDef.szInternalName,
weaponCompleteDef.szDisplayName,
weaponDef.fAdsZoomOutFrac);
}
}
@@ -767,7 +766,7 @@ namespace
weaponDef.fMinDamageRange = 999999.12f;
if (weaponDef.enemyCrosshairRange > 15000.0f)
std::cerr << std::format("Enemy crosshair ranges should be less than {}\n", 15000.0f);
con::error("Enemy crosshair ranges should be less than {}", 15000.0f);
if (weaponDef.weapType == WEAPTYPE_PROJECTILE)
CheckProjectileValues(weaponCompleteDef, weaponDef);
@@ -780,22 +779,21 @@ namespace
if (weaponDef.offhandClass && !weaponDef.bClipOnly)
{
std::cerr << std::format(
"Weapon {} ({}) is an offhand weapon but is not set to clip only, which is not supported since we can't reload the offhand slot.\n",
weaponCompleteDef.szInternalName,
weaponCompleteDef.szDisplayName);
con::error("Weapon {} ({}) is an offhand weapon but is not set to clip only, which is not supported since we can't reload the offhand slot.",
weaponCompleteDef.szInternalName,
weaponCompleteDef.szDisplayName);
}
if (weaponDef.weapType == WEAPTYPE_BULLET)
{
if (weaponDef.bulletExplDmgMult <= 0.0f)
std::cerr << std::format("Detected invalid bulletExplDmgMult of '{}' for weapon '{}'; please update weapon settings.\n",
weaponDef.bulletExplDmgMult,
weaponCompleteDef.szInternalName);
con::error("Detected invalid bulletExplDmgMult of '{}' for weapon '{}'; please update weapon settings.",
weaponDef.bulletExplDmgMult,
weaponCompleteDef.szInternalName);
if (weaponDef.bulletExplRadiusMult <= 0.0f)
std::cerr << std::format("Detected invalid bulletExplRadiusMult of '{}' for weapon '{}'; please update weapon settings.\n",
weaponDef.bulletExplRadiusMult,
weaponCompleteDef.szInternalName);
con::error("Detected invalid bulletExplRadiusMult of '{}' for weapon '{}'; please update weapon settings.",
weaponDef.bulletExplRadiusMult,
weaponCompleteDef.szInternalName);
}
}
@@ -856,33 +854,36 @@ namespace
}
} // namespace
InfoStringLoaderWeapon::InfoStringLoaderWeapon(MemoryManager& memory, ISearchPath& searchPath, Zone& zone)
: m_memory(memory),
m_search_path(searchPath),
m_zone(zone)
namespace weapon
{
}
AssetCreationResult InfoStringLoaderWeapon::CreateAsset(const std::string& assetName, const InfoString& infoString, AssetCreationContext& context) const
{
auto* weaponFullDef = m_memory.Alloc<WeaponFullDef>();
InitWeaponFullDef(*weaponFullDef);
weaponFullDef->weapCompleteDef.szInternalName = m_memory.Dup(assetName.c_str());
AssetRegistration<AssetWeapon> registration(assetName, &weaponFullDef->weapCompleteDef);
InfoStringToWeaponConverter converter(
infoString, *weaponFullDef, m_zone.m_script_strings, m_memory, context, registration, weapon_fields, std::extent_v<decltype(weapon_fields)>);
if (!converter.Convert())
InfoStringLoaderIW5::InfoStringLoaderIW5(MemoryManager& memory, ISearchPath& searchPath, Zone& zone)
: m_memory(memory),
m_search_path(searchPath),
m_zone(zone)
{
std::cerr << std::format("Failed to parse weapon: \"{}\"\n", assetName);
return AssetCreationResult::Failure();
}
CalculateWeaponFields(*weaponFullDef, m_memory);
AssetCreationResult InfoStringLoaderIW5::CreateAsset(const std::string& assetName, const InfoString& infoString, AssetCreationContext& context) const
{
auto* weaponFullDef = m_memory.Alloc<WeaponFullDef>();
LoadAccuracyGraphs(*weaponFullDef, m_memory, m_search_path, context);
InitWeaponFullDef(*weaponFullDef);
weaponFullDef->weapCompleteDef.szInternalName = m_memory.Dup(assetName.c_str());
return AssetCreationResult::Success(context.AddAsset(std::move(registration)));
}
AssetRegistration<AssetWeapon> registration(assetName, &weaponFullDef->weapCompleteDef);
InfoStringToWeaponConverter converter(
infoString, *weaponFullDef, m_zone.m_script_strings, m_memory, context, registration, weapon_fields, std::extent_v<decltype(weapon_fields)>);
if (!converter.Convert())
{
con::error("Failed to parse weapon: \"{}\"", assetName);
return AssetCreationResult::Failure();
}
CalculateWeaponFields(*weaponFullDef, m_memory);
LoadAccuracyGraphs(*weaponFullDef, m_memory, m_search_path, context);
return AssetCreationResult::Success(context.AddAsset(std::move(registration)));
}
} // namespace weapon

View File

@@ -4,12 +4,12 @@
#include "Asset/AssetCreationResult.h"
#include "InfoString/InfoString.h"
namespace IW5
namespace weapon
{
class InfoStringLoaderWeapon
class InfoStringLoaderIW5
{
public:
InfoStringLoaderWeapon(MemoryManager& memory, ISearchPath& searchPath, Zone& zone);
InfoStringLoaderIW5(MemoryManager& memory, ISearchPath& searchPath, Zone& zone);
AssetCreationResult CreateAsset(const std::string& assetName, const InfoString& infoString, AssetCreationContext& context) const;
@@ -18,4 +18,4 @@ namespace IW5
ISearchPath& m_search_path;
Zone& m_zone;
};
} // namespace IW5
} // namespace weapon

View File

@@ -1,645 +0,0 @@
#include "JsonWeaponAttachmentLoader.h"
#include "Game/IW5/CommonIW5.h"
#include "Game/IW5/Weapon/JsonWeaponAttachment.h"
#include <format>
#include <iostream>
#include <nlohmann/json.hpp>
using namespace nlohmann;
using namespace IW5;
namespace
{
class JsonLoader
{
public:
JsonLoader(std::istream& stream, MemoryManager& memory, AssetCreationContext& context, AssetRegistration<AssetAttachment>& registration)
: m_stream(stream),
m_memory(memory),
m_context(context),
m_registration(registration)
{
}
bool Load(WeaponAttachment& attachment) const
{
const auto jRoot = json::parse(m_stream);
std::string type;
unsigned version;
jRoot.at("_type").get_to(type);
jRoot.at("_version").get_to(version);
if (type != "attachment" || version != 1u)
{
std::cerr << "Tried to load attachment \"" << attachment.szInternalName << "\" but did not find expected type attachment of version 1\n";
return false;
}
try
{
const auto jAttachment = jRoot.get<JsonWeaponAttachment>();
return CreateWeaponAttachmentFromJson(jAttachment, attachment);
}
catch (const json::exception& e)
{
std::cerr << std::format("Failed to parse json of attachment: {}\n", e.what());
}
return false;
}
private:
static void PrintError(const WeaponAttachment& attachment, const std::string& message)
{
std::cerr << "Cannot load attachment \"" << attachment.szInternalName << "\": " << message << "\n";
}
bool CreateWeaponAttachmentFromJson(const JsonWeaponAttachment& jAttachment, WeaponAttachment& attachment) const
{
#define CONVERT_XMODEL_ARRAY(propertyName, count) \
CreateXModelArrayFromJson(jAttachment.propertyName, attachment.propertyName, #propertyName, count, attachment);
#define CONVERT_ATTRIBUTE(attributeClass, attributeName) \
if (jAttachment.attributeName) \
{ \
using AttributeType = std::remove_pointer_t<decltype(attachment.attributeName)>; \
attachment.attributeName = m_memory.Alloc<AttributeType>(); \
if (!Create##attributeClass##FromJson(jAttachment.attributeName.value(), *attachment.attributeName, attachment)) \
return false; \
} \
else \
attachment.attributeName = nullptr;
attachment.szDisplayName = m_memory.Dup(jAttachment.displayName.c_str());
attachment.type = jAttachment.type;
attachment.weaponType = jAttachment.weaponType;
attachment.weapClass = jAttachment.weapClass;
CONVERT_XMODEL_ARRAY(worldModels, ATTACHMENT_WORLD_MODEL_COUNT)
CONVERT_XMODEL_ARRAY(viewModels, ATTACHMENT_VIEW_MODEL_COUNT)
CONVERT_XMODEL_ARRAY(reticleViewModels, ATTACHMENT_RETICLE_VIEW_MODEL_COUNT)
CONVERT_ATTRIBUTE(AttAmmoGeneral, ammoGeneral)
CONVERT_ATTRIBUTE(AttSight, sight)
CONVERT_ATTRIBUTE(AttReload, reload)
CONVERT_ATTRIBUTE(AttAddOns, addOns)
CONVERT_ATTRIBUTE(AttGeneral, general)
CONVERT_ATTRIBUTE(AttAimAssist, aimAssist)
CONVERT_ATTRIBUTE(AttAmmunition, ammunition)
CONVERT_ATTRIBUTE(AttDamage, damage)
CONVERT_ATTRIBUTE(AttLocationDamage, locationDamage)
CONVERT_ATTRIBUTE(AttIdleSettings, idleSettings)
CONVERT_ATTRIBUTE(AttADSSettings, adsSettings)
CONVERT_ATTRIBUTE(AttADSSettings, adsSettingsMain)
CONVERT_ATTRIBUTE(AttHipSpread, hipSpread)
CONVERT_ATTRIBUTE(AttGunKick, gunKick)
CONVERT_ATTRIBUTE(AttViewKick, viewKick)
CONVERT_ATTRIBUTE(AttADSOverlay, adsOverlay)
CONVERT_ATTRIBUTE(AttUI, ui)
CONVERT_ATTRIBUTE(AttRumbles, rumbles)
CONVERT_ATTRIBUTE(AttProjectile, projectile)
attachment.ammunitionScale = jAttachment.ammunitionScale;
attachment.damageScale = jAttachment.damageScale;
attachment.damageScaleMin = jAttachment.damageScaleMin;
attachment.stateTimersScale = jAttachment.stateTimersScale;
attachment.fireTimersScale = jAttachment.fireTimersScale;
attachment.idleSettingsScale = jAttachment.idleSettingsScale;
attachment.adsSettingsScale = jAttachment.adsSettingsScale;
attachment.adsSettingsScaleMain = jAttachment.adsSettingsScaleMain;
attachment.hipSpreadScale = jAttachment.hipSpreadScale;
attachment.gunKickScale = jAttachment.gunKickScale;
attachment.viewKickScale = jAttachment.viewKickScale;
attachment.viewCenterScale = jAttachment.viewCenterScale;
attachment.loadIndex = jAttachment.loadIndex;
attachment.hideIronSightsWithThisAttachment = jAttachment.hideIronSightsWithThisAttachment;
attachment.shareAmmoWithAlt = jAttachment.shareAmmoWithAlt;
return true;
}
bool CreateTracerFromJson(const std::string& assetName, TracerDef*& tracerPtr, const WeaponAttachment& attachment) const
{
auto* tracer = m_context.LoadDependency<AssetTracer>(assetName);
if (!tracer)
{
PrintError(attachment, std::format("Could not find tracer {}", assetName));
return false;
}
m_registration.AddDependency(tracer);
tracerPtr = tracer->Asset();
return true;
}
bool CreateMaterialFromJson(const std::string& assetName, Material*& materialPtr, const WeaponAttachment& attachment) const
{
auto* material = m_context.LoadDependency<AssetMaterial>(assetName);
if (!material)
{
PrintError(attachment, std::format("Could not find material {}", assetName));
return false;
}
m_registration.AddDependency(material);
materialPtr = material->Asset();
return true;
}
bool CreateFxFromJson(const std::string& assetName, FxEffectDef*& fxPtr, const WeaponAttachment& attachment) const
{
auto* fx = m_context.LoadDependency<AssetFx>(assetName);
if (!fx)
{
PrintError(attachment, std::format("Could not find fx {}", assetName));
return false;
}
m_registration.AddDependency(fx);
fxPtr = fx->Asset();
return true;
}
bool CreateSoundFromJson(const std::string& assetName, SndAliasCustom& sndAliasCustom, const WeaponAttachment& attachment) const
{
m_registration.AddIndirectAssetReference(m_context.LoadIndirectAssetReference<AssetSound>(assetName));
sndAliasCustom.name = m_memory.Alloc<snd_alias_list_name>();
sndAliasCustom.name->soundName = m_memory.Dup(assetName.c_str());
return true;
}
bool CreateXModelFromJson(const std::string& assetName, XModel*& xmodelPtr, const WeaponAttachment& attachment) const
{
auto* xmodel = m_context.LoadDependency<AssetXModel>(assetName);
if (!xmodel)
{
PrintError(attachment, std::format("Could not find xmodel {}", assetName));
return false;
}
m_registration.AddDependency(xmodel);
xmodelPtr = xmodel->Asset();
return true;
}
bool CreateXModelArrayFromJson(const std::vector<std::string>& jXmodelArray,
XModel**& xmodelArray,
const char* propertyName,
size_t propertyCount,
const WeaponAttachment& attachment) const
{
if (!jXmodelArray.empty())
{
const auto arraySize = jXmodelArray.size();
if (arraySize > propertyCount)
{
PrintError(attachment, std::format("{} size cannot exceed {}", propertyName, propertyCount));
return false;
}
xmodelArray = m_memory.Alloc<XModel*>(propertyCount);
memset(xmodelArray, 0, sizeof(void*) * propertyCount);
for (auto i = 0u; i < arraySize; i++)
{
if (!CreateXModelFromJson(jXmodelArray[i], xmodelArray[i], attachment))
return false;
}
}
else
{
xmodelArray = nullptr;
}
return true;
}
bool CreateAttAmmoGeneralFromJson(const JsonAttAmmoGeneral& jAmmoGeneral, AttAmmoGeneral& ammoGeneral, const WeaponAttachment& attachment) const
{
ammoGeneral.penetrateType = jAmmoGeneral.penetrateType;
ammoGeneral.penetrateMultiplier = jAmmoGeneral.penetrateMultiplier;
ammoGeneral.impactType = jAmmoGeneral.impactType;
ammoGeneral.fireType = jAmmoGeneral.fireType;
if (jAmmoGeneral.tracerType)
{
if (!CreateTracerFromJson(jAmmoGeneral.tracerType.value(), ammoGeneral.tracerType, attachment))
return false;
}
else
ammoGeneral.tracerType = nullptr;
ammoGeneral.rifleBullet = jAmmoGeneral.rifleBullet;
ammoGeneral.armorPiercing = jAmmoGeneral.armorPiercing;
return true;
}
static bool CreateAttSightFromJson(const JsonAttSight& jSight, AttSight& sight, const WeaponAttachment& attachment)
{
sight.aimDownSight = jSight.aimDownSight;
sight.adsFire = jSight.adsFire;
sight.rechamberWhileAds = jSight.rechamberWhileAds;
sight.noAdsWhenMagEmpty = jSight.noAdsWhenMagEmpty;
sight.canHoldBreath = jSight.canHoldBreath;
sight.canVariableZoom = jSight.canVariableZoom;
sight.hideRailWithThisScope = jSight.hideRailWithThisScope;
return true;
}
static bool CreateAttReloadFromJson(const JsonAttReload& jReload, AttReload& reload, const WeaponAttachment& attachment)
{
reload.noPartialReload = jReload.noPartialReload;
reload.segmentedReload = jReload.segmentedReload;
return true;
}
static bool CreateAttAddOnsFromJson(const JsonAttAddOns& jAddOns, AttAddOns& addOns, const WeaponAttachment& attachment)
{
addOns.motionTracker = jAddOns.motionTracker;
addOns.silenced = jAddOns.silenced;
return true;
}
bool CreateAttGeneralFromJson(const JsonAttGeneral& jGeneral, AttGeneral& general, const WeaponAttachment& attachment) const
{
general.boltAction = jGeneral.boltAction;
general.inheritsPerks = jGeneral.inheritsPerks;
general.enemyCrosshairRange = jGeneral.enemyCrosshairRange;
if (jGeneral.reticleCenter)
{
if (!CreateMaterialFromJson(jGeneral.reticleCenter.value(), general.reticleCenter, attachment))
return false;
}
else
general.reticleCenter = nullptr;
if (jGeneral.reticleSide)
{
if (!CreateMaterialFromJson(jGeneral.reticleSide.value(), general.reticleSide, attachment))
return false;
}
else
general.reticleSide = nullptr;
general.reticleCenterSize = jGeneral.reticleCenterSize;
general.reticleSideSize = jGeneral.reticleSideSize;
general.moveSpeedScale = jGeneral.moveSpeedScale;
general.adsMoveSpeedScale = jGeneral.adsMoveSpeedScale;
return true;
}
static bool CreateAttAimAssistFromJson(const JsonAttAimAssist& jAimAssist, AttAimAssist& aimAssist, const WeaponAttachment& attachment)
{
aimAssist.autoAimRange = jAimAssist.autoAimRange;
aimAssist.aimAssistRange = jAimAssist.aimAssistRange;
aimAssist.aimAssistRangeAds = jAimAssist.aimAssistRangeAds;
return true;
}
static bool CreateAttAmmunitionFromJson(const JsonAttAmmunition& jAmmunition, AttAmmunition& ammunition, const WeaponAttachment& attachment)
{
ammunition.maxAmmo = jAmmunition.maxAmmo;
ammunition.startAmmo = jAmmunition.startAmmo;
ammunition.clipSize = jAmmunition.clipSize;
ammunition.shotCount = jAmmunition.shotCount;
ammunition.reloadAmmoAdd = jAmmunition.reloadAmmoAdd;
ammunition.reloadStartAdd = jAmmunition.reloadStartAdd;
return true;
}
static bool CreateAttDamageFromJson(const JsonAttDamage& jDamage, AttDamage& damage, const WeaponAttachment& attachment)
{
damage.damage = jDamage.damage;
damage.minDamage = jDamage.minDamage;
damage.meleeDamage = jDamage.meleeDamage;
damage.maxDamageRange = jDamage.maxDamageRange;
damage.minDamageRange = jDamage.minDamageRange;
damage.playerDamage = jDamage.playerDamage;
damage.minPlayerDamage = jDamage.minPlayerDamage;
return true;
}
static bool
CreateAttLocationDamageFromJson(const JsonAttLocationDamage& jLocationDamage, AttLocationDamage& locationDamage, const WeaponAttachment& attachment)
{
locationDamage.locNone = jLocationDamage.locNone;
locationDamage.locHelmet = jLocationDamage.locHelmet;
locationDamage.locHead = jLocationDamage.locHead;
locationDamage.locNeck = jLocationDamage.locNeck;
locationDamage.locTorsoUpper = jLocationDamage.locTorsoUpper;
locationDamage.locTorsoLower = jLocationDamage.locTorsoLower;
locationDamage.locRightArmUpper = jLocationDamage.locRightArmUpper;
locationDamage.locRightArmLower = jLocationDamage.locRightArmLower;
locationDamage.locRightHand = jLocationDamage.locRightHand;
locationDamage.locLeftArmUpper = jLocationDamage.locLeftArmUpper;
locationDamage.locLeftArmLower = jLocationDamage.locLeftArmLower;
locationDamage.locLeftHand = jLocationDamage.locLeftHand;
locationDamage.locRightLegUpper = jLocationDamage.locRightLegUpper;
locationDamage.locRightLegLower = jLocationDamage.locRightLegLower;
locationDamage.locRightFoot = jLocationDamage.locRightFoot;
locationDamage.locLeftLegUpper = jLocationDamage.locLeftLegUpper;
locationDamage.locLeftLegLower = jLocationDamage.locLeftLegLower;
locationDamage.locLeftFoot = jLocationDamage.locLeftFoot;
locationDamage.locGun = jLocationDamage.locGun;
return true;
}
static bool CreateAttIdleSettingsFromJson(const JsonAttIdleSettings& jIdleSettings, AttIdleSettings& idleSettings, const WeaponAttachment& attachment)
{
idleSettings.hipIdleAmount = jIdleSettings.hipIdleAmount;
idleSettings.hipIdleSpeed = jIdleSettings.hipIdleSpeed;
idleSettings.idleCrouchFactor = jIdleSettings.idleCrouchFactor;
idleSettings.idleProneFactor = jIdleSettings.idleProneFactor;
idleSettings.adsIdleLerpStartTime = jIdleSettings.adsIdleLerpStartTime;
idleSettings.adsIdleLerpTime = jIdleSettings.adsIdleLerpTime;
return true;
}
static bool CreateAttADSSettingsFromJson(const JsonAttADSSettings& jAdsSettings, AttADSSettings& adsSettings, const WeaponAttachment& attachment)
{
adsSettings.adsSpread = jAdsSettings.adsSpread;
adsSettings.adsAimPitch = jAdsSettings.adsAimPitch;
adsSettings.adsTransInTime = jAdsSettings.adsTransInTime;
adsSettings.adsTransOutTime = jAdsSettings.adsTransOutTime;
adsSettings.adsReloadTransTime = jAdsSettings.adsReloadTransTime;
adsSettings.adsCrosshairInFrac = jAdsSettings.adsCrosshairInFrac;
adsSettings.adsCrosshairOutFrac = jAdsSettings.adsCrosshairOutFrac;
adsSettings.adsZoomFov = jAdsSettings.adsZoomFov;
adsSettings.adsZoomInFrac = jAdsSettings.adsZoomInFrac;
adsSettings.adsZoomOutFrac = jAdsSettings.adsZoomOutFrac;
adsSettings.adsBobFactor = jAdsSettings.adsBobFactor;
adsSettings.adsViewBobMult = jAdsSettings.adsViewBobMult;
adsSettings.adsViewErrorMin = jAdsSettings.adsViewErrorMin;
adsSettings.adsViewErrorMax = jAdsSettings.adsViewErrorMax;
return true;
}
static bool CreateAttHipSpreadFromJson(const JsonAttHipSpread& jHipSpread, AttHipSpread& hipSpread, const WeaponAttachment& attachment)
{
hipSpread.hipSpreadStandMin = jHipSpread.hipSpreadStandMin;
hipSpread.hipSpreadDuckedMin = jHipSpread.hipSpreadDuckedMin;
hipSpread.hipSpreadProneMin = jHipSpread.hipSpreadProneMin;
hipSpread.hipSpreadMax = jHipSpread.hipSpreadMax;
hipSpread.hipSpreadDuckedMax = jHipSpread.hipSpreadDuckedMax;
hipSpread.hipSpreadProneMax = jHipSpread.hipSpreadProneMax;
hipSpread.hipSpreadFireAdd = jHipSpread.hipSpreadFireAdd;
hipSpread.hipSpreadTurnAdd = jHipSpread.hipSpreadTurnAdd;
hipSpread.hipSpreadMoveAdd = jHipSpread.hipSpreadMoveAdd;
hipSpread.hipSpreadDecayRate = jHipSpread.hipSpreadDecayRate;
hipSpread.hipSpreadDuckedDecay = jHipSpread.hipSpreadDuckedDecay;
hipSpread.hipSpreadProneDecay = jHipSpread.hipSpreadProneDecay;
return true;
}
static bool CreateAttGunKickFromJson(const JsonAttGunKick& jGunKick, AttGunKick& gunKick, const WeaponAttachment& attachment)
{
gunKick.hipGunKickReducedKickBullets = jGunKick.hipGunKickReducedKickBullets;
gunKick.hipGunKickReducedKickPercent = jGunKick.hipGunKickReducedKickPercent;
gunKick.hipGunKickPitchMin = jGunKick.hipGunKickPitchMin;
gunKick.hipGunKickPitchMax = jGunKick.hipGunKickPitchMax;
gunKick.hipGunKickYawMin = jGunKick.hipGunKickYawMin;
gunKick.hipGunKickYawMax = jGunKick.hipGunKickYawMax;
gunKick.hipGunKickAccel = jGunKick.hipGunKickAccel;
gunKick.hipGunKickSpeedMax = jGunKick.hipGunKickSpeedMax;
gunKick.hipGunKickSpeedDecay = jGunKick.hipGunKickSpeedDecay;
gunKick.hipGunKickStaticDecay = jGunKick.hipGunKickStaticDecay;
gunKick.adsGunKickReducedKickBullets = jGunKick.adsGunKickReducedKickBullets;
gunKick.adsGunKickReducedKickPercent = jGunKick.adsGunKickReducedKickPercent;
gunKick.adsGunKickPitchMin = jGunKick.adsGunKickPitchMin;
gunKick.adsGunKickPitchMax = jGunKick.adsGunKickPitchMax;
gunKick.adsGunKickYawMin = jGunKick.adsGunKickYawMin;
gunKick.adsGunKickYawMax = jGunKick.adsGunKickYawMax;
gunKick.adsGunKickAccel = jGunKick.adsGunKickAccel;
gunKick.adsGunKickSpeedMax = jGunKick.adsGunKickSpeedMax;
gunKick.adsGunKickSpeedDecay = jGunKick.adsGunKickSpeedDecay;
gunKick.adsGunKickStaticDecay = jGunKick.adsGunKickStaticDecay;
return true;
}
static bool CreateAttViewKickFromJson(const JsonAttViewKick& jViewKick, AttViewKick& viewKick, const WeaponAttachment& attachment)
{
viewKick.hipViewKickPitchMin = jViewKick.hipViewKickPitchMin;
viewKick.hipViewKickPitchMax = jViewKick.hipViewKickPitchMax;
viewKick.hipViewKickYawMin = jViewKick.hipViewKickYawMin;
viewKick.hipViewKickYawMax = jViewKick.hipViewKickYawMax;
viewKick.hipViewKickCenterSpeed = jViewKick.hipViewKickCenterSpeed;
viewKick.adsViewKickPitchMin = jViewKick.adsViewKickPitchMin;
viewKick.adsViewKickPitchMax = jViewKick.adsViewKickPitchMax;
viewKick.adsViewKickYawMin = jViewKick.adsViewKickYawMin;
viewKick.adsViewKickYawMax = jViewKick.adsViewKickYawMax;
viewKick.adsViewKickCenterSpeed = jViewKick.adsViewKickCenterSpeed;
return true;
}
bool CreateAttADSOverlayFromJson(const JsonAttADSOverlay& jAdsOverlay, AttADSOverlay& adsOverlay, const WeaponAttachment& attachment) const
{
if (jAdsOverlay.shader)
{
if (!CreateMaterialFromJson(jAdsOverlay.shader.value(), adsOverlay.overlay.shader, attachment))
return false;
}
else
adsOverlay.overlay.shader = nullptr;
if (jAdsOverlay.shaderLowRes)
{
if (!CreateMaterialFromJson(jAdsOverlay.shaderLowRes.value(), adsOverlay.overlay.shaderLowRes, attachment))
return false;
}
else
adsOverlay.overlay.shaderLowRes = nullptr;
if (jAdsOverlay.shaderEMP)
{
if (!CreateMaterialFromJson(jAdsOverlay.shaderEMP.value(), adsOverlay.overlay.shaderEMP, attachment))
return false;
}
else
adsOverlay.overlay.shaderEMP = nullptr;
if (jAdsOverlay.shaderEMPLowRes)
{
if (!CreateMaterialFromJson(jAdsOverlay.shaderEMPLowRes.value(), adsOverlay.overlay.shaderEMPLowRes, attachment))
return false;
}
else
adsOverlay.overlay.shaderEMPLowRes = nullptr;
adsOverlay.overlay.reticle = jAdsOverlay.reticle;
adsOverlay.overlay.width = jAdsOverlay.width;
adsOverlay.overlay.height = jAdsOverlay.height;
adsOverlay.overlay.widthSplitscreen = jAdsOverlay.widthSplitscreen;
adsOverlay.overlay.heightSplitscreen = jAdsOverlay.heightSplitscreen;
adsOverlay.thermalScope = jAdsOverlay.thermalScope;
return true;
}
bool CreateAttUIFromJson(const JsonAttUI& jUi, AttUI& ui, const WeaponAttachment& attachment) const
{
if (jUi.dpadIcon)
{
if (!CreateMaterialFromJson(jUi.dpadIcon.value(), ui.dpadIcon, attachment))
return false;
}
else
ui.dpadIcon = nullptr;
if (jUi.ammoCounterIcon)
{
if (!CreateMaterialFromJson(jUi.ammoCounterIcon.value(), ui.ammoCounterIcon, attachment))
return false;
}
else
ui.ammoCounterIcon = nullptr;
ui.dpadIconRatio = jUi.dpadIconRatio;
ui.ammoCounterIconRatio = jUi.ammoCounterIconRatio;
ui.ammoCounterClip = jUi.ammoCounterClip;
return true;
}
bool CreateAttRumblesFromJson(const JsonAttRumbles& jRumbles, AttRumbles& rumbles, const WeaponAttachment& attachment) const
{
if (jRumbles.fireRumble)
rumbles.fireRumble = m_memory.Dup(jRumbles.fireRumble.value().c_str());
else
rumbles.fireRumble = nullptr;
if (jRumbles.meleeImpactRumble)
rumbles.meleeImpactRumble = m_memory.Dup(jRumbles.meleeImpactRumble.value().c_str());
else
rumbles.meleeImpactRumble = nullptr;
return true;
}
bool CreateAttProjectileFromJson(const JsonAttProjectile& jProjectile, AttProjectile& projectile, const WeaponAttachment& attachment) const
{
projectile.explosionRadius = jProjectile.explosionRadius;
projectile.explosionInnerDamage = jProjectile.explosionInnerDamage;
projectile.explosionOuterDamage = jProjectile.explosionOuterDamage;
projectile.damageConeAngle = jProjectile.damageConeAngle;
projectile.projectileSpeed = jProjectile.projectileSpeed;
projectile.projectileSpeedUp = jProjectile.projectileSpeedUp;
projectile.projectileActivateDist = jProjectile.projectileActivateDist;
projectile.projectileLifetime = jProjectile.projectileLifetime;
if (jProjectile.projectileModel)
{
if (!CreateXModelFromJson(jProjectile.projectileModel.value(), projectile.projectileModel, attachment))
return false;
}
else
projectile.projectileModel = nullptr;
projectile.projExplosionType = jProjectile.projExplosionType;
if (jProjectile.projExplosionEffect)
{
if (!CreateFxFromJson(jProjectile.projExplosionEffect.value(), projectile.projExplosionEffect, attachment))
return false;
}
else
projectile.projExplosionEffect = nullptr;
projectile.projExplosionEffectForceNormalUp = jProjectile.projExplosionEffectForceNormalUp;
if (jProjectile.projExplosionSound)
{
if (!CreateSoundFromJson(jProjectile.projExplosionSound.value(), projectile.projExplosionSound, attachment))
return false;
}
else
projectile.projExplosionSound.name = nullptr;
if (jProjectile.projDudEffect)
{
if (!CreateFxFromJson(jProjectile.projDudEffect.value(), projectile.projDudEffect, attachment))
return false;
}
else
projectile.projDudEffect = nullptr;
if (jProjectile.projDudSound)
{
if (!CreateSoundFromJson(jProjectile.projDudSound.value(), projectile.projDudSound, attachment))
return false;
}
else
projectile.projDudSound.name = nullptr;
projectile.projImpactExplode = jProjectile.projImpactExplode;
projectile.destabilizationRateTime = jProjectile.destabilizationRateTime;
projectile.destabilizationCurvatureMax = jProjectile.destabilizationCurvatureMax;
projectile.destabilizeDistance = jProjectile.destabilizeDistance;
if (jProjectile.projTrailEffect)
{
if (!CreateFxFromJson(jProjectile.projTrailEffect.value(), projectile.projTrailEffect, attachment))
return false;
}
else
projectile.projTrailEffect = nullptr;
projectile.projIgnitionDelay = jProjectile.projIgnitionDelay;
if (jProjectile.projIgnitionEffect)
{
if (!CreateFxFromJson(jProjectile.projIgnitionEffect.value(), projectile.projIgnitionEffect, attachment))
return false;
}
else
projectile.projIgnitionEffect = nullptr;
if (jProjectile.projIgnitionSound)
{
if (!CreateSoundFromJson(jProjectile.projIgnitionSound.value(), projectile.projIgnitionSound, attachment))
return false;
}
else
projectile.projIgnitionSound.name = nullptr;
return true;
}
std::istream& m_stream;
MemoryManager& m_memory;
AssetCreationContext& m_context;
AssetRegistration<AssetAttachment>& m_registration;
};
} // namespace
namespace IW5
{
bool LoadWeaponAttachmentAsJson(std::istream& stream,
WeaponAttachment& attachment,
MemoryManager& memory,
AssetCreationContext& context,
AssetRegistration<AssetAttachment>& registration)
{
const JsonLoader loader(stream, memory, context, registration);
return loader.Load(attachment);
}
} // namespace IW5

View File

@@ -1,17 +0,0 @@
#pragma once
#include "Asset/AssetCreationContext.h"
#include "Asset/AssetRegistration.h"
#include "Game/IW5/IW5.h"
#include "Utils/MemoryManager.h"
#include <istream>
namespace IW5
{
bool LoadWeaponAttachmentAsJson(std::istream& stream,
WeaponAttachment& attachment,
MemoryManager& memory,
AssetCreationContext& context,
AssetRegistration<AssetAttachment>& registration);
} // namespace IW5

View File

@@ -1,16 +1,637 @@
#include "LoaderAttachmentIW5.h"
#include "Game/IW5/IW5.h"
#include "JsonWeaponAttachmentLoader.h"
#include "Game/IW5/Weapon/JsonWeaponAttachment.h"
#include "Utils/Logging/Log.h"
#include "Weapon/AttachmentCommon.h"
#include <cstring>
#include <format>
#include <iostream>
#include <nlohmann/json.hpp>
using namespace nlohmann;
using namespace IW5;
namespace
{
class JsonLoader
{
public:
JsonLoader(std::istream& stream, MemoryManager& memory, AssetCreationContext& context, AssetRegistration<AssetAttachment>& registration)
: m_stream(stream),
m_memory(memory),
m_context(context),
m_registration(registration)
{
}
bool Load(WeaponAttachment& attachment) const
{
try
{
const auto jRoot = json::parse(m_stream);
std::string type;
unsigned version;
jRoot.at("_type").get_to(type);
jRoot.at("_version").get_to(version);
if (type != "attachment" || version != 1u)
{
con::error("Tried to load attachment \"{}\" but did not find expected type attachment of version 1", attachment.szInternalName);
return false;
}
const auto jAttachment = jRoot.get<JsonWeaponAttachment>();
return CreateWeaponAttachmentFromJson(jAttachment, attachment);
}
catch (const json::exception& e)
{
con::error("Failed to parse json of attachment: {}", e.what());
}
return false;
}
private:
static void PrintError(const WeaponAttachment& attachment, const std::string& message)
{
con::error("Cannot load attachment \"{}\": {}", attachment.szInternalName, message);
}
bool CreateWeaponAttachmentFromJson(const JsonWeaponAttachment& jAttachment, WeaponAttachment& attachment) const
{
#define CONVERT_XMODEL_ARRAY(propertyName, count) \
CreateXModelArrayFromJson(jAttachment.propertyName, attachment.propertyName, #propertyName, count, attachment);
#define CONVERT_ATTRIBUTE(attributeClass, attributeName) \
if (jAttachment.attributeName) \
{ \
using AttributeType = std::remove_pointer_t<decltype(attachment.attributeName)>; \
attachment.attributeName = m_memory.Alloc<AttributeType>(); \
if (!Create##attributeClass##FromJson(jAttachment.attributeName.value(), *attachment.attributeName, attachment)) \
return false; \
} \
else \
attachment.attributeName = nullptr;
attachment.szDisplayName = m_memory.Dup(jAttachment.displayName.c_str());
attachment.type = jAttachment.type;
attachment.weaponType = jAttachment.weaponType;
attachment.weapClass = jAttachment.weapClass;
CONVERT_XMODEL_ARRAY(worldModels, ATTACHMENT_WORLD_MODEL_COUNT)
CONVERT_XMODEL_ARRAY(viewModels, ATTACHMENT_VIEW_MODEL_COUNT)
CONVERT_XMODEL_ARRAY(reticleViewModels, ATTACHMENT_RETICLE_VIEW_MODEL_COUNT)
CONVERT_ATTRIBUTE(AttAmmoGeneral, ammoGeneral)
CONVERT_ATTRIBUTE(AttSight, sight)
CONVERT_ATTRIBUTE(AttReload, reload)
CONVERT_ATTRIBUTE(AttAddOns, addOns)
CONVERT_ATTRIBUTE(AttGeneral, general)
CONVERT_ATTRIBUTE(AttAimAssist, aimAssist)
CONVERT_ATTRIBUTE(AttAmmunition, ammunition)
CONVERT_ATTRIBUTE(AttDamage, damage)
CONVERT_ATTRIBUTE(AttLocationDamage, locationDamage)
CONVERT_ATTRIBUTE(AttIdleSettings, idleSettings)
CONVERT_ATTRIBUTE(AttADSSettings, adsSettings)
CONVERT_ATTRIBUTE(AttADSSettings, adsSettingsMain)
CONVERT_ATTRIBUTE(AttHipSpread, hipSpread)
CONVERT_ATTRIBUTE(AttGunKick, gunKick)
CONVERT_ATTRIBUTE(AttViewKick, viewKick)
CONVERT_ATTRIBUTE(AttADSOverlay, adsOverlay)
CONVERT_ATTRIBUTE(AttUI, ui)
CONVERT_ATTRIBUTE(AttRumbles, rumbles)
CONVERT_ATTRIBUTE(AttProjectile, projectile)
attachment.ammunitionScale = jAttachment.ammunitionScale;
attachment.damageScale = jAttachment.damageScale;
attachment.damageScaleMin = jAttachment.damageScaleMin;
attachment.stateTimersScale = jAttachment.stateTimersScale;
attachment.fireTimersScale = jAttachment.fireTimersScale;
attachment.idleSettingsScale = jAttachment.idleSettingsScale;
attachment.adsSettingsScale = jAttachment.adsSettingsScale;
attachment.adsSettingsScaleMain = jAttachment.adsSettingsScaleMain;
attachment.hipSpreadScale = jAttachment.hipSpreadScale;
attachment.gunKickScale = jAttachment.gunKickScale;
attachment.viewKickScale = jAttachment.viewKickScale;
attachment.viewCenterScale = jAttachment.viewCenterScale;
attachment.loadIndex = jAttachment.loadIndex;
attachment.hideIronSightsWithThisAttachment = jAttachment.hideIronSightsWithThisAttachment;
attachment.shareAmmoWithAlt = jAttachment.shareAmmoWithAlt;
return true;
}
bool CreateTracerFromJson(const std::string& assetName, TracerDef*& tracerPtr, const WeaponAttachment& attachment) const
{
auto* tracer = m_context.LoadDependency<AssetTracer>(assetName);
if (!tracer)
{
PrintError(attachment, std::format("Could not find tracer {}", assetName));
return false;
}
m_registration.AddDependency(tracer);
tracerPtr = tracer->Asset();
return true;
}
bool CreateMaterialFromJson(const std::string& assetName, Material*& materialPtr, const WeaponAttachment& attachment) const
{
auto* material = m_context.LoadDependency<AssetMaterial>(assetName);
if (!material)
{
PrintError(attachment, std::format("Could not find material {}", assetName));
return false;
}
m_registration.AddDependency(material);
materialPtr = material->Asset();
return true;
}
bool CreateFxFromJson(const std::string& assetName, FxEffectDef*& fxPtr, const WeaponAttachment& attachment) const
{
auto* fx = m_context.LoadDependency<AssetFx>(assetName);
if (!fx)
{
PrintError(attachment, std::format("Could not find fx {}", assetName));
return false;
}
m_registration.AddDependency(fx);
fxPtr = fx->Asset();
return true;
}
bool CreateSoundFromJson(const std::string& assetName, SndAliasCustom& sndAliasCustom, const WeaponAttachment& attachment) const
{
m_registration.AddIndirectAssetReference(m_context.LoadIndirectAssetReference<AssetSound>(assetName));
sndAliasCustom.name = m_memory.Alloc<snd_alias_list_name>();
sndAliasCustom.name->soundName = m_memory.Dup(assetName.c_str());
return true;
}
bool CreateXModelFromJson(const std::string& assetName, XModel*& xmodelPtr, const WeaponAttachment& attachment) const
{
auto* xmodel = m_context.LoadDependency<AssetXModel>(assetName);
if (!xmodel)
{
PrintError(attachment, std::format("Could not find xmodel {}", assetName));
return false;
}
m_registration.AddDependency(xmodel);
xmodelPtr = xmodel->Asset();
return true;
}
bool CreateXModelArrayFromJson(const std::vector<std::string>& jXmodelArray,
XModel**& xmodelArray,
const char* propertyName,
size_t propertyCount,
const WeaponAttachment& attachment) const
{
if (!jXmodelArray.empty())
{
const auto arraySize = jXmodelArray.size();
if (arraySize > propertyCount)
{
PrintError(attachment, std::format("{} size cannot exceed {}", propertyName, propertyCount));
return false;
}
xmodelArray = m_memory.Alloc<XModel*>(propertyCount);
memset(xmodelArray, 0, sizeof(void*) * propertyCount);
for (auto i = 0u; i < arraySize; i++)
{
if (!CreateXModelFromJson(jXmodelArray[i], xmodelArray[i], attachment))
return false;
}
}
else
{
xmodelArray = nullptr;
}
return true;
}
bool CreateAttAmmoGeneralFromJson(const JsonAttAmmoGeneral& jAmmoGeneral, AttAmmoGeneral& ammoGeneral, const WeaponAttachment& attachment) const
{
ammoGeneral.penetrateType = jAmmoGeneral.penetrateType;
ammoGeneral.penetrateMultiplier = jAmmoGeneral.penetrateMultiplier;
ammoGeneral.impactType = jAmmoGeneral.impactType;
ammoGeneral.fireType = jAmmoGeneral.fireType;
if (jAmmoGeneral.tracerType)
{
if (!CreateTracerFromJson(jAmmoGeneral.tracerType.value(), ammoGeneral.tracerType, attachment))
return false;
}
else
ammoGeneral.tracerType = nullptr;
ammoGeneral.rifleBullet = jAmmoGeneral.rifleBullet;
ammoGeneral.armorPiercing = jAmmoGeneral.armorPiercing;
return true;
}
static bool CreateAttSightFromJson(const JsonAttSight& jSight, AttSight& sight, const WeaponAttachment& attachment)
{
sight.aimDownSight = jSight.aimDownSight;
sight.adsFire = jSight.adsFire;
sight.rechamberWhileAds = jSight.rechamberWhileAds;
sight.noAdsWhenMagEmpty = jSight.noAdsWhenMagEmpty;
sight.canHoldBreath = jSight.canHoldBreath;
sight.canVariableZoom = jSight.canVariableZoom;
sight.hideRailWithThisScope = jSight.hideRailWithThisScope;
return true;
}
static bool CreateAttReloadFromJson(const JsonAttReload& jReload, AttReload& reload, const WeaponAttachment& attachment)
{
reload.noPartialReload = jReload.noPartialReload;
reload.segmentedReload = jReload.segmentedReload;
return true;
}
static bool CreateAttAddOnsFromJson(const JsonAttAddOns& jAddOns, AttAddOns& addOns, const WeaponAttachment& attachment)
{
addOns.motionTracker = jAddOns.motionTracker;
addOns.silenced = jAddOns.silenced;
return true;
}
bool CreateAttGeneralFromJson(const JsonAttGeneral& jGeneral, AttGeneral& general, const WeaponAttachment& attachment) const
{
general.boltAction = jGeneral.boltAction;
general.inheritsPerks = jGeneral.inheritsPerks;
general.enemyCrosshairRange = jGeneral.enemyCrosshairRange;
if (jGeneral.reticleCenter)
{
if (!CreateMaterialFromJson(jGeneral.reticleCenter.value(), general.reticleCenter, attachment))
return false;
}
else
general.reticleCenter = nullptr;
if (jGeneral.reticleSide)
{
if (!CreateMaterialFromJson(jGeneral.reticleSide.value(), general.reticleSide, attachment))
return false;
}
else
general.reticleSide = nullptr;
general.reticleCenterSize = jGeneral.reticleCenterSize;
general.reticleSideSize = jGeneral.reticleSideSize;
general.moveSpeedScale = jGeneral.moveSpeedScale;
general.adsMoveSpeedScale = jGeneral.adsMoveSpeedScale;
return true;
}
static bool CreateAttAimAssistFromJson(const JsonAttAimAssist& jAimAssist, AttAimAssist& aimAssist, const WeaponAttachment& attachment)
{
aimAssist.autoAimRange = jAimAssist.autoAimRange;
aimAssist.aimAssistRange = jAimAssist.aimAssistRange;
aimAssist.aimAssistRangeAds = jAimAssist.aimAssistRangeAds;
return true;
}
static bool CreateAttAmmunitionFromJson(const JsonAttAmmunition& jAmmunition, AttAmmunition& ammunition, const WeaponAttachment& attachment)
{
ammunition.maxAmmo = jAmmunition.maxAmmo;
ammunition.startAmmo = jAmmunition.startAmmo;
ammunition.clipSize = jAmmunition.clipSize;
ammunition.shotCount = jAmmunition.shotCount;
ammunition.reloadAmmoAdd = jAmmunition.reloadAmmoAdd;
ammunition.reloadStartAdd = jAmmunition.reloadStartAdd;
return true;
}
static bool CreateAttDamageFromJson(const JsonAttDamage& jDamage, AttDamage& damage, const WeaponAttachment& attachment)
{
damage.damage = jDamage.damage;
damage.minDamage = jDamage.minDamage;
damage.meleeDamage = jDamage.meleeDamage;
damage.maxDamageRange = jDamage.maxDamageRange;
damage.minDamageRange = jDamage.minDamageRange;
damage.playerDamage = jDamage.playerDamage;
damage.minPlayerDamage = jDamage.minPlayerDamage;
return true;
}
static bool
CreateAttLocationDamageFromJson(const JsonAttLocationDamage& jLocationDamage, AttLocationDamage& locationDamage, const WeaponAttachment& attachment)
{
locationDamage.locNone = jLocationDamage.locNone;
locationDamage.locHelmet = jLocationDamage.locHelmet;
locationDamage.locHead = jLocationDamage.locHead;
locationDamage.locNeck = jLocationDamage.locNeck;
locationDamage.locTorsoUpper = jLocationDamage.locTorsoUpper;
locationDamage.locTorsoLower = jLocationDamage.locTorsoLower;
locationDamage.locRightArmUpper = jLocationDamage.locRightArmUpper;
locationDamage.locRightArmLower = jLocationDamage.locRightArmLower;
locationDamage.locRightHand = jLocationDamage.locRightHand;
locationDamage.locLeftArmUpper = jLocationDamage.locLeftArmUpper;
locationDamage.locLeftArmLower = jLocationDamage.locLeftArmLower;
locationDamage.locLeftHand = jLocationDamage.locLeftHand;
locationDamage.locRightLegUpper = jLocationDamage.locRightLegUpper;
locationDamage.locRightLegLower = jLocationDamage.locRightLegLower;
locationDamage.locRightFoot = jLocationDamage.locRightFoot;
locationDamage.locLeftLegUpper = jLocationDamage.locLeftLegUpper;
locationDamage.locLeftLegLower = jLocationDamage.locLeftLegLower;
locationDamage.locLeftFoot = jLocationDamage.locLeftFoot;
locationDamage.locGun = jLocationDamage.locGun;
return true;
}
static bool CreateAttIdleSettingsFromJson(const JsonAttIdleSettings& jIdleSettings, AttIdleSettings& idleSettings, const WeaponAttachment& attachment)
{
idleSettings.hipIdleAmount = jIdleSettings.hipIdleAmount;
idleSettings.hipIdleSpeed = jIdleSettings.hipIdleSpeed;
idleSettings.idleCrouchFactor = jIdleSettings.idleCrouchFactor;
idleSettings.idleProneFactor = jIdleSettings.idleProneFactor;
idleSettings.adsIdleLerpStartTime = jIdleSettings.adsIdleLerpStartTime;
idleSettings.adsIdleLerpTime = jIdleSettings.adsIdleLerpTime;
return true;
}
static bool CreateAttADSSettingsFromJson(const JsonAttADSSettings& jAdsSettings, AttADSSettings& adsSettings, const WeaponAttachment& attachment)
{
adsSettings.adsSpread = jAdsSettings.adsSpread;
adsSettings.adsAimPitch = jAdsSettings.adsAimPitch;
adsSettings.adsTransInTime = jAdsSettings.adsTransInTime;
adsSettings.adsTransOutTime = jAdsSettings.adsTransOutTime;
adsSettings.adsReloadTransTime = jAdsSettings.adsReloadTransTime;
adsSettings.adsCrosshairInFrac = jAdsSettings.adsCrosshairInFrac;
adsSettings.adsCrosshairOutFrac = jAdsSettings.adsCrosshairOutFrac;
adsSettings.adsZoomFov = jAdsSettings.adsZoomFov;
adsSettings.adsZoomInFrac = jAdsSettings.adsZoomInFrac;
adsSettings.adsZoomOutFrac = jAdsSettings.adsZoomOutFrac;
adsSettings.adsBobFactor = jAdsSettings.adsBobFactor;
adsSettings.adsViewBobMult = jAdsSettings.adsViewBobMult;
adsSettings.adsViewErrorMin = jAdsSettings.adsViewErrorMin;
adsSettings.adsViewErrorMax = jAdsSettings.adsViewErrorMax;
return true;
}
static bool CreateAttHipSpreadFromJson(const JsonAttHipSpread& jHipSpread, AttHipSpread& hipSpread, const WeaponAttachment& attachment)
{
hipSpread.hipSpreadStandMin = jHipSpread.hipSpreadStandMin;
hipSpread.hipSpreadDuckedMin = jHipSpread.hipSpreadDuckedMin;
hipSpread.hipSpreadProneMin = jHipSpread.hipSpreadProneMin;
hipSpread.hipSpreadMax = jHipSpread.hipSpreadMax;
hipSpread.hipSpreadDuckedMax = jHipSpread.hipSpreadDuckedMax;
hipSpread.hipSpreadProneMax = jHipSpread.hipSpreadProneMax;
hipSpread.hipSpreadFireAdd = jHipSpread.hipSpreadFireAdd;
hipSpread.hipSpreadTurnAdd = jHipSpread.hipSpreadTurnAdd;
hipSpread.hipSpreadMoveAdd = jHipSpread.hipSpreadMoveAdd;
hipSpread.hipSpreadDecayRate = jHipSpread.hipSpreadDecayRate;
hipSpread.hipSpreadDuckedDecay = jHipSpread.hipSpreadDuckedDecay;
hipSpread.hipSpreadProneDecay = jHipSpread.hipSpreadProneDecay;
return true;
}
static bool CreateAttGunKickFromJson(const JsonAttGunKick& jGunKick, AttGunKick& gunKick, const WeaponAttachment& attachment)
{
gunKick.hipGunKickReducedKickBullets = jGunKick.hipGunKickReducedKickBullets;
gunKick.hipGunKickReducedKickPercent = jGunKick.hipGunKickReducedKickPercent;
gunKick.hipGunKickPitchMin = jGunKick.hipGunKickPitchMin;
gunKick.hipGunKickPitchMax = jGunKick.hipGunKickPitchMax;
gunKick.hipGunKickYawMin = jGunKick.hipGunKickYawMin;
gunKick.hipGunKickYawMax = jGunKick.hipGunKickYawMax;
gunKick.hipGunKickAccel = jGunKick.hipGunKickAccel;
gunKick.hipGunKickSpeedMax = jGunKick.hipGunKickSpeedMax;
gunKick.hipGunKickSpeedDecay = jGunKick.hipGunKickSpeedDecay;
gunKick.hipGunKickStaticDecay = jGunKick.hipGunKickStaticDecay;
gunKick.adsGunKickReducedKickBullets = jGunKick.adsGunKickReducedKickBullets;
gunKick.adsGunKickReducedKickPercent = jGunKick.adsGunKickReducedKickPercent;
gunKick.adsGunKickPitchMin = jGunKick.adsGunKickPitchMin;
gunKick.adsGunKickPitchMax = jGunKick.adsGunKickPitchMax;
gunKick.adsGunKickYawMin = jGunKick.adsGunKickYawMin;
gunKick.adsGunKickYawMax = jGunKick.adsGunKickYawMax;
gunKick.adsGunKickAccel = jGunKick.adsGunKickAccel;
gunKick.adsGunKickSpeedMax = jGunKick.adsGunKickSpeedMax;
gunKick.adsGunKickSpeedDecay = jGunKick.adsGunKickSpeedDecay;
gunKick.adsGunKickStaticDecay = jGunKick.adsGunKickStaticDecay;
return true;
}
static bool CreateAttViewKickFromJson(const JsonAttViewKick& jViewKick, AttViewKick& viewKick, const WeaponAttachment& attachment)
{
viewKick.hipViewKickPitchMin = jViewKick.hipViewKickPitchMin;
viewKick.hipViewKickPitchMax = jViewKick.hipViewKickPitchMax;
viewKick.hipViewKickYawMin = jViewKick.hipViewKickYawMin;
viewKick.hipViewKickYawMax = jViewKick.hipViewKickYawMax;
viewKick.hipViewKickCenterSpeed = jViewKick.hipViewKickCenterSpeed;
viewKick.adsViewKickPitchMin = jViewKick.adsViewKickPitchMin;
viewKick.adsViewKickPitchMax = jViewKick.adsViewKickPitchMax;
viewKick.adsViewKickYawMin = jViewKick.adsViewKickYawMin;
viewKick.adsViewKickYawMax = jViewKick.adsViewKickYawMax;
viewKick.adsViewKickCenterSpeed = jViewKick.adsViewKickCenterSpeed;
return true;
}
bool CreateAttADSOverlayFromJson(const JsonAttADSOverlay& jAdsOverlay, AttADSOverlay& adsOverlay, const WeaponAttachment& attachment) const
{
if (jAdsOverlay.shader)
{
if (!CreateMaterialFromJson(jAdsOverlay.shader.value(), adsOverlay.overlay.shader, attachment))
return false;
}
else
adsOverlay.overlay.shader = nullptr;
if (jAdsOverlay.shaderLowRes)
{
if (!CreateMaterialFromJson(jAdsOverlay.shaderLowRes.value(), adsOverlay.overlay.shaderLowRes, attachment))
return false;
}
else
adsOverlay.overlay.shaderLowRes = nullptr;
if (jAdsOverlay.shaderEMP)
{
if (!CreateMaterialFromJson(jAdsOverlay.shaderEMP.value(), adsOverlay.overlay.shaderEMP, attachment))
return false;
}
else
adsOverlay.overlay.shaderEMP = nullptr;
if (jAdsOverlay.shaderEMPLowRes)
{
if (!CreateMaterialFromJson(jAdsOverlay.shaderEMPLowRes.value(), adsOverlay.overlay.shaderEMPLowRes, attachment))
return false;
}
else
adsOverlay.overlay.shaderEMPLowRes = nullptr;
adsOverlay.overlay.reticle = jAdsOverlay.reticle;
adsOverlay.overlay.width = jAdsOverlay.width;
adsOverlay.overlay.height = jAdsOverlay.height;
adsOverlay.overlay.widthSplitscreen = jAdsOverlay.widthSplitscreen;
adsOverlay.overlay.heightSplitscreen = jAdsOverlay.heightSplitscreen;
adsOverlay.thermalScope = jAdsOverlay.thermalScope;
return true;
}
bool CreateAttUIFromJson(const JsonAttUI& jUi, AttUI& ui, const WeaponAttachment& attachment) const
{
if (jUi.dpadIcon)
{
if (!CreateMaterialFromJson(jUi.dpadIcon.value(), ui.dpadIcon, attachment))
return false;
}
else
ui.dpadIcon = nullptr;
if (jUi.ammoCounterIcon)
{
if (!CreateMaterialFromJson(jUi.ammoCounterIcon.value(), ui.ammoCounterIcon, attachment))
return false;
}
else
ui.ammoCounterIcon = nullptr;
ui.dpadIconRatio = jUi.dpadIconRatio;
ui.ammoCounterIconRatio = jUi.ammoCounterIconRatio;
ui.ammoCounterClip = jUi.ammoCounterClip;
return true;
}
bool CreateAttRumblesFromJson(const JsonAttRumbles& jRumbles, AttRumbles& rumbles, const WeaponAttachment& attachment) const
{
if (jRumbles.fireRumble)
rumbles.fireRumble = m_memory.Dup(jRumbles.fireRumble.value().c_str());
else
rumbles.fireRumble = nullptr;
if (jRumbles.meleeImpactRumble)
rumbles.meleeImpactRumble = m_memory.Dup(jRumbles.meleeImpactRumble.value().c_str());
else
rumbles.meleeImpactRumble = nullptr;
return true;
}
bool CreateAttProjectileFromJson(const JsonAttProjectile& jProjectile, AttProjectile& projectile, const WeaponAttachment& attachment) const
{
projectile.explosionRadius = jProjectile.explosionRadius;
projectile.explosionInnerDamage = jProjectile.explosionInnerDamage;
projectile.explosionOuterDamage = jProjectile.explosionOuterDamage;
projectile.damageConeAngle = jProjectile.damageConeAngle;
projectile.projectileSpeed = jProjectile.projectileSpeed;
projectile.projectileSpeedUp = jProjectile.projectileSpeedUp;
projectile.projectileActivateDist = jProjectile.projectileActivateDist;
projectile.projectileLifetime = jProjectile.projectileLifetime;
if (jProjectile.projectileModel)
{
if (!CreateXModelFromJson(jProjectile.projectileModel.value(), projectile.projectileModel, attachment))
return false;
}
else
projectile.projectileModel = nullptr;
projectile.projExplosionType = jProjectile.projExplosionType;
if (jProjectile.projExplosionEffect)
{
if (!CreateFxFromJson(jProjectile.projExplosionEffect.value(), projectile.projExplosionEffect, attachment))
return false;
}
else
projectile.projExplosionEffect = nullptr;
projectile.projExplosionEffectForceNormalUp = jProjectile.projExplosionEffectForceNormalUp;
if (jProjectile.projExplosionSound)
{
if (!CreateSoundFromJson(jProjectile.projExplosionSound.value(), projectile.projExplosionSound, attachment))
return false;
}
else
projectile.projExplosionSound.name = nullptr;
if (jProjectile.projDudEffect)
{
if (!CreateFxFromJson(jProjectile.projDudEffect.value(), projectile.projDudEffect, attachment))
return false;
}
else
projectile.projDudEffect = nullptr;
if (jProjectile.projDudSound)
{
if (!CreateSoundFromJson(jProjectile.projDudSound.value(), projectile.projDudSound, attachment))
return false;
}
else
projectile.projDudSound.name = nullptr;
projectile.projImpactExplode = jProjectile.projImpactExplode;
projectile.destabilizationRateTime = jProjectile.destabilizationRateTime;
projectile.destabilizationCurvatureMax = jProjectile.destabilizationCurvatureMax;
projectile.destabilizeDistance = jProjectile.destabilizeDistance;
if (jProjectile.projTrailEffect)
{
if (!CreateFxFromJson(jProjectile.projTrailEffect.value(), projectile.projTrailEffect, attachment))
return false;
}
else
projectile.projTrailEffect = nullptr;
projectile.projIgnitionDelay = jProjectile.projIgnitionDelay;
if (jProjectile.projIgnitionEffect)
{
if (!CreateFxFromJson(jProjectile.projIgnitionEffect.value(), projectile.projIgnitionEffect, attachment))
return false;
}
else
projectile.projIgnitionEffect = nullptr;
if (jProjectile.projIgnitionSound)
{
if (!CreateSoundFromJson(jProjectile.projIgnitionSound.value(), projectile.projIgnitionSound, attachment))
return false;
}
else
projectile.projIgnitionSound.name = nullptr;
return true;
}
std::istream& m_stream;
MemoryManager& m_memory;
AssetCreationContext& m_context;
AssetRegistration<AssetAttachment>& m_registration;
};
class AttachmentLoader final : public AssetCreator<AssetAttachment>
{
public:
@@ -22,7 +643,7 @@ namespace
AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override
{
const auto file = m_search_path.Open(std::format("attachment/{}.json", assetName));
const auto file = m_search_path.Open(attachment::GetJsonFileNameForAssetName(assetName));
if (!file.IsOpen())
return AssetCreationResult::NoAction();
@@ -30,9 +651,10 @@ namespace
attachment->szInternalName = m_memory.Dup(assetName.c_str());
AssetRegistration<AssetAttachment> registration(assetName, attachment);
if (!LoadWeaponAttachmentAsJson(*file.m_stream, *attachment, m_memory, context, registration))
const JsonLoader loader(*file.m_stream, m_memory, context, registration);
if (!loader.Load(*attachment))
{
std::cerr << std::format("Failed to load attachment \"{}\"\n", assetName);
con::error("Failed to load attachment \"{}\"", assetName);
return AssetCreationResult::Failure();
}
@@ -45,10 +667,10 @@ namespace
};
} // namespace
namespace IW5
namespace attachment
{
std::unique_ptr<AssetCreator<AssetAttachment>> CreateAttachmentLoader(MemoryManager& memory, ISearchPath& searchPath)
std::unique_ptr<AssetCreator<AssetAttachment>> CreateLoaderIW5(MemoryManager& memory, ISearchPath& searchPath)
{
return std::make_unique<AttachmentLoader>(memory, searchPath);
}
} // namespace IW5
} // namespace attachment

View File

@@ -7,7 +7,7 @@
#include <memory>
namespace IW5
namespace attachment
{
std::unique_ptr<AssetCreator<AssetAttachment>> CreateAttachmentLoader(MemoryManager& memory, ISearchPath& searchPath);
} // namespace IW5
std::unique_ptr<AssetCreator<IW5::AssetAttachment>> CreateLoaderIW5(MemoryManager& memory, ISearchPath& searchPath);
} // namespace attachment

View File

@@ -4,12 +4,15 @@
#include "Game/IW5/ObjConstantsIW5.h"
#include "InfoString/InfoString.h"
#include "InfoStringLoaderWeaponIW5.h"
#include "Utils/Logging/Log.h"
#include "Weapon/WeaponCommon.h"
#include <cstring>
#include <format>
#include <iostream>
using namespace IW5;
using namespace ::weapon;
namespace
{
@@ -24,7 +27,7 @@ namespace
AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override
{
const auto fileName = std::format("weapons/{}", assetName);
const auto fileName = GetFileNameForAssetName(assetName);
const auto file = m_search_path.Open(fileName);
if (!file.IsOpen())
return AssetCreationResult::NoAction();
@@ -32,7 +35,7 @@ namespace
InfoString infoString;
if (!infoString.FromStream(ObjConstants::INFO_STRING_PREFIX_WEAPON, *file.m_stream))
{
std::cerr << std::format("Could not parse as info string file: \"{}\"\n", fileName);
con::error("Could not parse as info string file: \"{}\"", fileName);
return AssetCreationResult::Failure();
}
@@ -41,14 +44,14 @@ namespace
private:
ISearchPath& m_search_path;
InfoStringLoaderWeapon m_info_string_loader;
weapon::InfoStringLoaderIW5 m_info_string_loader;
};
} // namespace
namespace IW5
namespace weapon
{
std::unique_ptr<AssetCreator<AssetWeapon>> CreateRawWeaponLoader(MemoryManager& memory, ISearchPath& searchPath, Zone& zone)
std::unique_ptr<AssetCreator<AssetWeapon>> CreateRawLoaderIW5(MemoryManager& memory, ISearchPath& searchPath, Zone& zone)
{
return std::make_unique<RawLoaderWeapon>(memory, searchPath, zone);
}
} // namespace IW5
} // namespace weapon

View File

@@ -7,7 +7,7 @@
#include <memory>
namespace IW5
namespace weapon
{
std::unique_ptr<AssetCreator<AssetWeapon>> CreateRawWeaponLoader(MemoryManager& memory, ISearchPath& searchPath, Zone& zone);
} // namespace IW5
std::unique_ptr<AssetCreator<IW5::AssetWeapon>> CreateRawLoaderIW5(MemoryManager& memory, ISearchPath& searchPath, Zone& zone);
} // namespace weapon

View File

@@ -1,55 +0,0 @@
// #include "LoaderXModelIW5.h"
// #include "Game/IW5/IW5.h"
// #include "Game/IW5/XModel/XModelLoaderIW5.h"
// #include "Pool/GlobalAssetPool.h"
// #include <cstring>
// #include <format>
// #include <iostream>
// using namespace IW5;
// namespace
// {
// class XModelLoader final : public AssetCreator<AssetXModel>
// {
// public:
// XModelLoader(MemoryManager& memory, ISearchPath& searchPath)
// : m_memory(memory),
// m_search_path(searchPath)
// {
// }
// AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override
// {
// const auto file = m_search_path.Open(std::format("xmodel/{}.json", assetName));
// if (!file.IsOpen())
// return AssetCreationResult::NoAction();
// auto* xmodel = m_memory.Alloc<XModel>();
// xmodel->name = m_memory.Dup(assetName.c_str());
// AssetRegistration<AssetXModel> registration(assetName, xmodel);
// if (!LoadXModel(*file.m_stream, *xmodel, m_memory, context, registration))
// {
// std::cerr << std::format("Failed to load xmodel \"{}\"\n", assetName);
// return AssetCreationResult::Failure();
// }
// return AssetCreationResult::Success(context.AddAsset(std::move(registration)));
// }
// private:
// MemoryManager& m_memory;
// ISearchPath& m_search_path;
// };
// } // namespace
// namespace IW5
// {
// std::unique_ptr<AssetCreator<AssetXModel>> CreateXModelLoader(MemoryManager& memory, ISearchPath& searchPath)
// {
// return std::make_unique<XModelLoader>(memory, searchPath);
// }
// } // namespace IW5

View File

@@ -1,13 +0,0 @@
// #pragma once
// #include "Asset/IAssetCreator.h"
// #include "Game/IW5/IW5.h"
// #include "SearchPath/ISearchPath.h"
// #include "Utils/MemoryManager.h"
// #include <memory>
// namespace IW5
// {
// std::unique_ptr<AssetCreator<AssetXModel>> CreateXModelLoader(MemoryManager& memory, ISearchPath& searchPath);
// } // namespace IW5

View File

@@ -35,10 +35,10 @@ namespace
};
} // namespace
namespace T5
namespace localize
{
std::unique_ptr<AssetCreator<AssetLocalize>> CreateLocalizeLoader(MemoryManager& memory, ISearchPath& searchPath, Zone& zone)
std::unique_ptr<AssetCreator<AssetLocalize>> CreateLoaderT5(MemoryManager& memory, ISearchPath& searchPath, Zone& zone)
{
return std::make_unique<LocalizeLoader>(memory, searchPath, zone);
}
} // namespace T5
} // namespace localize

View File

@@ -8,7 +8,7 @@
#include <memory>
namespace T5
namespace localize
{
std::unique_ptr<AssetCreator<AssetLocalize>> CreateLocalizeLoader(MemoryManager& memory, ISearchPath& searchPath, Zone& zone);
} // namespace T5
std::unique_ptr<AssetCreator<T5::AssetLocalize>> CreateLoaderT5(MemoryManager& memory, ISearchPath& searchPath, Zone& zone);
} // namespace localize

View File

@@ -0,0 +1,55 @@
#include "LoaderMaterialT5.h"
#include "Game/T5/Material/JsonMaterialLoaderT5.h"
#include "Game/T5/T5.h"
#include "Material/MaterialCommon.h"
#include "Utils/Logging/Log.h"
#include <format>
#include <iostream>
using namespace T5;
namespace
{
class MaterialLoader final : public AssetCreator<AssetMaterial>
{
public:
MaterialLoader(MemoryManager& memory, ISearchPath& searchPath)
: m_memory(memory),
m_search_path(searchPath)
{
}
AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override
{
const auto file = m_search_path.Open(material::GetFileNameForAssetName(assetName));
if (!file.IsOpen())
return AssetCreationResult::NoAction();
auto* material = m_memory.Alloc<Material>();
material->info.name = m_memory.Dup(assetName.c_str());
AssetRegistration<AssetMaterial> registration(assetName, material);
if (!LoadMaterialAsJson(*file.m_stream, *material, m_memory, context, registration))
{
con::error("Failed to load material \"{}\"", assetName);
return AssetCreationResult::Failure();
}
return AssetCreationResult::Success(context.AddAsset(std::move(registration)));
}
private:
MemoryManager& m_memory;
ISearchPath& m_search_path;
};
} // namespace
namespace material
{
std::unique_ptr<AssetCreator<AssetMaterial>> CreateLoaderT5(MemoryManager& memory, ISearchPath& searchPath)
{
return std::make_unique<MaterialLoader>(memory, searchPath);
}
} // namespace material

View File

@@ -0,0 +1,12 @@
#pragma once
#include "Asset/IAssetCreator.h"
#include "Game/T5/T5.h"
#include "Gdt/IGdtQueryable.h"
#include "SearchPath/ISearchPath.h"
#include "Utils/MemoryManager.h"
namespace material
{
std::unique_ptr<AssetCreator<T5::AssetMaterial>> CreateLoaderT5(MemoryManager& memory, ISearchPath& searchPath);
} // namespace material

View File

@@ -5,6 +5,7 @@
#include "Game/T5/T5.h"
#include "Game/T5/XModel/LoaderXModelT5.h"
#include "Localize/LoaderLocalizeT5.h"
#include "Material/LoaderMaterialT5.h"
#include "ObjLoading.h"
#include "RawFile/LoaderRawFileT5.h"
#include "StringTable/LoaderStringTableT5.h"
@@ -103,8 +104,8 @@ namespace
// collection.AddAssetCreator(std::make_unique<AssetLoaderPhysConstraints>(memory));
// collection.AddAssetCreator(std::make_unique<AssetLoaderDestructibleDef>(memory));
// collection.AddAssetCreator(std::make_unique<AssetLoaderXAnim>(memory));
collection.AddAssetCreator(CreateXModelLoader(memory, searchPath, zone));
// collection.AddAssetCreator(std::make_unique<AssetLoaderMaterial>(memory));
collection.AddAssetCreator(xmodel::CreateLoaderT5(memory, searchPath, zone));
collection.AddAssetCreator(material::CreateLoaderT5(memory, searchPath));
// collection.AddAssetCreator(std::make_unique<AssetLoaderTechniqueSet>(memory));
// collection.AddAssetCreator(std::make_unique<AssetLoaderImage>(memory));
// collection.AddAssetCreator(std::make_unique<AssetLoaderSoundBank>(memory));
@@ -119,13 +120,13 @@ namespace
// collection.AddAssetCreator(std::make_unique<AssetLoaderFont>(memory));
// collection.AddAssetCreator(std::make_unique<AssetLoaderMenuList>(memory));
// collection.AddAssetCreator(std::make_unique<AssetLoaderMenu>(memory));
collection.AddAssetCreator(CreateLocalizeLoader(memory, searchPath, zone));
collection.AddAssetCreator(localize::CreateLoaderT5(memory, searchPath, zone));
// collection.AddAssetCreator(std::make_unique<AssetLoaderWeapon>(memory));
// collection.AddAssetCreator(std::make_unique<AssetLoaderSoundDriverGlobals>(memory));
// collection.AddAssetCreator(std::make_unique<AssetLoaderFx>(memory));
// collection.AddAssetCreator(std::make_unique<AssetLoaderImpactFx>(memory));
collection.AddAssetCreator(CreateRawFileLoader(memory, searchPath));
collection.AddAssetCreator(CreateStringTableLoader(memory, searchPath));
collection.AddAssetCreator(raw_file::CreateLoaderT5(memory, searchPath));
collection.AddAssetCreator(string_table::CreateLoaderT5(memory, searchPath));
// collection.AddAssetCreator(std::make_unique<AssetLoaderPackIndex>(memory));
// collection.AddAssetCreator(std::make_unique<AssetLoaderXGlobals>(memory));
// collection.AddAssetCreator(std::make_unique<AssetLoaderDDL>(memory));

View File

@@ -1,6 +1,7 @@
#include "LoaderRawFileT5.h"
#include "Game/T5/T5.h"
#include "Utils/Logging/Log.h"
#include <cstring>
#include <filesystem>
@@ -71,7 +72,7 @@ namespace
if (ret != Z_STREAM_END)
{
std::cerr << std::format("Deflate failed for loading gsc file \"{}\"\n", assetName);
con::error("Deflate failed for loading gsc file \"{}\"", assetName);
deflateEnd(&zs);
return AssetCreationResult::Failure();
}
@@ -114,10 +115,10 @@ namespace
};
} // namespace
namespace T5
namespace raw_file
{
std::unique_ptr<AssetCreator<AssetRawFile>> CreateRawFileLoader(MemoryManager& memory, ISearchPath& searchPath)
std::unique_ptr<AssetCreator<AssetRawFile>> CreateLoaderT5(MemoryManager& memory, ISearchPath& searchPath)
{
return std::make_unique<RawFileLoader>(memory, searchPath);
}
} // namespace T5
} // namespace raw_file

View File

@@ -7,7 +7,7 @@
#include <memory>
namespace T5
namespace raw_file
{
std::unique_ptr<AssetCreator<AssetRawFile>> CreateRawFileLoader(MemoryManager& memory, ISearchPath& searchPath);
} // namespace T5
std::unique_ptr<AssetCreator<T5::AssetRawFile>> CreateLoaderT5(MemoryManager& memory, ISearchPath& searchPath);
} // namespace raw_file

View File

@@ -37,10 +37,10 @@ namespace
};
} // namespace
namespace T5
namespace string_table
{
std::unique_ptr<AssetCreator<AssetStringTable>> CreateStringTableLoader(MemoryManager& memory, ISearchPath& searchPath)
std::unique_ptr<AssetCreator<AssetStringTable>> CreateLoaderT5(MemoryManager& memory, ISearchPath& searchPath)
{
return std::make_unique<StringTableLoader>(memory, searchPath);
}
} // namespace T5
} // namespace string_table

View File

@@ -7,7 +7,7 @@
#include <memory>
namespace T5
namespace string_table
{
std::unique_ptr<AssetCreator<AssetStringTable>> CreateStringTableLoader(MemoryManager& memory, ISearchPath& searchPath);
} // namespace T5
std::unique_ptr<AssetCreator<T5::AssetStringTable>> CreateLoaderT5(MemoryManager& memory, ISearchPath& searchPath);
} // namespace string_table

View File

@@ -1,8 +1,9 @@
#include "LoaderFontIconT6.h"
#include "CsvLoaderFontIconT6.h"
#include "Csv/CsvStream.h"
#include "Game/T6/CommonT6.h"
#include "Game/T6/T6.h"
#include "Utils/Logging/Log.h"
#include <algorithm>
#include <format>
@@ -30,10 +31,10 @@ namespace
constexpr unsigned COL_COUNT_ALIAS = 4;
constexpr unsigned COL_COUNT_MIN = std::min(COL_COUNT_ICON, COL_COUNT_ALIAS);
class FontIconLoader final : public AssetCreator<AssetFontIcon>
class CsvFontIconLoader final : public AssetCreator<AssetFontIcon>
{
public:
FontIconLoader(MemoryManager& memory, ISearchPath& searchPath)
CsvFontIconLoader(MemoryManager& memory, ISearchPath& searchPath)
: m_memory(memory),
m_search_path(searchPath)
{
@@ -65,14 +66,14 @@ namespace
if (currentRow.size() < COL_COUNT_MIN)
{
std::cerr << std::format("{} Column count lower than min column count ({})\n", ErrorPrefix(assetName, currentRowIndex), COL_COUNT_MIN);
con::error("{} Column count lower than min column count ({})", ErrorPrefix(assetName, currentRowIndex), COL_COUNT_MIN);
return AssetCreationResult::Failure();
}
int index;
if (!ParseInt(index, currentRow[ROW_INDEX]) || index < 0)
{
std::cerr << std::format("{} Failed to parse index\n", ErrorPrefix(assetName, currentRowIndex));
con::error("{} Failed to parse index", ErrorPrefix(assetName, currentRowIndex));
return AssetCreationResult::Failure();
}
@@ -118,7 +119,7 @@ namespace
}
else
{
std::cerr << std::format("{} Unknown row type \"{}\"\n", ErrorPrefix(assetName, currentRowIndex), currentRow[ROW_TYPE]);
con::error("{} Unknown row type \"{}\"", ErrorPrefix(assetName, currentRowIndex), currentRow[ROW_TYPE]);
return AssetCreationResult::Failure();
}
}
@@ -222,26 +223,26 @@ namespace
{
if (row.size() < COL_COUNT_ICON)
{
std::cerr << std::format("{} Column count lower than min column count for entries ({})\n", ErrorPrefix(assetName, rowIndex), COL_COUNT_ICON);
con::error("{} Column count lower than min column count for entries ({})", ErrorPrefix(assetName, rowIndex), COL_COUNT_ICON);
return false;
}
if (!ParseInt(icon.fontIconSize, row[ROW_ICON_SIZE]))
{
std::cerr << std::format("{} Failed to parse size\n", ErrorPrefix(assetName, rowIndex));
con::error("{} Failed to parse size", ErrorPrefix(assetName, rowIndex));
return false;
}
if (!ParseFloat(icon.xScale, row[ROW_ICON_XSCALE]) || !ParseFloat(icon.yScale, row[ROW_ICON_YSCALE]))
{
std::cerr << std::format("{} Failed to parse scale\n", ErrorPrefix(assetName, rowIndex));
con::error("{} Failed to parse scale", ErrorPrefix(assetName, rowIndex));
return false;
}
auto* materialDependency = context.LoadDependency<AssetMaterial>(row[ROW_ICON_MATERIAL]);
if (materialDependency == nullptr)
{
std::cerr << std::format("{} Failed to load material \"{}\"\n", ErrorPrefix(assetName, rowIndex), row[ROW_ICON_MATERIAL]);
con::error("{} Failed to load material \"{}\"", ErrorPrefix(assetName, rowIndex), row[ROW_ICON_MATERIAL]);
return false;
}
registration.AddDependency(materialDependency);
@@ -258,19 +259,19 @@ namespace
{
if (row.size() < COL_COUNT_ALIAS)
{
std::cerr << std::format("{} Column count lower than min column count for aliases ({})\n", ErrorPrefix(assetName, rowIndex), COL_COUNT_ALIAS);
con::error("{} Column count lower than min column count for aliases ({})", ErrorPrefix(assetName, rowIndex), COL_COUNT_ALIAS);
return false;
}
if (!ParseHashStr(alias.aliasHash, row[ROW_ALIAS_NAME]))
{
std::cerr << std::format("{} Failed to parse alias \"{}\"\n", ErrorPrefix(assetName, rowIndex), row[ROW_ALIAS_NAME]);
con::error("{} Failed to parse alias \"{}\"", ErrorPrefix(assetName, rowIndex), row[ROW_ALIAS_NAME]);
return false;
}
if (!ParseHashStr(alias.buttonHash, row[ROW_ALIAS_BUTTON]))
{
std::cerr << std::format("{} Failed to parse button \"{}\"\n", ErrorPrefix(assetName, rowIndex), row[ROW_ALIAS_BUTTON]);
con::error("{} Failed to parse button \"{}\"", ErrorPrefix(assetName, rowIndex), row[ROW_ALIAS_BUTTON]);
return false;
}
@@ -282,10 +283,10 @@ namespace
};
} // namespace
namespace T6
namespace font_icon
{
std::unique_ptr<AssetCreator<AssetFontIcon>> CreateFontIconLoader(MemoryManager& memory, ISearchPath& searchPath)
std::unique_ptr<AssetCreator<AssetFontIcon>> CreateCsvLoaderT6(MemoryManager& memory, ISearchPath& searchPath)
{
return std::make_unique<FontIconLoader>(memory, searchPath);
return std::make_unique<CsvFontIconLoader>(memory, searchPath);
}
} // namespace T6
} // namespace font_icon

View File

@@ -0,0 +1,13 @@
#pragma once
#include "Asset/IAssetCreator.h"
#include "Game/T6/T6.h"
#include "SearchPath/ISearchPath.h"
#include "Utils/MemoryManager.h"
#include <memory>
namespace font_icon
{
std::unique_ptr<AssetCreator<T6::AssetFontIcon>> CreateCsvLoaderT6(MemoryManager& memory, ISearchPath& searchPath);
} // namespace font_icon

View File

@@ -0,0 +1,151 @@
#include "JsonLoaderFontIconT6.h"
#include "FontIcon/FontIconCommon.h"
#include "Game/T6/CommonT6.h"
#include "Game/T6/FontIcon/JsonFontIconT6.h"
#include "Game/T6/T6.h"
#include "Utils/Logging/Log.h"
#include <algorithm>
#include <format>
#include <iostream>
#include <nlohmann/json.hpp>
using namespace nlohmann;
using namespace T6;
namespace
{
class JsonFontIconLoader final : public AssetCreator<AssetFontIcon>
{
public:
JsonFontIconLoader(MemoryManager& memory, ISearchPath& searchPath)
: m_memory(memory),
m_search_path(searchPath)
{
}
AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override
{
const auto file = m_search_path.Open(font_icon::GetJsonFileNameForAssetName(assetName));
if (!file.IsOpen())
return AssetCreationResult::NoAction();
auto* fontIcon = m_memory.Alloc<FontIcon>();
fontIcon->name = m_memory.Dup(assetName.c_str());
AssetRegistration<AssetFontIcon> registration(assetName, fontIcon);
try
{
const auto jRoot = json::parse(*file.m_stream);
std::string type;
unsigned version;
jRoot.at("_type").get_to(type);
jRoot.at("_version").get_to(version);
if (type != "font-icon" || version != 1u)
{
con::error("Tried to load font icon \"{}\" but did not find expected type font-icon of version 1", assetName);
return AssetCreationResult::Failure();
}
const auto jFontIcon = jRoot.get<JsonFontIcon>();
if (CreateFontIconFromJson(jFontIcon, *fontIcon, registration, context))
return AssetCreationResult::Success(context.AddAsset(std::move(registration)));
}
catch (const json::exception& e)
{
con::error("Failed to parse json of font icon: {}", e.what());
}
return AssetCreationResult::Failure();
}
private:
bool CreateFontIconFromJson(const JsonFontIcon& jFontIcon,
FontIcon& fontIcon,
AssetRegistration<AssetFontIcon>& registration,
AssetCreationContext& context) const
{
std::vector<FontIconAlias> aliases;
fontIcon.numEntries = static_cast<unsigned>(jFontIcon.entries.size());
fontIcon.fontIconEntry = m_memory.Alloc<FontIconEntry>(fontIcon.numEntries);
for (auto entryIndex = 0u; entryIndex < fontIcon.numEntries; entryIndex++)
{
if (!CreateFontIconEntryFromJson(jFontIcon.entries[entryIndex], fontIcon.fontIconEntry[entryIndex], aliases, registration, context))
return false;
}
std::sort(fontIcon.fontIconEntry,
&fontIcon.fontIconEntry[fontIcon.numEntries],
[](const FontIconEntry& e0, const FontIconEntry& e1) -> bool
{
return e0.fontIconName.hash < e1.fontIconName.hash;
});
if (!aliases.empty())
{
fontIcon.numAliasEntries = static_cast<unsigned>(aliases.size());
fontIcon.fontIconAlias = m_memory.Alloc<FontIconAlias>(fontIcon.numAliasEntries);
std::memcpy(fontIcon.fontIconAlias, aliases.data(), sizeof(FontIconAlias) * fontIcon.numAliasEntries);
std::sort(fontIcon.fontIconAlias,
&fontIcon.fontIconAlias[fontIcon.numAliasEntries],
[](const FontIconAlias& a0, const FontIconAlias& a1) -> bool
{
return a0.aliasHash < a1.aliasHash;
});
}
return true;
}
bool CreateFontIconEntryFromJson(const JsonFontIconEntry& jFontIconEntry,
FontIconEntry& fontIconEntry,
std::vector<FontIconAlias>& aliases,
AssetRegistration<AssetFontIcon>& registration,
AssetCreationContext& context) const
{
fontIconEntry.fontIconName.string = m_memory.Dup(jFontIconEntry.name.c_str());
fontIconEntry.fontIconName.hash = Common::Com_HashString(jFontIconEntry.name.c_str());
auto* materialDependency = context.LoadDependency<AssetMaterial>(jFontIconEntry.material);
if (materialDependency == nullptr)
{
con::error("Failed to load material \"{}\" for font icon entry \"{}\"", jFontIconEntry.material, jFontIconEntry.name);
return false;
}
registration.AddDependency(materialDependency);
fontIconEntry.fontIconMaterialHandle = materialDependency->Asset();
fontIconEntry.fontIconSize = static_cast<int>(jFontIconEntry.size);
fontIconEntry.xScale = jFontIconEntry.scale.has_value() ? jFontIconEntry.scale->x : 0;
fontIconEntry.yScale = jFontIconEntry.scale.has_value() ? jFontIconEntry.scale->y : 0;
for (const auto& alias : jFontIconEntry.aliases)
aliases.emplace_back(Common::Com_HashString(alias.c_str()), fontIconEntry.fontIconName.hash);
if (jFontIconEntry.aliasHashes.has_value())
{
for (const auto aliasHash : *jFontIconEntry.aliasHashes)
aliases.emplace_back(aliasHash, fontIconEntry.fontIconName.hash);
}
return true;
}
MemoryManager& m_memory;
ISearchPath& m_search_path;
};
} // namespace
namespace font_icon
{
std::unique_ptr<AssetCreator<AssetFontIcon>> CreateJsonLoaderT6(MemoryManager& memory, ISearchPath& searchPath)
{
return std::make_unique<JsonFontIconLoader>(memory, searchPath);
}
} // namespace font_icon

View File

@@ -0,0 +1,13 @@
#pragma once
#include "Asset/IAssetCreator.h"
#include "Game/T6/T6.h"
#include "SearchPath/ISearchPath.h"
#include "Utils/MemoryManager.h"
#include <memory>
namespace font_icon
{
std::unique_ptr<AssetCreator<T6::AssetFontIcon>> CreateJsonLoaderT6(MemoryManager& memory, ISearchPath& searchPath);
} // namespace font_icon

View File

@@ -1,13 +0,0 @@
#pragma once
#include "Asset/IAssetCreator.h"
#include "Game/T6/T6.h"
#include "SearchPath/ISearchPath.h"
#include "Utils/MemoryManager.h"
#include <memory>
namespace T6
{
std::unique_ptr<AssetCreator<AssetFontIcon>> CreateFontIconLoader(MemoryManager& memory, ISearchPath& searchPath);
} // namespace T6

View File

@@ -2,8 +2,9 @@
#include "Game/T6/CommonT6.h"
#include "Game/T6/T6.h"
#include "Image/ImageCommon.h"
#include "Image/IwiLoader.h"
#include "Image/IwiTypes.h"
#include "Utils/Logging/Log.h"
#include <cstring>
#include <format>
@@ -26,12 +27,7 @@ namespace
AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override
{
auto fileName = std::format("images/{}.iwi", assetName);
for (size_t i = 0; i < fileName.size(); i++)
if (fileName[i] == '*')
fileName[i] = '_';
const auto fileName = image::GetFileNameForAsset(assetName, ".iwi");
const auto file = m_search_path.Open(fileName);
if (!file.IsOpen())
return AssetCreationResult::NoAction();
@@ -45,7 +41,7 @@ namespace
const auto texture = iwi::LoadIwi(ss);
if (!texture)
{
std::cerr << std::format("Failed to load texture from: {}\n", fileName);
con::error("Failed to load texture from: {}", fileName);
return AssetCreationResult::Failure();
}
@@ -59,47 +55,11 @@ namespace
image->height = static_cast<uint16_t>(texture->GetHeight());
image->depth = static_cast<uint16_t>(texture->GetDepth());
if (texture->GetTextureType() == TextureType::T_2D)
image->mapType = 3;
else if (texture->GetTextureType() == TextureType::T_3D)
image->mapType = 4;
else if (texture->GetTextureType() == TextureType::T_CUBE)
image->mapType = 5;
else
_ASSERT(false);
//image->streaming = 1;
//image->streamedParts[0].levelCount = 1;
//image->streamedParts[0].levelSize = static_cast<uint32_t>(fileSize);
//image->streamedParts[0].hash = dataHash & 0x1FFFFFFF;
//image->streamedPartCount = 1;
int mipMapCount = texture->HasMipMaps() ? texture->GetMipMapCount() : 1;
size_t textureSize = 0;
for (int previousMipLevel = 0; previousMipLevel < mipMapCount; previousMipLevel++)
{
textureSize += texture->GetSizeOfMipLevel(previousMipLevel) * texture->GetFaceCount();
}
image->streaming = 0;
image->texture.loadDef = (GfxImageLoadDef*)malloc(sizeof(GfxImageLoadDef) + textureSize);
memset(image->texture.loadDef, 0, sizeof(GfxImageLoadDef) + textureSize);
image->texture.loadDef->format = texture->GetFormat()->GetDxgiFormat();
image->texture.loadDef->levelCount = 1;
image->texture.loadDef->resourceSize = textureSize;
memcpy(image->texture.loadDef->data,
texture->GetBufferForMipLevel(0),
textureSize); // GetBufferForMipLevel(0) returns a pointer to the start of the image
image->texture.loadDef->flags = 0;
if (image->noPicmip)
image->texture.loadDef->flags |= iwi27::IMG_FLAG_NOMIPMAPS;
if (texture->GetTextureType() == TextureType::T_3D)
image->texture.loadDef->flags |= iwi27::IMG_FLAG_VOLMAP;
if (texture->GetTextureType() == TextureType::T_CUBE)
image->texture.loadDef->flags |= iwi27::IMG_FLAG_CUBEMAP;
image->streaming = 1;
image->streamedParts[0].levelCount = 1;
image->streamedParts[0].levelSize = static_cast<uint32_t>(fileSize);
image->streamedParts[0].hash = dataHash & 0x1FFFFFFF;
image->streamedPartCount = 1;
return AssetCreationResult::Success(context.AddAsset<AssetImage>(assetName, image));
}
@@ -110,10 +70,10 @@ namespace
};
} // namespace
namespace T6
namespace image
{
std::unique_ptr<AssetCreator<AssetImage>> CreateImageLoader(MemoryManager& memory, ISearchPath& searchPath)
std::unique_ptr<AssetCreator<AssetImage>> CreateLoaderT6(MemoryManager& memory, ISearchPath& searchPath)
{
return std::make_unique<ImageLoader>(memory, searchPath);
}
} // namespace T6
} // namespace image

View File

@@ -7,7 +7,7 @@
#include <memory>
namespace T6
namespace image
{
std::unique_ptr<AssetCreator<AssetImage>> CreateImageLoader(MemoryManager& memory, ISearchPath& searchPath);
} // namespace T6
std::unique_ptr<AssetCreator<T6::AssetImage>> CreateLoaderT6(MemoryManager& memory, ISearchPath& searchPath);
} // namespace image

Some files were not shown because too many files have changed in this diff Show More