Merge pull request #198 from Laupetin/feature/accuracy-tables

feat: dump and load weapon accuracy tables
This commit is contained in:
Jan 2024-05-20 13:58:53 +02:00 committed by GitHub
commit 47f5f2aa45
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
35 changed files with 908 additions and 416 deletions

View File

@ -3091,20 +3091,16 @@ namespace IW3
float fHipViewScatterMax; float fHipViewScatterMax;
float fightDist; float fightDist;
float maxDist; float maxDist;
// TODO: Order is accuracyGraphName[0] -> originalAccuracyGraphKnots[0] -> accuracyGraphName[1] -> ... const char* aiVsAiAccuracyGraphName;
// Which is currently not possible to do in code generation. Afaik this is the only place where this is the case. const char* aiVsPlayerAccuracyGraphName;
// So might be something to fix but on the other hand it might be too much work for this little inconvenience. vec2_t* aiVsAiAccuracyGraphKnots;
// const char* accuracyGraphName[2]; vec2_t* aiVsPlayerAccuracyGraphKnots;
const char* accuracyGraphName0; vec2_t* originalAiVsAiAccuracyGraphKnots;
const char* accuracyGraphName1; vec2_t* originalAiVsPlayerAccuracyGraphKnots;
// float(*accuracyGraphKnots[2])[2]; int aiVsAiAccuracyGraphKnotCount;
vec2_t* accuracyGraphKnots0; int aiVsPlayerAccuracyGraphKnotCount;
vec2_t* accuracyGraphKnots1; int originalAiVsAiAccuracyGraphKnotCount;
// float(*originalAccuracyGraphKnots[2])[2]; int originalAiVsPlayerAccuracyGraphKnotCount;
vec2_t* originalAccuracyGraphKnots0;
vec2_t* originalAccuracyGraphKnots1;
int accuracyGraphKnotCount[2];
int originalAccuracyGraphKnotCount[2];
int iPositionReloadTransTime; int iPositionReloadTransTime;
float leftArc; float leftArc;
float rightArc; float rightArc;

View File

@ -4399,15 +4399,12 @@ namespace IW4
float fHipViewScatterMax; float fHipViewScatterMax;
float fightDist; float fightDist;
float maxDist; float maxDist;
// const char* accuracyGraphName[2];// TODO: Order is accuracyGraphName[0] -> originalAccuracyGraphKnots[0] -> accuracyGraphName[1] -> ... const char* aiVsAiAccuracyGraphName;
// Which is currently not possible to do in code generation. Afaik this is the only place where this is the case. const char* aiVsPlayerAccuracyGraphName;
// So might be something to fix but on the other hand it might be too much work for this little inconvenience. vec2_t* originalAiVsAiAccuracyGraphKnots;
// vec2_t* originalAccuracyGraphKnots[2]; vec2_t* originalAiVsPlayerAccuracyGraphKnots;
const char* accuracyGraphName0; uint16_t originalAiVsAiAccuracyGraphKnotCount;
const char* accuracyGraphName1; uint16_t originalAiVsPlayerAccuracyGraphKnotCount;
vec2_t* originalAccuracyGraphKnots0;
vec2_t* originalAccuracyGraphKnots1;
uint16_t originalAccuracyGraphKnotCount[2];
int iPositionReloadTransTime; int iPositionReloadTransTime;
float leftArc; float leftArc;
float rightArc; float rightArc;
@ -4551,8 +4548,10 @@ namespace IW4
int ammoDropStockMax; int ammoDropStockMax;
float adsDofStart; float adsDofStart;
float adsDofEnd; float adsDofEnd;
uint16_t accuracyGraphKnotCount[2]; uint16_t aiVsAiAccuracyGraphKnotCount;
vec2_t* accuracyGraphKnots[2]; uint16_t aiVsPlayerAccuracyGraphKnotCount;
vec2_t* aiVsAiAccuracyGraphKnots;
vec2_t* aiVsPlayerAccuracyGraphKnots;
bool motionTracker; bool motionTracker;
bool enhanced; bool enhanced;
bool dpadIconShowsAmmo; bool dpadIconShowsAmmo;

View File

@ -3756,15 +3756,12 @@ namespace IW5
float fHipViewScatterMax; float fHipViewScatterMax;
float fightDist; float fightDist;
float maxDist; float maxDist;
// const char* accuracyGraphName[2];// TODO: Order is accuracyGraphName[0] -> originalAccuracyGraphKnots[0] -> accuracyGraphName[1] -> ... const char* aiVsAiAccuracyGraphName;
// Which is currently not possible to do in code generation. Afaik this is the only place where this is the case. const char* aiVsPlayerAccuracyGraphName;
// So might be something to fix but on the other hand it might be too much work for this little inconvenience. vec2_t* originalAiVsAiAccuracyGraphKnots;
// vec2_t* originalAccuracyGraphKnots[2]; vec2_t* originalAiVsPlayerAccuracyGraphKnots;
const char* accuracyGraphName0; unsigned short originalAiVsAiAccuracyGraphKnotCount;
const char* accuracyGraphName1; unsigned short originalAiVsPlayerAccuracyGraphKnotCount;
vec2_t* originalAccuracyGraphKnots0;
vec2_t* originalAccuracyGraphKnots1;
unsigned short originalAccuracyGraphKnotCount[2];
int iPositionReloadTransTime; int iPositionReloadTransTime;
float leftArc; float leftArc;
float rightArc; float rightArc;
@ -4021,8 +4018,10 @@ namespace IW5
int ammoDropStockMax; int ammoDropStockMax;
float adsDofStart; float adsDofStart;
float adsDofEnd; float adsDofEnd;
unsigned short accuracyGraphKnotCount[2]; uint16_t aiVsAiAccuracyGraphKnotCount;
vec2_t* accuracyGraphKnots[2]; uint16_t aiVsPlayerAccuracyGraphKnotCount;
vec2_t* aiVsAiAccuracyGraphKnots;
vec2_t* aiVsPlayerAccuracyGraphKnots;
bool motionTracker; bool motionTracker;
bool enhanced; bool enhanced;
bool dpadIconShowsAmmo; bool dpadIconShowsAmmo;

View File

@ -3861,20 +3861,16 @@ namespace T5
float fHipViewScatterMax; float fHipViewScatterMax;
float fightDist; float fightDist;
float maxDist; float maxDist;
// const char *accuracyGraphName[2]; // TODO: Order is accuracyGraphName[0] -> accuracyGraphKnots[0] -> originalAccuracyGraphKnots[0] -> const char* aiVsAiAccuracyGraphName;
// accuracyGraphName[1] -> ... const char* aiVsPlayerAccuracyGraphName;
// Which is currently not possible to do in code generation. Afaik this is the only place where this is the case. vec2_t* aiVsAiAccuracyGraphKnots;
// So might be something to fix but on the other hand it might be too much work for this little inconvenience. vec2_t* aiVsPlayerAccuracyGraphKnots;
const char* accuracyGraphName0; vec2_t* originalAiVsAiAccuracyGraphKnots;
const char* accuracyGraphName1; vec2_t* originalAiVsPlayerAccuracyGraphKnots;
// vec2_t *accuracyGraphKnots[2]; int aiVsAiAccuracyGraphKnotCount;
vec2_t* accuracyGraphKnots0; int aiVsPlayerAccuracyGraphKnotCount;
vec2_t* accuracyGraphKnots1; int originalAiVsAiAccuracyGraphKnotCount;
// vec2_t *originalAccuracyGraphKnots[2]; int originalAiVsPlayerAccuracyGraphKnotCount;
vec2_t* originalAccuracyGraphKnots0;
vec2_t* originalAccuracyGraphKnots1;
int accuracyGraphKnotCount[2];
int originalAccuracyGraphKnotCount[2];
int iPositionReloadTransTime; int iPositionReloadTransTime;
float leftArc; float leftArc;
float rightArc; float rightArc;

View File

@ -4860,20 +4860,16 @@ namespace T6
float fAntiQuickScopeSwayFactor; float fAntiQuickScopeSwayFactor;
float fightDist; float fightDist;
float maxDist; float maxDist;
// const char *accuracyGraphName[2]; // TODO: Order is accuracyGraphName[0] -> accuracyGraphKnots[0] -> originalAccuracyGraphKnots[0] -> const char* aiVsAiAccuracyGraphName;
// accuracyGraphName[1] -> ... const char* aiVsPlayerAccuracyGraphName;
// Which is currently not possible to do in code generation. Afaik this is the only place where this is the case. vec2_t* aiVsAiAccuracyGraphKnots;
// So might be something to fix but on the other hand it might be too much work for this little inconvenience. vec2_t* aiVsPlayerAccuracyGraphKnots;
const char* accuracyGraphName0; vec2_t* originalAiVsAiAccuracyGraphKnots;
const char* accuracyGraphName1; vec2_t* originalAiVsPlayerAccuracyGraphKnots;
// vec2_t *accuracyGraphKnots[2]; int aiVsAiAccuracyGraphKnotCount;
vec2_t* accuracyGraphKnots0; int aiVsPlayerAccuracyGraphKnotCount;
vec2_t* accuracyGraphKnots1; int originalAiVsAiAccuracyGraphKnotCount;
// vec2_t *originalAccuracyGraphKnots[2]; int originalAiVsPlayerAccuracyGraphKnotCount;
vec2_t* originalAccuracyGraphKnots0;
vec2_t* originalAccuracyGraphKnots1;
int accuracyGraphKnotCount[2];
int originalAccuracyGraphKnotCount[2];
int iPositionReloadTransTime; int iPositionReloadTransTime;
float leftArc; float leftArc;
float rightArc; float rightArc;

