mirror of
https://github.com/Laupetin/OpenAssetTools.git
synced 2025-04-20 16:15:43 +00:00
Dump and load iw4 physpresets
This commit is contained in:
parent
87c2e58c4b
commit
bcafddd83a
@ -181,6 +181,21 @@ namespace IW4
|
|||||||
bool perSurfaceSndAlias;
|
bool perSurfaceSndAlias;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct PhysPresetInfo
|
||||||
|
{
|
||||||
|
float mass;
|
||||||
|
float bounce;
|
||||||
|
float friction;
|
||||||
|
int isFrictionInfinity;
|
||||||
|
float bulletForceScale;
|
||||||
|
float explosiveForceScale;
|
||||||
|
const char* sndAliasPrefix;
|
||||||
|
float piecesSpreadFraction;
|
||||||
|
float piecesUpwardVelocity;
|
||||||
|
int tempDefaultToCylinder;
|
||||||
|
int perSurfaceSndAlias;
|
||||||
|
};
|
||||||
|
|
||||||
struct Bounds
|
struct Bounds
|
||||||
{
|
{
|
||||||
float midPoint[3];
|
float midPoint[3];
|
||||||
|
20
src/ObjCommon/Game/IW4/InfoString/PhysPresetFields.h
Normal file
20
src/ObjCommon/Game/IW4/InfoString/PhysPresetFields.h
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "Game/IW4/IW4.h"
|
||||||
|
|
||||||
|
namespace IW4
|
||||||
|
{
|
||||||
|
inline cspField_t phys_preset_fields[]
|
||||||
|
{
|
||||||
|
{ "mass", offsetof(PhysPresetInfo, mass), CSPFT_FLOAT },
|
||||||
|
{ "bounce", offsetof(PhysPresetInfo, bounce), CSPFT_FLOAT },
|
||||||
|
{ "friction", offsetof(PhysPresetInfo, friction), CSPFT_FLOAT },
|
||||||
|
{ "isFrictionInfinity", offsetof(PhysPresetInfo, isFrictionInfinity), CSPFT_QBOOLEAN },
|
||||||
|
{ "bulletForceScale", offsetof(PhysPresetInfo, bulletForceScale), CSPFT_FLOAT },
|
||||||
|
{ "explosiveForceScale", offsetof(PhysPresetInfo, explosiveForceScale), CSPFT_FLOAT },
|
||||||
|
{ "sndAliasPrefix", offsetof(PhysPresetInfo, sndAliasPrefix), CSPFT_STRING },
|
||||||
|
{ "piecesSpreadFraction", offsetof(PhysPresetInfo, piecesSpreadFraction), CSPFT_FLOAT },
|
||||||
|
{ "piecesUpwardVelocity", offsetof(PhysPresetInfo, piecesUpwardVelocity), CSPFT_FLOAT },
|
||||||
|
{ "tempDefaultToCylinder", offsetof(PhysPresetInfo, tempDefaultToCylinder), CSPFT_QBOOLEAN },
|
||||||
|
{ "perSurfaceSndAlias", offsetof(PhysPresetInfo, perSurfaceSndAlias), CSPFT_QBOOLEAN },
|
||||||
|
};
|
||||||
|
}
|
@ -1,13 +1,77 @@
|
|||||||
#include "AssetLoaderPhysPreset.h"
|
#include "AssetLoaderPhysPreset.h"
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
#include "ObjLoading.h"
|
#include "ObjLoading.h"
|
||||||
#include "Game/IW4/IW4.h"
|
#include "Game/IW4/IW4.h"
|
||||||
|
#include "Game/IW4/ObjConstantsIW4.h"
|
||||||
|
#include "Game/IW4/InfoString/InfoStringToStructConverter.h"
|
||||||
|
#include "Game/IW4/InfoString/PhysPresetFields.h"
|
||||||
#include "Pool/GlobalAssetPool.h"
|
#include "Pool/GlobalAssetPool.h"
|
||||||
|
|
||||||
using namespace IW4;
|
using namespace IW4;
|
||||||
|
|
||||||
|
namespace IW4
|
||||||
|
{
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
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->sndAliasPrefix = physPresetInfo->sndAliasPrefix;
|
||||||
|
physPreset->piecesSpreadFraction = physPresetInfo->piecesSpreadFraction;
|
||||||
|
physPreset->piecesUpwardVelocity = physPresetInfo->piecesUpwardVelocity;
|
||||||
|
physPreset->tempDefaultToCylinder = physPresetInfo->tempDefaultToCylinder != 0;
|
||||||
|
physPreset->perSurfaceSndAlias = physPresetInfo->perSurfaceSndAlias != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
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<decltype(phys_preset_fields)>::value);
|
||||||
|
if (!converter.Convert())
|
||||||
|
{
|
||||||
|
std::cout << "Failed to parse phys preset: \"" << assetName << "\"" << std::endl;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto* physPreset = memory->Create<PhysPreset>();
|
||||||
|
|
||||||
|
CopyFromPhysPresetInfo(presetInfo.get(), physPreset);
|
||||||
|
physPreset->name = memory->Dup(assetName.c_str());
|
||||||
|
|
||||||
|
manager->AddAsset(ASSET_TYPE_PHYSPRESET, assetName, physPreset, converter.GetDependencies(), converter.GetUsedScriptStrings());
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void* AssetLoaderPhysPreset::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
|
void* AssetLoaderPhysPreset::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
|
||||||
{
|
{
|
||||||
auto* physPreset = memory->Create<PhysPreset>();
|
auto* physPreset = memory->Create<PhysPreset>();
|
||||||
@ -15,3 +79,47 @@ void* AssetLoaderPhysPreset::CreateEmptyAsset(const std::string& assetName, Memo
|
|||||||
physPreset->name = memory->Dup(assetName.c_str());
|
physPreset->name = memory->Dup(assetName.c_str());
|
||||||
return physPreset;
|
return physPreset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 << "\"" << std::endl;
|
||||||
|
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::cout << "Failed to read phys preset raw file: \"" << fileName << "\"" << std::endl;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return LoadFromInfoString(infoString, assetName, memory, manager, zone);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -2,13 +2,22 @@
|
|||||||
|
|
||||||
#include "Game/IW4/IW4.h"
|
#include "Game/IW4/IW4.h"
|
||||||
#include "AssetLoading/BasicAssetLoader.h"
|
#include "AssetLoading/BasicAssetLoader.h"
|
||||||
|
#include "InfoString/InfoString.h"
|
||||||
#include "SearchPath/ISearchPath.h"
|
#include "SearchPath/ISearchPath.h"
|
||||||
|
|
||||||
namespace IW4
|
namespace IW4
|
||||||
{
|
{
|
||||||
class AssetLoaderPhysPreset final : public BasicAssetLoader<ASSET_TYPE_PHYSPRESET, PhysPreset>
|
class AssetLoaderPhysPreset final : public BasicAssetLoader<ASSET_TYPE_PHYSPRESET, PhysPreset>
|
||||||
{
|
{
|
||||||
|
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:
|
public:
|
||||||
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
|
_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;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,227 @@
|
|||||||
#include "InfoStringToStructConverter.h"
|
#include "InfoStringToStructConverter.h"
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
using namespace IW4;
|
using namespace IW4;
|
||||||
|
|
||||||
|
InfoStringToStructConverter::InfoStringToStructConverter(const InfoString& infoString, void* structure, ZoneScriptStrings& zoneScriptStrings, MemoryManager* memory, IAssetLoadingManager* manager,
|
||||||
|
const cspField_t* fields, const size_t fieldCount)
|
||||||
|
: InfoStringToStructConverterBase(infoString, structure, zoneScriptStrings, memory),
|
||||||
|
m_loading_manager(manager),
|
||||||
|
m_fields(fields),
|
||||||
|
m_field_count(fieldCount)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool InfoStringToStructConverter::ConvertBaseField(const cspField_t& field, const std::string& value)
|
||||||
|
{
|
||||||
|
switch (static_cast<csParseFieldType_t>(field.iFieldType))
|
||||||
|
{
|
||||||
|
case CSPFT_STRING:
|
||||||
|
return ConvertString(value, field.iOffset);
|
||||||
|
|
||||||
|
case CSPFT_STRING_MAX_STRING_CHARS:
|
||||||
|
return ConvertStringBuffer(value, field.iOffset, 1024);
|
||||||
|
|
||||||
|
case CSPFT_STRING_MAX_QPATH:
|
||||||
|
return ConvertStringBuffer(value, field.iOffset, 64);
|
||||||
|
|
||||||
|
case CSPFT_STRING_MAX_OSPATH:
|
||||||
|
return ConvertStringBuffer(value, field.iOffset, 256);
|
||||||
|
|
||||||
|
case CSPFT_INT:
|
||||||
|
return ConvertInt(value, field.iOffset);
|
||||||
|
|
||||||
|
case CSPFT_BOOL:
|
||||||
|
return ConvertBool(value, field.iOffset);
|
||||||
|
|
||||||
|
case CSPFT_QBOOLEAN:
|
||||||
|
return ConvertQBoolean(value, field.iOffset);
|
||||||
|
|
||||||
|
case CSPFT_FLOAT:
|
||||||
|
return ConvertFloat(value, field.iOffset);
|
||||||
|
|
||||||
|
case CSPFT_MILLISECONDS:
|
||||||
|
return ConvertMilliseconds(value, field.iOffset);
|
||||||
|
|
||||||
|
case CSPFT_FX:
|
||||||
|
{
|
||||||
|
if (value.empty())
|
||||||
|
{
|
||||||
|
*reinterpret_cast<void**>(reinterpret_cast<uintptr_t>(m_structure) + field.iOffset) = nullptr;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto* fx = m_loading_manager->LoadDependency(ASSET_TYPE_FX, value);
|
||||||
|
|
||||||
|
if (fx == nullptr)
|
||||||
|
{
|
||||||
|
std::cout << "Failed to load fx asset \"" << value << "\"" << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_dependencies.emplace(fx);
|
||||||
|
*reinterpret_cast<void**>(reinterpret_cast<uintptr_t>(m_structure) + field.iOffset) = fx->m_ptr;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
case CSPFT_XMODEL:
|
||||||
|
{
|
||||||
|
if (value.empty())
|
||||||
|
{
|
||||||
|
*reinterpret_cast<void**>(reinterpret_cast<uintptr_t>(m_structure) + field.iOffset) = nullptr;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto* xmodel = m_loading_manager->LoadDependency(ASSET_TYPE_XMODEL, value);
|
||||||
|
|
||||||
|
if (xmodel == nullptr)
|
||||||
|
{
|
||||||
|
std::cout << "Failed to load xmodel asset \"" << value << "\"" << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_dependencies.emplace(xmodel);
|
||||||
|
*reinterpret_cast<void**>(reinterpret_cast<uintptr_t>(m_structure) + field.iOffset) = xmodel->m_ptr;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
case CSPFT_MATERIAL:
|
||||||
|
{
|
||||||
|
if (value.empty())
|
||||||
|
{
|
||||||
|
*reinterpret_cast<void**>(reinterpret_cast<uintptr_t>(m_structure) + field.iOffset) = nullptr;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto* material = m_loading_manager->LoadDependency(ASSET_TYPE_MATERIAL, value);
|
||||||
|
|
||||||
|
if (material == nullptr)
|
||||||
|
{
|
||||||
|
std::cout << "Failed to load material asset \"" << value << "\"" << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_dependencies.emplace(material);
|
||||||
|
*reinterpret_cast<void**>(reinterpret_cast<uintptr_t>(m_structure) + field.iOffset) = material->m_ptr;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
case CSPFT_TRACER:
|
||||||
|
{
|
||||||
|
if (value.empty())
|
||||||
|
{
|
||||||
|
*reinterpret_cast<void**>(reinterpret_cast<uintptr_t>(m_structure) + field.iOffset) = nullptr;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto* tracer = m_loading_manager->LoadDependency(ASSET_TYPE_TRACER, value);
|
||||||
|
|
||||||
|
if (tracer == nullptr)
|
||||||
|
{
|
||||||
|
std::cout << "Failed to load tracer asset \"" << value << "\"" << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_dependencies.emplace(tracer);
|
||||||
|
*reinterpret_cast<void**>(reinterpret_cast<uintptr_t>(m_structure) + field.iOffset) = tracer->m_ptr;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
case CSPFT_MPH_TO_INCHES_PER_SEC:
|
||||||
|
{
|
||||||
|
char* endPtr;
|
||||||
|
*reinterpret_cast<float*>(reinterpret_cast<uintptr_t>(m_structure) + field.iOffset) = strtof(value.c_str(), &endPtr) * 17.6f;
|
||||||
|
|
||||||
|
if (endPtr != &value[value.size()])
|
||||||
|
{
|
||||||
|
std::cout << "Failed to parse value \"" << value << "\" as mph" << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
case CSPFT_PHYS_COLLMAP:
|
||||||
|
{
|
||||||
|
if (value.empty())
|
||||||
|
{
|
||||||
|
*reinterpret_cast<void**>(reinterpret_cast<uintptr_t>(m_structure) + field.iOffset) = nullptr;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto* collmap = m_loading_manager->LoadDependency(ASSET_TYPE_PHYSCOLLMAP, value);
|
||||||
|
|
||||||
|
if (collmap == nullptr)
|
||||||
|
{
|
||||||
|
std::cout << "Failed to load collmap asset \"" << value << "\"" << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_dependencies.emplace(collmap);
|
||||||
|
*reinterpret_cast<void**>(reinterpret_cast<uintptr_t>(m_structure) + field.iOffset) = collmap->m_ptr;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
case CSPFT_SOUND:
|
||||||
|
{
|
||||||
|
if (value.empty())
|
||||||
|
{
|
||||||
|
*reinterpret_cast<void**>(reinterpret_cast<uintptr_t>(m_structure) + field.iOffset) = nullptr;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto* sound = m_loading_manager->LoadDependency(ASSET_TYPE_SOUND, value);
|
||||||
|
|
||||||
|
if (sound == nullptr)
|
||||||
|
{
|
||||||
|
std::cout << "Failed to load sound asset \"" << value << "\"" << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_dependencies.emplace(sound);
|
||||||
|
*reinterpret_cast<void**>(reinterpret_cast<uintptr_t>(m_structure) + field.iOffset) = sound->m_ptr;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
case CSPFT_NUM_BASE_FIELD_TYPES:
|
||||||
|
default:
|
||||||
|
assert(false);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool InfoStringToStructConverter::Convert()
|
||||||
|
{
|
||||||
|
for (auto fieldIndex = 0u; fieldIndex < m_field_count; fieldIndex++)
|
||||||
|
{
|
||||||
|
const auto& field = m_fields[fieldIndex];
|
||||||
|
assert(field.iFieldType >= 0);
|
||||||
|
|
||||||
|
auto foundValue = false;
|
||||||
|
const auto& value = m_info_string.GetValueForKey(std::string(field.szName), &foundValue);
|
||||||
|
|
||||||
|
if (foundValue)
|
||||||
|
{
|
||||||
|
if (field.iFieldType < CSPFT_NUM_BASE_FIELD_TYPES)
|
||||||
|
{
|
||||||
|
if (!ConvertBaseField(field, value))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!ConvertExtensionField(field, value))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
@ -12,8 +12,6 @@ namespace IW4
|
|||||||
const cspField_t* m_fields;
|
const cspField_t* m_fields;
|
||||||
size_t m_field_count;
|
size_t m_field_count;
|
||||||
|
|
||||||
static bool GetHashValue(const std::string& value, unsigned int& hash);
|
|
||||||
|
|
||||||
virtual bool ConvertExtensionField(const cspField_t& field, const std::string& value) = 0;
|
virtual bool ConvertExtensionField(const cspField_t& field, const std::string& value) = 0;
|
||||||
bool ConvertBaseField(const cspField_t& field, const std::string& value);
|
bool ConvertBaseField(const cspField_t& field, const std::string& value);
|
||||||
|
|
||||||
|
101
src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperPhysPreset.cpp
Normal file
101
src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperPhysPreset.cpp
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
#include "AssetDumperPhysPreset.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cassert>
|
||||||
|
#include <cmath>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
#include "Game/IW4/ObjConstantsIW4.h"
|
||||||
|
#include "Game/IW4/InfoString/InfoStringFromStructConverter.h"
|
||||||
|
#include "Game/IW4/InfoString/PhysPresetFields.h"
|
||||||
|
|
||||||
|
using namespace IW4;
|
||||||
|
|
||||||
|
namespace IW4
|
||||||
|
{
|
||||||
|
class InfoStringFromPhysPresetConverter final : public InfoStringFromStructConverter
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
void FillFromExtensionField(const cspField_t& field) override
|
||||||
|
{
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
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))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
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))
|
||||||
|
{
|
||||||
|
physPresetInfo->isFrictionInfinity = 1;
|
||||||
|
physPresetInfo->friction = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
physPresetInfo->isFrictionInfinity = 0;
|
||||||
|
physPresetInfo->friction = physPreset->friction;
|
||||||
|
}
|
||||||
|
|
||||||
|
physPresetInfo->bulletForceScale = physPreset->bulletForceScale;
|
||||||
|
physPresetInfo->explosiveForceScale = physPreset->explosiveForceScale;
|
||||||
|
physPresetInfo->sndAliasPrefix = physPreset->sndAliasPrefix;
|
||||||
|
physPresetInfo->piecesSpreadFraction = physPreset->piecesSpreadFraction;
|
||||||
|
physPresetInfo->piecesUpwardVelocity = physPreset->piecesUpwardVelocity;
|
||||||
|
physPresetInfo->tempDefaultToCylinder = physPreset->tempDefaultToCylinder ? 1 : 0;
|
||||||
|
physPresetInfo->perSurfaceSndAlias = physPreset->perSurfaceSndAlias ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 "";
|
||||||
|
|
||||||
|
return asset->m_zone->m_script_strings[scrStr];
|
||||||
|
});
|
||||||
|
|
||||||
|
return converter.Convert();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AssetDumperPhysPreset::ShouldDump(XAssetInfo<PhysPreset>* asset)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AssetDumperPhysPreset::DumpAsset(AssetDumpingContext& context, XAssetInfo<PhysPreset>* 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_PHYS_PRESET);
|
||||||
|
infoString.ToGdtProperties(ObjConstants::INFO_STRING_PREFIX_PHYS_PRESET, gdtEntry);
|
||||||
|
context.m_gdt->WriteEntry(gdtEntry);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const auto assetFile = context.OpenAssetFile("physic/" + asset->m_name);
|
||||||
|
|
||||||
|
if (!assetFile)
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto& stream = *assetFile;
|
||||||
|
const auto infoString = CreateInfoString(asset);
|
||||||
|
const auto stringValue = infoString.ToString(ObjConstants::INFO_STRING_PREFIX_PHYS_PRESET);
|
||||||
|
stream.write(stringValue.c_str(), stringValue.size());
|
||||||
|
}
|
||||||
|
}
|
18
src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperPhysPreset.h
Normal file
18
src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperPhysPreset.h
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Dumping/AbstractAssetDumper.h"
|
||||||
|
#include "Game/IW4/IW4.h"
|
||||||
|
#include "InfoString/InfoString.h"
|
||||||
|
|
||||||
|
namespace IW4
|
||||||
|
{
|
||||||
|
class AssetDumperPhysPreset final : public AbstractAssetDumper<PhysPreset>
|
||||||
|
{
|
||||||
|
static void CopyToPhysPresetInfo(const PhysPreset* physPreset, PhysPresetInfo* physPresetInfo);
|
||||||
|
static InfoString CreateInfoString(XAssetInfo<PhysPreset>* asset);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool ShouldDump(XAssetInfo<PhysPreset>* asset) override;
|
||||||
|
void DumpAsset(AssetDumpingContext& context, XAssetInfo<PhysPreset>* asset) override;
|
||||||
|
};
|
||||||
|
}
|
@ -10,6 +10,7 @@
|
|||||||
#include "AssetDumpers/AssetDumperLocalizeEntry.h"
|
#include "AssetDumpers/AssetDumperLocalizeEntry.h"
|
||||||
#include "AssetDumpers/AssetDumperMenuDef.h"
|
#include "AssetDumpers/AssetDumperMenuDef.h"
|
||||||
#include "AssetDumpers/AssetDumperMenuList.h"
|
#include "AssetDumpers/AssetDumperMenuList.h"
|
||||||
|
#include "AssetDumpers/AssetDumperPhysPreset.h"
|
||||||
#include "AssetDumpers/AssetDumperRawFile.h"
|
#include "AssetDumpers/AssetDumperRawFile.h"
|
||||||
#include "AssetDumpers/AssetDumperStringTable.h"
|
#include "AssetDumpers/AssetDumperStringTable.h"
|
||||||
#include "AssetDumpers/AssetDumperVehicle.h"
|
#include "AssetDumpers/AssetDumperVehicle.h"
|
||||||
@ -34,7 +35,7 @@ bool ZoneDumper::DumpZone(AssetDumpingContext& context) const
|
|||||||
|
|
||||||
const auto* assetPools = dynamic_cast<GameAssetPoolIW4*>(context.m_zone->m_pools.get());
|
const auto* assetPools = dynamic_cast<GameAssetPoolIW4*>(context.m_zone->m_pools.get());
|
||||||
|
|
||||||
// DUMP_ASSET_POOL(AssetDumperPhysPreset, m_phys_preset, ASSET_TYPE_PHYSPRESET)
|
DUMP_ASSET_POOL(AssetDumperPhysPreset, m_phys_preset, ASSET_TYPE_PHYSPRESET)
|
||||||
// DUMP_ASSET_POOL(AssetDumperPhysCollmap, m_phys_collmap, ASSET_TYPE_PHYSCOLLMAP)
|
// DUMP_ASSET_POOL(AssetDumperPhysCollmap, m_phys_collmap, ASSET_TYPE_PHYSCOLLMAP)
|
||||||
// DUMP_ASSET_POOL(AssetDumperXAnimParts, m_xanim_parts, ASSET_TYPE_XANIMPARTS)
|
// DUMP_ASSET_POOL(AssetDumperXAnimParts, m_xanim_parts, ASSET_TYPE_XANIMPARTS)
|
||||||
DUMP_ASSET_POOL(AssetDumperXModel, m_xmodel, ASSET_TYPE_XMODEL)
|
DUMP_ASSET_POOL(AssetDumperXModel, m_xmodel, ASSET_TYPE_XMODEL)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user