mirror of
https://github.com/Laupetin/OpenAssetTools.git
synced 2025-06-20 11:47:55 -05:00
Reformat code with clang format
This commit is contained in:
@ -23,123 +23,105 @@ class AssetDumperFontIconInternal
|
||||
};
|
||||
|
||||
inline static const std::string TYPE_ICON = "icon";
|
||||
inline static const std::string ICON_HEADERS[]
|
||||
{
|
||||
"# index",
|
||||
"# type",
|
||||
"# name",
|
||||
"# material",
|
||||
"# size",
|
||||
"# xScale",
|
||||
"# yScale"
|
||||
};
|
||||
inline static const std::string ICON_HEADERS[]{"# index", "# type", "# name", "# material", "# size", "# xScale", "# yScale"};
|
||||
|
||||
inline static const std::string TYPE_ALIAS = "alias";
|
||||
inline static const std::string ALIAS_HEADERS[]
|
||||
{
|
||||
"# index",
|
||||
"# type",
|
||||
"# alias",
|
||||
"# button"
|
||||
};
|
||||
inline static const std::string ALIAS_HEADERS[]{"# index", "# type", "# alias", "# button"};
|
||||
|
||||
inline static const KnownAlias KNOWN_ALIASES[]
|
||||
{
|
||||
KnownAlias("BUTTON_ADS"),
|
||||
KnownAlias("BUTTON_CAC_NEXT"),
|
||||
KnownAlias("BUTTON_CAC_PREV"),
|
||||
KnownAlias("BUTTON_CANCEL"),
|
||||
KnownAlias("BUTTON_CAROUSEL_STICK"),
|
||||
KnownAlias("BUTTON_CREATE"),
|
||||
KnownAlias("BUTTON_CYCLE_LEFT"),
|
||||
KnownAlias("BUTTON_CYCLE_LEFT_ACTIVE"),
|
||||
KnownAlias("BUTTON_CYCLE_RIGHT"),
|
||||
KnownAlias("BUTTON_CYCLE_RIGHT_ACTIVE"),
|
||||
KnownAlias("BUTTON_DELETE"),
|
||||
KnownAlias("BUTTON_EDIT"),
|
||||
KnownAlias("BUTTON_EMBLEM_BACKWARD"),
|
||||
KnownAlias("BUTTON_EMBLEM_FLIP"),
|
||||
KnownAlias("BUTTON_EMBLEM_FORWARD"),
|
||||
KnownAlias("BUTTON_EMBLEM_FORWARD_BACKWARD"),
|
||||
KnownAlias("BUTTON_EMBLEM_MOVE"),
|
||||
KnownAlias("BUTTON_EMBLEM_OUTLINE"),
|
||||
KnownAlias("BUTTON_EMBLEM_PALETTE_CYCLE"),
|
||||
KnownAlias("BUTTON_EMBLEM_PALETTE_NEXT"),
|
||||
KnownAlias("BUTTON_EMBLEM_PALETTE_PREV"),
|
||||
KnownAlias("BUTTON_EMBLEM_RESET"),
|
||||
KnownAlias("BUTTON_EMBLEM_ROTATE_LEFT"),
|
||||
KnownAlias("BUTTON_EMBLEM_ROTATE_RIGHT"),
|
||||
KnownAlias("BUTTON_EMBLEM_SCALE"),
|
||||
KnownAlias("BUTTON_FIRE"),
|
||||
KnownAlias("BUTTON_FRIENDSLIST"),
|
||||
KnownAlias("BUTTON_INTERACT"),
|
||||
KnownAlias("BUTTON_LOOKSTICK"),
|
||||
KnownAlias("BUTTON_LOOK"),
|
||||
KnownAlias("BUTTON_LUI_ALT1"),
|
||||
KnownAlias("BUTTON_LUI_ALT2"),
|
||||
KnownAlias("BUTTON_LUI_DPAD_ALL"),
|
||||
KnownAlias("BUTTON_LUI_DPAD_D"),
|
||||
KnownAlias("BUTTON_LUI_DPAD_L"),
|
||||
KnownAlias("BUTTON_LUI_DPAD_RL"),
|
||||
KnownAlias("BUTTON_LUI_DPAD_R"),
|
||||
KnownAlias("BUTTON_LUI_DPAD_UD"),
|
||||
KnownAlias("BUTTON_LUI_DPAD_U"),
|
||||
KnownAlias("BUTTON_LUI_LEFT_STICK_UP"),
|
||||
KnownAlias("BUTTON_LUI_LEFT_TRIGGER"),
|
||||
KnownAlias("BUTTON_LUI_PRIMARY"),
|
||||
KnownAlias("BUTTON_LUI_RIGHT_STICK"),
|
||||
KnownAlias("BUTTON_LUI_RIGHT_TRIGGER"),
|
||||
KnownAlias("BUTTON_LUI_SECONDARY"),
|
||||
KnownAlias("BUTTON_LUI_SELECT"),
|
||||
KnownAlias("BUTTON_LUI_SHOULDERL"),
|
||||
KnownAlias("BUTTON_LUI_SHOULDERR"),
|
||||
KnownAlias("BUTTON_LUI_START"),
|
||||
KnownAlias("BUTTON_MOUSE_CLICK"),
|
||||
KnownAlias("BUTTON_MOUSE_CLICK_ACTIVE"),
|
||||
KnownAlias("BUTTON_MOUSE_EDIT"),
|
||||
KnownAlias("BUTTON_MOUSE_EDIT_ACTIVE"),
|
||||
KnownAlias("BUTTON_MOUSE_LEFT"),
|
||||
KnownAlias("BUTTON_MOUSE_MIDDLE"),
|
||||
KnownAlias("BUTTON_MOUSE_RIGHT"),
|
||||
KnownAlias("BUTTON_MOVESTICK"),
|
||||
KnownAlias("BUTTON_MOVE"),
|
||||
KnownAlias("BUTTON_MP_CANCELCOMMAND"),
|
||||
KnownAlias("BUTTON_MP_CHANGESETTINGS"),
|
||||
KnownAlias("BUTTON_MP_GAMERCARD"),
|
||||
KnownAlias("BUTTON_MP_GAMERREVIEW"),
|
||||
KnownAlias("BUTTON_MP_JOINGAME"),
|
||||
KnownAlias("BUTTON_MP_KICKPLAYER"),
|
||||
KnownAlias("BUTTON_MP_LEAVEGAME"),
|
||||
KnownAlias("BUTTON_MP_LOBBY_GAMERCARD"),
|
||||
KnownAlias("BUTTON_MP_NOTREADY"),
|
||||
KnownAlias("BUTTON_MP_PGDOWN"),
|
||||
KnownAlias("BUTTON_MP_PGUP"),
|
||||
KnownAlias("BUTTON_MP_READY"),
|
||||
KnownAlias("BUTTON_MP_REFRESH"),
|
||||
KnownAlias("BUTTON_MP_SCOREBOARD"),
|
||||
KnownAlias("BUTTON_MP_SIGNIN"),
|
||||
KnownAlias("BUTTON_MP_SPECNEXT"),
|
||||
KnownAlias("BUTTON_MP_SPECPREV"),
|
||||
KnownAlias("BUTTON_MP_STARTGAME"),
|
||||
KnownAlias("BUTTON_MP_TOGGLECHASECAM"),
|
||||
KnownAlias("BUTTON_MP_TOGGLEVIEW"),
|
||||
KnownAlias("BUTTON_NO"),
|
||||
KnownAlias("BUTTON_RECORD_VIEW_NEXT"),
|
||||
KnownAlias("BUTTON_RECORD_VIEW_PREV"),
|
||||
KnownAlias("BUTTON_SELECTCHOICE"),
|
||||
KnownAlias("BUTTON_SP_TOGGLEMENU"),
|
||||
KnownAlias("BUTTON_YES"),
|
||||
KnownAlias("CP"),
|
||||
KnownAlias("FONT_CAPITAL_I"),
|
||||
KnownAlias("FONT_NUMBER_ZERO"),
|
||||
KnownAlias("KEY_DOWN_ARROW"),
|
||||
KnownAlias("KEY_LEFT_ARROW"),
|
||||
KnownAlias("KEY_RIGHT_ARROW"),
|
||||
KnownAlias("KEY_UP_ARROW"),
|
||||
KnownAlias("MOUSE_WHEEL_DOWN"),
|
||||
KnownAlias("MOUSE_WHEEL_UP"),
|
||||
KnownAlias("Remote_LStick")
|
||||
};
|
||||
inline static const KnownAlias KNOWN_ALIASES[]{KnownAlias("BUTTON_ADS"),
|
||||
KnownAlias("BUTTON_CAC_NEXT"),
|
||||
KnownAlias("BUTTON_CAC_PREV"),
|
||||
KnownAlias("BUTTON_CANCEL"),
|
||||
KnownAlias("BUTTON_CAROUSEL_STICK"),
|
||||
KnownAlias("BUTTON_CREATE"),
|
||||
KnownAlias("BUTTON_CYCLE_LEFT"),
|
||||
KnownAlias("BUTTON_CYCLE_LEFT_ACTIVE"),
|
||||
KnownAlias("BUTTON_CYCLE_RIGHT"),
|
||||
KnownAlias("BUTTON_CYCLE_RIGHT_ACTIVE"),
|
||||
KnownAlias("BUTTON_DELETE"),
|
||||
KnownAlias("BUTTON_EDIT"),
|
||||
KnownAlias("BUTTON_EMBLEM_BACKWARD"),
|
||||
KnownAlias("BUTTON_EMBLEM_FLIP"),
|
||||
KnownAlias("BUTTON_EMBLEM_FORWARD"),
|
||||
KnownAlias("BUTTON_EMBLEM_FORWARD_BACKWARD"),
|
||||
KnownAlias("BUTTON_EMBLEM_MOVE"),
|
||||
KnownAlias("BUTTON_EMBLEM_OUTLINE"),
|
||||
KnownAlias("BUTTON_EMBLEM_PALETTE_CYCLE"),
|
||||
KnownAlias("BUTTON_EMBLEM_PALETTE_NEXT"),
|
||||
KnownAlias("BUTTON_EMBLEM_PALETTE_PREV"),
|
||||
KnownAlias("BUTTON_EMBLEM_RESET"),
|
||||
KnownAlias("BUTTON_EMBLEM_ROTATE_LEFT"),
|
||||
KnownAlias("BUTTON_EMBLEM_ROTATE_RIGHT"),
|
||||
KnownAlias("BUTTON_EMBLEM_SCALE"),
|
||||
KnownAlias("BUTTON_FIRE"),
|
||||
KnownAlias("BUTTON_FRIENDSLIST"),
|
||||
KnownAlias("BUTTON_INTERACT"),
|
||||
KnownAlias("BUTTON_LOOKSTICK"),
|
||||
KnownAlias("BUTTON_LOOK"),
|
||||
KnownAlias("BUTTON_LUI_ALT1"),
|
||||
KnownAlias("BUTTON_LUI_ALT2"),
|
||||
KnownAlias("BUTTON_LUI_DPAD_ALL"),
|
||||
KnownAlias("BUTTON_LUI_DPAD_D"),
|
||||
KnownAlias("BUTTON_LUI_DPAD_L"),
|
||||
KnownAlias("BUTTON_LUI_DPAD_RL"),
|
||||
KnownAlias("BUTTON_LUI_DPAD_R"),
|
||||
KnownAlias("BUTTON_LUI_DPAD_UD"),
|
||||
KnownAlias("BUTTON_LUI_DPAD_U"),
|
||||
KnownAlias("BUTTON_LUI_LEFT_STICK_UP"),
|
||||
KnownAlias("BUTTON_LUI_LEFT_TRIGGER"),
|
||||
KnownAlias("BUTTON_LUI_PRIMARY"),
|
||||
KnownAlias("BUTTON_LUI_RIGHT_STICK"),
|
||||
KnownAlias("BUTTON_LUI_RIGHT_TRIGGER"),
|
||||
KnownAlias("BUTTON_LUI_SECONDARY"),
|
||||
KnownAlias("BUTTON_LUI_SELECT"),
|
||||
KnownAlias("BUTTON_LUI_SHOULDERL"),
|
||||
KnownAlias("BUTTON_LUI_SHOULDERR"),
|
||||
KnownAlias("BUTTON_LUI_START"),
|
||||
KnownAlias("BUTTON_MOUSE_CLICK"),
|
||||
KnownAlias("BUTTON_MOUSE_CLICK_ACTIVE"),
|
||||
KnownAlias("BUTTON_MOUSE_EDIT"),
|
||||
KnownAlias("BUTTON_MOUSE_EDIT_ACTIVE"),
|
||||
KnownAlias("BUTTON_MOUSE_LEFT"),
|
||||
KnownAlias("BUTTON_MOUSE_MIDDLE"),
|
||||
KnownAlias("BUTTON_MOUSE_RIGHT"),
|
||||
KnownAlias("BUTTON_MOVESTICK"),
|
||||
KnownAlias("BUTTON_MOVE"),
|
||||
KnownAlias("BUTTON_MP_CANCELCOMMAND"),
|
||||
KnownAlias("BUTTON_MP_CHANGESETTINGS"),
|
||||
KnownAlias("BUTTON_MP_GAMERCARD"),
|
||||
KnownAlias("BUTTON_MP_GAMERREVIEW"),
|
||||
KnownAlias("BUTTON_MP_JOINGAME"),
|
||||
KnownAlias("BUTTON_MP_KICKPLAYER"),
|
||||
KnownAlias("BUTTON_MP_LEAVEGAME"),
|
||||
KnownAlias("BUTTON_MP_LOBBY_GAMERCARD"),
|
||||
KnownAlias("BUTTON_MP_NOTREADY"),
|
||||
KnownAlias("BUTTON_MP_PGDOWN"),
|
||||
KnownAlias("BUTTON_MP_PGUP"),
|
||||
KnownAlias("BUTTON_MP_READY"),
|
||||
KnownAlias("BUTTON_MP_REFRESH"),
|
||||
KnownAlias("BUTTON_MP_SCOREBOARD"),
|
||||
KnownAlias("BUTTON_MP_SIGNIN"),
|
||||
KnownAlias("BUTTON_MP_SPECNEXT"),
|
||||
KnownAlias("BUTTON_MP_SPECPREV"),
|
||||
KnownAlias("BUTTON_MP_STARTGAME"),
|
||||
KnownAlias("BUTTON_MP_TOGGLECHASECAM"),
|
||||
KnownAlias("BUTTON_MP_TOGGLEVIEW"),
|
||||
KnownAlias("BUTTON_NO"),
|
||||
KnownAlias("BUTTON_RECORD_VIEW_NEXT"),
|
||||
KnownAlias("BUTTON_RECORD_VIEW_PREV"),
|
||||
KnownAlias("BUTTON_SELECTCHOICE"),
|
||||
KnownAlias("BUTTON_SP_TOGGLEMENU"),
|
||||
KnownAlias("BUTTON_YES"),
|
||||
KnownAlias("CP"),
|
||||
KnownAlias("FONT_CAPITAL_I"),
|
||||
KnownAlias("FONT_NUMBER_ZERO"),
|
||||
KnownAlias("KEY_DOWN_ARROW"),
|
||||
KnownAlias("KEY_LEFT_ARROW"),
|
||||
KnownAlias("KEY_RIGHT_ARROW"),
|
||||
KnownAlias("KEY_UP_ARROW"),
|
||||
KnownAlias("MOUSE_WHEEL_DOWN"),
|
||||
KnownAlias("MOUSE_WHEEL_UP"),
|
||||
KnownAlias("Remote_LStick")};
|
||||
|
||||
CsvOutputStream m_csv;
|
||||
|
||||
|
@ -11,4 +11,4 @@ namespace T6
|
||||
bool ShouldDump(XAssetInfo<FontIcon>* asset) override;
|
||||
void DumpAsset(AssetDumpingContext& context, XAssetInfo<FontIcon>* asset) override;
|
||||
};
|
||||
}
|
||||
} // namespace T6
|
||||
|
@ -1,10 +1,10 @@
|
||||
#include "AssetDumperGfxImage.h"
|
||||
|
||||
#include <cassert>
|
||||
|
||||
#include "ObjWriting.h"
|
||||
#include "Image/IwiWriter27.h"
|
||||
#include "Image/DdsWriter.h"
|
||||
#include "Image/IwiWriter27.h"
|
||||
#include "ObjWriting.h"
|
||||
|
||||
#include <cassert>
|
||||
|
||||
using namespace T6;
|
||||
|
||||
|
@ -1,11 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "Dumping/AbstractAssetDumper.h"
|
||||
#include "Game/T6/T6.h"
|
||||
#include "Image/IImageWriter.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace T6
|
||||
{
|
||||
class AssetDumperGfxImage final : public AbstractAssetDumper<GfxImage>
|
||||
@ -21,4 +21,4 @@ namespace T6
|
||||
public:
|
||||
AssetDumperGfxImage();
|
||||
};
|
||||
}
|
||||
} // namespace T6
|
||||
|
@ -1,9 +1,9 @@
|
||||
#include "AssetDumperLocalizeEntry.h"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
#include "Localize/LocalizeCommon.h"
|
||||
#include "Dumping/Localize/StringFileDumper.h"
|
||||
#include "Localize/LocalizeCommon.h"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
using namespace T6;
|
||||
|
||||
@ -29,7 +29,7 @@ void AssetDumperLocalizeEntry::DumpPool(AssetDumpingContext& context, AssetPool<
|
||||
|
||||
stringFileDumper.SetNotes("");
|
||||
|
||||
for(auto* localizeEntry : *pool)
|
||||
for (auto* localizeEntry : *pool)
|
||||
{
|
||||
stringFileDumper.WriteLocalizeEntry(localizeEntry->m_name, localizeEntry->Asset()->value);
|
||||
}
|
||||
@ -40,4 +40,4 @@ void AssetDumperLocalizeEntry::DumpPool(AssetDumpingContext& context, AssetPool<
|
||||
{
|
||||
printf("Could not create string file for dumping localized strings of zone '%s'\n", context.m_zone->m_name.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -10,4 +10,4 @@ namespace T6
|
||||
public:
|
||||
void DumpPool(AssetDumpingContext& context, AssetPool<LocalizeEntry>* pool) override;
|
||||
};
|
||||
}
|
||||
} // namespace T6
|
||||
|
@ -1,12 +1,12 @@
|
||||
#include "AssetDumperPhysConstraints.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <type_traits>
|
||||
|
||||
#include "Game/T6/ObjConstantsT6.h"
|
||||
#include "Game/T6/InfoString/EnumStrings.h"
|
||||
#include "Game/T6/InfoString/InfoStringFromStructConverter.h"
|
||||
#include "Game/T6/InfoString/PhysConstraintsFields.h"
|
||||
#include "Game/T6/ObjConstantsT6.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <type_traits>
|
||||
|
||||
using namespace T6;
|
||||
|
||||
@ -22,7 +22,7 @@ namespace T6
|
||||
case CFT_TYPE:
|
||||
FillFromEnumInt(std::string(field.szName), field.iOffset, s_constraintTypeNames, std::extent<decltype(s_constraintTypeNames)>::value);
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
assert(false);
|
||||
break;
|
||||
@ -30,25 +30,31 @@ namespace T6
|
||||
}
|
||||
|
||||
public:
|
||||
InfoStringFromPhysConstraintsConverter(const PhysConstraints* structure, const cspField_t* fields, const size_t fieldCount, std::function<std::string(scr_string_t)> scriptStringValueCallback)
|
||||
InfoStringFromPhysConstraintsConverter(const PhysConstraints* structure,
|
||||
const cspField_t* fields,
|
||||
const size_t fieldCount,
|
||||
std::function<std::string(scr_string_t)> scriptStringValueCallback)
|
||||
: InfoStringFromStructConverter(structure, fields, fieldCount, std::move(scriptStringValueCallback))
|
||||
{
|
||||
}
|
||||
};
|
||||
}
|
||||
} // namespace T6
|
||||
|
||||
InfoString AssetDumperPhysConstraints::CreateInfoString(XAssetInfo<PhysConstraints>* asset)
|
||||
{
|
||||
assert(asset->Asset()->count <= 4);
|
||||
|
||||
InfoStringFromPhysConstraintsConverter converter(asset->Asset(), phys_constraints_fields, std::extent<decltype(phys_constraints_fields)>::value, [asset](const scr_string_t scrStr) -> std::string
|
||||
{
|
||||
assert(scrStr < asset->m_zone->m_script_strings.Count());
|
||||
if (scrStr >= asset->m_zone->m_script_strings.Count())
|
||||
return "";
|
||||
InfoStringFromPhysConstraintsConverter converter(asset->Asset(),
|
||||
phys_constraints_fields,
|
||||
std::extent<decltype(phys_constraints_fields)>::value,
|
||||
[asset](const scr_string_t scrStr) -> std::string
|
||||
{
|
||||
assert(scrStr < asset->m_zone->m_script_strings.Count());
|
||||
if (scrStr >= asset->m_zone->m_script_strings.Count())
|
||||
return "";
|
||||
|
||||
return asset->m_zone->m_script_strings[scrStr];
|
||||
});
|
||||
return asset->m_zone->m_script_strings[scrStr];
|
||||
});
|
||||
|
||||
return converter.Convert();
|
||||
}
|
||||
@ -80,4 +86,4 @@ void AssetDumperPhysConstraints::DumpAsset(AssetDumpingContext& context, XAssetI
|
||||
const auto stringValue = infoString.ToString(ObjConstants::INFO_STRING_PREFIX_PHYS_CONSTRAINTS);
|
||||
stream.write(stringValue.c_str(), stringValue.size());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -14,4 +14,4 @@ namespace T6
|
||||
bool ShouldDump(XAssetInfo<PhysConstraints>* asset) override;
|
||||
void DumpAsset(AssetDumpingContext& context, XAssetInfo<PhysConstraints>* asset) override;
|
||||
};
|
||||
}
|
||||
} // namespace T6
|
||||
|
@ -1,14 +1,14 @@
|
||||
#include "AssetDumperPhysPreset.h"
|
||||
|
||||
#include "Game/T6/InfoString/InfoStringFromStructConverter.h"
|
||||
#include "Game/T6/InfoString/PhysPresetFields.h"
|
||||
#include "Game/T6/ObjConstantsT6.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cmath>
|
||||
#include <type_traits>
|
||||
|
||||
#include "Game/T6/ObjConstantsT6.h"
|
||||
#include "Game/T6/InfoString/InfoStringFromStructConverter.h"
|
||||
#include "Game/T6/InfoString/PhysPresetFields.h"
|
||||
|
||||
using namespace T6;
|
||||
|
||||
namespace T6
|
||||
@ -22,19 +22,22 @@ namespace T6
|
||||
}
|
||||
|
||||
public:
|
||||
InfoStringFromPhysPresetConverter(const PhysPresetInfo* structure, const cspField_t* fields, const size_t fieldCount, std::function<std::string(scr_string_t)> scriptStringValueCallback)
|
||||
InfoStringFromPhysPresetConverter(const PhysPresetInfo* structure,
|
||||
const cspField_t* fields,
|
||||
const size_t fieldCount,
|
||||
std::function<std::string(scr_string_t)> scriptStringValueCallback)
|
||||
: InfoStringFromStructConverter(structure, fields, fieldCount, std::move(scriptStringValueCallback))
|
||||
{
|
||||
}
|
||||
};
|
||||
}
|
||||
} // namespace T6
|
||||
|
||||
void AssetDumperPhysPreset::CopyToPhysPresetInfo(const PhysPreset* physPreset, PhysPresetInfo* physPresetInfo)
|
||||
{
|
||||
physPresetInfo->mass = std::clamp(physPreset->mass * 1000.0f, 1.0f, 2000.0f);
|
||||
physPresetInfo->bounce = physPreset->bounce;
|
||||
|
||||
if(std::isinf(physPreset->friction))
|
||||
if (std::isinf(physPreset->friction))
|
||||
{
|
||||
physPresetInfo->isFrictionInfinity = 1;
|
||||
physPresetInfo->friction = 0;
|
||||
@ -61,14 +64,17 @@ InfoString AssetDumperPhysPreset::CreateInfoString(XAssetInfo<PhysPreset>* asset
|
||||
auto* physPresetInfo = new PhysPresetInfo;
|
||||
CopyToPhysPresetInfo(asset->Asset(), physPresetInfo);
|
||||
|
||||
InfoStringFromPhysPresetConverter converter(physPresetInfo, phys_preset_fields, std::extent<decltype(phys_preset_fields)>::value, [asset](const scr_string_t scrStr) -> std::string
|
||||
{
|
||||
assert(scrStr < asset->m_zone->m_script_strings.Count());
|
||||
if (scrStr >= asset->m_zone->m_script_strings.Count())
|
||||
return "";
|
||||
InfoStringFromPhysPresetConverter converter(physPresetInfo,
|
||||
phys_preset_fields,
|
||||
std::extent<decltype(phys_preset_fields)>::value,
|
||||
[asset](const scr_string_t scrStr) -> std::string
|
||||
{
|
||||
assert(scrStr < asset->m_zone->m_script_strings.Count());
|
||||
if (scrStr >= asset->m_zone->m_script_strings.Count())
|
||||
return "";
|
||||
|
||||
return asset->m_zone->m_script_strings[scrStr];
|
||||
});
|
||||
return asset->m_zone->m_script_strings[scrStr];
|
||||
});
|
||||
|
||||
return converter.Convert();
|
||||
}
|
||||
@ -100,4 +106,4 @@ void AssetDumperPhysPreset::DumpAsset(AssetDumpingContext& context, XAssetInfo<P
|
||||
const auto stringValue = infoString.ToString(ObjConstants::INFO_STRING_PREFIX_PHYS_PRESET);
|
||||
stream.write(stringValue.c_str(), stringValue.size());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -15,4 +15,4 @@ namespace T6
|
||||
bool ShouldDump(XAssetInfo<PhysPreset>* asset) override;
|
||||
void DumpAsset(AssetDumpingContext& context, XAssetInfo<PhysPreset>* asset) override;
|
||||
};
|
||||
}
|
||||
} // namespace T6
|
||||
|
@ -17,4 +17,4 @@ void AssetDumperQdb::DumpAsset(AssetDumpingContext& context, XAssetInfo<Qdb>* as
|
||||
|
||||
auto& stream = *assetFile;
|
||||
stream.write(qdb->buffer, qdb->len);
|
||||
}
|
||||
}
|
||||
|
@ -11,4 +11,4 @@ namespace T6
|
||||
bool ShouldDump(XAssetInfo<Qdb>* asset) override;
|
||||
void DumpAsset(AssetDumpingContext& context, XAssetInfo<Qdb>* asset) override;
|
||||
};
|
||||
}
|
||||
} // namespace T6
|
||||
|
@ -17,4 +17,4 @@ void AssetDumperRawFile::DumpAsset(AssetDumpingContext& context, XAssetInfo<RawF
|
||||
|
||||
auto& stream = *assetFile;
|
||||
stream.write(rawFile->buffer, rawFile->len);
|
||||
}
|
||||
}
|
||||
|
@ -11,4 +11,4 @@ namespace T6
|
||||
bool ShouldDump(XAssetInfo<RawFile>* asset) override;
|
||||
void DumpAsset(AssetDumpingContext& context, XAssetInfo<RawFile>* asset) override;
|
||||
};
|
||||
}
|
||||
} // namespace T6
|
||||
|
@ -17,4 +17,4 @@ void AssetDumperScriptParseTree::DumpAsset(AssetDumpingContext& context, XAssetI
|
||||
|
||||
auto& stream = *assetFile;
|
||||
stream.write(scriptParseTree->buffer, scriptParseTree->len);
|
||||
}
|
||||
}
|
||||
|
@ -11,4 +11,4 @@ namespace T6
|
||||
bool ShouldDump(XAssetInfo<ScriptParseTree>* asset) override;
|
||||
void DumpAsset(AssetDumpingContext& context, XAssetInfo<ScriptParseTree>* asset) override;
|
||||
};
|
||||
}
|
||||
} // namespace T6
|
||||
|
@ -17,4 +17,4 @@ void AssetDumperSlug::DumpAsset(AssetDumpingContext& context, XAssetInfo<Slug>*
|
||||
|
||||
auto& stream = *assetFile;
|
||||
stream.write(slug->buffer, slug->len);
|
||||
}
|
||||
}
|
||||
|
@ -11,4 +11,4 @@ namespace T6
|
||||
bool ShouldDump(XAssetInfo<Slug>* asset) override;
|
||||
void DumpAsset(AssetDumpingContext& context, XAssetInfo<Slug>* asset) override;
|
||||
};
|
||||
}
|
||||
} // namespace T6
|
||||
|
@ -1,21 +1,20 @@
|
||||
#include "AssetDumperSndBank.h"
|
||||
|
||||
#include <fstream>
|
||||
#include <filesystem>
|
||||
#include <unordered_set>
|
||||
|
||||
#include "Utils/ClassUtils.h"
|
||||
#include "Csv/CsvStream.h"
|
||||
#include "ObjContainer/SoundBank/SoundBank.h"
|
||||
#include "Sound/WavWriter.h"
|
||||
#include "Utils/ClassUtils.h"
|
||||
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <unordered_set>
|
||||
|
||||
using namespace T6;
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
namespace
|
||||
{
|
||||
const std::string ALIAS_HEADERS[]
|
||||
{
|
||||
const std::string ALIAS_HEADERS[]{
|
||||
"# name",
|
||||
"# file",
|
||||
"# template",
|
||||
@ -81,25 +80,13 @@ namespace
|
||||
"# snapshot",
|
||||
};
|
||||
|
||||
const std::string PREFIXES_TO_DROP[]
|
||||
{
|
||||
const std::string PREFIXES_TO_DROP[]{
|
||||
"raw/",
|
||||
"devraw/",
|
||||
};
|
||||
|
||||
constexpr size_t FRAME_RATE_FOR_INDEX[]
|
||||
{
|
||||
8000,
|
||||
12000,
|
||||
16000,
|
||||
24000,
|
||||
32000,
|
||||
44100,
|
||||
48000,
|
||||
96000,
|
||||
192000
|
||||
};
|
||||
}
|
||||
constexpr size_t FRAME_RATE_FOR_INDEX[]{8000, 12000, 16000, 24000, 32000, 44100, 48000, 96000, 192000};
|
||||
} // namespace
|
||||
|
||||
class AssetDumperSndBank::Internal
|
||||
{
|
||||
@ -286,11 +273,7 @@ class AssetDumperSndBank::Internal
|
||||
if (soundFile.m_entry.frameRateIndex >= std::extent_v<decltype(FRAME_RATE_FOR_INDEX)>)
|
||||
return;
|
||||
|
||||
const WavMetaData metaData{
|
||||
soundFile.m_entry.channelCount,
|
||||
FRAME_RATE_FOR_INDEX[soundFile.m_entry.frameRateIndex],
|
||||
bitsPerSample
|
||||
};
|
||||
const WavMetaData metaData{soundFile.m_entry.channelCount, FRAME_RATE_FOR_INDEX[soundFile.m_entry.frameRateIndex], bitsPerSample};
|
||||
|
||||
writer.WritePcmHeader(metaData, soundFile.m_entry.size);
|
||||
|
||||
|
@ -12,4 +12,4 @@ namespace T6
|
||||
public:
|
||||
void DumpPool(AssetDumpingContext& context, AssetPool<SndBank>* pool) override;
|
||||
};
|
||||
}
|
||||
} // namespace T6
|
||||
|
@ -29,4 +29,4 @@ void AssetDumperStringTable::DumpAsset(AssetDumpingContext& context, XAssetInfo<
|
||||
|
||||
csv.NextRow();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -11,4 +11,4 @@ namespace T6
|
||||
bool ShouldDump(XAssetInfo<StringTable>* asset) override;
|
||||
void DumpAsset(AssetDumpingContext& context, XAssetInfo<StringTable>* asset) override;
|
||||
};
|
||||
}
|
||||
} // namespace T6
|
||||
|
@ -1,12 +1,12 @@
|
||||
#include "AssetDumperTracer.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <type_traits>
|
||||
|
||||
#include "Game/T6/ObjConstantsT6.h"
|
||||
#include "Game/T6/InfoString/EnumStrings.h"
|
||||
#include "Game/T6/InfoString/InfoStringFromStructConverter.h"
|
||||
#include "Game/T6/InfoString/TracerFields.h"
|
||||
#include "Game/T6/ObjConstantsT6.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <type_traits>
|
||||
|
||||
using namespace T6;
|
||||
|
||||
@ -31,23 +31,29 @@ namespace T6
|
||||
}
|
||||
|
||||
public:
|
||||
InfoStringFromTracerConverter(const TracerDef* structure, const cspField_t* fields, const size_t fieldCount, std::function<std::string(scr_string_t)> scriptStringValueCallback)
|
||||
InfoStringFromTracerConverter(const TracerDef* structure,
|
||||
const cspField_t* fields,
|
||||
const size_t fieldCount,
|
||||
std::function<std::string(scr_string_t)> scriptStringValueCallback)
|
||||
: InfoStringFromStructConverter(structure, fields, fieldCount, std::move(scriptStringValueCallback))
|
||||
{
|
||||
}
|
||||
};
|
||||
}
|
||||
} // namespace T6
|
||||
|
||||
InfoString AssetDumperTracer::CreateInfoString(XAssetInfo<TracerDef>* asset)
|
||||
{
|
||||
InfoStringFromTracerConverter converter(asset->Asset(), tracer_fields, std::extent<decltype(tracer_fields)>::value, [asset](const scr_string_t scrStr) -> std::string
|
||||
{
|
||||
assert(scrStr < asset->m_zone->m_script_strings.Count());
|
||||
if (scrStr >= asset->m_zone->m_script_strings.Count())
|
||||
return "";
|
||||
InfoStringFromTracerConverter converter(asset->Asset(),
|
||||
tracer_fields,
|
||||
std::extent<decltype(tracer_fields)>::value,
|
||||
[asset](const scr_string_t scrStr) -> std::string
|
||||
{
|
||||
assert(scrStr < asset->m_zone->m_script_strings.Count());
|
||||
if (scrStr >= asset->m_zone->m_script_strings.Count())
|
||||
return "";
|
||||
|
||||
return asset->m_zone->m_script_strings[scrStr];
|
||||
});
|
||||
return asset->m_zone->m_script_strings[scrStr];
|
||||
});
|
||||
|
||||
return converter.Convert();
|
||||
}
|
||||
|
@ -14,4 +14,4 @@ namespace T6
|
||||
bool ShouldDump(XAssetInfo<TracerDef>* asset) override;
|
||||
void DumpAsset(AssetDumpingContext& context, XAssetInfo<TracerDef>* asset) override;
|
||||
};
|
||||
}
|
||||
} // namespace T6
|
||||
|
@ -1,12 +1,12 @@
|
||||
#include "AssetDumperVehicle.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <type_traits>
|
||||
|
||||
#include "Game/T6/ObjConstantsT6.h"
|
||||
#include "Game/T6/InfoString/EnumStrings.h"
|
||||
#include "Game/T6/InfoString/InfoStringFromStructConverter.h"
|
||||
#include "Game/T6/InfoString/VehicleFields.h"
|
||||
#include "Game/T6/ObjConstantsT6.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <type_traits>
|
||||
|
||||
using namespace T6;
|
||||
|
||||
@ -32,43 +32,43 @@ namespace T6
|
||||
break;
|
||||
|
||||
case VFT_MPH_TO_INCHES_PER_SECOND:
|
||||
{
|
||||
const auto* num = reinterpret_cast<float*>(reinterpret_cast<uintptr_t>(m_structure) + field.iOffset);
|
||||
m_info_string.SetValueForKey(std::string(field.szName), std::to_string(*num / 17.6f));
|
||||
break;
|
||||
}
|
||||
{
|
||||
const auto* num = reinterpret_cast<float*>(reinterpret_cast<uintptr_t>(m_structure) + field.iOffset);
|
||||
m_info_string.SetValueForKey(std::string(field.szName), std::to_string(*num / 17.6f));
|
||||
break;
|
||||
}
|
||||
|
||||
case VFT_POUNDS_TO_GAME_MASS:
|
||||
{
|
||||
const auto* num = reinterpret_cast<float*>(reinterpret_cast<uintptr_t>(m_structure) + field.iOffset);
|
||||
m_info_string.SetValueForKey(std::string(field.szName), std::to_string(*num / 0.001f));
|
||||
break;
|
||||
}
|
||||
{
|
||||
const auto* num = reinterpret_cast<float*>(reinterpret_cast<uintptr_t>(m_structure) + field.iOffset);
|
||||
m_info_string.SetValueForKey(std::string(field.szName), std::to_string(*num / 0.001f));
|
||||
break;
|
||||
}
|
||||
|
||||
case VFT_TEAM:
|
||||
{
|
||||
const auto* num = reinterpret_cast<int*>(reinterpret_cast<uintptr_t>(m_structure) + field.iOffset);
|
||||
switch (*num)
|
||||
{
|
||||
const auto* num = reinterpret_cast<int*>(reinterpret_cast<uintptr_t>(m_structure) + field.iOffset);
|
||||
switch (*num)
|
||||
{
|
||||
case TEAM_AXIS:
|
||||
m_info_string.SetValueForKey(std::string(field.szName), "axis");
|
||||
break;
|
||||
case TEAM_AXIS:
|
||||
m_info_string.SetValueForKey(std::string(field.szName), "axis");
|
||||
break;
|
||||
|
||||
case TEAM_ALLIES:
|
||||
m_info_string.SetValueForKey(std::string(field.szName), "allies");
|
||||
break;
|
||||
case TEAM_ALLIES:
|
||||
m_info_string.SetValueForKey(std::string(field.szName), "allies");
|
||||
break;
|
||||
|
||||
case TEAM_FOUR:
|
||||
m_info_string.SetValueForKey(std::string(field.szName), "neutral");
|
||||
break;
|
||||
case TEAM_FOUR:
|
||||
m_info_string.SetValueForKey(std::string(field.szName), "neutral");
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(false);
|
||||
m_info_string.SetValueForKey(std::string(field.szName), "");
|
||||
break;
|
||||
}
|
||||
default:
|
||||
assert(false);
|
||||
m_info_string.SetValueForKey(std::string(field.szName), "");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case VFT_KEY_BINDING:
|
||||
case VFT_GRAPH:
|
||||
@ -81,23 +81,29 @@ namespace T6
|
||||
}
|
||||
|
||||
public:
|
||||
InfoStringFromVehicleConverter(const VehicleDef* structure, const cspField_t* fields, const size_t fieldCount, std::function<std::string(scr_string_t)> scriptStringValueCallback)
|
||||
InfoStringFromVehicleConverter(const VehicleDef* structure,
|
||||
const cspField_t* fields,
|
||||
const size_t fieldCount,
|
||||
std::function<std::string(scr_string_t)> scriptStringValueCallback)
|
||||
: InfoStringFromStructConverter(structure, fields, fieldCount, std::move(scriptStringValueCallback))
|
||||
{
|
||||
}
|
||||
};
|
||||
}
|
||||
} // namespace T6
|
||||
|
||||
InfoString AssetDumperVehicle::CreateInfoString(XAssetInfo<VehicleDef>* asset)
|
||||
{
|
||||
InfoStringFromVehicleConverter converter(asset->Asset(), vehicle_fields, std::extent<decltype(vehicle_fields)>::value, [asset](const scr_string_t scrStr) -> std::string
|
||||
{
|
||||
assert(scrStr < asset->m_zone->m_script_strings.Count());
|
||||
if (scrStr >= asset->m_zone->m_script_strings.Count())
|
||||
return "";
|
||||
InfoStringFromVehicleConverter converter(asset->Asset(),
|
||||
vehicle_fields,
|
||||
std::extent<decltype(vehicle_fields)>::value,
|
||||
[asset](const scr_string_t scrStr) -> std::string
|
||||
{
|
||||
assert(scrStr < asset->m_zone->m_script_strings.Count());
|
||||
if (scrStr >= asset->m_zone->m_script_strings.Count())
|
||||
return "";
|
||||
|
||||
return asset->m_zone->m_script_strings[scrStr];
|
||||
});
|
||||
return asset->m_zone->m_script_strings[scrStr];
|
||||
});
|
||||
|
||||
return converter.Convert();
|
||||
}
|
||||
|
@ -14,4 +14,4 @@ namespace T6
|
||||
bool ShouldDump(XAssetInfo<VehicleDef>* asset) override;
|
||||
void DumpAsset(AssetDumpingContext& context, XAssetInfo<VehicleDef>* asset) override;
|
||||
};
|
||||
}
|
||||
} // namespace T6
|
||||
|
@ -1,14 +1,14 @@
|
||||
#include "AssetDumperWeapon.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <sstream>
|
||||
#include <type_traits>
|
||||
#include <cstring>
|
||||
|
||||
#include "Game/T6/ObjConstantsT6.h"
|
||||
#include "Game/T6/InfoString/EnumStrings.h"
|
||||
#include "Game/T6/InfoString/InfoStringFromStructConverter.h"
|
||||
#include "Game/T6/InfoString/WeaponFields.h"
|
||||
#include "Game/T6/ObjConstantsT6.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
#include <sstream>
|
||||
#include <type_traits>
|
||||
|
||||
using namespace T6;
|
||||
|
||||
@ -41,18 +41,15 @@ namespace T6
|
||||
break;
|
||||
|
||||
case WFT_STANCE:
|
||||
FillFromEnumInt(std::string(field.szName), field.iOffset, szWeapStanceNames,
|
||||
std::extent<decltype(szWeapStanceNames)>::value);
|
||||
FillFromEnumInt(std::string(field.szName), field.iOffset, szWeapStanceNames, std::extent<decltype(szWeapStanceNames)>::value);
|
||||
break;
|
||||
|
||||
case WFT_PROJ_EXPLOSION:
|
||||
FillFromEnumInt(std::string(field.szName), field.iOffset, szProjectileExplosionNames,
|
||||
std::extent<decltype(szProjectileExplosionNames)>::value);
|
||||
FillFromEnumInt(std::string(field.szName), field.iOffset, szProjectileExplosionNames, std::extent<decltype(szProjectileExplosionNames)>::value);
|
||||
break;
|
||||
|
||||
case WFT_OFFHAND_CLASS:
|
||||
FillFromEnumInt(std::string(field.szName), field.iOffset, offhandClassNames,
|
||||
std::extent<decltype(offhandClassNames)>::value);
|
||||
FillFromEnumInt(std::string(field.szName), field.iOffset, offhandClassNames, std::extent<decltype(offhandClassNames)>::value);
|
||||
break;
|
||||
|
||||
case WFT_OFFHAND_SLOT:
|
||||
@ -60,44 +57,39 @@ namespace T6
|
||||
break;
|
||||
|
||||
case WFT_ANIMTYPE:
|
||||
FillFromEnumInt(std::string(field.szName), field.iOffset, playerAnimTypeNames,
|
||||
std::extent<decltype(playerAnimTypeNames)>::value);
|
||||
FillFromEnumInt(std::string(field.szName), field.iOffset, playerAnimTypeNames, std::extent<decltype(playerAnimTypeNames)>::value);
|
||||
break;
|
||||
|
||||
case WFT_ACTIVE_RETICLE_TYPE:
|
||||
FillFromEnumInt(std::string(field.szName), field.iOffset, activeReticleNames,
|
||||
std::extent<decltype(activeReticleNames)>::value);
|
||||
FillFromEnumInt(std::string(field.szName), field.iOffset, activeReticleNames, std::extent<decltype(activeReticleNames)>::value);
|
||||
break;
|
||||
|
||||
case WFT_GUIDED_MISSILE_TYPE:
|
||||
FillFromEnumInt(std::string(field.szName), field.iOffset, guidedMissileNames,
|
||||
std::extent<decltype(guidedMissileNames)>::value);
|
||||
FillFromEnumInt(std::string(field.szName), field.iOffset, guidedMissileNames, std::extent<decltype(guidedMissileNames)>::value);
|
||||
break;
|
||||
|
||||
case WFT_BOUNCE_SOUND:
|
||||
{
|
||||
const auto* bounceSound = *reinterpret_cast<const char***>(reinterpret_cast<uintptr_t>(m_structure) + field.iOffset);
|
||||
|
||||
if (bounceSound && bounceSound[0])
|
||||
{
|
||||
const auto* bounceSound = *reinterpret_cast<const char***>(reinterpret_cast<uintptr_t>(m_structure)
|
||||
+ field.iOffset);
|
||||
const std::string firstBounceSound(bounceSound[0]);
|
||||
const auto endOfBouncePrefix = firstBounceSound.rfind("_default");
|
||||
assert(endOfBouncePrefix != std::string::npos);
|
||||
|
||||
if (bounceSound && bounceSound[0])
|
||||
if (endOfBouncePrefix != std::string::npos)
|
||||
{
|
||||
const std::string firstBounceSound(bounceSound[0]);
|
||||
const auto endOfBouncePrefix = firstBounceSound.rfind("_default");
|
||||
assert(endOfBouncePrefix != std::string::npos);
|
||||
|
||||
if (endOfBouncePrefix != std::string::npos)
|
||||
{
|
||||
m_info_string.SetValueForKey(std::string(field.szName),
|
||||
firstBounceSound.substr(0, endOfBouncePrefix));
|
||||
}
|
||||
else
|
||||
m_info_string.SetValueForKey(std::string(field.szName), "");
|
||||
m_info_string.SetValueForKey(std::string(field.szName), firstBounceSound.substr(0, endOfBouncePrefix));
|
||||
}
|
||||
else
|
||||
m_info_string.SetValueForKey(std::string(field.szName), "");
|
||||
|
||||
break;
|
||||
}
|
||||
else
|
||||
m_info_string.SetValueForKey(std::string(field.szName), "");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case WFT_STICKINESS:
|
||||
FillFromEnumInt(std::string(field.szName), field.iOffset, stickinessNames, std::extent<decltype(stickinessNames)>::value);
|
||||
@ -108,28 +100,23 @@ namespace T6
|
||||
break;
|
||||
|
||||
case WFT_OVERLAYINTERFACE:
|
||||
FillFromEnumInt(std::string(field.szName), field.iOffset, overlayInterfaceNames,
|
||||
std::extent<decltype(overlayInterfaceNames)>::value);
|
||||
FillFromEnumInt(std::string(field.szName), field.iOffset, overlayInterfaceNames, std::extent<decltype(overlayInterfaceNames)>::value);
|
||||
break;
|
||||
|
||||
case WFT_INVENTORYTYPE:
|
||||
FillFromEnumInt(std::string(field.szName), field.iOffset, szWeapInventoryTypeNames,
|
||||
std::extent<decltype(szWeapInventoryTypeNames)>::value);
|
||||
FillFromEnumInt(std::string(field.szName), field.iOffset, szWeapInventoryTypeNames, std::extent<decltype(szWeapInventoryTypeNames)>::value);
|
||||
break;
|
||||
|
||||
case WFT_FIRETYPE:
|
||||
FillFromEnumInt(std::string(field.szName), field.iOffset, szWeapFireTypeNames,
|
||||
std::extent<decltype(szWeapFireTypeNames)>::value);
|
||||
FillFromEnumInt(std::string(field.szName), field.iOffset, szWeapFireTypeNames, std::extent<decltype(szWeapFireTypeNames)>::value);
|
||||
break;
|
||||
|
||||
case WFT_CLIPTYPE:
|
||||
FillFromEnumInt(std::string(field.szName), field.iOffset, szWeapClipTypeNames,
|
||||
std::extent<decltype(szWeapClipTypeNames)>::value);
|
||||
FillFromEnumInt(std::string(field.szName), field.iOffset, szWeapClipTypeNames, std::extent<decltype(szWeapClipTypeNames)>::value);
|
||||
break;
|
||||
|
||||
case WFT_AMMOCOUNTER_CLIPTYPE:
|
||||
FillFromEnumInt(std::string(field.szName), field.iOffset, ammoCounterClipNames,
|
||||
std::extent<decltype(ammoCounterClipNames)>::value);
|
||||
FillFromEnumInt(std::string(field.szName), field.iOffset, ammoCounterClipNames, std::extent<decltype(ammoCounterClipNames)>::value);
|
||||
break;
|
||||
|
||||
case WFT_ICONRATIO_HUD:
|
||||
@ -137,8 +124,7 @@ namespace T6
|
||||
case WFT_ICONRATIO_KILL:
|
||||
case WFT_ICONRATIO_DPAD:
|
||||
case WFT_ICONRATIO_INDICATOR:
|
||||
FillFromEnumInt(std::string(field.szName), field.iOffset, weapIconRatioNames,
|
||||
std::extent<decltype(weapIconRatioNames)>::value);
|
||||
FillFromEnumInt(std::string(field.szName), field.iOffset, weapIconRatioNames, std::extent<decltype(weapIconRatioNames)>::value);
|
||||
break;
|
||||
|
||||
case WFT_BARRELTYPE:
|
||||
@ -146,118 +132,117 @@ namespace T6
|
||||
break;
|
||||
|
||||
case WFT_HIDETAGS:
|
||||
{
|
||||
const auto* hideTags = reinterpret_cast<scr_string_t*>(reinterpret_cast<uintptr_t>(m_structure) + field.iOffset);
|
||||
std::stringstream ss;
|
||||
bool first = true;
|
||||
|
||||
for (auto i = 0u; i < std::extent<decltype(WeaponFullDef::hideTags)>::value; i++)
|
||||
{
|
||||
const auto* hideTags = reinterpret_cast<scr_string_t*>(reinterpret_cast<uintptr_t>(m_structure) + field.iOffset);
|
||||
std::stringstream ss;
|
||||
bool first = true;
|
||||
|
||||
for (auto i = 0u; i < std::extent<decltype(WeaponFullDef::hideTags)>::value; i++)
|
||||
const auto& str = m_get_scr_string(hideTags[i]);
|
||||
if (!str.empty())
|
||||
{
|
||||
const auto& str = m_get_scr_string(hideTags[i]);
|
||||
if (!str.empty())
|
||||
{
|
||||
if (!first)
|
||||
ss << "\n";
|
||||
else
|
||||
first = false;
|
||||
if (!first)
|
||||
ss << "\n";
|
||||
else
|
||||
first = false;
|
||||
|
||||
ss << str;
|
||||
}
|
||||
ss << str;
|
||||
}
|
||||
|
||||
m_info_string.SetValueForKey(std::string(field.szName), ss.str());
|
||||
break;
|
||||
}
|
||||
|
||||
m_info_string.SetValueForKey(std::string(field.szName), ss.str());
|
||||
break;
|
||||
}
|
||||
|
||||
case WFT_EXPLOSION_TAG:
|
||||
FillFromScriptString(std::string(field.szName), field.iOffset);
|
||||
break;
|
||||
|
||||
case WFT_NOTETRACKSOUNDMAP:
|
||||
{
|
||||
const auto* keys = reinterpret_cast<scr_string_t*>(reinterpret_cast<uintptr_t>(m_structure) + field.iOffset);
|
||||
const auto* values = &keys[std::extent<decltype(WeaponFullDef::notetrackSoundMapKeys)>::value];
|
||||
std::stringstream ss;
|
||||
bool first = true;
|
||||
|
||||
for (auto i = 0u; i < std::extent<decltype(WeaponFullDef::notetrackSoundMapKeys)>::value; i++)
|
||||
{
|
||||
const auto* keys = reinterpret_cast<scr_string_t*>(reinterpret_cast<uintptr_t>(m_structure) + field.iOffset);
|
||||
const auto* values = &keys[std::extent<decltype(WeaponFullDef::notetrackSoundMapKeys)>::value];
|
||||
std::stringstream ss;
|
||||
bool first = true;
|
||||
|
||||
for (auto i = 0u; i < std::extent<decltype(WeaponFullDef::notetrackSoundMapKeys)>::value; i++)
|
||||
const auto& key = m_get_scr_string(keys[i]);
|
||||
const auto& value = m_get_scr_string(values[i]);
|
||||
if (!key.empty())
|
||||
{
|
||||
const auto& key = m_get_scr_string(keys[i]);
|
||||
const auto& value = m_get_scr_string(values[i]);
|
||||
if (!key.empty())
|
||||
{
|
||||
if (!first)
|
||||
ss << "\n";
|
||||
else
|
||||
first = false;
|
||||
if (!first)
|
||||
ss << "\n";
|
||||
else
|
||||
first = false;
|
||||
|
||||
ss << key;
|
||||
ss << key;
|
||||
|
||||
if (!value.empty())
|
||||
ss << " " << value;
|
||||
}
|
||||
if (!value.empty())
|
||||
ss << " " << value;
|
||||
}
|
||||
|
||||
m_info_string.SetValueForKey(std::string(field.szName), ss.str());
|
||||
break;
|
||||
}
|
||||
|
||||
m_info_string.SetValueForKey(std::string(field.szName), ss.str());
|
||||
break;
|
||||
}
|
||||
|
||||
case WFT_WEAPON_CAMO:
|
||||
{
|
||||
const auto* camo = *reinterpret_cast<WeaponCamo**>(reinterpret_cast<uintptr_t>(m_structure) + field
|
||||
.iOffset);
|
||||
{
|
||||
const auto* camo = *reinterpret_cast<WeaponCamo**>(reinterpret_cast<uintptr_t>(m_structure) + field.iOffset);
|
||||
|
||||
if (camo)
|
||||
m_info_string.SetValueForKey(std::string(field.szName), std::string(AssetName(camo->name)));
|
||||
else
|
||||
m_info_string.SetValueForKey(std::string(field.szName), "");
|
||||
break;
|
||||
}
|
||||
if (camo)
|
||||
m_info_string.SetValueForKey(std::string(field.szName), std::string(AssetName(camo->name)));
|
||||
else
|
||||
m_info_string.SetValueForKey(std::string(field.szName), "");
|
||||
break;
|
||||
}
|
||||
|
||||
case WFT_ATTACHMENTS:
|
||||
{
|
||||
const auto* attachments = reinterpret_cast<WeaponAttachment**>(reinterpret_cast<uintptr_t>(m_structure) + field.iOffset);
|
||||
std::stringstream ss;
|
||||
auto first = true;
|
||||
|
||||
for (auto i = 0u; i < std::extent<decltype(WeaponFullDef::attachments)>::value; i++)
|
||||
{
|
||||
const auto* attachments = reinterpret_cast<WeaponAttachment**>(reinterpret_cast<uintptr_t>(m_structure) + field.iOffset);
|
||||
std::stringstream ss;
|
||||
auto first = true;
|
||||
|
||||
for (auto i = 0u; i < std::extent<decltype(WeaponFullDef::attachments)>::value; i++)
|
||||
if (attachments[i])
|
||||
{
|
||||
if (attachments[i])
|
||||
{
|
||||
if (!first)
|
||||
ss << "\n";
|
||||
else
|
||||
first = false;
|
||||
ss << AssetName(attachments[i]->szInternalName);
|
||||
}
|
||||
if (!first)
|
||||
ss << "\n";
|
||||
else
|
||||
first = false;
|
||||
ss << AssetName(attachments[i]->szInternalName);
|
||||
}
|
||||
|
||||
m_info_string.SetValueForKey(std::string(field.szName), ss.str());
|
||||
break;
|
||||
}
|
||||
|
||||
m_info_string.SetValueForKey(std::string(field.szName), ss.str());
|
||||
break;
|
||||
}
|
||||
|
||||
case WFT_ATTACHMENT_UNIQUES:
|
||||
{
|
||||
const auto* attachmentUniques = reinterpret_cast<WeaponAttachmentUnique**>(reinterpret_cast<uintptr_t>(m_structure) + field.iOffset);
|
||||
std::stringstream ss;
|
||||
auto first = true;
|
||||
|
||||
for (auto i = 0u; i < std::extent<decltype(WeaponFullDef::attachmentUniques)>::value; i++)
|
||||
{
|
||||
const auto* attachmentUniques = reinterpret_cast<WeaponAttachmentUnique**>(reinterpret_cast<uintptr_t>(m_structure) + field.iOffset);
|
||||
std::stringstream ss;
|
||||
auto first = true;
|
||||
|
||||
for (auto i = 0u; i < std::extent<decltype(WeaponFullDef::attachmentUniques)>::value; i++)
|
||||
if (attachmentUniques[i])
|
||||
{
|
||||
if (attachmentUniques[i])
|
||||
{
|
||||
if (!first)
|
||||
ss << "\n";
|
||||
else
|
||||
first = false;
|
||||
ss << AssetName(attachmentUniques[i]->szInternalName);
|
||||
}
|
||||
if (!first)
|
||||
ss << "\n";
|
||||
else
|
||||
first = false;
|
||||
ss << AssetName(attachmentUniques[i]->szInternalName);
|
||||
}
|
||||
|
||||
m_info_string.SetValueForKey(std::string(field.szName), ss.str());
|
||||
break;
|
||||
}
|
||||
|
||||
m_info_string.SetValueForKey(std::string(field.szName), ss.str());
|
||||
break;
|
||||
}
|
||||
|
||||
case WFT_NUM_FIELD_TYPES:
|
||||
default:
|
||||
assert(false);
|
||||
@ -266,12 +251,15 @@ namespace T6
|
||||
}
|
||||
|
||||
public:
|
||||
InfoStringFromWeaponConverter(const WeaponFullDef* structure, const cspField_t* fields, const size_t fieldCount, std::function<std::string(scr_string_t)> scriptStringValueCallback)
|
||||
InfoStringFromWeaponConverter(const WeaponFullDef* structure,
|
||||
const cspField_t* fields,
|
||||
const size_t fieldCount,
|
||||
std::function<std::string(scr_string_t)> scriptStringValueCallback)
|
||||
: InfoStringFromStructConverter(structure, fields, fieldCount, std::move(scriptStringValueCallback))
|
||||
{
|
||||
}
|
||||
};
|
||||
}
|
||||
} // namespace T6
|
||||
|
||||
void AssetDumperWeapon::CopyToFullDef(const WeaponVariantDef* weapon, WeaponFullDef* fullDef)
|
||||
{
|
||||
@ -321,14 +309,18 @@ void AssetDumperWeapon::CopyToFullDef(const WeaponVariantDef* weapon, WeaponFull
|
||||
if (fullDef->weapDef.notetrackSoundMapKeys)
|
||||
{
|
||||
assert(sizeof(WeaponFullDef::notetrackSoundMapKeys) >= sizeof(scr_string_t) * std::extent<decltype(WeaponFullDef::notetrackSoundMapKeys)>::value);
|
||||
memcpy(fullDef->notetrackSoundMapKeys, fullDef->weapDef.notetrackSoundMapKeys, sizeof(scr_string_t) * std::extent<decltype(WeaponFullDef::notetrackSoundMapKeys)>::value);
|
||||
memcpy(fullDef->notetrackSoundMapKeys,
|
||||
fullDef->weapDef.notetrackSoundMapKeys,
|
||||
sizeof(scr_string_t) * std::extent<decltype(WeaponFullDef::notetrackSoundMapKeys)>::value);
|
||||
fullDef->weapDef.notetrackSoundMapKeys = fullDef->notetrackSoundMapKeys;
|
||||
}
|
||||
|
||||
if (fullDef->weapDef.notetrackSoundMapValues)
|
||||
{
|
||||
assert(sizeof(WeaponFullDef::notetrackSoundMapValues) >= sizeof(scr_string_t) * std::extent<decltype(WeaponFullDef::notetrackSoundMapValues)>::value);
|
||||
memcpy(fullDef->notetrackSoundMapValues, fullDef->weapDef.notetrackSoundMapValues, sizeof(scr_string_t) * std::extent<decltype(WeaponFullDef::notetrackSoundMapValues)>::value);
|
||||
memcpy(fullDef->notetrackSoundMapValues,
|
||||
fullDef->weapDef.notetrackSoundMapValues,
|
||||
sizeof(scr_string_t) * std::extent<decltype(WeaponFullDef::notetrackSoundMapValues)>::value);
|
||||
fullDef->weapDef.notetrackSoundMapValues = fullDef->notetrackSoundMapValues;
|
||||
}
|
||||
|
||||
@ -400,14 +392,17 @@ InfoString AssetDumperWeapon::CreateInfoString(XAssetInfo<WeaponVariantDef>* ass
|
||||
memset(fullDef.get(), 0, sizeof(WeaponFullDef));
|
||||
CopyToFullDef(asset->Asset(), fullDef.get());
|
||||
|
||||
InfoStringFromWeaponConverter converter(fullDef.get(), weapon_fields, std::extent<decltype(weapon_fields)>::value, [asset](const scr_string_t scrStr) -> std::string
|
||||
{
|
||||
assert(scrStr < asset->m_zone->m_script_strings.Count());
|
||||
if (scrStr >= asset->m_zone->m_script_strings.Count())
|
||||
return "";
|
||||
InfoStringFromWeaponConverter converter(fullDef.get(),
|
||||
weapon_fields,
|
||||
std::extent<decltype(weapon_fields)>::value,
|
||||
[asset](const scr_string_t scrStr) -> std::string
|
||||
{
|
||||
assert(scrStr < asset->m_zone->m_script_strings.Count());
|
||||
if (scrStr >= asset->m_zone->m_script_strings.Count())
|
||||
return "";
|
||||
|
||||
return asset->m_zone->m_script_strings[scrStr];
|
||||
});
|
||||
return asset->m_zone->m_script_strings[scrStr];
|
||||
});
|
||||
|
||||
return converter.Convert();
|
||||
}
|
||||
|
@ -15,4 +15,4 @@ namespace T6
|
||||
bool ShouldDump(XAssetInfo<WeaponVariantDef>* asset) override;
|
||||
void DumpAsset(AssetDumpingContext& context, XAssetInfo<WeaponVariantDef>* asset) override;
|
||||
};
|
||||
}
|
||||
} // namespace T6
|
||||
|
@ -1,12 +1,12 @@
|
||||
#include "AssetDumperWeaponAttachment.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <type_traits>
|
||||
|
||||
#include "Game/T6/ObjConstantsT6.h"
|
||||
#include "Game/T6/InfoString/EnumStrings.h"
|
||||
#include "Game/T6/InfoString/InfoStringFromStructConverter.h"
|
||||
#include "Game/T6/InfoString/WeaponAttachmentFields.h"
|
||||
#include "Game/T6/ObjConstantsT6.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <type_traits>
|
||||
|
||||
using namespace T6;
|
||||
|
||||
@ -37,23 +37,29 @@ namespace T6
|
||||
}
|
||||
|
||||
public:
|
||||
InfoStringFromAttachmentConverter(const WeaponAttachment* structure, const cspField_t* fields, const size_t fieldCount, std::function<std::string(scr_string_t)> scriptStringValueCallback)
|
||||
InfoStringFromAttachmentConverter(const WeaponAttachment* structure,
|
||||
const cspField_t* fields,
|
||||
const size_t fieldCount,
|
||||
std::function<std::string(scr_string_t)> scriptStringValueCallback)
|
||||
: InfoStringFromStructConverter(structure, fields, fieldCount, std::move(scriptStringValueCallback))
|
||||
{
|
||||
}
|
||||
};
|
||||
}
|
||||
} // namespace T6
|
||||
|
||||
InfoString AssetDumperWeaponAttachment::CreateInfoString(XAssetInfo<WeaponAttachment>* asset)
|
||||
{
|
||||
InfoStringFromAttachmentConverter converter(asset->Asset(), attachment_fields, std::extent<decltype(attachment_fields)>::value, [asset](const scr_string_t scrStr) -> std::string
|
||||
{
|
||||
assert(scrStr < asset->m_zone->m_script_strings.Count());
|
||||
if (scrStr >= asset->m_zone->m_script_strings.Count())
|
||||
return "";
|
||||
InfoStringFromAttachmentConverter converter(asset->Asset(),
|
||||
attachment_fields,
|
||||
std::extent<decltype(attachment_fields)>::value,
|
||||
[asset](const scr_string_t scrStr) -> std::string
|
||||
{
|
||||
assert(scrStr < asset->m_zone->m_script_strings.Count());
|
||||
if (scrStr >= asset->m_zone->m_script_strings.Count())
|
||||
return "";
|
||||
|
||||
return asset->m_zone->m_script_strings[scrStr];
|
||||
});
|
||||
return asset->m_zone->m_script_strings[scrStr];
|
||||
});
|
||||
|
||||
return converter.Convert();
|
||||
}
|
||||
|
@ -14,4 +14,4 @@ namespace T6
|
||||
bool ShouldDump(XAssetInfo<WeaponAttachment>* asset) override;
|
||||
void DumpAsset(AssetDumpingContext& context, XAssetInfo<WeaponAttachment>* asset) override;
|
||||
};
|
||||
}
|
||||
} // namespace T6
|
||||
|
@ -1,14 +1,14 @@
|
||||
#include "AssetDumperWeaponAttachmentUnique.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <sstream>
|
||||
#include <type_traits>
|
||||
#include <cstring>
|
||||
|
||||
#include "Game/T6/ObjConstantsT6.h"
|
||||
#include "Game/T6/InfoString/EnumStrings.h"
|
||||
#include "Game/T6/InfoString/InfoStringFromStructConverter.h"
|
||||
#include "Game/T6/InfoString/WeaponAttachmentUniqueFields.h"
|
||||
#include "Game/T6/ObjConstantsT6.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
#include <sstream>
|
||||
#include <type_traits>
|
||||
|
||||
using namespace T6;
|
||||
|
||||
@ -26,44 +26,43 @@ namespace T6
|
||||
break;
|
||||
|
||||
case AUFT_HIDETAGS:
|
||||
{
|
||||
const auto* hideTags = reinterpret_cast<scr_string_t*>(reinterpret_cast<uintptr_t>(m_structure) + field.iOffset);
|
||||
std::stringstream ss;
|
||||
auto first = true;
|
||||
|
||||
for (auto i = 0u; i < std::extent<decltype(WeaponFullDef::hideTags)>::value; i++)
|
||||
{
|
||||
const auto* hideTags = reinterpret_cast<scr_string_t*>(reinterpret_cast<uintptr_t>(m_structure) + field.iOffset);
|
||||
std::stringstream ss;
|
||||
auto first = true;
|
||||
|
||||
for (auto i = 0u; i < std::extent<decltype(WeaponFullDef::hideTags)>::value; i++)
|
||||
const auto& str = m_get_scr_string(hideTags[i]);
|
||||
if (!str.empty())
|
||||
{
|
||||
const auto& str = m_get_scr_string(hideTags[i]);
|
||||
if (!str.empty())
|
||||
{
|
||||
if (!first)
|
||||
ss << "\n";
|
||||
else
|
||||
first = false;
|
||||
if (!first)
|
||||
ss << "\n";
|
||||
else
|
||||
first = false;
|
||||
|
||||
ss << str;
|
||||
}
|
||||
ss << str;
|
||||
}
|
||||
|
||||
m_info_string.SetValueForKey(std::string(field.szName), ss.str());
|
||||
break;
|
||||
}
|
||||
|
||||
m_info_string.SetValueForKey(std::string(field.szName), ss.str());
|
||||
break;
|
||||
}
|
||||
|
||||
case AUFT_OVERLAYRETICLE:
|
||||
FillFromEnumInt(std::string(field.szName), field.iOffset, szWeapOverlayReticleNames, std::extent<decltype(szWeapOverlayReticleNames)>::value);
|
||||
break;
|
||||
|
||||
case AUFT_CAMO:
|
||||
{
|
||||
const auto* camo = *reinterpret_cast<WeaponCamo**>(reinterpret_cast<uintptr_t>(m_structure) + field
|
||||
.iOffset);
|
||||
{
|
||||
const auto* camo = *reinterpret_cast<WeaponCamo**>(reinterpret_cast<uintptr_t>(m_structure) + field.iOffset);
|
||||
|
||||
if (camo)
|
||||
m_info_string.SetValueForKey(std::string(field.szName), std::string(AssetName(camo->name)));
|
||||
else
|
||||
m_info_string.SetValueForKey(std::string(field.szName), "");
|
||||
break;
|
||||
}
|
||||
if (camo)
|
||||
m_info_string.SetValueForKey(std::string(field.szName), std::string(AssetName(camo->name)));
|
||||
else
|
||||
m_info_string.SetValueForKey(std::string(field.szName), "");
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
assert(false);
|
||||
@ -72,13 +71,15 @@ namespace T6
|
||||
}
|
||||
|
||||
public:
|
||||
InfoStringFromWeaponAttachmentUniqueConverter(const WeaponAttachmentUniqueFull* structure, const cspField_t* fields, const size_t fieldCount,
|
||||
InfoStringFromWeaponAttachmentUniqueConverter(const WeaponAttachmentUniqueFull* structure,
|
||||
const cspField_t* fields,
|
||||
const size_t fieldCount,
|
||||
std::function<std::string(scr_string_t)> scriptStringValueCallback)
|
||||
: InfoStringFromStructConverter(structure, fields, fieldCount, std::move(scriptStringValueCallback))
|
||||
{
|
||||
}
|
||||
};
|
||||
}
|
||||
} // namespace T6
|
||||
|
||||
void AssetDumperWeaponAttachmentUnique::CopyToFullDef(const WeaponAttachmentUnique* attachment, WeaponAttachmentUniqueFull* fullDef)
|
||||
{
|
||||
@ -112,16 +113,17 @@ InfoString AssetDumperWeaponAttachmentUnique::CreateInfoString(XAssetInfo<Weapon
|
||||
memset(fullDef.get(), 0, sizeof(WeaponAttachmentUniqueFull));
|
||||
CopyToFullDef(asset->Asset(), fullDef.get());
|
||||
|
||||
InfoStringFromWeaponAttachmentUniqueConverter converter(
|
||||
fullDef.get(), attachment_unique_fields, std::extent<decltype(attachment_unique_fields)>::value,
|
||||
[asset](const scr_string_t scrStr) -> std::string
|
||||
{
|
||||
assert(scrStr < asset->m_zone->m_script_strings.Count());
|
||||
if (scrStr >= asset->m_zone->m_script_strings.Count())
|
||||
return "";
|
||||
InfoStringFromWeaponAttachmentUniqueConverter converter(fullDef.get(),
|
||||
attachment_unique_fields,
|
||||
std::extent<decltype(attachment_unique_fields)>::value,
|
||||
[asset](const scr_string_t scrStr) -> std::string
|
||||
{
|
||||
assert(scrStr < asset->m_zone->m_script_strings.Count());
|
||||
if (scrStr >= asset->m_zone->m_script_strings.Count())
|
||||
return "";
|
||||
|
||||
return asset->m_zone->m_script_strings[scrStr];
|
||||
});
|
||||
return asset->m_zone->m_script_strings[scrStr];
|
||||
});
|
||||
|
||||
return converter.Convert();
|
||||
}
|
||||
|
@ -15,4 +15,4 @@ namespace T6
|
||||
bool ShouldDump(XAssetInfo<WeaponAttachmentUnique>* asset) override;
|
||||
void DumpAsset(AssetDumpingContext& context, XAssetInfo<WeaponAttachmentUnique>* asset) override;
|
||||
};
|
||||
}
|
||||
} // namespace T6
|
||||
|
@ -1,15 +1,15 @@
|
||||
#include "AssetDumperXModel.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <sstream>
|
||||
|
||||
#include "ObjWriting.h"
|
||||
#include "Game/T6/CommonT6.h"
|
||||
#include "Math/Quaternion.h"
|
||||
#include "Model/XModel/XModelExportWriter.h"
|
||||
#include "ObjWriting.h"
|
||||
#include "Utils/HalfFloat.h"
|
||||
#include "Utils/QuatInt16.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <sstream>
|
||||
|
||||
using namespace T6;
|
||||
|
||||
bool AssetDumperXModel::ShouldDump(XAssetInfo<XModel>* asset)
|
||||
@ -21,7 +21,7 @@ GfxImage* AssetDumperXModel::GetMaterialColorMap(const Material* material)
|
||||
{
|
||||
std::vector<MaterialTextureDef*> potentialTextureDefs;
|
||||
|
||||
for(auto textureIndex = 0u; textureIndex < material->textureCount; textureIndex++)
|
||||
for (auto textureIndex = 0u; textureIndex < material->textureCount; textureIndex++)
|
||||
{
|
||||
MaterialTextureDef* def = &material->textureTable[textureIndex];
|
||||
|
||||
@ -34,19 +34,19 @@ GfxImage* AssetDumperXModel::GetMaterialColorMap(const Material* material)
|
||||
if (potentialTextureDefs.size() == 1)
|
||||
return potentialTextureDefs[0]->image;
|
||||
|
||||
for(const auto* def : potentialTextureDefs)
|
||||
for (const auto* def : potentialTextureDefs)
|
||||
{
|
||||
if (tolower(def->nameStart) == 'c' && tolower(def->nameEnd) == 'p')
|
||||
return def->image;
|
||||
}
|
||||
|
||||
for(const auto* def : potentialTextureDefs)
|
||||
for (const auto* def : potentialTextureDefs)
|
||||
{
|
||||
if (tolower(def->nameStart) == 'r' && tolower(def->nameEnd) == 'k')
|
||||
return def->image;
|
||||
}
|
||||
|
||||
for(const auto* def : potentialTextureDefs)
|
||||
for (const auto* def : potentialTextureDefs)
|
||||
{
|
||||
if (tolower(def->nameStart) == 'd' && tolower(def->nameEnd) == 'p')
|
||||
return def->image;
|
||||
@ -285,7 +285,8 @@ void AssetDumperXModel::AddXModelBones(const AssetDumpingContext& context, Abstr
|
||||
bone.globalOffset[0] = model->baseMat[boneNum].trans.x;
|
||||
bone.globalOffset[1] = model->baseMat[boneNum].trans.y;
|
||||
bone.globalOffset[2] = model->baseMat[boneNum].trans.z;
|
||||
bone.globalRotation = Quaternion32(model->baseMat[boneNum].quat.x, model->baseMat[boneNum].quat.y, model->baseMat[boneNum].quat.z, model->baseMat[boneNum].quat.w);
|
||||
bone.globalRotation =
|
||||
Quaternion32(model->baseMat[boneNum].quat.x, model->baseMat[boneNum].quat.y, model->baseMat[boneNum].quat.z, model->baseMat[boneNum].quat.w);
|
||||
|
||||
if (boneNum < model->numRootBones)
|
||||
{
|
||||
@ -299,12 +300,10 @@ void AssetDumperXModel::AddXModelBones(const AssetDumpingContext& context, Abstr
|
||||
bone.localOffset[0] = model->trans[boneNum - model->numRootBones][0];
|
||||
bone.localOffset[1] = model->trans[boneNum - model->numRootBones][1];
|
||||
bone.localOffset[2] = model->trans[boneNum - model->numRootBones][2];
|
||||
bone.localRotation = Quaternion32(
|
||||
QuatInt16::ToFloat(model->quats[boneNum - model->numRootBones][0]),
|
||||
QuatInt16::ToFloat(model->quats[boneNum - model->numRootBones][1]),
|
||||
QuatInt16::ToFloat(model->quats[boneNum - model->numRootBones][2]),
|
||||
QuatInt16::ToFloat(model->quats[boneNum - model->numRootBones][3])
|
||||
);
|
||||
bone.localRotation = Quaternion32(QuatInt16::ToFloat(model->quats[boneNum - model->numRootBones][0]),
|
||||
QuatInt16::ToFloat(model->quats[boneNum - model->numRootBones][1]),
|
||||
QuatInt16::ToFloat(model->quats[boneNum - model->numRootBones][2]),
|
||||
QuatInt16::ToFloat(model->quats[boneNum - model->numRootBones][3]));
|
||||
}
|
||||
|
||||
writer.AddBone(std::move(bone));
|
||||
@ -416,7 +415,10 @@ void AssetDumperXModel::AllocateXModelBoneWeights(const XModel* model, const uns
|
||||
weightCollection.weights = std::make_unique<XModelBoneWeight[]>(weightCollection.totalWeightCount);
|
||||
}
|
||||
|
||||
void AssetDumperXModel::AddXModelVertexBoneWeights(AbstractXModelWriter& writer, const XModel* model, const unsigned lod, XModelVertexBoneWeightCollection& weightCollection)
|
||||
void AssetDumperXModel::AddXModelVertexBoneWeights(AbstractXModelWriter& writer,
|
||||
const XModel* model,
|
||||
const unsigned lod,
|
||||
XModelVertexBoneWeightCollection& weightCollection)
|
||||
{
|
||||
const auto* surfs = &model->surfs[model->lodInfo[lod].surfIndex];
|
||||
const auto surfCount = model->lodInfo[lod].numsurfs;
|
||||
@ -438,17 +440,11 @@ void AssetDumperXModel::AddXModelVertexBoneWeights(AbstractXModelWriter& writer,
|
||||
const auto& vertList = surface.vertList[vertListIndex];
|
||||
const auto* boneWeightOffset = &weightCollection.weights[weightOffset];
|
||||
|
||||
weightCollection.weights[weightOffset++] = XModelBoneWeight{
|
||||
static_cast<int>(vertList.boneOffset / sizeof(DObjSkelMat)),
|
||||
1.0f
|
||||
};
|
||||
weightCollection.weights[weightOffset++] = XModelBoneWeight{static_cast<int>(vertList.boneOffset / sizeof(DObjSkelMat)), 1.0f};
|
||||
|
||||
for (auto vertListVertexOffset = 0u; vertListVertexOffset < vertList.vertCount; vertListVertexOffset++)
|
||||
{
|
||||
writer.AddVertexBoneWeights(XModelVertexBoneWeights{
|
||||
boneWeightOffset,
|
||||
1
|
||||
});
|
||||
writer.AddVertexBoneWeights(XModelVertexBoneWeights{boneWeightOffset, 1});
|
||||
}
|
||||
handledVertices += vertList.vertCount;
|
||||
}
|
||||
@ -462,17 +458,11 @@ void AssetDumperXModel::AddXModelVertexBoneWeights(AbstractXModelWriter& writer,
|
||||
{
|
||||
const auto* boneWeightOffset = &weightCollection.weights[weightOffset];
|
||||
const auto boneIndex0 = static_cast<int>(surface.vertInfo.vertsBlend[vertsBlendOffset + 0] / sizeof(DObjSkelMat));
|
||||
weightCollection.weights[weightOffset++] = XModelBoneWeight{
|
||||
boneIndex0,
|
||||
1.0f
|
||||
};
|
||||
weightCollection.weights[weightOffset++] = XModelBoneWeight{boneIndex0, 1.0f};
|
||||
|
||||
vertsBlendOffset += 1;
|
||||
|
||||
writer.AddVertexBoneWeights(XModelVertexBoneWeights{
|
||||
boneWeightOffset,
|
||||
1
|
||||
});
|
||||
writer.AddVertexBoneWeights(XModelVertexBoneWeights{boneWeightOffset, 1});
|
||||
}
|
||||
|
||||
// 2 bone weights
|
||||
@ -484,21 +474,12 @@ void AssetDumperXModel::AddXModelVertexBoneWeights(AbstractXModelWriter& writer,
|
||||
const auto boneWeight1 = HalfFloat::ToFloat(surface.vertInfo.vertsBlend[vertsBlendOffset + 2]);
|
||||
const auto boneWeight0 = 1.0f - boneWeight1;
|
||||
|
||||
weightCollection.weights[weightOffset++] = XModelBoneWeight{
|
||||
boneIndex0,
|
||||
boneWeight0
|
||||
};
|
||||
weightCollection.weights[weightOffset++] = XModelBoneWeight{
|
||||
boneIndex1,
|
||||
boneWeight1
|
||||
};
|
||||
weightCollection.weights[weightOffset++] = XModelBoneWeight{boneIndex0, boneWeight0};
|
||||
weightCollection.weights[weightOffset++] = XModelBoneWeight{boneIndex1, boneWeight1};
|
||||
|
||||
vertsBlendOffset += 3;
|
||||
|
||||
writer.AddVertexBoneWeights(XModelVertexBoneWeights{
|
||||
boneWeightOffset,
|
||||
2
|
||||
});
|
||||
writer.AddVertexBoneWeights(XModelVertexBoneWeights{boneWeightOffset, 2});
|
||||
}
|
||||
|
||||
// 3 bone weights
|
||||
@ -512,25 +493,13 @@ void AssetDumperXModel::AddXModelVertexBoneWeights(AbstractXModelWriter& writer,
|
||||
const auto boneWeight2 = HalfFloat::ToFloat(surface.vertInfo.vertsBlend[vertsBlendOffset + 4]);
|
||||
const auto boneWeight0 = 1.0f - boneWeight1 - boneWeight2;
|
||||
|
||||
weightCollection.weights[weightOffset++] = XModelBoneWeight{
|
||||
boneIndex0,
|
||||
boneWeight0
|
||||
};
|
||||
weightCollection.weights[weightOffset++] = XModelBoneWeight{
|
||||
boneIndex1,
|
||||
boneWeight1
|
||||
};
|
||||
weightCollection.weights[weightOffset++] = XModelBoneWeight{
|
||||
boneIndex2,
|
||||
boneWeight2
|
||||
};
|
||||
weightCollection.weights[weightOffset++] = XModelBoneWeight{boneIndex0, boneWeight0};
|
||||
weightCollection.weights[weightOffset++] = XModelBoneWeight{boneIndex1, boneWeight1};
|
||||
weightCollection.weights[weightOffset++] = XModelBoneWeight{boneIndex2, boneWeight2};
|
||||
|
||||
vertsBlendOffset += 5;
|
||||
|
||||
writer.AddVertexBoneWeights(XModelVertexBoneWeights{
|
||||
boneWeightOffset,
|
||||
3
|
||||
});
|
||||
writer.AddVertexBoneWeights(XModelVertexBoneWeights{boneWeightOffset, 3});
|
||||
}
|
||||
|
||||
// 4 bone weights
|
||||
@ -546,29 +515,14 @@ void AssetDumperXModel::AddXModelVertexBoneWeights(AbstractXModelWriter& writer,
|
||||
const auto boneWeight3 = HalfFloat::ToFloat(surface.vertInfo.vertsBlend[vertsBlendOffset + 6]);
|
||||
const auto boneWeight0 = 1.0f - boneWeight1 - boneWeight2 - boneWeight3;
|
||||
|
||||
weightCollection.weights[weightOffset++] = XModelBoneWeight{
|
||||
boneIndex0,
|
||||
boneWeight0
|
||||
};
|
||||
weightCollection.weights[weightOffset++] = XModelBoneWeight{
|
||||
boneIndex1,
|
||||
boneWeight1
|
||||
};
|
||||
weightCollection.weights[weightOffset++] = XModelBoneWeight{
|
||||
boneIndex2,
|
||||
boneWeight2
|
||||
};
|
||||
weightCollection.weights[weightOffset++] = XModelBoneWeight{
|
||||
boneIndex3,
|
||||
boneWeight3
|
||||
};
|
||||
weightCollection.weights[weightOffset++] = XModelBoneWeight{boneIndex0, boneWeight0};
|
||||
weightCollection.weights[weightOffset++] = XModelBoneWeight{boneIndex1, boneWeight1};
|
||||
weightCollection.weights[weightOffset++] = XModelBoneWeight{boneIndex2, boneWeight2};
|
||||
weightCollection.weights[weightOffset++] = XModelBoneWeight{boneIndex3, boneWeight3};
|
||||
|
||||
vertsBlendOffset += 7;
|
||||
|
||||
writer.AddVertexBoneWeights(XModelVertexBoneWeights{
|
||||
boneWeightOffset,
|
||||
4
|
||||
});
|
||||
writer.AddVertexBoneWeights(XModelVertexBoneWeights{boneWeightOffset, 4});
|
||||
}
|
||||
|
||||
handledVertices += surface.vertInfo.vertCount[0] + surface.vertInfo.vertCount[1] + surface.vertInfo.vertCount[2] + surface.vertInfo.vertCount[3];
|
||||
@ -576,10 +530,7 @@ void AssetDumperXModel::AddXModelVertexBoneWeights(AbstractXModelWriter& writer,
|
||||
|
||||
for (; handledVertices < surface.vertCount; handledVertices++)
|
||||
{
|
||||
writer.AddVertexBoneWeights(XModelVertexBoneWeights{
|
||||
nullptr,
|
||||
0
|
||||
});
|
||||
writer.AddVertexBoneWeights(XModelVertexBoneWeights{nullptr, 0});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,9 +2,9 @@
|
||||
|
||||
#include "Dumping/AbstractAssetDumper.h"
|
||||
#include "Game/T6/T6.h"
|
||||
#include "Utils/DistinctMapper.h"
|
||||
#include "Model/XModel/AbstractXModelWriter.h"
|
||||
#include "Model/Obj/ObjWriter.h"
|
||||
#include "Model/XModel/AbstractXModelWriter.h"
|
||||
#include "Utils/DistinctMapper.h"
|
||||
|
||||
namespace T6
|
||||
{
|
||||
@ -27,7 +27,8 @@ namespace T6
|
||||
static void AddXModelObjects(AbstractXModelWriter& writer, const XModel* model, unsigned lod);
|
||||
static void AddXModelVertices(AbstractXModelWriter& writer, const XModel* model, unsigned lod);
|
||||
static void AllocateXModelBoneWeights(const XModel* model, unsigned lod, XModelVertexBoneWeightCollection& weightCollection);
|
||||
static void AddXModelVertexBoneWeights(AbstractXModelWriter& writer, const XModel* model, unsigned lod, XModelVertexBoneWeightCollection& weightCollection);
|
||||
static void
|
||||
AddXModelVertexBoneWeights(AbstractXModelWriter& writer, const XModel* model, unsigned lod, XModelVertexBoneWeightCollection& weightCollection);
|
||||
static void AddXModelFaces(AbstractXModelWriter& writer, const DistinctMapper<Material*>& materialMapper, const XModel* model, unsigned lod);
|
||||
static void DumpXModelExportLod(const AssetDumpingContext& context, XAssetInfo<XModel>* asset, unsigned lod);
|
||||
static void DumpXModelExport(const AssetDumpingContext& context, XAssetInfo<XModel>* asset);
|
||||
@ -36,4 +37,4 @@ namespace T6
|
||||
bool ShouldDump(XAssetInfo<XModel>* asset) override;
|
||||
void DumpAsset(AssetDumpingContext& context, XAssetInfo<XModel>* asset) override;
|
||||
};
|
||||
}
|
||||
} // namespace T6
|
||||
|
@ -1,12 +1,12 @@
|
||||
#include "AssetDumperZBarrier.h"
|
||||
|
||||
#include "Game/T6/InfoString/InfoStringFromStructConverter.h"
|
||||
#include "Game/T6/InfoString/ZBarrierFields.h"
|
||||
#include "Game/T6/ObjConstantsT6.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <type_traits>
|
||||
|
||||
#include "Game/T6/ObjConstantsT6.h"
|
||||
#include "Game/T6/InfoString/InfoStringFromStructConverter.h"
|
||||
#include "Game/T6/InfoString/ZBarrierFields.h"
|
||||
|
||||
using namespace T6;
|
||||
|
||||
namespace T6
|
||||
@ -20,23 +20,29 @@ namespace T6
|
||||
}
|
||||
|
||||
public:
|
||||
InfoStringFromZBarrierConverter(const ZBarrierDef* structure, const cspField_t* fields, const size_t fieldCount, std::function<std::string(scr_string_t)> scriptStringValueCallback)
|
||||
InfoStringFromZBarrierConverter(const ZBarrierDef* structure,
|
||||
const cspField_t* fields,
|
||||
const size_t fieldCount,
|
||||
std::function<std::string(scr_string_t)> scriptStringValueCallback)
|
||||
: InfoStringFromStructConverter(structure, fields, fieldCount, std::move(scriptStringValueCallback))
|
||||
{
|
||||
}
|
||||
};
|
||||
}
|
||||
} // namespace T6
|
||||
|
||||
InfoString AssetDumperZBarrier::CreateInfoString(XAssetInfo<ZBarrierDef>* asset)
|
||||
{
|
||||
InfoStringFromZBarrierConverter converter(asset->Asset(), zbarrier_fields, std::extent<decltype(zbarrier_fields)>::value, [asset](const scr_string_t scrStr) -> std::string
|
||||
{
|
||||
assert(scrStr < asset->m_zone->m_script_strings.Count());
|
||||
if (scrStr >= asset->m_zone->m_script_strings.Count())
|
||||
return "";
|
||||
InfoStringFromZBarrierConverter converter(asset->Asset(),
|
||||
zbarrier_fields,
|
||||
std::extent<decltype(zbarrier_fields)>::value,
|
||||
[asset](const scr_string_t scrStr) -> std::string
|
||||
{
|
||||
assert(scrStr < asset->m_zone->m_script_strings.Count());
|
||||
if (scrStr >= asset->m_zone->m_script_strings.Count())
|
||||
return "";
|
||||
|
||||
return asset->m_zone->m_script_strings[scrStr];
|
||||
});
|
||||
return asset->m_zone->m_script_strings[scrStr];
|
||||
});
|
||||
|
||||
return converter.Convert();
|
||||
}
|
||||
|
@ -14,4 +14,4 @@ namespace T6
|
||||
bool ShouldDump(XAssetInfo<ZBarrierDef>* asset) override;
|
||||
void DumpAsset(AssetDumpingContext& context, XAssetInfo<ZBarrierDef>* asset) override;
|
||||
};
|
||||
}
|
||||
} // namespace T6
|
||||
|
@ -74,8 +74,7 @@ void InfoStringFromStructConverter::FillFromBaseField(const cspField_t& field)
|
||||
case CSPFT_MATERIAL:
|
||||
case CSPFT_MATERIAL_STREAM:
|
||||
{
|
||||
const auto* material = *reinterpret_cast<Material**>(reinterpret_cast<uintptr_t>(m_structure) + field.
|
||||
iOffset);
|
||||
const auto* material = *reinterpret_cast<Material**>(reinterpret_cast<uintptr_t>(m_structure) + field.iOffset);
|
||||
|
||||
if (material)
|
||||
m_info_string.SetValueForKey(std::string(field.szName), std::string(AssetName(material->info.name)));
|
||||
@ -86,8 +85,7 @@ void InfoStringFromStructConverter::FillFromBaseField(const cspField_t& field)
|
||||
|
||||
case CSPFT_PHYS_PRESET:
|
||||
{
|
||||
const auto* physPreset = *reinterpret_cast<PhysPreset**>(reinterpret_cast<uintptr_t>(m_structure) + field.
|
||||
iOffset);
|
||||
const auto* physPreset = *reinterpret_cast<PhysPreset**>(reinterpret_cast<uintptr_t>(m_structure) + field.iOffset);
|
||||
|
||||
if (physPreset)
|
||||
m_info_string.SetValueForKey(std::string(field.szName), std::string(AssetName(physPreset->name)));
|
||||
@ -142,18 +140,19 @@ void InfoStringFromStructConverter::FillInfoString()
|
||||
}
|
||||
}
|
||||
|
||||
InfoStringFromStructConverter::InfoStringFromStructConverter(const void* structure, const cspField_t* fields,
|
||||
const size_t fieldCount)
|
||||
InfoStringFromStructConverter::InfoStringFromStructConverter(const void* structure, const cspField_t* fields, const size_t fieldCount)
|
||||
: InfoStringFromStructConverterBase(structure),
|
||||
m_fields(fields),
|
||||
m_field_count(fieldCount)
|
||||
m_fields(fields),
|
||||
m_field_count(fieldCount)
|
||||
{
|
||||
}
|
||||
|
||||
InfoStringFromStructConverter::InfoStringFromStructConverter(const void* structure, const cspField_t* fields, const size_t fieldCount,
|
||||
std::function<std::string(scr_string_t)> scriptStringValueCallback)
|
||||
InfoStringFromStructConverter::InfoStringFromStructConverter(const void* structure,
|
||||
const cspField_t* fields,
|
||||
const size_t fieldCount,
|
||||
std::function<std::string(scr_string_t)> scriptStringValueCallback)
|
||||
: InfoStringFromStructConverterBase(structure, std::move(scriptStringValueCallback)),
|
||||
m_fields(fields),
|
||||
m_field_count(fieldCount)
|
||||
m_fields(fields),
|
||||
m_field_count(fieldCount)
|
||||
{
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
#include "InfoString/InfoStringFromStructConverterBase.h"
|
||||
#include "Game/T6/T6.h"
|
||||
#include "InfoString/InfoStringFromStructConverterBase.h"
|
||||
|
||||
namespace T6
|
||||
{
|
||||
@ -16,6 +16,9 @@ namespace T6
|
||||
|
||||
public:
|
||||
InfoStringFromStructConverter(const void* structure, const cspField_t* fields, size_t fieldCount);
|
||||
InfoStringFromStructConverter(const void* structure, const cspField_t* fields, size_t fieldCount, std::function<std::string(scr_string_t)> scriptStringValueCallback);
|
||||
InfoStringFromStructConverter(const void* structure,
|
||||
const cspField_t* fields,
|
||||
size_t fieldCount,
|
||||
std::function<std::string(scr_string_t)> scriptStringValueCallback);
|
||||
};
|
||||
}
|
||||
} // namespace T6
|
||||
|
@ -1,20 +1,16 @@
|
||||
#include "ZoneDumperT6.h"
|
||||
|
||||
#include "ObjWriting.h"
|
||||
#include "Game/T6/GameT6.h"
|
||||
#include "Game/T6/GameAssetPoolT6.h"
|
||||
|
||||
#include "AssetDumpers/AssetDumperRawFile.h"
|
||||
#include "AssetDumpers/AssetDumperSlug.h"
|
||||
#include "AssetDumpers/AssetDumperQdb.h"
|
||||
#include "AssetDumpers/AssetDumperScriptParseTree.h"
|
||||
#include "AssetDumpers/AssetDumperStringTable.h"
|
||||
#include "AssetDumpers/AssetDumperLocalizeEntry.h"
|
||||
#include "AssetDumpers/AssetDumperGfxImage.h"
|
||||
#include "AssetDumpers/AssetDumperFontIcon.h"
|
||||
#include "AssetDumpers/AssetDumperGfxImage.h"
|
||||
#include "AssetDumpers/AssetDumperLocalizeEntry.h"
|
||||
#include "AssetDumpers/AssetDumperPhysConstraints.h"
|
||||
#include "AssetDumpers/AssetDumperPhysPreset.h"
|
||||
#include "AssetDumpers/AssetDumperQdb.h"
|
||||
#include "AssetDumpers/AssetDumperRawFile.h"
|
||||
#include "AssetDumpers/AssetDumperScriptParseTree.h"
|
||||
#include "AssetDumpers/AssetDumperSlug.h"
|
||||
#include "AssetDumpers/AssetDumperSndBank.h"
|
||||
#include "AssetDumpers/AssetDumperStringTable.h"
|
||||
#include "AssetDumpers/AssetDumperTracer.h"
|
||||
#include "AssetDumpers/AssetDumperVehicle.h"
|
||||
#include "AssetDumpers/AssetDumperWeapon.h"
|
||||
@ -22,6 +18,9 @@
|
||||
#include "AssetDumpers/AssetDumperWeaponAttachmentUnique.h"
|
||||
#include "AssetDumpers/AssetDumperXModel.h"
|
||||
#include "AssetDumpers/AssetDumperZBarrier.h"
|
||||
#include "Game/T6/GameAssetPoolT6.h"
|
||||
#include "Game/T6/GameT6.h"
|
||||
#include "ObjWriting.h"
|
||||
|
||||
using namespace T6;
|
||||
|
||||
@ -32,11 +31,11 @@ bool ZoneDumper::CanHandleZone(AssetDumpingContext& context) const
|
||||
|
||||
bool ZoneDumper::DumpZone(AssetDumpingContext& context) const
|
||||
{
|
||||
#define DUMP_ASSET_POOL(dumperType, poolName, assetType) \
|
||||
if(assetPools->poolName && ObjWriting::ShouldHandleAssetType(assetType)) \
|
||||
{ \
|
||||
dumperType dumper; \
|
||||
dumper.DumpPool(context, assetPools->poolName.get()); \
|
||||
#define DUMP_ASSET_POOL(dumperType, poolName, assetType) \
|
||||
if (assetPools->poolName && ObjWriting::ShouldHandleAssetType(assetType)) \
|
||||
{ \
|
||||
dumperType dumper; \
|
||||
dumper.DumpPool(context, assetPools->poolName.get()); \
|
||||
}
|
||||
|
||||
const auto* assetPools = dynamic_cast<GameAssetPoolT6*>(context.m_zone->m_pools.get());
|
||||
|
@ -9,4 +9,4 @@ namespace T6
|
||||
bool CanHandleZone(AssetDumpingContext& context) const override;
|
||||
bool DumpZone(AssetDumpingContext& context) const override;
|
||||
};
|
||||
}
|
||||
} // namespace T6
|
||||
|
Reference in New Issue
Block a user