View File

@ -608,8 +608,8 @@ namespace IW4
{"scanPauseTime", offsetof(WeaponFullDef, weapDef.scanPauseTime), CSPFT_MILLISECONDS }, {"scanPauseTime", offsetof(WeaponFullDef, weapDef.scanPauseTime), CSPFT_MILLISECONDS },
{"fightDist", offsetof(WeaponFullDef, weapDef.fightDist), CSPFT_FLOAT }, {"fightDist", offsetof(WeaponFullDef, weapDef.fightDist), CSPFT_FLOAT },
{"maxDist", offsetof(WeaponFullDef, weapDef.maxDist), CSPFT_FLOAT }, {"maxDist", offsetof(WeaponFullDef, weapDef.maxDist), CSPFT_FLOAT },
{"aiVsAiAccuracyGraph", offsetof(WeaponFullDef, weapDef.accuracyGraphName0), CSPFT_STRING }, {"aiVsAiAccuracyGraph", offsetof(WeaponFullDef, weapDef.aiVsAiAccuracyGraphName), CSPFT_STRING },
{"aiVsPlayerAccuracyGraph", offsetof(WeaponFullDef, weapDef.accuracyGraphName1), CSPFT_STRING }, {"aiVsPlayerAccuracyGraph", offsetof(WeaponFullDef, weapDef.aiVsPlayerAccuracyGraphName), CSPFT_STRING },
{"locNone", offsetof(WeaponFullDef, locationDamageMultipliers[HITLOC_NONE]), CSPFT_FLOAT }, {"locNone", offsetof(WeaponFullDef, locationDamageMultipliers[HITLOC_NONE]), CSPFT_FLOAT },
{"locHelmet", offsetof(WeaponFullDef, locationDamageMultipliers[HITLOC_HELMET]), CSPFT_FLOAT }, {"locHelmet", offsetof(WeaponFullDef, locationDamageMultipliers[HITLOC_HELMET]), CSPFT_FLOAT },
{"locHead", offsetof(WeaponFullDef, locationDamageMultipliers[HITLOC_HEAD]), CSPFT_FLOAT }, {"locHead", offsetof(WeaponFullDef, locationDamageMultipliers[HITLOC_HEAD]), CSPFT_FLOAT },

View File

@ -697,8 +697,8 @@ namespace IW5
{"scanPauseTime", offsetof(WeaponFullDef, weapDef.scanPauseTime), CSPFT_MILLISECONDS }, {"scanPauseTime", offsetof(WeaponFullDef, weapDef.scanPauseTime), CSPFT_MILLISECONDS },
{"fightDist", offsetof(WeaponFullDef, weapDef.fightDist), CSPFT_FLOAT }, {"fightDist", offsetof(WeaponFullDef, weapDef.fightDist), CSPFT_FLOAT },
{"maxDist", offsetof(WeaponFullDef, weapDef.maxDist), CSPFT_FLOAT }, {"maxDist", offsetof(WeaponFullDef, weapDef.maxDist), CSPFT_FLOAT },
{"aiVsAiAccuracyGraph", offsetof(WeaponFullDef, weapDef.accuracyGraphName0), CSPFT_STRING }, {"aiVsAiAccuracyGraph", offsetof(WeaponFullDef, weapDef.aiVsAiAccuracyGraphName), CSPFT_STRING },
{"aiVsPlayerAccuracyGraph", offsetof(WeaponFullDef, weapDef.accuracyGraphName1), CSPFT_STRING }, {"aiVsPlayerAccuracyGraph", offsetof(WeaponFullDef, weapDef.aiVsPlayerAccuracyGraphName), CSPFT_STRING },
{"locNone", offsetof(WeaponFullDef, locationDamageMultipliers[HITLOC_NONE]), CSPFT_FLOAT }, {"locNone", offsetof(WeaponFullDef, locationDamageMultipliers[HITLOC_NONE]), CSPFT_FLOAT },
{"locHelmet", offsetof(WeaponFullDef, locationDamageMultipliers[HITLOC_HELMET]), CSPFT_FLOAT }, {"locHelmet", offsetof(WeaponFullDef, locationDamageMultipliers[HITLOC_HELMET]), CSPFT_FLOAT },
{"locHead", offsetof(WeaponFullDef, locationDamageMultipliers[HITLOC_HEAD]), CSPFT_FLOAT }, {"locHead", offsetof(WeaponFullDef, locationDamageMultipliers[HITLOC_HEAD]), CSPFT_FLOAT },

View File

@ -952,8 +952,8 @@ namespace T6
{"explosionCameraShakeRadius", offsetof(WeaponFullDef, weapDef.explosionCameraShakeRadius), CSPFT_INT }, {"explosionCameraShakeRadius", offsetof(WeaponFullDef, weapDef.explosionCameraShakeRadius), CSPFT_INT },
{"fightDist", offsetof(WeaponFullDef, weapDef.fightDist), CSPFT_FLOAT }, {"fightDist", offsetof(WeaponFullDef, weapDef.fightDist), CSPFT_FLOAT },
{"maxDist", offsetof(WeaponFullDef, weapDef.maxDist), CSPFT_FLOAT }, {"maxDist", offsetof(WeaponFullDef, weapDef.maxDist), CSPFT_FLOAT },
{"aiVsAiAccuracyGraph", offsetof(WeaponFullDef, weapDef.accuracyGraphName0), CSPFT_STRING }, {"aiVsAiAccuracyGraph", offsetof(WeaponFullDef, weapDef.aiVsAiAccuracyGraphName), CSPFT_STRING },
{"aiVsPlayerAccuracyGraph", offsetof(WeaponFullDef, weapDef.accuracyGraphName1), CSPFT_STRING }, {"aiVsPlayerAccuracyGraph", offsetof(WeaponFullDef, weapDef.aiVsPlayerAccuracyGraphName), CSPFT_STRING },
{"locNone", offsetof(WeaponFullDef, locationDamageMultipliers[HITLOC_NONE]), CSPFT_FLOAT }, {"locNone", offsetof(WeaponFullDef, locationDamageMultipliers[HITLOC_NONE]), CSPFT_FLOAT },
{"locHelmet", offsetof(WeaponFullDef, locationDamageMultipliers[HITLOC_HELMET]), CSPFT_FLOAT }, {"locHelmet", offsetof(WeaponFullDef, locationDamageMultipliers[HITLOC_HELMET]), CSPFT_FLOAT },
{"locHead", offsetof(WeaponFullDef, locationDamageMultipliers[HITLOC_HEAD]), CSPFT_FLOAT }, {"locHead", offsetof(WeaponFullDef, locationDamageMultipliers[HITLOC_HEAD]), CSPFT_FLOAT },

View File

@ -0,0 +1,25 @@
#pragma once
#include <string>
#include <vector>
class GenericGraph2DKnot
{
public:
double x;
double y;
GenericGraph2DKnot() = default;
GenericGraph2DKnot(const double x, const double y)
: x(x),
y(y)
{
}
};
class GenericGraph2D
{
public:
std::string name;
std::vector<GenericGraph2DKnot> knots;
};

View File

