|
|
|
|
#include <gtest/gtest.h>
|
|
|
|
|
|
|
|
|
|
#include "engine/animationinfo.h"
|
|
|
|
|
#include "nthread.h"
|
|
|
|
|
|
|
|
|
|
using namespace devilution;
|
|
|
|
|
|
|
|
|
|
enum class TestDataType {
|
|
|
|
|
SetNewAnimation,
|
|
|
|
|
GameTick,
|
|
|
|
|
Rendering
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Represents a Action in the game_logic or rendering.
|
|
|
|
|
*/
|
|
|
|
|
struct TestData {
|
|
|
|
|
virtual ~TestData() = default;
|
|
|
|
|
virtual TestDataType type() const = 0;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Represents a call to setNewAnimation
|
|
|
|
|
*/
|
|
|
|
|
struct SetNewAnimationData : public TestData {
|
|
|
|
|
SetNewAnimationData(int numberOfFrames, int delayLen, AnimationDistributionFlags params = AnimationDistributionFlags::None, int numSkippedFrames = 0, int distributeFramesBeforeFrame = 0)
|
|
|
|
|
{
|
|
|
|
|
_NumberOfFrames = numberOfFrames;
|
|
|
|
|
_DelayLen = delayLen;
|
|
|
|
|
_Params = params;
|
|
|
|
|
_NumSkippedFrames = numSkippedFrames;
|
|
|
|
|
_DistributeFramesBeforeFrame = distributeFramesBeforeFrame;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TestDataType type() const override
|
|
|
|
|
{
|
|
|
|
|
return TestDataType::SetNewAnimation;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int _NumberOfFrames;
|
|
|
|
|
int _DelayLen;
|
|
|
|
|
AnimationDistributionFlags _Params;
|
|
|
|
|
int _NumSkippedFrames;
|
|
|
|
|
int _DistributeFramesBeforeFrame;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Represents a GameTick, this includes skipping of Frames (for example because of Fastest Attack Modifier) and processAnimation (which also updates Animation Frame/Count).
|
|
|
|
|
*/
|
|
|
|
|
struct GameTickData : TestData {
|
|
|
|
|
int _ExpectedAnimationFrame;
|
|
|
|
|
int _ExpectedAnimationCnt;
|
|
|
|
|
GameTickData(int expectedAnimationFrame, int expectedAnimationCnt)
|
|
|
|
|
{
|
|
|
|
|
_ExpectedAnimationFrame = expectedAnimationFrame;
|
|
|
|
|
_ExpectedAnimationCnt = expectedAnimationCnt;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TestDataType type() const override
|
|
|
|
|
{
|
|
|
|
|
return TestDataType::GameTick;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Represents a rendering/drawing Action.
|
|
|
|
|
* This happens directly after the game_logic (_fProgressToNextGameTick = 0) or if no GameTick is due between two GameTicks (_fProgressToNextGameTick != 0).
|
|
|
|
|
*/
|
|
|
|
|
struct RenderingData : TestData {
|
|
|
|
|
/**
|
|
|
|
|
* @brief the progress as a fraction (0.0f to 1.0f) in time to the next game tick
|
|
|
|
|
*/
|
|
|
|
|
float _fProgressToNextGameTick;
|
|
|
|
|
int _ExpectedRenderingFrame;
|
|
|
|
|
RenderingData(float fProgressToNextGameTick, int expectedRenderingFrame)
|
|
|
|
|
{
|
|
|
|
|
this->_fProgressToNextGameTick = fProgressToNextGameTick;
|
|
|
|
|
this->_ExpectedRenderingFrame = expectedRenderingFrame;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TestDataType type() const override
|
|
|
|
|
{
|
|
|
|
|
return TestDataType::Rendering;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief
|
|
|
|
|
* This UnitTest tries to simulate the GameLoop (GameTickData) and the Rendering that can happen (RenderingData).
|
|
|
|
|
* Rendering can happen more often than GameTicks and at any time between two GameTicks.
|
|
|
|
|
* The Animation Distribution Logic must adjust to the Rendering that happens at any give point in time.
|
|
|
|
|
*/
|
|
|
|
|
void RunAnimationTest(const std::vector<TestData *> &vecTestData)
|
|
|
|
|
{
|
|
|
|
|
AnimationInfo animInfo = {};
|
|
|
|
|
|
|
|
|
|
int currentGameTick = 0;
|
|
|
|
|
for (TestData *x : vecTestData) {
|
|
|
|
|
switch (x->type()) {
|
|
|
|
|
case TestDataType::SetNewAnimation: {
|
|
|
|
|
auto setNewAnimationData = static_cast<SetNewAnimationData *>(x);
|
|
|
|
|
animInfo.setNewAnimation(std::nullopt, setNewAnimationData->_NumberOfFrames, setNewAnimationData->_DelayLen, setNewAnimationData->_Params, setNewAnimationData->_NumSkippedFrames, setNewAnimationData->_DistributeFramesBeforeFrame);
|
|
|
|
|
} break;
|
|
|
|
|
case TestDataType::GameTick: {
|
|
|
|
|
auto gameTickData = static_cast<GameTickData *>(x);
|
|
|
|
|
currentGameTick += 1;
|
|
|
|
|
animInfo.processAnimation();
|
|
|
|
|
EXPECT_EQ(animInfo.currentFrame, gameTickData->_ExpectedAnimationFrame);
|
|
|
|
|
EXPECT_EQ(animInfo.tickCounterOfCurrentFrame, gameTickData->_ExpectedAnimationCnt);
|
|
|
|
|
} break;
|
|
|
|
|
case TestDataType::Rendering: {
|
|
|
|
|
auto renderingData = static_cast<RenderingData *>(x);
|
|
|
|
|
ProgressToNextGameTick = static_cast<uint8_t>(renderingData->_fProgressToNextGameTick * AnimationInfo::baseValueFraction);
|
|
|
|
|
EXPECT_EQ(animInfo.getFrameToUseForRendering(), renderingData->_ExpectedRenderingFrame)
|
|
|
|
|
<< std::fixed << std::setprecision(2)
|
|
|
|
|
<< "ProgressToNextGameTick: " << renderingData->_fProgressToNextGameTick
|
|
|
|
|
<< " currentFrame: " << animInfo.currentFrame
|
|
|
|
|
<< " DelayCounter: " << animInfo.tickCounterOfCurrentFrame
|
|
|
|
|
<< " GameTick: " << currentGameTick;
|
|
|
|
|
} break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
for (TestData *x : vecTestData) {
|
|
|
|
|
delete x;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST(AnimationInfo, AttackSwordWarrior) // ProcessAnimationPending should be considered by distribution logic
|
|
|
|
|
{
|
|
|
|
|
RunAnimationTest(
|
|
|
|
|
{
|
|
|
|
|
new SetNewAnimationData(16, 1, AnimationDistributionFlags::ProcessAnimationPending, 0, 9),
|
|
|
|
|
// processAnimation directly after StartAttack (in same GameTick). So we don't see any rendering before.
|
|
|
|
|
new GameTickData(1, 0),
|
|
|
|
|
new RenderingData(0.0f, 0),
|
|
|
|
|
new RenderingData(0.3f, 0),
|
|
|
|
|
new RenderingData(0.6f, 0),
|
|
|
|
|
new RenderingData(0.8f, 0),
|
|
|
|
|
new GameTickData(2, 0),
|
|
|
|
|
new RenderingData(0.0f, 1),
|
|
|
|
|
new RenderingData(0.3f, 1),
|
|
|
|
|
new RenderingData(0.6f, 1),
|
|
|
|
|
new RenderingData(0.8f, 2),
|
|
|
|
|
new GameTickData(3, 0),
|
|
|
|
|
new RenderingData(0.0f, 2),
|
|
|
|
|
new RenderingData(0.3f, 2),
|
|
|
|
|
new RenderingData(0.6f, 2),
|
|
|
|
|
new RenderingData(0.8f, 3),
|
|
|
|
|
new GameTickData(4, 0),
|
|
|
|
|
new RenderingData(0.0f, 3),
|
|
|
|
|
new RenderingData(0.3f, 3),
|
|
|
|
|
new RenderingData(0.6f, 4),
|
|
|
|
|
new RenderingData(0.8f, 4),
|
|
|
|
|
new GameTickData(5, 0),
|
|
|
|
|
new RenderingData(0.0f, 4),
|
|
|
|
|
new RenderingData(0.3f, 4),
|
|
|
|
|
new RenderingData(0.6f, 5),
|
|
|
|
|
new RenderingData(0.8f, 5),
|
|
|
|
|
new GameTickData(6, 0),
|
|
|
|
|
new RenderingData(0.0f, 5),
|
|
|
|
|
new RenderingData(0.3f, 6),
|
|
|
|
|
new RenderingData(0.6f, 6),
|
|
|
|
|
new RenderingData(0.8f, 6),
|
|
|
|
|
new GameTickData(7, 0),
|
|
|
|
|
new RenderingData(0.0f, 6),
|
|
|
|
|
new RenderingData(0.3f, 7),
|
|
|
|
|
new RenderingData(0.6f, 7),
|
|
|
|
|
new RenderingData(0.8f, 7),
|
|
|
|
|
|
|
|
|
|
// After this GameTick, the Animation Distribution Logic is disabled
|
|
|
|
|
new GameTickData(8, 0),
|
|
|
|
|
new RenderingData(0.1f, 8),
|
|
|
|
|
new GameTickData(9, 0),
|
|
|
|
|
new RenderingData(0.4f, 9),
|
|
|
|
|
new GameTickData(10, 0),
|
|
|
|
|
new RenderingData(0.4f, 10),
|
|
|
|
|
new GameTickData(11, 0),
|
|
|
|
|
new RenderingData(0.3f, 11),
|
|
|
|
|
new GameTickData(12, 0),
|
|
|
|
|
new RenderingData(0.0f, 12),
|
|
|
|
|
new GameTickData(13, 0),
|
|
|
|
|
new RenderingData(0.6f, 13),
|
|
|
|
|
new GameTickData(14, 0),
|
|
|
|
|
new RenderingData(0.6f, 14),
|
|
|
|
|
new GameTickData(15, 0),
|
|
|
|
|
new RenderingData(0.6f, 15),
|
|
|
|
|
// Animation stopped cause PM_DoAttack would stop the Animation "if (plr[pnum].AnimInfo.currentFrame == plr[pnum]._pAFrames - 1) {"
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST(AnimationInfo, AttackSwordWarriorWithFastestAttack) // Skipped frames and ProcessAnimationPending should be considered by distribution logic
|
|
|
|
|
{
|
|
|
|
|
RunAnimationTest(
|
|
|
|
|
{
|
|
|
|
|
new SetNewAnimationData(16, 1, AnimationDistributionFlags::ProcessAnimationPending, 2, 9),
|
|
|
|
|
// processAnimation directly after StartAttack (in same GameTick). So we don't see any rendering before.
|
|
|
|
|
new GameTickData(3, 0),
|
|
|
|
|
new RenderingData(0.0f, 0),
|
|
|
|
|
new RenderingData(0.3f, 0),
|
|
|
|
|
new RenderingData(0.6f, 0),
|
|
|
|
|
new RenderingData(0.8f, 1),
|
|
|
|
|
new GameTickData(4, 0),
|
|
|
|
|
new RenderingData(0.0f, 1),
|
|
|
|
|
new RenderingData(0.3f, 2),
|
|
|
|
|
new RenderingData(0.6f, 2),
|
|
|
|
|
new RenderingData(0.8f, 2),
|
|
|
|
|
new GameTickData(5, 0),
|
|
|
|
|
new RenderingData(0.0f, 3),
|
|
|
|
|
new RenderingData(0.3f, 3),
|
|
|
|
|
new RenderingData(0.6f, 4),
|
|
|
|
|
new RenderingData(0.8f, 4),
|
|
|
|
|
new GameTickData(6, 0),
|
|
|
|
|
new RenderingData(0.0f, 4),
|
|
|
|
|
new RenderingData(0.3f, 5),
|
|
|
|
|
new RenderingData(0.6f, 5),
|
|
|
|
|
new RenderingData(0.8f, 6),
|
|
|
|
|
new GameTickData(7, 0),
|
|
|
|
|
new RenderingData(0.0f, 6),
|
|
|
|
|
new RenderingData(0.3f, 6),
|
|
|
|
|
new RenderingData(0.6f, 7),
|
|
|
|
|
new RenderingData(0.8f, 7),
|
|
|
|
|
|
|
|
|
|
// After this GameTick, the Animation Distribution Logic is disabled
|
|
|
|
|
new GameTickData(8, 0),
|
|
|
|
|
new RenderingData(0.1f, 8),
|
|
|
|
|
new GameTickData(9, 0),
|
|
|
|
|
new RenderingData(0.4f, 9),
|
|
|
|
|
new GameTickData(10, 0),
|
|
|
|
|
new RenderingData(0.4f, 10),
|
|
|
|
|
new GameTickData(11, 0),
|
|
|
|
|
new RenderingData(0.3f, 11),
|
|
|
|
|
new GameTickData(12, 0),
|
|
|
|
|
new RenderingData(0.0f, 12),
|
|
|
|
|
new GameTickData(13, 0),
|
|
|
|
|
new RenderingData(0.6f, 13),
|
|
|
|
|
new GameTickData(14, 0),
|
|
|
|
|
new RenderingData(0.6f, 14),
|
|
|
|
|
new GameTickData(15, 0),
|
|
|
|
|
new RenderingData(0.6f, 15),
|
|
|
|
|
// Animation stopped cause PM_DoAttack would stop the Animation "if (plr[pnum].AnimInfo.currentFrame == plr[pnum]._pAFrames - 1) {"
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief The Warrior make two attacks. The second queued attack cancels the first after the Hit Frame.
|
|
|
|
|
*/
|
|
|
|
|
TEST(AnimationInfo, AttackSwordWarriorRepeated)
|
|
|
|
|
{
|
|
|
|
|
RunAnimationTest(
|
|
|
|
|
{
|
|
|
|
|
new SetNewAnimationData(16, 1, AnimationDistributionFlags::ProcessAnimationPending, 0, 9),
|
|
|
|
|
// processAnimation directly after StartAttack (in same GameTick). So we don't see any rendering before.
|
|
|
|
|
new GameTickData(1, 0),
|
|
|
|
|
new RenderingData(0.0f, 0),
|
|
|
|
|
new RenderingData(0.3f, 0),
|
|
|
|
|
new RenderingData(0.6f, 0),
|
|
|
|
|
new RenderingData(0.8f, 0),
|
|
|
|
|
new GameTickData(2, 0),
|
|
|
|
|
new RenderingData(0.0f, 1),
|
|
|
|
|
new RenderingData(0.3f, 1),
|
|
|
|
|
new RenderingData(0.6f, 1),
|
|
|
|
|
new RenderingData(0.8f, 2),
|
|
|
|
|
new GameTickData(3, 0),
|
|
|
|
|
new RenderingData(0.0f, 2),
|
|
|
|
|
new RenderingData(0.3f, 2),
|
|
|
|
|
new RenderingData(0.6f, 2),
|
|
|
|
|
new RenderingData(0.8f, 3),
|
|
|
|
|
new GameTickData(4, 0),
|
|
|
|
|
new RenderingData(0.0f, 3),
|
|
|
|
|
new RenderingData(0.3f, 3),
|
|
|
|
|
new RenderingData(0.6f, 4),
|
|
|
|
|
new RenderingData(0.8f, 4),
|
|
|
|
|
new GameTickData(5, 0),
|
|
|
|
|
new RenderingData(0.0f, 4),
|
|
|
|
|
new RenderingData(0.3f, 4),
|
|
|
|
|
new RenderingData(0.6f, 5),
|
|
|
|
|
new RenderingData(0.8f, 5),
|
|
|
|
|
new GameTickData(6, 0),
|
|
|
|
|
new RenderingData(0.0f, 5),
|
|
|
|
|
new RenderingData(0.3f, 6),
|
|
|
|
|
new RenderingData(0.6f, 6),
|
|
|
|
|
new RenderingData(0.8f, 6),
|
|
|
|
|
new GameTickData(7, 0),
|
|
|
|
|
new RenderingData(0.0f, 6),
|
|
|
|
|
new RenderingData(0.3f, 7),
|
|
|
|
|
new RenderingData(0.6f, 7),
|
|
|
|
|
new RenderingData(0.8f, 7),
|
|
|
|
|
|
|
|
|
|
// After this GameTick, the Animation Distribution Logic is disabled
|
|
|
|
|
new GameTickData(8, 0),
|
|
|
|
|
new RenderingData(0.1f, 8),
|
|
|
|
|
new GameTickData(9, 0),
|
|
|
|
|
new RenderingData(0.3f, 9),
|
|
|
|
|
|
|
|
|
|
// Start of repeated attack, cause plr[pnum].AnimInfo.currentFrame > plr[myplr]._pAFNum
|
|
|
|
|
new SetNewAnimationData(16, 1, static_cast<AnimationDistributionFlags>(AnimationDistributionFlags::ProcessAnimationPending | AnimationDistributionFlags::RepeatedAction), 0, 9),
|
|
|
|
|
// processAnimation directly after StartAttack (in same GameTick). So we don't see any rendering before.
|
|
|
|
|
new GameTickData(1, 0),
|
|
|
|
|
new RenderingData(0.0f, 10),
|
|
|
|
|
new RenderingData(0.3f, 10),
|
|
|
|
|
new RenderingData(0.6f, 11),
|
|
|
|
|
new RenderingData(0.8f, 11),
|
|
|
|
|
new GameTickData(2, 0),
|
|
|
|
|
new RenderingData(0.0f, 12),
|
|
|
|
|
new RenderingData(0.3f, 12),
|
|
|
|
|
new RenderingData(0.6f, 13),
|
|
|
|
|
new RenderingData(0.8f, 13),
|
|
|
|
|
new GameTickData(3, 0),
|
|
|
|
|
new RenderingData(0.0f, 14),
|
|
|
|
|
new RenderingData(0.3f, 14),
|
|
|
|
|
new RenderingData(0.6f, 15),
|
|
|
|
|
new RenderingData(0.8f, 15),
|
|
|
|
|
new GameTickData(4, 0),
|
|
|
|
|
new RenderingData(0.0f, 0),
|
|
|
|
|
new RenderingData(0.3f, 0),
|
|
|
|
|
new RenderingData(0.6f, 1),
|
|
|
|
|
new RenderingData(0.8f, 1),
|
|
|
|
|
new GameTickData(5, 0),
|
|
|
|
|
new RenderingData(0.0f, 2),
|
|
|
|
|
new RenderingData(0.3f, 2),
|
|
|
|
|
new RenderingData(0.6f, 3),
|
|
|
|
|
new RenderingData(0.8f, 3),
|
|
|
|
|
new GameTickData(6, 0),
|
|
|
|
|
new RenderingData(0.0f, 4),
|
|
|
|
|
new RenderingData(0.3f, 4),
|
|
|
|
|
new RenderingData(0.6f, 5),
|
|
|
|
|
new RenderingData(0.8f, 5),
|
|
|
|
|
new GameTickData(7, 0),
|
|
|
|
|
new RenderingData(0.0f, 6),
|
|
|
|
|
new RenderingData(0.3f, 6),
|
|
|
|
|
new RenderingData(0.6f, 7),
|
|
|
|
|
new RenderingData(0.8f, 7),
|
|
|
|
|
|
|
|
|
|
// After this GameTick, the Animation Distribution Logic is disabled
|
|
|
|
|
new GameTickData(8, 0),
|
|
|
|
|
new RenderingData(0.1f, 8),
|
|
|
|
|
new GameTickData(9, 0),
|
|
|
|
|
new RenderingData(0.4f, 9),
|
|
|
|
|
new GameTickData(10, 0),
|
|
|
|
|
new RenderingData(0.4f, 10),
|
|
|
|
|
new GameTickData(11, 0),
|
|
|
|
|
new RenderingData(0.3f, 11),
|
|
|
|
|
new GameTickData(12, 0),
|
|
|
|
|
new RenderingData(0.0f, 12),
|
|
|
|
|
new GameTickData(13, 0),
|
|
|
|
|
new RenderingData(0.6f, 13),
|
|
|
|
|
new GameTickData(14, 0),
|
|
|
|
|
new RenderingData(0.6f, 14),
|
|
|
|
|
new GameTickData(15, 0),
|
|
|
|
|
new RenderingData(0.6f, 15),
|
|
|
|
|
// Animation stopped cause PM_DoAttack would stop the Animation "if (plr[pnum].AnimInfo.currentFrame == plr[pnum]._pAFrames - 1) {"
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST(AnimationInfo, BlockingWarriorNormal) // Ignored delay for last Frame should be considered by distribution logic
|
|
|
|
|
{
|
|
|
|
|
RunAnimationTest(
|
|
|
|
|
{
|
|
|
|
|
new SetNewAnimationData(2, 3, AnimationDistributionFlags::SkipsDelayOfLastFrame),
|
|
|
|
|
new RenderingData(0.0f, 0),
|
|
|
|
|
new RenderingData(0.3f, 0),
|
|
|
|
|
new RenderingData(0.6f, 0),
|
|
|
|
|
new RenderingData(0.8f, 0),
|
|
|
|
|
new GameTickData(0, 1),
|
|
|
|
|
new RenderingData(0.0f, 0),
|
|
|
|
|
new RenderingData(0.3f, 0),
|
|
|
|
|
new RenderingData(0.6f, 0),
|
|
|
|
|
new RenderingData(0.8f, 0),
|
|
|
|
|
new GameTickData(0, 2),
|
|
|
|
|
new RenderingData(0.0f, 1),
|
|
|
|
|
new RenderingData(0.3f, 1),
|
|
|
|
|
new RenderingData(0.6f, 1),
|
|
|
|
|
new RenderingData(0.8f, 1),
|
|
|
|
|
new GameTickData(1, 0),
|
|
|
|
|
new RenderingData(0.0f, 1),
|
|
|
|
|
new RenderingData(0.3f, 1),
|
|
|
|
|
new RenderingData(0.6f, 1),
|
|
|
|
|
new RenderingData(0.8f, 1),
|
|
|
|
|
// Animation stopped cause PM_DoBlock would stop the Animation "if (plr[pnum].AnimInfo.currentFrame >= plr[pnum]._pBFrames) {"
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST(AnimationInfo, BlockingSorcererWithFastBlock) // Skipped frames and ignored delay for last Frame should be considered by distribution logic
|
|
|
|
|
{
|
|
|
|
|
RunAnimationTest(
|
|
|
|
|
{
|
|
|
|
|
new SetNewAnimationData(6, 3, AnimationDistributionFlags::SkipsDelayOfLastFrame, 4),
|
|
|
|
|
new RenderingData(0.0f, 0),
|
|
|
|
|
new RenderingData(0.3f, 0),
|
|
|
|
|
new RenderingData(0.6f, 0),
|
|
|
|
|
new RenderingData(0.8f, 1),
|
|
|
|
|
new GameTickData(4, 1),
|
|
|
|
|
new RenderingData(0.0f, 1),
|
|
|
|
|
new RenderingData(0.3f, 1),
|
|
|
|
|
new RenderingData(0.6f, 2),
|
|
|
|
|
new RenderingData(0.8f, 2),
|
|
|
|
|
new GameTickData(4, 2),
|
|
|
|
|
new RenderingData(0.0f, 3),
|
|
|
|
|
new RenderingData(0.3f, 3),
|
|
|
|
|
new RenderingData(0.6f, 3),
|
|
|
|
|
new RenderingData(0.8f, 4),
|
|
|
|
|
new GameTickData(5, 0),
|
|
|
|
|
new RenderingData(0.0f, 4),
|
|
|
|
|
new RenderingData(0.3f, 4),
|
|
|
|
|
new RenderingData(0.6f, 5),
|
|
|
|
|
new RenderingData(0.8f, 5),
|
|
|
|
|
// Animation stopped cause PM_DoBlock would stop the Animation "if (plr[pnum].AnimInfo.currentFrame >= plr[pnum]._pBFrames) {"
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST(AnimationInfo, HitRecoverySorcererHarmony) // Skipped frames and ignored delay for last Frame should be considered by distribution logic
|
|
|
|
|
{
|
|
|
|
|
RunAnimationTest(
|
|
|
|
|
{
|
|
|
|
|
new SetNewAnimationData(8, 1, AnimationDistributionFlags::None, 3),
|
|
|
|
|
new RenderingData(0.0f, 0),
|
|
|
|
|
new RenderingData(0.3f, 0),
|
|
|
|
|
new RenderingData(0.6f, 0),
|
|
|
|
|
new RenderingData(0.8f, 1),
|
|
|
|
|
new GameTickData(4, 0),
|
|
|
|
|
new RenderingData(0.0f, 1),
|
|
|
|
|
new RenderingData(0.3f, 2),
|
|
|
|
|
new RenderingData(0.6f, 2),
|
|
|
|
|
new RenderingData(0.8f, 2),
|
|
|
|
|
new GameTickData(5, 0),
|
|
|
|
|
new RenderingData(0.0f, 3),
|
|
|
|
|
new RenderingData(0.3f, 3),
|
|
|
|
|
new RenderingData(0.6f, 4),
|
|
|
|
|
new RenderingData(0.8f, 4),
|
|
|
|
|
new GameTickData(6, 0),
|
|
|
|
|
new RenderingData(0.0f, 4),
|
|
|
|
|
new RenderingData(0.3f, 5),
|
|
|
|
|
new RenderingData(0.6f, 5),
|
|
|
|
|
new RenderingData(0.8f, 6),
|
|
|
|
|
new GameTickData(7, 0),
|
|
|
|
|
new RenderingData(0.0f, 6),
|
|
|
|
|
new RenderingData(0.3f, 6),
|
|
|
|
|
new RenderingData(0.6f, 7),
|
|
|
|
|
new RenderingData(0.8f, 7),
|
|
|
|
|
// Animation stopped cause PM_DoGotHit would stop the Animation "if (plr[pnum].AnimInfo.currentFrame >= plr[pnum]._pHFrames) {"
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
TEST(AnimationInfo, Stand) // Distribution Logic shouldn't change anything here
|
|
|
|
|
{
|
|
|
|
|
RunAnimationTest(
|
|
|
|
|
{
|
|
|
|
|
new SetNewAnimationData(10, 4),
|
|
|
|
|
new RenderingData(0.1f, 0),
|
|
|
|
|
new GameTickData(0, 1),
|
|
|
|
|
new RenderingData(0.6f, 0),
|
|
|
|
|
new GameTickData(0, 2),
|
|
|
|
|
new RenderingData(0.6f, 0),
|
|
|
|
|
new GameTickData(0, 3),
|
|
|
|
|
new RenderingData(0.6f, 0),
|
|
|
|
|
|
|
|
|
|
new GameTickData(1, 0),
|
|
|
|
|
new RenderingData(0.6f, 1),
|
|
|
|
|
new GameTickData(1, 1),
|
|
|
|
|
new RenderingData(0.6f, 1),
|
|
|
|
|
new GameTickData(1, 2),
|
|
|
|
|
new RenderingData(0.6f, 1),
|
|
|
|
|
new GameTickData(1, 3),
|
|
|
|
|
new RenderingData(0.6f, 1),
|
|
|
|
|
|
|
|
|
|
new GameTickData(2, 0),
|
|
|
|
|
new RenderingData(0.6f, 2),
|
|
|
|
|
new GameTickData(2, 1),
|
|
|
|
|
new RenderingData(0.6f, 2),
|
|
|
|
|
new GameTickData(2, 2),
|
|
|
|
|
new RenderingData(0.6f, 2),
|
|
|
|
|
new GameTickData(2, 3),
|
|
|
|
|
new RenderingData(0.6f, 2),
|
|
|
|
|
|
|
|
|
|
new GameTickData(3, 0),
|
|
|
|
|
new RenderingData(0.6f, 3),
|
|
|
|
|
new GameTickData(3, 1),
|
|
|
|
|
new RenderingData(0.6f, 3),
|
|
|
|
|
new GameTickData(3, 2),
|
|
|
|
|
new RenderingData(0.6f, 3),
|
|
|
|
|
new GameTickData(3, 3),
|
|
|
|
|
new RenderingData(0.6f, 3),
|
|
|
|
|
|
|
|
|
|
new GameTickData(4, 0),
|
|
|
|
|
new RenderingData(0.6f, 4),
|
|
|
|
|
new GameTickData(4, 1),
|
|
|
|
|
new RenderingData(0.6f, 4),
|
|
|
|
|
new GameTickData(4, 2),
|
|
|
|
|
new RenderingData(0.6f, 4),
|
|
|
|
|
new GameTickData(4, 3),
|
|
|
|
|
new RenderingData(0.6f, 4),
|
|
|
|
|
|
|
|
|
|
new GameTickData(5, 0),
|
|
|
|
|
new RenderingData(0.6f, 5),
|
|
|
|
|
new GameTickData(5, 1),
|
|
|
|
|
new RenderingData(0.6f, 5),
|
|
|
|
|
new GameTickData(5, 2),
|
|
|
|
|
new RenderingData(0.6f, 5),
|
|
|
|
|
new GameTickData(5, 3),
|
|
|
|
|
new RenderingData(0.6f, 5),
|
|
|
|
|
|
|
|
|
|
new GameTickData(6, 0),
|
|
|
|
|
new RenderingData(0.6f, 6),
|
|
|
|
|
new GameTickData(6, 1),
|
|
|
|
|
new RenderingData(0.6f, 6),
|
|
|
|
|
new GameTickData(6, 2),
|
|
|
|
|
new RenderingData(0.6f, 6),
|
|
|
|
|
new GameTickData(6, 3),
|
|
|
|
|
new RenderingData(0.6f, 6),
|
|
|
|
|
|
|
|
|
|
new GameTickData(7, 0),
|
|
|
|
|
new RenderingData(0.6f, 7),
|
|
|
|
|
new GameTickData(7, 1),
|
|
|
|
|
new RenderingData(0.6f, 7),
|
|
|
|
|
new GameTickData(7, 2),
|
|
|
|
|
new RenderingData(0.6f, 7),
|
|
|
|
|
new GameTickData(7, 3),
|
|
|
|
|
new RenderingData(0.6f, 7),
|
|
|
|
|
|
|
|
|
|
new GameTickData(8, 0),
|
|
|
|
|
new RenderingData(0.6f, 8),
|
|
|
|
|
new GameTickData(8, 1),
|
|
|
|
|
new RenderingData(0.6f, 8),
|
|
|
|
|
new GameTickData(8, 2),
|
|
|
|
|
new RenderingData(0.6f, 8),
|
|
|
|
|
new GameTickData(8, 3),
|
|
|
|
|
new RenderingData(0.6f, 8),
|
|
|
|
|
|
|
|
|
|
new GameTickData(9, 0),
|
|
|
|
|
new RenderingData(0.6f, 9),
|
|
|
|
|
new GameTickData(9, 1),
|
|
|
|
|
new RenderingData(0.6f, 9),
|
|
|
|
|
new GameTickData(9, 2),
|
|
|
|
|
new RenderingData(0.6f, 9),
|
|
|
|
|
new GameTickData(9, 3),
|
|
|
|
|
new RenderingData(0.6f, 9),
|
|
|
|
|
|
|
|
|
|
// Animation starts again
|
|
|
|
|
new GameTickData(0, 0),
|
|
|
|
|
new RenderingData(0.1f, 0),
|
|
|
|
|
new GameTickData(0, 1),
|
|
|
|
|
new RenderingData(0.6f, 0),
|
|
|
|
|
new GameTickData(0, 2),
|
|
|
|
|
new RenderingData(0.6f, 0),
|
|
|
|
|
new GameTickData(0, 3),
|
|
|
|
|
new RenderingData(0.6f, 0),
|
|
|
|
|
});
|
|
|
|
|
}
|