chore: fix loading and writing code for T6

This commit is contained in:
Jan 2024-12-31 12:38:01 +01:00
parent d8bc156ffd
commit 83d13aa166
No known key found for this signature in database
GPG Key ID: 44B581F78FF5C57C
193 changed files with 4129 additions and 4208 deletions

View File

@ -81,4 +81,17 @@ namespace T6
{"c4_yaw", offsetof(PhysConstraints, data[3].scale.y), CSPFT_FLOAT },
{"c4_pitch", offsetof(PhysConstraints, data[3].scale.x), CSPFT_FLOAT },
};
}
inline const char* s_constraintTypeNames[]{
"none",
"point",
"distance",
"hinge",
"joint",
"actuator",
"fake_shake",
"launch",
"rope",
"light",
};
} // namespace T6

View File

@ -36,4 +36,9 @@ namespace T6
{"colorB4", offsetof(TracerDef, colors[4].b), CSPFT_FLOAT },
{"colorA4", offsetof(TracerDef, colors[4].a), CSPFT_FLOAT },
};
}
inline const char* tracerTypeNames[]{
"Laser",
"Smoke",
};
} // namespace T6

View File

@ -561,4 +561,31 @@ namespace T6
{"customBool1", offsetof(VehicleDef, customBool1), CSPFT_BOOL },
{"customBool2", offsetof(VehicleDef, customBool2), CSPFT_BOOL },
};
}
inline const char* s_vehicleClassNames[]{
"4 wheel",
"motorcycle",
"tank",
"plane",
"boat",
"artillery",
"helicopter",
};
inline const char* s_vehicleCameraModes[]{
"first",
"chase",
"view",
"strafe",
"horse",
"oldtank",
"hover",
"vtol",
};
inline const char* s_tractionTypeNames[]{
"TRACTION_TYPE_FRONT",
"TRACTION_TYPE_BACK",
"TRACTION_TYPE_ALL_WD",
};
} // namespace T6

View File

@ -81,4 +81,4 @@ namespace T6
{"customBool1", offsetof(WeaponAttachment, customBool1), CSPFT_BOOL },
{"customBool2", offsetof(WeaponAttachment, customBool2), CSPFT_BOOL },
};
}
} // namespace T6

View File

@ -206,4 +206,4 @@ namespace T6
{"customBool1", offsetof(WeaponAttachmentUniqueFull, attachment.customBool1), CSPFT_BOOL },
{"customBool2", offsetof(WeaponAttachmentUniqueFull, attachment.customBool2), CSPFT_BOOL },
};
}
} // namespace T6

View File