@ -1,214 +0,0 @@
#include "SndCurveReader.h"
#include "Parsing/Impl/AbstractParser.h"
#include "Parsing/Impl/ParserSingleInputStream.h"
#include "Parsing/Simple/Matcher/SimpleMatcherFactory.h"
#include "Parsing/Simple/SimpleLexer.h"
#include "Parsing/Simple/SimpleParserValue.h"
enum class SndCurveParserStatus
{
EXPECT_MAGIC,
EXPECT_KNOT_COUNT,
KNOTS
};
class SndCurveParserState
{
public:
SndCurveParserStatus m_status;
size_t m_knot_count;
SndCurveReader::Result m_result;
SndCurveParserState()
: m_status(SndCurveParserStatus::EXPECT_MAGIC),
m_knot_count(0u)
{
}
};
using snd_sequence_t = AbstractSequence<SimpleParserValue, SndCurveParserState>;
class SndCurveMagicSequence final : public snd_sequence_t
{
public:
SndCurveMagicSequence()
{
const SimpleMatcherFactory create(this);
AddMatchers({
create.Keyword("SNDCURVE"),
});
}
protected:
void ProcessMatch(SndCurveParserState* state, SequenceResult<SimpleParserValue>& result) const override
{
state->m_status = SndCurveParserStatus::EXPECT_KNOT_COUNT;
}
};
class SndCurveKnotCountSequence final : public snd_sequence_t
{
static constexpr auto CAPTURE_KNOT_COUNT = 1;
public:
SndCurveKnotCountSequence()
{
const SimpleMatcherFactory create(this);
AddMatchers({
create.Integer().Capture(CAPTURE_KNOT_COUNT),
});
}
protected:
void ProcessMatch(SndCurveParserState* state, SequenceResult<SimpleParserValue>& result) const override
{
state->m_status = SndCurveParserStatus::KNOTS;
const auto& knotCountToken = result.NextCapture(CAPTURE_KNOT_COUNT);
if (knotCountToken.IntegerValue() < 0)
throw ParsingException(knotCountToken.GetPos(), "Negative knot count is invalid");
state->m_knot_count = static_cast<size_t>(knotCountToken.IntegerValue());
state->m_result.m_knots.reserve(state->m_knot_count);
}
};
class SndCurveKnotSequence final : public snd_sequence_t
{
static constexpr auto CAPTURE_X = 1;
static constexpr auto CAPTURE_Y = 2;
public:
SndCurveKnotSequence()
{
const SimpleMatcherFactory create(this);
AddMatchers({
create
.Or({
create.FloatingPoint(),
create.Integer(),
})
.Capture(CAPTURE_X),
create
.Or({
create.FloatingPoint(),
create.Integer(),
})
.Capture(CAPTURE_Y),
});
}
private:
static double GetValue(const SimpleParserValue& token)
{
if (token.m_type == SimpleParserValueType::INTEGER)
return static_cast<double>(token.IntegerValue());
return token.FloatingPointValue();
}
protected:
void ProcessMatch(SndCurveParserState* state, SequenceResult<SimpleParserValue>& result) const override
{
const auto& xToken = result.NextCapture(CAPTURE_X);
const auto& yToken = result.NextCapture(CAPTURE_Y);
if (state->m_result.m_knots.size() >= state->m_knot_count)
throw ParsingException(xToken.GetPos(), "Too many knots");
const auto xValue = GetValue(xToken);
const auto yValue = GetValue(yToken);
state->m_result.m_knots.push_back(SndCurveReader::Result::Knot{xValue, yValue});
}
};
class SndCurveParser final : public AbstractParser<SimpleParserValue, SndCurveParserState>
{
public:
explicit SndCurveParser(ILexer<SimpleParserValue>* lexer)
: AbstractParser<SimpleParserValue, SndCurveParserState>(lexer, std::make_unique<SndCurveParserState>())
{
}
protected:
const std::vector<sequence_t*>& GetTestsForState() override
{
switch (m_state->m_status)
{
case SndCurveParserStatus::EXPECT_MAGIC:
{
static std::vector<sequence_t*> expectMagicSequences{
new SndCurveMagicSequence(),
};
return expectMagicSequences;
}
case SndCurveParserStatus::EXPECT_KNOT_COUNT:
{
static std::vector<sequence_t*> expectKnotCountSequences{
new SndCurveKnotCountSequence(),
};
return expectKnotCountSequences;
}
case SndCurveParserStatus::KNOTS:
{
static std::vector<sequence_t*> knotsSequences{
new SndCurveKnotSequence(),
};
return knotsSequences;
}
}
assert(false);
throw std::runtime_error("Invalid parsing status");
}
public:
_NODISCARD SndCurveReader::Result& GetResult() const
{
return m_state->m_result;
}
_NODISCARD bool HasExpectedKnotCount() const
{
return m_state->m_knot_count == m_state->m_result.m_knots.size();
}
};
SndCurveReader::SndCurveReader(std::istream& stream, const std::string& filename)
: m_stream(stream),
m_filename(filename)
{
}
std::unique_ptr<SndCurveReader::Result> SndCurveReader::Read() const
{
ParserSingleInputStream parserStream(m_stream, m_filename);
SimpleLexer::Config lexerConfig;
lexerConfig.m_emit_new_line_tokens = false;
lexerConfig.m_read_strings = false;
lexerConfig.m_read_integer_numbers = true;
lexerConfig.m_read_floating_point_numbers = true;
SimpleLexer lexer(&parserStream, std::move(lexerConfig));
SndCurveParser parser(&lexer);
if (!parser.Parse())
{
std::cerr << "Failed to parse SndCurve \"" << m_filename << "\"\n";
return nullptr;
}
if (!parser.HasExpectedKnotCount())
{
std::cerr << "Failed to load SndCurve: Actual knot count differs from expected: \"" << m_filename << "\"\n";
return nullptr;
}
return std::make_unique<Result>(std::move(parser.GetResult()));
}

View File

@ -1,32 +0,0 @@
#pragma once
#include "Utils/ClassUtils.h"
#include <istream>
#include <memory>
#include <vector>
class SndCurveReader
{
public:
class Result
{
public:
struct Knot
{
double m_x;
double m_y;
};
std::vector<Knot> m_knots;
};
private:
std::istream& m_stream;
const std::string& m_filename;
public:
SndCurveReader(std::istream& stream, const std::string& filename);
_NODISCARD std::unique_ptr<Result> Read() const;
};

View File

