Browse Source

Change animation frames and tick per frame to int8_t

pull/4865/head
obligaron 4 years ago committed by Gleb Mazovetskiy
parent
commit
e87aca38bb
  1. 16
      Source/engine/animationinfo.cpp
  2. 18
      Source/engine/animationinfo.h
  3. 8
      Source/items.cpp
  4. 2
      Source/items.h
  5. 8
      Source/monstdat.h
  6. 6
      Source/monster.cpp
  7. 4
      Source/monster.h
  8. 14
      Source/player.cpp
  9. 20
      Source/player.h

16
Source/engine/animationinfo.cpp

@ -12,14 +12,14 @@
namespace devilution {
int AnimationInfo::GetFrameToUseForRendering() const
int8_t AnimationInfo::GetFrameToUseForRendering() const
{
// Normal logic is used,
// - if no frame-skipping is required and so we have exactly one Animationframe per game tick
// or
// - if we load from a savegame where the new variables are not stored (we don't want to break savegame compatiblity because of smoother rendering of one animation)
if (RelevantFramesForDistributing <= 0)
return std::max(0, CurrentFrame);
return std::max<int8_t>(0, CurrentFrame);
if (CurrentFrame >= RelevantFramesForDistributing)
return CurrentFrame;
@ -33,7 +33,7 @@ int AnimationInfo::GetFrameToUseForRendering() const
// we don't use the processed game ticks alone but also the fraction of the next game tick (if a rendering happens between game ticks). This helps to smooth the animations.
float totalTicksForCurrentAnimationSequence = GetProgressToNextGameTick() + ticksSinceSequenceStarted;
int absoluteAnimationFrame = static_cast<int>(totalTicksForCurrentAnimationSequence * TickModifier);
int8_t absoluteAnimationFrame = static_cast<int8_t>(totalTicksForCurrentAnimationSequence * TickModifier);
if (SkippedFramesFromPreviousAnimation > 0) {
// absoluteAnimationFrames contains also the Frames from the previous Animation, so if we want to get the current Frame we have to remove them
absoluteAnimationFrame -= SkippedFramesFromPreviousAnimation;
@ -74,7 +74,7 @@ float AnimationInfo::GetAnimationProgress() const
return animationFraction;
}
void AnimationInfo::SetNewAnimation(std::optional<CelSprite> celSprite, int numberOfFrames, int ticksPerFrame, AnimationDistributionFlags flags /*= AnimationDistributionFlags::None*/, int numSkippedFrames /*= 0*/, int distributeFramesBeforeFrame /*= 0*/, float previewShownGameTickFragments /*= 0.F*/)
void AnimationInfo::SetNewAnimation(std::optional<CelSprite> celSprite, int8_t numberOfFrames, int8_t ticksPerFrame, AnimationDistributionFlags flags /*= AnimationDistributionFlags::None*/, int8_t numSkippedFrames /*= 0*/, int8_t distributeFramesBeforeFrame /*= 0*/, float previewShownGameTickFragments /*= 0.F*/)
{
if ((flags & AnimationDistributionFlags::RepeatedAction) == AnimationDistributionFlags::RepeatedAction && distributeFramesBeforeFrame != 0 && NumberOfFrames == numberOfFrames && CurrentFrame + 1 >= distributeFramesBeforeFrame && CurrentFrame != NumberOfFrames - 1) {
// We showed the same Animation (for example a melee attack) before but truncated the Animation.
@ -101,7 +101,7 @@ void AnimationInfo::SetNewAnimation(std::optional<CelSprite> celSprite, int numb
if (numSkippedFrames != 0 || flags != AnimationDistributionFlags::None) {
// Animation Frames that will be adjusted for the skipped Frames/game ticks
int relevantAnimationFramesForDistributing = numberOfFrames;
int8_t relevantAnimationFramesForDistributing = numberOfFrames;
if (distributeFramesBeforeFrame != 0) {
// After an attack hits (_pAFNum or _pSFNum) it can be canceled or another attack can be queued and this means the animation is canceled.
// In normal attacks frame skipping always happens before the attack actual hit.
@ -111,7 +111,7 @@ void AnimationInfo::SetNewAnimation(std::optional<CelSprite> celSprite, int numb
}
// Game ticks that will be adjusted for the skipped Frames/game ticks
int relevantAnimationTicksForDistribution = relevantAnimationFramesForDistributing * ticksPerFrame;
int8_t relevantAnimationTicksForDistribution = relevantAnimationFramesForDistributing * ticksPerFrame;
// How many game ticks will the Animation be really shown (skipped Frames and game ticks removed)
float relevantAnimationTicksWithSkipping = relevantAnimationTicksForDistribution - (numSkippedFrames * ticksPerFrame);
@ -167,12 +167,12 @@ void AnimationInfo::SetNewAnimation(std::optional<CelSprite> celSprite, int numb
}
}
void AnimationInfo::ChangeAnimationData(std::optional<CelSprite> celSprite, int numberOfFrames, int ticksPerFrame)
void AnimationInfo::ChangeAnimationData(std::optional<CelSprite> celSprite, int8_t numberOfFrames, int8_t ticksPerFrame)
{
if (numberOfFrames != NumberOfFrames || ticksPerFrame != TicksPerFrame) {
// Ensure that the CurrentFrame is still valid and that we disable ADL cause the calculcated values (for example TickModifier) could be wrong
if (numberOfFrames >= 1)
CurrentFrame = clamp(CurrentFrame, 0, numberOfFrames - 1);
CurrentFrame = clamp<int8_t>(CurrentFrame, 0, numberOfFrames - 1);
else
CurrentFrame = -1;

18
Source/engine/animationinfo.h

@ -44,19 +44,19 @@ public:
/**
* @brief How many game ticks are needed to advance one Animation Frame
*/
int TicksPerFrame;
int8_t TicksPerFrame;
/**
* @brief Increases by one each game tick, counting how close we are to TicksPerFrame
*/
int TickCounterOfCurrentFrame;
int8_t TickCounterOfCurrentFrame;
/**
* @brief Number of frames in current animation
*/
int NumberOfFrames;
int8_t NumberOfFrames;
/**
* @brief Current frame of animation
*/
int CurrentFrame;
int8_t CurrentFrame;
/**
* @brief Is the animation currently petrified and shouldn't advance with gfProgressToNextGameTick
*/
@ -66,7 +66,7 @@ public:
* @brief Calculates the Frame to use for the Animation rendering
* @return The Frame to use for rendering
*/
int GetFrameToUseForRendering() const;
int8_t GetFrameToUseForRendering() const;
/**
* @brief Calculates the progress of the current animation as a fraction (0.0f to 1.0f)
@ -83,7 +83,7 @@ public:
* @param distributeFramesBeforeFrame Distribute the numSkippedFrames only before this frame
* @param previewShownGameTickFragments Defines how long (in game ticks fraction) the preview animation was shown
*/
void SetNewAnimation(std::optional<CelSprite> celSprite, int numberOfFrames, int ticksPerFrame, AnimationDistributionFlags flags = AnimationDistributionFlags::None, int numSkippedFrames = 0, int distributeFramesBeforeFrame = 0, float previewShownGameTickFragments = 0.F);
void SetNewAnimation(std::optional<CelSprite> celSprite, int8_t numberOfFrames, int8_t ticksPerFrame, AnimationDistributionFlags flags = AnimationDistributionFlags::None, int8_t numSkippedFrames = 0, int8_t distributeFramesBeforeFrame = 0, float previewShownGameTickFragments = 0.F);
/**
* @brief Changes the Animation Data on-the-fly. This is needed if a animation is currently in progress and the player changes his gear.
@ -91,7 +91,7 @@ public:
* @param numberOfFrames Number of Frames in Animation
* @param ticksPerFrame How many game ticks are needed to advance one Animation Frame
*/
void ChangeAnimationData(std::optional<CelSprite> celSprite, int numberOfFrames, int ticksPerFrame);
void ChangeAnimationData(std::optional<CelSprite> celSprite, int8_t numberOfFrames, int8_t ticksPerFrame);
/**
* @brief Process the Animation for a game tick (for example advances the frame)
@ -117,11 +117,11 @@ private:
/**
* @brief Animation Frames that will be adjusted for the skipped Frames/game ticks
*/
int RelevantFramesForDistributing;
int8_t RelevantFramesForDistributing;
/**
* @brief Animation Frames that wasn't shown from previous Animation
*/
int SkippedFramesFromPreviousAnimation;
int8_t SkippedFramesFromPreviousAnimation;
};
} // namespace devilution

8
Source/items.cpp

@ -56,7 +56,7 @@ bool UniqueItemFlags[128];
int MaxGold = GOLD_MAX_LIMIT;
/** Maps from item_cursor_graphic to in-memory item type. */
BYTE ItemCAnimTbl[] = {
int8_t ItemCAnimTbl[] = {
20, 16, 16, 16, 4, 4, 4, 12, 12, 12,
12, 12, 12, 12, 12, 21, 21, 25, 12, 28,
28, 28, 38, 38, 38, 32, 38, 38, 38, 24,
@ -225,7 +225,7 @@ const char *const ItemDropNames[] = {
"mooses1",
};
/** Maps of item drop animation length. */
BYTE ItemAnimLs[] = {
int8_t ItemAnimLs[] = {
15,
13,
16,
@ -4580,8 +4580,8 @@ std::string DebugSpawnUniqueItem(std::string itemName)
void Item::setNewAnimation(bool showAnimation)
{
int it = ItemCAnimTbl[_iCurs];
int numberOfFrames = ItemAnimLs[it];
int8_t it = ItemCAnimTbl[_iCurs];
int8_t numberOfFrames = ItemAnimLs[it];
auto celSprite = itemanims[it] ? std::optional<CelSprite> { *itemanims[it] } : std::nullopt;
if (_iCurs != ICURS_MAGIC_ROCK)
AnimInfo.SetNewAnimation(celSprite, numberOfFrames, 1, AnimationDistributionFlags::ProcessAnimationPending, 0, numberOfFrames);

2
Source/items.h

@ -535,7 +535,7 @@ std::string DebugSpawnUniqueItem(std::string itemName);
extern int MaxGold;
extern BYTE ItemCAnimTbl[];
extern int8_t ItemCAnimTbl[];
extern _sfx_id ItemInvSnds[];
} // namespace devilution

8
Source/monstdat.h

@ -99,8 +99,8 @@ struct MonsterData {
bool has_special;
bool snd_special;
bool has_trans;
uint8_t Frames[6];
uint8_t Rate[6];
int8_t Frames[6];
int8_t Rate[6];
int8_t mMinDLvl;
int8_t mMaxDLvl;
int8_t mLevel;
@ -111,11 +111,11 @@ struct MonsterData {
uint16_t mFlags;
uint8_t mInt;
uint8_t mHit;
uint8_t mAFNum;
int8_t mAFNum;
uint8_t mMinDamage;
uint8_t mMaxDamage;
uint8_t mHit2;
uint8_t mAFNum2;
int8_t mAFNum2;
uint8_t mMinDamage2;
uint8_t mMaxDamage2;
uint8_t mArmorClass;

6
Source/monster.cpp

@ -675,7 +675,7 @@ void DeleteMonster(size_t activeIndex)
std::swap(ActiveMonsters[activeIndex], ActiveMonsters[ActiveMonsterCount]); // This ensures alive monsters are before ActiveMonsterCount in the array and any deleted monster after
}
void NewMonsterAnim(Monster &monster, MonsterGraphic graphic, Direction md, AnimationDistributionFlags flags = AnimationDistributionFlags::None, int numSkippedFrames = 0, int distributeFramesBeforeFrame = 0)
void NewMonsterAnim(Monster &monster, MonsterGraphic graphic, Direction md, AnimationDistributionFlags flags = AnimationDistributionFlags::None, int8_t numSkippedFrames = 0, int8_t distributeFramesBeforeFrame = 0)
{
const auto &animData = monster.MType->getAnimData(graphic);
monster.AnimInfo.SetNewAnimation(animData.getCelSpritesForDirection(md), animData.frames, animData.rate, flags, numSkippedFrames, distributeFramesBeforeFrame);
@ -688,7 +688,7 @@ void StartMonsterGotHit(int monsterId)
auto &monster = Monsters[monsterId];
if (monster.MType->type != MT_GOLEM) {
auto animationFlags = gGameLogicStep < GameLogicStep::ProcessMonsters ? AnimationDistributionFlags::ProcessAnimationPending : AnimationDistributionFlags::None;
int numSkippedFrames = (gbIsHellfire && monster.MType->type == MT_DIABLO) ? 4 : 0;
int8_t numSkippedFrames = (gbIsHellfire && monster.MType->type == MT_DIABLO) ? 4 : 0;
NewMonsterAnim(monster, MonsterGraphic::GotHit, monster._mdir, animationFlags, numSkippedFrames);
monster._mmode = MonsterMode::HitRecovery;
}
@ -905,7 +905,7 @@ void StartRangedAttack(Monster &monster, missile_id missileType, int dam)
void StartRangedSpecialAttack(Monster &monster, missile_id missileType, int dam)
{
Direction md = GetMonsterDirection(monster);
int distributeFramesBeforeFrame = 0;
int8_t distributeFramesBeforeFrame = 0;
if (monster._mAi == AI_MEGA)
distributeFramesBeforeFrame = monster.MData->mAFNum2;
NewMonsterAnim(monster, MonsterGraphic::Special, md, AnimationDistributionFlags::ProcessAnimationPending, 0, distributeFramesBeforeFrame);

4
Source/monster.h

@ -143,8 +143,8 @@ struct AnimStruct {
std::array<byte *, 8> celSpritesForDirections;
uint16_t width;
int frames;
int rate;
int8_t frames;
int8_t rate;
};
struct CMonster {

14
Source/player.cpp

@ -171,7 +171,7 @@ struct DirectionSettings {
};
/** Specifies the frame of each animation for which an action is triggered, for each player class. */
const int PlrGFXAnimLens[enum_size<HeroClass>::value][11] = {
const int8_t PlrGFXAnimLens[enum_size<HeroClass>::value][11] = {
{ 10, 16, 8, 2, 20, 20, 6, 20, 8, 9, 14 },
{ 8, 18, 8, 4, 20, 16, 7, 20, 8, 10, 12 },
{ 8, 16, 8, 6, 20, 12, 8, 20, 8, 12, 8 },
@ -344,7 +344,7 @@ void HandleWalkMode(int pnum, Displacement vel, Direction dir)
void StartWalkAnimation(Player &player, Direction dir, bool pmWillBeCalled)
{
int skippedFrames = -2;
int8_t skippedFrames = -2;
if (leveltype == DTYPE_TOWN && sgGameInitInfo.bRunInTown != 0)
skippedFrames = 2;
if (pmWillBeCalled)
@ -446,7 +446,7 @@ void StartAttack(int pnum, Direction d)
return;
}
int skippedAnimationFrames = 0;
int8_t skippedAnimationFrames = 0;
if (HasAnyOf(player._pIFlags, ItemSpecialEffect::FasterAttack)) {
// The combination of Faster and Fast Attack doesn't result in more skipped skipped frames, cause the secound frame skip of Faster Attack is not triggered.
skippedAnimationFrames = 2;
@ -478,7 +478,7 @@ void StartRangeAttack(int pnum, Direction d, WorldTileCoord cx, WorldTileCoord c
return;
}
int skippedAnimationFrames = 0;
int8_t skippedAnimationFrames = 0;
if (!gbIsHellfire) {
if (HasAnyOf(player._pIFlags, ItemSpecialEffect::FastAttack)) {
skippedAnimationFrames += 1;
@ -2339,7 +2339,7 @@ void ResetPlayerGFX(Player &player)
}
}
void NewPlrAnim(Player &player, player_graphic graphic, Direction dir, int numberOfFrames, int delayLen, AnimationDistributionFlags flags /*= AnimationDistributionFlags::None*/, int numSkippedFrames /*= 0*/, int distributeFramesBeforeFrame /*= 0*/)
void NewPlrAnim(Player &player, player_graphic graphic, Direction dir, int8_t numberOfFrames, int8_t delayLen, AnimationDistributionFlags flags /*= AnimationDistributionFlags::None*/, int8_t numSkippedFrames /*= 0*/, int8_t distributeFramesBeforeFrame /*= 0*/)
{
LoadPlrGFX(player, graphic);
@ -2911,7 +2911,7 @@ void StartPlrBlock(int pnum, Direction dir)
PlaySfxLoc(IS_ISWORD, player.position.tile);
int skippedAnimationFrames = 0;
int8_t skippedAnimationFrames = 0;
if (HasAnyOf(player._pIFlags, ItemSpecialEffect::FastBlock)) {
skippedAnimationFrames = (player._pBFrames - 2); // ISPL_FASTBLOCK means we cancel the animation if frame 2 was shown
}
@ -2980,7 +2980,7 @@ void StartPlrHit(int pnum, int dam, bool forcehit)
Direction pd = player._pdir;
int skippedAnimationFrames = 0;
int8_t skippedAnimationFrames = 0;
constexpr ItemSpecialEffect ZenFlags = ItemSpecialEffect::FastHitRecovery | ItemSpecialEffect::FasterHitRecovery | ItemSpecialEffect::FastestHitRecovery;
if (HasAllOf(player._pIFlags, ZenFlags)) { // if multiple hitrecovery modes are present the skipping of frames can go so far, that they skip frames that would skip. so the additional skipping thats skipped. that means we can't add the different modes together.
skippedAnimationFrames = 4;

20
Source/player.h

@ -302,15 +302,15 @@ struct Player {
* @brief Contains Data (Sprites) for the different Animations
*/
std::array<PlayerAnimationData, enum_size<player_graphic>::value> AnimationData;
int _pNFrames;
int _pWFrames;
int _pAFrames;
int _pAFNum;
int _pSFrames;
int _pSFNum;
int _pHFrames;
int _pDFrames;
int _pBFrames;
int8_t _pNFrames;
int8_t _pWFrames;
int8_t _pAFrames;
int8_t _pAFNum;
int8_t _pSFrames;
int8_t _pSFNum;
int8_t _pHFrames;
int8_t _pDFrames;
int8_t _pBFrames;
Item InvBody[NUM_INVLOC];
Item InvList[NUM_INV_GRID_ELEM];
int _pNumInv;
@ -758,7 +758,7 @@ void ResetPlayerGFX(Player &player);
* @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(Player &player, player_graphic graphic, Direction dir, int numberOfFrames, int delayLen, AnimationDistributionFlags flags = AnimationDistributionFlags::None, int numSkippedFrames = 0, int distributeFramesBeforeFrame = 0);
void NewPlrAnim(Player &player, player_graphic graphic, Direction dir, int8_t numberOfFrames, int8_t delayLen, AnimationDistributionFlags flags = AnimationDistributionFlags::None, int8_t numSkippedFrames = 0, int8_t distributeFramesBeforeFrame = 0);
void SetPlrAnims(Player &player);
void CreatePlayer(Player &player, HeroClass c);
int CalcStatDiff(Player &player);

Loading…
Cancel
Save