Browse Source

Change AnimationDistributionParams to AnimationDistributionFlags

pull/1848/head
obligaron 5 years ago committed by Anders Jenbo
parent
commit
b5954eb34b
  1. 8
      Source/engine/animationinfo.cpp
  2. 13
      Source/engine/animationinfo.h
  3. 18
      Source/player.cpp
  4. 4
      Source/player.h
  5. 18
      test/animationinfo_test.cpp

8
Source/engine/animationinfo.cpp

@ -52,7 +52,7 @@ int AnimationInfo::GetFrameToUseForRendering() const
return absoluteAnimationFrame;
}
void AnimationInfo::SetNewAnimation(uint8_t *pData, int numberOfFrames, int delayLen, AnimationDistributionParams params /*= AnimationDistributionParams::None*/, int numSkippedFrames /*= 0*/, int distributeFramesBeforeFrame /*= 0*/)
void AnimationInfo::SetNewAnimation(uint8_t *pData, int numberOfFrames, int delayLen, AnimationDistributionFlags flags /*= AnimationDistributionFlags::None*/, int numSkippedFrames /*= 0*/, int distributeFramesBeforeFrame /*= 0*/)
{
if (pData == this->pData && distributeFramesBeforeFrame != 0 && NumberOfFrames == numberOfFrames && CurrentFrame >= distributeFramesBeforeFrame && CurrentFrame != NumberOfFrames) {
// We showed the same Animation (for example a melee attack) before but truncated the Animation.
@ -71,7 +71,7 @@ void AnimationInfo::SetNewAnimation(uint8_t *pData, int numberOfFrames, int dela
RelevantFramesForDistributing = 0;
TickModifier = 0.0f;
if (numSkippedFrames != 0 || params != AnimationDistributionParams::None) {
if (numSkippedFrames != 0 || flags != AnimationDistributionFlags::None) {
// Animation Frames that will be adjusted for the skipped Frames/game ticks
int relevantAnimationFramesForDistributing = numberOfFrames;
if (distributeFramesBeforeFrame != 0) {
@ -91,7 +91,7 @@ void AnimationInfo::SetNewAnimation(uint8_t *pData, int numberOfFrames, int dela
// How many game ticks will the Animation be really shown (skipped Frames and game ticks removed)
int relevantAnimationTicksWithSkipping = relevantAnimationTicksForDistribution - (numSkippedFrames * ticksPerFrame);
if (params == AnimationDistributionParams::ProcessAnimationPending) {
if ((flags & AnimationDistributionFlags::ProcessAnimationPending) == AnimationDistributionFlags::ProcessAnimationPending) {
// If ProcessAnimation will be called after SetNewAnimation (in same game tick as SetNewAnimation), we increment the Animation-Counter.
// If no delay is specified, this will result in complete skipped frame (see ProcessAnimation).
// But if we have a delay specified, this would only result in a reduced time the first frame is shown (one skipped delay).
@ -103,7 +103,7 @@ void AnimationInfo::SetNewAnimation(uint8_t *pData, int numberOfFrames, int dela
TicksSinceSequenceStarted = -1;
}
if (params == AnimationDistributionParams::SkipsDelayOfLastFrame) {
if ((flags & AnimationDistributionFlags::SkipsDelayOfLastFrame) == AnimationDistributionFlags::SkipsDelayOfLastFrame) {
// The logic for player/monster/... (not ProcessAnimation) only checks the frame not the delay.
// That means if a delay is specified, the last-frame is shown less then the other frames
// Example:

13
Source/engine/animationinfo.h

@ -6,22 +6,23 @@
#pragma once
#include <stdint.h>
#include <type_traits>
namespace devilution {
/**
* @brief Specifies what special logics are applied for a Animation
*/
enum class AnimationDistributionParams : uint8_t {
None,
enum AnimationDistributionFlags : uint8_t {
None = 0,
/*
* @brief ProcessAnimation will be called after SetNewAnimation (in same game tick as NewPlrAnim)
*/
ProcessAnimationPending,
ProcessAnimationPending = 1 << 0,
/*
* @brief Delay of last Frame is ignored (for example, because only Frame and not delay is checked in game_logic)
*/
SkipsDelayOfLastFrame,
SkipsDelayOfLastFrame = 1 << 1,
};
/*
@ -61,11 +62,11 @@ public:
* @param pData Pointer to Animation Data
* @param numberOfFrames Number of Frames in Animation
* @param delayLen Delay after each Animation sequence
* @param params Specifies what special logics are applied to this Animation
* @param flags Specifies what special logics are applied to this Animation
* @param numSkippedFrames Number of Frames that will be skipped (for example with modifier "faster attack")
* @param distributeFramesBeforeFrame Distribute the numSkippedFrames only before this frame
*/
void SetNewAnimation(uint8_t *pData, int numberOfFrames, int delayLen, AnimationDistributionParams params = AnimationDistributionParams::None, int numSkippedFrames = 0, int distributeFramesBeforeFrame = 0);
void SetNewAnimation(uint8_t *pData, int numberOfFrames, int delayLen, AnimationDistributionFlags flags = AnimationDistributionFlags::None, int numSkippedFrames = 0, int distributeFramesBeforeFrame = 0);
/*
* @brief Process the Animation for a game tick (for example advances the frame)

18
Source/player.cpp

@ -552,14 +552,14 @@ void FreePlayerGFX(int pnum)
plr[pnum]._pGFXLoad = 0;
}
void NewPlrAnim(int pnum, BYTE *pData, int numberOfFrames, int delayLen, int width, AnimationDistributionParams params /*= AnimationDistributionParams::None*/, int numSkippedFrames /*= 0*/, int distributeFramesBeforeFrame /*= 0*/)
void NewPlrAnim(int pnum, BYTE *pData, int numberOfFrames, int delayLen, int width, AnimationDistributionFlags flags /*= AnimationDistributionFlags::None*/, int numSkippedFrames /*= 0*/, int distributeFramesBeforeFrame /*= 0*/)
{
if ((DWORD)pnum >= MAX_PLRS) {
app_fatal("NewPlrAnim: illegal player %d", pnum);
}
plr[pnum]._pAnimWidth = width;
plr[pnum].AnimInfo.SetNewAnimation(pData, numberOfFrames, delayLen, params, numSkippedFrames, distributeFramesBeforeFrame);
plr[pnum].AnimInfo.SetNewAnimation(pData, numberOfFrames, delayLen, flags, numSkippedFrames, distributeFramesBeforeFrame);
}
void ClearPlrPVars(int pnum)
@ -1489,7 +1489,7 @@ void StartAttack(int pnum, direction d)
skippedAnimationFrames = 2;
}
NewPlrAnim(pnum, plr[pnum]._pAAnim[d], plr[pnum]._pAFrames, 0, plr[pnum]._pAWidth, AnimationDistributionParams::ProcessAnimationPending, skippedAnimationFrames, plr[pnum]._pAFNum);
NewPlrAnim(pnum, plr[pnum]._pAAnim[d], plr[pnum]._pAFrames, 0, plr[pnum]._pAWidth, AnimationDistributionFlags::ProcessAnimationPending, skippedAnimationFrames, plr[pnum]._pAFNum);
plr[pnum]._pmode = PM_ATTACK;
FixPlayerLocation(pnum, d);
SetPlayerOld(pnum);
@ -1517,7 +1517,7 @@ void StartRangeAttack(int pnum, direction d, int cx, int cy)
}
}
NewPlrAnim(pnum, plr[pnum]._pAAnim[d], plr[pnum]._pAFrames, 0, plr[pnum]._pAWidth, AnimationDistributionParams::ProcessAnimationPending, skippedAnimationFrames, plr[pnum]._pAFNum);
NewPlrAnim(pnum, plr[pnum]._pAAnim[d], plr[pnum]._pAFrames, 0, plr[pnum]._pAWidth, AnimationDistributionFlags::ProcessAnimationPending, skippedAnimationFrames, plr[pnum]._pAFNum);
plr[pnum]._pmode = PM_RATTACK;
FixPlayerLocation(pnum, d);
@ -1547,7 +1547,7 @@ void StartPlrBlock(int pnum, direction dir)
skippedAnimationFrames = (plr[pnum]._pBFrames - 2); // ISPL_FASTBLOCK means we cancel the animation if frame 2 was shown
}
NewPlrAnim(pnum, plr[pnum]._pBAnim[dir], plr[pnum]._pBFrames, 2, plr[pnum]._pBWidth, AnimationDistributionParams::SkipsDelayOfLastFrame, skippedAnimationFrames);
NewPlrAnim(pnum, plr[pnum]._pBAnim[dir], plr[pnum]._pBFrames, 2, plr[pnum]._pBWidth, AnimationDistributionFlags::SkipsDelayOfLastFrame, skippedAnimationFrames);
plr[pnum]._pmode = PM_BLOCK;
FixPlayerLocation(pnum, dir);
@ -1570,19 +1570,19 @@ void StartSpell(int pnum, direction d, int cx, int cy)
if ((plr[pnum]._pGFXLoad & PFILE_FIRE) == 0) {
LoadPlrGFX(pnum, PFILE_FIRE);
}
NewPlrAnim(pnum, plr[pnum]._pFAnim[d], plr[pnum]._pSFrames, 0, plr[pnum]._pSWidth, AnimationDistributionParams::ProcessAnimationPending, 0, plr[pnum]._pSFNum);
NewPlrAnim(pnum, plr[pnum]._pFAnim[d], plr[pnum]._pSFrames, 0, plr[pnum]._pSWidth, AnimationDistributionFlags::ProcessAnimationPending, 0, plr[pnum]._pSFNum);
break;
case STYPE_LIGHTNING:
if ((plr[pnum]._pGFXLoad & PFILE_LIGHTNING) == 0) {
LoadPlrGFX(pnum, PFILE_LIGHTNING);
}
NewPlrAnim(pnum, plr[pnum]._pLAnim[d], plr[pnum]._pSFrames, 0, plr[pnum]._pSWidth, AnimationDistributionParams::ProcessAnimationPending, 0, plr[pnum]._pSFNum);
NewPlrAnim(pnum, plr[pnum]._pLAnim[d], plr[pnum]._pSFrames, 0, plr[pnum]._pSWidth, AnimationDistributionFlags::ProcessAnimationPending, 0, plr[pnum]._pSFNum);
break;
case STYPE_MAGIC:
if ((plr[pnum]._pGFXLoad & PFILE_MAGIC) == 0) {
LoadPlrGFX(pnum, PFILE_MAGIC);
}
NewPlrAnim(pnum, plr[pnum]._pTAnim[d], plr[pnum]._pSFrames, 0, plr[pnum]._pSWidth, AnimationDistributionParams::ProcessAnimationPending, 0, plr[pnum]._pSFNum);
NewPlrAnim(pnum, plr[pnum]._pTAnim[d], plr[pnum]._pSFrames, 0, plr[pnum]._pSWidth, AnimationDistributionFlags::ProcessAnimationPending, 0, plr[pnum]._pSFNum);
break;
}
}
@ -1693,7 +1693,7 @@ void StartPlrHit(int pnum, int dam, bool forcehit)
skippedAnimationFrames = 0;
}
NewPlrAnim(pnum, plr[pnum]._pHAnim[pd], plr[pnum]._pHFrames, 0, plr[pnum]._pHWidth, AnimationDistributionParams::None, skippedAnimationFrames);
NewPlrAnim(pnum, plr[pnum]._pHAnim[pd], plr[pnum]._pHFrames, 0, plr[pnum]._pHWidth, AnimationDistributionFlags::None, skippedAnimationFrames);
plr[pnum]._pmode = PM_GOTHIT;
FixPlayerLocation(pnum, pd);

4
Source/player.h

@ -399,11 +399,11 @@ void FreePlayerGFX(int pnum);
* @param numberOfFrames Number of Frames in Animation
* @param delayLen Delay after each Animation sequence
* @param width Width of sprite
* @param params Specifies what special logics are applied to this Animation
* @param flags Specifies what special logics are applied to this Animation
* @param numSkippedFrames Number of Frames that will be skipped (for example with modifier "faster attack")
* @param distributeFramesBeforeFrame Distribute the numSkippedFrames only before this frame
*/
void NewPlrAnim(int pnum, BYTE *pData, int numberOfFrames, int delayLen, int width, AnimationDistributionParams params = AnimationDistributionParams::None, int numSkippedFrames = 0, int distributeFramesBeforeFrame = 0);
void NewPlrAnim(int pnum, BYTE *pData, int numberOfFrames, int delayLen, int width, AnimationDistributionFlags flags = AnimationDistributionFlags::None, int numSkippedFrames = 0, int distributeFramesBeforeFrame = 0);
void SetPlrAnims(int pnum);
void CreatePlayer(int pnum, HeroClass c);
int CalcStatDiff(int pnum);

18
test/animationinfo_test.cpp

@ -16,7 +16,7 @@ struct TestData {
* @brief Represents a call to SetNewAnimation
*/
struct SetNewAnimationData : TestData {
SetNewAnimationData(int numberOfFrames, int delayLen, AnimationDistributionParams params = AnimationDistributionParams::None, int numSkippedFrames = 0, int distributeFramesBeforeFrame = 0)
SetNewAnimationData(int numberOfFrames, int delayLen, AnimationDistributionFlags params = AnimationDistributionFlags::None, int numSkippedFrames = 0, int distributeFramesBeforeFrame = 0)
{
_NumberOfFrames = numberOfFrames;
_DelayLen = delayLen;
@ -26,7 +26,7 @@ struct SetNewAnimationData : TestData {
}
int _NumberOfFrames;
int _DelayLen;
AnimationDistributionParams _Params;
AnimationDistributionFlags _Params;
int _NumSkippedFrames;
int _DistributeFramesBeforeFrame;
};
@ -111,7 +111,7 @@ TEST(AnimationInfo, AttackSwordWarrior) // ProcessAnimationPending should be con
{
RunAnimationTest(
{
new SetNewAnimationData(16, 0, AnimationDistributionParams::ProcessAnimationPending, 0, 9),
new SetNewAnimationData(16, 0, AnimationDistributionFlags::ProcessAnimationPending, 0, 9),
// ProcessAnimation directly after StartAttack (in same GameTick). So we don't see any rendering before.
new GameTickData(2, 0),
new RenderingData(0.0f, 1),
@ -174,7 +174,7 @@ TEST(AnimationInfo, AttackSwordWarriorWithFastestAttack) // Skipped frames and P
{
RunAnimationTest(
{
new SetNewAnimationData(16, 0, AnimationDistributionParams::ProcessAnimationPending, 2, 9),
new SetNewAnimationData(16, 0, AnimationDistributionFlags::ProcessAnimationPending, 2, 9),
// ProcessAnimation directly after StartAttack (in same GameTick). So we don't see any rendering before.
new GameTickData(2, 0),
new RenderingData(0.0f, 1),
@ -230,7 +230,7 @@ TEST(AnimationInfo, AttackSwordWarriorRepeated)
{
RunAnimationTest(
{
new SetNewAnimationData(16, 0, AnimationDistributionParams::ProcessAnimationPending, 0, 9),
new SetNewAnimationData(16, 0, AnimationDistributionFlags::ProcessAnimationPending, 0, 9),
// ProcessAnimation directly after StartAttack (in same GameTick). So we don't see any rendering before.
new GameTickData(2, 0),
new RenderingData(0.0f, 1),
@ -275,7 +275,7 @@ TEST(AnimationInfo, AttackSwordWarriorRepeated)
new RenderingData(0.3f, 10),
// Start of repeated attack, cause plr[pnum].AnimInfo.CurrentFrame > plr[myplr]._pAFNum
new SetNewAnimationData(16, 0, AnimationDistributionParams::ProcessAnimationPending, 0, 9),
new SetNewAnimationData(16, 0, AnimationDistributionFlags::ProcessAnimationPending, 0, 9),
// ProcessAnimation directly after StartAttack (in same GameTick). So we don't see any rendering before.
new GameTickData(2, 0),
new RenderingData(0.0f, 11),
@ -338,7 +338,7 @@ TEST(AnimationInfo, BlockingWarriorNormal) // Ignored delay for last Frame shoul
{
RunAnimationTest(
{
new SetNewAnimationData(2, 2, AnimationDistributionParams::SkipsDelayOfLastFrame),
new SetNewAnimationData(2, 2, AnimationDistributionFlags::SkipsDelayOfLastFrame),
new RenderingData(0.0f, 1),
new RenderingData(0.3f, 1),
new RenderingData(0.6f, 1),
@ -366,7 +366,7 @@ TEST(AnimationInfo, BlockingSorcererWithFastBlock) // Skipped frames and ignored
{
RunAnimationTest(
{
new SetNewAnimationData(6, 2, AnimationDistributionParams::SkipsDelayOfLastFrame, 4),
new SetNewAnimationData(6, 2, AnimationDistributionFlags::SkipsDelayOfLastFrame, 4),
new RenderingData(0.0f, 1),
new RenderingData(0.3f, 1),
new RenderingData(0.6f, 1),
@ -394,7 +394,7 @@ TEST(AnimationInfo, HitRecoverySorcererZenMode) // Skipped frames and ignored de
{
RunAnimationTest(
{
new SetNewAnimationData(8, 0, AnimationDistributionParams::None, 4),
new SetNewAnimationData(8, 0, AnimationDistributionFlags::None, 4),
new RenderingData(0.0f, 1),
new RenderingData(0.3f, 1),
new RenderingData(0.6f, 2),

Loading…
Cancel
Save