2
0
mirror of https://github.com/Laupetin/OpenAssetTools.git synced 2026-01-11 19:21:50 +00:00

refactor: streamline weapon dumping

This commit is contained in:
Jan Laupetin
2025-08-03 13:12:50 +02:00
parent 58de885ebe
commit 0546572ecf
68 changed files with 1380 additions and 1349 deletions

View File

@@ -24,7 +24,7 @@
#include "Techset/TechsetDumperIW4.h"
#include "Tracer/TracerDumperIW4.h"
#include "Vehicle/VehicleDumperIW4.h"
#include "Weapon/AssetDumperWeapon.h"
#include "Weapon/WeaponDumperIW4.h"
using namespace IW4;
@@ -66,7 +66,7 @@ bool ObjWriter::DumpZone(AssetDumpingContext& context) const
DUMP_ASSET_POOL(AssetDumperMenuList, m_menu_list, ASSET_TYPE_MENULIST)
DUMP_ASSET_POOL(AssetDumperMenuDef, m_menu_def, ASSET_TYPE_MENU)
DUMP_ASSET_POOL(localize::Dumper, m_localize, ASSET_TYPE_LOCALIZE_ENTRY)
DUMP_ASSET_POOL(AssetDumperWeapon, m_weapon, ASSET_TYPE_WEAPON)
DUMP_ASSET_POOL(weapon::Dumper, m_weapon, ASSET_TYPE_WEAPON)
// DUMP_ASSET_POOL(AssetDumperSndDriverGlobals, m_snd_driver_globals, ASSET_TYPE_SNDDRIVER_GLOBALS)
// DUMP_ASSET_POOL(AssetDumperFxEffectDef, m_fx, ASSET_TYPE_FX)
// DUMP_ASSET_POOL(AssetDumperFxImpactTable, m_fx_impact_table, ASSET_TYPE_IMPACT_FX)

View File

@@ -1,19 +0,0 @@
#pragma once
#include "Dumping/AbstractAssetDumper.h"
#include "Game/IW4/IW4.h"
#include "InfoString/InfoString.h"
namespace IW4
{
class AssetDumperWeapon final : public AbstractAssetDumper<WeaponCompleteDef>
{
static void CopyToFullDef(const WeaponCompleteDef* weapon, WeaponFullDef* fullDef);
static InfoString CreateInfoString(XAssetInfo<WeaponCompleteDef>* asset);
static void DumpAccuracyGraphs(AssetDumpingContext& context, XAssetInfo<WeaponCompleteDef>* asset);
protected:
bool ShouldDump(XAssetInfo<WeaponCompleteDef>* asset) override;
void DumpAsset(AssetDumpingContext& context, XAssetInfo<WeaponCompleteDef>* asset) override;
};
} // namespace IW4

View File

