mirror of
https://github.com/Laupetin/OpenAssetTools.git
synced 2025-08-30 21:53:15 +00:00
refactor: streamline IW5 asset loading
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
#include "LoaderImageIW5.h"
|
||||
|
||||
#include "Game/IW5/IW5.h"
|
||||
#include "Image/ImageCommon.h"
|
||||
#include "Image/IwiLoader.h"
|
||||
|
||||
#include <cstring>
|
||||
@@ -9,6 +10,7 @@
|
||||
#include <sstream>
|
||||
|
||||
using namespace IW5;
|
||||
using namespace ::image;
|
||||
|
||||
namespace
|
||||
{
|
||||
@@ -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 = GetFileNameForAsset(assetName, ".iwi");
|
||||
const auto file = m_search_path.Open(fileName);
|
||||
if (!file.IsOpen())
|
||||
return AssetCreationResult::NoAction();
|
||||
@@ -60,10 +62,10 @@ namespace
|
||||
};
|
||||
} // namespace
|
||||
|
||||
namespace IW5
|
||||
namespace IW5::image
|
||||
{
|
||||
std::unique_ptr<AssetCreator<AssetImage>> CreateImageLoader(MemoryManager& memory, ISearchPath& searchPath)
|
||||
std::unique_ptr<AssetCreator<AssetImage>> CreateLoader(MemoryManager& memory, ISearchPath& searchPath)
|
||||
{
|
||||
return std::make_unique<ImageLoader>(memory, searchPath);
|
||||
}
|
||||
} // namespace IW5
|
||||
} // namespace IW5::image
|
||||
|
@@ -7,7 +7,7 @@
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace IW5
|
||||
namespace IW5::image
|
||||
{
|
||||
std::unique_ptr<AssetCreator<AssetImage>> CreateImageLoader(MemoryManager& memory, ISearchPath& searchPath);
|
||||
} // namespace IW5
|
||||
std::unique_ptr<AssetCreator<AssetImage>> CreateLoader(MemoryManager& memory, ISearchPath& searchPath);
|
||||
} // namespace IW5::image
|
||||
|
@@ -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
|
||||
{
|
||||
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)
|
||||
{
|
||||
std::cerr << std::format("Tried to load leaderboard \"{}\" but did not find expected type leaderboard of version 1\n", leaderboardDef.name);
|
||||
return false;
|
||||
}
|
||||
|
||||
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
|
@@ -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
|
@@ -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 <cstring>
|
||||
#include <format>
|
||||
#include <iostream>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
using namespace nlohmann;
|
||||
using namespace IW5;
|
||||
using namespace ::leaderboard;
|
||||
|
||||
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)
|
||||
{
|
||||
std::cerr << std::format("Tried to load leaderboard \"{}\" but did not find expected type leaderboard of version 1\n", leaderboardDef.name);
|
||||
return false;
|
||||
}
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
class LeaderboardLoader final : public AssetCreator<AssetLeaderboard>
|
||||
{
|
||||
public:
|
||||
@@ -22,14 +133,15 @@ 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(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);
|
||||
return AssetCreationResult::Failure();
|
||||
@@ -44,10 +156,10 @@ namespace
|
||||
};
|
||||
} // namespace
|
||||
|
||||
namespace IW5
|
||||
namespace IW5::leaderboard
|
||||
{
|
||||
std::unique_ptr<AssetCreator<AssetLeaderboard>> CreateLeaderboardLoader(MemoryManager& memory, ISearchPath& searchPath)
|
||||
std::unique_ptr<AssetCreator<AssetLeaderboard>> CreateLoader(MemoryManager& memory, ISearchPath& searchPath)
|
||||
{
|
||||
return std::make_unique<LeaderboardLoader>(memory, searchPath);
|
||||
}
|
||||
} // namespace IW5
|
||||
} // namespace IW5::leaderboard
|
||||
|
@@ -7,7 +7,7 @@
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace IW5
|
||||
namespace IW5::leaderboard
|
||||
{
|
||||
std::unique_ptr<AssetCreator<AssetLeaderboard>> CreateLeaderboardLoader(MemoryManager& memory, ISearchPath& searchPath);
|
||||
} // namespace IW5
|
||||
std::unique_ptr<AssetCreator<AssetLeaderboard>> CreateLoader(MemoryManager& memory, ISearchPath& searchPath);
|
||||
} // namespace IW5::leaderboard
|
||||
|
@@ -35,10 +35,10 @@ namespace
|
||||
};
|
||||
} // namespace
|
||||
|
||||
namespace IW5
|
||||
namespace IW5::localize
|
||||
{
|
||||
std::unique_ptr<AssetCreator<AssetLocalize>> CreateLocalizeLoader(MemoryManager& memory, ISearchPath& searchPath, Zone& zone)
|
||||
std::unique_ptr<AssetCreator<AssetLocalize>> CreateLoader(MemoryManager& memory, ISearchPath& searchPath, Zone& zone)
|
||||
{
|
||||
return std::make_unique<LocalizeLoader>(memory, searchPath, zone);
|
||||
}
|
||||
} // namespace IW5
|
||||
} // namespace IW5::localize
|
||||
|
@@ -8,7 +8,7 @@
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace IW5
|
||||
namespace IW5::localize
|
||||
{
|
||||
std::unique_ptr<AssetCreator<AssetLocalize>> CreateLocalizeLoader(MemoryManager& memory, ISearchPath& searchPath, Zone& zone);
|
||||
} // namespace IW5
|
||||
std::unique_ptr<AssetCreator<AssetLocalize>> CreateLoader(MemoryManager& memory, ISearchPath& searchPath, Zone& zone);
|
||||
} // namespace IW5::localize
|
||||
|
@@ -8,6 +8,7 @@
|
||||
#include <iostream>
|
||||
|
||||
using namespace IW5;
|
||||
using namespace ::material;
|
||||
|
||||
namespace
|
||||
{
|
||||
@@ -22,7 +23,7 @@ namespace
|
||||
|
||||
AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override
|
||||
{
|
||||
const auto file = m_search_path.Open(material::GetFileNameForAssetName(assetName));
|
||||
const auto file = m_search_path.Open(GetFileNameForAssetName(assetName));
|
||||
if (!file.IsOpen())
|
||||
return AssetCreationResult::NoAction();
|
||||
|
||||
@@ -45,10 +46,10 @@ namespace
|
||||
};
|
||||
} // namespace
|
||||
|
||||
namespace IW5
|
||||
namespace IW5::material
|
||||
{
|
||||
std::unique_ptr<AssetCreator<AssetMaterial>> CreateMaterialLoader(MemoryManager& memory, ISearchPath& searchPath)
|
||||
std::unique_ptr<AssetCreator<AssetMaterial>> CreateLoader(MemoryManager& memory, ISearchPath& searchPath)
|
||||
{
|
||||
return std::make_unique<MaterialLoader>(memory, searchPath);
|
||||
}
|
||||
} // namespace IW5
|
||||
} // namespace IW5::material
|
||||
|
@@ -7,7 +7,7 @@
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace IW5
|
||||
namespace IW5::material
|
||||
{
|
||||
std::unique_ptr<AssetCreator<AssetMaterial>> CreateMaterialLoader(MemoryManager& memory, ISearchPath& searchPath);
|
||||
} // namespace IW5
|
||||
std::unique_ptr<AssetCreator<AssetMaterial>> CreateLoader(MemoryManager& memory, ISearchPath& searchPath);
|
||||
} // namespace IW5::material
|
||||
|
@@ -11,6 +11,7 @@
|
||||
#include <iostream>
|
||||
|
||||
using namespace IW5;
|
||||
using namespace ::menu;
|
||||
|
||||
namespace
|
||||
{
|
||||
@@ -28,7 +29,7 @@ namespace
|
||||
std::vector<menuDef_t*> menus;
|
||||
AssetRegistration<AssetMenuList> registration(assetName);
|
||||
|
||||
auto& zoneState = context.GetZoneAssetCreationState<menu::MenuAssetZoneState>();
|
||||
auto& zoneState = context.GetZoneAssetCreationState<MenuAssetZoneState>();
|
||||
auto& conversionState = context.GetZoneAssetCreationState<MenuConversionZoneState>();
|
||||
|
||||
std::deque<std::string> menuLoadQueue;
|
||||
@@ -80,7 +81,7 @@ namespace
|
||||
private:
|
||||
bool LoadMenuFileFromQueue(const std::string& menuFilePath,
|
||||
AssetCreationContext& context,
|
||||
menu::MenuAssetZoneState& zoneState,
|
||||
MenuAssetZoneState& zoneState,
|
||||
MenuConversionZoneState& conversionState,
|
||||
std::vector<menuDef_t*>& menus,
|
||||
AssetRegistration<AssetMenuList>& registration) const
|
||||
@@ -121,8 +122,8 @@ namespace
|
||||
|
||||
bool ProcessParsedResults(const std::string& fileName,
|
||||
AssetCreationContext& context,
|
||||
menu::ParsingResult& parsingResult,
|
||||
menu::MenuAssetZoneState& zoneState,
|
||||
ParsingResult& parsingResult,
|
||||
MenuAssetZoneState& zoneState,
|
||||
MenuConversionZoneState& conversionState,
|
||||
std::vector<menuDef_t*>& menus,
|
||||
AssetRegistration<AssetMenuList>& registration) const
|
||||
@@ -196,10 +197,9 @@ namespace
|
||||
menuList.menus = nullptr;
|
||||
}
|
||||
|
||||
std::unique_ptr<menu::ParsingResult>
|
||||
ParseMenuFile(std::istream& stream, const std::string& menuFileName, const menu::MenuAssetZoneState& zoneState) const
|
||||
std::unique_ptr<ParsingResult> ParseMenuFile(std::istream& stream, const std::string& menuFileName, const MenuAssetZoneState& zoneState) const
|
||||
{
|
||||
menu::MenuFileReader reader(stream, menuFileName, menu::FeatureLevel::IW5, m_search_path);
|
||||
MenuFileReader reader(stream, menuFileName, FeatureLevel::IW5, m_search_path);
|
||||
|
||||
reader.IncludeZoneState(zoneState);
|
||||
reader.SetPermissiveMode(ObjLoading::Configuration.MenuPermissiveParsing);
|
||||
@@ -212,10 +212,10 @@ namespace
|
||||
};
|
||||
} // namespace
|
||||
|
||||
namespace IW5
|
||||
namespace IW5::menu
|
||||
{
|
||||
std::unique_ptr<AssetCreator<AssetMenuList>> CreateMenuListLoader(MemoryManager& memory, ISearchPath& searchPath)
|
||||
{
|
||||
return std::make_unique<MenuListLoader>(memory, searchPath);
|
||||
}
|
||||
} // namespace IW5
|
||||
} // namespace IW5::menu
|
||||
|
@@ -7,7 +7,7 @@
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace IW5
|
||||
namespace IW5::menu
|
||||
{
|
||||
std::unique_ptr<AssetCreator<AssetMenuList>> CreateMenuListLoader(MemoryManager& memory, ISearchPath& searchPath);
|
||||
} // namespace IW5
|
||||
} // namespace IW5::menu
|
||||
|
@@ -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);
|
||||
};
|
||||
|
@@ -126,12 +126,12 @@ namespace
|
||||
// collection.AddAssetCreator(std::make_unique<AssetLoaderXAnim>(memory));
|
||||
// collection.AddAssetCreator(std::make_unique<AssetLoaderXModelSurfs>(memory));
|
||||
collection.AddAssetCreator(xmodel::CreateXModelLoader(memory, searchPath, zone));
|
||||
collection.AddAssetCreator(CreateMaterialLoader(memory, searchPath));
|
||||
collection.AddAssetCreator(material::CreateLoader(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::CreateLoader(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::CreateMenuListLoader(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::CreateLoader(memory, searchPath, zone));
|
||||
collection.AddAssetCreator(attachment::CreateLoader(memory, searchPath));
|
||||
collection.AddAssetCreator(weapon::CreateRawLoader(memory, searchPath, zone));
|
||||
collection.AddAssetCreator(weapon::CreateGdtLoader(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::CreateLoader(memory, searchPath));
|
||||
collection.AddAssetCreator(script::CreateLoader(memory, searchPath));
|
||||
collection.AddAssetCreator(string_table::CreateLoader(memory, searchPath));
|
||||
collection.AddAssetCreator(leaderboard::CreateLoader(memory, searchPath));
|
||||
// collection.AddAssetCreator(std::make_unique<AssetLoaderStructuredDataDef>(memory));
|
||||
// collection.AddAssetCreator(std::make_unique<AssetLoaderTracer>(memory));
|
||||
// collection.AddAssetCreator(std::make_unique<AssetLoaderVehicle>(memory));
|
||||
|
@@ -81,10 +81,10 @@ namespace
|
||||
};
|
||||
} // namespace
|
||||
|
||||
namespace IW5
|
||||
namespace IW5::raw_file
|
||||
{
|
||||
std::unique_ptr<AssetCreator<AssetRawFile>> CreateRawFileLoader(MemoryManager& memory, ISearchPath& searchPath)
|
||||
std::unique_ptr<AssetCreator<AssetRawFile>> CreateLoader(MemoryManager& memory, ISearchPath& searchPath)
|
||||
{
|
||||
return std::make_unique<RawFileLoader>(memory, searchPath);
|
||||
}
|
||||
} // namespace IW5
|
||||
} // namespace IW5::raw_file
|
||||
|
@@ -7,7 +7,7 @@
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace IW5
|
||||
namespace IW5::raw_file
|
||||
{
|
||||
std::unique_ptr<AssetCreator<AssetRawFile>> CreateRawFileLoader(MemoryManager& memory, ISearchPath& searchPath);
|
||||
} // namespace IW5
|
||||
std::unique_ptr<AssetCreator<AssetRawFile>> CreateLoader(MemoryManager& memory, ISearchPath& searchPath);
|
||||
} // namespace IW5::raw_file
|
||||
|
@@ -79,10 +79,10 @@ namespace
|
||||
};
|
||||
} // namespace
|
||||
|
||||
namespace IW5
|
||||
namespace IW5::script
|
||||
{
|
||||
std::unique_ptr<AssetCreator<AssetScript>> CreateScriptLoader(MemoryManager& memory, ISearchPath& searchPath)
|
||||
std::unique_ptr<AssetCreator<AssetScript>> CreateLoader(MemoryManager& memory, ISearchPath& searchPath)
|
||||
{
|
||||
return std::make_unique<ScriptLoader>(memory, searchPath);
|
||||
}
|
||||
} // namespace IW5
|
||||
} // namespace IW5::script
|
||||
|
@@ -7,7 +7,7 @@
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace IW5
|
||||
namespace IW5::script
|
||||
{
|
||||
std::unique_ptr<AssetCreator<AssetScript>> CreateScriptLoader(MemoryManager& memory, ISearchPath& searchPath);
|
||||
} // namespace IW5
|
||||
std::unique_ptr<AssetCreator<AssetScript>> CreateLoader(MemoryManager& memory, ISearchPath& searchPath);
|
||||
} // namespace IW5::script
|
||||
|
@@ -10,6 +10,7 @@
|
||||
#include <cstring>
|
||||
|
||||
using namespace IW5;
|
||||
using namespace ::string_table;
|
||||
|
||||
namespace
|
||||
{
|
||||
@@ -28,7 +29,7 @@ namespace
|
||||
if (!file.IsOpen())
|
||||
return AssetCreationResult::NoAction();
|
||||
|
||||
string_table::StringTableLoaderV2<StringTable, Common::StringTable_HashString> loader;
|
||||
StringTableLoaderV2<StringTable, Common::StringTable_HashString> loader;
|
||||
auto* stringTable = loader.LoadFromStream(assetName, m_memory, *file.m_stream);
|
||||
|
||||
return AssetCreationResult::Success(context.AddAsset<AssetStringTable>(assetName, stringTable));
|
||||
@@ -40,10 +41,10 @@ namespace
|
||||
};
|
||||
} // namespace
|
||||
|
||||
namespace IW5
|
||||
namespace IW5::string_table
|
||||
{
|
||||
std::unique_ptr<AssetCreator<AssetStringTable>> CreateStringTableLoader(MemoryManager& memory, ISearchPath& searchPath)
|
||||
std::unique_ptr<AssetCreator<AssetStringTable>> CreateLoader(MemoryManager& memory, ISearchPath& searchPath)
|
||||
{
|
||||
return std::make_unique<StringTableLoader>(memory, searchPath);
|
||||
}
|
||||
} // namespace IW5
|
||||
} // namespace IW5::string_table
|
||||
|
@@ -7,7 +7,7 @@
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace IW5
|
||||
namespace IW5::string_table
|
||||
{
|
||||
std::unique_ptr<AssetCreator<AssetStringTable>> CreateStringTableLoader(MemoryManager& memory, ISearchPath& searchPath);
|
||||
} // namespace IW5
|
||||
std::unique_ptr<AssetCreator<AssetStringTable>> CreateLoader(MemoryManager& memory, ISearchPath& searchPath);
|
||||
} // namespace IW5::string_table
|
||||
|
@@ -40,14 +40,14 @@ namespace
|
||||
|
||||
private:
|
||||
IGdtQueryable& m_gdt;
|
||||
InfoStringLoaderWeapon m_info_string_loader;
|
||||
IW5::weapon::InfoStringLoader m_info_string_loader;
|
||||
};
|
||||
} // namespace
|
||||
|
||||
namespace IW5
|
||||
namespace IW5::weapon
|
||||
{
|
||||
std::unique_ptr<AssetCreator<AssetWeapon>> CreateGdtWeaponLoader(MemoryManager& memory, ISearchPath& searchPath, IGdtQueryable& gdt, Zone& zone)
|
||||
std::unique_ptr<AssetCreator<AssetWeapon>> CreateGdtLoader(MemoryManager& memory, ISearchPath& searchPath, IGdtQueryable& gdt, Zone& zone)
|
||||
{
|
||||
return std::make_unique<GdtLoaderWeapon>(memory, searchPath, gdt, zone);
|
||||
}
|
||||
} // namespace IW5
|
||||
} // namespace IW5::weapon
|
||||
|
@@ -8,7 +8,7 @@
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace IW5
|
||||
namespace IW5::weapon
|
||||
{
|
||||
std::unique_ptr<AssetCreator<AssetWeapon>> CreateGdtWeaponLoader(MemoryManager& memory, ISearchPath& searchPath, IGdtQueryable& gdt, Zone& zone);
|
||||
} // namespace IW5
|
||||
std::unique_ptr<AssetCreator<AssetWeapon>> CreateGdtLoader(MemoryManager& memory, ISearchPath& searchPath, IGdtQueryable& gdt, Zone& zone);
|
||||
} // namespace IW5::weapon
|
||||
|
@@ -856,33 +856,36 @@ namespace
|
||||
}
|
||||
} // namespace
|
||||
|
||||
InfoStringLoaderWeapon::InfoStringLoaderWeapon(MemoryManager& memory, ISearchPath& searchPath, Zone& zone)
|
||||
: m_memory(memory),
|
||||
m_search_path(searchPath),
|
||||
m_zone(zone)
|
||||
namespace IW5::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())
|
||||
InfoStringLoader::InfoStringLoader(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 InfoStringLoader::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())
|
||||
{
|
||||
std::cerr << std::format("Failed to parse weapon: \"{}\"\n", 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 IW5::weapon
|
||||
|
@@ -4,12 +4,12 @@
|
||||
#include "Asset/AssetCreationResult.h"
|
||||
#include "InfoString/InfoString.h"
|
||||
|
||||
namespace IW5
|
||||
namespace IW5::weapon
|
||||
{
|
||||
class InfoStringLoaderWeapon
|
||||
class InfoStringLoader
|
||||
{
|
||||
public:
|
||||
InfoStringLoaderWeapon(MemoryManager& memory, ISearchPath& searchPath, Zone& zone);
|
||||
InfoStringLoader(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 IW5::weapon
|
||||
|
@@ -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
|
||||
{
|
||||
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)
|
||||
{
|
||||
std::cerr << "Tried to load attachment \"" << attachment.szInternalName << "\" but did not find expected type attachment of version 1\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
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
|
@@ -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
|
@@ -1,16 +1,637 @@
|
||||
#include "LoaderAttachmentIW5.h"
|
||||
|
||||
#include "Game/IW5/IW5.h"
|
||||
#include "JsonWeaponAttachmentLoader.h"
|
||||
#include "Game/IW5/Weapon/JsonWeaponAttachment.h"
|
||||
#include "Weapon/AttachmentCommon.h"
|
||||
|
||||
#include <cstring>
|
||||
#include <format>
|
||||
#include <iostream>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
using namespace nlohmann;
|
||||
using namespace IW5;
|
||||
using namespace ::attachment;
|
||||
|
||||
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)
|
||||
{
|
||||
std::cerr << "Tried to load attachment \"" << attachment.szInternalName << "\" but did not find expected type attachment of version 1\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
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(GetJsonFileNameForAssetName(assetName));
|
||||
if (!file.IsOpen())
|
||||
return AssetCreationResult::NoAction();
|
||||
|
||||
@@ -30,7 +651,8 @@ 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);
|
||||
return AssetCreationResult::Failure();
|
||||
@@ -45,10 +667,10 @@ namespace
|
||||
};
|
||||
} // namespace
|
||||
|
||||
namespace IW5
|
||||
namespace IW5::attachment
|
||||
{
|
||||
std::unique_ptr<AssetCreator<AssetAttachment>> CreateAttachmentLoader(MemoryManager& memory, ISearchPath& searchPath)
|
||||
std::unique_ptr<AssetCreator<AssetAttachment>> CreateLoader(MemoryManager& memory, ISearchPath& searchPath)
|
||||
{
|
||||
return std::make_unique<AttachmentLoader>(memory, searchPath);
|
||||
}
|
||||
} // namespace IW5
|
||||
} // namespace IW5::attachment
|
||||
|
@@ -7,7 +7,7 @@
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace IW5
|
||||
namespace IW5::attachment
|
||||
{
|
||||
std::unique_ptr<AssetCreator<AssetAttachment>> CreateAttachmentLoader(MemoryManager& memory, ISearchPath& searchPath);
|
||||
} // namespace IW5
|
||||
std::unique_ptr<AssetCreator<AssetAttachment>> CreateLoader(MemoryManager& memory, ISearchPath& searchPath);
|
||||
} // namespace IW5::attachment
|
||||
|
@@ -4,12 +4,14 @@
|
||||
#include "Game/IW5/ObjConstantsIW5.h"
|
||||
#include "InfoString/InfoString.h"
|
||||
#include "InfoStringLoaderWeaponIW5.h"
|
||||
#include "Weapon/WeaponCommon.h"
|
||||
|
||||
#include <cstring>
|
||||
#include <format>
|
||||
#include <iostream>
|
||||
|
||||
using namespace IW5;
|
||||
using namespace ::weapon;
|
||||
|
||||
namespace
|
||||
{
|
||||
@@ -24,7 +26,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();
|
||||
@@ -41,14 +43,14 @@ namespace
|
||||
|
||||
private:
|
||||
ISearchPath& m_search_path;
|
||||
InfoStringLoaderWeapon m_info_string_loader;
|
||||
IW5::weapon::InfoStringLoader m_info_string_loader;
|
||||
};
|
||||
} // namespace
|
||||
|
||||
namespace IW5
|
||||
namespace IW5::weapon
|
||||
{
|
||||
std::unique_ptr<AssetCreator<AssetWeapon>> CreateRawWeaponLoader(MemoryManager& memory, ISearchPath& searchPath, Zone& zone)
|
||||
std::unique_ptr<AssetCreator<AssetWeapon>> CreateRawLoader(MemoryManager& memory, ISearchPath& searchPath, Zone& zone)
|
||||
{
|
||||
return std::make_unique<RawLoaderWeapon>(memory, searchPath, zone);
|
||||
}
|
||||
} // namespace IW5
|
||||
} // namespace IW5::weapon
|
||||
|
@@ -7,7 +7,7 @@
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace IW5
|
||||
namespace IW5::weapon
|
||||
{
|
||||
std::unique_ptr<AssetCreator<AssetWeapon>> CreateRawWeaponLoader(MemoryManager& memory, ISearchPath& searchPath, Zone& zone);
|
||||
} // namespace IW5
|
||||
std::unique_ptr<AssetCreator<AssetWeapon>> CreateRawLoader(MemoryManager& memory, ISearchPath& searchPath, Zone& zone);
|
||||
} // namespace IW5::weapon
|
||||
|
@@ -26,7 +26,7 @@ namespace
|
||||
IgnoredAssetLookup ignoredAssetLookup;
|
||||
AssetCreationContext context(zone, &creatorCollection, &ignoredAssetLookup);
|
||||
|
||||
auto loader = CreateStringTableLoader(memory, searchPath);
|
||||
auto loader = string_table::CreateLoader(memory, searchPath);
|
||||
auto result = loader->CreateAsset("mp/cooltable.csv", context);
|
||||
REQUIRE(result.HasBeenSuccessful());
|
||||
|
||||
|
@@ -313,7 +313,7 @@ namespace
|
||||
GivenImage("me_metal_rusty02_col", context, memory);
|
||||
GivenTechset("wc_l_sm_r0c0n0s0", context, memory);
|
||||
|
||||
auto loader = CreateMaterialLoader(memory, searchPath);
|
||||
auto loader = material::CreateLoader(memory, searchPath);
|
||||
auto result = loader->CreateAsset("wc/me_metal_rust_02", context);
|
||||
REQUIRE(result.HasBeenSuccessful());
|
||||
|
||||
|
Reference in New Issue
Block a user