diff --git a/Source/engine/animationinfo.cpp b/Source/engine/animationinfo.cpp index 0346c5f5f..ea43ec94e 100644 --- a/Source/engine/animationinfo.cpp +++ b/Source/engine/animationinfo.cpp @@ -75,7 +75,7 @@ float AnimationInfo::GetAnimationProgress() const return animationFraction; } -void AnimationInfo::SetNewAnimation(const CelSprite *celSprite, int numberOfFrames, int ticksPerFrame, AnimationDistributionFlags flags /*= AnimationDistributionFlags::None*/, int numSkippedFrames /*= 0*/, int distributeFramesBeforeFrame /*= 0*/) +void AnimationInfo::SetNewAnimation(const CelSprite *celSprite, int numberOfFrames, int ticksPerFrame, AnimationDistributionFlags flags /*= AnimationDistributionFlags::None*/, int numSkippedFrames /*= 0*/, int distributeFramesBeforeFrame /*= 0*/, float previewShownGameTickFragments /*= 0.F*/) { if ((flags & AnimationDistributionFlags::RepeatedAction) == AnimationDistributionFlags::RepeatedAction && distributeFramesBeforeFrame != 0 && NumberOfFrames == numberOfFrames && CurrentFrame >= distributeFramesBeforeFrame && CurrentFrame != NumberOfFrames) { // We showed the same Animation (for example a melee attack) before but truncated the Animation. @@ -129,6 +129,11 @@ void AnimationInfo::SetNewAnimation(const CelSprite *celSprite, int numberOfFram TicksSinceSequenceStarted = -1.F; } + // The preview animation was shown some times (less then one game tick) + // So we overall have a longer time the animation is shown + TicksSinceSequenceStarted += previewShownGameTickFragments; + relevantAnimationTicksWithSkipping += previewShownGameTickFragments; + 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 than the other frames diff --git a/Source/engine/animationinfo.h b/Source/engine/animationinfo.h index 31a591114..fb3ea1a28 100644 --- a/Source/engine/animationinfo.h +++ b/Source/engine/animationinfo.h @@ -80,8 +80,9 @@ public: * @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 + * @param previewShownGameTickFragments Defines how long (in game ticks fraction) the preview animation was shown */ - void SetNewAnimation(const CelSprite *celSprite, int numberOfFrames, int ticksPerFrame, AnimationDistributionFlags flags = AnimationDistributionFlags::None, int numSkippedFrames = 0, int distributeFramesBeforeFrame = 0); + void SetNewAnimation(const CelSprite *celSprite, int numberOfFrames, int ticksPerFrame, AnimationDistributionFlags flags = AnimationDistributionFlags::None, int numSkippedFrames = 0, int 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. diff --git a/Source/player.cpp b/Source/player.cpp index a60255541..ea8fb580a 100644 --- a/Source/player.cpp +++ b/Source/player.cpp @@ -23,6 +23,7 @@ #include "loadsave.h" #include "minitext.h" #include "missiles.h" +#include "nthread.h" #include "options.h" #include "player.h" #include "qol/autopickup.h" @@ -2263,6 +2264,7 @@ void Player::UpdatePreviewCelSprite(_cmd_id cmdId, Point point, uint16_t wParam1 auto &celSprites = AnimationData[static_cast(*graphic)].CelSpritesForDirections[static_cast(dir)]; if (celSprites && pPreviewCelSprite != &*celSprites) { pPreviewCelSprite = &*celSprites; + progressToNextGameTickWhenPreviewWasSet = gfProgressToNextGameTick; } } @@ -2406,7 +2408,10 @@ void NewPlrAnim(Player &player, player_graphic graphic, Direction dir, int numbe CelSprite *pCelSprite = celSprite ? &*celSprite : nullptr; - player.AnimInfo.SetNewAnimation(pCelSprite, numberOfFrames, delayLen, flags, numSkippedFrames, distributeFramesBeforeFrame); + float previewShownGameTickFragments = 0.F; + if (pCelSprite == player.pPreviewCelSprite) + previewShownGameTickFragments = clamp(1.F - player.progressToNextGameTickWhenPreviewWasSet, 0.F, 1.F); + player.AnimInfo.SetNewAnimation(pCelSprite, numberOfFrames, delayLen, flags, numSkippedFrames, distributeFramesBeforeFrame, previewShownGameTickFragments); } void SetPlrAnims(Player &player) diff --git a/Source/player.h b/Source/player.h index eef205266..9c97ba68c 100644 --- a/Source/player.h +++ b/Source/player.h @@ -221,6 +221,10 @@ struct Player { * @brief Contains a optional preview CelSprite that is displayed until the current command is handled by the game logic */ CelSprite *pPreviewCelSprite; + /** + * @brief Contains the progress to next game tick when pPreviewCelSprite was set + */ + float progressToNextGameTickWhenPreviewWasSet; int _plid; int _pvid; spell_id _pSpell;