diff --git a/src/ObjCommon/Weapon/GenericAccuracyGraph.h b/src/ObjCommon/Weapon/GenericAccuracyGraph.h new file mode 100644 index 00000000..2f827204 --- /dev/null +++ b/src/ObjCommon/Weapon/GenericAccuracyGraph.h @@ -0,0 +1,17 @@ +#pragma once +#include +#include + +class GenericAccuracyGraphKnot +{ +public: + float x; + float y; +}; + +class GenericAccuracyGraph +{ +public: + std::string name; + std::vector knots; +}; diff --git a/src/ObjWriting/Weapon/AccuracyGraphWriter.cpp b/src/ObjWriting/Weapon/AccuracyGraphWriter.cpp new file mode 100644 index 00000000..b6f0583f --- /dev/null +++ b/src/ObjWriting/Weapon/AccuracyGraphWriter.cpp @@ -0,0 +1,57 @@ +#include "AccuracyGraphWriter.h" + +#include + +namespace +{ + bool ShouldDumpAccuracyGraph(std::unordered_set& dumpedGraphs, const std::string& graphName) + { + if (graphName.empty()) + return false; + + const auto existingEntry = dumpedGraphs.find(graphName); + if (existingEntry == dumpedGraphs.end()) + { + dumpedGraphs.emplace(graphName); + return true; + } + + return false; + } + + void DumpAccuracyGraph(const AssetDumpingContext& context, const GenericAccuracyGraph& graph, const std::string& subFolder) + { + const auto file = context.OpenAssetFile(std::format("accuracy/{}/{}", subFolder, graph.name)); + if (!file) + { + std::cerr << "Failed to open file for accuracy graph: " << subFolder << "/" << graph.name << "\n"; + return; + } + + *file << "WEAPONACCUFILE\n\n"; + *file << graph.knots.size() << "\n"; + + for (const auto& knot : graph.knots) + *file << std::format("{:.4f} {:.4f}\n", knot.x, knot.y); + } +} // namespace + +bool AccuracyGraphWriter::ShouldDumpAiVsAiGraph(const std::string& graphName) +{ + return ShouldDumpAccuracyGraph(m_dumped_ai_vs_ai_graphs, graphName); +} + +bool AccuracyGraphWriter::ShouldDumpAiVsPlayerGraph(const std::string& graphName) +{ + return ShouldDumpAccuracyGraph(m_dumped_ai_vs_player_graphs, graphName); +} + +void AccuracyGraphWriter::DumpAiVsAiGraph(const AssetDumpingContext& context, const GenericAccuracyGraph& aiVsAiGraph) +{ + DumpAccuracyGraph(context, aiVsAiGraph, "aivsai"); +} + +void AccuracyGraphWriter::DumpAiVsPlayerGraph(const AssetDumpingContext& context, const GenericAccuracyGraph& aiVsPlayerGraph) +{ + DumpAccuracyGraph(context, aiVsPlayerGraph, "aivsplayer"); +} diff --git a/src/ObjWriting/Weapon/AccuracyGraphWriter.h b/src/ObjWriting/Weapon/AccuracyGraphWriter.h new file mode 100644 index 00000000..a5e2edc3 --- /dev/null +++ b/src/ObjWriting/Weapon/AccuracyGraphWriter.h @@ -0,0 +1,21 @@ +#pragma once +#include "Dumping/AssetDumpingContext.h" +#include "Dumping/IZoneAssetDumperState.h" +#include "Weapon/GenericAccuracyGraph.h" + +#include +#include + +class AccuracyGraphWriter final : public IZoneAssetDumperState +{ +public: + bool ShouldDumpAiVsAiGraph(const std::string& graphName); + bool ShouldDumpAiVsPlayerGraph(const std::string& graphName); + + static void DumpAiVsAiGraph(const AssetDumpingContext& context, const GenericAccuracyGraph& aiVsAiGraph); + static void DumpAiVsPlayerGraph(const AssetDumpingContext& context, const GenericAccuracyGraph& aiVsPlayerGraph); + +private: + std::unordered_set m_dumped_ai_vs_ai_graphs; + std::unordered_set m_dumped_ai_vs_player_graphs; +};