@ -1,9 +1,9 @@
#include "AssetLoaderSndCurve.h" #include "AssetLoaderSndCurve.h"
#include "AssetLoading/SndCurve/SndCurveReader.h"
#include "Game/IW4/IW4.h" #include "Game/IW4/IW4.h"
#include "ObjLoading.h" #include "ObjLoading.h"
#include "Pool/GlobalAssetPool.h" #include "Pool/GlobalAssetPool.h"
#include "Sound/SoundCurveLoader.h"
#include <cstring> #include <cstring>
#include <iostream> #include <iostream>
@ -11,15 +11,6 @@
using namespace IW4; using namespace IW4;
std::string AssetLoaderSndCurve::GetAssetFilename(const std::string& assetName)
{
std::ostringstream ss;
ss << "soundaliases/" << assetName << ".vfcurve";
return ss.str();
}
void* AssetLoaderSndCurve::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) void* AssetLoaderSndCurve::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
{ {
auto* sndCurve = memory->Create<SndCurve>(); auto* sndCurve = memory->Create<SndCurve>();
@ -36,33 +27,26 @@ bool AssetLoaderSndCurve::CanLoadFromRaw() const
bool AssetLoaderSndCurve::LoadFromRaw( bool AssetLoaderSndCurve::LoadFromRaw(
const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const
{ {
const auto filename = GetAssetFilename(assetName); const auto sndCurveData = sound_curve::LoadSoundCurve(manager, assetName);
const auto file = searchPath->Open(filename);
if (!file.IsOpen())
return false;
const SndCurveReader reader(*file.m_stream, filename);
const auto sndCurveData = reader.Read();
if (!sndCurveData) if (!sndCurveData)
return false; return false;
if (sndCurveData->m_knots.size() > std::extent_v<decltype(SndCurve::knots)>) if (sndCurveData->knots.size() > std::extent_v<decltype(SndCurve::knots)>)
{ {
std::cerr << "Failed to load SndCurve \"" << assetName << "\": Too many knots (" << sndCurveData->m_knots.size() << ")\n"; std::cerr << "Failed to load SndCurve \"" << assetName << "\": Too many knots (" << sndCurveData->knots.size() << ")\n";
return false; return false;
} }
auto* sndCurve = memory->Create<SndCurve>(); auto* sndCurve = memory->Create<SndCurve>();
sndCurve->filename = memory->Dup(assetName.c_str()); sndCurve->filename = memory->Dup(assetName.c_str());
sndCurve->knotCount = static_cast<uint16_t>(sndCurveData->m_knots.size()); sndCurve->knotCount = static_cast<uint16_t>(sndCurveData->knots.size());
for (auto i = 0u; i < std::extent_v<decltype(SndCurve::knots)>; i++) for (auto i = 0u; i < std::extent_v<decltype(SndCurve::knots)>; i++)
{ {
if (i < sndCurveData->m_knots.size()) if (i < sndCurveData->knots.size())
{ {
const auto& [x, y] = sndCurveData->m_knots[i]; const auto& [x, y] = sndCurveData->knots[i];
sndCurve->knots[i][0] = static_cast<float>(x); sndCurve->knots[i][0] = static_cast<float>(x);
sndCurve->knots[i][1] = static_cast<float>(y); sndCurve->knots[i][1] = static_cast<float>(y);
} }

View File

@ -8,8 +8,6 @@ namespace IW4
{ {
class AssetLoaderSndCurve final : public BasicAssetLoader<ASSET_TYPE_SOUND_CURVE, SndCurve> class AssetLoaderSndCurve final : public BasicAssetLoader<ASSET_TYPE_SOUND_CURVE, SndCurve>
{ {
static std::string GetAssetFilename(const std::string& assetName);
public: public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
_NODISCARD bool CanLoadFromRaw() const override; _NODISCARD bool CanLoadFromRaw() const override;

View File

@ -9,6 +9,7 @@
#include "ObjLoading.h" #include "ObjLoading.h"
#include "Pool/GlobalAssetPool.h" #include "Pool/GlobalAssetPool.h"
#include "Utils/StringUtils.h" #include "Utils/StringUtils.h"
#include "Weapon/AccuracyGraphLoader.h"
#include <cstring> #include <cstring>
#include <format> #include <format>
@ -370,6 +371,62 @@ namespace
} }
} }
void ConvertAccuracyGraph(const GenericGraph2D& graph,
vec2_t*& originalGraphKnots,
uint16_t& originalGraphKnotCount,
vec2_t*& graphKnots,
uint16_t& graphKnotCount,
MemoryManager* memory)
{
originalGraphKnotCount = static_cast<uint16_t>(graph.knots.size());
originalGraphKnots = memory->Alloc<vec2_t>(originalGraphKnotCount);
for (auto i = 0u; i < originalGraphKnotCount; i++)
{
const auto& commonKnot = graph.knots[i];
originalGraphKnots[i][0] = static_cast<float>(commonKnot.x);
originalGraphKnots[i][1] = static_cast<float>(commonKnot.y);
}
graphKnots = originalGraphKnots;
graphKnotCount = originalGraphKnotCount;
}
bool LoadAccuracyGraphs(WeaponFullDef* weaponFullDef, MemoryManager* memory, const IAssetLoadingManager* manager)
{
auto* accuracyGraphLoader = manager->GetAssetLoadingContext()->GetZoneAssetLoaderState<AccuracyGraphLoader>();
if (weaponFullDef->weapDef.aiVsAiAccuracyGraphName && weaponFullDef->weapDef.aiVsAiAccuracyGraphName[0])
{
const auto* graph = accuracyGraphLoader->LoadAiVsAiGraph(manager, weaponFullDef->weapDef.aiVsAiAccuracyGraphName);
if (!graph)
return false;
ConvertAccuracyGraph(*graph,
weaponFullDef->weapDef.originalAiVsAiAccuracyGraphKnots,
weaponFullDef->weapDef.originalAiVsAiAccuracyGraphKnotCount,
weaponFullDef->weapCompleteDef.aiVsAiAccuracyGraphKnots,
weaponFullDef->weapCompleteDef.aiVsAiAccuracyGraphKnotCount,
memory);
}
if (weaponFullDef->weapDef.aiVsPlayerAccuracyGraphName && weaponFullDef->weapDef.aiVsPlayerAccuracyGraphName[0])
{
const auto* graph = accuracyGraphLoader->LoadAiVsPlayerGraph(manager, weaponFullDef->weapDef.aiVsPlayerAccuracyGraphName);
if (!graph)
return false;
ConvertAccuracyGraph(*graph,
weaponFullDef->weapDef.originalAiVsPlayerAccuracyGraphKnots,
weaponFullDef->weapDef.originalAiVsPlayerAccuracyGraphKnotCount,
weaponFullDef->weapCompleteDef.aiVsPlayerAccuracyGraphKnots,
weaponFullDef->weapCompleteDef.aiVsPlayerAccuracyGraphKnotCount,
memory);
}
return true;
}
bool LoadFromInfoString(const InfoString& infoString, const std::string& assetName, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) bool LoadFromInfoString(const InfoString& infoString, const std::string& assetName, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone)
{ {
auto* weaponFullDef = memory->Create<WeaponFullDef>(); auto* weaponFullDef = memory->Create<WeaponFullDef>();
@ -387,6 +444,8 @@ namespace
CalculateWeaponFields(weaponFullDef, memory); CalculateWeaponFields(weaponFullDef, memory);
LoadAccuracyGraphs(weaponFullDef, memory, manager);
manager->AddAsset<AssetWeapon>( manager->AddAsset<AssetWeapon>(
assetName, &weaponFullDef->weapCompleteDef, converter.GetDependencies(), converter.GetUsedScriptStrings(), converter.GetIndirectAssetReferences()); assetName, &weaponFullDef->weapCompleteDef, converter.GetDependencies(), converter.GetUsedScriptStrings(), converter.GetIndirectAssetReferences());

View File

@ -8,6 +8,7 @@
#include "ObjLoading.h" #include "ObjLoading.h"
#include "Pool/GlobalAssetPool.h" #include "Pool/GlobalAssetPool.h"
#include "Utils/StringUtils.h" #include "Utils/StringUtils.h"
#include "Weapon/AccuracyGraphLoader.h"
#include <cstring> #include <cstring>
#include <format> #include <format>
@ -800,6 +801,62 @@ namespace
} }
} }
void ConvertAccuracyGraph(const GenericGraph2D& graph,
vec2_t*& originalGraphKnots,
uint16_t& originalGraphKnotCount,
vec2_t*& graphKnots,
uint16_t& graphKnotCount,
MemoryManager* memory)
{
originalGraphKnotCount = static_cast<uint16_t>(graph.knots.size());
originalGraphKnots = memory->Alloc<vec2_t>(originalGraphKnotCount);
for (auto i = 0u; i < originalGraphKnotCount; i++)
{
const auto& commonKnot = graph.knots[i];
originalGraphKnots[i][0] = static_cast<float>(commonKnot.x);
originalGraphKnots[i][1] = static_cast<float>(commonKnot.y);
}
graphKnots = originalGraphKnots;
graphKnotCount = originalGraphKnotCount;
}
bool LoadAccuracyGraphs(WeaponFullDef* weaponFullDef, MemoryManager* memory, const IAssetLoadingManager* manager)
{
auto* accuracyGraphLoader = manager->GetAssetLoadingContext()->GetZoneAssetLoaderState<AccuracyGraphLoader>();
if (weaponFullDef->weapDef.aiVsAiAccuracyGraphName && weaponFullDef->weapDef.aiVsAiAccuracyGraphName[0])
{
const auto* graph = accuracyGraphLoader->LoadAiVsAiGraph(manager, weaponFullDef->weapDef.aiVsAiAccuracyGraphName);
if (!graph)
return false;
ConvertAccuracyGraph(*graph,
weaponFullDef->weapDef.originalAiVsAiAccuracyGraphKnots,
weaponFullDef->weapDef.originalAiVsAiAccuracyGraphKnotCount,
weaponFullDef->weapCompleteDef.aiVsAiAccuracyGraphKnots,
weaponFullDef->weapCompleteDef.aiVsAiAccuracyGraphKnotCount,
memory);
}
if (weaponFullDef->weapDef.aiVsPlayerAccuracyGraphName && weaponFullDef->weapDef.aiVsPlayerAccuracyGraphName[0])
{
const auto* graph = accuracyGraphLoader->LoadAiVsPlayerGraph(manager, weaponFullDef->weapDef.aiVsPlayerAccuracyGraphName);
if (!graph)
return false;
ConvertAccuracyGraph(*graph,
weaponFullDef->weapDef.originalAiVsPlayerAccuracyGraphKnots,
weaponFullDef->weapDef.originalAiVsPlayerAccuracyGraphKnotCount,
weaponFullDef->weapCompleteDef.aiVsPlayerAccuracyGraphKnots,
weaponFullDef->weapCompleteDef.aiVsPlayerAccuracyGraphKnotCount,
memory);
}
return true;
}
bool LoadFromInfoString(const InfoString& infoString, const std::string& assetName, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) bool LoadFromInfoString(const InfoString& infoString, const std::string& assetName, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone)
{ {
auto* weaponFullDef = memory->Create<WeaponFullDef>(); auto* weaponFullDef = memory->Create<WeaponFullDef>();
@ -817,6 +874,8 @@ namespace
CalculateWeaponFields(weaponFullDef, memory); CalculateWeaponFields(weaponFullDef, memory);
LoadAccuracyGraphs(weaponFullDef, memory, manager);
manager->AddAsset<AssetWeapon>( manager->AddAsset<AssetWeapon>(
assetName, &weaponFullDef->weapCompleteDef, converter.GetDependencies(), converter.GetUsedScriptStrings(), converter.GetIndirectAssetReferences()); assetName, &weaponFullDef->weapCompleteDef, converter.GetDependencies(), converter.GetUsedScriptStrings(), converter.GetIndirectAssetReferences());

View File

@ -9,6 +9,7 @@
#include "InfoString/InfoString.h" #include "InfoString/InfoString.h"
#include "Utils/ClassUtils.h" #include "Utils/ClassUtils.h"
#include "Utils/StringUtils.h" #include "Utils/StringUtils.h"
#include "Weapon/AccuracyGraphLoader.h"
#include <cassert> #include <cassert>
#include <cstring> #include <cstring>
@ -385,6 +386,58 @@ namespace T6
{ {
} }
}; };
void ConvertAccuracyGraph(
const GenericGraph2D& graph, vec2_t*& originalGraphKnots, int& originalGraphKnotCount, vec2_t*& graphKnots, int& graphKnotCount, MemoryManager* memory)
{
originalGraphKnotCount = static_cast<int>(graph.knots.size());
originalGraphKnots = memory->Alloc<vec2_t>(originalGraphKnotCount);
for (auto i = 0; i < originalGraphKnotCount; i++)
{
const auto& commonKnot = graph.knots[i];
originalGraphKnots[i].x = static_cast<float>(commonKnot.x);
originalGraphKnots[i].y = static_cast<float>(commonKnot.y);
}
graphKnots = originalGraphKnots;
graphKnotCount = originalGraphKnotCount;
}
bool LoadAccuracyGraphs(WeaponFullDef* weaponFullDef, MemoryManager* memory, const IAssetLoadingManager* manager)
{
auto* accuracyGraphLoader = manager->GetAssetLoadingContext()->GetZoneAssetLoaderState<AccuracyGraphLoader>();
if (weaponFullDef->weapDef.aiVsAiAccuracyGraphName && weaponFullDef->weapDef.aiVsAiAccuracyGraphName[0])
{
const auto* graph = accuracyGraphLoader->LoadAiVsAiGraph(manager, weaponFullDef->weapDef.aiVsAiAccuracyGraphName);
if (!graph)
return false;
ConvertAccuracyGraph(*graph,
weaponFullDef->weapDef.originalAiVsAiAccuracyGraphKnots,
weaponFullDef->weapDef.originalAiVsAiAccuracyGraphKnotCount,
weaponFullDef->weapDef.aiVsAiAccuracyGraphKnots,
weaponFullDef->weapDef.aiVsAiAccuracyGraphKnotCount,
memory);
}
if (weaponFullDef->weapDef.aiVsPlayerAccuracyGraphName && weaponFullDef->weapDef.aiVsPlayerAccuracyGraphName[0])
{
const auto* graph = accuracyGraphLoader->LoadAiVsPlayerGraph(manager, weaponFullDef->weapDef.aiVsPlayerAccuracyGraphName);
if (!graph)
return false;
ConvertAccuracyGraph(*graph,
weaponFullDef->weapDef.originalAiVsPlayerAccuracyGraphKnots,
weaponFullDef->weapDef.originalAiVsPlayerAccuracyGraphKnotCount,
weaponFullDef->weapDef.aiVsPlayerAccuracyGraphKnots,
weaponFullDef->weapDef.aiVsPlayerAccuracyGraphKnotCount,
memory);
}
return true;
}
} // namespace T6 } // namespace T6
void AssetLoaderWeapon::LinkWeaponFullDefSubStructs(WeaponFullDef* weapon) void AssetLoaderWeapon::LinkWeaponFullDefSubStructs(WeaponFullDef* weapon)
@ -563,10 +616,12 @@ bool AssetLoaderWeapon::LoadFromInfoString(
weaponFullDef->weapVariantDef.szInternalName = memory->Dup(assetName.c_str()); weaponFullDef->weapVariantDef.szInternalName = memory->Dup(assetName.c_str());
// TODO: Load accuracy graph and flametable // TODO: Load flametable
CalculateWeaponFields(weaponFullDef); CalculateWeaponFields(weaponFullDef);
CalculateAttachmentFields(weaponFullDef); CalculateAttachmentFields(weaponFullDef);
LoadAccuracyGraphs(weaponFullDef, memory, manager);
manager->AddAsset<AssetWeapon>( manager->AddAsset<AssetWeapon>(
assetName, &weaponFullDef->weapVariantDef, converter.GetDependencies(), converter.GetUsedScriptStrings(), converter.GetIndirectAssetReferences()); assetName, &weaponFullDef->weapVariantDef, converter.GetDependencies(), converter.GetUsedScriptStrings(), converter.GetIndirectAssetReferences());

View File

@ -0,0 +1,229 @@
#include "Graph2DReader.h"
#include "Parsing/Impl/AbstractParser.h"
#include "Parsing/Impl/ParserSingleInputStream.h"
#include "Parsing/Simple/Matcher/SimpleMatcherFactory.h"
#include "Parsing/Simple/SimpleLexer.h"
#include "Parsing/Simple/SimpleParserValue.h"
#include <format>
namespace graph2d
{
enum class SndCurveParserStatus
{
EXPECT_MAGIC,
EXPECT_KNOT_COUNT,
KNOTS
};
class SndCurveParserState
{
public:
SndCurveParserStatus m_status;
size_t m_expected_knot_count;
GenericGraph2D m_result;
SndCurveParserState()
: m_status(SndCurveParserStatus::EXPECT_MAGIC),
m_expected_knot_count(0u)
{
}
};
using snd_sequence_t = AbstractSequence<SimpleParserValue, SndCurveParserState>;
class SndCurveMagicSequence final : public snd_sequence_t
{
public:
explicit SndCurveMagicSequence(std::string magicWord)
{
const SimpleMatcherFactory create(this);
AddMatchers({
create.Keyword(std::move(magicWord)),
});
}
protected:
void ProcessMatch(SndCurveParserState* state, SequenceResult<SimpleParserValue>& result) const override
{
state->m_status = SndCurveParserStatus::EXPECT_KNOT_COUNT;
}
};
class SndCurveKnotCountSequence final : public snd_sequence_t
{
static constexpr auto CAPTURE_KNOT_COUNT = 1;
public:
SndCurveKnotCountSequence()
{
const SimpleMatcherFactory create(this);
AddMatchers({
create.Integer().Capture(CAPTURE_KNOT_COUNT),
});
}
protected:
void ProcessMatch(SndCurveParserState* state, SequenceResult<SimpleParserValue>& result) const override
{
state->m_status = SndCurveParserStatus::KNOTS;
const auto& knotCountToken = result.NextCapture(CAPTURE_KNOT_COUNT);
if (knotCountToken.IntegerValue() < 0)
throw ParsingException(knotCountToken.GetPos(), "Negative knot count is invalid");
state->m_expected_knot_count = static_cast<size_t>(knotCountToken.IntegerValue());
state->m_result.knots.reserve(state->m_expected_knot_count);
}
};
class SndCurveKnotSequence final : public snd_sequence_t
{
static constexpr auto CAPTURE_X = 1;
static constexpr auto CAPTURE_Y = 2;
public:
SndCurveKnotSequence()
{
const SimpleMatcherFactory create(this);
AddMatchers({
create
.Or({
create.FloatingPoint(),
create.Integer(),
})
.Capture(CAPTURE_X),
create
.Or({
create.FloatingPoint(),
create.Integer(),
})
.Capture(CAPTURE_Y),
});
}
private:
static double GetValue(const SimpleParserValue& token)
{
if (token.m_type == SimpleParserValueType::INTEGER)
return token.IntegerValue();
return token.FloatingPointValue();
}
protected:
void ProcessMatch(SndCurveParserState* state, SequenceResult<SimpleParserValue>& result) const override
{
const auto& xToken = result.NextCapture(CAPTURE_X);
const auto& yToken = result.NextCapture(CAPTURE_Y);
if (state->m_result.knots.size() >= state->m_expected_knot_count)
throw ParsingException(xToken.GetPos(), std::format("More knots than expected ({})", state->m_expected_knot_count));
const auto xValue = GetValue(xToken);
const auto yValue = GetValue(yToken);
state->m_result.knots.emplace_back(xValue, yValue);
}
};
class SndCurveParser final : public AbstractParser<SimpleParserValue, SndCurveParserState>
{
public:
explicit SndCurveParser(ILexer<SimpleParserValue>* lexer, std::string magicWord)
: AbstractParser(lexer, std::make_unique<SndCurveParserState>()),
m_magic_sequence(std::move(magicWord)),
m_magic_sequences({&m_magic_sequence})
{
}
protected:
const std::vector<sequence_t*>& GetTestsForState() override
{
switch (m_state->m_status)
{
case SndCurveParserStatus::EXPECT_MAGIC:
return m_magic_sequences;
case SndCurveParserStatus::EXPECT_KNOT_COUNT:
{
static std::vector<sequence_t*> expectKnotCountSequences{
new SndCurveKnotCountSequence(),
};
return expectKnotCountSequences;
}
case SndCurveParserStatus::KNOTS:
{
static std::vector<sequence_t*> knotsSequences{
new SndCurveKnotSequence(),
};
return knotsSequences;
}
}
assert(false);
throw std::runtime_error("Invalid parsing status");
}
public:
_NODISCARD GenericGraph2D& GetResult() const
{
return m_state->m_result;
}
_NODISCARD bool HasExpectedKnotCount() const
{
return GetExpectedKnotCount() == GetActualKnotCount();
}
[[nodiscard]] size_t GetExpectedKnotCount() const
{
return m_state->m_expected_knot_count;
}
[[nodiscard]] size_t GetActualKnotCount() const
{
return m_state->m_result.knots.size();
}
private:
SndCurveMagicSequence m_magic_sequence;
std::vector<sequence_t*> m_magic_sequences;
};
std::unique_ptr<GenericGraph2D>
Read(const std::string& graphTypeName, std::string graphMagicWord, std::istream& stream, const std::string& fileName, std::string graphName)
{
ParserSingleInputStream parserStream(stream, fileName);
SimpleLexer::Config lexerConfig;
lexerConfig.m_emit_new_line_tokens = false;
lexerConfig.m_read_strings = false;
lexerConfig.m_read_integer_numbers = true;
lexerConfig.m_read_floating_point_numbers = true;
SimpleLexer lexer(&parserStream, std::move(lexerConfig));
SndCurveParser parser(&lexer, std::move(graphMagicWord));
if (!parser.Parse())
{
std::cerr << std::format("Failed to parse {} \"{}\"\n", graphTypeName, graphName);
return nullptr;
}
if (!parser.HasExpectedKnotCount())
{
std::cerr << std::format("Failed to load {} \"{}\": Actual knot count ({}) differs from expected ({})\n",
graphTypeName,
graphName,
parser.GetActualKnotCount(),
parser.GetExpectedKnotCount());
return nullptr;
}
return std::make_unique<GenericGraph2D>(std::move(parser.GetResult()));
}
} // namespace graph2d

View File

@ -0,0 +1,12 @@
#pragma once
#include "Parsing/GenericGraph2D.h"
#include <istream>
#include <memory>
namespace graph2d
{
[[nodiscard]] std::unique_ptr<GenericGraph2D>
Read(const std::string& graphTypeName, std::string graphMagicWord, std::istream& stream, const std::string& fileName, std::string graphName);
}

View File

@ -0,0 +1,23 @@
#include "SoundCurveLoader.h"
#include "Parsing/Graph2D/Graph2DReader.h"
#include <format>
#include <iostream>
namespace sound_curve
{
std::unique_ptr<GenericGraph2D> LoadSoundCurve(const IAssetLoadingManager* manager, const std::string& soundCurveName)
{
auto* searchPath = manager->GetAssetLoadingContext()->m_raw_search_path;
const auto fileName = std::format("soundaliases/{}.vfcurve", soundCurveName);
const auto file = searchPath->Open(fileName);
if (!file.IsOpen())
{
std::cerr << std::format("Failed to open file for sound curve \"{}\"\n", soundCurveName);
return nullptr;
}
return graph2d::Read("sound curve", "SNDCURVE", *file.m_stream, fileName, soundCurveName);
}
} // namespace sound_curve

View File

@ -0,0 +1,11 @@
#pragma once
#include "AssetLoading/IAssetLoadingManager.h"
#include "Parsing/GenericGraph2D.h"
#include <memory>
namespace sound_curve
{
std::unique_ptr<GenericGraph2D> LoadSoundCurve(const IAssetLoadingManager* manager, const std::string& soundCurveName);
}

View File

@ -0,0 +1,55 @@
#include "AccuracyGraphLoader.h"
#include "Parsing/Graph2D/Graph2DReader.h"
#include <format>
#include <iostream>
namespace
{
std::unique_ptr<GenericGraph2D> LoadAccuracyGraph(const IAssetLoadingManager* manager, const std::string& graphName, const std::string& subFolder)
{
auto* searchPath = manager->GetAssetLoadingContext()->m_raw_search_path;
const auto fileName = std::format("accuracy/{}/{}", subFolder, graphName);
const auto file = searchPath->Open(fileName);
if (!file.IsOpen())
{
std::cerr << std::format("Failed to open file for accuracy graph: {}/{}\n", subFolder, graphName);
return nullptr;
}
return graph2d::Read("accuracy graph", "WEAPONACCUFILE", *file.m_stream, fileName, graphName);
}
} // namespace
const GenericGraph2D* AccuracyGraphLoader::LoadAiVsAiGraph(const IAssetLoadingManager* manager, const std::string& graphName)
{
const auto alreadyLoadedGraph = m_loaded_ai_vs_ai_graphs.find(graphName);
if (alreadyLoadedGraph != m_loaded_ai_vs_ai_graphs.end())
return alreadyLoadedGraph->second.get();
auto graph = LoadAccuracyGraph(manager, graphName, "aivsai");
if (!graph)
return nullptr;
const auto* graphPtr = graph.get();
m_loaded_ai_vs_ai_graphs.emplace(graphName, std::move(graph));
return graphPtr;
}
const GenericGraph2D* AccuracyGraphLoader::LoadAiVsPlayerGraph(const IAssetLoadingManager* manager, const std::string& graphName)
{
const auto alreadyLoadedGraph = m_loaded_ai_vs_player_graphs.find(graphName);
if (alreadyLoadedGraph != m_loaded_ai_vs_player_graphs.end())
return alreadyLoadedGraph->second.get();
auto graph = LoadAccuracyGraph(manager, graphName, "aivsplayer");
if (!graph)
return nullptr;
const auto* graphPtr = graph.get();
m_loaded_ai_vs_player_graphs.emplace(graphName, std::move(graph));
return graphPtr;
}

View File

@ -0,0 +1,17 @@
#pragma once
#include "AssetLoading/IAssetLoadingManager.h"
#include "AssetLoading/IZoneAssetLoaderState.h"
#include "Parsing/GenericGraph2D.h"
#include <memory>
class AccuracyGraphLoader final : public IZoneAssetLoaderState
{
public:
const GenericGraph2D* LoadAiVsAiGraph(const IAssetLoadingManager* manager, const std::string& graphName);
const GenericGraph2D* LoadAiVsPlayerGraph(const IAssetLoadingManager* manager, const std::string& graphName);
private:
std::unordered_map<std::string, std::unique_ptr<GenericGraph2D>> m_loaded_ai_vs_ai_graphs;
std::unordered_map<std::string, std::unique_ptr<GenericGraph2D>> m_loaded_ai_vs_player_graphs;
};

View File

@ -5,6 +5,7 @@
#include "Game/IW4/InfoString/InfoStringFromStructConverter.h" #include "Game/IW4/InfoString/InfoStringFromStructConverter.h"
#include "Game/IW4/InfoString/WeaponFields.h" #include "Game/IW4/InfoString/WeaponFields.h"
#include "Game/IW4/ObjConstantsIW4.h" #include "Game/IW4/ObjConstantsIW4.h"
#include "Weapon/AccuracyGraphWriter.h"
#include <cassert> #include <cassert>
#include <cstring> #include <cstring>
@ -219,6 +220,23 @@ namespace IW4
{ {
} }
}; };
GenericGraph2D ConvertAccuracyGraph(const char* graphName, const vec2_t* originalKnots, const unsigned originalKnotCount)
{
GenericGraph2D graph;
graph.name = graphName;
graph.knots.resize(originalKnotCount);
for (auto i = 0u; i < originalKnotCount; i++)
{
auto& knot = graph.knots[i];
knot.x = originalKnots[i][0];
knot.y = originalKnots[i][1];
}
return graph;
}
} // namespace IW4 } // namespace IW4
void AssetDumperWeapon::CopyToFullDef(const WeaponCompleteDef* weapon, WeaponFullDef* fullDef) void AssetDumperWeapon::CopyToFullDef(const WeaponCompleteDef* weapon, WeaponFullDef* fullDef)
@ -354,6 +372,33 @@ InfoString AssetDumperWeapon::CreateInfoString(XAssetInfo<WeaponCompleteDef>* as
return converter.Convert(); 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) bool AssetDumperWeapon::ShouldDump(XAssetInfo<WeaponCompleteDef>* asset)
{ {
return true; return true;
@ -381,4 +426,6 @@ void AssetDumperWeapon::DumpAsset(AssetDumpingContext& context, XAssetInfo<Weapo
const auto stringValue = infoString.ToString(ObjConstants::INFO_STRING_PREFIX_WEAPON); const auto stringValue = infoString.ToString(ObjConstants::INFO_STRING_PREFIX_WEAPON);
stream.write(stringValue.c_str(), stringValue.size()); stream.write(stringValue.c_str(), stringValue.size());
} }
DumpAccuracyGraphs(context, asset);
} }

View File

@ -10,6 +10,7 @@ namespace IW4
{ {
static void CopyToFullDef(const WeaponCompleteDef* weapon, WeaponFullDef* fullDef); static void CopyToFullDef(const WeaponCompleteDef* weapon, WeaponFullDef* fullDef);
static InfoString CreateInfoString(XAssetInfo<WeaponCompleteDef>* asset); static InfoString CreateInfoString(XAssetInfo<WeaponCompleteDef>* asset);
static void DumpAccuracyGraphs(AssetDumpingContext& context, XAssetInfo<WeaponCompleteDef>* asset);
protected: protected:
bool ShouldDump(XAssetInfo<WeaponCompleteDef>* asset) override; bool ShouldDump(XAssetInfo<WeaponCompleteDef>* asset) override;

View File

@ -4,12 +4,14 @@
#include "Game/IW5/InfoString/InfoStringFromStructConverter.h" #include "Game/IW5/InfoString/InfoStringFromStructConverter.h"
#include "Game/IW5/InfoString/WeaponFields.h" #include "Game/IW5/InfoString/WeaponFields.h"
#include "Game/IW5/ObjConstantsIW5.h" #include "Game/IW5/ObjConstantsIW5.h"
#include "Weapon/AccuracyGraphWriter.h"
#include <bit> #include <bit>
#include <cassert> #include <cassert>
#include <cstring> #include <cstring>
#include <sstream> #include <sstream>
#include <type_traits> #include <type_traits>
#include <unordered_set>
using namespace IW5; using namespace IW5;
@ -532,6 +534,23 @@ namespace IW5
const WeaponFullDef* m_weapon; const WeaponFullDef* m_weapon;
}; };
GenericGraph2D ConvertAccuracyGraph(const char* graphName, const vec2_t* originalKnots, const unsigned originalKnotCount)
{
GenericGraph2D graph;
graph.name = graphName;
graph.knots.resize(originalKnotCount);
for (auto i = 0u; i < originalKnotCount; i++)
{
auto& knot = graph.knots[i];
knot.x = originalKnots[i][0];
knot.y = originalKnots[i][1];
}
return graph;
}
} // namespace IW5 } // namespace IW5
void AssetDumperWeapon::CopyToFullDef(const WeaponCompleteDef* weapon, WeaponFullDef* fullDef) void AssetDumperWeapon::CopyToFullDef(const WeaponCompleteDef* weapon, WeaponFullDef* fullDef)
@ -681,6 +700,33 @@ InfoString AssetDumperWeapon::CreateInfoString(XAssetInfo<WeaponCompleteDef>* as
return converter.Convert(); 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) bool AssetDumperWeapon::ShouldDump(XAssetInfo<WeaponCompleteDef>* asset)
{ {
return true; return true;
@ -710,4 +756,6 @@ void AssetDumperWeapon::DumpAsset(AssetDumpingContext& context, XAssetInfo<Weapo
const auto stringValue = infoString.ToString(ObjConstants::INFO_STRING_PREFIX_WEAPON); const auto stringValue = infoString.ToString(ObjConstants::INFO_STRING_PREFIX_WEAPON);
stream.write(stringValue.c_str(), stringValue.size()); stream.write(stringValue.c_str(), stringValue.size());
} }
DumpAccuracyGraphs(context, asset);
} }