@ -36,31 +36,11 @@ namespace T6
"crosshair",
};
inline const char* szWeapInventoryTypeNames[]{
"primary",
"offhand",
"item",
"altmode",
"melee",
"dwlefthand",
};
inline const char* szWeapClipTypeNames[]{
"bottom",
"top",
"left",
"dp28",
"ptrs",
"lmg",
};
inline const char* barrelTypeNames[]{
"Single",
"Dual Barrel",
"Dual Barrel Alternate",
"Quad Barrel",
"Quad Barrel Alternate",
"Quad Barrel Double Alternate",
inline const char* penetrateTypeNames[]{
"none",
"small",
"medium",
"large",
};
inline const char* impactTypeNames[]{
@ -165,6 +145,37 @@ namespace T6
"Turret Scope",
};
inline const char* szWeapInventoryTypeNames[]{
"primary",
"offhand",
"item",
"altmode",
"melee",
"dwlefthand",
};
inline const char* szWeapFireTypeNames[]{
"Full Auto",
"Single Shot",
"2-Round Burst",
"3-Round Burst",
"4-Round Burst",
"5-Round Burst",
"Stacked Fire",
"Minigun",
"Charge Shot",
"Jetgun",
};
inline const char* szWeapClipTypeNames[]{
"bottom",
"top",
"left",
"dp28",
"ptrs",
"lmg",
};
inline const char* ammoCounterClipNames[]{
"None",
"Magazine",
@ -181,75 +192,13 @@ namespace T6
"4:1",
};
inline const char* szAttachmentTypeNames[]{
"none", "acog", "dualclip", "dualoptic", "dw", "extbarrel", "extclip", "extramags", "fastads", "fastreload",
"fmj", "gl", "grip", "holo", "ir", "is", "longbreath", "mk", "mms", "rangefinder",
"reflex", "rf", "sf", "silencer", "stackfire", "stalker", "steadyaim", "swayreduc", "tacknife", "vzoom",
};
inline const char* szWeapFireTypeNames[]{
"Full Auto",
"Single Shot",
"2-Round Burst",
"3-Round Burst",
"4-Round Burst",
"5-Round Burst",
"Stacked Fire",
"Minigun",
"Charge Shot",
"Jetgun",
};
inline const char* penetrateTypeNames[]{
"none",
"small",
"medium",
"large",
};
inline const char* s_constraintTypeNames[]{
"none",
"point",
"distance",
"hinge",
"joint",
"actuator",
"fake_shake",
"launch",
"rope",
"light",
};
inline const char* s_vehicleClassNames[]{
"4 wheel",
"motorcycle",
"tank",
"plane",
"boat",
"artillery",
"helicopter",
};
inline const char* s_vehicleCameraModes[]{
"first",
"chase",
"view",
"strafe",
"horse",
"oldtank",
"hover",
"vtol",
};
inline const char* s_tractionTypeNames[]{
"TRACTION_TYPE_FRONT",
"TRACTION_TYPE_BACK",
"TRACTION_TYPE_ALL_WD",
};
inline const char* tracerTypeNames[]{
"Laser",
"Smoke",
inline const char* barrelTypeNames[]{
"Single",
"Dual Barrel",
"Dual Barrel Alternate",
"Quad Barrel",
"Quad Barrel Alternate",
"Quad Barrel Double Alternate",
};
inline const char* bounceSoundSuffixes[]{
@ -257,4 +206,10 @@ namespace T6
"_gravel", "_ice", "_metal", "_mud", "_paper", "_plaster", "_rock", "_sand", "_snow", "_water", "_wood",
"_asphalt", "_ceramic", "_plastic", "_rubber", "_cushion", "_fruit", "_paintedmetal", "_player", "_tallgrass", "_riotshield",
};
inline const char* szAttachmentTypeNames[]{
"none", "acog", "dualclip", "dualoptic", "dw", "extbarrel", "extclip", "extramags", "fastads", "fastreload",
"fmj", "gl", "grip", "holo", "ir", "is", "longbreath", "mk", "mms", "rangefinder",
"reflex", "rf", "sf", "silencer", "stackfire", "stalker", "steadyaim", "swayreduc", "tacknife", "vzoom",
};
} // namespace T6

View File

@ -1,13 +0,0 @@
#include "AssetLoaderAddonMapEnts.h"
#include "Game/T6/T6.h"
#include "ObjLoading.h"
using namespace T6;
void* AssetLoaderAddonMapEnts::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
{
auto* asset = memory->Alloc<AssetAddonMapEnts::Type>();
asset->name = memory->Dup(assetName.c_str());
return asset;
}

View File

@ -1,14 +0,0 @@
#pragma once
#include "AssetLoading/BasicAssetLoader.h"
#include "Game/T6/T6.h"
#include "SearchPath/ISearchPath.h"
namespace T6
{
class AssetLoaderAddonMapEnts final : public BasicAssetLoader<AssetAddonMapEnts>
{
public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
};
} // namespace T6

View File

@ -1,23 +0,0 @@
#include "AssetLoaderClipMap.h"
#include "Game/T6/T6.h"
#include "ObjLoading.h"
using namespace T6;
void* AssetLoaderClipMapBase::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
{
auto* asset = memory->Alloc<clipMap_t>();
asset->name = memory->Dup(assetName.c_str());
return asset;
}
asset_type_t AssetLoaderClipMap::GetHandlingAssetType() const
{
return ASSET_TYPE_CLIPMAP;
}
asset_type_t AssetLoaderClipMapPvs::GetHandlingAssetType() const
{
return ASSET_TYPE_CLIPMAP_PVS;
}

View File

@ -1,26 +0,0 @@
#pragma once
#include "AssetLoading/BasicAssetLoader.h"
#include "Game/T6/T6.h"
#include "SearchPath/ISearchPath.h"
namespace T6
{
class AssetLoaderClipMapBase : public BasicAssetLoaderWithoutType<clipMap_t>
{
public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
};
class AssetLoaderClipMap final : public AssetLoaderClipMapBase
{
public:
[[nodiscard]] asset_type_t GetHandlingAssetType() const override;
};
class AssetLoaderClipMapPvs final : public AssetLoaderClipMapBase
{
public:
[[nodiscard]] asset_type_t GetHandlingAssetType() const override;
};
} // namespace T6

View File

@ -1,13 +0,0 @@
#include "AssetLoaderComWorld.h"
#include "Game/T6/T6.h"
#include "ObjLoading.h"
using namespace T6;
void* AssetLoaderComWorld::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
{
auto* asset = memory->Alloc<AssetComWorld::Type>();
asset->name = memory->Dup(assetName.c_str());
return asset;
}

View File

@ -1,14 +0,0 @@
#pragma once
#include "AssetLoading/BasicAssetLoader.h"
#include "Game/T6/T6.h"
#include "SearchPath/ISearchPath.h"
namespace T6
{
class AssetLoaderComWorld final : public BasicAssetLoader<AssetComWorld>
{
public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
};
} // namespace T6

View File

@ -1,13 +0,0 @@
#include "AssetLoaderDDL.h"
#include "Game/T6/T6.h"
#include "ObjLoading.h"
using namespace T6;
void* AssetLoaderDDL::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
{
auto* asset = memory->Alloc<AssetDDL::Type>();
asset->name = memory->Dup(assetName.c_str());
return asset;
}

View File

@ -1,14 +0,0 @@
#pragma once
#include "AssetLoading/BasicAssetLoader.h"
#include "Game/T6/T6.h"
#include "SearchPath/ISearchPath.h"
namespace T6
{
class AssetLoaderDDL final : public BasicAssetLoader<AssetDDL>
{
public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
};
} // namespace T6

View File

@ -1,13 +0,0 @@
#include "AssetLoaderDestructibleDef.h"
#include "Game/T6/T6.h"
#include "ObjLoading.h"
using namespace T6;
void* AssetLoaderDestructibleDef::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
{
auto* asset = memory->Alloc<AssetDestructibleDef::Type>();
asset->name = memory->Dup(assetName.c_str());
return asset;
}

View File

@ -1,14 +0,0 @@
#pragma once
#include "AssetLoading/BasicAssetLoader.h"
#include "Game/T6/T6.h"
#include "SearchPath/ISearchPath.h"
namespace T6
{
class AssetLoaderDestructibleDef final : public BasicAssetLoader<AssetDestructibleDef>
{
public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
};
} // namespace T6

View File

@ -1,13 +0,0 @@
#include "AssetLoaderEmblemSet.h"
#include "Game/T6/T6.h"
#include "ObjLoading.h"
using namespace T6;
void* AssetLoaderEmblemSet::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
{
// Asset does not have a name
// So this cannot be an asset reference
return nullptr;
}

View File

@ -1,14 +0,0 @@
#pragma once
#include "AssetLoading/BasicAssetLoader.h"
#include "Game/T6/T6.h"
#include "SearchPath/ISearchPath.h"
namespace T6
{
class AssetLoaderEmblemSet final : public BasicAssetLoader<AssetEmblemSet>
{
public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
};
} // namespace T6

View File

@ -1,13 +0,0 @@
#include "AssetLoaderFont.h"
#include "Game/T6/T6.h"
#include "ObjLoading.h"
using namespace T6;
void* AssetLoaderFont::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
{
auto* asset = memory->Alloc<AssetFont::Type>();
asset->fontName = memory->Dup(assetName.c_str());
return asset;
}

View File

@ -1,14 +0,0 @@
#pragma once
#include "AssetLoading/BasicAssetLoader.h"
#include "Game/T6/T6.h"
#include "SearchPath/ISearchPath.h"
namespace T6
{
class AssetLoaderFont final : public BasicAssetLoader<AssetFont>
{
public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
};
} // namespace T6

View File

@ -1,270 +0,0 @@
#include "AssetLoaderFontIcon.h"
#include "Csv/CsvStream.h"
#include "Game/T6/CommonT6.h"
#include "Game/T6/T6.h"
#include "Pool/GlobalAssetPool.h"
#include <algorithm>
#include <cstring>
#include <sstream>
using namespace T6;
void* AssetLoaderFontIcon::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
{
auto* asset = memory->Alloc<AssetFontIcon::Type>();
asset->name = memory->Dup(assetName.c_str());
return asset;
}
bool AssetLoaderFontIcon::CanLoadFromRaw() const
{
return true;
}
std::string AssetLoaderFontIcon::ErrorPrefix(const std::string& assetName, const unsigned rowIndex)
{
std::ostringstream str;
str << "FontIcon \"" << assetName << "\" Row " << rowIndex << ": ";
return str.str();
}
void AssetLoaderFontIcon::PreprocessRow(std::vector<std::string>& row)
{
for (auto& cell : row)
{
for (auto c : cell)
{
if (isspace(c))
continue;
if (c == '#')
cell = "";
break;
}
}
}
bool AssetLoaderFontIcon::RowIsEmpty(const std::vector<std::string>& row)
{
return std::ranges::all_of(row,
[](const std::string& cell)
{
return cell.empty();
});
}
bool AssetLoaderFontIcon::ParseInt(int& value, const std::string& str)
{
char* endPtr;
value = strtol(str.c_str(), &endPtr, 0);
if (endPtr != &str[str.size()])
return false;
return true;
}
bool AssetLoaderFontIcon::ParseFloat(float& value, const std::string& str)
{
char* endPtr;
value = strtof(str.c_str(), &endPtr);
if (endPtr != &str[str.size()])
return false;
return true;
}
bool AssetLoaderFontIcon::ParseHashStr(int& value, const std::string& str)
{
if (!str.empty() && str[0] == '@' && str.size() > 1)
{
char* endPtr;
value = strtol(&str[1], &endPtr, 16);
if (endPtr != &str[str.size()])
return false;
}
else
{
value = Common::Com_HashString(str.c_str());
}
return true;
}
bool AssetLoaderFontIcon::ReadIconRow(const std::vector<std::string>& row,
FontIconEntry& icon,
const std::string& assetName,
const unsigned rowIndex,
MemoryManager* memory,
IAssetLoadingManager* manager,
std::vector<XAssetInfoGeneric*>& dependencies)
{
if (row.size() < COL_COUNT_ICON)
{
std::cout << ErrorPrefix(assetName, rowIndex) << "Column count lower than min column count for entries (" << COL_COUNT_ICON << ")\n";
return false;
}
if (!ParseInt(icon.fontIconSize, row[ROW_ICON_SIZE]))
{
std::cout << ErrorPrefix(assetName, rowIndex) << "Failed to parse size\n";
return false;
}
if (!ParseFloat(icon.xScale, row[ROW_ICON_XSCALE]) || !ParseFloat(icon.yScale, row[ROW_ICON_YSCALE]))
{
std::cout << ErrorPrefix(assetName, rowIndex) << "Failed to parse scale\n";
return false;
}
auto* materialDependency = manager->LoadDependency<AssetMaterial>(row[ROW_ICON_MATERIAL]);
if (materialDependency == nullptr)
{
std::cout << ErrorPrefix(assetName, rowIndex) << "Failed to load material \"" << row[ROW_ICON_MATERIAL] << "\"\n";
return false;
}
icon.fontIconMaterialHandle = materialDependency->Asset();
icon.fontIconName.string = memory->Dup(row[ROW_ICON_NAME].c_str());
icon.fontIconName.hash = Common::Com_HashString(icon.fontIconName.string);
return true;
}
bool AssetLoaderFontIcon::ReadAliasRow(const std::vector<std::string>& row,
FontIconAlias& alias,
const std::string& assetName,
const unsigned rowIndex,
MemoryManager* memory,
IAssetLoadingManager* manager)
{
if (row.size() < COL_COUNT_ALIAS)
{
std::cout << ErrorPrefix(assetName, rowIndex) << "Column count lower than min column count for aliases (" << COL_COUNT_ALIAS << ")\n";
return false;
}
if (!ParseHashStr(alias.aliasHash, row[ROW_ALIAS_NAME]))
{
std::cout << ErrorPrefix(assetName, rowIndex) << "Failed to parse alias \"" << row[ROW_ALIAS_NAME] << "\"\n";
return false;
}
if (!ParseHashStr(alias.buttonHash, row[ROW_ALIAS_BUTTON]))
{
std::cout << ErrorPrefix(assetName, rowIndex) << "Failed to parse button \"" << row[ROW_ALIAS_BUTTON] << "\"\n";
return false;
}
return true;
}
bool AssetLoaderFontIcon::LoadFromRaw(
const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const
{
const auto file = searchPath->Open(assetName);
if (!file.IsOpen())
return false;
auto* fontIcon = memory->Create<FontIcon>();
fontIcon->name = memory->Dup(assetName.c_str());
const CsvInputStream csv(*file.m_stream);
std::vector<XAssetInfoGeneric*> dependencies;
std::vector<std::string> currentRow;
std::vector<FontIconEntry> entries;
std::vector<FontIconAlias> aliases;
auto currentRowIndex = 0u;
while (csv.NextRow(currentRow))
{
currentRowIndex++;
PreprocessRow(currentRow);
if (RowIsEmpty(currentRow))
continue;
if (currentRow.size() < COL_COUNT_MIN)
{
std::cout << ErrorPrefix(assetName, currentRowIndex) << "Column count lower than min column count (" << COL_COUNT_MIN << ")\n";
return true;
}
int index;
if (!ParseInt(index, currentRow[ROW_INDEX]) || index < 0)
{
std::cout << ErrorPrefix(assetName, currentRowIndex) << "Failed to parse index\n";
return true;
}
if (currentRow[ROW_TYPE] == VALUE_TYPE_ICON)
{
FontIconEntry icon{};
if (!ReadIconRow(currentRow, icon, assetName, currentRowIndex, memory, manager, dependencies))
return true;
if (static_cast<unsigned>(index) == entries.size())
{
entries.push_back(icon);
}
else if (static_cast<unsigned>(index) > entries.size())
{
entries.reserve(index + 1);
entries[index] = icon;
}
else
{
entries[index] = icon;
}
}
else if (currentRow[ROW_TYPE] == VALUE_TYPE_ALIAS)
{
FontIconAlias alias{};
if (!ReadAliasRow(currentRow, alias, assetName, currentRowIndex, memory, manager))
return true;
if (static_cast<unsigned>(index) == aliases.size())
{
aliases.push_back(alias);
}
else if (static_cast<unsigned>(index) > aliases.size())
{
aliases.reserve(index + 1);
aliases[index] = alias;
}
else
{
aliases[index] = alias;
}
}
else
{
std::cout << ErrorPrefix(assetName, currentRowIndex) << "Unknown row type \"" << currentRow[ROW_TYPE] << "\"\n";
return true;
}
}
fontIcon->numEntries = entries.size();
fontIcon->numAliasEntries = aliases.size();
if (fontIcon->numEntries > 0)
{
fontIcon->fontIconEntry = memory->Alloc<FontIconEntry>(fontIcon->numEntries);
for (auto i = 0u; i < entries.size(); i++)
fontIcon->fontIconEntry[i] = entries[i];
}
else
fontIcon->fontIconEntry = nullptr;
if (fontIcon->numAliasEntries > 0)
{
fontIcon->fontIconAlias = memory->Alloc<FontIconAlias>(fontIcon->numAliasEntries);
for (auto i = 0u; i < aliases.size(); i++)
fontIcon->fontIconAlias[i] = aliases[i];
}
else
fontIcon->fontIconAlias = nullptr;
manager->AddAsset<AssetFontIcon>(assetName, fontIcon);
return true;
}

View File

@ -1,63 +0,0 @@
#pragma once
#include "AssetLoading/BasicAssetLoader.h"
#include "AssetLoading/IAssetLoadingManager.h"
#include "Game/T6/T6.h"
#include "SearchPath/ISearchPath.h"
#include <algorithm>
#include <string>
#include <vector>
namespace T6
{
class AssetLoaderFontIcon final : public BasicAssetLoader<AssetFontIcon>
{
static constexpr unsigned ROW_INDEX = 0;
static constexpr unsigned ROW_TYPE = 1;
static constexpr unsigned ROW_ICON_NAME = 2;
static constexpr unsigned ROW_ICON_MATERIAL = 3;
static constexpr unsigned ROW_ICON_SIZE = 4;
static constexpr unsigned ROW_ICON_XSCALE = 5;
static constexpr unsigned ROW_ICON_YSCALE = 6;
static constexpr unsigned ROW_ALIAS_NAME = 2;
static constexpr unsigned ROW_ALIAS_BUTTON = 3;
static constexpr const char* VALUE_TYPE_ICON = "icon";
static constexpr const char* VALUE_TYPE_ALIAS = "alias";
static constexpr unsigned COL_COUNT_ICON = 7;
static constexpr unsigned COL_COUNT_ALIAS = 4;
static constexpr unsigned COL_COUNT_MIN = std::min(COL_COUNT_ICON, COL_COUNT_ALIAS);
static std::string ErrorPrefix(const std::string& assetName, unsigned rowIndex);
static void PreprocessRow(std::vector<std::string>& row);
static bool RowIsEmpty(const std::vector<std::string>& row);
static bool ParseInt(int& value, const std::string& str);
static bool ParseFloat(float& value, const std::string& str);
static bool ParseHashStr(int& value, const std::string& str);
static bool ReadIconRow(const std::vector<std::string>& row,
FontIconEntry& icon,
const std::string& assetName,
unsigned rowIndex,
MemoryManager* memory,
IAssetLoadingManager* manager,
std::vector<XAssetInfoGeneric*>& dependencies);
static bool ReadAliasRow(const std::vector<std::string>& row,
FontIconAlias& alias,
const std::string& assetName,
unsigned rowIndex,
MemoryManager* memory,
IAssetLoadingManager* manager);
public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
_NODISCARD bool CanLoadFromRaw() const override;
bool
LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override;
};
} // namespace T6

View File

@ -1,13 +0,0 @@
#include "AssetLoaderFootstepFxTable.h"
#include "Game/T6/T6.h"
#include "ObjLoading.h"
using namespace T6;
void* AssetLoaderFootstepFxTable::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
{
auto* asset = memory->Alloc<AssetFootstepFxTable::Type>();
asset->name = memory->Dup(assetName.c_str());
return asset;
}

View File

@ -1,14 +0,0 @@
#pragma once
#include "AssetLoading/BasicAssetLoader.h"
#include "Game/T6/T6.h"
#include "SearchPath/ISearchPath.h"
namespace T6
{
class AssetLoaderFootstepFxTable final : public BasicAssetLoader<AssetFootstepFxTable>
{
public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
};
} // namespace T6

View File

@ -1,13 +0,0 @@
#include "AssetLoaderFootstepTable.h"
#include "Game/T6/T6.h"
#include "ObjLoading.h"
using namespace T6;
void* AssetLoaderFootstepTable::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
{
auto* asset = memory->Alloc<AssetFootstepTable::Type>();
asset->name = memory->Dup(assetName.c_str());
return asset;
}

View File

@ -1,14 +0,0 @@
#pragma once
#include "AssetLoading/BasicAssetLoader.h"
#include "Game/T6/T6.h"
#include "SearchPath/ISearchPath.h"
namespace T6
{
class AssetLoaderFootstepTable final : public BasicAssetLoader<AssetFootstepTable>
{
public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
};
} // namespace T6

View File

@ -1,13 +0,0 @@
#include "AssetLoaderFx.h"
#include "Game/T6/T6.h"
#include "ObjLoading.h"
using namespace T6;
void* AssetLoaderFx::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
{
auto* asset = memory->Alloc<AssetFx::Type>();
asset->name = memory->Dup(assetName.c_str());
return asset;
}

View File

@ -1,14 +0,0 @@
#pragma once
#include "AssetLoading/BasicAssetLoader.h"
#include "Game/T6/T6.h"
#include "SearchPath/ISearchPath.h"
namespace T6
{
class AssetLoaderFx final : public BasicAssetLoader<AssetFx>
{
public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
};
} // namespace T6

View File

@ -1,13 +0,0 @@
#include "AssetLoaderGameWorldMp.h"
#include "Game/T6/T6.h"
#include "ObjLoading.h"
using namespace T6;
void* AssetLoaderGameWorldMp::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
{
auto* asset = memory->Alloc<AssetGameWorldMp::Type>();
asset->name = memory->Dup(assetName.c_str());
return asset;
}

View File

@ -1,14 +0,0 @@
#pragma once
#include "AssetLoading/BasicAssetLoader.h"
#include "Game/T6/T6.h"
#include "SearchPath/ISearchPath.h"
namespace T6
{
class AssetLoaderGameWorldMp final : public BasicAssetLoader<AssetGameWorldMp>
{
public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
};
} // namespace T6

View File

@ -1,13 +0,0 @@
#include "AssetLoaderGameWorldSp.h"
#include "Game/T6/T6.h"
#include "ObjLoading.h"
using namespace T6;
void* AssetLoaderGameWorldSp::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
{
auto* asset = memory->Alloc<AssetGameWorldSp::Type>();
asset->name = memory->Dup(assetName.c_str());
return asset;
}

View File

@ -1,14 +0,0 @@
#pragma once
#include "AssetLoading/BasicAssetLoader.h"
#include "Game/T6/T6.h"
#include "SearchPath/ISearchPath.h"
namespace T6
{
class AssetLoaderGameWorldSp final : public BasicAssetLoader<AssetGameWorldSp>
{
public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
};
} // namespace T6

View File

@ -1,70 +0,0 @@
#include "AssetLoaderGfxImage.h"
#include "Game/T6/CommonT6.h"
#include "Game/T6/T6.h"
#include "Image/IwiLoader.h"
#include "Pool/GlobalAssetPool.h"
#include <cstring>
#include <format>
#include <iostream>
#include <sstream>
#include <zlib.h>
using namespace T6;
void* AssetLoaderGfxImage::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
{
auto* asset = memory->Alloc<AssetImage::Type>();
asset->name = memory->Dup(assetName.c_str());
return asset;
}
bool AssetLoaderGfxImage::CanLoadFromRaw() const
{
return true;
}
bool AssetLoaderGfxImage::LoadFromRaw(
const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const
{
const auto fileName = std::format("images/{}.iwi", assetName);
const auto file = searchPath->Open(fileName);
if (!file.IsOpen())
return false;
const auto fileSize = static_cast<size_t>(file.m_length);
const auto fileData = std::make_unique<char[]>(fileSize);
file.m_stream->read(fileData.get(), fileSize);
const auto dataHash = static_cast<unsigned>(crc32(0u, reinterpret_cast<const Bytef*>(fileData.get()), fileSize));
std::istringstream ss(std::string(fileData.get(), fileSize));
const auto texture = iwi::LoadIwi(ss);
if (!texture)
{
std::cerr << std::format("Failed to load texture from: {}\n", fileName);
return false;
}
auto* image = memory->Create<GfxImage>();
memset(image, 0, sizeof(GfxImage));
image->name = memory->Dup(assetName.c_str());
image->hash = Common::R_HashString(image->name, 0);
image->delayLoadPixels = true;
image->noPicmip = !texture->HasMipMaps();
image->width = static_cast<uint16_t>(texture->GetWidth());
image->height = static_cast<uint16_t>(texture->GetHeight());
image->depth = static_cast<uint16_t>(texture->GetDepth());
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;
manager->AddAsset<AssetImage>(assetName, image);
return true;
}

View File

@ -1,17 +0,0 @@
#pragma once
#include "AssetLoading/BasicAssetLoader.h"
#include "AssetLoading/IAssetLoadingManager.h"
#include "Game/T6/T6.h"
#include "SearchPath/ISearchPath.h"
namespace T6
{
class AssetLoaderGfxImage final : public BasicAssetLoader<AssetImage>
{
public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
_NODISCARD bool CanLoadFromRaw() const override;
bool
LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override;
};
} // namespace T6

View File

@ -1,13 +0,0 @@
#include "AssetLoaderGfxLightDef.h"
#include "Game/T6/T6.h"
#include "ObjLoading.h"
using namespace T6;
void* AssetLoaderGfxLightDef::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
{
auto* asset = memory->Alloc<AssetLightDef::Type>();
asset->name = memory->Dup(assetName.c_str());
return asset;
}

View File

@ -1,14 +0,0 @@
#pragma once
#include "AssetLoading/BasicAssetLoader.h"
#include "Game/T6/T6.h"
#include "SearchPath/ISearchPath.h"
namespace T6
{
class AssetLoaderGfxLightDef final : public BasicAssetLoader<AssetLightDef>
{
public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
};
} // namespace T6

View File

@ -1,13 +0,0 @@
#include "AssetLoaderGfxWorld.h"
#include "Game/T6/T6.h"
#include "ObjLoading.h"
using namespace T6;
void* AssetLoaderGfxWorld::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
{
auto* asset = memory->Alloc<AssetGfxWorld::Type>();
asset->name = memory->Dup(assetName.c_str());
return asset;
}

View File

@ -1,14 +0,0 @@
#pragma once
#include "AssetLoading/BasicAssetLoader.h"
#include "Game/T6/T6.h"
#include "SearchPath/ISearchPath.h"
namespace T6
{
class AssetLoaderGfxWorld final : public BasicAssetLoader<AssetGfxWorld>
{
public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
};
} // namespace T6

View File

@ -1,13 +0,0 @@
#include "AssetLoaderGlasses.h"
#include "Game/T6/T6.h"
#include "ObjLoading.h"
using namespace T6;
void* AssetLoaderGlasses::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
{
auto* asset = memory->Alloc<AssetGlasses::Type>();
asset->name = memory->Dup(assetName.c_str());
return asset;
}

View File

@ -1,14 +0,0 @@
#pragma once
#include "AssetLoading/BasicAssetLoader.h"
#include "Game/T6/T6.h"
#include "SearchPath/ISearchPath.h"
namespace T6
{
class AssetLoaderGlasses final : public BasicAssetLoader<AssetGlasses>
{
public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
};
} // namespace T6

View File

@ -1,13 +0,0 @@
#include "AssetLoaderImpactFx.h"
#include "Game/T6/T6.h"
#include "ObjLoading.h"
using namespace T6;
void* AssetLoaderImpactFx::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
{
auto* asset = memory->Alloc<AssetImpactFx::Type>();
asset->name = memory->Dup(assetName.c_str());
return asset;
}

View File

@ -1,14 +0,0 @@
#pragma once
#include "AssetLoading/BasicAssetLoader.h"
#include "Game/T6/T6.h"
#include "SearchPath/ISearchPath.h"
namespace T6
{
class AssetLoaderImpactFx final : public BasicAssetLoader<AssetImpactFx>
{
public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
};
} // namespace T6

View File

@ -1,42 +0,0 @@
#include "AssetLoaderLeaderboard.h"
#include "Game/T6/CommonT6.h"
#include "Game/T6/Leaderboard/JsonLeaderboardDefLoader.h"
#include "Game/T6/T6.h"
#include "Pool/GlobalAssetPool.h"
#include <cstring>
#include <format>
#include <iostream>
using namespace T6;
void* AssetLoaderLeaderboard::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
{
auto* asset = memory->Alloc<AssetLeaderboard::Type>();
asset->name = memory->Dup(assetName.c_str());
return asset;
}
bool AssetLoaderLeaderboard::CanLoadFromRaw() const
{
return true;
}
bool AssetLoaderLeaderboard::LoadFromRaw(
const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const
{
const auto file = searchPath->Open(std::format("leaderboards/{}.json", assetName));
if (!file.IsOpen())
return false;
auto* leaderboardDef = memory->Alloc<LeaderboardDef>();
leaderboardDef->name = memory->Dup(assetName.c_str());
if (LoadLeaderboardAsJson(*file.m_stream, *leaderboardDef, memory))
manager->AddAsset<AssetLeaderboard>(assetName, leaderboardDef);
else
std::cerr << std::format("Failed to load leaderboard \"{}\"\n", assetName);
return true;
}

View File

@ -1,17 +0,0 @@
#pragma once
#include "AssetLoading/BasicAssetLoader.h"
#include "AssetLoading/IAssetLoadingManager.h"
#include "Game/T6/T6.h"
#include "SearchPath/ISearchPath.h"
namespace T6
{
class AssetLoaderLeaderboard final : public BasicAssetLoader<AssetLeaderboard>
{
public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
_NODISCARD bool CanLoadFromRaw() const override;
bool
LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override;
};
} // namespace T6

View File

@ -1,13 +0,0 @@
#include "AssetLoaderMapEnts.h"
#include "Game/T6/T6.h"
#include "ObjLoading.h"
using namespace T6;
void* AssetLoaderMapEnts::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
{
auto* asset = memory->Alloc<AssetMapEnts::Type>();
asset->name = memory->Dup(assetName.c_str());
return asset;
}

View File

@ -1,14 +0,0 @@
#pragma once
#include "AssetLoading/BasicAssetLoader.h"
#include "Game/T6/T6.h"
#include "SearchPath/ISearchPath.h"
namespace T6
{
class AssetLoaderMapEnts final : public BasicAssetLoader<AssetMapEnts>
{
public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
};
} // namespace T6

View File

@ -1,57 +0,0 @@
#include "AssetLoaderMaterial.h"
#include "Game/T6/Material/JsonMaterialLoader.h"
#include "Game/T6/T6.h"
#include "Pool/GlobalAssetPool.h"
#include <cstring>
#include <format>
#include <iostream>
using namespace T6;
void* AssetLoaderMaterial::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
{
auto* asset = memory->Alloc<AssetMaterial::Type>();
asset->info.name = memory->Dup(assetName.c_str());
return asset;
}
bool AssetLoaderMaterial::CanLoadFromRaw() const
{
return true;
}
std::string AssetLoaderMaterial::GetFileNameForAsset(const std::string& assetName)
{
std::string sanitizedFileName(assetName);
if (sanitizedFileName[0] == '*')
{
std::ranges::replace(sanitizedFileName, '*', '_');
const auto parenthesisPos = sanitizedFileName.find('(');
if (parenthesisPos != std::string::npos)
sanitizedFileName.erase(parenthesisPos);
sanitizedFileName = "generated/" + sanitizedFileName;
}
return std::format("materials/{}.json", sanitizedFileName);
}
bool AssetLoaderMaterial::LoadFromRaw(
const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const
{
const auto file = searchPath->Open(GetFileNameForAsset(assetName));
if (!file.IsOpen())
return false;
auto* material = memory->Alloc<Material>();
material->info.name = memory->Dup(assetName.c_str());
std::vector<XAssetInfoGeneric*> dependencies;
if (LoadMaterialAsJson(*file.m_stream, *material, memory, manager, dependencies))
manager->AddAsset<AssetMaterial>(assetName, material, std::move(dependencies));
else
std::cerr << "Failed to load material \"" << assetName << "\"\n";
return true;
}

View File

@ -1,19 +0,0 @@
#pragma once
#include "AssetLoading/BasicAssetLoader.h"
#include "AssetLoading/IAssetLoadingManager.h"
#include "Game/T6/T6.h"
#include "SearchPath/ISearchPath.h"
namespace T6
{
class AssetLoaderMaterial final : public BasicAssetLoader<AssetMaterial>
{
static std::string GetFileNameForAsset(const std::string& assetName);
public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
_NODISCARD bool CanLoadFromRaw() const override;
bool
LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override;
};
} // namespace T6

View File

@ -1,13 +0,0 @@
#include "AssetLoaderMemoryBlock.h"
#include "Game/T6/T6.h"
#include "ObjLoading.h"
using namespace T6;
void* AssetLoaderMemoryBlock::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
{
auto* asset = memory->Alloc<AssetMemoryBlock::Type>();
asset->name = memory->Dup(assetName.c_str());
return asset;
}

View File

@ -1,14 +0,0 @@
#pragma once
#include "AssetLoading/BasicAssetLoader.h"
#include "Game/T6/T6.h"
#include "SearchPath/ISearchPath.h"
namespace T6
{
class AssetLoaderMemoryBlock final : public BasicAssetLoader<AssetMemoryBlock>
{
public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
};
} // namespace T6

View File

@ -1,13 +0,0 @@
#include "AssetLoaderMenu.h"
#include "Game/T6/T6.h"
#include "ObjLoading.h"
using namespace T6;
void* AssetLoaderMenu::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
{
auto* asset = memory->Alloc<AssetMenu::Type>();
asset->window.name = memory->Dup(assetName.c_str());
return asset;
}

View File

@ -1,14 +0,0 @@
#pragma once
#include "AssetLoading/BasicAssetLoader.h"
#include "Game/T6/T6.h"
#include "SearchPath/ISearchPath.h"
namespace T6
{
class AssetLoaderMenu final : public BasicAssetLoader<AssetMenu>
{
public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
};
} // namespace T6

View File

@ -1,13 +0,0 @@
#include "AssetLoaderMenuList.h"
#include "Game/T6/T6.h"
#include "ObjLoading.h"
using namespace T6;
void* AssetLoaderMenuList::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
{
auto* asset = memory->Alloc<AssetMenuList::Type>();
asset->name = memory->Dup(assetName.c_str());
return asset;
}

View File

@ -1,14 +0,0 @@
#pragma once
#include "AssetLoading/BasicAssetLoader.h"
#include "Game/T6/T6.h"
#include "SearchPath/ISearchPath.h"
namespace T6
{
class AssetLoaderMenuList final : public BasicAssetLoader<AssetMenuList>
{
public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
};
} // namespace T6

View File

@ -1,153 +0,0 @@
#include "AssetLoaderPhysConstraints.h"
#include "Game/T6/InfoString/EnumStrings.h"
#include "Game/T6/InfoString/InfoStringToStructConverter.h"
#include "Game/T6/InfoString/PhysConstraintsFields.h"
#include "Game/T6/ObjConstantsT6.h"
#include "Game/T6/T6.h"
#include "InfoString/InfoString.h"
#include <cassert>
#include <cstring>
#include <iostream>
using namespace T6;
namespace T6
{
class InfoStringToPhysConstraintsConverter final : public InfoStringToStructConverter
{
protected:
bool ConvertExtensionField(const cspField_t& field, const std::string& value) override
{
switch (static_cast<constraintsFieldType_t>(field.iFieldType))
{
case CFT_TYPE:
return ConvertEnumInt(field.szName, value, field.iOffset, s_constraintTypeNames, std::extent_v<decltype(s_constraintTypeNames)>);
default:
assert(false);
return false;
}
}
public:
InfoStringToPhysConstraintsConverter(const InfoString& infoString,
PhysConstraints* physConstraints,
ZoneScriptStrings& zoneScriptStrings,
MemoryManager* memory,
IAssetLoadingManager* manager,
const cspField_t* fields,
const size_t fieldCount)
: InfoStringToStructConverter(infoString, physConstraints, zoneScriptStrings, memory, manager, fields, fieldCount)
{
}
};
} // namespace T6
void AssetLoaderPhysConstraints::CalculatePhysConstraintsFields(PhysConstraints* physConstraints, Zone* zone)
{
for (auto& constraint : physConstraints->data)
{
constraint.targetname = zone->m_script_strings.AddOrGetScriptString("");
constraint.target_ent1 = zone->m_script_strings.AddOrGetScriptString("");
constraint.target_ent2 = zone->m_script_strings.AddOrGetScriptString("");
constraint.attach_point_type1 = ATTACH_POINT_BONE;
constraint.attach_point_type2 = ATTACH_POINT_BONE;
constraint.target_bone1 = "";
constraint.target_bone2 = "";
}
// count
{
auto foundEnd = false;
for (auto i = 0u; i < std::extent_v<decltype(PhysConstraints::data)>; i++)
{
if (physConstraints->data[i].type == CONSTRAINT_NONE)
{
foundEnd = true;
physConstraints->count = i;
break;
}
}
if (!foundEnd)
physConstraints->count = std::extent_v<decltype(PhysConstraints::data)>;
}
}
bool AssetLoaderPhysConstraints::LoadFromInfoString(
const InfoString& infoString, const std::string& assetName, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone)
{
auto* physConstraints = memory->Create<PhysConstraints>();
memset(physConstraints, 0, sizeof(PhysConstraints));
InfoStringToPhysConstraintsConverter converter(
infoString, physConstraints, zone->m_script_strings, memory, manager, phys_constraints_fields, std::extent_v<decltype(phys_constraints_fields)>);
if (!converter.Convert())
{
std::cout << "Failed to parse phys constraints: \"" << assetName << "\"\n";
return true;
}
CalculatePhysConstraintsFields(physConstraints, zone);
physConstraints->name = memory->Dup(assetName.c_str());
auto scrStrings = converter.GetUsedScriptStrings();
scrStrings.push_back(zone->m_script_strings.AddOrGetScriptString(""));
manager->AddAsset<AssetPhysConstraints>(assetName, physConstraints, converter.GetDependencies(), scrStrings);
return true;
}
void* AssetLoaderPhysConstraints::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
{
auto* asset = memory->Alloc<AssetPhysConstraints::Type>();
asset->name = memory->Dup(assetName.c_str());
return asset;
}
bool AssetLoaderPhysConstraints::CanLoadFromGdt() const
{
return true;
}
bool AssetLoaderPhysConstraints::LoadFromGdt(
const std::string& assetName, IGdtQueryable* gdtQueryable, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const
{
auto* gdtEntry = gdtQueryable->GetGdtEntryByGdfAndName(ObjConstants::GDF_FILENAME_PHYS_CONSTRAINTS, assetName);
if (gdtEntry == nullptr)
return false;
InfoString infoString;
if (!infoString.FromGdtProperties(*gdtEntry))
{
std::cout << "Failed to read phys constraints gdt entry: \"" << assetName << "\"\n";
return true;
}
return LoadFromInfoString(infoString, assetName, memory, manager, zone);
}
bool AssetLoaderPhysConstraints::CanLoadFromRaw() const
{
return true;
}
bool AssetLoaderPhysConstraints::LoadFromRaw(
const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const
{
const auto fileName = "physconstraints/" + assetName;
const auto file = searchPath->Open(fileName);
if (!file.IsOpen())
return false;
InfoString infoString;
if (!infoString.FromStream(ObjConstants::INFO_STRING_PREFIX_PHYS_CONSTRAINTS, *file.m_stream))
{
std::cerr << "Could not parse as info string file: \"" << fileName << "\"\n";
return true;
}
return LoadFromInfoString(infoString, assetName, memory, manager, zone);
}

View File

@ -1,26 +0,0 @@
#pragma once
#include "AssetLoading/BasicAssetLoader.h"
#include "AssetLoading/IAssetLoadingManager.h"
#include "Game/T6/T6.h"
#include "InfoString/InfoString.h"
#include "SearchPath/ISearchPath.h"
namespace T6
{
class AssetLoaderPhysConstraints final : public BasicAssetLoader<AssetPhysConstraints>
{
static void CalculatePhysConstraintsFields(PhysConstraints* physConstraints, Zone* zone);
static bool
LoadFromInfoString(const InfoString& infoString, const std::string& assetName, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone);
public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
_NODISCARD bool CanLoadFromGdt() const override;
bool LoadFromGdt(
const std::string& assetName, IGdtQueryable* gdtQueryable, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override;
_NODISCARD bool CanLoadFromRaw() const override;
bool
LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override;
};
} // namespace T6

View File

@ -1,136 +0,0 @@
#include "AssetLoaderPhysPreset.h"
#include "Game/T6/InfoString/InfoStringToStructConverter.h"
#include "Game/T6/InfoString/PhysPresetFields.h"
#include "Game/T6/ObjConstantsT6.h"
#include "Game/T6/T6.h"
#include "InfoString/InfoString.h"
#include <algorithm>
#include <cassert>
#include <cstring>
#include <iostream>
#include <limits>
using namespace T6;
namespace T6
{
class InfoStringToPhysPresetConverter final : public InfoStringToStructConverter
{
protected:
bool ConvertExtensionField(const cspField_t& field, const std::string& value) override
{
assert(false);
return false;
}
public:
InfoStringToPhysPresetConverter(const InfoString& infoString,
PhysPresetInfo* physPreset,
ZoneScriptStrings& zoneScriptStrings,
MemoryManager* memory,
IAssetLoadingManager* manager,
const cspField_t* fields,
const size_t fieldCount)
: InfoStringToStructConverter(infoString, physPreset, zoneScriptStrings, memory, manager, fields, fieldCount)
{
}
};
} // namespace T6
void AssetLoaderPhysPreset::CopyFromPhysPresetInfo(const PhysPresetInfo* physPresetInfo, PhysPreset* physPreset)
{
physPreset->mass = std::clamp(physPresetInfo->mass, 1.0f, 2000.0f) * 0.001f;
physPreset->bounce = physPresetInfo->bounce;
if (physPresetInfo->isFrictionInfinity != 0)
physPreset->friction = std::numeric_limits<float>::infinity();
else
physPreset->friction = physPresetInfo->friction;
physPreset->bulletForceScale = physPresetInfo->bulletForceScale;
physPreset->explosiveForceScale = physPresetInfo->explosiveForceScale;
physPreset->piecesSpreadFraction = physPresetInfo->piecesSpreadFraction;
physPreset->piecesUpwardVelocity = physPresetInfo->piecesUpwardVelocity;
physPreset->canFloat = physPresetInfo->canFloat;
physPreset->gravityScale = std::clamp(physPresetInfo->gravityScale, 0.01f, 10.0f);
physPreset->centerOfMassOffset = physPresetInfo->centerOfMassOffset;
physPreset->buoyancyBoxMin = physPresetInfo->buoyancyBoxMin;
physPreset->buoyancyBoxMax = physPresetInfo->buoyancyBoxMax;
}
bool AssetLoaderPhysPreset::LoadFromInfoString(
const InfoString& infoString, const std::string& assetName, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone)
{
const auto presetInfo = std::make_unique<PhysPresetInfo>();
memset(presetInfo.get(), 0, sizeof(PhysPresetInfo));
InfoStringToPhysPresetConverter converter(
infoString, presetInfo.get(), zone->m_script_strings, memory, manager, phys_preset_fields, std::extent_v<decltype(phys_preset_fields)>);
if (!converter.Convert())
{
std::cout << "Failed to parse phys preset: \"" << assetName << "\"\n";
return true;
}
auto* physPreset = memory->Create<PhysPreset>();
CopyFromPhysPresetInfo(presetInfo.get(), physPreset);
physPreset->name = memory->Dup(assetName.c_str());
manager->AddAsset<AssetPhysPreset>(assetName, physPreset, converter.GetDependencies(), converter.GetUsedScriptStrings());
return true;
}
void* AssetLoaderPhysPreset::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
{
auto* asset = memory->Alloc<AssetPhysPreset::Type>();
asset->name = memory->Dup(assetName.c_str());
return asset;
}
bool AssetLoaderPhysPreset::CanLoadFromGdt() const
{
return true;
}
bool AssetLoaderPhysPreset::LoadFromGdt(
const std::string& assetName, IGdtQueryable* gdtQueryable, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const
{
auto* gdtEntry = gdtQueryable->GetGdtEntryByGdfAndName(ObjConstants::GDF_FILENAME_PHYS_PRESET, assetName);
if (gdtEntry == nullptr)
return false;
InfoString infoString;
if (!infoString.FromGdtProperties(*gdtEntry))
{
std::cout << "Failed to read phys preset gdt entry: \"" << assetName << "\"\n";
return true;
}
return LoadFromInfoString(infoString, assetName, memory, manager, zone);
}
bool AssetLoaderPhysPreset::CanLoadFromRaw() const
{
return true;
}
bool AssetLoaderPhysPreset::LoadFromRaw(
const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const
{
const auto fileName = "physic/" + assetName;
const auto file = searchPath->Open(fileName);
if (!file.IsOpen())
return false;
InfoString infoString;
if (!infoString.FromStream(ObjConstants::INFO_STRING_PREFIX_PHYS_PRESET, *file.m_stream))
{
std::cerr << "Could not parse as info string file: \"" << fileName << "\"\n";
return true;
}
return LoadFromInfoString(infoString, assetName, memory, manager, zone);
}

View File

@ -1,26 +0,0 @@
#pragma once
#include "AssetLoading/BasicAssetLoader.h"
#include "AssetLoading/IAssetLoadingManager.h"
#include "Game/T6/T6.h"
#include "InfoString/InfoString.h"
#include "SearchPath/ISearchPath.h"
namespace T6
{
class AssetLoaderPhysPreset final : public BasicAssetLoader<AssetPhysPreset>
{
static void CopyFromPhysPresetInfo(const PhysPresetInfo* physPresetInfo, PhysPreset* physPreset);
static bool
LoadFromInfoString(const InfoString& infoString, const std::string& assetName, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone);
public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
_NODISCARD bool CanLoadFromGdt() const override;
bool LoadFromGdt(
const std::string& assetName, IGdtQueryable* gdtQueryable, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override;
_NODISCARD bool CanLoadFromRaw() const override;
bool
LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override;
};
} // namespace T6

View File

@ -1,42 +0,0 @@
#include "AssetLoaderQdb.h"
#include "Game/T6/T6.h"
#include "Pool/GlobalAssetPool.h"
#include <cstring>
using namespace T6;
void* AssetLoaderQdb::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
{
auto* asset = memory->Alloc<AssetQdb::Type>();
asset->name = memory->Dup(assetName.c_str());
return asset;
}
bool AssetLoaderQdb::CanLoadFromRaw() const
{
return true;
}
bool AssetLoaderQdb::LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const
{
const auto file = searchPath->Open(assetName);
if (!file.IsOpen())
return false;
auto* qdb = memory->Create<Qdb>();
qdb->name = memory->Dup(assetName.c_str());
qdb->len = static_cast<int>(file.m_length);
auto* fileBuffer = memory->Alloc<char>(static_cast<size_t>(file.m_length + 1));
file.m_stream->read(fileBuffer, file.m_length);
if (file.m_stream->gcount() != file.m_length)
return false;
fileBuffer[qdb->len] = '\0';
qdb->buffer = static_cast<char16*>(fileBuffer);
manager->AddAsset<AssetQdb>(assetName, qdb);
return true;
}

View File

@ -1,17 +0,0 @@
#pragma once
#include "AssetLoading/BasicAssetLoader.h"
#include "AssetLoading/IAssetLoadingManager.h"
#include "Game/T6/T6.h"
#include "SearchPath/ISearchPath.h"
namespace T6
{
class AssetLoaderQdb final : public BasicAssetLoader<AssetQdb>
{
public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
_NODISCARD bool CanLoadFromRaw() const override;
bool
LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override;
};
} // namespace T6

View File

@ -1,114 +0,0 @@
#include "AssetLoaderRawFile.h"
#include "Game/T6/T6.h"
#include "Pool/GlobalAssetPool.h"
#include <cstring>
#include <filesystem>
#include <iostream>
#include <zlib.h>
#include <zutil.h>
using namespace T6;
namespace fs = std::filesystem;
void* AssetLoaderRawFile::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
{
auto* asset = memory->Alloc<AssetRawFile::Type>();
asset->name = memory->Dup(assetName.c_str());
return asset;
}
bool AssetLoaderRawFile::CanLoadFromRaw() const
{
return true;
}
bool AssetLoaderRawFile::LoadAnimtree(
const SearchPathOpenFile& file, const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager)
{
const auto uncompressedBuffer = std::make_unique<char[]>(static_cast<size_t>(file.m_length));
file.m_stream->read(uncompressedBuffer.get(), file.m_length);
if (file.m_stream->gcount() != file.m_length)
return false;
const auto compressionBufferSize = static_cast<size_t>(file.m_length + sizeof(uint32_t) + COMPRESSED_BUFFER_SIZE_PADDING);
auto* compressedBuffer = memory->Alloc<char>(compressionBufferSize);
z_stream_s zs{};
zs.zalloc = Z_NULL;
zs.zfree = Z_NULL;
zs.opaque = Z_NULL;
zs.avail_in = static_cast<uInt>(file.m_length);
zs.avail_out = compressionBufferSize;
zs.next_in = reinterpret_cast<const Bytef*>(uncompressedBuffer.get());
zs.next_out = reinterpret_cast<Bytef*>(&compressedBuffer[sizeof(uint32_t)]);
int ret = deflateInit2(&zs, Z_DEFAULT_COMPRESSION, Z_DEFLATED, -DEF_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY);
if (ret != Z_OK)
{
throw std::runtime_error("Initializing deflate failed");
}
ret = deflate(&zs, Z_FINISH);
if (ret != Z_STREAM_END)
{
std::cerr << "Deflate failed for loading animtree file \"" << assetName << "\"\n";
deflateEnd(&zs);
return false;
}
const auto compressedSize = compressionBufferSize + sizeof(uint32_t) - zs.avail_out;
reinterpret_cast<uint32_t*>(compressedBuffer)[0] = static_cast<uint32_t>(file.m_length); // outLen
auto* rawFile = memory->Create<RawFile>();
rawFile->name = memory->Dup(assetName.c_str());
rawFile->len = static_cast<int>(compressedSize);
rawFile->buffer = static_cast<const char*>(compressedBuffer);
deflateEnd(&zs);
manager->AddAsset<AssetRawFile>(assetName, rawFile);
return true;
}
bool AssetLoaderRawFile::LoadDefault(
const SearchPathOpenFile& file, const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager)
{
auto* rawFile = memory->Create<RawFile>();
rawFile->name = memory->Dup(assetName.c_str());
rawFile->len = static_cast<int>(file.m_length);
auto* fileBuffer = memory->Alloc<char>(static_cast<size_t>(file.m_length + 1));
file.m_stream->read(fileBuffer, file.m_length);
if (file.m_stream->gcount() != file.m_length)
return false;
fileBuffer[rawFile->len] = '\0';
rawFile->buffer = static_cast<char16*>(fileBuffer);
manager->AddAsset<AssetRawFile>(assetName, rawFile);
return true;
}
bool AssetLoaderRawFile::LoadFromRaw(
const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const
{
const auto file = searchPath->Open(assetName);
if (!file.IsOpen())
return false;
const fs::path rawFilePath(assetName);
const auto extension = rawFilePath.extension().string();
if (extension == ".atr")
return LoadAnimtree(file, assetName, searchPath, memory, manager);
return LoadDefault(file, assetName, searchPath, memory, manager);
}

View File

@ -1,24 +0,0 @@
#pragma once
#include "AssetLoading/BasicAssetLoader.h"
#include "AssetLoading/IAssetLoadingManager.h"
#include "Game/T6/T6.h"
#include "SearchPath/ISearchPath.h"
namespace T6
{
class AssetLoaderRawFile final : public BasicAssetLoader<AssetRawFile>
{
static constexpr size_t COMPRESSED_BUFFER_SIZE_PADDING = 64;
static bool LoadAnimtree(
const SearchPathOpenFile& file, const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager);
static bool LoadDefault(
const SearchPathOpenFile& file, const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager);
public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
_NODISCARD bool CanLoadFromRaw() const override;
bool
LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override;
};
} // namespace T6

View File

@ -1,43 +0,0 @@
#include "AssetLoaderScriptParseTree.h"
#include "Game/T6/T6.h"
#include "Pool/GlobalAssetPool.h"
#include <cstring>
using namespace T6;
void* AssetLoaderScriptParseTree::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
{
auto* asset = memory->Alloc<AssetScript::Type>();
asset->name = memory->Dup(assetName.c_str());
return asset;
}
bool AssetLoaderScriptParseTree::CanLoadFromRaw() const
{
return true;
}
bool AssetLoaderScriptParseTree::LoadFromRaw(
const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const
{
const auto file = searchPath->Open(assetName);
if (!file.IsOpen())
return false;
auto* scriptParseTree = memory->Create<ScriptParseTree>();
scriptParseTree->name = memory->Dup(assetName.c_str());
scriptParseTree->len = static_cast<int>(file.m_length);
auto* fileBuffer = memory->Alloc<char>(static_cast<size_t>(file.m_length + 1));
file.m_stream->read(fileBuffer, file.m_length);
if (file.m_stream->gcount() != file.m_length)
return false;
fileBuffer[scriptParseTree->len] = '\0';
scriptParseTree->buffer = static_cast<char16*>(fileBuffer);
manager->AddAsset<AssetScript>(assetName, scriptParseTree);
return true;
}

View File

@ -1,17 +0,0 @@
#pragma once
#include "AssetLoading/BasicAssetLoader.h"
#include "AssetLoading/IAssetLoadingManager.h"
#include "Game/T6/T6.h"
#include "SearchPath/ISearchPath.h"
namespace T6
{
class AssetLoaderScriptParseTree final : public BasicAssetLoader<AssetScript>
{
public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
_NODISCARD bool CanLoadFromRaw() const override;
bool
LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override;
};
} // namespace T6

View File

@ -1,13 +0,0 @@
#include "AssetLoaderSkinnedVerts.h"
#include "Game/T6/T6.h"
#include "ObjLoading.h"
using namespace T6;
void* AssetLoaderSkinnedVerts::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
{
auto* asset = memory->Alloc<AssetSkinnedVerts::Type>();
asset->name = memory->Dup(assetName.c_str());
return asset;
}

View File

@ -1,14 +0,0 @@
#pragma once
#include "AssetLoading/BasicAssetLoader.h"
#include "Game/T6/T6.h"
#include "SearchPath/ISearchPath.h"
namespace T6
{
class AssetLoaderSkinnedVerts final : public BasicAssetLoader<AssetSkinnedVerts>
{
public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
};
} // namespace T6

View File

@ -1,42 +0,0 @@
#include "AssetLoaderSlug.h"
#include "Game/T6/T6.h"
#include "Pool/GlobalAssetPool.h"
#include <cstring>
using namespace T6;
void* AssetLoaderSlug::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
{
auto* asset = memory->Alloc<AssetSlug::Type>();
asset->name = memory->Dup(assetName.c_str());
return asset;
}
bool AssetLoaderSlug::CanLoadFromRaw() const
{
return true;
}
bool AssetLoaderSlug::LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const
{
const auto file = searchPath->Open(assetName);
if (!file.IsOpen())
return false;
auto* slug = memory->Create<Slug>();
slug->name = memory->Dup(assetName.c_str());
slug->len = static_cast<int>(file.m_length);
auto* fileBuffer = memory->Alloc<char>(static_cast<size_t>(file.m_length + 1));
file.m_stream->read(fileBuffer, file.m_length);
if (file.m_stream->gcount() != file.m_length)
return false;
fileBuffer[slug->len] = '\0';
slug->buffer = static_cast<char16*>(fileBuffer);
manager->AddAsset<AssetSlug>(assetName, slug);
return true;
}

View File

@ -1,17 +0,0 @@
#pragma once
#include "AssetLoading/BasicAssetLoader.h"
#include "AssetLoading/IAssetLoadingManager.h"
#include "Game/T6/T6.h"
#include "SearchPath/ISearchPath.h"
namespace T6
{
class AssetLoaderSlug final : public BasicAssetLoader<AssetSlug>
{
public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
_NODISCARD bool CanLoadFromRaw() const override;
bool
LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override;
};
} // namespace T6

View File

@ -1,17 +0,0 @@
#pragma once
#include "AssetLoading/BasicAssetLoader.h"
#include "AssetLoading/IAssetLoadingManager.h"
#include "Game/T6/T6.h"
#include "SearchPath/ISearchPath.h"
namespace T6
{
class AssetLoaderSoundBank final : public BasicAssetLoader<AssetSoundBank>
{
public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
_NODISCARD bool CanLoadFromRaw() const override;
bool
LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override;
};
} // namespace T6

View File

@ -1,13 +0,0 @@
#include "AssetLoaderSoundDriverGlobals.h"
#include "Game/T6/T6.h"
#include "ObjLoading.h"
using namespace T6;
void* AssetLoaderSoundDriverGlobals::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
{
auto* asset = memory->Alloc<AssetSoundDriverGlobals::Type>();
asset->name = memory->Dup(assetName.c_str());
return asset;
}

View File

@ -1,14 +0,0 @@
#pragma once
#include "AssetLoading/BasicAssetLoader.h"
#include "Game/T6/T6.h"
#include "SearchPath/ISearchPath.h"
namespace T6
{
class AssetLoaderSoundDriverGlobals final : public BasicAssetLoader<AssetSoundDriverGlobals>
{
public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
};
} // namespace T6

View File

@ -1,13 +0,0 @@
#include "AssetLoaderSoundPatch.h"
#include "Game/T6/T6.h"
#include "ObjLoading.h"
using namespace T6;
void* AssetLoaderSoundPatch::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
{
auto* asset = memory->Alloc<AssetSoundPatch::Type>();
asset->name = memory->Dup(assetName.c_str());
return asset;
}

View File

@ -1,14 +0,0 @@
#pragma once
#include "AssetLoading/BasicAssetLoader.h"
#include "Game/T6/T6.h"
#include "SearchPath/ISearchPath.h"
namespace T6
{
class AssetLoaderSoundPatch final : public BasicAssetLoader<AssetSoundPatch>
{
public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
};
} // namespace T6

View File

@ -1,38 +0,0 @@
#include "AssetLoaderStringTable.h"
#include "Csv/CsvStream.h"
#include "Game/T6/CommonT6.h"
#include "Game/T6/T6.h"
#include "Pool/GlobalAssetPool.h"
#include "StringTable/StringTableLoader.h"
#include <cstring>
using namespace T6;
void* AssetLoaderStringTable::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
{
auto* asset = memory->Alloc<AssetStringTable::Type>();
asset->name = memory->Dup(assetName.c_str());
return asset;
}
bool AssetLoaderStringTable::CanLoadFromRaw() const
{
return true;
}
bool AssetLoaderStringTable::LoadFromRaw(
const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const
{
const auto file = searchPath->Open(assetName);
if (!file.IsOpen())
return false;
string_table::StringTableLoaderV3<StringTable, Common::Com_HashString> loader;
auto* stringTable = loader.LoadFromStream(assetName, *memory, *file.m_stream);
manager->AddAsset<AssetStringTable>(assetName, stringTable);
return true;
}

View File

@ -1,17 +0,0 @@
#pragma once
#include "AssetLoading/BasicAssetLoader.h"
#include "AssetLoading/IAssetLoadingManager.h"
#include "Game/T6/T6.h"
#include "SearchPath/ISearchPath.h"
namespace T6
{
class AssetLoaderStringTable final : public BasicAssetLoader<AssetStringTable>
{
public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
_NODISCARD bool CanLoadFromRaw() const override;
bool
LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override;
};
} // namespace T6

View File

@ -1,13 +0,0 @@
#include "AssetLoaderTechniqueSet.h"
#include "Game/T6/T6.h"
#include "ObjLoading.h"
using namespace T6;
void* AssetLoaderTechniqueSet::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
{
auto* asset = memory->Alloc<AssetTechniqueSet::Type>();
asset->name = memory->Dup(assetName.c_str());
return asset;
}

View File

@ -1,14 +0,0 @@
#pragma once
#include "AssetLoading/BasicAssetLoader.h"
#include "Game/T6/T6.h"
#include "SearchPath/ISearchPath.h"
namespace T6
{
class AssetLoaderTechniqueSet final : public BasicAssetLoader<AssetTechniqueSet>
{
public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
};
} // namespace T6

View File

@ -1,119 +0,0 @@
#include "AssetLoaderTracer.h"
#include "Game/T6/InfoString/EnumStrings.h"
#include "Game/T6/InfoString/InfoStringToStructConverter.h"
#include "Game/T6/InfoString/TracerFields.h"
#include "Game/T6/ObjConstantsT6.h"
#include "Game/T6/T6.h"
#include "InfoString/InfoString.h"
#include <cassert>
#include <cstring>
#include <iostream>
using namespace T6;
namespace T6
{
class InfoStringToTracerConverter final : public InfoStringToStructConverter
{
protected:
bool ConvertExtensionField(const cspField_t& field, const std::string& value) override
{
switch (static_cast<tracerFieldType_t>(field.iFieldType))
{
case TFT_TRACERTYPE:
return ConvertEnumInt(field.szName, value, field.iOffset, tracerTypeNames, std::extent_v<decltype(tracerTypeNames)>);
case TFT_NUM_FIELD_TYPES:
default:
assert(false);
return false;
}
}
public:
InfoStringToTracerConverter(const InfoString& infoString,
TracerDef* tracer,
ZoneScriptStrings& zoneScriptStrings,
MemoryManager* memory,
IAssetLoadingManager* manager,
const cspField_t* fields,
const size_t fieldCount)
: InfoStringToStructConverter(infoString, tracer, zoneScriptStrings, memory, manager, fields, fieldCount)
{
}
};
} // namespace T6
bool AssetLoaderTracer::LoadFromInfoString(
const InfoString& infoString, const std::string& assetName, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone)
{
auto* tracer = memory->Create<TracerDef>();
memset(tracer, 0, sizeof(TracerDef));
InfoStringToTracerConverter converter(infoString, tracer, zone->m_script_strings, memory, manager, tracer_fields, std::extent_v<decltype(tracer_fields)>);
if (!converter.Convert())
{
std::cout << "Failed to parse tracer: \"" << assetName << "\"\n";
return true;
}
tracer->name = memory->Dup(assetName.c_str());
manager->AddAsset<AssetTracer>(assetName, tracer, converter.GetDependencies(), converter.GetUsedScriptStrings());
return true;
}
void* AssetLoaderTracer::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
{
auto* asset = memory->Alloc<AssetTracer::Type>();
asset->name = memory->Dup(assetName.c_str());
return asset;
}
bool AssetLoaderTracer::CanLoadFromGdt() const
{
return true;
}
bool AssetLoaderTracer::LoadFromGdt(
const std::string& assetName, IGdtQueryable* gdtQueryable, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const
{
auto* gdtEntry = gdtQueryable->GetGdtEntryByGdfAndName(ObjConstants::GDF_FILENAME_TRACER, assetName);
if (gdtEntry == nullptr)
return false;
InfoString infoString;
if (!infoString.FromGdtProperties(*gdtEntry))
{
std::cout << "Failed to read tracer gdt entry: \"" << assetName << "\"\n";
return true;
}
return LoadFromInfoString(infoString, assetName, memory, manager, zone);
}
bool AssetLoaderTracer::CanLoadFromRaw() const
{
return true;
}
bool AssetLoaderTracer::LoadFromRaw(
const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const
{
const auto fileName = "tracer/" + assetName;
const auto file = searchPath->Open(fileName);
if (!file.IsOpen())
return false;
InfoString infoString;
if (!infoString.FromStream(ObjConstants::INFO_STRING_PREFIX_TRACER, *file.m_stream))
{
std::cerr << "Could not parse as info string file: \"" << fileName << "\"\n";
return true;
}
return LoadFromInfoString(infoString, assetName, memory, manager, zone);
}

View File

@ -1,24 +0,0 @@
#pragma once
#include "AssetLoading/BasicAssetLoader.h"
#include "AssetLoading/IAssetLoadingManager.h"
#include "Game/T6/T6.h"
#include "InfoString/InfoString.h"
#include "SearchPath/ISearchPath.h"
namespace T6
{
class AssetLoaderTracer final : public BasicAssetLoader<AssetTracer>
{
static bool
LoadFromInfoString(const InfoString& infoString, const std::string& assetName, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone);
public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
_NODISCARD bool CanLoadFromGdt() const override;
bool LoadFromGdt(
const std::string& assetName, IGdtQueryable* gdtQueryable, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override;
_NODISCARD bool CanLoadFromRaw() const override;
bool
LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override;
};
} // namespace T6

View File

@ -1,24 +0,0 @@
#pragma once
#include "AssetLoading/BasicAssetLoader.h"
#include "AssetLoading/IAssetLoadingManager.h"
#include "Game/T6/T6.h"
#include "InfoString/InfoString.h"
#include "SearchPath/ISearchPath.h"
namespace T6
{
class AssetLoaderVehicle final : public BasicAssetLoader<AssetVehicle>
{
static bool
LoadFromInfoString(const InfoString& infoString, const std::string& assetName, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone);
public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
_NODISCARD bool CanLoadFromGdt() const override;
bool LoadFromGdt(
const std::string& assetName, IGdtQueryable* gdtQueryable, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override;
_NODISCARD bool CanLoadFromRaw() const override;
bool
LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override;
};
} // namespace T6

View File

@ -1,683 +0,0 @@
#include "AssetLoaderWeapon.h"
#include "AssetLoaderWeaponAttachmentUnique.h"
#include "Game/T6/InfoString/EnumStrings.h"
#include "Game/T6/InfoString/InfoStringToStructConverter.h"
#include "Game/T6/InfoString/WeaponFields.h"
#include "Game/T6/ObjConstantsT6.h"
#include "Game/T6/T6.h"
#include "InfoString/InfoString.h"
#include "Utils/ClassUtils.h"
#include "Utils/StringUtils.h"
#include "Weapon/AccuracyGraphLoader.h"
#include <cassert>
#include <cstring>
#include <iostream>
using namespace T6;
namespace T6
{
class InfoStringToWeaponConverter final : public InfoStringToStructConverter
{
bool ConvertHideTags(const cspField_t& field, const std::string& value)
{
std::vector<std::string> valueArray;
if (!ParseAsArray(value, valueArray))
{
std::cerr << "Failed to parse hide tags as array\n";
return false;
}
if (valueArray.size() > std::extent_v<decltype(WeaponFullDef::hideTags)>)
{
std::cerr << "Cannot have more than " << std::extent_v<decltype(WeaponFullDef::hideTags)> << " hide tags!\n";
return false;
}
auto* hideTags = reinterpret_cast<scr_string_t*>(reinterpret_cast<uintptr_t>(m_structure) + field.iOffset);
if (valueArray.size() < std::extent_v<decltype(WeaponFullDef::hideTags)>)
{
m_used_script_string_list.emplace(m_zone_script_strings.AddOrGetScriptString(nullptr));
}
auto currentHideTag = 0u;
for (; currentHideTag < valueArray.size(); currentHideTag++)
{
const auto& currentValue = valueArray[currentHideTag];
const auto scrString =
!currentValue.empty() ? m_zone_script_strings.AddOrGetScriptString(currentValue) : m_zone_script_strings.AddOrGetScriptString(nullptr);
hideTags[currentHideTag] = scrString;
m_used_script_string_list.emplace(scrString);
}
for (; currentHideTag < std::extent_v<decltype(WeaponFullDef::hideTags)>; currentHideTag++)
{
hideTags[currentHideTag] = m_zone_script_strings.GetScriptString(nullptr);
}
return true;
}
_NODISCARD bool ConvertBounceSounds(const cspField_t& field, const std::string& value) const
{
auto*** bounceSound = reinterpret_cast<const char***>(reinterpret_cast<uintptr_t>(m_structure) + field.iOffset);
if (value.empty())
{
*bounceSound = nullptr;
return true;
}
assert(std::extent_v<decltype(bounceSoundSuffixes)> == SURF_TYPE_NUM);
*bounceSound = m_memory->Alloc<const char*>(SURF_TYPE_NUM);
for (auto i = 0u; i < SURF_TYPE_NUM; i++)
{
const auto currentBounceSound = value + bounceSoundSuffixes[i];
(*bounceSound)[i] = m_memory->Dup(currentBounceSound.c_str());
}
return true;
}
_NODISCARD bool ConvertNotetrackSoundMap(const cspField_t& field, const std::string& value)
{
std::vector<std::array<std::string, 2>> pairs;
if (!ParseAsArray(value, pairs))
{
std::cerr << "Failed to parse notetracksoundmap as pairs\n";
return false;
}
if (pairs.size() > std::extent_v<decltype(WeaponFullDef::notetrackSoundMapKeys)>)
{
std::cerr << "Cannot have more than " << std::extent_v<decltype(WeaponFullDef::notetrackSoundMapKeys)> << " notetracksoundmap entries!\n";
return false;
}
auto* keys = reinterpret_cast<scr_string_t*>(reinterpret_cast<uintptr_t>(m_structure) + field.iOffset);
auto* values = &keys[std::extent_v<decltype(WeaponFullDef::notetrackSoundMapKeys)>];
auto currentEntryNum = 0u;
if (pairs.size() < std::extent_v<decltype(WeaponFullDef::notetrackSoundMapKeys)>)
{
m_used_script_string_list.emplace(m_zone_script_strings.AddOrGetScriptString(nullptr));
}
for (; currentEntryNum < pairs.size(); currentEntryNum++)
{
const auto& currentValue = pairs[currentEntryNum];
const auto keyScriptString = !currentValue[0].empty() ? m_zone_script_strings.AddOrGetScriptString(currentValue[0])
: m_zone_script_strings.AddOrGetScriptString(nullptr);
const auto valueScriptString = !currentValue[1].empty() ? m_zone_script_strings.AddOrGetScriptString(currentValue[1])
: m_zone_script_strings.AddOrGetScriptString(nullptr);
keys[currentEntryNum] = keyScriptString;
m_used_script_string_list.emplace(keyScriptString);
values[currentEntryNum] = valueScriptString;
m_used_script_string_list.emplace(valueScriptString);
}
for (; currentEntryNum < std::extent_v<decltype(WeaponFullDef::notetrackSoundMapKeys)>; currentEntryNum++)
{
const auto emptyScr = m_zone_script_strings.GetScriptString(nullptr);
keys[currentEntryNum] = emptyScr;
values[currentEntryNum] = emptyScr;
}
return true;
}
_NODISCARD bool ConvertWeaponCamo(const cspField_t& field, const std::string& value)
{
if (value.empty())
{
*reinterpret_cast<WeaponCamo**>(reinterpret_cast<uintptr_t>(m_structure) + field.iOffset) = nullptr;
return true;
}
auto* camo = m_loading_manager->LoadDependency<AssetWeaponCamo>(value);
if (camo == nullptr)
{
std::cerr << "Failed to load camo asset \"" << value << "\"\n";
return false;
}
m_dependencies.emplace(camo);
*reinterpret_cast<WeaponCamo**>(reinterpret_cast<uintptr_t>(m_structure) + field.iOffset) = camo->Asset();
return true;
}
_NODISCARD bool ConvertAttachments(const cspField_t& field, const std::string& value)
{
std::vector<std::string> valueArray;
if (!ParseAsArray(value, valueArray))
{
std::cerr << "Failed to parse attachments as array\n";
return false;
}
auto** attachments = reinterpret_cast<WeaponAttachment**>(reinterpret_cast<uintptr_t>(m_structure) + field.iOffset);
for (const auto& attachmentName : valueArray)
{
auto* attachmentAssetInfo = m_loading_manager->LoadDependency<AssetAttachment>(attachmentName);
if (attachmentAssetInfo == nullptr)
{
std::cerr << "Failed to load attachment asset \"" << attachmentName << "\"\n";
return false;
}
auto* attachmentAsset = attachmentAssetInfo->Asset();
if (static_cast<unsigned>(attachmentAsset->attachmentType) >= ATTACHMENT_TYPE_COUNT)
{
std::cerr << "Invalid attachment type " << attachmentAsset->attachmentType << " for attachment asset \"" << attachmentName << "\"\n";
return false;
}
if (attachments[attachmentAsset->attachmentType] != nullptr)
{
std::cerr << "Already loaded attachment with same type " << attachmentAsset->attachmentType << ": \""
<< attachments[attachmentAsset->attachmentType]->szInternalName << "\", \"" << attachmentName << "\"\n";
return false;
}
attachments[attachmentAsset->attachmentType] = attachmentAsset;
m_dependencies.emplace(attachmentAssetInfo);
}
return true;
}
_NODISCARD static bool HasMoreThanOneAttachmentSetInMask(const int mask)
{
// Check if int has more than 1 bit set
return (mask & (mask - 1)) != 0;
}
_NODISCARD bool ConvertAttachmentUniques(const cspField_t& field, const std::string& value)
{
std::vector<std::string> valueArray;
if (!ParseAsArray(value, valueArray))
{
std::cerr << "Failed to parse attachment uniques as array\n";
return false;
}
auto** attachmentUniques = reinterpret_cast<WeaponAttachmentUnique**>(reinterpret_cast<uintptr_t>(m_structure) + field.iOffset);
auto attachmentCombinationIndex = std::extent_v<decltype(WeaponFullDef::attachments)>;
for (const auto& attachmentUniqueName : valueArray)
{
auto* attachmentUniqueAssetInfo = m_loading_manager->LoadDependency<AssetAttachmentUnique>(attachmentUniqueName);
if (attachmentUniqueAssetInfo == nullptr)
{
std::cerr << "Failed to load attachment unique asset \"" << attachmentUniqueName << "\"\n";
return false;
}
auto* attachmentUniqueAsset = attachmentUniqueAssetInfo->Asset();
if (HasMoreThanOneAttachmentSetInMask(attachmentUniqueAsset->combinedAttachmentTypeMask))
{
if (attachmentCombinationIndex >= std::extent_v<decltype(WeaponFullDef::attachmentUniques)>)
{
std::cerr << "Cannot have more than "
<< (std::extent_v<decltype(WeaponFullDef::attachmentUniques)> - std::extent_v<decltype(WeaponFullDef::attachments)>)
<< " combined attachment attachment unique entries!\n";
return false;
}
attachmentUniques[attachmentCombinationIndex++] = attachmentUniqueAsset;
m_dependencies.emplace(attachmentUniqueAssetInfo);
}
else
{
if (static_cast<unsigned>(attachmentUniqueAsset->attachmentType) >= ATTACHMENT_TYPE_COUNT)
{
std::cerr << "Invalid attachment type " << attachmentUniqueAsset->attachmentType << " for attachment unique asset \""
<< attachmentUniqueName << "\"\n";
return false;
}
if (attachmentUniques[attachmentUniqueAsset->attachmentType] != nullptr)
{
std::cerr << "Already loaded attachment unique with same type " << attachmentUniqueAsset->attachmentType << ": \""
<< attachmentUniques[attachmentUniqueAsset->attachmentType]->szInternalName << "\", \"" << attachmentUniqueName << "\"\n";
return false;
}
attachmentUniques[attachmentUniqueAsset->attachmentType] = attachmentUniqueAsset;
m_dependencies.emplace(attachmentUniqueAssetInfo);
}
}
return true;
}
bool ConvertAnimName(const cspField_t& field, const std::string& value)
{
if (ConvertString(value, field.iOffset))
{
if (!value.empty())
m_indirect_asset_references.emplace(m_loading_manager->LoadIndirectAssetReference<AssetXAnim>(value));
return true;
}
return false;
}
protected:
bool ConvertExtensionField(const cspField_t& field, const std::string& value) override
{
switch (static_cast<weapFieldType_t>(field.iFieldType))
{
case WFT_WEAPONTYPE:
return ConvertEnumInt(field.szName, value, field.iOffset, szWeapTypeNames, std::extent_v<decltype(szWeapTypeNames)>);
case WFT_WEAPONCLASS:
return ConvertEnumInt(field.szName, value, field.iOffset, szWeapClassNames, std::extent_v<decltype(szWeapClassNames)>);
case WFT_OVERLAYRETICLE:
return ConvertEnumInt(field.szName, value, field.iOffset, szWeapOverlayReticleNames, std::extent_v<decltype(szWeapOverlayReticleNames)>);
case WFT_PENETRATE_TYPE:
return ConvertEnumInt(field.szName, value, field.iOffset, penetrateTypeNames, std::extent_v<decltype(penetrateTypeNames)>);
case WFT_IMPACT_TYPE:
return ConvertEnumInt(field.szName, value, field.iOffset, impactTypeNames, std::extent_v<decltype(impactTypeNames)>);
case WFT_STANCE:
return ConvertEnumInt(field.szName, value, field.iOffset, szWeapStanceNames, std::extent_v<decltype(szWeapStanceNames)>);
case WFT_PROJ_EXPLOSION:
return ConvertEnumInt(field.szName, value, field.iOffset, szProjectileExplosionNames, std::extent_v<decltype(szProjectileExplosionNames)>);
case WFT_OFFHAND_CLASS:
return ConvertEnumInt(field.szName, value, field.iOffset, offhandClassNames, std::extent_v<decltype(offhandClassNames)>);
case WFT_OFFHAND_SLOT:
return ConvertEnumInt(field.szName, value, field.iOffset, offhandSlotNames, std::extent_v<decltype(offhandSlotNames)>);
case WFT_ANIMTYPE:
return ConvertEnumInt(field.szName, value, field.iOffset, playerAnimTypeNames, std::extent_v<decltype(playerAnimTypeNames)>);
case WFT_ACTIVE_RETICLE_TYPE:
return ConvertEnumInt(field.szName, value, field.iOffset, activeReticleNames, std::extent_v<decltype(activeReticleNames)>);
case WFT_GUIDED_MISSILE_TYPE:
return ConvertEnumInt(field.szName, value, field.iOffset, guidedMissileNames, std::extent_v<decltype(guidedMissileNames)>);
case WFT_BOUNCE_SOUND:
return ConvertBounceSounds(field, value);
case WFT_STICKINESS:
return ConvertEnumInt(field.szName, value, field.iOffset, stickinessNames, std::extent_v<decltype(stickinessNames)>);
case WFT_ROTATETYPE:
return ConvertEnumInt(field.szName, value, field.iOffset, rotateTypeNames, std::extent_v<decltype(rotateTypeNames)>);
case WFT_OVERLAYINTERFACE:
return ConvertEnumInt(field.szName, value, field.iOffset, overlayInterfaceNames, std::extent_v<decltype(overlayInterfaceNames)>);
case WFT_INVENTORYTYPE:
return ConvertEnumInt(field.szName, value, field.iOffset, szWeapInventoryTypeNames, std::extent_v<decltype(szWeapInventoryTypeNames)>);
case WFT_FIRETYPE:
return ConvertEnumInt(field.szName, value, field.iOffset, szWeapFireTypeNames, std::extent_v<decltype(szWeapFireTypeNames)>);
case WFT_CLIPTYPE:
return ConvertEnumInt(field.szName, value, field.iOffset, szWeapClipTypeNames, std::extent_v<decltype(szWeapClipTypeNames)>);
case WFT_AMMOCOUNTER_CLIPTYPE:
return ConvertEnumInt(field.szName, value, field.iOffset, ammoCounterClipNames, std::extent_v<decltype(ammoCounterClipNames)>);
case WFT_ICONRATIO_HUD:
case WFT_ICONRATIO_AMMOCOUNTER:
case WFT_ICONRATIO_KILL:
case WFT_ICONRATIO_DPAD:
case WFT_ICONRATIO_INDICATOR:
return ConvertEnumInt(field.szName, value, field.iOffset, weapIconRatioNames, std::extent_v<decltype(weapIconRatioNames)>);
case WFT_BARRELTYPE:
return ConvertEnumInt(field.szName, value, field.iOffset, barrelTypeNames, std::extent_v<decltype(barrelTypeNames)>);
case WFT_HIDETAGS:
return ConvertHideTags(field, value);
case WFT_EXPLOSION_TAG:
return ConvertScriptString(value, field.iOffset);
case WFT_NOTETRACKSOUNDMAP:
return ConvertNotetrackSoundMap(field, value);
case WFT_WEAPON_CAMO:
return ConvertWeaponCamo(field, value);
case WFT_ATTACHMENTS:
return ConvertAttachments(field, value);
case WFT_ATTACHMENT_UNIQUES:
return ConvertAttachmentUniques(field, value);
case WFT_ANIM_NAME:
return ConvertAnimName(field, value);
default:
assert(false);
return false;
}
}
public:
InfoStringToWeaponConverter(const InfoString& infoString,
WeaponFullDef* weaponFullDef,
ZoneScriptStrings& zoneScriptStrings,
MemoryManager* memory,
IAssetLoadingManager* manager,
const cspField_t* fields,
const size_t fieldCount)
: InfoStringToStructConverter(infoString, weaponFullDef, zoneScriptStrings, memory, manager, fields, fieldCount)
{
}
};
void ConvertAccuracyGraph(
const GenericGraph2D& graph, vec2_t*& originalGraphKnots, int& originalGraphKnotCount, vec2_t*& graphKnots, int& graphKnotCount, MemoryManager* memory)
{
originalGraphKnotCount = static_cast<int>(graph.knots.size());
originalGraphKnots = memory->Alloc<vec2_t>(originalGraphKnotCount);
for (auto i = 0; i < originalGraphKnotCount; i++)
{
const auto& commonKnot = graph.knots[i];
originalGraphKnots[i].x = static_cast<float>(commonKnot.x);
originalGraphKnots[i].y = static_cast<float>(commonKnot.y);
}
graphKnots = originalGraphKnots;
graphKnotCount = originalGraphKnotCount;
}
bool LoadAccuracyGraphs(WeaponFullDef* weaponFullDef, MemoryManager* memory, const IAssetLoadingManager* manager)
{
auto* accuracyGraphLoader = manager->GetAssetLoadingContext()->GetZoneAssetLoaderState<AccuracyGraphLoader>();
if (weaponFullDef->weapDef.aiVsAiAccuracyGraphName && weaponFullDef->weapDef.aiVsAiAccuracyGraphName[0])
{
const auto* graph = accuracyGraphLoader->LoadAiVsAiGraph(manager, weaponFullDef->weapDef.aiVsAiAccuracyGraphName);
if (!graph)
return false;
ConvertAccuracyGraph(*graph,
weaponFullDef->weapDef.originalAiVsAiAccuracyGraphKnots,
weaponFullDef->weapDef.originalAiVsAiAccuracyGraphKnotCount,
weaponFullDef->weapDef.aiVsAiAccuracyGraphKnots,
weaponFullDef->weapDef.aiVsAiAccuracyGraphKnotCount,
memory);
}
if (weaponFullDef->weapDef.aiVsPlayerAccuracyGraphName && weaponFullDef->weapDef.aiVsPlayerAccuracyGraphName[0])
{
const auto* graph = accuracyGraphLoader->LoadAiVsPlayerGraph(manager, weaponFullDef->weapDef.aiVsPlayerAccuracyGraphName);
if (!graph)
return false;
ConvertAccuracyGraph(*graph,
weaponFullDef->weapDef.originalAiVsPlayerAccuracyGraphKnots,
weaponFullDef->weapDef.originalAiVsPlayerAccuracyGraphKnotCount,
weaponFullDef->weapDef.aiVsPlayerAccuracyGraphKnots,
weaponFullDef->weapDef.aiVsPlayerAccuracyGraphKnotCount,
memory);
}
return true;
}
} // namespace T6
void AssetLoaderWeapon::LinkWeaponFullDefSubStructs(WeaponFullDef* weapon)
{
weapon->weapVariantDef.weapDef = &weapon->weapDef;
weapon->weapVariantDef.attachments = weapon->attachments;
weapon->weapVariantDef.attachmentUniques = weapon->attachmentUniques;
weapon->weapDef.gunXModel = weapon->gunXModel;
weapon->weapVariantDef.szXAnims = weapon->szXAnims;
weapon->weapVariantDef.hideTags = weapon->hideTags;
weapon->weapDef.notetrackSoundMapKeys = weapon->notetrackSoundMapKeys;
weapon->weapDef.notetrackSoundMapValues = weapon->notetrackSoundMapValues;
weapon->weapDef.worldModel = weapon->worldModel;
weapon->weapVariantDef.attachViewModel = weapon->attachViewModel;
weapon->weapVariantDef.attachWorldModel = weapon->attachWorldModel;
weapon->weapVariantDef.attachViewModelTag = weapon->attachViewModelTag;
weapon->weapVariantDef.attachWorldModelTag = weapon->attachWorldModelTag;
weapon->weapDef.parallelBounce = weapon->parallelBounce;
weapon->weapDef.perpendicularBounce = weapon->perpendicularBounce;
weapon->weapDef.locationDamageMultipliers = weapon->locationDamageMultipliers;
}
void AssetLoaderWeapon::CalculateWeaponFields(WeaponFullDef* weapon)
{
// iAttachments
weapon->weapVariantDef.iAttachments = 0;
for (auto i = 1u; i < sizeof(WeaponVariantDef::iAttachments) * 8; i++) // Bit for default attachment always 0
{
if (weapon->attachments[i])
weapon->weapVariantDef.iAttachments |= 1 << i;
}
if (weapon->weapVariantDef.iAdsTransInTime <= 0)
weapon->weapVariantDef.fOOPosAnimLength[0] = 0.0033333334f;
else
weapon->weapVariantDef.fOOPosAnimLength[0] = 1.0f / static_cast<float>(weapon->weapVariantDef.iAdsTransInTime);
if (weapon->weapVariantDef.iAdsTransOutTime <= 0)
weapon->weapVariantDef.fOOPosAnimLength[1] = 0.0020000001f;
else
weapon->weapVariantDef.fOOPosAnimLength[1] = 1.0f / static_cast<float>(weapon->weapVariantDef.iAdsTransOutTime);
}
bool AssetLoaderWeapon::IsStringOverride(const char* baseString, const char* overrideString)
{
if (overrideString == nullptr || overrideString[0] == '\0')
return false;
if (baseString == nullptr || baseString[0] == '\0')
return true;
return strcmp(baseString, overrideString) != 0;
}
bool AssetLoaderWeapon::IsFxOverride(const FxEffectDef* baseEffect, const FxEffectDef* overrideEffect)
{
if (overrideEffect == nullptr)
return false;
if (baseEffect == nullptr)
return true;
return strcmp(baseEffect->name, overrideEffect->name) != 0;
}
void AssetLoaderWeapon::HandleSoundOverride(WeaponAttachmentUnique* attachmentUnique,
const char* snd1,
const char* snd2,
const eAttachmentOverrideSounds sndOverrideIndex)
{
if (IsStringOverride(snd1, snd2))
attachmentUnique->soundOverrides |= 1 << static_cast<unsigned>(sndOverrideIndex);
}
void AssetLoaderWeapon::HandleFxOverride(WeaponAttachmentUnique* attachmentUnique,
const FxEffectDef* effect1,
const FxEffectDef* effect2,
const eAttachmentOverrideEffects fxOverrideIndex)
{
if (IsFxOverride(effect1, effect2))
attachmentUnique->effectOverrides |= 1 << static_cast<unsigned>(fxOverrideIndex);
}
void AssetLoaderWeapon::CalculateAttachmentFields(const WeaponFullDef* weapon, unsigned attachmentIndex, WeaponAttachmentUnique* attachmentUnique)
{
for (auto& val : attachmentUnique->animationOverrides)
val = 0;
for (auto animIndex = 0u; animIndex < std::extent_v<decltype(WeaponFullDef::szXAnims)>; animIndex++)
{
if (IsStringOverride(weapon->szXAnims[animIndex], attachmentUnique->szXAnims[animIndex]))
attachmentUnique->animationOverrides[animIndex / 32] |= 1 << (animIndex % 32);
}
attachmentUnique->soundOverrides = 0;
HandleSoundOverride(attachmentUnique, weapon->weapDef.fireSound, attachmentUnique->fireSound, ATTACHMENT_OVERRIDE_SOUND_FIRE);
HandleSoundOverride(attachmentUnique, weapon->weapDef.fireSoundPlayer, attachmentUnique->fireSoundPlayer, ATTACHMENT_OVERRIDE_SOUND_FIRE_PLAYER);
HandleSoundOverride(attachmentUnique, weapon->weapDef.fireLoopSound, attachmentUnique->fireLoopSound, ATTACHMENT_OVERRIDE_SOUND_FIRE_LOOP);
HandleSoundOverride(
attachmentUnique, weapon->weapDef.fireLoopSoundPlayer, attachmentUnique->fireLoopSoundPlayer, ATTACHMENT_OVERRIDE_SOUND_FIRE_LOOP_PLAYER);
HandleSoundOverride(attachmentUnique, weapon->weapDef.fireLoopEndSound, attachmentUnique->fireLoopEndSound, ATTACHMENT_OVERRIDE_SOUND_FIRE_LOOP_END);
HandleSoundOverride(
attachmentUnique, weapon->weapDef.fireLoopEndSoundPlayer, attachmentUnique->fireLoopEndSoundPlayer, ATTACHMENT_OVERRIDE_SOUND_FIRE_LOOP_END_PLAYER);
HandleSoundOverride(attachmentUnique, weapon->weapDef.fireStartSound, attachmentUnique->fireStartSound, ATTACHMENT_OVERRIDE_SOUND_FIRE_START);
HandleSoundOverride(attachmentUnique, weapon->weapDef.fireStopSound, attachmentUnique->fireStopSound, ATTACHMENT_OVERRIDE_SOUND_FIRE_STOP);
HandleSoundOverride(
attachmentUnique, weapon->weapDef.fireStartSoundPlayer, attachmentUnique->fireStartSoundPlayer, ATTACHMENT_OVERRIDE_SOUND_FIRE_START_PLAYER);
HandleSoundOverride(
attachmentUnique, weapon->weapDef.fireStopSoundPlayer, attachmentUnique->fireStopSoundPlayer, ATTACHMENT_OVERRIDE_SOUND_FIRE_STOP_PLAYER);
HandleSoundOverride(attachmentUnique, weapon->weapDef.fireLastSound, attachmentUnique->fireLastSound, ATTACHMENT_OVERRIDE_SOUND_FIRE_LAST);
HandleSoundOverride(
attachmentUnique, weapon->weapDef.fireLastSoundPlayer, attachmentUnique->fireLastSoundPlayer, ATTACHMENT_OVERRIDE_SOUND_FIRE_LAST_PLAYER);
attachmentUnique->effectOverrides = 0;
HandleFxOverride(attachmentUnique, weapon->weapDef.viewFlashEffect, attachmentUnique->viewFlashEffect, ATTACHMENT_OVERRIDE_EFFECT_VIEW_FLASH);
HandleFxOverride(attachmentUnique, weapon->weapDef.worldFlashEffect, attachmentUnique->worldFlashEffect, ATTACHMENT_OVERRIDE_EFFECT_WORLD_FLASH);
attachmentUnique->childLink = 0;
if (attachmentUnique->combinedAttachmentTypeMask == 0)
{
WeaponAttachmentUnique* lastSibling = nullptr;
for (auto attachmentUniqueIndex = std::extent_v<decltype(WeaponFullDef::attachments)>;
attachmentUniqueIndex < std::extent_v<decltype(WeaponFullDef::attachmentUniques)>;
attachmentUniqueIndex++)
{
if (weapon->attachmentUniques[attachmentUniqueIndex] != nullptr
&& weapon->attachmentUniques[attachmentUniqueIndex]->combinedAttachmentTypeMask & (1 << static_cast<unsigned>(attachmentUnique->attachmentType))
&& weapon->attachmentUniques[attachmentUniqueIndex]->attachmentType != attachmentUnique->attachmentType)
{
std::vector<eAttachment> attachments;
if (AssetLoaderWeaponAttachmentUnique::ExtractAttachmentsFromAssetName(weapon->attachmentUniques[attachmentUniqueIndex]->szInternalName,
attachments)
&& attachments.front() == attachmentUnique->attachmentType)
{
if (lastSibling == nullptr)
{
attachmentUnique->childLink = attachmentUniqueIndex;
lastSibling = weapon->attachmentUniques[attachmentUniqueIndex];
}
else
{
lastSibling->siblingLink = attachmentUniqueIndex;
lastSibling = weapon->attachmentUniques[attachmentUniqueIndex];
}
}
}
}
}
}
void AssetLoaderWeapon::CalculateAttachmentFields(const WeaponFullDef* weapon)
{
for (auto attachmentUniqueIndex = 0u; attachmentUniqueIndex < std::extent_v<decltype(WeaponFullDef::attachmentUniques)>; attachmentUniqueIndex++)
{
if (weapon->attachmentUniques[attachmentUniqueIndex] == nullptr)
continue;
CalculateAttachmentFields(weapon, attachmentUniqueIndex, weapon->attachmentUniques[attachmentUniqueIndex]);
}
}
bool AssetLoaderWeapon::LoadFromInfoString(
const InfoString& infoString, const std::string& assetName, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone)
{
auto* weaponFullDef = memory->Create<WeaponFullDef>();
memset(weaponFullDef, 0, sizeof(WeaponFullDef));
LinkWeaponFullDefSubStructs(weaponFullDef);
InfoStringToWeaponConverter converter(
infoString, weaponFullDef, zone->m_script_strings, memory, manager, weapon_fields, std::extent_v<decltype(weapon_fields)>);
if (!converter.Convert())
{
std::cerr << "Failed to parse weapon: \"" << assetName << "\"\n";
return true;
}
weaponFullDef->weapVariantDef.szInternalName = memory->Dup(assetName.c_str());
// TODO: Load flametable
CalculateWeaponFields(weaponFullDef);
CalculateAttachmentFields(weaponFullDef);
LoadAccuracyGraphs(weaponFullDef, memory, manager);
manager->AddAsset<AssetWeapon>(
assetName, &weaponFullDef->weapVariantDef, converter.GetDependencies(), converter.GetUsedScriptStrings(), converter.GetIndirectAssetReferences());
return true;
}
void* AssetLoaderWeapon::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
{
auto* weaponFullDef = memory->Alloc<WeaponFullDef>();
LinkWeaponFullDefSubStructs(weaponFullDef);
CalculateWeaponFields(weaponFullDef);
weaponFullDef->weapVariantDef.szInternalName = memory->Dup(assetName.c_str());
return weaponFullDef;
}
bool AssetLoaderWeapon::CanLoadFromGdt() const
{
return true;
}
bool AssetLoaderWeapon::LoadFromGdt(
const std::string& assetName, IGdtQueryable* gdtQueryable, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const
{
const auto* gdtEntry = gdtQueryable->GetGdtEntryByGdfAndName(ObjConstants::GDF_FILENAME_WEAPON, assetName);
if (gdtEntry == nullptr)
return false;
InfoString infoString;
if (!infoString.FromGdtProperties(*gdtEntry))
{
std::cerr << "Failed to read weapon gdt entry: \"" << assetName << "\"\n";
return true;
}
return LoadFromInfoString(infoString, assetName, memory, manager, zone);
}
bool AssetLoaderWeapon::CanLoadFromRaw() const
{
return true;
}
bool AssetLoaderWeapon::LoadFromRaw(
const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const
{
const auto fileName = "weapons/" + assetName;
const auto file = searchPath->Open(fileName);
if (!file.IsOpen())
return false;
InfoString infoString;
if (!infoString.FromStream(ObjConstants::INFO_STRING_PREFIX_WEAPON, *file.m_stream))
{
std::cerr << "Could not parse as info string file: \"" << fileName << "\"\n";
return true;
}
return LoadFromInfoString(infoString, assetName, memory, manager, zone);
}

View File

@ -1,39 +0,0 @@
#pragma once
#include "AssetLoading/BasicAssetLoader.h"
#include "AssetLoading/IAssetLoadingManager.h"
#include "Game/T6/T6.h"
#include "InfoString/InfoString.h"
#include "SearchPath/ISearchPath.h"
namespace T6
{
class AssetLoaderWeapon final : public BasicAssetLoader<AssetWeapon>
{
static void LinkWeaponFullDefSubStructs(WeaponFullDef* weapon);
static bool IsStringOverride(const char* baseString, const char* overrideString);
static bool IsFxOverride(const FxEffectDef* baseEffect, const FxEffectDef* overrideEffect);
static void
HandleSoundOverride(WeaponAttachmentUnique* attachmentUnique, const char* snd1, const char* snd2, eAttachmentOverrideSounds sndOverrideIndex);
static void HandleFxOverride(WeaponAttachmentUnique* attachmentUnique,
const FxEffectDef* effect1,
const FxEffectDef* effect2,
eAttachmentOverrideEffects fxOverrideIndex);
static void CalculateWeaponFields(WeaponFullDef* weapon);
static void CalculateAttachmentFields(const WeaponFullDef* weapon, unsigned attachmentIndex, WeaponAttachmentUnique* attachmentUnique);
static void CalculateAttachmentFields(const WeaponFullDef* weapon);
static bool
LoadFromInfoString(const InfoString& infoString, const std::string& assetName, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone);
public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
_NODISCARD bool CanLoadFromGdt() const override;
bool LoadFromGdt(
const std::string& assetName, IGdtQueryable* gdtQueryable, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override;
_NODISCARD bool CanLoadFromRaw() const override;
bool
LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override;
};
} // namespace T6

View File

@ -1,172 +0,0 @@
#include "AssetLoaderWeaponAttachment.h"
#include "Game/T6/InfoString/EnumStrings.h"
#include "Game/T6/InfoString/InfoStringToStructConverter.h"
#include "Game/T6/InfoString/WeaponAttachmentFields.h"
#include "Game/T6/ObjConstantsT6.h"
#include "Game/T6/T6.h"
#include "InfoString/InfoString.h"
#include <cassert>
#include <cstring>
#include <iostream>
using namespace T6;
namespace T6
{
eAttachmentPoint attachmentPointByAttachmentTable[]{
ATTACHMENT_POINT_NONE, // none
ATTACHMENT_POINT_TOP, // acog
ATTACHMENT_POINT_TRIGGER, // dualclip
ATTACHMENT_POINT_TOP, // dualoptic
ATTACHMENT_POINT_BOTTOM, // dw
ATTACHMENT_POINT_MUZZLE, // extbarrel
ATTACHMENT_POINT_TRIGGER, // extclip
ATTACHMENT_POINT_TRIGGER, // extramags
ATTACHMENT_POINT_GUNPERK, // fastads
ATTACHMENT_POINT_TOP, // fastreload
ATTACHMENT_POINT_TRIGGER, // fmj
ATTACHMENT_POINT_BOTTOM, // gl
ATTACHMENT_POINT_BOTTOM, // grip
ATTACHMENT_POINT_TOP, // holo
ATTACHMENT_POINT_BOTTOM, // ir
ATTACHMENT_POINT_BOTTOM, // is
ATTACHMENT_POINT_GUNPERK, // longbreath
ATTACHMENT_POINT_BOTTOM, // mk
ATTACHMENT_POINT_TOP, // mms
ATTACHMENT_POINT_TOP, // rangefinder
ATTACHMENT_POINT_TOP, // reflex
ATTACHMENT_POINT_MUZZLE, // rf
ATTACHMENT_POINT_BOTTOM, // sf
ATTACHMENT_POINT_MUZZLE, // silencer
ATTACHMENT_POINT_TRIGGER, // stackfire
ATTACHMENT_POINT_GUNPERK, // stalker
ATTACHMENT_POINT_GUNPERK, // steadyaim
ATTACHMENT_POINT_GUNPERK, // swayreduc
ATTACHMENT_POINT_TOP, // tacknife
ATTACHMENT_POINT_TOP, // vzoom
};
static_assert(std::extent_v<decltype(attachmentPointByAttachmentTable)> == ATTACHMENT_TYPE_COUNT);
class InfoStringToWeaponAttachmentConverter final : public InfoStringToStructConverter
{
protected:
bool ConvertExtensionField(const cspField_t& field, const std::string& value) override
{
switch (static_cast<attachmentFieldType_t>(field.iFieldType))
{
case AFT_ATTACHMENTTYPE:
return ConvertEnumInt(field.szName, value, field.iOffset, szAttachmentTypeNames, std::extent_v<decltype(szAttachmentTypeNames)>);
case AFT_PENETRATE_TYPE:
return ConvertEnumInt(field.szName, value, field.iOffset, penetrateTypeNames, std::extent_v<decltype(penetrateTypeNames)>);
case AFT_FIRETYPE:
return ConvertEnumInt(field.szName, value, field.iOffset, szWeapFireTypeNames, std::extent_v<decltype(szWeapFireTypeNames)>);
default:
assert(false);
return false;
}
}
public:
InfoStringToWeaponAttachmentConverter(const InfoString& infoString,
WeaponAttachment* weaponAttachment,
ZoneScriptStrings& zoneScriptStrings,
MemoryManager* memory,
IAssetLoadingManager* manager,
const cspField_t* fields,
const size_t fieldCount)
: InfoStringToStructConverter(infoString, weaponAttachment, zoneScriptStrings, memory, manager, fields, fieldCount)
{
}
};
} // namespace T6
void AssetLoaderWeaponAttachment::CalculateAttachmentFields(WeaponAttachment* attachment)
{
// attachmentPoint
if (static_cast<unsigned>(attachment->attachmentType) < ATTACHMENT_TYPE_COUNT)
{
attachment->attachmentPoint = attachmentPointByAttachmentTable[attachment->attachmentType];
}
}
bool AssetLoaderWeaponAttachment::LoadFromInfoString(
const InfoString& infoString, const std::string& assetName, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone)
{
auto* attachment = memory->Create<WeaponAttachment>();
memset(attachment, 0, sizeof(WeaponAttachment));
InfoStringToWeaponAttachmentConverter converter(
infoString, attachment, zone->m_script_strings, memory, manager, attachment_fields, std::extent_v<decltype(attachment_fields)>);
if (!converter.Convert())
{
std::cerr << "Failed to parse attachment: \"" << assetName << "\"\n";
return true;
}
CalculateAttachmentFields(attachment);
attachment->szInternalName = memory->Dup(assetName.c_str());
manager->AddAsset<AssetAttachment>(
assetName, attachment, converter.GetDependencies(), converter.GetUsedScriptStrings(), converter.GetIndirectAssetReferences());
return true;
}
void* AssetLoaderWeaponAttachment::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
{
auto* attachment = memory->Alloc<WeaponAttachment>();
CalculateAttachmentFields(attachment);
attachment->szInternalName = memory->Dup(assetName.c_str());
return attachment;
}
bool AssetLoaderWeaponAttachment::CanLoadFromGdt() const
{
return true;
}
bool AssetLoaderWeaponAttachment::LoadFromGdt(
const std::string& assetName, IGdtQueryable* gdtQueryable, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const
{
const auto* gdtEntry = gdtQueryable->GetGdtEntryByGdfAndName(ObjConstants::GDF_FILENAME_WEAPON_ATTACHMENT, assetName);
if (gdtEntry == nullptr)
return false;
InfoString infoString;
if (!infoString.FromGdtProperties(*gdtEntry))
{
std::cerr << "Failed to read attachment gdt entry: \"" << assetName << "\"\n";
return true;
}
return LoadFromInfoString(infoString, assetName, memory, manager, zone);
}
bool AssetLoaderWeaponAttachment::CanLoadFromRaw() const
{
return true;
}
bool AssetLoaderWeaponAttachment::LoadFromRaw(
const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const
{
const auto fileName = "attachment/" + assetName;
const auto file = searchPath->Open(fileName);
if (!file.IsOpen())
return false;
InfoString infoString;
if (!infoString.FromStream(ObjConstants::INFO_STRING_PREFIX_WEAPON_ATTACHMENT, *file.m_stream))
{
std::cerr << "Could not parse as info string file: \"" << fileName << "\"\n";
return true;
}
return LoadFromInfoString(infoString, assetName, memory, manager, zone);
}

View File

@ -1,26 +0,0 @@
#pragma once
#include "AssetLoading/BasicAssetLoader.h"
#include "AssetLoading/IAssetLoadingManager.h"
#include "Game/T6/T6.h"
#include "InfoString/InfoString.h"
#include "SearchPath/ISearchPath.h"
namespace T6
{
class AssetLoaderWeaponAttachment final : public BasicAssetLoader<AssetAttachment>
{
static void CalculateAttachmentFields(WeaponAttachment* attachment);
static bool
LoadFromInfoString(const InfoString& infoString, const std::string& assetName, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone);
public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
_NODISCARD bool CanLoadFromGdt() const override;
bool LoadFromGdt(
const std::string& assetName, IGdtQueryable* gdtQueryable, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override;
_NODISCARD bool CanLoadFromRaw() const override;
bool
LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override;
};
} // namespace T6

View File

@ -1,292 +0,0 @@
#include "AssetLoaderWeaponAttachmentUnique.h"
#include "Game/T6/InfoString/EnumStrings.h"
#include "Game/T6/InfoString/InfoStringToStructConverter.h"
#include "Game/T6/InfoString/WeaponAttachmentUniqueFields.h"
#include "Game/T6/ObjConstantsT6.h"
#include "Game/T6/T6.h"
#include "InfoString/InfoString.h"
#include "Utils/ClassUtils.h"
#include <cassert>
#include <cstring>
#include <iostream>
using namespace T6;
namespace T6
{
class InfoStringToWeaponAttachmentUniqueConverter final : public InfoStringToStructConverter
{
bool ConvertHideTags(const cspField_t& field, const std::string& value)
{
std::vector<std::string> valueArray;
if (!ParseAsArray(value, valueArray))
{
std::cerr << "Failed to parse hide tags as array\n";
return false;
}
if (valueArray.size() > std::extent_v<decltype(WeaponFullDef::hideTags)>)
{
std::cerr << "Cannot have more than " << std::extent_v<decltype(WeaponFullDef::hideTags)> << " hide tags!\n";
return false;
}
auto* hideTags = reinterpret_cast<scr_string_t*>(reinterpret_cast<uintptr_t>(m_structure) + field.iOffset);
if (valueArray.size() < std::extent_v<decltype(WeaponFullDef::hideTags)>)
{
m_used_script_string_list.emplace(m_zone_script_strings.AddOrGetScriptString(nullptr));
}
auto currentHideTag = 0u;
for (; currentHideTag < valueArray.size(); currentHideTag++)
{
const auto& currentValue = valueArray[currentHideTag];
const auto scrString =
!currentValue.empty() ? m_zone_script_strings.AddOrGetScriptString(currentValue) : m_zone_script_strings.AddOrGetScriptString(nullptr);
hideTags[currentHideTag] = scrString;
m_used_script_string_list.emplace(scrString);
}
for (; currentHideTag < std::extent_v<decltype(WeaponFullDef::hideTags)>; currentHideTag++)
{
hideTags[currentHideTag] = m_zone_script_strings.GetScriptString(nullptr);
}
return true;
}
_NODISCARD bool ConvertWeaponCamo(const cspField_t& field, const std::string& value)
{
if (value.empty())
{
*reinterpret_cast<WeaponCamo**>(reinterpret_cast<uintptr_t>(m_structure) + field.iOffset) = nullptr;
return true;
}
auto* camo = m_loading_manager->LoadDependency<AssetWeaponCamo>(value);
if (camo == nullptr)
{
std::cerr << "Failed to load camo asset \"" << value << "\"\n";
return false;
}
m_dependencies.emplace(camo);
*reinterpret_cast<WeaponCamo**>(reinterpret_cast<uintptr_t>(m_structure) + field.iOffset) = camo->Asset();
return true;
}
bool ConvertAnimName(const cspField_t& field, const std::string& value)
{
if (ConvertString(value, field.iOffset))
{
if (!value.empty())
m_indirect_asset_references.emplace(m_loading_manager->LoadIndirectAssetReference<AssetXAnim>(value));
return true;
}
return false;
}
protected:
bool ConvertExtensionField(const cspField_t& field, const std::string& value) override
{
switch (static_cast<attachmentUniqueFieldType_t>(field.iFieldType))
{
case AUFT_ATTACHMENTTYPE:
return ConvertEnumInt(field.szName, value, field.iOffset, szAttachmentTypeNames, std::extent_v<decltype(szAttachmentTypeNames)>);
case AUFT_HIDETAGS:
return ConvertHideTags(field, value);
case AUFT_OVERLAYRETICLE:
return ConvertEnumInt(field.szName, value, field.iOffset, szWeapOverlayReticleNames, std::extent_v<decltype(szWeapOverlayReticleNames)>);
case AUFT_CAMO:
return ConvertWeaponCamo(field, value);
case AUFT_ANIM_NAME:
return ConvertAnimName(field, value);
default:
assert(false);
return false;
}
}
public:
InfoStringToWeaponAttachmentUniqueConverter(const InfoString& infoString,
WeaponAttachmentUniqueFull* attachmentUniqueFull,
ZoneScriptStrings& zoneScriptStrings,
MemoryManager* memory,
IAssetLoadingManager* manager,
const cspField_t* fields,
const size_t fieldCount)
: InfoStringToStructConverter(infoString, attachmentUniqueFull, zoneScriptStrings, memory, manager, fields, fieldCount)
{
}
};
} // namespace T6
bool AssetLoaderWeaponAttachmentUnique::ExtractAttachmentsFromAssetName(const std::string& assetName, std::vector<eAttachment>& attachmentList)
{
std::vector<std::string> parts;
auto attachCount = 1u;
auto partStart = 0u;
for (auto ci = 0u; ci < assetName.size(); ci++)
{
if (assetName[ci] == '_')
{
parts.emplace_back(assetName, partStart, ci - partStart);
partStart = ci + 1;
}
else if (assetName[ci] == '+')
{
attachCount++;
parts.emplace_back(assetName, partStart, ci - partStart);
partStart = ci + 1;
}
}
if (partStart < assetName.size())
parts.emplace_back(assetName, partStart, assetName.size() - partStart);
for (auto attachPartOffset = parts.size() - attachCount; attachPartOffset < parts.size(); attachPartOffset++)
{
auto& specifiedAttachName = parts[attachPartOffset];
for (auto& c : specifiedAttachName)
c = static_cast<char>(tolower(c));
auto foundAttachment = false;
for (auto attachIndex = 0u; attachIndex < std::extent_v<decltype(szAttachmentTypeNames)>; attachIndex++)
{
if (specifiedAttachName == szAttachmentTypeNames[attachIndex])
{
attachmentList.push_back(static_cast<eAttachment>(attachIndex));
foundAttachment = true;
break;
}
}
if (!foundAttachment)
return false;
}
return true;
}
void AssetLoaderWeaponAttachmentUnique::LinkAttachmentUniqueFullSubStructs(WeaponAttachmentUniqueFull* attachmentUnique)
{
attachmentUnique->attachment.hideTags = attachmentUnique->hideTags;
attachmentUnique->attachment.szXAnims = attachmentUnique->szXAnims;
attachmentUnique->attachment.locationDamageMultipliers = attachmentUnique->locationDamageMultipliers;
}
bool AssetLoaderWeaponAttachmentUnique::CalculateAttachmentUniqueFields(const std::string& assetName, WeaponAttachmentUniqueFull* attachmentUnique)
{
// combinedAttachmentTypeMask
std::vector<eAttachment> attachmentsFromName;
if (!ExtractAttachmentsFromAssetName(assetName, attachmentsFromName))
{
std::cerr << "Failed to determine attachments from attachment unique name \"" << assetName << "\"\n";
return false;
}
if (attachmentsFromName.size() > 1)
{
for (const auto attachment : attachmentsFromName)
{
attachmentUnique->attachment.combinedAttachmentTypeMask |= 1 << attachment;
}
}
return true;
}
bool AssetLoaderWeaponAttachmentUnique::LoadFromInfoString(
const InfoString& infoString, const std::string& assetName, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone)
{
auto* attachmentUniqueFull = memory->Create<WeaponAttachmentUniqueFull>();
memset(attachmentUniqueFull, 0, sizeof(WeaponAttachmentUniqueFull));
LinkAttachmentUniqueFullSubStructs(attachmentUniqueFull);
InfoStringToWeaponAttachmentUniqueConverter converter(
infoString, attachmentUniqueFull, zone->m_script_strings, memory, manager, attachment_unique_fields, std::extent_v<decltype(attachment_unique_fields)>);
if (!converter.Convert())
{
std::cerr << "Failed to parse attachment unique: \"" << assetName << "\"\n";
return true;
}
if (!CalculateAttachmentUniqueFields(assetName, attachmentUniqueFull))
return true;
attachmentUniqueFull->attachment.szInternalName = memory->Dup(assetName.c_str());
manager->AddAsset<AssetAttachmentUnique>(
assetName, &attachmentUniqueFull->attachment, converter.GetDependencies(), converter.GetUsedScriptStrings(), converter.GetIndirectAssetReferences());
return true;
}
void* AssetLoaderWeaponAttachmentUnique::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
{
auto* attachmentUniqueFull = memory->Alloc<WeaponAttachmentUniqueFull>();
LinkAttachmentUniqueFullSubStructs(attachmentUniqueFull);
CalculateAttachmentUniqueFields(assetName, attachmentUniqueFull);
attachmentUniqueFull->attachment.szInternalName = memory->Dup(assetName.c_str());
return attachmentUniqueFull;
}
bool AssetLoaderWeaponAttachmentUnique::CanLoadFromGdt() const
{
return true;
}
bool AssetLoaderWeaponAttachmentUnique::LoadFromGdt(
const std::string& assetName, IGdtQueryable* gdtQueryable, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const
{
const auto* gdtEntry = gdtQueryable->GetGdtEntryByGdfAndName(ObjConstants::GDF_FILENAME_WEAPON_ATTACHMENT_UNIQUE, assetName);
if (gdtEntry == nullptr)
return false;
InfoString infoString;
if (!infoString.FromGdtProperties(*gdtEntry))
{
std::cerr << "Failed to read attachment unique gdt entry: \"" << assetName << "\"\n";
return true;
}
return LoadFromInfoString(infoString, assetName, memory, manager, zone);
}
bool AssetLoaderWeaponAttachmentUnique::CanLoadFromRaw() const
{
return true;
}
bool AssetLoaderWeaponAttachmentUnique::LoadFromRaw(
const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const
{
const auto fileName = "attachmentunique/" + assetName;
const auto file = searchPath->Open(fileName);
if (!file.IsOpen())
return false;
InfoString infoString;
if (!infoString.FromStream(ObjConstants::INFO_STRING_PREFIX_WEAPON_ATTACHMENT_UNIQUE, *file.m_stream))
{
std::cerr << "Could not parse as info string file: \"" << fileName << "\"\n";
return true;
}
return LoadFromInfoString(infoString, assetName, memory, manager, zone);
}

View File

@ -1,29 +0,0 @@
#pragma once
#include "AssetLoading/BasicAssetLoader.h"
#include "AssetLoading/IAssetLoadingManager.h"
#include "Game/T6/T6.h"
#include "InfoString/InfoString.h"
#include "SearchPath/ISearchPath.h"
namespace T6
{
class AssetLoaderWeaponAttachmentUnique final : public BasicAssetLoader<AssetAttachmentUnique>
{
static void LinkAttachmentUniqueFullSubStructs(WeaponAttachmentUniqueFull* attachmentUnique);
static bool CalculateAttachmentUniqueFields(const std::string& assetName, WeaponAttachmentUniqueFull* attachmentUnique);
static bool
LoadFromInfoString(const InfoString& infoString, const std::string& assetName, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone);
public:
static bool ExtractAttachmentsFromAssetName(const std::string& assetName, std::vector<eAttachment>& attachmentList);
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
_NODISCARD bool CanLoadFromGdt() const override;
bool LoadFromGdt(
const std::string& assetName, IGdtQueryable* gdtQueryable, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override;
_NODISCARD bool CanLoadFromRaw() const override;
bool
LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override;
};
} // namespace T6

View File

@ -1,43 +0,0 @@
#include "AssetLoaderWeaponCamo.h"
#include "Game/T6/T6.h"
#include "Game/T6/WeaponCamo/JsonWeaponCamoLoader.h"
#include "Pool/GlobalAssetPool.h"
#include <cstring>
#include <format>
#include <iostream>
using namespace T6;
void* AssetLoaderWeaponCamo::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
{
auto* asset = memory->Alloc<AssetWeaponCamo::Type>();
asset->name = memory->Dup(assetName.c_str());
return asset;
}
bool AssetLoaderWeaponCamo::CanLoadFromRaw() const
{
return true;
}
bool AssetLoaderWeaponCamo::LoadFromRaw(
const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const
{
const auto fileName = std::format("camo/{}.json", assetName);
const auto file = searchPath->Open(fileName);
if (!file.IsOpen())
return false;
auto* weaponCamo = memory->Alloc<WeaponCamo>();
weaponCamo->name = memory->Dup(assetName.c_str());
std::vector<XAssetInfoGeneric*> dependencies;
if (LoadWeaponCamoAsJson(*file.m_stream, *weaponCamo, memory, manager, dependencies))
manager->AddAsset<AssetWeaponCamo>(assetName, weaponCamo, std::move(dependencies));
else
std::cerr << "Failed to load weapon camo \"" << assetName << "\"\n";
return true;
}

View File

@ -1,17 +0,0 @@
#pragma once
#include "AssetLoading/BasicAssetLoader.h"
#include "AssetLoading/IAssetLoadingManager.h"
#include "Game/T6/T6.h"
#include "SearchPath/ISearchPath.h"
namespace T6
{
class AssetLoaderWeaponCamo final : public BasicAssetLoader<AssetWeaponCamo>
{
public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
_NODISCARD bool CanLoadFromRaw() const override;
bool
LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override;
};
} // namespace T6

View File

@ -1,13 +0,0 @@
#include "AssetLoaderXAnim.h"
#include "Game/T6/T6.h"
#include "ObjLoading.h"
using namespace T6;
void* AssetLoaderXAnim::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
{
auto* asset = memory->Alloc<AssetXAnim::Type>();
asset->name = memory->Dup(assetName.c_str());
return asset;
}

View File

@ -1,14 +0,0 @@
#pragma once
#include "AssetLoading/BasicAssetLoader.h"
#include "Game/T6/T6.h"
#include "SearchPath/ISearchPath.h"
namespace T6
{
class AssetLoaderXAnim final : public BasicAssetLoader<AssetXAnim>
{
public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
};
} // namespace T6

View File

@ -1,13 +0,0 @@
#include "AssetLoaderXGlobals.h"
#include "Game/T6/T6.h"
#include "ObjLoading.h"
using namespace T6;
void* AssetLoaderXGlobals::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
{
auto* asset = memory->Alloc<AssetXGlobals::Type>();
asset->name = memory->Dup(assetName.c_str());
return asset;
}

View File

@ -1,14 +0,0 @@
#pragma once
#include "AssetLoading/BasicAssetLoader.h"
#include "Game/T6/T6.h"
#include "SearchPath/ISearchPath.h"
namespace T6
{
class AssetLoaderXGlobals final : public BasicAssetLoader<AssetXGlobals>
{
public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
};
} // namespace T6

View File

@ -1,47 +0,0 @@
#include "AssetLoaderXModel.h"
#include "Game/T6/T6.h"
#include "Game/T6/XModel/XModelLoaderT6.h"
#include "Pool/GlobalAssetPool.h"
#include <cstring>
#include <format>
#include <iostream>
using namespace T6;
void* AssetLoaderXModel::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
{
auto* asset = memory->Alloc<AssetXModel::Type>();
asset->name = memory->Dup(assetName.c_str());
return asset;
}
bool AssetLoaderXModel::CanLoadFromRaw() const
{
return true;
}
bool AssetLoaderXModel::LoadFromRaw(
const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const
{
const auto file = searchPath->Open(std::format("xmodel/{}.json", assetName));
if (!file.IsOpen())
return false;
auto* xmodel = memory->Alloc<XModel>();
xmodel->name = memory->Dup(assetName.c_str());
std::vector<XAssetInfoGeneric*> dependencies;
if (LoadXModel(*file.m_stream, *xmodel, memory, manager, dependencies))
{
manager->AddAsset<AssetXModel>(assetName, xmodel, std::move(dependencies));
}
else
{
std::cerr << std::format("Failed to load xmodel \"{}\"\n", assetName);
return false;
}
return true;
}

View File

@ -1,19 +0,0 @@
#pragma once
#include "AssetLoading/BasicAssetLoader.h"
#include "AssetLoading/IAssetLoadingManager.h"
#include "Game/T6/T6.h"
#include "SearchPath/ISearchPath.h"
namespace T6
{
class AssetLoaderXModel final : public BasicAssetLoader<AssetXModel>
{
static std::string GetFileNameForAsset(const std::string& assetName);
public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
_NODISCARD bool CanLoadFromRaw() const override;
bool
LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override;
};
} // namespace T6

View File

@ -1,133 +0,0 @@
#include "AssetLoaderZBarrier.h"
#include "Game/T6/InfoString/InfoStringToStructConverter.h"
#include "Game/T6/InfoString/ZBarrierFields.h"
#include "Game/T6/ObjConstantsT6.h"
#include "Game/T6/T6.h"
#include "InfoString/InfoString.h"
#include <cassert>
#include <cstring>
#include <iostream>
using namespace T6;
namespace T6
{
class InfoStringToZBarrierConverter final : public InfoStringToStructConverter
{
protected:
bool ConvertExtensionField(const cspField_t& field, const std::string& value) override
{
assert(false);
return false;
}
public:
InfoStringToZBarrierConverter(const InfoString& infoString,
ZBarrierDef* zbarrier,
ZoneScriptStrings& zoneScriptStrings,
MemoryManager* memory,
IAssetLoadingManager* manager,
const cspField_t* fields,
const size_t fieldCount)
: InfoStringToStructConverter(infoString, zbarrier, zoneScriptStrings, memory, manager, fields, fieldCount)
{
}
};
} // namespace T6
void AssetLoaderZBarrier::CalculateZBarrierFields(ZBarrierDef* zbarrier)
{
// numBoardsInBarrier
{
auto foundEnd = false;
for (auto i = 0u; i < std::extent_v<decltype(ZBarrierDef::boards)>; i++)
{
if (zbarrier->boards[i].pBoardModel == nullptr)
{
foundEnd = true;
zbarrier->numBoardsInBarrier = i;
break;
}
}
if (!foundEnd)
zbarrier->numBoardsInBarrier = std::extent_v<decltype(ZBarrierDef::boards)>;
}
}
bool AssetLoaderZBarrier::LoadFromInfoString(
const InfoString& infoString, const std::string& assetName, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone)
{
auto* zbarrier = memory->Create<ZBarrierDef>();
memset(zbarrier, 0, sizeof(ZBarrierDef));
InfoStringToZBarrierConverter converter(
infoString, zbarrier, zone->m_script_strings, memory, manager, zbarrier_fields, std::extent_v<decltype(zbarrier_fields)>);
if (!converter.Convert())
{
std::cout << "Failed to parse zbarrier: \"" << assetName << "\"\n";
return true;
}
CalculateZBarrierFields(zbarrier);
zbarrier->name = memory->Dup(assetName.c_str());
manager->AddAsset<AssetZBarrier>(assetName, zbarrier, converter.GetDependencies(), converter.GetUsedScriptStrings());
return true;
}
void* AssetLoaderZBarrier::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
{
auto* zbarrier = memory->Alloc<ZBarrierDef>();
CalculateZBarrierFields(zbarrier);
zbarrier->name = memory->Dup(assetName.c_str());
return zbarrier;
}
bool AssetLoaderZBarrier::CanLoadFromGdt() const
{
return true;
}
bool AssetLoaderZBarrier::LoadFromGdt(
const std::string& assetName, IGdtQueryable* gdtQueryable, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const
{
auto* gdtEntry = gdtQueryable->GetGdtEntryByGdfAndName(ObjConstants::GDF_FILENAME_ZBARRIER, assetName);
if (gdtEntry == nullptr)
return false;
InfoString infoString;
if (!infoString.FromGdtProperties(*gdtEntry))
{
std::cout << "Failed to read zbarrier gdt entry: \"" << assetName << "\"\n";
return true;
}
return LoadFromInfoString(infoString, assetName, memory, manager, zone);
}
bool AssetLoaderZBarrier::CanLoadFromRaw() const
{
return true;
}
bool AssetLoaderZBarrier::LoadFromRaw(
const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const
{
const auto fileName = "zbarrier/" + assetName;
const auto file = searchPath->Open(fileName);
if (!file.IsOpen())
return false;
InfoString infoString;
if (!infoString.FromStream(ObjConstants::INFO_STRING_PREFIX_ZBARRIER, *file.m_stream))
{
std::cerr << "Could not parse as info string file: \"" << fileName << "\"\n";
return true;
}
return LoadFromInfoString(infoString, assetName, memory, manager, zone);
}

View File

@ -1,26 +0,0 @@
#pragma once
#include "AssetLoading/BasicAssetLoader.h"
#include "AssetLoading/IAssetLoadingManager.h"
#include "Game/T6/T6.h"
#include "InfoString/InfoString.h"
#include "SearchPath/ISearchPath.h"
namespace T6
{
class AssetLoaderZBarrier final : public BasicAssetLoader<AssetZBarrier>
{
static void CalculateZBarrierFields(ZBarrierDef* zbarrier);
static bool
LoadFromInfoString(const InfoString& infoString, const std::string& assetName, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone);
public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
_NODISCARD bool CanLoadFromGdt() const override;
bool LoadFromGdt(
const std::string& assetName, IGdtQueryable* gdtQueryable, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override;
_NODISCARD bool CanLoadFromRaw() const override;
bool
LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override;
};
} // namespace T6

View File

@ -0,0 +1,292 @@
#include "LoaderFontIconT6.h"
#include "Csv/CsvStream.h"
#include "Game/T6/CommonT6.h"
#include "Game/T6/T6.h"
#include <algorithm>
#include <cstring>
#include <format>
#include <sstream>
using namespace T6;
namespace
{
constexpr unsigned ROW_INDEX = 0;
constexpr unsigned ROW_TYPE = 1;
constexpr unsigned ROW_ICON_NAME = 2;
constexpr unsigned ROW_ICON_MATERIAL = 3;
constexpr unsigned ROW_ICON_SIZE = 4;
constexpr unsigned ROW_ICON_XSCALE = 5;
constexpr unsigned ROW_ICON_YSCALE = 6;
constexpr unsigned ROW_ALIAS_NAME = 2;
constexpr unsigned ROW_ALIAS_BUTTON = 3;
constexpr const char* VALUE_TYPE_ICON = "icon";
constexpr const char* VALUE_TYPE_ALIAS = "alias";
constexpr unsigned COL_COUNT_ICON = 7;
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>
{
public:
FontIconLoader(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(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);
const CsvInputStream csv(*file.m_stream);
std::vector<std::string> currentRow;
std::vector<FontIconEntry> entries;
std::vector<FontIconAlias> aliases;
auto currentRowIndex = 0u;
while (csv.NextRow(currentRow))
{
currentRowIndex++;
PreprocessRow(currentRow);
if (RowIsEmpty(currentRow))
continue;
if (currentRow.size() < COL_COUNT_MIN)
{
std::cerr << std::format("{} Column count lower than min column count ({})\n", 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));
return AssetCreationResult::Failure();
}
if (currentRow[ROW_TYPE] == VALUE_TYPE_ICON)
{
FontIconEntry icon{};
if (!ReadIconRow(currentRow, icon, assetName, currentRowIndex, context, registration))
return AssetCreationResult::Failure();
if (static_cast<unsigned>(index) == entries.size())
{
entries.push_back(icon);
}
else if (static_cast<unsigned>(index) > entries.size())
{
entries.reserve(index + 1);
entries[index] = icon;
}
else
{
entries[index] = icon;
}
}
else if (currentRow[ROW_TYPE] == VALUE_TYPE_ALIAS)
{
FontIconAlias alias{};
if (!ReadAliasRow(currentRow, alias, assetName, currentRowIndex, context))
return AssetCreationResult::Failure();
if (static_cast<unsigned>(index) == aliases.size())
{
aliases.push_back(alias);
}
else if (static_cast<unsigned>(index) > aliases.size())
{
aliases.reserve(index + 1);
aliases[index] = alias;
}
else
{
aliases[index] = alias;
}
}
else
{
std::cerr << std::format("{} Unknown row type \"{}\"\n", ErrorPrefix(assetName, currentRowIndex), currentRow[ROW_TYPE]);
return AssetCreationResult::Failure();
}
}
fontIcon->numEntries = entries.size();
fontIcon->numAliasEntries = aliases.size();
if (fontIcon->numEntries > 0)
{
fontIcon->fontIconEntry = m_memory.Alloc<FontIconEntry>(fontIcon->numEntries);
for (auto i = 0u; i < entries.size(); i++)
fontIcon->fontIconEntry[i] = entries[i];
}
else
fontIcon->fontIconEntry = nullptr;
if (fontIcon->numAliasEntries > 0)
{
fontIcon->fontIconAlias = m_memory.Alloc<FontIconAlias>(fontIcon->numAliasEntries);
for (auto i = 0u; i < aliases.size(); i++)
fontIcon->fontIconAlias[i] = aliases[i];
}
else
fontIcon->fontIconAlias = nullptr;
return AssetCreationResult::Success(context.AddAsset(std::move(registration)));
}
private:
static std::string ErrorPrefix(const std::string& assetName, const unsigned rowIndex)
{
return std::format("FontIcon \"{}\" Row {}:", assetName, rowIndex);
}
static void PreprocessRow(std::vector<std::string>& row)
{
for (auto& cell : row)
{
for (auto c : cell)
{
if (isspace(c))
continue;
if (c == '#')
cell = "";
break;
}
}
}
static bool RowIsEmpty(const std::vector<std::string>& row)
{
return std::ranges::all_of(row,
[](const std::string& cell)
{
return cell.empty();
});
}
static bool ParseInt(int& value, const std::string& str)
{
char* endPtr;
value = strtol(str.c_str(), &endPtr, 0);
if (endPtr != &str[str.size()])
return false;
return true;
}
static bool ParseFloat(float& value, const std::string& str)
{
char* endPtr;
value = strtof(str.c_str(), &endPtr);
if (endPtr != &str[str.size()])
return false;
return true;
}
static bool ParseHashStr(int& value, const std::string& str)
{
if (!str.empty() && str[0] == '@' && str.size() > 1)
{
char* endPtr;
value = strtol(&str[1], &endPtr, 16);
if (endPtr != &str[str.size()])
return false;
}
else
{
value = Common::Com_HashString(str.c_str());
}
return true;
}
bool ReadIconRow(const std::vector<std::string>& row,
FontIconEntry& icon,
const std::string& assetName,
const unsigned rowIndex,
AssetCreationContext& context,
AssetRegistration<AssetFontIcon>& registration)
{
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);
return false;
}
if (!ParseInt(icon.fontIconSize, row[ROW_ICON_SIZE]))
{
std::cerr << std::format("{} Failed to parse size\n", 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));
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]);
return false;
}
icon.fontIconMaterialHandle = materialDependency->Asset();
icon.fontIconName.string = m_memory.Dup(row[ROW_ICON_NAME].c_str());
icon.fontIconName.hash = Common::Com_HashString(icon.fontIconName.string);
return true;
}
bool ReadAliasRow(
const std::vector<std::string>& row, FontIconAlias& alias, const std::string& assetName, const unsigned rowIndex, AssetCreationContext& context)
{
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);
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]);
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]);
return false;
}
return true;
}
MemoryManager& m_memory;
ISearchPath& m_search_path;
};
} // namespace
namespace T6
{
std::unique_ptr<AssetCreator<AssetFontIcon>> CreateFontIconLoader(MemoryManager& memory, ISearchPath& searchPath)
{
return std::make_unique<FontIconLoader>(memory, searchPath);
}
} // namespace T6

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