diff --git a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderVehicle.cpp b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderVehicle.cpp new file mode 100644 index 00000000..a976a56e --- /dev/null +++ b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderVehicle.cpp @@ -0,0 +1,142 @@ +#include "AssetLoaderVehicle.h" + +#include +#include + +#include "Game/T6/ObjConstantsT6.h" +#include "Game/T6/T6.h" +#include "Game/T6/InfoString/EnumStrings.h" +#include "Game/T6/InfoString/InfoStringToStructConverter.h" +#include "Game/T6/InfoString/VehicleFields.h" +#include "InfoString/InfoString.h" +#include "Pool/GlobalAssetPool.h" + +using namespace T6; + +namespace T6 +{ + class InfoStringToVehicleConverter final : public InfoStringToStructConverter + { + protected: + bool ConvertExtensionField(const cspField_t& field, const std::string& value) override + { + switch (static_cast(field.iFieldType)) + { + case VFT_TYPE: + return ConvertEnumInt(value, field.iOffset, s_vehicleClassNames, std::extent::value); + + case VFT_CAMERAMODE: + return ConvertEnumInt(value, field.iOffset, s_vehicleCameraModes, std::extent::value); + + case VFT_TRACTION_TYPE: + return ConvertEnumInt(value, field.iOffset, s_tractionTypeNames, std::extent::value); + + case VFT_MPH_TO_INCHES_PER_SECOND: + { + char* endPtr; + *reinterpret_cast(reinterpret_cast(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 VFT_POUNDS_TO_GAME_MASS: + { + char* endPtr; + *reinterpret_cast(reinterpret_cast(m_structure) + field.iOffset) = strtof(value.c_str(), &endPtr) * 0.001f; + + if (endPtr != &value[value.size()]) + { + std::cout << "Failed to parse value \"" << value << "\" as pounds" << std::endl; + return false; + } + + return true; + } + + case VFT_TEAM: + { + if (value == "axis") + { + *reinterpret_cast(reinterpret_cast(m_structure) + field.iOffset) = TEAM_AXIS; + return true; + } + + if (value == "allies") + { + *reinterpret_cast(reinterpret_cast(m_structure) + field.iOffset) = TEAM_ALLIES; + return true; + } + + *reinterpret_cast(reinterpret_cast(m_structure) + field.iOffset) = TEAM_BAD; + std::cout << "Failed to parse value \"" << value << "\" as team" << std::endl; + return false; + } + + case VFT_KEY_BINDING: + case VFT_GRAPH: + case VFT_WIIUCONTROLOVERRIDE: + case VFT_NUM: + default: + assert(false); + return false; + } + } + + public: + InfoStringToVehicleConverter(const InfoString& infoString, VehicleDef* vehicleDef, ZoneScriptStrings& zoneScriptStrings, MemoryManager* memory, IAssetLoadingManager* manager, + const cspField_t* fields, const size_t fieldCount) + : InfoStringToStructConverter(infoString, vehicleDef, zoneScriptStrings, memory, manager, fields, fieldCount) + { + } + }; +} + +void* AssetLoaderVehicle::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) +{ + auto* vehicleDef = memory->Create(); + memset(vehicleDef, 0, sizeof(VehicleDef)); + vehicleDef->name = memory->Dup(assetName.c_str()); + return vehicleDef; +} + +bool AssetLoaderVehicle::CanLoadFromRaw() const +{ + return true; +} + +bool AssetLoaderVehicle::LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const +{ + const auto fileName = "vehicles/" + assetName; + const auto file = searchPath->Open(fileName); + if (!file.IsOpen()) + return false; + + InfoString infoString; + if (!infoString.FromStream(ObjConstants::INFO_STRING_PREFIX_VEHICLE, *file.m_stream)) + { + std::cout << "Failed to read vehicle raw file: \"" << fileName << "\"" << std::endl; + return true; + } + + auto* vehicleDef = memory->Create(); + memset(vehicleDef, 0, sizeof(VehicleDef)); + + InfoStringToVehicleConverter converter(infoString, vehicleDef, zone->m_script_strings, memory, manager, vehicle_fields, std::extent::value); + if(!converter.Convert()) + { + std::cout << "Failed to parse vehicle raw file: \"" << fileName << "\"" << std::endl; + return true; + } + + vehicleDef->name = memory->Dup(assetName.c_str()); + + manager->AddAsset(ASSET_TYPE_VEHICLEDEF, assetName, vehicleDef, converter.GetDependencies(), converter.GetUsedScriptStrings()); + + return true; +} diff --git a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderVehicle.h b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderVehicle.h new file mode 100644 index 00000000..b3e5e3e7 --- /dev/null +++ b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderVehicle.h @@ -0,0 +1,16 @@ +#pragma once +#include "Game/T6/T6.h" +#include "AssetLoading/BasicAssetLoader.h" +#include "AssetLoading/IAssetLoadingManager.h" +#include "SearchPath/ISearchPath.h" + +namespace T6 +{ + class AssetLoaderVehicle final : public BasicAssetLoader + { + public: + _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; + _NODISCARD bool CanLoadFromRaw() const override; + bool LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override; + }; +} diff --git a/src/ObjLoading/Game/T6/ObjLoaderT6.cpp b/src/ObjLoading/Game/T6/ObjLoaderT6.cpp index 7f62f18b..aac55bf9 100644 --- a/src/ObjLoading/Game/T6/ObjLoaderT6.cpp +++ b/src/ObjLoading/Game/T6/ObjLoaderT6.cpp @@ -11,6 +11,7 @@ #include "AssetLoaders/AssetLoaderScriptParseTree.h" #include "AssetLoaders/AssetLoaderSlug.h" #include "AssetLoaders/AssetLoaderStringTable.h" +#include "AssetLoaders/AssetLoaderVehicle.h" #include "AssetLoading/AssetLoadingManager.h" #include "Image/Texture.h" #include "Image/IwiLoader.h" @@ -64,7 +65,7 @@ namespace T6 REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_GLASSES, Glasses)) REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_EMBLEMSET, EmblemSet)) REGISTER_ASSET_LOADER(AssetLoaderScriptParseTree) - REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_VEHICLEDEF, VehicleDef)) + REGISTER_ASSET_LOADER(AssetLoaderVehicle) REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_MEMORYBLOCK, MemoryBlock)) REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_ADDON_MAP_ENTS, AddonMapEnts)) REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_TRACER, TracerDef))