View File

@ -10,6 +10,7 @@ namespace IW5
{ {
static void CopyToFullDef(const WeaponCompleteDef* weapon, WeaponFullDef* fullDef); static void CopyToFullDef(const WeaponCompleteDef* weapon, WeaponFullDef* fullDef);
static InfoString CreateInfoString(XAssetInfo<WeaponCompleteDef>* asset); static InfoString CreateInfoString(XAssetInfo<WeaponCompleteDef>* asset);
static void DumpAccuracyGraphs(AssetDumpingContext& context, XAssetInfo<WeaponCompleteDef>* asset);
protected: protected:
bool ShouldDump(XAssetInfo<WeaponCompleteDef>* asset) override; bool ShouldDump(XAssetInfo<WeaponCompleteDef>* asset) override;

View File

@ -4,6 +4,7 @@
#include "Game/T6/InfoString/InfoStringFromStructConverter.h" #include "Game/T6/InfoString/InfoStringFromStructConverter.h"
#include "Game/T6/InfoString/WeaponFields.h" #include "Game/T6/InfoString/WeaponFields.h"
#include "Game/T6/ObjConstantsT6.h" #include "Game/T6/ObjConstantsT6.h"
#include "Weapon/AccuracyGraphWriter.h"
#include <cassert> #include <cassert>
#include <cstring> #include <cstring>
@ -263,6 +264,23 @@ namespace T6
{ {
} }
}; };
GenericGraph2D ConvertAccuracyGraph(const char* graphName, const vec2_t* originalKnots, const unsigned originalKnotCount)
{
GenericGraph2D graph;
graph.name = graphName;
graph.knots.resize(originalKnotCount);
for (auto i = 0u; i < originalKnotCount; i++)
{
auto& knot = graph.knots[i];
knot.x = originalKnots[i].x;
knot.y = originalKnots[i].y;
}
return graph;
}
} // namespace T6 } // namespace T6
void AssetDumperWeapon::CopyToFullDef(const WeaponVariantDef* weapon, WeaponFullDef* fullDef) void AssetDumperWeapon::CopyToFullDef(const WeaponVariantDef* weapon, WeaponFullDef* fullDef)
@ -411,6 +429,33 @@ InfoString AssetDumperWeapon::CreateInfoString(XAssetInfo<WeaponVariantDef>* ass
return converter.Convert(); return converter.Convert();
} }
void AssetDumperWeapon::DumpAccuracyGraphs(AssetDumpingContext& context, XAssetInfo<WeaponVariantDef>* 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<WeaponVariantDef>* asset) bool AssetDumperWeapon::ShouldDump(XAssetInfo<WeaponVariantDef>* asset)
{ {
return true; return true;
@ -438,4 +483,6 @@ void AssetDumperWeapon::DumpAsset(AssetDumpingContext& context, XAssetInfo<Weapo
const auto stringValue = infoString.ToString(ObjConstants::INFO_STRING_PREFIX_WEAPON); const auto stringValue = infoString.ToString(ObjConstants::INFO_STRING_PREFIX_WEAPON);
stream.write(stringValue.c_str(), stringValue.size()); stream.write(stringValue.c_str(), stringValue.size());
} }
DumpAccuracyGraphs(context, asset);
} }