@@ -1,4 +1,4 @@
#include "AssetDumperWeapon.h"
#include "WeaponDumperIW4.h"
#include "Game/IW4/CommonIW4.h"
#include "Game/IW4/InfoString/EnumStrings.h"
@@ -6,6 +6,7 @@
#include "Game/IW4/ObjConstantsIW4.h"
#include "Game/IW4/Weapon/WeaponFields.h"
#include "Weapon/AccuracyGraphWriter.h"
#include "Weapon/WeaponCommon.h"
#include <cassert>
#include <cstring>
@@ -13,8 +14,9 @@
#include <type_traits>
using namespace IW4;
using namespace ::weapon;
namespace IW4
namespace
{
class InfoStringFromWeaponConverter final : public InfoStringFromStructConverter
{
@@ -237,195 +239,201 @@ namespace IW4
return graph;
}
} // namespace IW4
void AssetDumperWeapon::CopyToFullDef(const WeaponCompleteDef* weapon, WeaponFullDef* fullDef)
{
fullDef->weapCompleteDef = *weapon;
if (weapon->weapDef)
void CopyToFullDef(const WeaponCompleteDef* weapon, WeaponFullDef* fullDef)
{
fullDef->weapDef = *weapon->weapDef;
fullDef->weapCompleteDef.weapDef = &fullDef->weapDef;
fullDef->weapCompleteDef = *weapon;
if (weapon->weapDef)
{
fullDef->weapDef = *weapon->weapDef;
fullDef->weapCompleteDef.weapDef = &fullDef->weapDef;
}
if (weapon->hideTags)
{
assert(sizeof(WeaponFullDef::hideTags) >= sizeof(scr_string_t) * std::extent_v<decltype(WeaponFullDef::hideTags)>);
memcpy(fullDef->hideTags, weapon->hideTags, sizeof(scr_string_t) * std::extent_v<decltype(WeaponFullDef::hideTags)>);
fullDef->weapCompleteDef.hideTags = fullDef->hideTags;
}
if (weapon->szXAnims)
{
assert(sizeof(WeaponFullDef::szXAnims) >= sizeof(void*) * NUM_WEAP_ANIMS);
memcpy(fullDef->szXAnims, weapon->szXAnims, sizeof(void*) * NUM_WEAP_ANIMS);
fullDef->weapCompleteDef.szXAnims = fullDef->szXAnims;
}
if (fullDef->weapDef.gunXModel)
{
assert(sizeof(WeaponFullDef::gunXModel) >= sizeof(void*) * std::extent_v<decltype(WeaponFullDef::gunXModel)>);
memcpy(fullDef->gunXModel, fullDef->weapDef.gunXModel, sizeof(void*) * std::extent_v<decltype(WeaponFullDef::gunXModel)>);
fullDef->weapDef.gunXModel = fullDef->gunXModel;
}
if (fullDef->weapDef.szXAnimsRightHanded)
{
assert(sizeof(WeaponFullDef::szXAnimsRightHanded) >= sizeof(void*) * NUM_WEAP_ANIMS);
memcpy(fullDef->szXAnimsRightHanded, fullDef->weapDef.szXAnimsRightHanded, sizeof(void*) * NUM_WEAP_ANIMS);
fullDef->weapDef.szXAnimsRightHanded = fullDef->szXAnimsRightHanded;
}
if (fullDef->weapDef.szXAnimsLeftHanded)
{
assert(sizeof(WeaponFullDef::szXAnimsLeftHanded) >= sizeof(void*) * NUM_WEAP_ANIMS);
memcpy(fullDef->szXAnimsLeftHanded, fullDef->weapDef.szXAnimsLeftHanded, sizeof(void*) * NUM_WEAP_ANIMS);
fullDef->weapDef.szXAnimsLeftHanded = fullDef->szXAnimsLeftHanded;
}
if (fullDef->weapDef.notetrackSoundMapKeys)
{
assert(sizeof(WeaponFullDef::notetrackSoundMapKeys) >= sizeof(scr_string_t) * std::extent_v<decltype(WeaponFullDef::notetrackSoundMapKeys)>);
memcpy(fullDef->notetrackSoundMapKeys,
fullDef->weapDef.notetrackSoundMapKeys,
sizeof(scr_string_t) * std::extent_v<decltype(WeaponFullDef::notetrackSoundMapKeys)>);
fullDef->weapDef.notetrackSoundMapKeys = fullDef->notetrackSoundMapKeys;
}
if (fullDef->weapDef.notetrackSoundMapValues)
{
assert(sizeof(WeaponFullDef::notetrackSoundMapValues) >= sizeof(scr_string_t) * std::extent_v<decltype(WeaponFullDef::notetrackSoundMapKeys)>);
memcpy(fullDef->notetrackSoundMapValues,
fullDef->weapDef.notetrackSoundMapValues,
sizeof(scr_string_t) * std::extent_v<decltype(WeaponFullDef::notetrackSoundMapKeys)>);
fullDef->weapDef.notetrackSoundMapValues = fullDef->notetrackSoundMapValues;
}
if (fullDef->weapDef.notetrackRumbleMapKeys)
{
assert(sizeof(WeaponFullDef::notetrackRumbleMapKeys) >= sizeof(scr_string_t) * std::extent_v<decltype(WeaponFullDef::notetrackRumbleMapKeys)>);
memcpy(fullDef->notetrackRumbleMapKeys,
fullDef->weapDef.notetrackRumbleMapKeys,
sizeof(scr_string_t) * std::extent_v<decltype(WeaponFullDef::notetrackRumbleMapKeys)>);
fullDef->weapDef.notetrackRumbleMapKeys = fullDef->notetrackRumbleMapKeys;
}
if (fullDef->weapDef.notetrackRumbleMapValues)
{
assert(sizeof(WeaponFullDef::notetrackRumbleMapValues) >= sizeof(scr_string_t) * std::extent_v<decltype(WeaponFullDef::notetrackRumbleMapKeys)>);
memcpy(fullDef->notetrackRumbleMapValues,
fullDef->weapDef.notetrackRumbleMapValues,
sizeof(scr_string_t) * std::extent_v<decltype(WeaponFullDef::notetrackRumbleMapKeys)>);
fullDef->weapDef.notetrackRumbleMapValues = fullDef->notetrackRumbleMapValues;
}
if (fullDef->weapDef.worldModel)
{
assert(sizeof(WeaponFullDef::worldModel) >= sizeof(void*) * std::extent_v<decltype(WeaponFullDef::worldModel)>);
memcpy(fullDef->worldModel, fullDef->weapDef.worldModel, sizeof(void*) * std::extent_v<decltype(WeaponFullDef::worldModel)>);
fullDef->weapDef.worldModel = fullDef->worldModel;
}
if (fullDef->weapDef.parallelBounce)
{
assert(sizeof(WeaponFullDef::parallelBounce) >= sizeof(float) * std::extent_v<decltype(WeaponFullDef::parallelBounce)>);
memcpy(fullDef->parallelBounce, fullDef->weapDef.parallelBounce, sizeof(float) * std::extent_v<decltype(WeaponFullDef::parallelBounce)>);
fullDef->weapDef.parallelBounce = fullDef->parallelBounce;
}
if (fullDef->weapDef.perpendicularBounce)
{
assert(sizeof(WeaponFullDef::perpendicularBounce) >= sizeof(float) * std::extent_v<decltype(WeaponFullDef::perpendicularBounce)>);
memcpy(fullDef->perpendicularBounce,
fullDef->weapDef.perpendicularBounce,
sizeof(float) * std::extent_v<decltype(WeaponFullDef::perpendicularBounce)>);
fullDef->weapDef.perpendicularBounce = fullDef->perpendicularBounce;
}
if (fullDef->weapDef.locationDamageMultipliers)
{
assert(sizeof(WeaponFullDef::locationDamageMultipliers) >= sizeof(float) * std::extent_v<decltype(WeaponFullDef::locationDamageMultipliers)>);
memcpy(fullDef->locationDamageMultipliers,
fullDef->weapDef.locationDamageMultipliers,
sizeof(float) * std::extent_v<decltype(WeaponFullDef::locationDamageMultipliers)>);
fullDef->weapDef.locationDamageMultipliers = fullDef->locationDamageMultipliers;
}
}
if (weapon->hideTags)
InfoString CreateInfoString(XAssetInfo<WeaponCompleteDef>* asset)
{
assert(sizeof(WeaponFullDef::hideTags) >= sizeof(scr_string_t) * std::extent_v<decltype(WeaponFullDef::hideTags)>);
memcpy(fullDef->hideTags, weapon->hideTags, sizeof(scr_string_t) * std::extent_v<decltype(WeaponFullDef::hideTags)>);
fullDef->weapCompleteDef.hideTags = fullDef->hideTags;
const auto fullDef = std::make_unique<WeaponFullDef>();
memset(fullDef.get(), 0, sizeof(WeaponFullDef));
CopyToFullDef(asset->Asset(), fullDef.get());
InfoStringFromWeaponConverter converter(fullDef.get(),
weapon_fields,
std::extent_v<decltype(weapon_fields)>,
[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 converter.Convert();
}
if (weapon->szXAnims)
void DumpAccuracyGraphs(AssetDumpingContext& context, XAssetInfo<WeaponCompleteDef>* asset)
{
assert(sizeof(WeaponFullDef::szXAnims) >= sizeof(void*) * NUM_WEAP_ANIMS);
memcpy(fullDef->szXAnims, weapon->szXAnims, sizeof(void*) * NUM_WEAP_ANIMS);
fullDef->weapCompleteDef.szXAnims = fullDef->szXAnims;
}
auto* accuracyGraphWriter = context.GetZoneAssetDumperState<AccuracyGraphWriter>();
const auto weapon = asset->Asset();
const auto* weapDef = weapon->weapDef;
if (fullDef->weapDef.gunXModel)
{
assert(sizeof(WeaponFullDef::gunXModel) >= sizeof(void*) * std::extent_v<decltype(WeaponFullDef::gunXModel)>);
memcpy(fullDef->gunXModel, fullDef->weapDef.gunXModel, sizeof(void*) * std::extent_v<decltype(WeaponFullDef::gunXModel)>);
fullDef->weapDef.gunXModel = fullDef->gunXModel;
}
if (fullDef->weapDef.szXAnimsRightHanded)
{
assert(sizeof(WeaponFullDef::szXAnimsRightHanded) >= sizeof(void*) * NUM_WEAP_ANIMS);
memcpy(fullDef->szXAnimsRightHanded, fullDef->weapDef.szXAnimsRightHanded, sizeof(void*) * NUM_WEAP_ANIMS);
fullDef->weapDef.szXAnimsRightHanded = fullDef->szXAnimsRightHanded;
}
if (fullDef->weapDef.szXAnimsLeftHanded)
{
assert(sizeof(WeaponFullDef::szXAnimsLeftHanded) >= sizeof(void*) * NUM_WEAP_ANIMS);
memcpy(fullDef->szXAnimsLeftHanded, fullDef->weapDef.szXAnimsLeftHanded, sizeof(void*) * NUM_WEAP_ANIMS);
fullDef->weapDef.szXAnimsLeftHanded = fullDef->szXAnimsLeftHanded;
}
if (fullDef->weapDef.notetrackSoundMapKeys)
{
assert(sizeof(WeaponFullDef::notetrackSoundMapKeys) >= sizeof(scr_string_t) * std::extent_v<decltype(WeaponFullDef::notetrackSoundMapKeys)>);
memcpy(fullDef->notetrackSoundMapKeys,
fullDef->weapDef.notetrackSoundMapKeys,
sizeof(scr_string_t) * std::extent_v<decltype(WeaponFullDef::notetrackSoundMapKeys)>);
fullDef->weapDef.notetrackSoundMapKeys = fullDef->notetrackSoundMapKeys;
}
if (fullDef->weapDef.notetrackSoundMapValues)
{
assert(sizeof(WeaponFullDef::notetrackSoundMapValues) >= sizeof(scr_string_t) * std::extent_v<decltype(WeaponFullDef::notetrackSoundMapKeys)>);
memcpy(fullDef->notetrackSoundMapValues,
fullDef->weapDef.notetrackSoundMapValues,
sizeof(scr_string_t) * std::extent_v<decltype(WeaponFullDef::notetrackSoundMapKeys)>);
fullDef->weapDef.notetrackSoundMapValues = fullDef->notetrackSoundMapValues;
}
if (fullDef->weapDef.notetrackRumbleMapKeys)
{
assert(sizeof(WeaponFullDef::notetrackRumbleMapKeys) >= sizeof(scr_string_t) * std::extent_v<decltype(WeaponFullDef::notetrackRumbleMapKeys)>);
memcpy(fullDef->notetrackRumbleMapKeys,
fullDef->weapDef.notetrackRumbleMapKeys,
sizeof(scr_string_t) * std::extent_v<decltype(WeaponFullDef::notetrackRumbleMapKeys)>);
fullDef->weapDef.notetrackRumbleMapKeys = fullDef->notetrackRumbleMapKeys;
}
if (fullDef->weapDef.notetrackRumbleMapValues)
{
assert(sizeof(WeaponFullDef::notetrackRumbleMapValues) >= sizeof(scr_string_t) * std::extent_v<decltype(WeaponFullDef::notetrackRumbleMapKeys)>);
memcpy(fullDef->notetrackRumbleMapValues,
fullDef->weapDef.notetrackRumbleMapValues,
sizeof(scr_string_t) * std::extent_v<decltype(WeaponFullDef::notetrackRumbleMapKeys)>);
fullDef->weapDef.notetrackRumbleMapValues = fullDef->notetrackRumbleMapValues;
}
if (fullDef->weapDef.worldModel)
{
assert(sizeof(WeaponFullDef::worldModel) >= sizeof(void*) * std::extent_v<decltype(WeaponFullDef::worldModel)>);
memcpy(fullDef->worldModel, fullDef->weapDef.worldModel, sizeof(void*) * std::extent_v<decltype(WeaponFullDef::worldModel)>);
fullDef->weapDef.worldModel = fullDef->worldModel;
}
if (fullDef->weapDef.parallelBounce)
{
assert(sizeof(WeaponFullDef::parallelBounce) >= sizeof(float) * std::extent_v<decltype(WeaponFullDef::parallelBounce)>);
memcpy(fullDef->parallelBounce, fullDef->weapDef.parallelBounce, sizeof(float) * std::extent_v<decltype(WeaponFullDef::parallelBounce)>);
fullDef->weapDef.parallelBounce = fullDef->parallelBounce;
}
if (fullDef->weapDef.perpendicularBounce)
{
assert(sizeof(WeaponFullDef::perpendicularBounce) >= sizeof(float) * std::extent_v<decltype(WeaponFullDef::perpendicularBounce)>);
memcpy(fullDef->perpendicularBounce, fullDef->weapDef.perpendicularBounce, sizeof(float) * std::extent_v<decltype(WeaponFullDef::perpendicularBounce)>);
fullDef->weapDef.perpendicularBounce = fullDef->perpendicularBounce;
}
if (fullDef->weapDef.locationDamageMultipliers)
{
assert(sizeof(WeaponFullDef::locationDamageMultipliers) >= sizeof(float) * std::extent_v<decltype(WeaponFullDef::locationDamageMultipliers)>);
memcpy(fullDef->locationDamageMultipliers,
fullDef->weapDef.locationDamageMultipliers,
sizeof(float) * std::extent_v<decltype(WeaponFullDef::locationDamageMultipliers)>);
fullDef->weapDef.locationDamageMultipliers = fullDef->locationDamageMultipliers;
}
}
InfoString AssetDumperWeapon::CreateInfoString(XAssetInfo<WeaponCompleteDef>* asset)
{
const auto fullDef = std::make_unique<WeaponFullDef>();
memset(fullDef.get(), 0, sizeof(WeaponFullDef));
CopyToFullDef(asset->Asset(), fullDef.get());
InfoStringFromWeaponConverter converter(fullDef.get(),
weapon_fields,
std::extent_v<decltype(weapon_fields)>,
[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 converter.Convert();
}
void AssetDumperWeapon::DumpAccuracyGraphs(AssetDumpingContext& context, XAssetInfo<WeaponCompleteDef>* asset)
{
auto* accuracyGraphWriter = context.GetZoneAssetDumperState<AccuracyGraphWriter>();
const auto weapon = asset->Asset();
const auto* weapDef = weapon->weapDef;
if (!weapDef)
return;
if (weapDef->aiVsAiAccuracyGraphName && weapDef->originalAiVsAiAccuracyGraphKnots
&& accuracyGraphWriter->ShouldDumpAiVsAiGraph(weapDef->aiVsAiAccuracyGraphName))
{
AccuracyGraphWriter::DumpAiVsAiGraph(
context,
ConvertAccuracyGraph(weapDef->aiVsAiAccuracyGraphName, weapDef->originalAiVsAiAccuracyGraphKnots, weapDef->originalAiVsAiAccuracyGraphKnotCount));
}
if (weapDef->aiVsPlayerAccuracyGraphName && weapDef->originalAiVsPlayerAccuracyGraphKnots
&& accuracyGraphWriter->ShouldDumpAiVsPlayerGraph(weapDef->aiVsPlayerAccuracyGraphName))
{
AccuracyGraphWriter::DumpAiVsPlayerGraph(context,
ConvertAccuracyGraph(weapDef->aiVsPlayerAccuracyGraphName,
weapDef->originalAiVsPlayerAccuracyGraphKnots,
weapDef->originalAiVsPlayerAccuracyGraphKnotCount));
}
}
bool AssetDumperWeapon::ShouldDump(XAssetInfo<WeaponCompleteDef>* asset)
{
return true;
}
void AssetDumperWeapon::DumpAsset(AssetDumpingContext& context, XAssetInfo<WeaponCompleteDef>* asset)
{
// Only dump raw when no gdt available
if (context.m_gdt)
{
const auto infoString = CreateInfoString(asset);
GdtEntry gdtEntry(asset->m_name, ObjConstants::GDF_FILENAME_WEAPON);
infoString.ToGdtProperties(ObjConstants::INFO_STRING_PREFIX_WEAPON, gdtEntry);
context.m_gdt->WriteEntry(gdtEntry);
}
else
{
const auto assetFile = context.OpenAssetFile("weapons/" + asset->m_name);
if (!assetFile)
if (!weapDef)
return;
auto& stream = *assetFile;
const auto infoString = CreateInfoString(asset);
const auto stringValue = infoString.ToString(ObjConstants::INFO_STRING_PREFIX_WEAPON);
stream.write(stringValue.c_str(), stringValue.size());
if (weapDef->aiVsAiAccuracyGraphName && weapDef->originalAiVsAiAccuracyGraphKnots
&& accuracyGraphWriter->ShouldDumpAiVsAiGraph(weapDef->aiVsAiAccuracyGraphName))
{
AccuracyGraphWriter::DumpAiVsAiGraph(context,
ConvertAccuracyGraph(weapDef->aiVsAiAccuracyGraphName,
weapDef->originalAiVsAiAccuracyGraphKnots,
weapDef->originalAiVsAiAccuracyGraphKnotCount));
}
if (weapDef->aiVsPlayerAccuracyGraphName && weapDef->originalAiVsPlayerAccuracyGraphKnots
&& accuracyGraphWriter->ShouldDumpAiVsPlayerGraph(weapDef->aiVsPlayerAccuracyGraphName))
{
AccuracyGraphWriter::DumpAiVsPlayerGraph(context,
ConvertAccuracyGraph(weapDef->aiVsPlayerAccuracyGraphName,
weapDef->originalAiVsPlayerAccuracyGraphKnots,
weapDef->originalAiVsPlayerAccuracyGraphKnotCount));
}
}
} // namespace
namespace IW4::weapon
{
bool Dumper::ShouldDump(XAssetInfo<WeaponCompleteDef>* asset)
{
return true;
}
DumpAccuracyGraphs(context, asset);
}
void Dumper::DumpAsset(AssetDumpingContext& context, XAssetInfo<WeaponCompleteDef>* asset)
{
// Only dump raw when no gdt available
if (context.m_gdt)
{
const auto infoString = CreateInfoString(asset);
GdtEntry gdtEntry(asset->m_name, ObjConstants::GDF_FILENAME_WEAPON);
infoString.ToGdtProperties(ObjConstants::INFO_STRING_PREFIX_WEAPON, gdtEntry);
context.m_gdt->WriteEntry(gdtEntry);
}
else
{
const auto assetFile = context.OpenAssetFile(GetFileNameForAssetName(asset->m_name));
if (!assetFile)
return;
auto& stream = *assetFile;
const auto infoString = CreateInfoString(asset);
const auto stringValue = infoString.ToString(ObjConstants::INFO_STRING_PREFIX_WEAPON);
stream.write(stringValue.c_str(), stringValue.size());
}
DumpAccuracyGraphs(context, asset);
}
} // namespace IW4::weapon

View File

@@ -0,0 +1,15 @@
#pragma once
#include "Dumping/AbstractAssetDumper.h"
#include "Game/IW4/IW4.h"
#include "InfoString/InfoString.h"
namespace IW4::weapon
{
class Dumper final : public AbstractAssetDumper<WeaponCompleteDef>
{
protected:
bool ShouldDump(XAssetInfo<WeaponCompleteDef>* asset) override;
void DumpAsset(AssetDumpingContext& context, XAssetInfo<WeaponCompleteDef>* asset) override;
};
} // namespace IW4::weapon