View File

@ -10,6 +10,7 @@ namespace T6
{ {
static void CopyToFullDef(const WeaponVariantDef* weapon, WeaponFullDef* fullDef); static void CopyToFullDef(const WeaponVariantDef* weapon, WeaponFullDef* fullDef);
static InfoString CreateInfoString(XAssetInfo<WeaponVariantDef>* asset); static InfoString CreateInfoString(XAssetInfo<WeaponVariantDef>* asset);
static void DumpAccuracyGraphs(AssetDumpingContext& context, XAssetInfo<WeaponVariantDef>* asset);
protected: protected:
bool ShouldDump(XAssetInfo<WeaponVariantDef>* asset) override; bool ShouldDump(XAssetInfo<WeaponVariantDef>* asset) override;

View File

@ -0,0 +1,57 @@
#include "AccuracyGraphWriter.h"
#include <format>
namespace
{
bool ShouldDumpAccuracyGraph(std::unordered_set<std::string>& 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 GenericGraph2D& 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 GenericGraph2D& aiVsAiGraph)
{
DumpAccuracyGraph(context, aiVsAiGraph, "aivsai");
}
void AccuracyGraphWriter::DumpAiVsPlayerGraph(const AssetDumpingContext& context, const GenericGraph2D& aiVsPlayerGraph)
{
DumpAccuracyGraph(context, aiVsPlayerGraph, "aivsplayer");
}

View File

@ -0,0 +1,21 @@
#pragma once
#include "Dumping/AssetDumpingContext.h"
#include "Dumping/IZoneAssetDumperState.h"
#include "Parsing/GenericGraph2D.h"
#include <string>
#include <unordered_set>
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 GenericGraph2D& aiVsAiGraph);
static void DumpAiVsPlayerGraph(const AssetDumpingContext& context, const GenericGraph2D& aiVsPlayerGraph);
private:
std::unordered_set<std::string> m_dumped_ai_vs_ai_graphs;
std::unordered_set<std::string> m_dumped_ai_vs_player_graphs;
};

View File

@ -19,16 +19,16 @@ set string szAmmoName;
set string szClipName; set string szClipName;
set string szSharedAmmoCapName; set string szSharedAmmoCapName;
set string szAltWeaponName; set string szAltWeaponName;
set string accuracyGraphName0; set string aiVsAiAccuracyGraphName;
set string accuracyGraphName1; set string aiVsPlayerAccuracyGraphName;
set reusable accuracyGraphKnots0; set reusable aiVsAiAccuracyGraphKnots;
set reusable accuracyGraphKnots1; set count aiVsAiAccuracyGraphKnots aiVsAiAccuracyGraphKnotCount;
set reusable originalAccuracyGraphKnots0; set reusable aiVsPlayerAccuracyGraphKnots;
set reusable originalAccuracyGraphKnots1; set count aiVsPlayerAccuracyGraphKnots aiVsPlayerAccuracyGraphKnotCount;
set count accuracyGraphKnots0 accuracyGraphKnotCount[0]; set reusable originalAiVsAiAccuracyGraphKnots;
set count accuracyGraphKnots1 accuracyGraphKnotCount[1]; set count originalAiVsAiAccuracyGraphKnots aiVsAiAccuracyGraphKnotCount; // yeah it does not use original count
set count originalAccuracyGraphKnots0 accuracyGraphKnotCount[0]; // yeah it uses accuracyGraphKnotCount set reusable originalAiVsPlayerAccuracyGraphKnots;
set count originalAccuracyGraphKnots1 accuracyGraphKnotCount[1]; set count originalAiVsPlayerAccuracyGraphKnots aiVsPlayerAccuracyGraphKnotCount; // yeah it does not use original count
set string szUseHintString; set string szUseHintString;
set string dropHintString; set string dropHintString;
set string szScript; set string szScript;
@ -37,12 +37,12 @@ set string meleeImpactRumble;
reorder: reorder:
... ...
accuracyGraphName0 aiVsAiAccuracyGraphName
accuracyGraphKnots0 aiVsAiAccuracyGraphKnots
originalAccuracyGraphKnots0 originalAiVsAiAccuracyGraphKnots
accuracyGraphName1 aiVsPlayerAccuracyGraphName
accuracyGraphKnots1 aiVsPlayerAccuracyGraphKnots
originalAccuracyGraphKnots1; originalAiVsPlayerAccuracyGraphKnots;
// SndAliasCustom // SndAliasCustom
use SndAliasCustom; use SndAliasCustom;

View File

@ -15,9 +15,10 @@ set assetref szXAnims ASSET_TYPE_XANIMPARTS;
set reusable szXAnims; set reusable szXAnims;
set count szXAnims 37; set count szXAnims 37;
set string szAltWeaponName; set string szAltWeaponName;
set reusable accuracyGraphKnots; set reusable aiVsAiAccuracyGraphKnots;
set count accuracyGraphKnots[0] accuracyGraphKnotCount[0]; set count aiVsAiAccuracyGraphKnots aiVsAiAccuracyGraphKnotCount;
set count accuracyGraphKnots[1] accuracyGraphKnotCount[1]; set reusable aiVsPlayerAccuracyGraphKnots;
set count aiVsPlayerAccuracyGraphKnots aiVsPlayerAccuracyGraphKnotCount;
// WeaponDef // WeaponDef
use WeaponDef; use WeaponDef;
@ -56,12 +57,12 @@ set reusable parallelBounce;
set count parallelBounce SURF_TYPE_NUM; set count parallelBounce SURF_TYPE_NUM;
set reusable perpendicularBounce; set reusable perpendicularBounce;
set count perpendicularBounce SURF_TYPE_NUM; set count perpendicularBounce SURF_TYPE_NUM;
set string accuracyGraphName0; set string aiVsAiAccuracyGraphName;
set string accuracyGraphName1; set string aiVsPlayerAccuracyGraphName;
set reusable originalAccuracyGraphKnots0; set reusable originalAiVsAiAccuracyGraphKnots;
set reusable originalAccuracyGraphKnots1; set count originalAiVsAiAccuracyGraphKnots WeaponCompleteDef::aiVsAiAccuracyGraphKnotCount;
set count originalAccuracyGraphKnots0 WeaponCompleteDef::accuracyGraphKnotCount[0]; set reusable originalAiVsPlayerAccuracyGraphKnots;
set count originalAccuracyGraphKnots1 WeaponCompleteDef::accuracyGraphKnotCount[1]; set count originalAiVsPlayerAccuracyGraphKnots WeaponCompleteDef::aiVsPlayerAccuracyGraphKnotCount;
set string szUseHintString; set string szUseHintString;
set string dropHintString; set string dropHintString;
set string szScript; set string szScript;
@ -72,10 +73,10 @@ set string meleeImpactRumble;
set string turretBarrelSpinRumble; set string turretBarrelSpinRumble;
reorder: reorder:
... ...
accuracyGraphName0 aiVsAiAccuracyGraphName
originalAccuracyGraphKnots0 originalAiVsAiAccuracyGraphKnots
accuracyGraphName1 aiVsPlayerAccuracyGraphName
originalAccuracyGraphKnots1; originalAiVsPlayerAccuracyGraphKnots;
// SndAliasCustom // SndAliasCustom
use SndAliasCustom; use SndAliasCustom;

View File

@ -31,9 +31,10 @@ set count reloadOverrides numReloadStateTimerOverrides;
set reusable notetrackOverrides; set reusable notetrackOverrides;
set count notetrackOverrides numNotetrackOverrides; set count notetrackOverrides numNotetrackOverrides;
set string szAltWeaponName; set string szAltWeaponName;
set reusable accuracyGraphKnots; set reusable aiVsAiAccuracyGraphKnots;
set count accuracyGraphKnots[0] accuracyGraphKnotCount[0]; set count aiVsAiAccuracyGraphKnots aiVsAiAccuracyGraphKnotCount;
set count accuracyGraphKnots[1] accuracyGraphKnotCount[1]; set reusable aiVsPlayerAccuracyGraphKnots;
set count aiVsPlayerAccuracyGraphKnots aiVsPlayerAccuracyGraphKnotCount;
// AnimOverrideEntry // AnimOverrideEntry
use AnimOverrideEntry; use AnimOverrideEntry;
@ -90,12 +91,12 @@ set reusable parallelBounce;
set count parallelBounce SURF_TYPE_COUNT; set count parallelBounce SURF_TYPE_COUNT;
set reusable perpendicularBounce; set reusable perpendicularBounce;
set count perpendicularBounce SURF_TYPE_COUNT; set count perpendicularBounce SURF_TYPE_COUNT;
set string accuracyGraphName0; set string aiVsAiAccuracyGraphName;
set string accuracyGraphName1; set string aiVsPlayerAccuracyGraphName;
set reusable originalAccuracyGraphKnots0; set reusable originalAiVsAiAccuracyGraphKnots;
set reusable originalAccuracyGraphKnots1; set count originalAiVsAiAccuracyGraphKnots WeaponCompleteDef::aiVsAiAccuracyGraphKnotCount;
set count originalAccuracyGraphKnots0 WeaponCompleteDef::accuracyGraphKnotCount[0]; set reusable originalAiVsPlayerAccuracyGraphKnots;
set count originalAccuracyGraphKnots1 WeaponCompleteDef::accuracyGraphKnotCount[1]; set count originalAiVsPlayerAccuracyGraphKnots WeaponCompleteDef::aiVsPlayerAccuracyGraphKnotCount;
set string szUseHintString; set string szUseHintString;
set string dropHintString; set string dropHintString;
set string szScript; set string szScript;
@ -107,10 +108,10 @@ set string turretBarrelSpinRumble;
set scriptstring stowTag; set scriptstring stowTag;
reorder: reorder:
... ...
accuracyGraphName0 aiVsAiAccuracyGraphName
originalAccuracyGraphKnots0 originalAiVsAiAccuracyGraphKnots
accuracyGraphName1 aiVsPlayerAccuracyGraphName
originalAccuracyGraphKnots1; originalAiVsPlayerAccuracyGraphKnots;
// SndAliasCustom // SndAliasCustom
use SndAliasCustom; use SndAliasCustom;

View File

@ -126,16 +126,16 @@ set reusable parallelBounce;
set count perpendicularBounce SURF_TYPE_NUM; set count perpendicularBounce SURF_TYPE_NUM;
set reusable perpendicularBounce; set reusable perpendicularBounce;
set string projIgnitionSound; set string projIgnitionSound;
set string accuracyGraphName0; set string aiVsAiAccuracyGraphName;
set string accuracyGraphName1; set string aiVsPlayerAccuracyGraphName;
set reusable accuracyGraphKnots0; set reusable aiVsAiAccuracyGraphKnots;
set reusable accuracyGraphKnots1; set count aiVsAiAccuracyGraphKnots aiVsAiAccuracyGraphKnotCount;
set count accuracyGraphKnots0 accuracyGraphKnotCount[0]; set reusable aiVsPlayerAccuracyGraphKnots;
set count accuracyGraphKnots1 accuracyGraphKnotCount[1]; set count aiVsPlayerAccuracyGraphKnots aiVsPlayerAccuracyGraphKnotCount;
set reusable originalAccuracyGraphKnots0; set reusable originalAiVsAiAccuracyGraphKnots;
set reusable originalAccuracyGraphKnots1; set count originalAiVsAiAccuracyGraphKnots aiVsAiAccuracyGraphKnotCount; // yeah it does not use original count
set count originalAccuracyGraphKnots0 accuracyGraphKnotCount[0]; set reusable originalAiVsPlayerAccuracyGraphKnots;
set count originalAccuracyGraphKnots1 accuracyGraphKnotCount[1]; set count originalAiVsPlayerAccuracyGraphKnots aiVsPlayerAccuracyGraphKnotCount; // yeah it does not use original count
set string szUseHintString; set string szUseHintString;
set string dropHintString; set string dropHintString;
set string szScript; set string szScript;
@ -151,12 +151,12 @@ set reusable flameTableThirdPersonPtr;
reorder: reorder:
... ...
accuracyGraphName0 aiVsAiAccuracyGraphName
accuracyGraphKnots0 aiVsAiAccuracyGraphKnots
originalAccuracyGraphKnots0 originalAiVsAiAccuracyGraphKnots
accuracyGraphName1 aiVsPlayerAccuracyGraphName
accuracyGraphKnots1 aiVsPlayerAccuracyGraphKnots
originalAccuracyGraphKnots1; originalAiVsPlayerAccuracyGraphKnots;
reorder: reorder:
... ...

View File

@ -147,16 +147,16 @@ set reusable parallelBounce;
set count perpendicularBounce SURF_TYPE_NUM; set count perpendicularBounce SURF_TYPE_NUM;
set reusable perpendicularBounce; set reusable perpendicularBounce;
set string projIgnitionSound; set string projIgnitionSound;
set string accuracyGraphName0; set string aiVsAiAccuracyGraphName;
set string accuracyGraphName1; set string aiVsPlayerAccuracyGraphName;
set reusable accuracyGraphKnots0; set reusable aiVsAiAccuracyGraphKnots;
set reusable accuracyGraphKnots1; set count aiVsAiAccuracyGraphKnots aiVsAiAccuracyGraphKnotCount;
set count accuracyGraphKnots0 accuracyGraphKnotCount[0]; set reusable aiVsPlayerAccuracyGraphKnots;
set count accuracyGraphKnots1 accuracyGraphKnotCount[1]; set count aiVsPlayerAccuracyGraphKnots aiVsPlayerAccuracyGraphKnotCount;
set reusable originalAccuracyGraphKnots0; set reusable originalAiVsAiAccuracyGraphKnots;
set reusable originalAccuracyGraphKnots1; set count originalAiVsAiAccuracyGraphKnots aiVsAiAccuracyGraphKnotCount; // yeah it does not use original count
set count originalAccuracyGraphKnots0 accuracyGraphKnotCount[0]; set reusable originalAiVsPlayerAccuracyGraphKnots;
set count originalAccuracyGraphKnots1 accuracyGraphKnotCount[1]; set count originalAiVsPlayerAccuracyGraphKnots aiVsPlayerAccuracyGraphKnotCount; // yeah it does not use original count
set string szUseHintString; set string szUseHintString;
set string dropHintString; set string dropHintString;
set string szScript; set string szScript;
@ -174,12 +174,12 @@ set string throwBackType;
reorder: reorder:
... ...
accuracyGraphName0 aiVsAiAccuracyGraphName
accuracyGraphKnots0 aiVsAiAccuracyGraphKnots
originalAccuracyGraphKnots0 originalAiVsAiAccuracyGraphKnots
accuracyGraphName1 aiVsPlayerAccuracyGraphName
accuracyGraphKnots1 aiVsPlayerAccuracyGraphKnots
originalAccuracyGraphKnots1; originalAiVsPlayerAccuracyGraphKnots;
reorder: reorder:
... ...